| 
      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
     | 
    
       * Stores the Twig configuration.
 
     | 
  
  
    | 
      14
     | 
    
       *
 
     | 
  
  
    | 
      15
     | 
    
       * @package twig
 
     | 
  
  
    | 
      16
     | 
    
       * @author  Fabien Potencier <fabien@symfony.com>
 
     | 
  
  
    | 
      17
     | 
    
       */
 
     | 
  
  
    | 
      18
     | 
    
      class Twig_Environment
 
     | 
  
  
    | 
      19
     | 
    
      {
     | 
  
  
    | 
      20
     | 
    
          const VERSION = '1.11.1';
 
     | 
  
  
    | 
      21
     | 
    
      
 
     | 
  
  
    | 
      22
     | 
    
          protected $charset;
 
     | 
  
  
    | 
      23
     | 
    
          protected $loader;
 
     | 
  
  
    | 
      24
     | 
    
          protected $debug;
 
     | 
  
  
    | 
      25
     | 
    
          protected $autoReload;
 
     | 
  
  
    | 
      26
     | 
    
          protected $cache;
 
     | 
  
  
    | 
      27
     | 
    
          protected $lexer;
 
     | 
  
  
    | 
      28
     | 
    
          protected $parser;
 
     | 
  
  
    | 
      29
     | 
    
          protected $compiler;
 
     | 
  
  
    | 
      30
     | 
    
          protected $baseTemplateClass;
 
     | 
  
  
    | 
      31
     | 
    
          protected $extensions;
 
     | 
  
  
    | 
      32
     | 
    
          protected $parsers;
 
     | 
  
  
    | 
      33
     | 
    
          protected $visitors;
 
     | 
  
  
    | 
      34
     | 
    
          protected $filters;
 
     | 
  
  
    | 
      35
     | 
    
          protected $tests;
 
     | 
  
  
    | 
      36
     | 
    
          protected $functions;
 
     | 
  
  
    | 
      37
     | 
    
          protected $globals;
 
     | 
  
  
    | 
      38
     | 
    
          protected $runtimeInitialized;
 
     | 
  
  
    | 
      39
     | 
    
          protected $loadedTemplates;
 
     | 
  
  
    | 
      40
     | 
    
          protected $strictVariables;
 
     | 
  
  
    | 
      41
     | 
    
          protected $unaryOperators;
 
     | 
  
  
    | 
      42
     | 
    
          protected $binaryOperators;
 
     | 
  
  
    | 
      43
     | 
    
          protected $templateClassPrefix = '__TwigTemplate_';
 
     | 
  
  
    | 
      44
     | 
    
          protected $functionCallbacks;
 
     | 
  
  
    | 
      45
     | 
    
          protected $filterCallbacks;
 
     | 
  
  
    | 
      46
     | 
    
          protected $staging;
 
     | 
  
  
    | 
      47
     | 
    
      
 
     | 
  
  
    | 
      48
     | 
    
          /**
 
     | 
  
  
    | 
      49
     | 
    
           * Constructor.
 
     | 
  
  
    | 
      50
     | 
    
           *
 
     | 
  
  
    | 
      51
     | 
    
           * Available options:
 
     | 
  
  
    | 
      52
     | 
    
           *
 
     | 
  
  
    | 
      53
     | 
    
           *  * debug: When set to true, it automatically set "auto_reload" to true as
 
     | 
  
  
    | 
      54
     | 
    
           *           well (default to false).
 
     | 
  
  
    | 
      55
     | 
    
           *
 
     | 
  
  
    | 
      56
     | 
    
           *  * charset: The charset used by the templates (default to utf-8).
 
     | 
  
  
    | 
      57
     | 
    
           *
 
     | 
  
  
    | 
      58
     | 
    
           *  * base_template_class: The base template class to use for generated
 
     | 
  
  
    | 
      59
     | 
    
           *                         templates (default to Twig_Template).
 
     | 
  
  
    | 
      60
     | 
    
           *
 
     | 
  
  
    | 
      61
     | 
    
           *  * cache: An absolute path where to store the compiled templates, or
 
     | 
  
  
    | 
      62
     | 
    
           *           false to disable compilation cache (default).
 
     | 
  
  
    | 
      63
     | 
    
           *
 
     | 
  
  
    | 
      64
     | 
    
           *  * auto_reload: Whether to reload the template is the original source changed.
 
     | 
  
  
    | 
      65
     | 
    
           *                 If you don't provide the auto_reload option, it will be
 
     | 
  
  
    | 
      66
     | 
    
           *                 determined automatically base on the debug value.
 
     | 
  
  
    | 
      67
     | 
    
           *
 
     | 
  
  
    | 
      68
     | 
    
           *  * strict_variables: Whether to ignore invalid variables in templates
 
     | 
  
  
    | 
      69
     | 
    
           *                      (default to false).
 
     | 
  
  
    | 
      70
     | 
    
           *
 
     | 
  
  
    | 
      71
     | 
    
           *  * autoescape: Whether to enable auto-escaping (default to html):
 
     | 
  
  
    | 
      72
     | 
    
           *                  * false: disable auto-escaping
 
     | 
  
  
    | 
      73
     | 
    
           *                  * true: equivalent to html
 
     | 
  
  
    | 
      74
     | 
    
           *                  * html, js: set the autoescaping to one of the supported strategies
 
     | 
  
  
    | 
      75
     | 
    
           *                  * PHP callback: a PHP callback that returns an escaping strategy based on the template "filename"
 
     | 
  
  
    | 
      76
     | 
    
           *
 
     | 
  
  
    | 
      77
     | 
    
           *  * optimizations: A flag that indicates which optimizations to apply
 
     | 
  
  
    | 
      78
     | 
    
           *                   (default to -1 which means that all optimizations are enabled;
 
     | 
  
  
    | 
      79
     | 
    
           *                   set it to 0 to disable).
 
     | 
  
  
    | 
      80
     | 
    
           *
 
     | 
  
  
    | 
      81
     | 
    
           * @param Twig_LoaderInterface $loader  A Twig_LoaderInterface instance
 
     | 
  
  
    | 
      82
     | 
    
           * @param array                $options An array of options
 
     | 
  
  
    | 
      83
     | 
    
           */
 
     | 
  
  
    | 
      84
     | 
    
          public function __construct(Twig_LoaderInterface $loader = null, $options = array())
 
     | 
  
  
    | 
      85
     | 
    
          {
     | 
  
  
    | 
      86
     | 
    
              if (null !== $loader) {
     | 
  
  
    | 
      87
     | 
    
                  $this->setLoader($loader);
 
     | 
  
  
    | 
      88
     | 
    
              }
 
     | 
  
  
    | 
      89
     | 
    
      
 
     | 
  
  
    | 
      90
     | 
    
              $options = array_merge(array(
 
     | 
  
  
    | 
      91
     | 
    
                  'debug'               => false,
 
     | 
  
  
    | 
      92
     | 
    
                  'charset'             => 'UTF-8',
 
     | 
  
  
    | 
      93
     | 
    
                  'base_template_class' => 'Twig_Template',
 
     | 
  
  
    | 
      94
     | 
    
                  'strict_variables'    => false,
 
     | 
  
  
    | 
      95
     | 
    
                  'autoescape'          => 'html',
 
     | 
  
  
    | 
      96
     | 
    
                  'cache'               => false,
 
     | 
  
  
    | 
      97
     | 
    
                  'auto_reload'         => null,
 
     | 
  
  
    | 
      98
     | 
    
                  'optimizations'       => -1,
 
     | 
  
  
    | 
      99
     | 
    
              ), $options);
 
     | 
  
  
    | 
      100
     | 
    
      
 
     | 
  
  
    | 
      101
     | 
    
              $this->debug              = (bool) $options['debug'];
 
     | 
  
  
    | 
      102
     | 
    
              $this->charset            = $options['charset'];
 
     | 
  
  
    | 
      103
     | 
    
              $this->baseTemplateClass  = $options['base_template_class'];
 
     | 
  
  
    | 
      104
     | 
    
              $this->autoReload         = null === $options['auto_reload'] ? $this->debug : (bool) $options['auto_reload'];
 
     | 
  
  
    | 
      105
     | 
    
              $this->extensions         = array(
 
     | 
  
  
    | 
      106
     | 
    
                  'core'      => new Twig_Extension_Core(),
 
     | 
  
  
    | 
      107
     | 
    
                  'escaper'   => new Twig_Extension_Escaper($options['autoescape']),
 
     | 
  
  
    | 
      108
     | 
    
                  'optimizer' => new Twig_Extension_Optimizer($options['optimizations']),
 
     | 
  
  
    | 
      109
     | 
    
              );
 
     | 
  
  
    | 
      110
     | 
    
              $this->strictVariables    = (bool) $options['strict_variables'];
 
     | 
  
  
    | 
      111
     | 
    
              $this->runtimeInitialized = false;
 
     | 
  
  
    | 
      112
     | 
    
              $this->setCache($options['cache']);
 
     | 
  
  
    | 
      113
     | 
    
              $this->functionCallbacks = array();
 
     | 
  
  
    | 
      114
     | 
    
              $this->filterCallbacks = array();
 
     | 
  
  
    | 
      115
     | 
    
              $this->staging = array(
 
     | 
  
  
    | 
      116
     | 
    
                  'functions'     => array(),
 
     | 
  
  
    | 
      117
     | 
    
                  'filters'       => array(),
 
     | 
  
  
    | 
      118
     | 
    
                  'tests'         => array(),
 
     | 
  
  
    | 
      119
     | 
    
                  'token_parsers' => array(),
 
     | 
  
  
    | 
      120
     | 
    
                  'visitors'      => array(),
 
     | 
  
  
    | 
      121
     | 
    
                  'globals'       => array(),
 
     | 
  
  
    | 
      122
     | 
    
              );
 
     | 
  
  
    | 
      123
     | 
    
          }
 
     | 
  
  
    | 
      124
     | 
    
      
 
     | 
  
  
    | 
      125
     | 
    
          /**
 
     | 
  
  
    | 
      126
     | 
    
           * Gets the base template class for compiled templates.
 
     | 
  
  
    | 
      127
     | 
    
           *
 
     | 
  
  
    | 
      128
     | 
    
           * @return string The base template class name
 
     | 
  
  
    | 
      129
     | 
    
           */
 
     | 
  
  
    | 
      130
     | 
    
          public function getBaseTemplateClass()
 
     | 
  
  
    | 
      131
     | 
    
          {
     | 
  
  
    | 
      132
     | 
    
              return $this->baseTemplateClass;
 
     | 
  
  
    | 
      133
     | 
    
          }
 
     | 
  
  
    | 
      134
     | 
    
      
 
     | 
  
  
    | 
      135
     | 
    
          /**
 
     | 
  
  
    | 
      136
     | 
    
           * Sets the base template class for compiled templates.
 
     | 
  
  
    | 
      137
     | 
    
           *
 
     | 
  
  
    | 
      138
     | 
    
           * @param string $class The base template class name
 
     | 
  
  
    | 
      139
     | 
    
           */
 
     | 
  
  
    | 
      140
     | 
    
          public function setBaseTemplateClass($class)
 
     | 
  
  
    | 
      141
     | 
    
          {
     | 
  
  
    | 
      142
     | 
    
              $this->baseTemplateClass = $class;
 
     | 
  
  
    | 
      143
     | 
    
          }
 
     | 
  
  
    | 
      144
     | 
    
      
 
     | 
  
  
    | 
      145
     | 
    
          /**
 
     | 
  
  
    | 
      146
     | 
    
           * Enables debugging mode.
 
     | 
  
  
    | 
      147
     | 
    
           */
 
     | 
  
  
    | 
      148
     | 
    
          public function enableDebug()
 
     | 
  
  
    | 
      149
     | 
    
          {
     | 
  
  
    | 
      150
     | 
    
              $this->debug = true;
 
     | 
  
  
    | 
      151
     | 
    
          }
 
     | 
  
  
    | 
      152
     | 
    
      
 
     | 
  
  
    | 
      153
     | 
    
          /**
 
     | 
  
  
    | 
      154
     | 
    
           * Disables debugging mode.
 
     | 
  
  
    | 
      155
     | 
    
           */
 
     | 
  
  
    | 
      156
     | 
    
          public function disableDebug()
 
     | 
  
  
    | 
      157
     | 
    
          {
     | 
  
  
    | 
      158
     | 
    
              $this->debug = false;
 
     | 
  
  
    | 
      159
     | 
    
          }
 
     | 
  
  
    | 
      160
     | 
    
      
 
     | 
  
  
    | 
      161
     | 
    
          /**
 
     | 
  
  
    | 
      162
     | 
    
           * Checks if debug mode is enabled.
 
     | 
  
  
    | 
      163
     | 
    
           *
 
     | 
  
  
    | 
      164
     | 
    
           * @return Boolean true if debug mode is enabled, false otherwise
 
     | 
  
  
    | 
      165
     | 
    
           */
 
     | 
  
  
    | 
      166
     | 
    
          public function isDebug()
 
     | 
  
  
    | 
      167
     | 
    
          {
     | 
  
  
    | 
      168
     | 
    
              return $this->debug;
 
     | 
  
  
    | 
      169
     | 
    
          }
 
     | 
  
  
    | 
      170
     | 
    
      
 
     | 
  
  
    | 
      171
     | 
    
          /**
 
     | 
  
  
    | 
      172
     | 
    
           * Enables the auto_reload option.
 
     | 
  
  
    | 
      173
     | 
    
           */
 
     | 
  
  
    | 
      174
     | 
    
          public function enableAutoReload()
 
     | 
  
  
    | 
      175
     | 
    
          {
     | 
  
  
    | 
      176
     | 
    
              $this->autoReload = true;
 
     | 
  
  
    | 
      177
     | 
    
          }
 
     | 
  
  
    | 
      178
     | 
    
      
 
     | 
  
  
    | 
      179
     | 
    
          /**
 
     | 
  
  
    | 
      180
     | 
    
           * Disables the auto_reload option.
 
     | 
  
  
    | 
      181
     | 
    
           */
 
     | 
  
  
    | 
      182
     | 
    
          public function disableAutoReload()
 
     | 
  
  
    | 
      183
     | 
    
          {
     | 
  
  
    | 
      184
     | 
    
              $this->autoReload = false;
 
     | 
  
  
    | 
      185
     | 
    
          }
 
     | 
  
  
    | 
      186
     | 
    
      
 
     | 
  
  
    | 
      187
     | 
    
          /**
 
     | 
  
  
    | 
      188
     | 
    
           * Checks if the auto_reload option is enabled.
 
     | 
  
  
    | 
      189
     | 
    
           *
 
     | 
  
  
    | 
      190
     | 
    
           * @return Boolean true if auto_reload is enabled, false otherwise
 
     | 
  
  
    | 
      191
     | 
    
           */
 
     | 
  
  
    | 
      192
     | 
    
          public function isAutoReload()
 
     | 
  
  
    | 
      193
     | 
    
          {
     | 
  
  
    | 
      194
     | 
    
              return $this->autoReload;
 
     | 
  
  
    | 
      195
     | 
    
          }
 
     | 
  
  
    | 
      196
     | 
    
      
 
     | 
  
  
    | 
      197
     | 
    
          /**
 
     | 
  
  
    | 
      198
     | 
    
           * Enables the strict_variables option.
 
     | 
  
  
    | 
      199
     | 
    
           */
 
     | 
  
  
    | 
      200
     | 
    
          public function enableStrictVariables()
 
     | 
  
  
    | 
      201
     | 
    
          {
     | 
  
  
    | 
      202
     | 
    
              $this->strictVariables = true;
 
     | 
  
  
    | 
      203
     | 
    
          }
 
     | 
  
  
    | 
      204
     | 
    
      
 
     | 
  
  
    | 
      205
     | 
    
          /**
 
     | 
  
  
    | 
      206
     | 
    
           * Disables the strict_variables option.
 
     | 
  
  
    | 
      207
     | 
    
           */
 
     | 
  
  
    | 
      208
     | 
    
          public function disableStrictVariables()
 
     | 
  
  
    | 
      209
     | 
    
          {
     | 
  
  
    | 
      210
     | 
    
              $this->strictVariables = false;
 
     | 
  
  
    | 
      211
     | 
    
          }
 
     | 
  
  
    | 
      212
     | 
    
      
 
     | 
  
  
    | 
      213
     | 
    
          /**
 
     | 
  
  
    | 
      214
     | 
    
           * Checks if the strict_variables option is enabled.
 
     | 
  
  
    | 
      215
     | 
    
           *
 
     | 
  
  
    | 
      216
     | 
    
           * @return Boolean true if strict_variables is enabled, false otherwise
 
     | 
  
  
    | 
      217
     | 
    
           */
 
     | 
  
  
    | 
      218
     | 
    
          public function isStrictVariables()
 
     | 
  
  
    | 
      219
     | 
    
          {
     | 
  
  
    | 
      220
     | 
    
              return $this->strictVariables;
 
     | 
  
  
    | 
      221
     | 
    
          }
 
     | 
  
  
    | 
      222
     | 
    
      
 
     | 
  
  
    | 
      223
     | 
    
          /**
 
     | 
  
  
    | 
      224
     | 
    
           * Gets the cache directory or false if cache is disabled.
 
     | 
  
  
    | 
      225
     | 
    
           *
 
     | 
  
  
    | 
      226
     | 
    
           * @return string|false
 
     | 
  
  
    | 
      227
     | 
    
           */
 
     | 
  
  
    | 
      228
     | 
    
          public function getCache()
 
     | 
  
  
    | 
      229
     | 
    
          {
     | 
  
  
    | 
      230
     | 
    
              return $this->cache;
 
     | 
  
  
    | 
      231
     | 
    
          }
 
     | 
  
  
    | 
      232
     | 
    
      
 
     | 
  
  
    | 
      233
     | 
    
           /**
 
     | 
  
  
    | 
      234
     | 
    
            * Sets the cache directory or false if cache is disabled.
 
     | 
  
  
    | 
      235
     | 
    
            *
 
     | 
  
  
    | 
      236
     | 
    
            * @param string|false $cache The absolute path to the compiled templates,
 
     | 
  
  
    | 
      237
     | 
    
            *                            or false to disable cache
 
     | 
  
  
    | 
      238
     | 
    
            */
 
     | 
  
  
    | 
      239
     | 
    
          public function setCache($cache)
 
     | 
  
  
    | 
      240
     | 
    
          {
     | 
  
  
    | 
      241
     | 
    
              $this->cache = $cache ? $cache : false;
 
     | 
  
  
    | 
      242
     | 
    
          }
 
     | 
  
  
    | 
      243
     | 
    
      
 
     | 
  
  
    | 
      244
     | 
    
          /**
 
     | 
  
  
    | 
      245
     | 
    
           * Gets the cache filename for a given template.
 
     | 
  
  
    | 
      246
     | 
    
           *
 
     | 
  
  
    | 
      247
     | 
    
           * @param string $name The template name
 
     | 
  
  
    | 
      248
     | 
    
           *
 
     | 
  
  
    | 
      249
     | 
    
           * @return string The cache file name
 
     | 
  
  
    | 
      250
     | 
    
           */
 
     | 
  
  
    | 
      251
     | 
    
          public function getCacheFilename($name)
 
     | 
  
  
    | 
      252
     | 
    
          {
     | 
  
  
    | 
      253
     | 
    
              if (false === $this->cache) {
     | 
  
  
    | 
      254
     | 
    
                  return false;
 
     | 
  
  
    | 
      255
     | 
    
              }
 
     | 
  
  
    | 
      256
     | 
    
      
 
     | 
  
  
    | 
      257
     | 
    
              $class = substr($this->getTemplateClass($name), strlen($this->templateClassPrefix));
 
     | 
  
  
    | 
      258
     | 
    
      
 
     | 
  
  
    | 
      259
     | 
    
              return $this->getCache().'/'.substr($class, 0, 2).'/'.substr($class, 2, 2).'/'.substr($class, 4).'.php';
 
     | 
  
  
    | 
      260
     | 
    
          }
 
     | 
  
  
    | 
      261
     | 
    
      
 
     | 
  
  
    | 
      262
     | 
    
          /**
 
     | 
  
  
    | 
      263
     | 
    
           * Gets the template class associated with the given string.
 
     | 
  
  
    | 
      264
     | 
    
           *
 
     | 
  
  
    | 
      265
     | 
    
           * @param string  $name  The name for which to calculate the template class name
 
     | 
  
  
    | 
      266
     | 
    
           * @param integer $index The index if it is an embedded template
 
     | 
  
  
    | 
      267
     | 
    
           *
 
     | 
  
  
    | 
      268
     | 
    
           * @return string The template class name
 
     | 
  
  
    | 
      269
     | 
    
           */
 
     | 
  
  
    | 
      270
     | 
    
          public function getTemplateClass($name, $index = null)
 
     | 
  
  
    | 
      271
     | 
    
          {
     | 
  
  
    | 
      272
     | 
    
              return $this->templateClassPrefix.md5($this->loader->getCacheKey($name)).(null === $index ? '' : '_'.$index);
 
     | 
  
  
    | 
      273
     | 
    
          }
 
     | 
  
  
    | 
      274
     | 
    
      
 
     | 
  
  
    | 
      275
     | 
    
          /**
 
     | 
  
  
    | 
      276
     | 
    
           * Gets the template class prefix.
 
     | 
  
  
    | 
      277
     | 
    
           *
 
     | 
  
  
    | 
      278
     | 
    
           * @return string The template class prefix
 
     | 
  
  
    | 
      279
     | 
    
           */
 
     | 
  
  
    | 
      280
     | 
    
          public function getTemplateClassPrefix()
 
     | 
  
  
    | 
      281
     | 
    
          {
     | 
  
  
    | 
      282
     | 
    
              return $this->templateClassPrefix;
 
     | 
  
  
    | 
      283
     | 
    
          }
 
     | 
  
  
    | 
      284
     | 
    
      
 
     | 
  
  
    | 
      285
     | 
    
          /**
 
     | 
  
  
    | 
      286
     | 
    
           * Renders a template.
 
     | 
  
  
    | 
      287
     | 
    
           *
 
     | 
  
  
    | 
      288
     | 
    
           * @param string $name    The template name
 
     | 
  
  
    | 
      289
     | 
    
           * @param array  $context An array of parameters to pass to the template
 
     | 
  
  
    | 
      290
     | 
    
           *
 
     | 
  
  
    | 
      291
     | 
    
           * @return string The rendered template
 
     | 
  
  
    | 
      292
     | 
    
           */
 
     | 
  
  
    | 
      293
     | 
    
          public function render($name, array $context = array())
 
     | 
  
  
    | 
      294
     | 
    
          {
     | 
  
  
    | 
      295
     | 
    
              return $this->loadTemplate($name)->render($context);
 
     | 
  
  
    | 
      296
     | 
    
          }
 
     | 
  
  
    | 
      297
     | 
    
      
 
     | 
  
  
    | 
      298
     | 
    
          /**
 
     | 
  
  
    | 
      299
     | 
    
           * Displays a template.
 
     | 
  
  
    | 
      300
     | 
    
           *
 
     | 
  
  
    | 
      301
     | 
    
           * @param string $name    The template name
 
     | 
  
  
    | 
      302
     | 
    
           * @param array  $context An array of parameters to pass to the template
 
     | 
  
  
    | 
      303
     | 
    
           */
 
     | 
  
  
    | 
      304
     | 
    
          public function display($name, array $context = array())
 
     | 
  
  
    | 
      305
     | 
    
          {
     | 
  
  
    | 
      306
     | 
    
              $this->loadTemplate($name)->display($context);
 
     | 
  
  
    | 
      307
     | 
    
          }
 
     | 
  
  
    | 
      308
     | 
    
      
 
     | 
  
  
    | 
      309
     | 
    
          /**
 
     | 
  
  
    | 
      310
     | 
    
           * Loads a template by name.
 
     | 
  
  
    | 
      311
     | 
    
           *
 
     | 
  
  
    | 
      312
     | 
    
           * @param string  $name  The template name
 
     | 
  
  
    | 
      313
     | 
    
           * @param integer $index The index if it is an embedded template
 
     | 
  
  
    | 
      314
     | 
    
           *
 
     | 
  
  
    | 
      315
     | 
    
           * @return Twig_TemplateInterface A template instance representing the given template name
 
     | 
  
  
    | 
      316
     | 
    
           */
 
     | 
  
  
    | 
      317
     | 
    
          public function loadTemplate($name, $index = null)
 
     | 
  
  
    | 
      318
     | 
    
          {
     | 
  
  
    | 
      319
     | 
    
              $cls = $this->getTemplateClass($name, $index);
 
     | 
  
  
    | 
      320
     | 
    
      
 
     | 
  
  
    | 
      321
     | 
    
              if (isset($this->loadedTemplates[$cls])) {
     | 
  
  
    | 
      322
     | 
    
                  return $this->loadedTemplates[$cls];
 
     | 
  
  
    | 
      323
     | 
    
              }
 
     | 
  
  
    | 
      324
     | 
    
      
 
     | 
  
  
    | 
      325
     | 
    
              if (!class_exists($cls, false)) {
     | 
  
  
    | 
      326
     | 
    
                  if (false === $cache = $this->getCacheFilename($name)) {
     | 
  
  
    | 
      327
     | 
    
                      eval('?>'.$this->compileSource($this->loader->getSource($name), $name));
     | 
  
  
    | 
      328
     | 
    
                  } else {
     | 
  
  
    | 
      329
     | 
    
                      if (!is_file($cache) || ($this->isAutoReload() && !$this->isTemplateFresh($name, filemtime($cache)))) {
     | 
  
  
    | 
      330
     | 
    
                          $this->writeCacheFile($cache, $this->compileSource($this->loader->getSource($name), $name));
 
     | 
  
  
    | 
      331
     | 
    
                      }
 
     | 
  
  
    | 
      332
     | 
    
      
 
     | 
  
  
    | 
      333
     | 
    
                      require_once $cache;
 
     | 
  
  
    | 
      334
     | 
    
                  }
 
     | 
  
  
    | 
      335
     | 
    
              }
 
     | 
  
  
    | 
      336
     | 
    
      
 
     | 
  
  
    | 
      337
     | 
    
              if (!$this->runtimeInitialized) {
     | 
  
  
    | 
      338
     | 
    
                  $this->initRuntime();
 
     | 
  
  
    | 
      339
     | 
    
              }
 
     | 
  
  
    | 
      340
     | 
    
      
 
     | 
  
  
    | 
      341
     | 
    
              return $this->loadedTemplates[$cls] = new $cls($this);
 
     | 
  
  
    | 
      342
     | 
    
          }
 
     | 
  
  
    | 
      343
     | 
    
      
 
     | 
  
  
    | 
      344
     | 
    
          /**
 
     | 
  
  
    | 
      345
     | 
    
           * Returns true if the template is still fresh.
 
     | 
  
  
    | 
      346
     | 
    
           *
 
     | 
  
  
    | 
      347
     | 
    
           * Besides checking the loader for freshness information,
 
     | 
  
  
    | 
      348
     | 
    
           * this method also checks if the enabled extensions have
 
     | 
  
  
    | 
      349
     | 
    
           * not changed.
 
     | 
  
  
    | 
      350
     | 
    
           *
 
     | 
  
  
    | 
      351
     | 
    
           * @param string    $name The template name
 
     | 
  
  
    | 
      352
     | 
    
           * @param timestamp $time The last modification time of the cached template
 
     | 
  
  
    | 
      353
     | 
    
           *
 
     | 
  
  
    | 
      354
     | 
    
           * @return Boolean true if the template is fresh, false otherwise
 
     | 
  
  
    | 
      355
     | 
    
           */
 
     | 
  
  
    | 
      356
     | 
    
          public function isTemplateFresh($name, $time)
 
     | 
  
  
    | 
      357
     | 
    
          {
     | 
  
  
    | 
      358
     | 
    
              foreach ($this->extensions as $extension) {
     | 
  
  
    | 
      359
     | 
    
                  $r = new ReflectionObject($extension);
 
     | 
  
  
    | 
      360
     | 
    
                  if (filemtime($r->getFileName()) > $time) {
     | 
  
  
    | 
      361
     | 
    
                      return false;
 
     | 
  
  
    | 
      362
     | 
    
                  }
 
     | 
  
  
    | 
      363
     | 
    
              }
 
     | 
  
  
    | 
      364
     | 
    
      
 
     | 
  
  
    | 
      365
     | 
    
              return $this->loader->isFresh($name, $time);
 
     | 
  
  
    | 
      366
     | 
    
          }
 
     | 
  
  
    | 
      367
     | 
    
      
 
     | 
  
  
    | 
      368
     | 
    
          public function resolveTemplate($names)
 
     | 
  
  
    | 
      369
     | 
    
          {
     | 
  
  
    | 
      370
     | 
    
              if (!is_array($names)) {
     | 
  
  
    | 
      371
     | 
    
                  $names = array($names);
 
     | 
  
  
    | 
      372
     | 
    
              }
 
     | 
  
  
    | 
      373
     | 
    
      
 
     | 
  
  
    | 
      374
     | 
    
              foreach ($names as $name) {
     | 
  
  
    | 
      375
     | 
    
                  if ($name instanceof Twig_Template) {
     | 
  
  
    | 
      376
     | 
    
                      return $name;
 
     | 
  
  
    | 
      377
     | 
    
                  }
 
     | 
  
  
    | 
      378
     | 
    
      
 
     | 
  
  
    | 
      379
     | 
    
                  try {
     | 
  
  
    | 
      380
     | 
    
                      return $this->loadTemplate($name);
 
     | 
  
  
    | 
      381
     | 
    
                  } catch (Twig_Error_Loader $e) {
     | 
  
  
    | 
      382
     | 
    
                  }
 
     | 
  
  
    | 
      383
     | 
    
              }
 
     | 
  
  
    | 
      384
     | 
    
      
 
     | 
  
  
    | 
      385
     | 
    
              if (1 === count($names)) {
     | 
  
  
    | 
      386
     | 
    
                  throw $e;
 
     | 
  
  
    | 
      387
     | 
    
              }
 
     | 
  
  
    | 
      388
     | 
    
      
 
     | 
  
  
    | 
      389
     | 
    
              throw new Twig_Error_Loader(sprintf('Unable to find one of the following templates: "%s".', implode('", "', $names)));
     | 
  
  
    | 
      390
     | 
    
          }
 
     | 
  
  
    | 
      391
     | 
    
      
 
     | 
  
  
    | 
      392
     | 
    
          /**
 
     | 
  
  
    | 
      393
     | 
    
           * Clears the internal template cache.
 
     | 
  
  
    | 
      394
     | 
    
           */
 
     | 
  
  
    | 
      395
     | 
    
          public function clearTemplateCache()
 
     | 
  
  
    | 
      396
     | 
    
          {
     | 
  
  
    | 
      397
     | 
    
              $this->loadedTemplates = array();
 
     | 
  
  
    | 
      398
     | 
    
          }
 
     | 
  
  
    | 
      399
     | 
    
      
 
     | 
  
  
    | 
      400
     | 
    
          /**
 
     | 
  
  
    | 
      401
     | 
    
           * Clears the template cache files on the filesystem.
 
     | 
  
  
    | 
      402
     | 
    
           */
 
     | 
  
  
    | 
      403
     | 
    
          public function clearCacheFiles()
 
     | 
  
  
    | 
      404
     | 
    
          {
     | 
  
  
    | 
      405
     | 
    
              if (false === $this->cache) {
     | 
  
  
    | 
      406
     | 
    
                  return;
 
     | 
  
  
    | 
      407
     | 
    
              }
 
     | 
  
  
    | 
      408
     | 
    
      
 
     | 
  
  
    | 
      409
     | 
    
              foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($this->cache), RecursiveIteratorIterator::LEAVES_ONLY) as $file) {
     | 
  
  
    | 
      410
     | 
    
                  if ($file->isFile()) {
     | 
  
  
    | 
      411
     | 
    
                      @unlink($file->getPathname());
 
     | 
  
  
    | 
      412
     | 
    
                  }
 
     | 
  
  
    | 
      413
     | 
    
              }
 
     | 
  
  
    | 
      414
     | 
    
          }
 
     | 
  
  
    | 
      415
     | 
    
      
 
     | 
  
  
    | 
      416
     | 
    
          /**
 
     | 
  
  
    | 
      417
     | 
    
           * Gets the Lexer instance.
 
     | 
  
  
    | 
      418
     | 
    
           *
 
     | 
  
  
    | 
      419
     | 
    
           * @return Twig_LexerInterface A Twig_LexerInterface instance
 
     | 
  
  
    | 
      420
     | 
    
           */
 
     | 
  
  
    | 
      421
     | 
    
          public function getLexer()
 
     | 
  
  
    | 
      422
     | 
    
          {
     | 
  
  
    | 
      423
     | 
    
              if (null === $this->lexer) {
     | 
  
  
    | 
      424
     | 
    
                  $this->lexer = new Twig_Lexer($this);
 
     | 
  
  
    | 
      425
     | 
    
              }
 
     | 
  
  
    | 
      426
     | 
    
      
 
     | 
  
  
    | 
      427
     | 
    
              return $this->lexer;
 
     | 
  
  
    | 
      428
     | 
    
          }
 
     | 
  
  
    | 
      429
     | 
    
      
 
     | 
  
  
    | 
      430
     | 
    
          /**
 
     | 
  
  
    | 
      431
     | 
    
           * Sets the Lexer instance.
 
     | 
  
  
    | 
      432
     | 
    
           *
 
     | 
  
  
    | 
      433
     | 
    
           * @param Twig_LexerInterface A Twig_LexerInterface instance
 
     | 
  
  
    | 
      434
     | 
    
           */
 
     | 
  
  
    | 
      435
     | 
    
          public function setLexer(Twig_LexerInterface $lexer)
 
     | 
  
  
    | 
      436
     | 
    
          {
     | 
  
  
    | 
      437
     | 
    
              $this->lexer = $lexer;
 
     | 
  
  
    | 
      438
     | 
    
          }
 
     | 
  
  
    | 
      439
     | 
    
      
 
     | 
  
  
    | 
      440
     | 
    
          /**
 
     | 
  
  
    | 
      441
     | 
    
           * Tokenizes a source code.
 
     | 
  
  
    | 
      442
     | 
    
           *
 
     | 
  
  
    | 
      443
     | 
    
           * @param string $source The template source code
 
     | 
  
  
    | 
      444
     | 
    
           * @param string $name   The template name
 
     | 
  
  
    | 
      445
     | 
    
           *
 
     | 
  
  
    | 
      446
     | 
    
           * @return Twig_TokenStream A Twig_TokenStream instance
 
     | 
  
  
    | 
      447
     | 
    
           */
 
     | 
  
  
    | 
      448
     | 
    
          public function tokenize($source, $name = null)
 
     | 
  
  
    | 
      449
     | 
    
          {
     | 
  
  
    | 
      450
     | 
    
              return $this->getLexer()->tokenize($source, $name);
 
     | 
  
  
    | 
      451
     | 
    
          }
 
     | 
  
  
    | 
      452
     | 
    
      
 
     | 
  
  
    | 
      453
     | 
    
          /**
 
     | 
  
  
    | 
      454
     | 
    
           * Gets the Parser instance.
 
     | 
  
  
    | 
      455
     | 
    
           *
 
     | 
  
  
    | 
      456
     | 
    
           * @return Twig_ParserInterface A Twig_ParserInterface instance
 
     | 
  
  
    | 
      457
     | 
    
           */
 
     | 
  
  
    | 
      458
     | 
    
          public function getParser()
 
     | 
  
  
    | 
      459
     | 
    
          {
     | 
  
  
    | 
      460
     | 
    
              if (null === $this->parser) {
     | 
  
  
    | 
      461
     | 
    
                  $this->parser = new Twig_Parser($this);
 
     | 
  
  
    | 
      462
     | 
    
              }
 
     | 
  
  
    | 
      463
     | 
    
      
 
     | 
  
  
    | 
      464
     | 
    
              return $this->parser;
 
     | 
  
  
    | 
      465
     | 
    
          }
 
     | 
  
  
    | 
      466
     | 
    
      
 
     | 
  
  
    | 
      467
     | 
    
          /**
 
     | 
  
  
    | 
      468
     | 
    
           * Sets the Parser instance.
 
     | 
  
  
    | 
      469
     | 
    
           *
 
     | 
  
  
    | 
      470
     | 
    
           * @param Twig_ParserInterface A Twig_ParserInterface instance
 
     | 
  
  
    | 
      471
     | 
    
           */
 
     | 
  
  
    | 
      472
     | 
    
          public function setParser(Twig_ParserInterface $parser)
 
     | 
  
  
    | 
      473
     | 
    
          {
     | 
  
  
    | 
      474
     | 
    
              $this->parser = $parser;
 
     | 
  
  
    | 
      475
     | 
    
          }
 
     | 
  
  
    | 
      476
     | 
    
      
 
     | 
  
  
    | 
      477
     | 
    
          /**
 
     | 
  
  
    | 
      478
     | 
    
           * Parses a token stream.
 
     | 
  
  
    | 
      479
     | 
    
           *
 
     | 
  
  
    | 
      480
     | 
    
           * @param Twig_TokenStream $tokens A Twig_TokenStream instance
 
     | 
  
  
    | 
      481
     | 
    
           *
 
     | 
  
  
    | 
      482
     | 
    
           * @return Twig_Node_Module A Node tree
 
     | 
  
  
    | 
      483
     | 
    
           */
 
     | 
  
  
    | 
      484
     | 
    
          public function parse(Twig_TokenStream $tokens)
 
     | 
  
  
    | 
      485
     | 
    
          {
     | 
  
  
    | 
      486
     | 
    
              return $this->getParser()->parse($tokens);
 
     | 
  
  
    | 
      487
     | 
    
          }
 
     | 
  
  
    | 
      488
     | 
    
      
 
     | 
  
  
    | 
      489
     | 
    
          /**
 
     | 
  
  
    | 
      490
     | 
    
           * Gets the Compiler instance.
 
     | 
  
  
    | 
      491
     | 
    
           *
 
     | 
  
  
    | 
      492
     | 
    
           * @return Twig_CompilerInterface A Twig_CompilerInterface instance
 
     | 
  
  
    | 
      493
     | 
    
           */
 
     | 
  
  
    | 
      494
     | 
    
          public function getCompiler()
 
     | 
  
  
    | 
      495
     | 
    
          {
     | 
  
  
    | 
      496
     | 
    
              if (null === $this->compiler) {
     | 
  
  
    | 
      497
     | 
    
                  $this->compiler = new Twig_Compiler($this);
 
     | 
  
  
    | 
      498
     | 
    
              }
 
     | 
  
  
    | 
      499
     | 
    
      
 
     | 
  
  
    | 
      500
     | 
    
              return $this->compiler;
 
     | 
  
  
    | 
      501
     | 
    
          }
 
     | 
  
  
    | 
      502
     | 
    
      
 
     | 
  
  
    | 
      503
     | 
    
          /**
 
     | 
  
  
    | 
      504
     | 
    
           * Sets the Compiler instance.
 
     | 
  
  
    | 
      505
     | 
    
           *
 
     | 
  
  
    | 
      506
     | 
    
           * @param Twig_CompilerInterface $compiler A Twig_CompilerInterface instance
 
     | 
  
  
    | 
      507
     | 
    
           */
 
     | 
  
  
    | 
      508
     | 
    
          public function setCompiler(Twig_CompilerInterface $compiler)
 
     | 
  
  
    | 
      509
     | 
    
          {
     | 
  
  
    | 
      510
     | 
    
              $this->compiler = $compiler;
 
     | 
  
  
    | 
      511
     | 
    
          }
 
     | 
  
  
    | 
      512
     | 
    
      
 
     | 
  
  
    | 
      513
     | 
    
          /**
 
     | 
  
  
    | 
      514
     | 
    
           * Compiles a Node.
 
     | 
  
  
    | 
      515
     | 
    
           *
 
     | 
  
  
    | 
      516
     | 
    
           * @param Twig_NodeInterface $node A Twig_NodeInterface instance
 
     | 
  
  
    | 
      517
     | 
    
           *
 
     | 
  
  
    | 
      518
     | 
    
           * @return string The compiled PHP source code
 
     | 
  
  
    | 
      519
     | 
    
           */
 
     | 
  
  
    | 
      520
     | 
    
          public function compile(Twig_NodeInterface $node)
 
     | 
  
  
    | 
      521
     | 
    
          {
     | 
  
  
    | 
      522
     | 
    
              return $this->getCompiler()->compile($node)->getSource();
 
     | 
  
  
    | 
      523
     | 
    
          }
 
     | 
  
  
    | 
      524
     | 
    
      
 
     | 
  
  
    | 
      525
     | 
    
          /**
 
     | 
  
  
    | 
      526
     | 
    
           * Compiles a template source code.
 
     | 
  
  
    | 
      527
     | 
    
           *
 
     | 
  
  
    | 
      528
     | 
    
           * @param string $source The template source code
 
     | 
  
  
    | 
      529
     | 
    
           * @param string $name   The template name
 
     | 
  
  
    | 
      530
     | 
    
           *
 
     | 
  
  
    | 
      531
     | 
    
           * @return string The compiled PHP source code
 
     | 
  
  
    | 
      532
     | 
    
           */
 
     | 
  
  
    | 
      533
     | 
    
          public function compileSource($source, $name = null)
 
     | 
  
  
    | 
      534
     | 
    
          {
     | 
  
  
    | 
      535
     | 
    
              try {
     | 
  
  
    | 
      536
     | 
    
                  return $this->compile($this->parse($this->tokenize($source, $name)));
 
     | 
  
  
    | 
      537
     | 
    
              } catch (Twig_Error $e) {
     | 
  
  
    | 
      538
     | 
    
                  $e->setTemplateFile($name);
 
     | 
  
  
    | 
      539
     | 
    
                  throw $e;
 
     | 
  
  
    | 
      540
     | 
    
              } catch (Exception $e) {
     | 
  
  
    | 
      541
     | 
    
                  throw new Twig_Error_Runtime(sprintf('An exception has been thrown during the compilation of a template ("%s").', $e->getMessage()), -1, $name, $e);
     | 
  
  
    | 
      542
     | 
    
              }
 
     | 
  
  
    | 
      543
     | 
    
          }
 
     | 
  
  
    | 
      544
     | 
    
      
 
     | 
  
  
    | 
      545
     | 
    
          /**
 
     | 
  
  
    | 
      546
     | 
    
           * Sets the Loader instance.
 
     | 
  
  
    | 
      547
     | 
    
           *
 
     | 
  
  
    | 
      548
     | 
    
           * @param Twig_LoaderInterface $loader A Twig_LoaderInterface instance
 
     | 
  
  
    | 
      549
     | 
    
           */
 
     | 
  
  
    | 
      550
     | 
    
          public function setLoader(Twig_LoaderInterface $loader)
 
     | 
  
  
    | 
      551
     | 
    
          {
     | 
  
  
    | 
      552
     | 
    
              $this->loader = $loader;
 
     | 
  
  
    | 
      553
     | 
    
          }
 
     | 
  
  
    | 
      554
     | 
    
      
 
     | 
  
  
    | 
      555
     | 
    
          /**
 
     | 
  
  
    | 
      556
     | 
    
           * Gets the Loader instance.
 
     | 
  
  
    | 
      557
     | 
    
           *
 
     | 
  
  
    | 
      558
     | 
    
           * @return Twig_LoaderInterface A Twig_LoaderInterface instance
 
     | 
  
  
    | 
      559
     | 
    
           */
 
     | 
  
  
    | 
      560
     | 
    
          public function getLoader()
 
     | 
  
  
    | 
      561
     | 
    
          {
     | 
  
  
    | 
      562
     | 
    
              return $this->loader;
 
     | 
  
  
    | 
      563
     | 
    
          }
 
     | 
  
  
    | 
      564
     | 
    
      
 
     | 
  
  
    | 
      565
     | 
    
          /**
 
     | 
  
  
    | 
      566
     | 
    
           * Sets the default template charset.
 
     | 
  
  
    | 
      567
     | 
    
           *
 
     | 
  
  
    | 
      568
     | 
    
           * @param string $charset The default charset
 
     | 
  
  
    | 
      569
     | 
    
           */
 
     | 
  
  
    | 
      570
     | 
    
          public function setCharset($charset)
 
     | 
  
  
    | 
      571
     | 
    
          {
     | 
  
  
    | 
      572
     | 
    
              $this->charset = $charset;
 
     | 
  
  
    | 
      573
     | 
    
          }
 
     | 
  
  
    | 
      574
     | 
    
      
 
     | 
  
  
    | 
      575
     | 
    
          /**
 
     | 
  
  
    | 
      576
     | 
    
           * Gets the default template charset.
 
     | 
  
  
    | 
      577
     | 
    
           *
 
     | 
  
  
    | 
      578
     | 
    
           * @return string The default charset
 
     | 
  
  
    | 
      579
     | 
    
           */
 
     | 
  
  
    | 
      580
     | 
    
          public function getCharset()
 
     | 
  
  
    | 
      581
     | 
    
          {
     | 
  
  
    | 
      582
     | 
    
              return $this->charset;
 
     | 
  
  
    | 
      583
     | 
    
          }
 
     | 
  
  
    | 
      584
     | 
    
      
 
     | 
  
  
    | 
      585
     | 
    
          /**
 
     | 
  
  
    | 
      586
     | 
    
           * Initializes the runtime environment.
 
     | 
  
  
    | 
      587
     | 
    
           */
 
     | 
  
  
    | 
      588
     | 
    
          public function initRuntime()
 
     | 
  
  
    | 
      589
     | 
    
          {
     | 
  
  
    | 
      590
     | 
    
              $this->runtimeInitialized = true;
 
     | 
  
  
    | 
      591
     | 
    
      
 
     | 
  
  
    | 
      592
     | 
    
              foreach ($this->getExtensions() as $extension) {
     | 
  
  
    | 
      593
     | 
    
                  $extension->initRuntime($this);
 
     | 
  
  
    | 
      594
     | 
    
              }
 
     | 
  
  
    | 
      595
     | 
    
          }
 
     | 
  
  
    | 
      596
     | 
    
      
 
     | 
  
  
    | 
      597
     | 
    
          /**
 
     | 
  
  
    | 
      598
     | 
    
           * Returns true if the given extension is registered.
 
     | 
  
  
    | 
      599
     | 
    
           *
 
     | 
  
  
    | 
      600
     | 
    
           * @param string $name The extension name
 
     | 
  
  
    | 
      601
     | 
    
           *
 
     | 
  
  
    | 
      602
     | 
    
           * @return Boolean Whether the extension is registered or not
 
     | 
  
  
    | 
      603
     | 
    
           */
 
     | 
  
  
    | 
      604
     | 
    
          public function hasExtension($name)
 
     | 
  
  
    | 
      605
     | 
    
          {
     | 
  
  
    | 
      606
     | 
    
              return isset($this->extensions[$name]);
 
     | 
  
  
    | 
      607
     | 
    
          }
 
     | 
  
  
    | 
      608
     | 
    
      
 
     | 
  
  
    | 
      609
     | 
    
          /**
 
     | 
  
  
    | 
      610
     | 
    
           * Gets an extension by name.
 
     | 
  
  
    | 
      611
     | 
    
           *
 
     | 
  
  
    | 
      612
     | 
    
           * @param string $name The extension name
 
     | 
  
  
    | 
      613
     | 
    
           *
 
     | 
  
  
    | 
      614
     | 
    
           * @return Twig_ExtensionInterface A Twig_ExtensionInterface instance
 
     | 
  
  
    | 
      615
     | 
    
           */
 
     | 
  
  
    | 
      616
     | 
    
          public function getExtension($name)
 
     | 
  
  
    | 
      617
     | 
    
          {
     | 
  
  
    | 
      618
     | 
    
              if (!isset($this->extensions[$name])) {
     | 
  
  
    | 
      619
     | 
    
                  throw new Twig_Error_Runtime(sprintf('The "%s" extension is not enabled.', $name));
     | 
  
  
    | 
      620
     | 
    
              }
 
     | 
  
  
    | 
      621
     | 
    
      
 
     | 
  
  
    | 
      622
     | 
    
              return $this->extensions[$name];
 
     | 
  
  
    | 
      623
     | 
    
          }
 
     | 
  
  
    | 
      624
     | 
    
      
 
     | 
  
  
    | 
      625
     | 
    
          /**
 
     | 
  
  
    | 
      626
     | 
    
           * Registers an extension.
 
     | 
  
  
    | 
      627
     | 
    
           *
 
     | 
  
  
    | 
      628
     | 
    
           * @param Twig_ExtensionInterface $extension A Twig_ExtensionInterface instance
 
     | 
  
  
    | 
      629
     | 
    
           */
 
     | 
  
  
    | 
      630
     | 
    
          public function addExtension(Twig_ExtensionInterface $extension)
 
     | 
  
  
    | 
      631
     | 
    
          {
     | 
  
  
    | 
      632
     | 
    
              $this->extensions[$extension->getName()] = $extension;
 
     | 
  
  
    | 
      633
     | 
    
              $this->parsers = null;
 
     | 
  
  
    | 
      634
     | 
    
              $this->visitors = null;
 
     | 
  
  
    | 
      635
     | 
    
              $this->filters = null;
 
     | 
  
  
    | 
      636
     | 
    
              $this->tests = null;
 
     | 
  
  
    | 
      637
     | 
    
              $this->functions = null;
 
     | 
  
  
    | 
      638
     | 
    
              $this->globals = null;
 
     | 
  
  
    | 
      639
     | 
    
          }
 
     | 
  
  
    | 
      640
     | 
    
      
 
     | 
  
  
    | 
      641
     | 
    
          /**
 
     | 
  
  
    | 
      642
     | 
    
           * Removes an extension by name.
 
     | 
  
  
    | 
      643
     | 
    
           *
 
     | 
  
  
    | 
      644
     | 
    
           * @param string $name The extension name
 
     | 
  
  
    | 
      645
     | 
    
           */
 
     | 
  
  
    | 
      646
     | 
    
          public function removeExtension($name)
 
     | 
  
  
    | 
      647
     | 
    
          {
     | 
  
  
    | 
      648
     | 
    
              unset($this->extensions[$name]);
 
     | 
  
  
    | 
      649
     | 
    
              $this->parsers = null;
 
     | 
  
  
    | 
      650
     | 
    
              $this->visitors = null;
 
     | 
  
  
    | 
      651
     | 
    
              $this->filters = null;
 
     | 
  
  
    | 
      652
     | 
    
              $this->tests = null;
 
     | 
  
  
    | 
      653
     | 
    
              $this->functions = null;
 
     | 
  
  
    | 
      654
     | 
    
              $this->globals = null;
 
     | 
  
  
    | 
      655
     | 
    
          }
 
     | 
  
  
    | 
      656
     | 
    
      
 
     | 
  
  
    | 
      657
     | 
    
          /**
 
     | 
  
  
    | 
      658
     | 
    
           * Registers an array of extensions.
 
     | 
  
  
    | 
      659
     | 
    
           *
 
     | 
  
  
    | 
      660
     | 
    
           * @param array $extensions An array of extensions
 
     | 
  
  
    | 
      661
     | 
    
           */
 
     | 
  
  
    | 
      662
     | 
    
          public function setExtensions(array $extensions)
 
     | 
  
  
    | 
      663
     | 
    
          {
     | 
  
  
    | 
      664
     | 
    
              foreach ($extensions as $extension) {
     | 
  
  
    | 
      665
     | 
    
                  $this->addExtension($extension);
 
     | 
  
  
    | 
      666
     | 
    
              }
 
     | 
  
  
    | 
      667
     | 
    
          }
 
     | 
  
  
    | 
      668
     | 
    
      
 
     | 
  
  
    | 
      669
     | 
    
          /**
 
     | 
  
  
    | 
      670
     | 
    
           * Returns all registered extensions.
 
     | 
  
  
    | 
      671
     | 
    
           *
 
     | 
  
  
    | 
      672
     | 
    
           * @return array An array of extensions
 
     | 
  
  
    | 
      673
     | 
    
           */
 
     | 
  
  
    | 
      674
     | 
    
          public function getExtensions()
 
     | 
  
  
    | 
      675
     | 
    
          {
     | 
  
  
    | 
      676
     | 
    
              return $this->extensions;
 
     | 
  
  
    | 
      677
     | 
    
          }
 
     | 
  
  
    | 
      678
     | 
    
      
 
     | 
  
  
    | 
      679
     | 
    
          /**
 
     | 
  
  
    | 
      680
     | 
    
           * Registers a Token Parser.
 
     | 
  
  
    | 
      681
     | 
    
           *
 
     | 
  
  
    | 
      682
     | 
    
           * @param Twig_TokenParserInterface $parser A Twig_TokenParserInterface instance
 
     | 
  
  
    | 
      683
     | 
    
           */
 
     | 
  
  
    | 
      684
     | 
    
          public function addTokenParser(Twig_TokenParserInterface $parser)
 
     | 
  
  
    | 
      685
     | 
    
          {
     | 
  
  
    | 
      686
     | 
    
              $this->staging['token_parsers'][] = $parser;
 
     | 
  
  
    | 
      687
     | 
    
              $this->parsers = null;
 
     | 
  
  
    | 
      688
     | 
    
          }
 
     | 
  
  
    | 
      689
     | 
    
      
 
     | 
  
  
    | 
      690
     | 
    
          /**
 
     | 
  
  
    | 
      691
     | 
    
           * Gets the registered Token Parsers.
 
     | 
  
  
    | 
      692
     | 
    
           *
 
     | 
  
  
    | 
      693
     | 
    
           * @return Twig_TokenParserBrokerInterface A broker containing token parsers
 
     | 
  
  
    | 
      694
     | 
    
           */
 
     | 
  
  
    | 
      695
     | 
    
          public function getTokenParsers()
 
     | 
  
  
    | 
      696
     | 
    
          {
     | 
  
  
    | 
      697
     | 
    
              if (null === $this->parsers) {
     | 
  
  
    | 
      698
     | 
    
                  $this->parsers = new Twig_TokenParserBroker();
 
     | 
  
  
    | 
      699
     | 
    
      
 
     | 
  
  
    | 
      700
     | 
    
                  if (isset($this->staging['token_parsers'])) {
     | 
  
  
    | 
      701
     | 
    
                      foreach ($this->staging['token_parsers'] as $parser) {
     | 
  
  
    | 
      702
     | 
    
                          $this->parsers->addTokenParser($parser);
 
     | 
  
  
    | 
      703
     | 
    
                      }
 
     | 
  
  
    | 
      704
     | 
    
                  }
 
     | 
  
  
    | 
      705
     | 
    
      
 
     | 
  
  
    | 
      706
     | 
    
                  foreach ($this->getExtensions() as $extension) {
     | 
  
  
    | 
      707
     | 
    
                      $parsers = $extension->getTokenParsers();
 
     | 
  
  
    | 
      708
     | 
    
                      foreach ($parsers as $parser) {
     | 
  
  
    | 
      709
     | 
    
                          if ($parser instanceof Twig_TokenParserInterface) {
     | 
  
  
    | 
      710
     | 
    
                              $this->parsers->addTokenParser($parser);
 
     | 
  
  
    | 
      711
     | 
    
                          } elseif ($parser instanceof Twig_TokenParserBrokerInterface) {
     | 
  
  
    | 
      712
     | 
    
                              $this->parsers->addTokenParserBroker($parser);
 
     | 
  
  
    | 
      713
     | 
    
                          } else {
     | 
  
  
    | 
      714
     | 
    
                              throw new LogicException('getTokenParsers() must return an array of Twig_TokenParserInterface or Twig_TokenParserBrokerInterface instances');
     | 
  
  
    | 
      715
     | 
    
                          }
 
     | 
  
  
    | 
      716
     | 
    
                      }
 
     | 
  
  
    | 
      717
     | 
    
                  }
 
     | 
  
  
    | 
      718
     | 
    
              }
 
     | 
  
  
    | 
      719
     | 
    
      
 
     | 
  
  
    | 
      720
     | 
    
              return $this->parsers;
 
     | 
  
  
    | 
      721
     | 
    
          }
 
     | 
  
  
    | 
      722
     | 
    
      
 
     | 
  
  
    | 
      723
     | 
    
          /**
 
     | 
  
  
    | 
      724
     | 
    
           * Gets registered tags.
 
     | 
  
  
    | 
      725
     | 
    
           *
 
     | 
  
  
    | 
      726
     | 
    
           * Be warned that this method cannot return tags defined by Twig_TokenParserBrokerInterface classes.
 
     | 
  
  
    | 
      727
     | 
    
           *
 
     | 
  
  
    | 
      728
     | 
    
           * @return Twig_TokenParserInterface[] An array of Twig_TokenParserInterface instances
 
     | 
  
  
    | 
      729
     | 
    
           */
 
     | 
  
  
    | 
      730
     | 
    
          public function getTags()
 
     | 
  
  
    | 
      731
     | 
    
          {
     | 
  
  
    | 
      732
     | 
    
              $tags = array();
 
     | 
  
  
    | 
      733
     | 
    
              foreach ($this->getTokenParsers()->getParsers() as $parser) {
     | 
  
  
    | 
      734
     | 
    
                  if ($parser instanceof Twig_TokenParserInterface) {
     | 
  
  
    | 
      735
     | 
    
                      $tags[$parser->getTag()] = $parser;
 
     | 
  
  
    | 
      736
     | 
    
                  }
 
     | 
  
  
    | 
      737
     | 
    
              }
 
     | 
  
  
    | 
      738
     | 
    
      
 
     | 
  
  
    | 
      739
     | 
    
              return $tags;
 
     | 
  
  
    | 
      740
     | 
    
          }
 
     | 
  
  
    | 
      741
     | 
    
      
 
     | 
  
  
    | 
      742
     | 
    
          /**
 
     | 
  
  
    | 
      743
     | 
    
           * Registers a Node Visitor.
 
     | 
  
  
    | 
      744
     | 
    
           *
 
     | 
  
  
    | 
      745
     | 
    
           * @param Twig_NodeVisitorInterface $visitor A Twig_NodeVisitorInterface instance
 
     | 
  
  
    | 
      746
     | 
    
           */
 
     | 
  
  
    | 
      747
     | 
    
          public function addNodeVisitor(Twig_NodeVisitorInterface $visitor)
 
     | 
  
  
    | 
      748
     | 
    
          {
     | 
  
  
    | 
      749
     | 
    
              $this->staging['visitors'][] = $visitor;
 
     | 
  
  
    | 
      750
     | 
    
              $this->visitors = null;
 
     | 
  
  
    | 
      751
     | 
    
          }
 
     | 
  
  
    | 
      752
     | 
    
      
 
     | 
  
  
    | 
      753
     | 
    
          /**
 
     | 
  
  
    | 
      754
     | 
    
           * Gets the registered Node Visitors.
 
     | 
  
  
    | 
      755
     | 
    
           *
 
     | 
  
  
    | 
      756
     | 
    
           * @return Twig_NodeVisitorInterface[] An array of Twig_NodeVisitorInterface instances
 
     | 
  
  
    | 
      757
     | 
    
           */
 
     | 
  
  
    | 
      758
     | 
    
          public function getNodeVisitors()
 
     | 
  
  
    | 
      759
     | 
    
          {
     | 
  
  
    | 
      760
     | 
    
              if (null === $this->visitors) {
     | 
  
  
    | 
      761
     | 
    
                  foreach ($this->getExtensions() as $extension) {
     | 
  
  
    | 
      762
     | 
    
                      foreach ($extension->getNodeVisitors() as $visitor) {
     | 
  
  
    | 
      763
     | 
    
                          $this->addNodeVisitor($visitor);
 
     | 
  
  
    | 
      764
     | 
    
                      }
 
     | 
  
  
    | 
      765
     | 
    
                  }
 
     | 
  
  
    | 
      766
     | 
    
      
 
     | 
  
  
    | 
      767
     | 
    
                  $this->visitors = $this->staging['visitors'];
 
     | 
  
  
    | 
      768
     | 
    
              }
 
     | 
  
  
    | 
      769
     | 
    
      
 
     | 
  
  
    | 
      770
     | 
    
              return $this->visitors;
 
     | 
  
  
    | 
      771
     | 
    
          }
 
     | 
  
  
    | 
      772
     | 
    
      
 
     | 
  
  
    | 
      773
     | 
    
          /**
 
     | 
  
  
    | 
      774
     | 
    
           * Registers a Filter.
 
     | 
  
  
    | 
      775
     | 
    
           *
 
     | 
  
  
    | 
      776
     | 
    
           * @param string               $name   The filter name
 
     | 
  
  
    | 
      777
     | 
    
           * @param Twig_FilterInterface $filter A Twig_FilterInterface instance
 
     | 
  
  
    | 
      778
     | 
    
           */
 
     | 
  
  
    | 
      779
     | 
    
          public function addFilter($name, Twig_FilterInterface $filter)
 
     | 
  
  
    | 
      780
     | 
    
          {
     | 
  
  
    | 
      781
     | 
    
              $this->staging['filters'][$name] = $filter;
 
     | 
  
  
    | 
      782
     | 
    
              $this->filters = null;
 
     | 
  
  
    | 
      783
     | 
    
          }
 
     | 
  
  
    | 
      784
     | 
    
      
 
     | 
  
  
    | 
      785
     | 
    
          /**
 
     | 
  
  
    | 
      786
     | 
    
           * Get a filter by name.
 
     | 
  
  
    | 
      787
     | 
    
           *
 
     | 
  
  
    | 
      788
     | 
    
           * Subclasses may override this method and load filters differently;
 
     | 
  
  
    | 
      789
     | 
    
           * so no list of filters is available.
 
     | 
  
  
    | 
      790
     | 
    
           *
 
     | 
  
  
    | 
      791
     | 
    
           * @param string $name The filter name
 
     | 
  
  
    | 
      792
     | 
    
           *
 
     | 
  
  
    | 
      793
     | 
    
           * @return Twig_Filter|false A Twig_Filter instance or false if the filter does not exists
 
     | 
  
  
    | 
      794
     | 
    
           */
 
     | 
  
  
    | 
      795
     | 
    
          public function getFilter($name)
 
     | 
  
  
    | 
      796
     | 
    
          {
     | 
  
  
    | 
      797
     | 
    
              if (null === $this->filters) {
     | 
  
  
    | 
      798
     | 
    
                  $this->getFilters();
 
     | 
  
  
    | 
      799
     | 
    
              }
 
     | 
  
  
    | 
      800
     | 
    
      
 
     | 
  
  
    | 
      801
     | 
    
              if (isset($this->filters[$name])) {
     | 
  
  
    | 
      802
     | 
    
                  return $this->filters[$name];
 
     | 
  
  
    | 
      803
     | 
    
              }
 
     | 
  
  
    | 
      804
     | 
    
      
 
     | 
  
  
    | 
      805
     | 
    
              foreach ($this->filters as $pattern => $filter) {
     | 
  
  
    | 
      806
     | 
    
                  $pattern = str_replace('\\*', '(.*?)', preg_quote($pattern, '#'), $count);
     | 
  
  
    | 
      807
     | 
    
      
 
     | 
  
  
    | 
      808
     | 
    
                  if ($count) {
     | 
  
  
    | 
      809
     | 
    
                      if (preg_match('#^'.$pattern.'$#', $name, $matches)) {
     | 
  
  
    | 
      810
     | 
    
                          array_shift($matches);
 
     | 
  
  
    | 
      811
     | 
    
                          $filter->setArguments($matches);
 
     | 
  
  
    | 
      812
     | 
    
      
 
     | 
  
  
    | 
      813
     | 
    
                          return $filter;
 
     | 
  
  
    | 
      814
     | 
    
                      }
 
     | 
  
  
    | 
      815
     | 
    
                  }
 
     | 
  
  
    | 
      816
     | 
    
              }
 
     | 
  
  
    | 
      817
     | 
    
      
 
     | 
  
  
    | 
      818
     | 
    
              foreach ($this->filterCallbacks as $callback) {
     | 
  
  
    | 
      819
     | 
    
                  if (false !== $filter = call_user_func($callback, $name)) {
     | 
  
  
    | 
      820
     | 
    
                      return $filter;
 
     | 
  
  
    | 
      821
     | 
    
                  }
 
     | 
  
  
    | 
      822
     | 
    
              }
 
     | 
  
  
    | 
      823
     | 
    
      
 
     | 
  
  
    | 
      824
     | 
    
              return false;
 
     | 
  
  
    | 
      825
     | 
    
          }
 
     | 
  
  
    | 
      826
     | 
    
      
 
     | 
  
  
    | 
      827
     | 
    
          public function registerUndefinedFilterCallback($callable)
 
     | 
  
  
    | 
      828
     | 
    
          {
     | 
  
  
    | 
      829
     | 
    
              $this->filterCallbacks[] = $callable;
 
     | 
  
  
    | 
      830
     | 
    
          }
 
     | 
  
  
    | 
      831
     | 
    
      
 
     | 
  
  
    | 
      832
     | 
    
          /**
 
     | 
  
  
    | 
      833
     | 
    
           * Gets the registered Filters.
 
     | 
  
  
    | 
      834
     | 
    
           *
 
     | 
  
  
    | 
      835
     | 
    
           * Be warned that this method cannot return filters defined with registerUndefinedFunctionCallback.
 
     | 
  
  
    | 
      836
     | 
    
           *
 
     | 
  
  
    | 
      837
     | 
    
           * @return Twig_FilterInterface[] An array of Twig_FilterInterface instances
 
     | 
  
  
    | 
      838
     | 
    
           *
 
     | 
  
  
    | 
      839
     | 
    
           * @see registerUndefinedFilterCallback
 
     | 
  
  
    | 
      840
     | 
    
           */
 
     | 
  
  
    | 
      841
     | 
    
          public function getFilters()
 
     | 
  
  
    | 
      842
     | 
    
          {
     | 
  
  
    | 
      843
     | 
    
              if (null === $this->filters) {
     | 
  
  
    | 
      844
     | 
    
                  foreach ($this->getExtensions() as $extension) {
     | 
  
  
    | 
      845
     | 
    
                      foreach ($extension->getFilters() as $name => $filter) {
     | 
  
  
    | 
      846
     | 
    
                          $this->addFilter($name, $filter);
 
     | 
  
  
    | 
      847
     | 
    
                      }
 
     | 
  
  
    | 
      848
     | 
    
                  }
 
     | 
  
  
    | 
      849
     | 
    
      
 
     | 
  
  
    | 
      850
     | 
    
                  $this->filters = $this->staging['filters'];
 
     | 
  
  
    | 
      851
     | 
    
              }
 
     | 
  
  
    | 
      852
     | 
    
      
 
     | 
  
  
    | 
      853
     | 
    
              return $this->filters;
 
     | 
  
  
    | 
      854
     | 
    
          }
 
     | 
  
  
    | 
      855
     | 
    
      
 
     | 
  
  
    | 
      856
     | 
    
          /**
 
     | 
  
  
    | 
      857
     | 
    
           * Registers a Test.
 
     | 
  
  
    | 
      858
     | 
    
           *
 
     | 
  
  
    | 
      859
     | 
    
           * @param string             $name The test name
 
     | 
  
  
    | 
      860
     | 
    
           * @param Twig_TestInterface $test A Twig_TestInterface instance
 
     | 
  
  
    | 
      861
     | 
    
           */
 
     | 
  
  
    | 
      862
     | 
    
          public function addTest($name, Twig_TestInterface $test)
 
     | 
  
  
    | 
      863
     | 
    
          {
     | 
  
  
    | 
      864
     | 
    
              $this->staging['tests'][$name] = $test;
 
     | 
  
  
    | 
      865
     | 
    
              $this->tests = null;
 
     | 
  
  
    | 
      866
     | 
    
          }
 
     | 
  
  
    | 
      867
     | 
    
      
 
     | 
  
  
    | 
      868
     | 
    
          /**
 
     | 
  
  
    | 
      869
     | 
    
           * Gets the registered Tests.
 
     | 
  
  
    | 
      870
     | 
    
           *
 
     | 
  
  
    | 
      871
     | 
    
           * @return Twig_TestInterface[] An array of Twig_TestInterface instances
 
     | 
  
  
    | 
      872
     | 
    
           */
 
     | 
  
  
    | 
      873
     | 
    
          public function getTests()
 
     | 
  
  
    | 
      874
     | 
    
          {
     | 
  
  
    | 
      875
     | 
    
              if (null === $this->tests) {
     | 
  
  
    | 
      876
     | 
    
                  foreach ($this->getExtensions() as $extension) {
     | 
  
  
    | 
      877
     | 
    
                      foreach ($extension->getTests() as $name => $test) {
     | 
  
  
    | 
      878
     | 
    
                          $this->addTest($name, $test);
 
     | 
  
  
    | 
      879
     | 
    
                      }
 
     | 
  
  
    | 
      880
     | 
    
                  }
 
     | 
  
  
    | 
      881
     | 
    
      
 
     | 
  
  
    | 
      882
     | 
    
                  $this->tests = $this->staging['tests'];
 
     | 
  
  
    | 
      883
     | 
    
              }
 
     | 
  
  
    | 
      884
     | 
    
      
 
     | 
  
  
    | 
      885
     | 
    
              return $this->tests;
 
     | 
  
  
    | 
      886
     | 
    
          }
 
     | 
  
  
    | 
      887
     | 
    
      
 
     | 
  
  
    | 
      888
     | 
    
          /**
 
     | 
  
  
    | 
      889
     | 
    
           * Registers a Function.
 
     | 
  
  
    | 
      890
     | 
    
           *
 
     | 
  
  
    | 
      891
     | 
    
           * @param string                 $name     The function name
 
     | 
  
  
    | 
      892
     | 
    
           * @param Twig_FunctionInterface $function A Twig_FunctionInterface instance
 
     | 
  
  
    | 
      893
     | 
    
           */
 
     | 
  
  
    | 
      894
     | 
    
          public function addFunction($name, Twig_FunctionInterface $function)
 
     | 
  
  
    | 
      895
     | 
    
          {
     | 
  
  
    | 
      896
     | 
    
              $this->staging['functions'][$name] = $function;
 
     | 
  
  
    | 
      897
     | 
    
              $this->functions = null;
 
     | 
  
  
    | 
      898
     | 
    
          }
 
     | 
  
  
    | 
      899
     | 
    
      
 
     | 
  
  
    | 
      900
     | 
    
          /**
 
     | 
  
  
    | 
      901
     | 
    
           * Get a function by name.
 
     | 
  
  
    | 
      902
     | 
    
           *
 
     | 
  
  
    | 
      903
     | 
    
           * Subclasses may override this method and load functions differently;
 
     | 
  
  
    | 
      904
     | 
    
           * so no list of functions is available.
 
     | 
  
  
    | 
      905
     | 
    
           *
 
     | 
  
  
    | 
      906
     | 
    
           * @param string $name function name
 
     | 
  
  
    | 
      907
     | 
    
           *
 
     | 
  
  
    | 
      908
     | 
    
           * @return Twig_Function|false A Twig_Function instance or false if the function does not exists
 
     | 
  
  
    | 
      909
     | 
    
           */
 
     | 
  
  
    | 
      910
     | 
    
          public function getFunction($name)
 
     | 
  
  
    | 
      911
     | 
    
          {
     | 
  
  
    | 
      912
     | 
    
              if (null === $this->functions) {
     | 
  
  
    | 
      913
     | 
    
                  $this->getFunctions();
 
     | 
  
  
    | 
      914
     | 
    
              }
 
     | 
  
  
    | 
      915
     | 
    
      
 
     | 
  
  
    | 
      916
     | 
    
              if (isset($this->functions[$name])) {
     | 
  
  
    | 
      917
     | 
    
                  return $this->functions[$name];
 
     | 
  
  
    | 
      918
     | 
    
              }
 
     | 
  
  
    | 
      919
     | 
    
      
 
     | 
  
  
    | 
      920
     | 
    
              foreach ($this->functions as $pattern => $function) {
     | 
  
  
    | 
      921
     | 
    
                  $pattern = str_replace('\\*', '(.*?)', preg_quote($pattern, '#'), $count);
     | 
  
  
    | 
      922
     | 
    
      
 
     | 
  
  
    | 
      923
     | 
    
                  if ($count) {
     | 
  
  
    | 
      924
     | 
    
                      if (preg_match('#^'.$pattern.'$#', $name, $matches)) {
     | 
  
  
    | 
      925
     | 
    
                          array_shift($matches);
 
     | 
  
  
    | 
      926
     | 
    
                          $function->setArguments($matches);
 
     | 
  
  
    | 
      927
     | 
    
      
 
     | 
  
  
    | 
      928
     | 
    
                          return $function;
 
     | 
  
  
    | 
      929
     | 
    
                      }
 
     | 
  
  
    | 
      930
     | 
    
                  }
 
     | 
  
  
    | 
      931
     | 
    
              }
 
     | 
  
  
    | 
      932
     | 
    
      
 
     | 
  
  
    | 
      933
     | 
    
              foreach ($this->functionCallbacks as $callback) {
     | 
  
  
    | 
      934
     | 
    
                  if (false !== $function = call_user_func($callback, $name)) {
     | 
  
  
    | 
      935
     | 
    
                      return $function;
 
     | 
  
  
    | 
      936
     | 
    
                  }
 
     | 
  
  
    | 
      937
     | 
    
              }
 
     | 
  
  
    | 
      938
     | 
    
      
 
     | 
  
  
    | 
      939
     | 
    
              return false;
 
     | 
  
  
    | 
      940
     | 
    
          }
 
     | 
  
  
    | 
      941
     | 
    
      
 
     | 
  
  
    | 
      942
     | 
    
          public function registerUndefinedFunctionCallback($callable)
 
     | 
  
  
    | 
      943
     | 
    
          {
     | 
  
  
    | 
      944
     | 
    
              $this->functionCallbacks[] = $callable;
 
     | 
  
  
    | 
      945
     | 
    
          }
 
     | 
  
  
    | 
      946
     | 
    
      
 
     | 
  
  
    | 
      947
     | 
    
          /**
 
     | 
  
  
    | 
      948
     | 
    
           * Gets registered functions.
 
     | 
  
  
    | 
      949
     | 
    
           *
 
     | 
  
  
    | 
      950
     | 
    
           * Be warned that this method cannot return functions defined with registerUndefinedFunctionCallback.
 
     | 
  
  
    | 
      951
     | 
    
           *
 
     | 
  
  
    | 
      952
     | 
    
           * @return Twig_FunctionInterface[] An array of Twig_FunctionInterface instances
 
     | 
  
  
    | 
      953
     | 
    
           *
 
     | 
  
  
    | 
      954
     | 
    
           * @see registerUndefinedFunctionCallback
 
     | 
  
  
    | 
      955
     | 
    
           */
 
     | 
  
  
    | 
      956
     | 
    
          public function getFunctions()
 
     | 
  
  
    | 
      957
     | 
    
          {
     | 
  
  
    | 
      958
     | 
    
              if (null === $this->functions) {
     | 
  
  
    | 
      959
     | 
    
                  foreach ($this->getExtensions() as $extension) {
     | 
  
  
    | 
      960
     | 
    
                      foreach ($extension->getFunctions() as $name => $function) {
     | 
  
  
    | 
      961
     | 
    
                          $this->addFunction($name, $function);
 
     | 
  
  
    | 
      962
     | 
    
                      }
 
     | 
  
  
    | 
      963
     | 
    
                  }
 
     | 
  
  
    | 
      964
     | 
    
      
 
     | 
  
  
    | 
      965
     | 
    
                  $this->functions = $this->staging['functions'];
 
     | 
  
  
    | 
      966
     | 
    
              }
 
     | 
  
  
    | 
      967
     | 
    
      
 
     | 
  
  
    | 
      968
     | 
    
              return $this->functions;
 
     | 
  
  
    | 
      969
     | 
    
          }
 
     | 
  
  
    | 
      970
     | 
    
      
 
     | 
  
  
    | 
      971
     | 
    
          /**
 
     | 
  
  
    | 
      972
     | 
    
           * Registers a Global.
 
     | 
  
  
    | 
      973
     | 
    
           *
 
     | 
  
  
    | 
      974
     | 
    
           * @param string $name  The global name
 
     | 
  
  
    | 
      975
     | 
    
           * @param mixed  $value The global value
 
     | 
  
  
    | 
      976
     | 
    
           */
 
     | 
  
  
    | 
      977
     | 
    
          public function addGlobal($name, $value)
 
     | 
  
  
    | 
      978
     | 
    
          {
     | 
  
  
    | 
      979
     | 
    
              $this->staging['globals'][$name] = $value;
 
     | 
  
  
    | 
      980
     | 
    
              $this->globals = null;
 
     | 
  
  
    | 
      981
     | 
    
          }
 
     | 
  
  
    | 
      982
     | 
    
      
 
     | 
  
  
    | 
      983
     | 
    
          /**
 
     | 
  
  
    | 
      984
     | 
    
           * Gets the registered Globals.
 
     | 
  
  
    | 
      985
     | 
    
           *
 
     | 
  
  
    | 
      986
     | 
    
           * @return array An array of globals
 
     | 
  
  
    | 
      987
     | 
    
           */
 
     | 
  
  
    | 
      988
     | 
    
          public function getGlobals()
 
     | 
  
  
    | 
      989
     | 
    
          {
     | 
  
  
    | 
      990
     | 
    
              if (null === $this->globals) {
     | 
  
  
    | 
      991
     | 
    
                  $this->globals = isset($this->staging['globals']) ? $this->staging['globals'] : array();
 
     | 
  
  
    | 
      992
     | 
    
                  foreach ($this->getExtensions() as $extension) {
     | 
  
  
    | 
      993
     | 
    
                      $this->globals = array_merge($this->globals, $extension->getGlobals());
 
     | 
  
  
    | 
      994
     | 
    
                  }
 
     | 
  
  
    | 
      995
     | 
    
              }
 
     | 
  
  
    | 
      996
     | 
    
      
 
     | 
  
  
    | 
      997
     | 
    
              return $this->globals;
 
     | 
  
  
    | 
      998
     | 
    
          }
 
     | 
  
  
    | 
      999
     | 
    
      
 
     | 
  
  
    | 
      1000
     | 
    
          /**
 
     | 
  
  
    | 
      1001
     | 
    
           * Merges a context with the defined globals.
 
     | 
  
  
    | 
      1002
     | 
    
           *
 
     | 
  
  
    | 
      1003
     | 
    
           * @param array $context An array representing the context
 
     | 
  
  
    | 
      1004
     | 
    
           *
 
     | 
  
  
    | 
      1005
     | 
    
           * @return array The context merged with the globals
 
     | 
  
  
    | 
      1006
     | 
    
           */
 
     | 
  
  
    | 
      1007
     | 
    
          public function mergeGlobals(array $context)
 
     | 
  
  
    | 
      1008
     | 
    
          {
     | 
  
  
    | 
      1009
     | 
    
              // we don't use array_merge as the context being generally
 
     | 
  
  
    | 
      1010
     | 
    
              // bigger than globals, this code is faster.
 
     | 
  
  
    | 
      1011
     | 
    
              foreach ($this->getGlobals() as $key => $value) {
     | 
  
  
    | 
      1012
     | 
    
                  if (!array_key_exists($key, $context)) {
     | 
  
  
    | 
      1013
     | 
    
                      $context[$key] = $value;
 
     | 
  
  
    | 
      1014
     | 
    
                  }
 
     | 
  
  
    | 
      1015
     | 
    
              }
 
     | 
  
  
    | 
      1016
     | 
    
      
 
     | 
  
  
    | 
      1017
     | 
    
              return $context;
 
     | 
  
  
    | 
      1018
     | 
    
          }
 
     | 
  
  
    | 
      1019
     | 
    
      
 
     | 
  
  
    | 
      1020
     | 
    
          /**
 
     | 
  
  
    | 
      1021
     | 
    
           * Gets the registered unary Operators.
 
     | 
  
  
    | 
      1022
     | 
    
           *
 
     | 
  
  
    | 
      1023
     | 
    
           * @return array An array of unary operators
 
     | 
  
  
    | 
      1024
     | 
    
           */
 
     | 
  
  
    | 
      1025
     | 
    
          public function getUnaryOperators()
 
     | 
  
  
    | 
      1026
     | 
    
          {
     | 
  
  
    | 
      1027
     | 
    
              if (null === $this->unaryOperators) {
     | 
  
  
    | 
      1028
     | 
    
                  $this->initOperators();
 
     | 
  
  
    | 
      1029
     | 
    
              }
 
     | 
  
  
    | 
      1030
     | 
    
      
 
     | 
  
  
    | 
      1031
     | 
    
              return $this->unaryOperators;
 
     | 
  
  
    | 
      1032
     | 
    
          }
 
     | 
  
  
    | 
      1033
     | 
    
      
 
     | 
  
  
    | 
      1034
     | 
    
          /**
 
     | 
  
  
    | 
      1035
     | 
    
           * Gets the registered binary Operators.
 
     | 
  
  
    | 
      1036
     | 
    
           *
 
     | 
  
  
    | 
      1037
     | 
    
           * @return array An array of binary operators
 
     | 
  
  
    | 
      1038
     | 
    
           */
 
     | 
  
  
    | 
      1039
     | 
    
          public function getBinaryOperators()
 
     | 
  
  
    | 
      1040
     | 
    
          {
     | 
  
  
    | 
      1041
     | 
    
              if (null === $this->binaryOperators) {
     | 
  
  
    | 
      1042
     | 
    
                  $this->initOperators();
 
     | 
  
  
    | 
      1043
     | 
    
              }
 
     | 
  
  
    | 
      1044
     | 
    
      
 
     | 
  
  
    | 
      1045
     | 
    
              return $this->binaryOperators;
 
     | 
  
  
    | 
      1046
     | 
    
          }
 
     | 
  
  
    | 
      1047
     | 
    
      
 
     | 
  
  
    | 
      1048
     | 
    
          public function computeAlternatives($name, $items)
 
     | 
  
  
    | 
      1049
     | 
    
          {
     | 
  
  
    | 
      1050
     | 
    
              $alternatives = array();
 
     | 
  
  
    | 
      1051
     | 
    
              foreach ($items as $item) {
     | 
  
  
    | 
      1052
     | 
    
                  $lev = levenshtein($name, $item);
 
     | 
  
  
    | 
      1053
     | 
    
                  if ($lev <= strlen($name) / 3 || false !== strpos($item, $name)) {
     | 
  
  
    | 
      1054
     | 
    
                      $alternatives[$item] = $lev;
 
     | 
  
  
    | 
      1055
     | 
    
                  }
 
     | 
  
  
    | 
      1056
     | 
    
              }
 
     | 
  
  
    | 
      1057
     | 
    
              asort($alternatives);
 
     | 
  
  
    | 
      1058
     | 
    
      
 
     | 
  
  
    | 
      1059
     | 
    
              return array_keys($alternatives);
 
     | 
  
  
    | 
      1060
     | 
    
          }
 
     | 
  
  
    | 
      1061
     | 
    
      
 
     | 
  
  
    | 
      1062
     | 
    
          protected function initOperators()
 
     | 
  
  
    | 
      1063
     | 
    
          {
     | 
  
  
    | 
      1064
     | 
    
              $this->unaryOperators = array();
 
     | 
  
  
    | 
      1065
     | 
    
              $this->binaryOperators = array();
 
     | 
  
  
    | 
      1066
     | 
    
              foreach ($this->getExtensions() as $extension) {
     | 
  
  
    | 
      1067
     | 
    
                  $operators = $extension->getOperators();
 
     | 
  
  
    | 
      1068
     | 
    
      
 
     | 
  
  
    | 
      1069
     | 
    
                  if (!$operators) {
     | 
  
  
    | 
      1070
     | 
    
                      continue;
 
     | 
  
  
    | 
      1071
     | 
    
                  }
 
     | 
  
  
    | 
      1072
     | 
    
      
 
     | 
  
  
    | 
      1073
     | 
    
                  if (2 !== count($operators)) {
     | 
  
  
    | 
      1074
     | 
    
                      throw new InvalidArgumentException(sprintf('"%s::getOperators()" does not return a valid operators array.', get_class($extension)));
     | 
  
  
    | 
      1075
     | 
    
                  }
 
     | 
  
  
    | 
      1076
     | 
    
      
 
     | 
  
  
    | 
      1077
     | 
    
                  $this->unaryOperators = array_merge($this->unaryOperators, $operators[0]);
 
     | 
  
  
    | 
      1078
     | 
    
                  $this->binaryOperators = array_merge($this->binaryOperators, $operators[1]);
 
     | 
  
  
    | 
      1079
     | 
    
              }
 
     | 
  
  
    | 
      1080
     | 
    
          }
 
     | 
  
  
    | 
      1081
     | 
    
      
 
     | 
  
  
    | 
      1082
     | 
    
          protected function writeCacheFile($file, $content)
 
     | 
  
  
    | 
      1083
     | 
    
          {
     | 
  
  
    | 
      1084
     | 
    
              $dir = dirname($file);
 
     | 
  
  
    | 
      1085
     | 
    
              if (!is_dir($dir)) {
     | 
  
  
    | 
      1086
     | 
    
                  if (false === @mkdir($dir, 0777, true) && !is_dir($dir)) {
     | 
  
  
    | 
      1087
     | 
    
                      throw new RuntimeException(sprintf("Unable to create the cache directory (%s).", $dir));
     | 
  
  
    | 
      1088
     | 
    
                  }
 
     | 
  
  
    | 
      1089
     | 
    
              } elseif (!is_writable($dir)) {
     | 
  
  
    | 
      1090
     | 
    
                  throw new RuntimeException(sprintf("Unable to write in the cache directory (%s).", $dir));
     | 
  
  
    | 
      1091
     | 
    
              }
 
     | 
  
  
    | 
      1092
     | 
    
      
 
     | 
  
  
    | 
      1093
     | 
    
              $tmpFile = tempnam(dirname($file), basename($file));
 
     | 
  
  
    | 
      1094
     | 
    
              if (false !== @file_put_contents($tmpFile, $content)) {
     | 
  
  
    | 
      1095
     | 
    
                  // rename does not work on Win32 before 5.2.6
 
     | 
  
  
    | 
      1096
     | 
    
                  if (@rename($tmpFile, $file) || (@copy($tmpFile, $file) && unlink($tmpFile))) {
     | 
  
  
    | 
      1097
     | 
    
                      @chmod($file, 0666 & ~umask());
 
     | 
  
  
    | 
      1098
     | 
    
      
 
     | 
  
  
    | 
      1099
     | 
    
                      return;
 
     | 
  
  
    | 
      1100
     | 
    
                  }
 
     | 
  
  
    | 
      1101
     | 
    
              }
 
     | 
  
  
    | 
      1102
     | 
    
      
 
     | 
  
  
    | 
      1103
     | 
    
              throw new RuntimeException(sprintf('Failed to write cache file "%s".', $file));
     | 
  
  
    | 
      1104
     | 
    
          }
 
     | 
  
  
    | 
      1105
     | 
    
      }
 
     |