Source for file caching_xtemplate.class.php

Documentation is available at caching_xtemplate.class.php

  1. <?php
  2.  
  3. require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'xtemplate.class.php');
  4.  
  5. /**
  6. * CachingXTemplate
  7. * Extension to XTemplate to provide block level and whole template caching facilities
  8. * Needs Web server writable directory
  9. *
  10. * @package XTemplate
  11. * @subpackage CachingXTemplate
  12. * @uses XTemplate
  13. * @author Jeremy Coates [cocomp@users.sourceforge.net]
  14. * @copyright Jeremy Coates / Co-Comp Ltd 2006-2007
  15. * @see license.txt BSD license
  16. * @since PHP 5
  17. * @link $HeadURL: https://xtpl.svn.sourceforge.net/svnroot/xtpl/trunk/caching_xtemplate.class.php $
  18. * @version $Id: caching_xtemplate.class.php 21 2007-05-29 18:01:15Z cocomp $
  19. *
  20. * @example Whole template level caching (e.g. the total parsed output for the file)
  21. * @example $xtpl = new CachingXTemplate('template.xtpl', '', null, 'main', true, 600, session_id(), './xcache', '.xcache');
  22. *
  23. * @example Alternatively (and perhaps more useful in real world):
  24. * @example Block level caching
  25. * @example $xtpl = new CachingXTemplate('template.xtpl', '', null, 'main', true, 0, session_id(), './xcache', '.xcache');
  26. * @example $xtpl->parse('main', 600);
  27. * @example Bear in mind that because XTemplate uses a reversed parsing tree the innermost blocks need to be parsed
  28. * @example first, therefore if you cache an outer block, don't be surprised when it's inner content blocks don't update!
  29. */
  30. class CachingXTemplate extends XTemplate {
  31.  
  32. /**
  33. * Cache expiry time (seconds)
  34. *
  35. * @access public
  36. * @var int
  37. */
  38. public $cache_expiry = 0;
  39.  
  40. /**
  41. * Cache file unique identifier
  42. *
  43. * @example session_id()
  44. * @access public
  45. * @var string
  46. */
  47. public $cache_unique = 'unique';
  48.  
  49. /**
  50. * Filename extension
  51. *
  52. * @example .xcache
  53. * @access public
  54. * @var string
  55. */
  56. public $cache_ext = '.xcache';
  57.  
  58. /**
  59. * Path to cache dir
  60. * Needs to be writable by webserver
  61. *
  62. * @example ./xcache
  63. * @access public
  64. * @var string
  65. */
  66. public $cache_dir = './xcache';
  67.  
  68. /**
  69. * Flag showing whether template is cached
  70. *
  71. * @access private
  72. * @var boolean
  73. */
  74. private $_template_is_cached = false;
  75.  
  76. /**
  77. * Cache expiry time
  78. *
  79. * @access private
  80. * @var int
  81. */
  82. private $_cache_expiry = 0;
  83.  
  84. /**
  85. * File modified time
  86. *
  87. * @access private
  88. * @var int
  89. */
  90. private $_cache_filemtime = 0;
  91.  
  92. /**
  93. * Override of parent constructor
  94. *
  95. * @access public
  96. * @param string $file Template file to work on
  97. * @param string $tpldir Location of template files (useful for keeping files outside web server root)
  98. * @param array $files Filenames lookup
  99. * @param string $mainblock Name of main block in the template
  100. * @param boolean $autosetup If true, run setup() as part of constuctor
  101. * @param int $cache_expiry Seconds to cache for
  102. * @param string $cache_unique Unique file id (e.g. session_id())
  103. * @param string $cache_dir Cache folder
  104. * @param string $cache_ext Cache file extension
  105. */
  106. public function __construct($file, $tpldir = '', $files = null, $mainblock = 'main', $autosetup = true, $cache_expiry = 0, $cache_unique = '', $cache_dir = './xcache', $cache_ext = '.xcache') {
  107.  
  108. $this->restart($file, $tpldir, $files, $mainblock, $autosetup, $this->tag_start_delim, $this->tag_end_delim, $cache_expiry, $cache_unique, $cache_dir, $cache_ext);
  109.  
  110. }
  111.  
  112. /**
  113. * Override of parent restart method
  114. *
  115. * @access public
  116. * @param string $file Template file to work on
  117. * @param string $tpldir Location of template files
  118. * @param array $files Filenames lookup
  119. * @param string $mainblock Name of main block in the template
  120. * @param boolean $autosetup If true, run setup() as part of restarting
  121. * @param string $tag_start {
  122. * @param string $tag_end }
  123. * @param int $cache_expiry Seconds to cache for
  124. * @param string $cache_unique Unique file id (e.g. session_id())
  125. * @param string $cache_dir Cache folder
  126. * @param string $cache_ext Cache file extension
  127. */
  128. public function restart ($file, $tpldir = '', $files = null, $mainblock = 'main', $autosetup = true, $tag_start = '{', $tag_end = '}', $cache_expiry = 0, $cache_unique = '', $cache_dir = './xcache', $cache_ext = '.xcache') {
  129.  
  130. if ($cache_expiry > 0) {
  131. $this->cache_expiry = $cache_expiry;
  132. }
  133.  
  134. if (!empty($cache_unique)) {
  135. if (!preg_match('/^\./', $cache_unique)) {
  136. $cache_unique = '.' . $cache_unique;
  137. }
  138. $this->cache_unique = $cache_unique;
  139. }
  140.  
  141. if (!empty($cache_dir)) {
  142. $this->cache_dir = $cache_dir;
  143. }
  144.  
  145. if (!empty($cache_ext)) {
  146. if (!preg_match('/^\./', $cache_ext)) {
  147. $cache_ext = '.' . $cache_ext;
  148. }
  149. $this->cache_ext = $cache_ext;
  150. }
  151.  
  152. // Call parent restart method but don't run setup yet!
  153. parent::restart($file, $tpldir, $files, $mainblock, false, $tag_start, $tag_end);
  154.  
  155. if ($this->cache_expiry > 0) {
  156. $this->read_template_cache();
  157. }
  158.  
  159. if (!$this->_template_is_cached && $autosetup) {
  160. $this->setup();
  161. }
  162. }
  163.  
  164. /**
  165. * Override of parent assign method
  166. *
  167. * @access public
  168. * @param string $name Variable to assign $val to
  169. * @param string / array $val Value to assign to $name
  170. * @param boolean $magic_quotes
  171. */
  172. public function assign ($name, $val = '', $magic_quotes = false) {
  173.  
  174. if (!$this->_template_is_cached) {
  175. parent::assign($name, $val, $magic_quotes);
  176. }
  177. }
  178.  
  179. /**
  180. * Override of parent assign_file method
  181. *
  182. * @access public
  183. * @param string $name Variable to assign $val to
  184. * @param string / array $val Values to assign to $name
  185. */
  186. public function assign_file ($name, $val = '') {
  187.  
  188. if (!$this->_template_is_cached) {
  189. parent::assign_file($name, $val);
  190. }
  191. }
  192.  
  193. /**
  194. * Override of parent parse method
  195. *
  196. * @access public
  197. * @param string $bname Block name to parse
  198. * @param int $cache_expiry Seconds to cache block for
  199. */
  200. public function parse ($bname, $cache_expiry = 0) {
  201.  
  202. if (!$this->_template_is_cached) {
  203.  
  204. if (!$this->read_block_cache($bname, $cache_expiry)) {
  205.  
  206. parent::parse($bname);
  207.  
  208. $this->write_block_cache($bname, $cache_expiry);
  209. }
  210. }
  211. }
  212.  
  213. /**
  214. * Override of parent text method
  215. *
  216. * @access public
  217. * @param string $bname Block name to return
  218. * @return string
  219. */
  220. public function text ($bname = '') {
  221.  
  222. $text = parent::text($bname);
  223.  
  224. if (!$this->_template_is_cached && $this->cache_expiry > 0) {
  225.  
  226. $this->write_template_cache();
  227.  
  228. } elseif ($this->debug && $this->output_type == 'HTML') {
  229.  
  230. $text_header = "<!-- CachingXTemplate debug:\n";
  231.  
  232. if ($this->cache_expiry > 0) {
  233.  
  234. $filename = $this->_get_filename();
  235.  
  236. $file = $this->cache_dir . DIRECTORY_SEPARATOR . $filename . $this->cache_unique . $this->cache_ext;
  237.  
  238. $text_header .= 'File: ' . $file . "\nExpires in: " . ($this->_cache_filemtime - $this->_cache_expiry) . " seconds -->\n";
  239. } else {
  240. $text_header .= "Template Cache (whole template) disabled -->\n";
  241. }
  242.  
  243. $text = $text_header . $text;
  244. }
  245.  
  246. return $text;
  247. }
  248.  
  249. /**
  250. * Read whole template cache file
  251. *
  252. * @access protected
  253. */
  254. protected function read_template_cache () {
  255.  
  256. $filename = $this->_get_filename();
  257.  
  258. $file = $this->cache_dir . DIRECTORY_SEPARATOR . $filename . DIRECTORY_SEPARATOR . $this->cache_unique . $this->cache_ext;
  259.  
  260. if ($this->cache_expiry > 0 && file_exists($file)) {
  261.  
  262. $this->_cache_filemtime = filemtime($file);
  263. $this->_cache_expiry = time() - $this->cache_expiry;
  264.  
  265. if ($this->_cache_filemtime >= $this->_cache_expiry) {
  266. if ($parsed_blocks = file_get_contents($file)) {
  267. $this->parsed_blocks = unserialize($parsed_blocks);
  268. $this->_template_is_cached = true;
  269. }
  270. } else {
  271. // Stale file
  272. if (is_writable($this->cache_dir) && is_writable($file)) {
  273. unlink($file);
  274. }
  275. }
  276. }
  277. }
  278.  
  279. /**
  280. * Write out whole template cache file
  281. *
  282. * @access protected
  283. */
  284. protected function write_template_cache () {
  285.  
  286. if ($this->cache_expiry > 0 && is_writable($this->cache_dir)) {
  287.  
  288. $filename = $this->_get_filename();
  289.  
  290. if (!file_exists($this->cache_dir . DIRECTORY_SEPARATOR . $filename)) {
  291. mkdir($this->cache_dir . DIRECTORY_SEPARATOR . $filename);
  292. }
  293.  
  294. file_put_contents($this->cache_dir . DIRECTORY_SEPARATOR . $filename . DIRECTORY_SEPARATOR . $this->cache_unique . $this->cache_ext, serialize($this->parsed_blocks));
  295. }
  296. }
  297.  
  298. /**
  299. * Read block level cache file
  300. *
  301. * @access protected
  302. * @param string $bname Block name to read from cache
  303. * @param ing $cache_expiry Seconds to cache block for
  304. * @return boolean
  305. */
  306. protected function read_block_cache ($bname, $cache_expiry = 0) {
  307.  
  308. $retval = false;
  309.  
  310. $filename = $this->_get_filename();
  311.  
  312. $file = $this->cache_dir . DIRECTORY_SEPARATOR . $filename . DIRECTORY_SEPARATOR . $bname . $this->cache_unique . $this->cache_ext;
  313.  
  314. if ($cache_expiry > 0 && file_exists($file)) {
  315.  
  316. $filemtime = filemtime($file);
  317. $cache_expiry = time() - $cache_expiry;
  318.  
  319. if ($filemtime >= $cache_expiry) {
  320. if ($block = file_get_contents($file)) {
  321. $block = unserialize($block);
  322. if ($this->debug) {
  323. $block = "<!-- CachingXTemplate debug:\nFile: " . $file . "\nBlock: " . $bname . "\nExpires in: " . ($filemtime - $cache_expiry) . ' seconds -->' . "\n" . $block;
  324. }
  325. $this->parsed_blocks[$bname] = $block;
  326. $retval = true;
  327. }
  328. } else {
  329. // Stale file
  330. if (is_writable($this->cache_dir) && is_writable($file)) {
  331. unlink($file);
  332. }
  333. }
  334. }
  335.  
  336. return $retval;
  337. }
  338.  
  339. /**
  340. * Write out block level cache file
  341. *
  342. * @access protected
  343. * @param string $bname Block name to cache
  344. * @param int $cache_expiry Seconds to cache block for
  345. */
  346. protected function write_block_cache ($bname, $cache_expiry = 0) {
  347.  
  348. if ($cache_expiry > 0 && is_writable($this->cache_dir)) {
  349.  
  350. $filename = $this->_get_filename();
  351.  
  352. if (!file_exists($this->cache_dir . DIRECTORY_SEPARATOR . $filename)) {
  353. mkdir($this->cache_dir . DIRECTORY_SEPARATOR . $filename);
  354. }
  355.  
  356. file_put_contents($this->cache_dir . DIRECTORY_SEPARATOR . $filename . DIRECTORY_SEPARATOR . $bname . $this->cache_unique . $this->cache_ext, serialize($this->parsed_blocks[$bname]));
  357. }
  358. }
  359.  
  360. /**
  361. * Create the main part of the cache filename
  362. *
  363. * @access private
  364. * @return string
  365. */
  366. private function _get_filename () {
  367.  
  368. $filename = $this->filename;
  369. if (!empty($this->tpldir)) {
  370.  
  371. $filename = str_replace(DIRECTORY_SEPARATOR, '_', $this->tpldir . DIRECTORY_SEPARATOR) . $this->filename;
  372. }
  373.  
  374. return $filename;
  375. }
  376. }
  377.  
  378. ?>

Documentation generated on Tue, 29 May 2007 19:29:31 +0100 by phpDocumentor 1.3.0RC3