1<?php
2/**
3 * Created by PhpStorm.
4 * User: Uwe Tews
5 * Date: 04.12.2014
6 * Time: 06:08
7 */
8
9/**
10 * Smarty Resource Data Object
11 * Cache Data Container for Template Files
12 *
13 * @package    Smarty
14 * @subpackage TemplateResources
15 * @author     Rodney Rehm
16 */
17class Smarty_Template_Cached extends Smarty_Template_Resource_Base
18{
19    /**
20     * Cache Is Valid
21     *
22     * @var boolean
23     */
24    public $valid = null;
25
26    /**
27     * CacheResource Handler
28     *
29     * @var Smarty_CacheResource
30     */
31    public $handler = null;
32
33    /**
34     * Template Cache Id (Smarty_Internal_Template::$cache_id)
35     *
36     * @var string
37     */
38    public $cache_id = null;
39
40    /**
41     * saved cache lifetime in seconds
42     *
43     * @var integer
44     */
45    public $cache_lifetime = 0;
46
47    /**
48     * Id for cache locking
49     *
50     * @var string
51     */
52    public $lock_id = null;
53
54    /**
55     * flag that cache is locked by this instance
56     *
57     * @var bool
58     */
59    public $is_locked = false;
60
61    /**
62     * Source Object
63     *
64     * @var Smarty_Template_Source
65     */
66    public $source = null;
67
68    /**
69     * Nocache hash codes of processed compiled templates
70     *
71     * @var array
72     */
73    public $hashes = array();
74
75    /**
76     * Flag if this is a cache resource
77     *
78     * @var bool
79     */
80    public $isCache = true;
81
82    /**
83     * create Cached Object container
84     *
85     * @param Smarty_Internal_Template $_template template object
86     *
87     * @throws \SmartyException
88     */
89    public function __construct(Smarty_Internal_Template $_template)
90    {
91        $this->compile_id = $_template->compile_id;
92        $this->cache_id = $_template->cache_id;
93        $this->source = $_template->source;
94        if (!class_exists('Smarty_CacheResource', false)) {
95            include SMARTY_SYSPLUGINS_DIR . 'smarty_cacheresource.php';
96        }
97        $this->handler = Smarty_CacheResource::load($_template->smarty);
98    }
99
100    /**
101     * @param Smarty_Internal_Template $_template
102     *
103     * @return Smarty_Template_Cached
104     */
105    public static function load(Smarty_Internal_Template $_template)
106    {
107        $_template->cached = new Smarty_Template_Cached($_template);
108        $_template->cached->handler->populate($_template->cached, $_template);
109        // caching enabled ?
110        if (!$_template->caching || $_template->source->handler->recompiled
111        ) {
112            $_template->cached->valid = false;
113        }
114        return $_template->cached;
115    }
116
117    /**
118     * Render cache template
119     *
120     * @param \Smarty_Internal_Template $_template
121     * @param bool                      $no_output_filter
122     *
123     * @throws \Exception
124     */
125    public function render(Smarty_Internal_Template $_template, $no_output_filter = true)
126    {
127        if ($this->isCached($_template)) {
128            if ($_template->smarty->debugging) {
129                if (!isset($_template->smarty->_debug)) {
130                    $_template->smarty->_debug = new Smarty_Internal_Debug();
131                }
132                $_template->smarty->_debug->start_cache($_template);
133            }
134            if (!$this->processed) {
135                $this->process($_template);
136            }
137            $this->getRenderedTemplateCode($_template);
138            if ($_template->smarty->debugging) {
139                $_template->smarty->_debug->end_cache($_template);
140            }
141            return;
142        } else {
143            $_template->smarty->ext->_updateCache->updateCache($this, $_template, $no_output_filter);
144        }
145    }
146
147    /**
148     * Check if cache is valid, lock cache if required
149     *
150     * @param \Smarty_Internal_Template $_template
151     *
152     * @return bool flag true if cache is valid
153     */
154    public function isCached(Smarty_Internal_Template $_template)
155    {
156        if ($this->valid !== null) {
157            return $this->valid;
158        }
159        while (true) {
160            while (true) {
161                if ($this->exists === false || $_template->smarty->force_compile || $_template->smarty->force_cache) {
162                    $this->valid = false;
163                } else {
164                    $this->valid = true;
165                }
166                if ($this->valid && $_template->caching === Smarty::CACHING_LIFETIME_CURRENT
167                    && $_template->cache_lifetime >= 0 && time() > ($this->timestamp + $_template->cache_lifetime)
168                ) {
169                    // lifetime expired
170                    $this->valid = false;
171                }
172                if ($this->valid && $_template->compile_check === Smarty::COMPILECHECK_ON
173                    && $_template->source->getTimeStamp() > $this->timestamp
174                ) {
175                    $this->valid = false;
176                }
177                if ($this->valid || !$_template->smarty->cache_locking) {
178                    break;
179                }
180                if (!$this->handler->locked($_template->smarty, $this)) {
181                    $this->handler->acquireLock($_template->smarty, $this);
182                    break 2;
183                }
184                $this->handler->populate($this, $_template);
185            }
186            if ($this->valid) {
187                if (!$_template->smarty->cache_locking || $this->handler->locked($_template->smarty, $this) === null) {
188                    // load cache file for the following checks
189                    if ($_template->smarty->debugging) {
190                        $_template->smarty->_debug->start_cache($_template);
191                    }
192                    if ($this->handler->process($_template, $this) === false) {
193                        $this->valid = false;
194                    } else {
195                        $this->processed = true;
196                    }
197                    if ($_template->smarty->debugging) {
198                        $_template->smarty->_debug->end_cache($_template);
199                    }
200                } else {
201                    $this->is_locked = true;
202                    continue;
203                }
204            } else {
205                return $this->valid;
206            }
207            if ($this->valid && $_template->caching === Smarty::CACHING_LIFETIME_SAVED
208                && $_template->cached->cache_lifetime >= 0
209                && (time() > ($_template->cached->timestamp + $_template->cached->cache_lifetime))
210            ) {
211                $this->valid = false;
212            }
213            if ($_template->smarty->cache_locking) {
214                if (!$this->valid) {
215                    $this->handler->acquireLock($_template->smarty, $this);
216                } elseif ($this->is_locked) {
217                    $this->handler->releaseLock($_template->smarty, $this);
218                }
219            }
220            return $this->valid;
221        }
222        return $this->valid;
223    }
224
225    /**
226     * Process cached template
227     *
228     * @param Smarty_Internal_Template $_template template object
229     * @param bool                     $update    flag if called because cache update
230     */
231    public function process(Smarty_Internal_Template $_template, $update = false)
232    {
233        if ($this->handler->process($_template, $this, $update) === false) {
234            $this->valid = false;
235        }
236        if ($this->valid) {
237            $this->processed = true;
238        } else {
239            $this->processed = false;
240        }
241    }
242
243    /**
244     * Read cache content from handler
245     *
246     * @param Smarty_Internal_Template $_template template object
247     *
248     * @return string|false content
249     */
250    public function read(Smarty_Internal_Template $_template)
251    {
252        if (!$_template->source->handler->recompiled) {
253            return $this->handler->readCachedContent($_template);
254        }
255        return false;
256    }
257}
258