]> git.mxchange.org Git - friendica.git/blob - library/Smarty/libs/sysplugins/smarty_resource.php
Merge remote branch 'upstream/master'
[friendica.git] / library / Smarty / libs / sysplugins / smarty_resource.php
1 <?php
2 /**
3  * Smarty Resource Plugin
4  *
5  * @package Smarty
6  * @subpackage TemplateResources
7  * @author Rodney Rehm
8  */
9
10 /**
11  * Smarty Resource Plugin
12  *
13  * Base implementation for resource plugins
14  *
15  * @package Smarty
16  * @subpackage TemplateResources
17  */
18 abstract class Smarty_Resource {
19     /**
20      * cache for Smarty_Template_Source instances
21      * @var array
22      */
23     public static $sources = array();
24     /**
25      * cache for Smarty_Template_Compiled instances
26      * @var array
27      */
28     public static $compileds = array();
29     /**
30      * cache for Smarty_Resource instances
31      * @var array
32      */
33     public static $resources = array();
34     /**
35      * resource types provided by the core
36      * @var array
37      */
38     protected static $sysplugins = array(
39         'file' => true,
40         'string' => true,
41         'extends' => true,
42         'stream' => true,
43         'eval' => true,
44         'php' => true
45     );
46
47     /**
48      * Name of the Class to compile this resource's contents with
49      * @var string
50      */
51     public $compiler_class = 'Smarty_Internal_SmartyTemplateCompiler';
52
53     /**
54      * Name of the Class to tokenize this resource's contents with
55      * @var string
56      */
57     public $template_lexer_class = 'Smarty_Internal_Templatelexer';
58
59     /**
60      * Name of the Class to parse this resource's contents with
61      * @var string
62      */
63     public $template_parser_class = 'Smarty_Internal_Templateparser';
64
65     /**
66      * Load template's source into current template object
67      *
68      * {@internal The loaded source is assigned to $_template->source->content directly.}}
69      *
70      * @param Smarty_Template_Source $source source object
71      * @return string template source
72      * @throws SmartyException if source cannot be loaded
73      */
74     public abstract function getContent(Smarty_Template_Source $source);
75
76     /**
77      * populate Source Object with meta data from Resource
78      *
79      * @param Smarty_Template_Source   $source source object
80      * @param Smarty_Internal_Template $_template     template object
81      */
82     public abstract function populate(Smarty_Template_Source $source, Smarty_Internal_Template $_template=null);
83
84     /**
85      * populate Source Object with timestamp and exists from Resource
86      *
87      * @param Smarty_Template_Source $source source object
88      */
89     public function populateTimestamp(Smarty_Template_Source $source)
90     {
91         // intentionally left blank
92     }
93
94
95     /**
96      * modify resource_name according to resource handlers specifications
97      *
98      * @param Smarty $smarty        Smarty instance
99      * @param string $resource_name resource_name to make unique
100      * @return string unique resource name
101      */
102     protected function buildUniqueResourceName(Smarty $smarty, $resource_name)
103     {
104         return get_class($this) . '#' . $smarty->joined_template_dir . '#' . $resource_name;
105     }
106
107     /**
108      * populate Compiled Object with compiled filepath
109      *
110      * @param Smarty_Template_Compiled $compiled  compiled object
111      * @param Smarty_Internal_Template $_template template object
112      */
113     public function populateCompiledFilepath(Smarty_Template_Compiled $compiled, Smarty_Internal_Template $_template)
114     {
115         $_compile_id = isset($_template->compile_id) ? preg_replace('![^\w\|]+!', '_', $_template->compile_id) : null;
116         $_filepath = $compiled->source->uid;
117         // if use_sub_dirs, break file into directories
118         if ($_template->smarty->use_sub_dirs) {
119             $_filepath = substr($_filepath, 0, 2) . DS
120              . substr($_filepath, 2, 2) . DS
121              . substr($_filepath, 4, 2) . DS
122              . $_filepath;
123         }
124         $_compile_dir_sep = $_template->smarty->use_sub_dirs ? DS : '^';
125         if (isset($_compile_id)) {
126             $_filepath = $_compile_id . $_compile_dir_sep . $_filepath;
127         }
128         // caching token
129         if ($_template->caching) {
130             $_cache = '.cache';
131         } else {
132             $_cache = '';
133         }
134         $_compile_dir = $_template->smarty->getCompileDir();
135         // set basename if not specified
136         $_basename = $this->getBasename($compiled->source);
137         if ($_basename === null) {
138             $_basename = basename( preg_replace('![^\w\/]+!', '_', $compiled->source->name) );
139         }
140         // separate (optional) basename by dot
141         if ($_basename) {
142             $_basename = '.' . $_basename;
143         }
144
145         $compiled->filepath = $_compile_dir . $_filepath . '.' . $compiled->source->type . $_basename . $_cache . '.php';
146     }
147     
148     /**
149      * Normalize Paths "foo/../bar" to "bar" 
150      *
151      * @param string $_path path to normalize
152      * @param boolean $ds respect windows directory separator
153      * @return string normalized path
154      */
155     protected function normalizePath($_path, $ds=true)
156     {
157         if ($ds) {
158             // don't we all just love windows?
159             $_path = str_replace('\\', '/', $_path);
160         }
161         
162         // resolve simples
163         $_path = preg_replace('#(/\./(\./)*)|/{2,}#', '/', $_path);
164         // resolve parents
165         while (true) {
166             $_parent = strpos($_path, '/../');
167             if ($_parent === false) {
168                 break;
169             } else if ($_parent === 0) {
170                 $_path = substr($_path, 3);
171                 break;
172             }
173             
174             $_pos = strrpos($_path, '/', $_parent - strlen($_path) - 1);
175             if ($_pos === false) {
176                 // don't we all just love windows?
177                 $_pos = $_parent;
178             }
179             
180             $_path = substr_replace($_path, '', $_pos, $_parent + 3 - $_pos);
181         }
182         
183         if ($ds && DS != '/') {
184             // don't we all just love windows?
185             $_path = str_replace('/', '\\', $_path);
186         }
187         
188         return $_path;
189     }
190     
191     /**
192      * build template filepath by traversing the template_dir array
193      *
194      * @param Smarty_Template_Source   $source    source object
195      * @param Smarty_Internal_Template $_template template object
196      * @return string fully qualified filepath
197      * @throws SmartyException if default template handler is registered but not callable
198      */
199     protected function buildFilepath(Smarty_Template_Source $source, Smarty_Internal_Template $_template=null)
200     {
201         $file = $source->name;
202         if ($source instanceof Smarty_Config_Source) {
203             $_directories = $source->smarty->getConfigDir();
204             $_default_handler = $source->smarty->default_config_handler_func;
205         } else {
206             $_directories = $source->smarty->getTemplateDir();
207             $_default_handler = $source->smarty->default_template_handler_func;
208         }
209
210         // go relative to a given template?
211         $_file_is_dotted = $file[0] == '.' && ($file[1] == '.' || $file[1] == '/' || $file[1] == "\\");
212         if ($_template && $_template->parent instanceof Smarty_Internal_Template && $_file_is_dotted) {
213             if ($_template->parent->source->type != 'file' && $_template->parent->source->type != 'extends' && !$_template->parent->allow_relative_path) {
214                 throw new SmartyException("Template '{$file}' cannot be relative to template of resource type '{$_template->parent->source->type}'");
215             }
216             $file = dirname($_template->parent->source->filepath) . DS . $file;
217             $_file_exact_match = true;
218             if (!preg_match('/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/', $file)) {
219                 // the path gained from the parent template is relative to the current working directory
220                 // as expansions (like include_path) have already been done
221                 $file = getcwd() . DS . $file;
222             }
223         }
224
225         // resolve relative path
226         if (!preg_match('/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/', $file)) {
227             // don't we all just love windows?
228             $_path = str_replace('\\', '/', $file);
229             $_was_relative_prefix = $file[0] == '.' ? substr($file, 0, strpos($_path, '/')) : null;
230             $_path = DS . trim($file, '/');
231             $_was_relative = true;
232         } else {
233             // don't we all just love windows?
234             $_path = str_replace('\\', '/', $file);
235         }
236         $_path = $this->normalizePath($_path, false);
237         if (DS != '/') {
238             // don't we all just love windows?
239             $_path = str_replace('/', '\\', $_path);
240         }
241         // revert to relative
242         if (isset($_was_relative)) {
243             if (isset($_was_relative_prefix)){
244                 $_path = $_was_relative_prefix . $_path;
245             } else {
246                 $_path = substr($_path, 1);
247             }
248         }
249
250         // this is only required for directories
251         $file = rtrim($_path, '/\\');
252
253         // files relative to a template only get one shot
254         if (isset($_file_exact_match)) {
255             return $this->fileExists($source, $file) ? $file : false;
256         }
257
258         // template_dir index?
259         if (preg_match('#^\[(?P<key>[^\]]+)\](?P<file>.+)$#', $file, $match)) {
260             $_directory = null;
261             // try string indexes
262             if (isset($_directories[$match['key']])) {
263                 $_directory = $_directories[$match['key']];
264             } else if (is_numeric($match['key'])) {
265                 // try numeric index
266                 $match['key'] = (int) $match['key'];
267                 if (isset($_directories[$match['key']])) {
268                     $_directory = $_directories[$match['key']];
269                 } else {
270                     // try at location index
271                     $keys = array_keys($_directories);
272                     $_directory = $_directories[$keys[$match['key']]];
273                 }
274             }
275
276             if ($_directory) {
277                 $_file = substr($file, strpos($file, ']') + 1);
278                 $_filepath = $_directory . $_file;
279                 if ($this->fileExists($source, $_filepath)) {
280                     return $_filepath;
281                 }
282             }
283         }
284
285         $_stream_resolve_include_path = function_exists('stream_resolve_include_path');
286
287         // relative file name?
288         if (!preg_match('/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/', $file)) {
289             foreach ($_directories as $_directory) {
290                 $_filepath = $_directory . $file;
291                 if ($this->fileExists($source, $_filepath)) {
292                     return $this->normalizePath($_filepath);
293                 }
294                 if ($source->smarty->use_include_path && !preg_match('/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/', $_directory)) {
295                     // try PHP include_path
296                     if ($_stream_resolve_include_path) {
297                         $_filepath = stream_resolve_include_path($_filepath);
298                     } else {
299                         $_filepath = Smarty_Internal_Get_Include_Path::getIncludePath($_filepath);
300                     }
301
302                     if ($_filepath !== false) {
303                         if ($this->fileExists($source, $_filepath)) {
304                             return $this->normalizePath($_filepath);
305                         }
306                     }
307                 }
308             }
309         }
310
311         // try absolute filepath
312         if ($this->fileExists($source, $file)) {
313             return $file;
314         }
315
316         // no tpl file found
317         if ($_default_handler) {
318             if (!is_callable($_default_handler)) {
319                 if ($source instanceof Smarty_Config_Source) {
320                     throw new SmartyException("Default config handler not callable");
321                 } else {
322                     throw new SmartyException("Default template handler not callable");
323                 }
324             }
325             $_return = call_user_func_array($_default_handler,
326                 array($source->type, $source->name, &$_content, &$_timestamp, $source->smarty));
327             if (is_string($_return)) {
328                 $source->timestamp = @filemtime($_return);
329                 $source->exists = !!$source->timestamp;
330                 return $_return;
331             } elseif ($_return === true) {
332                 $source->content = $_content;
333                 $source->timestamp = $_timestamp;
334                 $source->exists = true;
335                 return $_filepath;
336             }
337         }
338
339         // give up
340         return false;
341     }
342
343     /**
344      * test is file exists and save timestamp
345      *
346      * @param Smarty_Template_Source   $source    source object
347      * @param string $file file name
348      * @return bool  true if file exists
349      */
350     protected function fileExists(Smarty_Template_Source $source, $file)
351     {
352         $source->timestamp = @filemtime($file);
353         return $source->exists = !!$source->timestamp;
354
355     }
356
357     /**
358      * Determine basename for compiled filename
359      *
360      * @param Smarty_Template_Source $source source object
361      * @return string resource's basename
362      */
363     protected function getBasename(Smarty_Template_Source $source)
364     {
365         return null;
366     }
367
368     /**
369      * Load Resource Handler
370      *
371      * @param Smarty $smarty    smarty object
372      * @param string $type      name of the resource
373      * @return Smarty_Resource Resource Handler
374      */
375     public static function load(Smarty $smarty, $type)
376     {
377         // try smarty's cache
378         if (isset($smarty->_resource_handlers[$type])) {
379             return $smarty->_resource_handlers[$type];
380         }
381
382         // try registered resource
383         if (isset($smarty->registered_resources[$type])) {
384             if ($smarty->registered_resources[$type] instanceof Smarty_Resource) {
385                 $smarty->_resource_handlers[$type] = $smarty->registered_resources[$type];
386                 // note registered to smarty is not kept unique!
387                 return $smarty->_resource_handlers[$type];
388             }
389
390             if (!isset(self::$resources['registered'])) {
391                 self::$resources['registered'] = new Smarty_Internal_Resource_Registered();
392             }
393             if (!isset($smarty->_resource_handlers[$type])) {
394                 $smarty->_resource_handlers[$type] = self::$resources['registered'];
395             }
396
397             return $smarty->_resource_handlers[$type];
398         }
399
400         // try sysplugins dir
401         if (isset(self::$sysplugins[$type])) {
402             if (!isset(self::$resources[$type])) {
403                 $_resource_class = 'Smarty_Internal_Resource_' . ucfirst($type);
404                 self::$resources[$type] = new $_resource_class();
405             }
406             return $smarty->_resource_handlers[$type] = self::$resources[$type];
407         }
408
409         // try plugins dir
410         $_resource_class = 'Smarty_Resource_' . ucfirst($type);
411         if ($smarty->loadPlugin($_resource_class)) {
412             if (isset(self::$resources[$type])) {
413                 return $smarty->_resource_handlers[$type] = self::$resources[$type];
414             }
415
416             if (class_exists($_resource_class, false)) {
417                 self::$resources[$type] = new $_resource_class();
418                 return $smarty->_resource_handlers[$type] = self::$resources[$type];
419             } else {
420                 $smarty->registerResource($type, array(
421                     "smarty_resource_{$type}_source",
422                     "smarty_resource_{$type}_timestamp",
423                     "smarty_resource_{$type}_secure",
424                     "smarty_resource_{$type}_trusted"
425                 ));
426
427                 // give it another try, now that the resource is registered properly
428                 return self::load($smarty, $type);
429             }
430         }
431
432         // try streams
433         $_known_stream = stream_get_wrappers();
434         if (in_array($type, $_known_stream)) {
435             // is known stream
436             if (is_object($smarty->security_policy)) {
437                 $smarty->security_policy->isTrustedStream($type);
438             }
439             if (!isset(self::$resources['stream'])) {
440                 self::$resources['stream'] = new Smarty_Internal_Resource_Stream();
441             }
442             return $smarty->_resource_handlers[$type] = self::$resources['stream'];
443         }
444
445         // TODO: try default_(template|config)_handler
446
447         // give up
448         throw new SmartyException("Unkown resource type '{$type}'");
449     }
450
451     /**
452      * extract resource_type and resource_name from template_resource and config_resource
453      *
454      * @note "C:/foo.tpl" was forced to file resource up till Smarty 3.1.3 (including).
455      * @param string  $resource_name    template_resource or config_resource to parse
456      * @param string  $default_resource the default resource_type defined in $smarty
457      * @param string &$name             the parsed resource name
458      * @param string &$type             the parsed resource type
459      * @return void
460      */
461     protected static function parseResourceName($resource_name, $default_resource, &$name, &$type)
462     {
463         $parts = explode(':', $resource_name, 2);
464         if (!isset($parts[1]) || !isset($parts[0][1])) {
465             // no resource given, use default
466             // or single character before the colon is not a resource type, but part of the filepath
467             $type = $default_resource;
468             $name = $resource_name;
469         } else {
470             $type = $parts[0];
471             $name = $parts[1];
472         }
473     }
474
475
476     /**
477      * modify resource_name according to resource handlers specifications
478      *
479      * @param Smarty $smarty        Smarty instance
480      * @param string $resource_name resource_name to make unique
481      * @return string unique resource name
482      */
483
484     /**
485      * modify template_resource according to resource handlers specifications
486      *
487      * @param string $smarty            Smarty instance
488      * @param string $template_resource template_resource to extracate resource handler and name of
489      * @return string unique resource name
490      */
491     public static function getUniqueTemplateName($smarty, $template_resource)
492     {
493         self::parseResourceName($template_resource, $smarty->default_resource_type, $name, $type);
494         // TODO: optimize for Smarty's internal resource types
495         $resource = Smarty_Resource::load($smarty, $type);
496         return $resource->buildUniqueResourceName($smarty, $name);
497     }
498
499     /**
500      * initialize Source Object for given resource
501      *
502      * Either [$_template] or [$smarty, $template_resource] must be specified
503      *
504      * @param Smarty_Internal_Template $_template         template object
505      * @param Smarty                   $smarty            smarty object
506      * @param string                   $template_resource resource identifier
507      * @return Smarty_Template_Source Source Object
508      */
509     public static function source(Smarty_Internal_Template $_template=null, Smarty $smarty=null, $template_resource=null)
510     {
511         if ($_template) {
512             $smarty = $_template->smarty;
513             $template_resource = $_template->template_resource;
514         }
515
516         // parse resource_name, load resource handler, identify unique resource name
517         self::parseResourceName($template_resource, $smarty->default_resource_type, $name, $type);
518         $resource = Smarty_Resource::load($smarty, $type);
519         $unique_resource_name = $resource->buildUniqueResourceName($smarty, $name);
520
521         // check runtime cache
522         $_cache_key = 'template|' . $unique_resource_name;
523         if ($smarty->compile_id) {
524             $_cache_key .= '|'.$smarty->compile_id;
525         }
526         if (isset(self::$sources[$_cache_key])) {
527             return self::$sources[$_cache_key];
528         }
529
530         // create source
531         $source = new Smarty_Template_Source($resource, $smarty, $template_resource, $type, $name, $unique_resource_name);
532         $resource->populate($source, $_template);
533
534         // runtime cache
535         self::$sources[$_cache_key] = $source;
536         return $source;
537     }
538
539     /**
540      * initialize Config Source Object for given resource
541      *
542      * @param Smarty_Internal_Config $_config config object
543      * @return Smarty_Config_Source Source Object
544      */
545     public static function config(Smarty_Internal_Config $_config)
546     {
547         static $_incompatible_resources = array('eval' => true, 'string' => true, 'extends' => true, 'php' => true);
548         $config_resource = $_config->config_resource;
549         $smarty = $_config->smarty;
550
551         // parse resource_name
552         self::parseResourceName($config_resource, $smarty->default_config_type, $name, $type);
553
554         // make sure configs are not loaded via anything smarty can't handle
555         if (isset($_incompatible_resources[$type])) {
556             throw new SmartyException ("Unable to use resource '{$type}' for config");
557         }
558
559         // load resource handler, identify unique resource name
560         $resource = Smarty_Resource::load($smarty, $type);
561         $unique_resource_name = $resource->buildUniqueResourceName($smarty, $name);
562
563         // check runtime cache
564         $_cache_key = 'config|' . $unique_resource_name;
565         if (isset(self::$sources[$_cache_key])) {
566             return self::$sources[$_cache_key];
567         }
568
569         // create source
570         $source = new Smarty_Config_Source($resource, $smarty, $config_resource, $type, $name, $unique_resource_name);
571         $resource->populate($source, null);
572
573         // runtime cache
574         self::$sources[$_cache_key] = $source;
575         return $source;
576     }
577
578 }
579
580 /**
581  * Smarty Resource Data Object
582  *
583  * Meta Data Container for Template Files
584  *
585  * @package Smarty
586  * @subpackage TemplateResources
587  * @author Rodney Rehm
588  *
589  * @property integer $timestamp Source Timestamp
590  * @property boolean $exists    Source Existance
591  * @property boolean $template  Extended Template reference
592  * @property string  $content   Source Content
593  */
594 class Smarty_Template_Source {
595
596     /**
597      * Name of the Class to compile this resource's contents with
598      * @var string
599      */
600     public $compiler_class = null;
601
602     /**
603      * Name of the Class to tokenize this resource's contents with
604      * @var string
605      */
606     public $template_lexer_class = null;
607
608     /**
609      * Name of the Class to parse this resource's contents with
610      * @var string
611      */
612     public $template_parser_class = null;
613
614     /**
615      * Unique Template ID
616      * @var string
617      */
618     public $uid = null;
619
620     /**
621      * Template Resource (Smarty_Internal_Template::$template_resource)
622      * @var string
623      */
624     public $resource = null;
625
626     /**
627      * Resource Type
628      * @var string
629      */
630     public $type = null;
631
632     /**
633      * Resource Name
634      * @var string
635      */
636     public $name = null;
637
638     /**
639      * Unique Resource Name
640      * @var string
641      */
642     public $unique_resource = null;
643
644     /**
645      * Source Filepath
646      * @var string
647      */
648     public $filepath = null;
649
650     /**
651      * Source is bypassing compiler
652      * @var boolean
653      */
654     public $uncompiled = null;
655
656     /**
657      * Source must be recompiled on every occasion
658      * @var boolean
659      */
660     public $recompiled = null;
661
662     /**
663      * The Components an extended template is made of
664      * @var array
665      */
666     public $components = null;
667
668     /**
669      * Resource Handler
670      * @var Smarty_Resource
671      */
672     public $handler = null;
673
674     /**
675      * Smarty instance
676      * @var Smarty
677      */
678     public $smarty = null;
679
680     /**
681      * create Source Object container
682      *
683      * @param Smarty_Resource $handler          Resource Handler this source object communicates with
684      * @param Smarty          $smarty           Smarty instance this source object belongs to
685      * @param string          $resource         full template_resource
686      * @param string          $type             type of resource
687      * @param string          $name             resource name
688      * @param string          $unique_resource  unqiue resource name
689      */
690     public function __construct(Smarty_Resource $handler, Smarty $smarty, $resource, $type, $name, $unique_resource)
691     {
692         $this->handler = $handler; // Note: prone to circular references
693
694         $this->compiler_class = $handler->compiler_class;
695         $this->template_lexer_class = $handler->template_lexer_class;
696         $this->template_parser_class = $handler->template_parser_class;
697         $this->uncompiled = $this->handler instanceof Smarty_Resource_Uncompiled;
698         $this->recompiled = $this->handler instanceof Smarty_Resource_Recompiled;
699
700         $this->smarty = $smarty;
701         $this->resource = $resource;
702         $this->type = $type;
703         $this->name = $name;
704         $this->unique_resource = $unique_resource;
705     }
706
707     /**
708      * get a Compiled Object of this source
709      *
710      * @param Smarty_Internal_Template $_template template objet
711      * @return Smarty_Template_Compiled compiled object
712      */
713     public function getCompiled(Smarty_Internal_Template $_template)
714     {
715         // check runtime cache
716         $_cache_key = $this->unique_resource . '#' . $_template->compile_id;
717         if (isset(Smarty_Resource::$compileds[$_cache_key])) {
718             return Smarty_Resource::$compileds[$_cache_key];
719         }
720
721         $compiled = new Smarty_Template_Compiled($this);
722         $this->handler->populateCompiledFilepath($compiled, $_template);
723         $compiled->timestamp = @filemtime($compiled->filepath);
724         $compiled->exists = !!$compiled->timestamp;
725
726         // runtime cache
727         Smarty_Resource::$compileds[$_cache_key] = $compiled;
728
729         return $compiled;
730     }
731
732     /**
733      * render the uncompiled source
734      *
735      * @param Smarty_Internal_Template $_template template object
736      */
737     public function renderUncompiled(Smarty_Internal_Template $_template)
738     {
739         return $this->handler->renderUncompiled($this, $_template);
740     }
741
742     /**
743      * <<magic>> Generic Setter.
744      *
745      * @param string $property_name valid: timestamp, exists, content, template
746      * @param mixed  $value        new value (is not checked)
747      * @throws SmartyException if $property_name is not valid
748      */
749     public function __set($property_name, $value)
750     {
751         switch ($property_name) {
752             // regular attributes
753             case 'timestamp':
754             case 'exists':
755             case 'content':
756             // required for extends: only
757             case 'template':
758                 $this->$property_name = $value;
759                 break;
760
761             default:
762                 throw new SmartyException("invalid source property '$property_name'.");
763         }
764     }
765
766     /**
767      * <<magic>> Generic getter.
768      *
769      * @param string $property_name valid: timestamp, exists, content
770      * @return mixed
771      * @throws SmartyException if $property_name is not valid
772      */
773     public function __get($property_name)
774     {
775         switch ($property_name) {
776             case 'timestamp':
777             case 'exists':
778                 $this->handler->populateTimestamp($this);
779                 return $this->$property_name;
780
781             case 'content':
782                 return $this->content = $this->handler->getContent($this);
783
784             default:
785                 throw new SmartyException("source property '$property_name' does not exist.");
786         }
787     }
788
789 }
790
791 /**
792  * Smarty Resource Data Object
793  *
794  * Meta Data Container for Template Files
795  *
796  * @package Smarty
797  * @subpackage TemplateResources
798  * @author Rodney Rehm
799  *
800  * @property string $content compiled content
801  */
802 class Smarty_Template_Compiled {
803
804     /**
805      * Compiled Filepath
806      * @var string
807      */
808     public $filepath = null;
809
810     /**
811      * Compiled Timestamp
812      * @var integer
813      */
814     public $timestamp = null;
815
816     /**
817      * Compiled Existance
818      * @var boolean
819      */
820     public $exists = false;
821
822     /**
823      * Compiled Content Loaded
824      * @var boolean
825      */
826     public $loaded = false;
827
828     /**
829      * Template was compiled
830      * @var boolean
831      */
832     public $isCompiled = false;
833
834     /**
835      * Source Object
836      * @var Smarty_Template_Source
837      */
838     public $source = null;
839
840     /**
841      * Metadata properties
842      *
843      * populated by Smarty_Internal_Template::decodeProperties()
844      * @var array
845      */
846     public $_properties = null;
847
848     /**
849      * create Compiled Object container
850      *
851      * @param Smarty_Template_Source $source source object this compiled object belongs to
852      */
853     public function __construct(Smarty_Template_Source $source)
854     {
855         $this->source = $source;
856     }
857
858 }
859
860 ?>