shop.balmet.com

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

Filesystem.php (7226B)


      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  */
     17 class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderInterface
     18 {
     19     /** Identifier of the main namespace. */
     20     const MAIN_NAMESPACE = '__main__';
     21 
     22     protected $paths = array();
     23     protected $cache = array();
     24     protected $errorCache = array();
     25 
     26     /**
     27      * Constructor.
     28      *
     29      * @param string|array $paths A path or an array of paths where to look for templates
     30      */
     31     public function __construct($paths = array())
     32     {
     33         if ($paths) {
     34             $this->setPaths($paths);
     35         }
     36     }
     37 
     38     /**
     39      * Returns the paths to the templates.
     40      *
     41      * @param string $namespace A path namespace
     42      *
     43      * @return array The array of paths where to look for templates
     44      */
     45     public function getPaths($namespace = self::MAIN_NAMESPACE)
     46     {
     47         return isset($this->paths[$namespace]) ? $this->paths[$namespace] : array();
     48     }
     49 
     50     /**
     51      * Returns the path namespaces.
     52      *
     53      * The main namespace is always defined.
     54      *
     55      * @return array The array of defined namespaces
     56      */
     57     public function getNamespaces()
     58     {
     59         return array_keys($this->paths);
     60     }
     61 
     62     /**
     63      * Sets the paths where templates are stored.
     64      *
     65      * @param string|array $paths     A path or an array of paths where to look for templates
     66      * @param string       $namespace A path namespace
     67      */
     68     public function setPaths($paths, $namespace = self::MAIN_NAMESPACE)
     69     {
     70         if (!is_array($paths)) {
     71             $paths = array($paths);
     72         }
     73 
     74         $this->paths[$namespace] = array();
     75         foreach ($paths as $path) {
     76             $this->addPath($path, $namespace);
     77         }
     78     }
     79 
     80     /**
     81      * Adds a path where templates are stored.
     82      *
     83      * @param string $path      A path where to look for templates
     84      * @param string $namespace A path name
     85      *
     86      * @throws Twig_Error_Loader
     87      */
     88     public function addPath($path, $namespace = self::MAIN_NAMESPACE)
     89     {
     90         // invalidate the cache
     91         $this->cache = $this->errorCache = array();
     92 
     93         if (!is_dir($path)) {
     94             throw new Twig_Error_Loader(sprintf('The "%s" directory does not exist.', $path));
     95         }
     96 
     97         $this->paths[$namespace][] = rtrim($path, '/\\');
     98     }
     99 
    100     /**
    101      * Prepends a path where templates are stored.
    102      *
    103      * @param string $path      A path where to look for templates
    104      * @param string $namespace A path name
    105      *
    106      * @throws Twig_Error_Loader
    107      */
    108     public function prependPath($path, $namespace = self::MAIN_NAMESPACE)
    109     {
    110         // invalidate the cache
    111         $this->cache = $this->errorCache = array();
    112 
    113         if (!is_dir($path)) {
    114             throw new Twig_Error_Loader(sprintf('The "%s" directory does not exist.', $path));
    115         }
    116 
    117         $path = rtrim($path, '/\\');
    118 
    119         if (!isset($this->paths[$namespace])) {
    120             $this->paths[$namespace][] = $path;
    121         } else {
    122             array_unshift($this->paths[$namespace], $path);
    123         }
    124     }
    125 
    126     /**
    127      * {@inheritdoc}
    128      */
    129     public function getSource($name)
    130     {
    131         return file_get_contents($this->findTemplate($name));
    132     }
    133 
    134     /**
    135      * {@inheritdoc}
    136      */
    137     public function getCacheKey($name)
    138     {
    139         return $this->findTemplate($name);
    140     }
    141 
    142     /**
    143      * {@inheritdoc}
    144      */
    145     public function exists($name)
    146     {
    147         $name = $this->normalizeName($name);
    148 
    149         if (isset($this->cache[$name])) {
    150             return true;
    151         }
    152 
    153         try {
    154             return false !== $this->findTemplate($name, false);
    155         } catch (Twig_Error_Loader $exception) {
    156             return false;
    157         }
    158     }
    159 
    160     /**
    161      * {@inheritdoc}
    162      */
    163     public function isFresh($name, $time)
    164     {
    165         return filemtime($this->findTemplate($name)) <= $time;
    166     }
    167 
    168     protected function findTemplate($name)
    169     {
    170         $throw = func_num_args() > 1 ? func_get_arg(1) : true;
    171         $name = $this->normalizeName($name);
    172 
    173         if (isset($this->cache[$name])) {
    174             return $this->cache[$name];
    175         }
    176 
    177         if (isset($this->errorCache[$name])) {
    178             if (!$throw) {
    179                 return false;
    180             }
    181 
    182             throw new Twig_Error_Loader($this->errorCache[$name]);
    183         }
    184 
    185         $this->validateName($name);
    186 
    187         list($namespace, $shortname) = $this->parseName($name);
    188 
    189         if (!isset($this->paths[$namespace])) {
    190             $this->errorCache[$name] = sprintf('There are no registered paths for namespace "%s".', $namespace);
    191 
    192             if (!$throw) {
    193                 return false;
    194             }
    195 
    196             throw new Twig_Error_Loader($this->errorCache[$name]);
    197         }
    198 
    199         foreach ($this->paths[$namespace] as $path) {
    200             if (is_file($path.'/'.$shortname)) {
    201                 if (false !== $realpath = realpath($path.'/'.$shortname)) {
    202                     return $this->cache[$name] = $realpath;
    203                 }
    204 
    205                 return $this->cache[$name] = $path.'/'.$shortname;
    206             }
    207         }
    208 
    209         $this->errorCache[$name] = sprintf('Unable to find template "%s" (looked into: %s).', $name, implode(', ', $this->paths[$namespace]));
    210 
    211         if (!$throw) {
    212             return false;
    213         }
    214 
    215         throw new Twig_Error_Loader($this->errorCache[$name]);
    216     }
    217 
    218     protected function parseName($name, $default = self::MAIN_NAMESPACE)
    219     {
    220         if (isset($name[0]) && '@' == $name[0]) {
    221             if (false === $pos = strpos($name, '/')) {
    222                 throw new Twig_Error_Loader(sprintf('Malformed namespaced template name "%s" (expecting "@namespace/template_name").', $name));
    223             }
    224 
    225             $namespace = substr($name, 1, $pos - 1);
    226             $shortname = substr($name, $pos + 1);
    227 
    228             return array($namespace, $shortname);
    229         }
    230 
    231         return array($default, $name);
    232     }
    233 
    234     protected function normalizeName($name)
    235     {
    236         return preg_replace('#/{2,}#', '/', str_replace('\\', '/', (string) $name));
    237     }
    238 
    239     protected function validateName($name)
    240     {
    241         if (false !== strpos($name, "\0")) {
    242             throw new Twig_Error_Loader('A template name cannot contain NUL bytes.');
    243         }
    244 
    245         $name = ltrim($name, '/');
    246         $parts = explode('/', $name);
    247         $level = 0;
    248         foreach ($parts as $part) {
    249             if ('..' === $part) {
    250                 --$level;
    251             } elseif ('.' !== $part) {
    252                 ++$level;
    253             }
    254 
    255             if ($level < 0) {
    256                 throw new Twig_Error_Loader(sprintf('Looks like you try to load a template outside configured directories (%s).', $name));
    257             }
    258         }
    259     }
    260 }