template_loader.php needs to include template.php
[hoplite.git] / views / template_loader.php
1 <?php
2 // Hoplite
3 // Copyright (c) 2011 Blue Static
4 //
5 // This program is free software: you can redistribute it and/or modify it
6 // under the terms of the GNU General Public License as published by the Free
7 // Software Foundation, either version 3 of the License, or any later version.
8 //
9 // This program is distributed in the hope that it will be useful, but WITHOUT
10 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 // more details.
13 //
14 // You should have received a copy of the GNU General Public License along with
15 // this program. If not, see <http://www.gnu.org/licenses/>.
16
17 namespace hoplite\views;
18
19 require_once HOPLITE_ROOT . '/views/template.php';
20
21 /*!
22 This class knows how to load and cache templates to the file system.
23 */
24 class TemplateLoader
25 {
26 /*! @var TemplateLoader Singleton instance */
27 static private $instance = NULL;
28
29 /*! @var string Base path for loading the template file. Use %s to indicate
30 where the name (passed to the constructor) should be
31 substituted.
32 */
33 protected $template_path = '%s.tpl';
34
35 /*! @var string The cache path for templates. Unlike |$template_path|, this
36 should only be a path, to which the cached template name will
37 be appended. This should not end with a trailing slash.
38 */
39 protected $cache_path = '/tmp/phalanx_views';
40
41 /*! @var string A header to put at the beginning of each cached template file,
42 common for setting include paths or cache debug information.
43 */
44 protected $cache_prefix = '';
45
46 /*! @var array An array of Template objects, keyed by the template name. */
47 protected $cache = array();
48
49 /*! Gets the singleton instance. */
50 static public function GetInstance()
51 {
52 if (!self::$instance) {
53 $class = get_called_class();
54 self::$instance = new $class();
55 }
56 return self::$instance;
57 }
58 /*! Sets the singleton instance. */
59 static public function SetInstance($instance) { self::$instance = $instance; }
60
61 /*! Accessors */
62 public function set_template_path($path) { $this->template_path = $path; }
63 function template_path() { return $this->template_path; }
64
65 public function set_cache_path($path) { $this->cache_path = $path; }
66 public function cache_path() { return $this->cache_path; }
67
68 /*!
69 Loads a template from a file, creates a Template object, and returns a copy
70 of that object.
71
72 @param string Template name, with wich the template plath is formatted.
73
74 @return Template Clone of the cached template.
75 */
76 public function Load($name)
77 {
78 // First check the memory cache.
79 if (isset($this->cache[$name]))
80 return clone $this->cache[$name];
81
82 // Then check the filesystem cache.
83 $template = $this->_LoadIfCached($name);
84 if ($template) {
85 $this->cache[$name] = $template;
86 return clone $template;
87 }
88
89 // Finally, parse and cache the template.
90 $template = $this->_Cache($name);
91 $this->cache[$name] = $template;
92 return clone $template;
93 }
94
95 /*! Convenience function for loading templates. */
96 static public function Fetch($name)
97 {
98 return self::GetInstance()->Load($name);
99 }
100
101 /*!
102 Loads a cached filesystem template if it is up-to-date.
103
104 @param string Template name
105
106 @return Template|NULL
107 */
108 protected function _LoadIfCached($name)
109 {
110 $cache_path = $this->_CachePath($name);
111 $tpl_path = $this->_TemplatePath($name);
112
113 // Make sure the cached file exists and hasn't gotten out-of-date.
114 if (!file_exists($cache_path) || filemtime($cache_path) < filemtime($tpl_path))
115 return NULL;
116
117 // Load the contents of the cache.
118 $data = @file_get_contents($cache_path);
119 if ($data === FALSE)
120 return NULL;
121
122 return Template::NewWithCompiledData($data);
123 }
124
125 /*!
126 Loads a raw template from the file system, stores the compiled template in
127 the file system, and returns a new template object with that data.
128
129 @param string Template name.
130
131 @return Template
132 */
133 protected function _Cache($name)
134 {
135 $cache_path = $this->_CachePath($name);
136 $tpl_path = $this->_TemplatePath($name);
137
138 $data = @file_get_contents($tpl_path);
139 if ($data === FALSE)
140 throw new TemplateLoaderException('Could not load template ' . $name);
141
142 $template = Template::NewWithData($data);
143
144 // Cache the file.
145 if (file_put_contents($cache_path, $this->cache_prefix . $template->template()) === FALSE)
146 throw new TemplateLoaderException('Could not cache ' . $name . ' to ' . $cache_path);
147
148 return $template;
149 }
150
151 /*! Returns the template path for a given template name. */
152 protected function _TemplatePath($name)
153 {
154 return sprintf($this->template_path, $name);
155 }
156
157 /*! Returns the cache path for a given template name. */
158 protected function _CachePath($name)
159 {
160 return $this->cache_path . $name . '.phpi';
161 }
162 }
163
164 class TemplateLoaderException extends \Exception {}