aboutsummaryrefslogtreecommitdiffhomepage
path: root/inc/Twig/Loader
diff options
context:
space:
mode:
Diffstat (limited to 'inc/Twig/Loader')
-rw-r--r--inc/Twig/Loader/Array.php98
-rw-r--r--inc/Twig/Loader/Chain.php139
-rw-r--r--inc/Twig/Loader/Filesystem.php223
-rw-r--r--inc/Twig/Loader/String.php59
4 files changed, 519 insertions, 0 deletions
diff --git a/inc/Twig/Loader/Array.php b/inc/Twig/Loader/Array.php
new file mode 100644
index 00000000..89087aea
--- /dev/null
+++ b/inc/Twig/Loader/Array.php
@@ -0,0 +1,98 @@
1<?php
2
3/*
4 * This file is part of Twig.
5 *
6 * (c) 2009 Fabien Potencier
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12/**
13 * Loads a template from an array.
14 *
15 * When using this loader with a cache mechanism, you should know that a new cache
16 * key is generated each time a template content "changes" (the cache key being the
17 * source code of the template). If you don't want to see your cache grows out of
18 * control, you need to take care of clearing the old cache file by yourself.
19 *
20 * @author Fabien Potencier <fabien@symfony.com>
21 */
22class Twig_Loader_Array implements Twig_LoaderInterface, Twig_ExistsLoaderInterface
23{
24 protected $templates;
25
26 /**
27 * Constructor.
28 *
29 * @param array $templates An array of templates (keys are the names, and values are the source code)
30 *
31 * @see Twig_Loader
32 */
33 public function __construct(array $templates)
34 {
35 $this->templates = array();
36 foreach ($templates as $name => $template) {
37 $this->templates[$name] = $template;
38 }
39 }
40
41 /**
42 * Adds or overrides a template.
43 *
44 * @param string $name The template name
45 * @param string $template The template source
46 */
47 public function setTemplate($name, $template)
48 {
49 $this->templates[(string) $name] = $template;
50 }
51
52 /**
53 * {@inheritdoc}
54 */
55 public function getSource($name)
56 {
57 $name = (string) $name;
58 if (!isset($this->templates[$name])) {
59 throw new Twig_Error_Loader(sprintf('Template "%s" is not defined.', $name));
60 }
61
62 return $this->templates[$name];
63 }
64
65 /**
66 * {@inheritdoc}
67 */
68 public function exists($name)
69 {
70 return isset($this->templates[(string) $name]);
71 }
72
73 /**
74 * {@inheritdoc}
75 */
76 public function getCacheKey($name)
77 {
78 $name = (string) $name;
79 if (!isset($this->templates[$name])) {
80 throw new Twig_Error_Loader(sprintf('Template "%s" is not defined.', $name));
81 }
82
83 return $this->templates[$name];
84 }
85
86 /**
87 * {@inheritdoc}
88 */
89 public function isFresh($name, $time)
90 {
91 $name = (string) $name;
92 if (!isset($this->templates[$name])) {
93 throw new Twig_Error_Loader(sprintf('Template "%s" is not defined.', $name));
94 }
95
96 return true;
97 }
98}
diff --git a/inc/Twig/Loader/Chain.php b/inc/Twig/Loader/Chain.php
new file mode 100644
index 00000000..1f1cf065
--- /dev/null
+++ b/inc/Twig/Loader/Chain.php
@@ -0,0 +1,139 @@
1<?php
2
3/*
4 * This file is part of Twig.
5 *
6 * (c) 2011 Fabien Potencier
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12/**
13 * Loads templates from other loaders.
14 *
15 * @author Fabien Potencier <fabien@symfony.com>
16 */
17class Twig_Loader_Chain implements Twig_LoaderInterface, Twig_ExistsLoaderInterface
18{
19 private $hasSourceCache = array();
20 protected $loaders;
21
22 /**
23 * Constructor.
24 *
25 * @param Twig_LoaderInterface[] $loaders An array of loader instances
26 */
27 public function __construct(array $loaders = array())
28 {
29 $this->loaders = array();
30 foreach ($loaders as $loader) {
31 $this->addLoader($loader);
32 }
33 }
34
35 /**
36 * Adds a loader instance.
37 *
38 * @param Twig_LoaderInterface $loader A Loader instance
39 */
40 public function addLoader(Twig_LoaderInterface $loader)
41 {
42 $this->loaders[] = $loader;
43 $this->hasSourceCache = array();
44 }
45
46 /**
47 * {@inheritdoc}
48 */
49 public function getSource($name)
50 {
51 $exceptions = array();
52 foreach ($this->loaders as $loader) {
53 if ($loader instanceof Twig_ExistsLoaderInterface && !$loader->exists($name)) {
54 continue;
55 }
56
57 try {
58 return $loader->getSource($name);
59 } catch (Twig_Error_Loader $e) {
60 $exceptions[] = $e->getMessage();
61 }
62 }
63
64 throw new Twig_Error_Loader(sprintf('Template "%s" is not defined (%s).', $name, implode(', ', $exceptions)));
65 }
66
67 /**
68 * {@inheritdoc}
69 */
70 public function exists($name)
71 {
72 $name = (string) $name;
73
74 if (isset($this->hasSourceCache[$name])) {
75 return $this->hasSourceCache[$name];
76 }
77
78 foreach ($this->loaders as $loader) {
79 if ($loader instanceof Twig_ExistsLoaderInterface) {
80 if ($loader->exists($name)) {
81 return $this->hasSourceCache[$name] = true;
82 }
83
84 continue;
85 }
86
87 try {
88 $loader->getSource($name);
89
90 return $this->hasSourceCache[$name] = true;
91 } catch (Twig_Error_Loader $e) {
92 }
93 }
94
95 return $this->hasSourceCache[$name] = false;
96 }
97
98 /**
99 * {@inheritdoc}
100 */
101 public function getCacheKey($name)
102 {
103 $exceptions = array();
104 foreach ($this->loaders as $loader) {
105 if ($loader instanceof Twig_ExistsLoaderInterface && !$loader->exists($name)) {
106 continue;
107 }
108
109 try {
110 return $loader->getCacheKey($name);
111 } catch (Twig_Error_Loader $e) {
112 $exceptions[] = get_class($loader).': '.$e->getMessage();
113 }
114 }
115
116 throw new Twig_Error_Loader(sprintf('Template "%s" is not defined (%s).', $name, implode(' ', $exceptions)));
117 }
118
119 /**
120 * {@inheritdoc}
121 */
122 public function isFresh($name, $time)
123 {
124 $exceptions = array();
125 foreach ($this->loaders as $loader) {
126 if ($loader instanceof Twig_ExistsLoaderInterface && !$loader->exists($name)) {
127 continue;
128 }
129
130 try {
131 return $loader->isFresh($name, $time);
132 } catch (Twig_Error_Loader $e) {
133 $exceptions[] = get_class($loader).': '.$e->getMessage();
134 }
135 }
136
137 throw new Twig_Error_Loader(sprintf('Template "%s" is not defined (%s).', $name, implode(' ', $exceptions)));
138 }
139}
diff --git a/inc/Twig/Loader/Filesystem.php b/inc/Twig/Loader/Filesystem.php
new file mode 100644
index 00000000..f9211cbd
--- /dev/null
+++ b/inc/Twig/Loader/Filesystem.php
@@ -0,0 +1,223 @@
1<?php
2
3/*
4 * This file is part of Twig.
5 *
6 * (c) 2009 Fabien Potencier
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12/**
13 * Loads template from the filesystem.
14 *
15 * @author Fabien Potencier <fabien@symfony.com>
16 */
17class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderInterface
18{
19 protected $paths;
20 protected $cache;
21
22 /**
23 * Constructor.
24 *
25 * @param string|array $paths A path or an array of paths where to look for templates
26 */
27 public function __construct($paths = array())
28 {
29 if ($paths) {
30 $this->setPaths($paths);
31 }
32 }
33
34 /**
35 * Returns the paths to the templates.
36 *
37 * @param string $namespace A path namespace
38 *
39 * @return array The array of paths where to look for templates
40 */
41 public function getPaths($namespace = '__main__')
42 {
43 return isset($this->paths[$namespace]) ? $this->paths[$namespace] : array();
44 }
45
46 /**
47 * Returns the path namespaces.
48 *
49 * The "__main__" namespace is always defined.
50 *
51 * @return array The array of defined namespaces
52 */
53 public function getNamespaces()
54 {
55 return array_keys($this->paths);
56 }
57
58 /**
59 * Sets the paths where templates are stored.
60 *
61 * @param string|array $paths A path or an array of paths where to look for templates
62 * @param string $namespace A path namespace
63 */
64 public function setPaths($paths, $namespace = '__main__')
65 {
66 if (!is_array($paths)) {
67 $paths = array($paths);
68 }
69
70 $this->paths[$namespace] = array();
71 foreach ($paths as $path) {
72 $this->addPath($path, $namespace);
73 }
74 }
75
76 /**
77 * Adds a path where templates are stored.
78 *
79 * @param string $path A path where to look for templates
80 * @param string $namespace A path name
81 *
82 * @throws Twig_Error_Loader
83 */
84 public function addPath($path, $namespace = '__main__')
85 {
86 // invalidate the cache
87 $this->cache = array();
88
89 if (!is_dir($path)) {
90 throw new Twig_Error_Loader(sprintf('The "%s" directory does not exist.', $path));
91 }
92
93 $this->paths[$namespace][] = rtrim($path, '/\\');
94 }
95
96 /**
97 * Prepends a path where templates are stored.
98 *
99 * @param string $path A path where to look for templates
100 * @param string $namespace A path name
101 *
102 * @throws Twig_Error_Loader
103 */
104 public function prependPath($path, $namespace = '__main__')
105 {
106 // invalidate the cache
107 $this->cache = array();
108
109 if (!is_dir($path)) {
110 throw new Twig_Error_Loader(sprintf('The "%s" directory does not exist.', $path));
111 }
112
113 $path = rtrim($path, '/\\');
114
115 if (!isset($this->paths[$namespace])) {
116 $this->paths[$namespace][] = $path;
117 } else {
118 array_unshift($this->paths[$namespace], $path);
119 }
120 }
121
122 /**
123 * {@inheritdoc}
124 */
125 public function getSource($name)
126 {
127 return file_get_contents($this->findTemplate($name));
128 }
129
130 /**
131 * {@inheritdoc}
132 */
133 public function getCacheKey($name)
134 {
135 return $this->findTemplate($name);
136 }
137
138 /**
139 * {@inheritdoc}
140 */
141 public function exists($name)
142 {
143 $name = (string) $name;
144 if (isset($this->cache[$name])) {
145 return true;
146 }
147
148 try {
149 $this->findTemplate($name);
150
151 return true;
152 } catch (Twig_Error_Loader $exception) {
153 return false;
154 }
155 }
156
157 /**
158 * {@inheritdoc}
159 */
160 public function isFresh($name, $time)
161 {
162 return filemtime($this->findTemplate($name)) <= $time;
163 }
164
165 protected function findTemplate($name)
166 {
167 $name = (string) $name;
168
169 // normalize name
170 $name = preg_replace('#/{2,}#', '/', strtr($name, '\\', '/'));
171
172 if (isset($this->cache[$name])) {
173 return $this->cache[$name];
174 }
175
176 $this->validateName($name);
177
178 $namespace = '__main__';
179 if (isset($name[0]) && '@' == $name[0]) {
180 if (false === $pos = strpos($name, '/')) {
181 throw new Twig_Error_Loader(sprintf('Malformed namespaced template name "%s" (expecting "@namespace/template_name").', $name));
182 }
183
184 $namespace = substr($name, 1, $pos - 1);
185
186 $name = substr($name, $pos + 1);
187 }
188
189 if (!isset($this->paths[$namespace])) {
190 throw new Twig_Error_Loader(sprintf('There are no registered paths for namespace "%s".', $namespace));
191 }
192
193 foreach ($this->paths[$namespace] as $path) {
194 if (is_file($path.'/'.$name)) {
195 return $this->cache[$name] = $path.'/'.$name;
196 }
197 }
198
199 throw new Twig_Error_Loader(sprintf('Unable to find template "%s" (looked into: %s).', $name, implode(', ', $this->paths[$namespace])));
200 }
201
202 protected function validateName($name)
203 {
204 if (false !== strpos($name, "\0")) {
205 throw new Twig_Error_Loader('A template name cannot contain NUL bytes.');
206 }
207
208 $name = ltrim($name, '/');
209 $parts = explode('/', $name);
210 $level = 0;
211 foreach ($parts as $part) {
212 if ('..' === $part) {
213 --$level;
214 } elseif ('.' !== $part) {
215 ++$level;
216 }
217
218 if ($level < 0) {
219 throw new Twig_Error_Loader(sprintf('Looks like you try to load a template outside configured directories (%s).', $name));
220 }
221 }
222 }
223}
diff --git a/inc/Twig/Loader/String.php b/inc/Twig/Loader/String.php
new file mode 100644
index 00000000..8ad9856c
--- /dev/null
+++ b/inc/Twig/Loader/String.php
@@ -0,0 +1,59 @@
1<?php
2
3/*
4 * This file is part of Twig.
5 *
6 * (c) 2009 Fabien Potencier
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12/**
13 * Loads a template from a string.
14 *
15 * This loader should only be used for unit testing as it has many limitations
16 * (for instance, the include or extends tag does not make any sense for a string
17 * loader).
18 *
19 * When using this loader with a cache mechanism, you should know that a new cache
20 * key is generated each time a template content "changes" (the cache key being the
21 * source code of the template). If you don't want to see your cache grows out of
22 * control, you need to take care of clearing the old cache file by yourself.
23 *
24 * @author Fabien Potencier <fabien@symfony.com>
25 */
26class Twig_Loader_String implements Twig_LoaderInterface, Twig_ExistsLoaderInterface
27{
28 /**
29 * {@inheritdoc}
30 */
31 public function getSource($name)
32 {
33 return $name;
34 }
35
36 /**
37 * {@inheritdoc}
38 */
39 public function exists($name)
40 {
41 return true;
42 }
43
44 /**
45 * {@inheritdoc}
46 */
47 public function getCacheKey($name)
48 {
49 return $name;
50 }
51
52 /**
53 * {@inheritdoc}
54 */
55 public function isFresh($name, $time)
56 {
57 return true;
58 }
59}