smarty_resource.php 28 KB

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