Improvements for loader speeds
authorFlorin Patan <florinpatan@gmail.com>
Tue, 18 Sep 2012 19:27:45 +0000 (22:27 +0300)
committerFabien Potencier <fabien.potencier@gmail.com>
Fri, 19 Oct 2012 12:27:32 +0000 (14:27 +0200)
lib/Twig/Error.php
lib/Twig/ExtendedLoaderInterface.php [new file with mode: 0644]
lib/Twig/Loader/Array.php
lib/Twig/Loader/Chain.php
lib/Twig/Loader/Filesystem.php
lib/Twig/Loader/String.php

index b5ac00e..3e61c3f 100644 (file)
@@ -112,6 +112,8 @@ class Twig_Error extends Exception
      * @param array  $arguments The parameters to be passed to the method
      *
      * @return Exception The previous exception or null
+     *
+     * @throws BadMethodCallException
      */
     public function __call($method, $arguments)
     {
diff --git a/lib/Twig/ExtendedLoaderInterface.php b/lib/Twig/ExtendedLoaderInterface.php
new file mode 100644 (file)
index 0000000..8d59867
--- /dev/null
@@ -0,0 +1,31 @@
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) 2009 Fabien Potencier
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Interface all loaders must implement in order to provide extra functionality
+ * for the Twig core.
+ *
+ * @package    twig
+ * @author     Florin Patan <florinpatan@gmail.com>
+ */
+interface Twig_ExtendedLoaderInterface
+{
+
+    /**
+     * Check if we have the source code of a template, given its name.
+     *
+     * @param string $name The name of the template to check if we can load
+     *
+     * @return boolean If the template source code is handled by this loader or not
+     */
+    public function exists($name);
+
+}
index 8776264..dfaf701 100644 (file)
@@ -20,7 +20,7 @@
  * @package    twig
  * @author     Fabien Potencier <fabien@symfony.com>
  */
-class Twig_Loader_Array implements Twig_LoaderInterface
+class Twig_Loader_Array implements Twig_LoaderInterface, Twig_ExtendedLoaderInterface
 {
     protected $templates;
 
@@ -51,11 +51,7 @@ class Twig_Loader_Array implements Twig_LoaderInterface
     }
 
     /**
-     * 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)
     {
@@ -68,11 +64,15 @@ 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)
     {
@@ -85,10 +85,7 @@ 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)
     {
index b6b0ce9..fd767c2 100644 (file)
@@ -15,8 +15,9 @@
  * @package twig
  * @author  Fabien Potencier <fabien@symfony.com>
  */
-class Twig_Loader_Chain implements Twig_LoaderInterface
+class Twig_Loader_Chain implements Twig_LoaderInterface, Twig_ExtendedLoaderInterface
 {
+    private $hasSourceCache = array();
     protected $loaders;
 
     /**
@@ -40,19 +41,20 @@ 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_ExtendedLoaderInterface && !$loader->exists($name)) {
+                continue;
+            }
+
             try {
                 return $loader->getSource($name);
             } catch (Twig_Error_Loader $e) {
@@ -64,16 +66,43 @@ class Twig_Loader_Chain 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)
+    {
+        if (isset($this->hasSourceCache[$name])) {
+            return $this->hasSourceCache[$name];
+        }
+
+        foreach ($this->loaders as $loader) {
+            if ($loader instanceof Twig_ExtendedLoaderInterface) {
+                if ($loader->exists($name)) {
+                    return $this->hasSourceCache[$name] = true;
+                }
+            } else {
+                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_ExtendedLoaderInterface && !$loader->exists($name)) {
+                continue;
+            }
+
             try {
                 return $loader->getCacheKey($name);
             } catch (Twig_Error_Loader $e) {
@@ -85,15 +114,16 @@ class Twig_Loader_Chain 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)
     {
         $exceptions = array();
         foreach ($this->loaders as $loader) {
+            if ($loader instanceof Twig_ExtendedLoaderInterface && !$loader->exists($name)) {
+                continue;
+            }
+
             try {
                 return $loader->isFresh($name, $time);
             } catch (Twig_Error_Loader $e) {
index eb9c7cd..9e8b503 100644 (file)
@@ -15,7 +15,7 @@
  * @package    twig
  * @author     Fabien Potencier <fabien@symfony.com>
  */
-class Twig_Loader_Filesystem implements Twig_LoaderInterface
+class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExtendedLoaderInterface
 {
     protected $paths;
     protected $cache;
@@ -77,6 +77,8 @@ class Twig_Loader_Filesystem implements Twig_LoaderInterface
      *
      * @param string $path      A path where to look for templates
      * @param string $namespace A path name
+     *
+     * @throws Twig_Error_Loader
      */
     public function addPath($path, $namespace = '__main__')
     {
@@ -95,6 +97,8 @@ class Twig_Loader_Filesystem implements Twig_LoaderInterface
      *
      * @param string $path      A path where to look for templates
      * @param string $namespace A path name
+     *
+     * @throws Twig_Error_Loader
      */
     public function prependPath($path, $namespace = '__main__')
     {
@@ -115,11 +119,7 @@ class Twig_Loader_Filesystem implements Twig_LoaderInterface
     }
 
     /**
-     * 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)
     {
@@ -127,11 +127,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)
     {
@@ -139,10 +135,25 @@ 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)
+    {
+        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)
     {
index a103bce..04742cd 100644 (file)
  * @package    twig
  * @author     Fabien Potencier <fabien@symfony.com>
  */
-class Twig_Loader_String implements Twig_LoaderInterface
+class Twig_Loader_String implements Twig_LoaderInterface, Twig_ExtendedLoaderInterface
 {
     /**
-     * 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)
     {
@@ -39,6 +35,14 @@ class Twig_Loader_String implements Twig_LoaderInterface
     }
 
     /**
+     * {@inheritdoc}
+     */
+    public function exists($name)
+    {
+        return true;
+    }
+
+    /**
      * Gets the cache key to use for the cache for a given template name.
      *
      * @param string $name The name of the template to load
@@ -51,10 +55,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)
     {