summaryrefslogtreecommitdiff
path: root/inc/lib/Twig/Loader
diff options
context:
space:
mode:
authorMichael Foster <savetheinternet@tinyboard.org>2013-08-01 15:20:12 -0400
committerMichael Foster <savetheinternet@tinyboard.org>2013-08-01 15:20:12 -0400
commit0fe552857468aa12097a74e08f51f5aaa983be07 (patch)
tree22dbca1be90d7086b20a077752552296abf23325 /inc/lib/Twig/Loader
parent22f3a95e0e421de05a11633eac846df96a2a4768 (diff)
Upgrade Twig library
Diffstat (limited to 'inc/lib/Twig/Loader')
-rw-r--r--inc/lib/Twig/Loader/Array.php39
-rw-r--r--inc/lib/Twig/Loader/Chain.php79
-rw-r--r--inc/lib/Twig/Loader/Filesystem.php129
-rw-r--r--inc/lib/Twig/Loader/String.php34
4 files changed, 197 insertions, 84 deletions
diff --git a/inc/lib/Twig/Loader/Array.php b/inc/lib/Twig/Loader/Array.php
index e8dc1605..89087aea 100644
--- a/inc/lib/Twig/Loader/Array.php
+++ b/inc/lib/Twig/Loader/Array.php
@@ -17,10 +17,9 @@
* source code of the template). If you don't want to see your cache grows out of
* control, you need to take care of clearing the old cache file by yourself.
*
- * @package twig
- * @author Fabien Potencier <fabien@symfony.com>
+ * @author Fabien Potencier <fabien@symfony.com>
*/
-class Twig_Loader_Array implements Twig_LoaderInterface
+class Twig_Loader_Array implements Twig_LoaderInterface, Twig_ExistsLoaderInterface
{
protected $templates;
@@ -47,18 +46,15 @@ class Twig_Loader_Array implements Twig_LoaderInterface
*/
public function setTemplate($name, $template)
{
- $this->templates[$name] = $template;
+ $this->templates[(string) $name] = $template;
}
/**
- * Gets the source code of a template, given its name.
- *
- * @param string $name The name of the template to load
- *
- * @return string The template source code
+ * {@inheritdoc}
*/
public function getSource($name)
{
+ $name = (string) $name;
if (!isset($this->templates[$name])) {
throw new Twig_Error_Loader(sprintf('Template "%s" is not defined.', $name));
}
@@ -67,14 +63,19 @@ class Twig_Loader_Array implements Twig_LoaderInterface
}
/**
- * Gets the cache key to use for the cache for a given template name.
- *
- * @param string $name The name of the template to load
- *
- * @return string The cache key
+ * {@inheritdoc}
+ */
+ public function exists($name)
+ {
+ return isset($this->templates[(string) $name]);
+ }
+
+ /**
+ * {@inheritdoc}
*/
public function getCacheKey($name)
{
+ $name = (string) $name;
if (!isset($this->templates[$name])) {
throw new Twig_Error_Loader(sprintf('Template "%s" is not defined.', $name));
}
@@ -83,13 +84,15 @@ class Twig_Loader_Array implements Twig_LoaderInterface
}
/**
- * Returns true if the template is still fresh.
- *
- * @param string $name The template name
- * @param timestamp $time The last modification time of the cached template
+ * {@inheritdoc}
*/
public function isFresh($name, $time)
{
+ $name = (string) $name;
+ if (!isset($this->templates[$name])) {
+ throw new Twig_Error_Loader(sprintf('Template "%s" is not defined.', $name));
+ }
+
return true;
}
}
diff --git a/inc/lib/Twig/Loader/Chain.php b/inc/lib/Twig/Loader/Chain.php
index 48dd8b84..1f1cf065 100644
--- a/inc/lib/Twig/Loader/Chain.php
+++ b/inc/lib/Twig/Loader/Chain.php
@@ -12,11 +12,11 @@
/**
* Loads templates from other loaders.
*
- * @package twig
- * @author Fabien Potencier <fabien@symfony.com>
+ * @author Fabien Potencier <fabien@symfony.com>
*/
-class Twig_Loader_Chain implements Twig_LoaderInterface
+class Twig_Loader_Chain implements Twig_LoaderInterface, Twig_ExistsLoaderInterface
{
+ private $hasSourceCache = array();
protected $loaders;
/**
@@ -40,61 +40,100 @@ class Twig_Loader_Chain implements Twig_LoaderInterface
public function addLoader(Twig_LoaderInterface $loader)
{
$this->loaders[] = $loader;
+ $this->hasSourceCache = array();
}
/**
- * Gets the source code of a template, given its name.
- *
- * @param string $name The name of the template to load
- *
- * @return string The template source code
+ * {@inheritdoc}
*/
public function getSource($name)
{
+ $exceptions = array();
foreach ($this->loaders as $loader) {
+ if ($loader instanceof Twig_ExistsLoaderInterface && !$loader->exists($name)) {
+ continue;
+ }
+
try {
return $loader->getSource($name);
} catch (Twig_Error_Loader $e) {
+ $exceptions[] = $e->getMessage();
}
}
- throw new Twig_Error_Loader(sprintf('Template "%s" is not defined.', $name));
+ throw new Twig_Error_Loader(sprintf('Template "%s" is not defined (%s).', $name, implode(', ', $exceptions)));
}
/**
- * Gets the cache key to use for the cache for a given template name.
- *
- * @param string $name The name of the template to load
- *
- * @return string The cache key
+ * {@inheritdoc}
+ */
+ public function exists($name)
+ {
+ $name = (string) $name;
+
+ if (isset($this->hasSourceCache[$name])) {
+ return $this->hasSourceCache[$name];
+ }
+
+ foreach ($this->loaders as $loader) {
+ if ($loader instanceof Twig_ExistsLoaderInterface) {
+ if ($loader->exists($name)) {
+ return $this->hasSourceCache[$name] = true;
+ }
+
+ continue;
+ }
+
+ try {
+ $loader->getSource($name);
+
+ return $this->hasSourceCache[$name] = true;
+ } catch (Twig_Error_Loader $e) {
+ }
+ }
+
+ return $this->hasSourceCache[$name] = false;
+ }
+
+ /**
+ * {@inheritdoc}
*/
public function getCacheKey($name)
{
+ $exceptions = array();
foreach ($this->loaders as $loader) {
+ if ($loader instanceof Twig_ExistsLoaderInterface && !$loader->exists($name)) {
+ continue;
+ }
+
try {
return $loader->getCacheKey($name);
} catch (Twig_Error_Loader $e) {
+ $exceptions[] = get_class($loader).': '.$e->getMessage();
}
}
- throw new Twig_Error_Loader(sprintf('Template "%s" is not defined.', $name));
+ throw new Twig_Error_Loader(sprintf('Template "%s" is not defined (%s).', $name, implode(' ', $exceptions)));
}
/**
- * Returns true if the template is still fresh.
- *
- * @param string $name The template name
- * @param timestamp $time The last modification time of the cached template
+ * {@inheritdoc}
*/
public function isFresh($name, $time)
{
+ $exceptions = array();
foreach ($this->loaders as $loader) {
+ if ($loader instanceof Twig_ExistsLoaderInterface && !$loader->exists($name)) {
+ continue;
+ }
+
try {
return $loader->isFresh($name, $time);
} catch (Twig_Error_Loader $e) {
+ $exceptions[] = get_class($loader).': '.$e->getMessage();
}
}
- throw new Twig_Error_Loader(sprintf('Template "%s" is not defined.', $name));
+ throw new Twig_Error_Loader(sprintf('Template "%s" is not defined (%s).', $name, implode(' ', $exceptions)));
}
}
diff --git a/inc/lib/Twig/Loader/Filesystem.php b/inc/lib/Twig/Loader/Filesystem.php
index be348aa3..f9211cbd 100644
--- a/inc/lib/Twig/Loader/Filesystem.php
+++ b/inc/lib/Twig/Loader/Filesystem.php
@@ -12,10 +12,9 @@
/**
* Loads template from the filesystem.
*
- * @package twig
- * @author Fabien Potencier <fabien@symfony.com>
+ * @author Fabien Potencier <fabien@symfony.com>
*/
-class Twig_Loader_Filesystem implements Twig_LoaderInterface
+class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderInterface
{
protected $paths;
protected $cache;
@@ -25,44 +24,64 @@ class Twig_Loader_Filesystem implements Twig_LoaderInterface
*
* @param string|array $paths A path or an array of paths where to look for templates
*/
- public function __construct($paths)
+ public function __construct($paths = array())
{
- $this->setPaths($paths);
+ if ($paths) {
+ $this->setPaths($paths);
+ }
}
/**
* Returns the paths to the templates.
*
+ * @param string $namespace A path namespace
+ *
* @return array The array of paths where to look for templates
*/
- public function getPaths()
+ public function getPaths($namespace = '__main__')
+ {
+ return isset($this->paths[$namespace]) ? $this->paths[$namespace] : array();
+ }
+
+ /**
+ * Returns the path namespaces.
+ *
+ * The "__main__" namespace is always defined.
+ *
+ * @return array The array of defined namespaces
+ */
+ public function getNamespaces()
{
- return $this->paths;
+ return array_keys($this->paths);
}
/**
* Sets the paths where templates are stored.
*
- * @param string|array $paths A path or an array of paths where to look for templates
+ * @param string|array $paths A path or an array of paths where to look for templates
+ * @param string $namespace A path namespace
*/
- public function setPaths($paths)
+ public function setPaths($paths, $namespace = '__main__')
{
if (!is_array($paths)) {
$paths = array($paths);
}
- $this->paths = array();
+ $this->paths[$namespace] = array();
foreach ($paths as $path) {
- $this->addPath($path);
+ $this->addPath($path, $namespace);
}
}
/**
* Adds a path where templates are stored.
*
- * @param string $path A path where to look for templates
+ * @param string $path A path where to look for templates
+ * @param string $namespace A path name
+ *
+ * @throws Twig_Error_Loader
*/
- public function addPath($path)
+ public function addPath($path, $namespace = '__main__')
{
// invalidate the cache
$this->cache = array();
@@ -71,15 +90,37 @@ class Twig_Loader_Filesystem implements Twig_LoaderInterface
throw new Twig_Error_Loader(sprintf('The "%s" directory does not exist.', $path));
}
- $this->paths[] = $path;
+ $this->paths[$namespace][] = rtrim($path, '/\\');
}
/**
- * Gets the source code of a template, given its name.
+ * Prepends a path where templates are stored.
*
- * @param string $name The name of the template to load
+ * @param string $path A path where to look for templates
+ * @param string $namespace A path name
*
- * @return string The template source code
+ * @throws Twig_Error_Loader
+ */
+ public function prependPath($path, $namespace = '__main__')
+ {
+ // invalidate the cache
+ $this->cache = array();
+
+ if (!is_dir($path)) {
+ throw new Twig_Error_Loader(sprintf('The "%s" directory does not exist.', $path));
+ }
+
+ $path = rtrim($path, '/\\');
+
+ if (!isset($this->paths[$namespace])) {
+ $this->paths[$namespace][] = $path;
+ } else {
+ array_unshift($this->paths[$namespace], $path);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
*/
public function getSource($name)
{
@@ -87,11 +128,7 @@ class Twig_Loader_Filesystem implements Twig_LoaderInterface
}
/**
- * Gets the cache key to use for the cache for a given template name.
- *
- * @param string $name The name of the template to load
- *
- * @return string The cache key
+ * {@inheritdoc}
*/
public function getCacheKey($name)
{
@@ -99,18 +136,36 @@ class Twig_Loader_Filesystem implements Twig_LoaderInterface
}
/**
- * Returns true if the template is still fresh.
- *
- * @param string $name The template name
- * @param timestamp $time The last modification time of the cached template
+ * {@inheritdoc}
+ */
+ public function exists($name)
+ {
+ $name = (string) $name;
+ if (isset($this->cache[$name])) {
+ return true;
+ }
+
+ try {
+ $this->findTemplate($name);
+
+ return true;
+ } catch (Twig_Error_Loader $exception) {
+ return false;
+ }
+ }
+
+ /**
+ * {@inheritdoc}
*/
public function isFresh($name, $time)
{
- return filemtime($this->findTemplate($name)) < $time;
+ return filemtime($this->findTemplate($name)) <= $time;
}
protected function findTemplate($name)
{
+ $name = (string) $name;
+
// normalize name
$name = preg_replace('#/{2,}#', '/', strtr($name, '\\', '/'));
@@ -120,13 +175,28 @@ class Twig_Loader_Filesystem implements Twig_LoaderInterface
$this->validateName($name);
- foreach ($this->paths as $path) {
+ $namespace = '__main__';
+ if (isset($name[0]) && '@' == $name[0]) {
+ if (false === $pos = strpos($name, '/')) {
+ throw new Twig_Error_Loader(sprintf('Malformed namespaced template name "%s" (expecting "@namespace/template_name").', $name));
+ }
+
+ $namespace = substr($name, 1, $pos - 1);
+
+ $name = substr($name, $pos + 1);
+ }
+
+ if (!isset($this->paths[$namespace])) {
+ throw new Twig_Error_Loader(sprintf('There are no registered paths for namespace "%s".', $namespace));
+ }
+
+ foreach ($this->paths[$namespace] as $path) {
if (is_file($path.'/'.$name)) {
return $this->cache[$name] = $path.'/'.$name;
}
}
- throw new Twig_Error_Loader(sprintf('Unable to find template "%s" (looked into: %s).', $name, implode(', ', $this->paths)));
+ throw new Twig_Error_Loader(sprintf('Unable to find template "%s" (looked into: %s).', $name, implode(', ', $this->paths[$namespace])));
}
protected function validateName($name)
@@ -135,6 +205,7 @@ class Twig_Loader_Filesystem implements Twig_LoaderInterface
throw new Twig_Error_Loader('A template name cannot contain NUL bytes.');
}
+ $name = ltrim($name, '/');
$parts = explode('/', $name);
$level = 0;
foreach ($parts as $part) {
diff --git a/inc/lib/Twig/Loader/String.php b/inc/lib/Twig/Loader/String.php
index 26eb0096..8ad9856c 100644
--- a/inc/lib/Twig/Loader/String.php
+++ b/inc/lib/Twig/Loader/String.php
@@ -12,22 +12,21 @@
/**
* Loads a template from a string.
*
+ * This loader should only be used for unit testing as it has many limitations
+ * (for instance, the include or extends tag does not make any sense for a string
+ * loader).
+ *
* When using this loader with a cache mechanism, you should know that a new cache
* key is generated each time a template content "changes" (the cache key being the
* source code of the template). If you don't want to see your cache grows out of
* control, you need to take care of clearing the old cache file by yourself.
*
- * @package twig
- * @author Fabien Potencier <fabien@symfony.com>
+ * @author Fabien Potencier <fabien@symfony.com>
*/
-class Twig_Loader_String implements Twig_LoaderInterface
+class Twig_Loader_String implements Twig_LoaderInterface, Twig_ExistsLoaderInterface
{
/**
- * Gets the source code of a template, given its name.
- *
- * @param string $name The name of the template to load
- *
- * @return string The template source code
+ * {@inheritdoc}
*/
public function getSource($name)
{
@@ -35,11 +34,15 @@ class Twig_Loader_String implements Twig_LoaderInterface
}
/**
- * Gets the cache key to use for the cache for a given template name.
- *
- * @param string $name The name of the template to load
- *
- * @return string The cache key
+ * {@inheritdoc}
+ */
+ public function exists($name)
+ {
+ return true;
+ }
+
+ /**
+ * {@inheritdoc}
*/
public function getCacheKey($name)
{
@@ -47,10 +50,7 @@ class Twig_Loader_String implements Twig_LoaderInterface
}
/**
- * Returns true if the template is still fresh.
- *
- * @param string $name The template name
- * @param timestamp $time The last modification time of the cached template
+ * {@inheritdoc}
*/
public function isFresh($name, $time)
{