Verzeichnisstruktur phpBB-3.1.0


Veröffentlicht
27.10.2014

So funktioniert es


Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück

Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis.
Auf den Verzeichnisnamen klicken, dies zeigt nur das Verzeichnis mit Inhalt an

(Beispiel Datei-Icons)

Auf das Icon klicken um den Quellcode anzuzeigen

Core.php

Zuletzt modifiziert: 09.10.2024, 12:58 - Dateigröße: 44.33 KiB


0001  <?php
0002   
0003  if (!defined('ENT_SUBSTITUTE')) {
0004      define('ENT_SUBSTITUTE', 8);
0005  }
0006   
0007  /*
0008   * This file is part of Twig.
0009   *
0010   * (c) 2009 Fabien Potencier
0011   *
0012   * For the full copyright and license information, please view the LICENSE
0013   * file that was distributed with this source code.
0014   */
0015  class Twig_Extension_Core extends Twig_Extension
0016  {
0017      protected $dateFormats = array('F j, Y H:i', '%d days');
0018      protected $numberFormat = array(0, '.', ',');
0019      protected $timezone = null;
0020   
0021      /**
0022       * Sets the default format to be used by the date filter.
0023       *
0024       * @param string $format             The default date format string
0025       * @param string $dateIntervalFormat The default date interval format string
0026       */
0027      public function setDateFormat($format = null, $dateIntervalFormat = null)
0028      {
0029          if (null !== $format) {
0030              $this->dateFormats[0] = $format;
0031          }
0032   
0033          if (null !== $dateIntervalFormat) {
0034              $this->dateFormats[1] = $dateIntervalFormat;
0035          }
0036      }
0037   
0038      /**
0039       * Gets the default format to be used by the date filter.
0040       *
0041       * @return array The default date format string and the default date interval format string
0042       */
0043      public function getDateFormat()
0044      {
0045          return $this->dateFormats;
0046      }
0047   
0048      /**
0049       * Sets the default timezone to be used by the date filter.
0050       *
0051       * @param DateTimeZone|string $timezone The default timezone string or a DateTimeZone object
0052       */
0053      public function setTimezone($timezone)
0054      {
0055          $this->timezone = $timezone instanceof DateTimeZone ? $timezone : new DateTimeZone($timezone);
0056      }
0057   
0058      /**
0059       * Gets the default timezone to be used by the date filter.
0060       *
0061       * @return DateTimeZone The default timezone currently in use
0062       */
0063      public function getTimezone()
0064      {
0065          if (null === $this->timezone) {
0066              $this->timezone = new DateTimeZone(date_default_timezone_get());
0067          }
0068   
0069          return $this->timezone;
0070      }
0071   
0072      /**
0073       * Sets the default format to be used by the number_format filter.
0074       *
0075       * @param integer $decimal      The number of decimal places to use.
0076       * @param string  $decimalPoint The character(s) to use for the decimal point.
0077       * @param string  $thousandSep  The character(s) to use for the thousands separator.
0078       */
0079      public function setNumberFormat($decimal, $decimalPoint, $thousandSep)
0080      {
0081          $this->numberFormat = array($decimal, $decimalPoint, $thousandSep);
0082      }
0083   
0084      /**
0085       * Get the default format used by the number_format filter.
0086       *
0087       * @return array The arguments for number_format()
0088       */
0089      public function getNumberFormat()
0090      {
0091          return $this->numberFormat;
0092      }
0093   
0094      /**
0095       * Returns the token parser instance to add to the existing list.
0096       *
0097       * @return array An array of Twig_TokenParser instances
0098       */
0099      public function getTokenParsers()
0100      {
0101          return array(
0102              new Twig_TokenParser_For(),
0103              new Twig_TokenParser_If(),
0104              new Twig_TokenParser_Extends(),
0105              new Twig_TokenParser_Include(),
0106              new Twig_TokenParser_Block(),
0107              new Twig_TokenParser_Use(),
0108              new Twig_TokenParser_Filter(),
0109              new Twig_TokenParser_Macro(),
0110              new Twig_TokenParser_Import(),
0111              new Twig_TokenParser_From(),
0112              new Twig_TokenParser_Set(),
0113              new Twig_TokenParser_Spaceless(),
0114              new Twig_TokenParser_Flush(),
0115              new Twig_TokenParser_Do(),
0116              new Twig_TokenParser_Embed(),
0117          );
0118      }
0119   
0120      /**
0121       * Returns a list of filters to add to the existing list.
0122       *
0123       * @return array An array of filters
0124       */
0125      public function getFilters()
0126      {
0127          $filters = array(
0128              // formatting filters
0129              new Twig_SimpleFilter('date', 'twig_date_format_filter', array('needs_environment' => true)),
0130              new Twig_SimpleFilter('date_modify', 'twig_date_modify_filter', array('needs_environment' => true)),
0131              new Twig_SimpleFilter('format', 'sprintf'),
0132              new Twig_SimpleFilter('replace', 'strtr'),
0133              new Twig_SimpleFilter('number_format', 'twig_number_format_filter', array('needs_environment' => true)),
0134              new Twig_SimpleFilter('abs', 'abs'),
0135   
0136              // encoding
0137              new Twig_SimpleFilter('url_encode', 'twig_urlencode_filter'),
0138              new Twig_SimpleFilter('json_encode', 'twig_jsonencode_filter'),
0139              new Twig_SimpleFilter('convert_encoding', 'twig_convert_encoding'),
0140   
0141              // string filters
0142              new Twig_SimpleFilter('title', 'twig_title_string_filter', array('needs_environment' => true)),
0143              new Twig_SimpleFilter('capitalize', 'twig_capitalize_string_filter', array('needs_environment' => true)),
0144              new Twig_SimpleFilter('upper', 'strtoupper'),
0145              new Twig_SimpleFilter('lower', 'strtolower'),
0146              new Twig_SimpleFilter('striptags', 'strip_tags'),
0147              new Twig_SimpleFilter('trim', 'trim'),
0148              new Twig_SimpleFilter('nl2br', 'nl2br', array('pre_escape' => 'html', 'is_safe' => array('html'))),
0149   
0150              // array helpers
0151              new Twig_SimpleFilter('join', 'twig_join_filter'),
0152              new Twig_SimpleFilter('split', 'twig_split_filter'),
0153              new Twig_SimpleFilter('sort', 'twig_sort_filter'),
0154              new Twig_SimpleFilter('merge', 'twig_array_merge'),
0155              new Twig_SimpleFilter('batch', 'twig_array_batch'),
0156   
0157              // string/array filters
0158              new Twig_SimpleFilter('reverse', 'twig_reverse_filter', array('needs_environment' => true)),
0159              new Twig_SimpleFilter('length', 'twig_length_filter', array('needs_environment' => true)),
0160              new Twig_SimpleFilter('slice', 'twig_slice', array('needs_environment' => true)),
0161              new Twig_SimpleFilter('first', 'twig_first', array('needs_environment' => true)),
0162              new Twig_SimpleFilter('last', 'twig_last', array('needs_environment' => true)),
0163   
0164              // iteration and runtime
0165              new Twig_SimpleFilter('default', '_twig_default_filter', array('node_class' => 'Twig_Node_Expression_Filter_Default')),
0166              new Twig_SimpleFilter('keys', 'twig_get_array_keys_filter'),
0167   
0168              // escaping
0169              new Twig_SimpleFilter('escape', 'twig_escape_filter', array('needs_environment' => true, 'is_safe_callback' => 'twig_escape_filter_is_safe')),
0170              new Twig_SimpleFilter('e', 'twig_escape_filter', array('needs_environment' => true, 'is_safe_callback' => 'twig_escape_filter_is_safe')),
0171          );
0172   
0173          if (function_exists('mb_get_info')) {
0174              $filters[] = new Twig_SimpleFilter('upper', 'twig_upper_filter', array('needs_environment' => true));
0175              $filters[] = new Twig_SimpleFilter('lower', 'twig_lower_filter', array('needs_environment' => true));
0176          }
0177   
0178          return $filters;
0179      }
0180   
0181      /**
0182       * Returns a list of global functions to add to the existing list.
0183       *
0184       * @return array An array of global functions
0185       */
0186      public function getFunctions()
0187      {
0188          return array(
0189              new Twig_SimpleFunction('range', 'range'),
0190              new Twig_SimpleFunction('constant', 'twig_constant'),
0191              new Twig_SimpleFunction('cycle', 'twig_cycle'),
0192              new Twig_SimpleFunction('random', 'twig_random', array('needs_environment' => true)),
0193              new Twig_SimpleFunction('date', 'twig_date_converter', array('needs_environment' => true)),
0194              new Twig_SimpleFunction('include', 'twig_include', array('needs_environment' => true, 'needs_context' => true, 'is_safe' => array('all'))),
0195          );
0196      }
0197   
0198      /**
0199       * Returns a list of tests to add to the existing list.
0200       *
0201       * @return array An array of tests
0202       */
0203      public function getTests()
0204      {
0205          return array(
0206              new Twig_SimpleTest('even', null, array('node_class' => 'Twig_Node_Expression_Test_Even')),
0207              new Twig_SimpleTest('odd', null, array('node_class' => 'Twig_Node_Expression_Test_Odd')),
0208              new Twig_SimpleTest('defined', null, array('node_class' => 'Twig_Node_Expression_Test_Defined')),
0209              new Twig_SimpleTest('sameas', null, array('node_class' => 'Twig_Node_Expression_Test_Sameas')),
0210              new Twig_SimpleTest('none', null, array('node_class' => 'Twig_Node_Expression_Test_Null')),
0211              new Twig_SimpleTest('null', null, array('node_class' => 'Twig_Node_Expression_Test_Null')),
0212              new Twig_SimpleTest('divisibleby', null, array('node_class' => 'Twig_Node_Expression_Test_Divisibleby')),
0213              new Twig_SimpleTest('constant', null, array('node_class' => 'Twig_Node_Expression_Test_Constant')),
0214              new Twig_SimpleTest('empty', 'twig_test_empty'),
0215              new Twig_SimpleTest('iterable', 'twig_test_iterable'),
0216          );
0217      }
0218   
0219      /**
0220       * Returns a list of operators to add to the existing list.
0221       *
0222       * @return array An array of operators
0223       */
0224      public function getOperators()
0225      {
0226          return array(
0227              array(
0228                  'not' => array('precedence' => 50, 'class' => 'Twig_Node_Expression_Unary_Not'),
0229                  '-'   => array('precedence' => 500, 'class' => 'Twig_Node_Expression_Unary_Neg'),
0230                  '+'   => array('precedence' => 500, 'class' => 'Twig_Node_Expression_Unary_Pos'),
0231              ),
0232              array(
0233                  'or'     => array('precedence' => 10, 'class' => 'Twig_Node_Expression_Binary_Or', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
0234                  'and'    => array('precedence' => 15, 'class' => 'Twig_Node_Expression_Binary_And', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
0235                  'b-or'   => array('precedence' => 16, 'class' => 'Twig_Node_Expression_Binary_BitwiseOr', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
0236                  'b-xor'  => array('precedence' => 17, 'class' => 'Twig_Node_Expression_Binary_BitwiseXor', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
0237                  'b-and'  => array('precedence' => 18, 'class' => 'Twig_Node_Expression_Binary_BitwiseAnd', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
0238                  '=='     => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_Equal', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
0239                  '!='     => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_NotEqual', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
0240                  '<'      => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_Less', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
0241                  '>'      => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_Greater', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
0242                  '>='     => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_GreaterEqual', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
0243                  '<='     => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_LessEqual', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
0244                  'not in' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_NotIn', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
0245                  'in'     => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_In', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
0246                  '..'     => array('precedence' => 25, 'class' => 'Twig_Node_Expression_Binary_Range', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
0247                  '+'      => array('precedence' => 30, 'class' => 'Twig_Node_Expression_Binary_Add', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
0248                  '-'      => array('precedence' => 30, 'class' => 'Twig_Node_Expression_Binary_Sub', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
0249                  '~'      => array('precedence' => 40, 'class' => 'Twig_Node_Expression_Binary_Concat', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
0250                  '*'      => array('precedence' => 60, 'class' => 'Twig_Node_Expression_Binary_Mul', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
0251                  '/'      => array('precedence' => 60, 'class' => 'Twig_Node_Expression_Binary_Div', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
0252                  '//'     => array('precedence' => 60, 'class' => 'Twig_Node_Expression_Binary_FloorDiv', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
0253                  '%'      => array('precedence' => 60, 'class' => 'Twig_Node_Expression_Binary_Mod', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
0254                  'is'     => array('precedence' => 100, 'callable' => array($this, 'parseTestExpression'), 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
0255                  'is not' => array('precedence' => 100, 'callable' => array($this, 'parseNotTestExpression'), 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
0256                  '**'     => array('precedence' => 200, 'class' => 'Twig_Node_Expression_Binary_Power', 'associativity' => Twig_ExpressionParser::OPERATOR_RIGHT),
0257              ),
0258          );
0259      }
0260   
0261      public function parseNotTestExpression(Twig_Parser $parser, $node)
0262      {
0263          return new Twig_Node_Expression_Unary_Not($this->parseTestExpression($parser, $node), $parser->getCurrentToken()->getLine());
0264      }
0265   
0266      public function parseTestExpression(Twig_Parser $parser, $node)
0267      {
0268          $stream = $parser->getStream();
0269          $name = $stream->expect(Twig_Token::NAME_TYPE)->getValue();
0270          $arguments = null;
0271          if ($stream->test(Twig_Token::PUNCTUATION_TYPE, '(')) {
0272              $arguments = $parser->getExpressionParser()->parseArguments(true);
0273          }
0274   
0275          $class = $this->getTestNodeClass($parser, $name, $node->getLine());
0276   
0277          return new $class($node, $name, $arguments, $parser->getCurrentToken()->getLine());
0278      }
0279   
0280      protected function getTestNodeClass(Twig_Parser $parser, $name, $line)
0281      {
0282          $env = $parser->getEnvironment();
0283          $testMap = $env->getTests();
0284          if (!isset($testMap[$name])) {
0285              $message = sprintf('The test "%s" does not exist', $name);
0286              if ($alternatives = $env->computeAlternatives($name, array_keys($env->getTests()))) {
0287                  $message = sprintf('%s. Did you mean "%s"', $message, implode('", "', $alternatives));
0288              }
0289   
0290              throw new Twig_Error_Syntax($message, $line, $parser->getFilename());
0291          }
0292   
0293          if ($testMap[$name] instanceof Twig_SimpleTest) {
0294              return $testMap[$name]->getNodeClass();
0295          }
0296   
0297          return $testMap[$name] instanceof Twig_Test_Node ? $testMap[$name]->getClass() : 'Twig_Node_Expression_Test';
0298      }
0299   
0300      /**
0301       * Returns the name of the extension.
0302       *
0303       * @return string The extension name
0304       */
0305      public function getName()
0306      {
0307          return 'core';
0308      }
0309  }
0310   
0311  /**
0312   * Cycles over a value.
0313   *
0314   * @param ArrayAccess|array $values   An array or an ArrayAccess instance
0315   * @param integer           $position The cycle position
0316   *
0317   * @return string The next value in the cycle
0318   */
0319  function twig_cycle($values, $position)
0320  {
0321      if (!is_array($values) && !$values instanceof ArrayAccess) {
0322          return $values;
0323      }
0324   
0325      return $values[$position % count($values)];
0326  }
0327   
0328  /**
0329   * Returns a random value depending on the supplied parameter type:
0330   * - a random item from a Traversable or array
0331   * - a random character from a string
0332   * - a random integer between 0 and the integer parameter
0333   *
0334   * @param Twig_Environment                 $env    A Twig_Environment instance
0335   * @param Traversable|array|integer|string $values The values to pick a random item from
0336   *
0337   * @throws Twig_Error_Runtime When $values is an empty array (does not apply to an empty string which is returned as is).
0338   *
0339   * @return mixed A random value from the given sequence
0340   */
0341  function twig_random(Twig_Environment $env, $values = null)
0342  {
0343      if (null === $values) {
0344          return mt_rand();
0345      }
0346   
0347      if (is_int($values) || is_float($values)) {
0348          return $values < 0 ? mt_rand($values, 0) : mt_rand(0, $values);
0349      }
0350   
0351      if ($values instanceof Traversable) {
0352          $values = iterator_to_array($values);
0353      } elseif (is_string($values)) {
0354          if ('' === $values) {
0355              return '';
0356          }
0357          if (null !== $charset = $env->getCharset()) {
0358              if ('UTF-8' != $charset) {
0359                  $values = twig_convert_encoding($values, 'UTF-8', $charset);
0360              }
0361   
0362              // unicode version of str_split()
0363              // split at all positions, but not after the start and not before the end
0364              $values = preg_split('/(?<!^)(?!$)/u', $values);
0365   
0366              if ('UTF-8' != $charset) {
0367                  foreach ($values as $i => $value) {
0368                      $values[$i] = twig_convert_encoding($value, $charset, 'UTF-8');
0369                  }
0370              }
0371          } else {
0372              return $values[mt_rand(0, strlen($values) - 1)];
0373          }
0374      }
0375   
0376      if (!is_array($values)) {
0377          return $values;
0378      }
0379   
0380      if (0 === count($values)) {
0381          throw new Twig_Error_Runtime('The random function cannot pick from an empty array.');
0382      }
0383   
0384      return $values[array_rand($values, 1)];
0385  }
0386   
0387  /**
0388   * Converts a date to the given format.
0389   *
0390   * <pre>
0391   *   {{ post.published_at|date("m/d/Y") }}
0392   * </pre>
0393   *
0394   * @param Twig_Environment             $env      A Twig_Environment instance
0395   * @param DateTime|DateInterval|string $date     A date
0396   * @param string                       $format   A format
0397   * @param DateTimeZone|string          $timezone A timezone
0398   *
0399   * @return string The formatted date
0400   */
0401  function twig_date_format_filter(Twig_Environment $env, $date, $format = null, $timezone = null)
0402  {
0403      if (null === $format) {
0404          $formats = $env->getExtension('core')->getDateFormat();
0405          $format = $date instanceof DateInterval ? $formats[1] : $formats[0];
0406      }
0407   
0408      if ($date instanceof DateInterval) {
0409          return $date->format($format);
0410      }
0411   
0412      return twig_date_converter($env, $date, $timezone)->format($format);
0413  }
0414   
0415  /**
0416   * Returns a new date object modified
0417   *
0418   * <pre>
0419   *   {{ post.published_at|date_modify("-1day")|date("m/d/Y") }}
0420   * </pre>
0421   *
0422   * @param Twig_Environment  $env      A Twig_Environment instance
0423   * @param DateTime|string   $date     A date
0424   * @param string            $modifier A modifier string
0425   *
0426   * @return DateTime A new date object
0427   */
0428  function twig_date_modify_filter(Twig_Environment $env, $date, $modifier)
0429  {
0430      $date = twig_date_converter($env, $date, false);
0431      $date->modify($modifier);
0432   
0433      return $date;
0434  }
0435   
0436  /**
0437   * Converts an input to a DateTime instance.
0438   *
0439   * <pre>
0440   *    {% if date(user.created_at) < date('+2days') %}
0441   *      {# do something #}
0442   *    {% endif %}
0443   * </pre>
0444   *
0445   * @param Twig_Environment    $env      A Twig_Environment instance
0446   * @param DateTime|string     $date     A date
0447   * @param DateTimeZone|string $timezone A timezone
0448   *
0449   * @return DateTime A DateTime instance
0450   */
0451  function twig_date_converter(Twig_Environment $env, $date = null, $timezone = null)
0452  {
0453      // determine the timezone
0454      if (!$timezone) {
0455          $defaultTimezone = $env->getExtension('core')->getTimezone();
0456      } elseif (!$timezone instanceof DateTimeZone) {
0457          $defaultTimezone = new DateTimeZone($timezone);
0458      } else {
0459          $defaultTimezone = $timezone;
0460      }
0461   
0462      if ($date instanceof DateTime) {
0463          $date = clone $date;
0464          if (false !== $timezone) {
0465              $date->setTimezone($defaultTimezone);
0466          }
0467   
0468          return $date;
0469      }
0470   
0471      $asString = (string) $date;
0472      if (ctype_digit($asString) || (!empty($asString) && '-' === $asString[0] && ctype_digit(substr($asString, 1)))) {
0473          $date = '@'.$date;
0474      }
0475   
0476      $date = new DateTime($date, $defaultTimezone);
0477      if (false !== $timezone) {
0478          $date->setTimezone($defaultTimezone);
0479      }
0480   
0481      return $date;
0482  }
0483   
0484  /**
0485   * Number format filter.
0486   *
0487   * All of the formatting options can be left null, in that case the defaults will
0488   * be used.  Supplying any of the parameters will override the defaults set in the
0489   * environment object.
0490   *
0491   * @param Twig_Environment    $env          A Twig_Environment instance
0492   * @param mixed               $number       A float/int/string of the number to format
0493   * @param integer             $decimal      The number of decimal points to display.
0494   * @param string              $decimalPoint The character(s) to use for the decimal point.
0495   * @param string              $thousandSep  The character(s) to use for the thousands separator.
0496   *
0497   * @return string The formatted number
0498   */
0499  function twig_number_format_filter(Twig_Environment $env, $number, $decimal = null, $decimalPoint = null, $thousandSep = null)
0500  {
0501      $defaults = $env->getExtension('core')->getNumberFormat();
0502      if (null === $decimal) {
0503          $decimal = $defaults[0];
0504      }
0505   
0506      if (null === $decimalPoint) {
0507          $decimalPoint = $defaults[1];
0508      }
0509   
0510      if (null === $thousandSep) {
0511          $thousandSep = $defaults[2];
0512      }
0513   
0514      return number_format((float) $number, $decimal, $decimalPoint, $thousandSep);
0515  }
0516   
0517  /**
0518   * URL encodes a string as a path segment or an array as a query string.
0519   *
0520   * @param string|array $url A URL or an array of query parameters
0521   * @param bool         $raw true to use rawurlencode() instead of urlencode
0522   *
0523   * @return string The URL encoded value
0524   */
0525  function twig_urlencode_filter($url, $raw = false)
0526  {
0527      if (is_array($url)) {
0528          return http_build_query($url, '', '&');
0529      }
0530   
0531      if ($raw) {
0532          return rawurlencode($url);
0533      }
0534   
0535      return urlencode($url);
0536  }
0537   
0538  if (version_compare(PHP_VERSION, '5.3.0', '<')) {
0539      /**
0540       * JSON encodes a variable.
0541       *
0542       * @param mixed   $value   The value to encode.
0543       * @param integer $options Not used on PHP 5.2.x
0544       *
0545       * @return mixed The JSON encoded value
0546       */
0547      function twig_jsonencode_filter($value, $options = 0)
0548      {
0549          if ($value instanceof Twig_Markup) {
0550              $value = (string) $value;
0551          } elseif (is_array($value)) {
0552              array_walk_recursive($value, '_twig_markup2string');
0553          }
0554   
0555          return json_encode($value);
0556      }
0557  } else {
0558      /**
0559       * JSON encodes a variable.
0560       *
0561       * @param mixed   $value   The value to encode.
0562       * @param integer $options Bitmask consisting of JSON_HEX_QUOT, JSON_HEX_TAG, JSON_HEX_AMP, JSON_HEX_APOS, JSON_NUMERIC_CHECK, JSON_PRETTY_PRINT, JSON_UNESCAPED_SLASHES, JSON_FORCE_OBJECT
0563       *
0564       * @return mixed The JSON encoded value
0565       */
0566      function twig_jsonencode_filter($value, $options = 0)
0567      {
0568          if ($value instanceof Twig_Markup) {
0569              $value = (string) $value;
0570          } elseif (is_array($value)) {
0571              array_walk_recursive($value, '_twig_markup2string');
0572          }
0573   
0574          return json_encode($value, $options);
0575      }
0576  }
0577   
0578  function _twig_markup2string(&$value)
0579  {
0580      if ($value instanceof Twig_Markup) {
0581          $value = (string) $value;
0582      }
0583  }
0584   
0585  /**
0586   * Merges an array with another one.
0587   *
0588   * <pre>
0589   *  {% set items = { 'apple': 'fruit', 'orange': 'fruit' } %}
0590   *
0591   *  {% set items = items|merge({ 'peugeot': 'car' }) %}
0592   *
0593   *  {# items now contains { 'apple': 'fruit', 'orange': 'fruit', 'peugeot': 'car' } #}
0594   * </pre>
0595   *
0596   * @param array $arr1 An array
0597   * @param array $arr2 An array
0598   *
0599   * @return array The merged array
0600   */
0601  function twig_array_merge($arr1, $arr2)
0602  {
0603      if (!is_array($arr1) || !is_array($arr2)) {
0604          throw new Twig_Error_Runtime('The merge filter only works with arrays or hashes.');
0605      }
0606   
0607      return array_merge($arr1, $arr2);
0608  }
0609   
0610  /**
0611   * Slices a variable.
0612   *
0613   * @param Twig_Environment $env          A Twig_Environment instance
0614   * @param mixed            $item         A variable
0615   * @param integer          $start        Start of the slice
0616   * @param integer          $length       Size of the slice
0617   * @param Boolean          $preserveKeys Whether to preserve key or not (when the input is an array)
0618   *
0619   * @return mixed The sliced variable
0620   */
0621  function twig_slice(Twig_Environment $env, $item, $start, $length = null, $preserveKeys = false)
0622  {
0623      if ($item instanceof Traversable) {
0624          $item = iterator_to_array($item, false);
0625      }
0626   
0627      if (is_array($item)) {
0628          return array_slice($item, $start, $length, $preserveKeys);
0629      }
0630   
0631      $item = (string) $item;
0632   
0633      if (function_exists('mb_get_info') && null !== $charset = $env->getCharset()) {
0634          return mb_substr($item, $start, null === $length ? mb_strlen($item, $charset) - $start : $length, $charset);
0635      }
0636   
0637      return null === $length ? substr($item, $start) : substr($item, $start, $length);
0638  }
0639   
0640  /**
0641   * Returns the first element of the item.
0642   *
0643   * @param Twig_Environment $env  A Twig_Environment instance
0644   * @param mixed            $item A variable
0645   *
0646   * @return mixed The first element of the item
0647   */
0648  function twig_first(Twig_Environment $env, $item)
0649  {
0650      $elements = twig_slice($env, $item, 0, 1, false);
0651   
0652      return is_string($elements) ? $elements[0] : current($elements);
0653  }
0654   
0655  /**
0656   * Returns the last element of the item.
0657   *
0658   * @param Twig_Environment $env  A Twig_Environment instance
0659   * @param mixed            $item A variable
0660   *
0661   * @return mixed The last element of the item
0662   */
0663  function twig_last(Twig_Environment $env, $item)
0664  {
0665      $elements = twig_slice($env, $item, -1, 1, false);
0666   
0667      return is_string($elements) ? $elements[0] : current($elements);
0668  }
0669   
0670  /**
0671   * Joins the values to a string.
0672   *
0673   * The separator between elements is an empty string per default, you can define it with the optional parameter.
0674   *
0675   * <pre>
0676   *  {{ [1, 2, 3]|join('|') }}
0677   *  {# returns 1|2|3 #}
0678   *
0679   *  {{ [1, 2, 3]|join }}
0680   *  {# returns 123 #}
0681   * </pre>
0682   *
0683   * @param array  $value An array
0684   * @param string $glue  The separator
0685   *
0686   * @return string The concatenated string
0687   */
0688  function twig_join_filter($value, $glue = '')
0689  {
0690      if ($value instanceof Traversable) {
0691          $value = iterator_to_array($value, false);
0692      }
0693   
0694      return implode($glue, (array) $value);
0695  }
0696   
0697  /**
0698   * Splits the string into an array.
0699   *
0700   * <pre>
0701   *  {{ "one,two,three"|split(',') }}
0702   *  {# returns [one, two, three] #}
0703   *
0704   *  {{ "one,two,three,four,five"|split(',', 3) }}
0705   *  {# returns [one, two, "three,four,five"] #}
0706   *
0707   *  {{ "123"|split('') }}
0708   *  {# returns [1, 2, 3] #}
0709   *
0710   *  {{ "aabbcc"|split('', 2) }}
0711   *  {# returns [aa, bb, cc] #}
0712   * </pre>
0713   *
0714   * @param string  $value     A string
0715   * @param string  $delimiter The delimiter
0716   * @param integer $limit     The limit
0717   *
0718   * @return array The split string as an array
0719   */
0720  function twig_split_filter($value, $delimiter, $limit = null)
0721  {
0722      if (empty($delimiter)) {
0723          return str_split($value, null === $limit ? 1 : $limit);
0724      }
0725   
0726      return null === $limit ? explode($delimiter, $value) : explode($delimiter, $value, $limit);
0727  }
0728   
0729  // The '_default' filter is used internally to avoid using the ternary operator
0730  // which costs a lot for big contexts (before PHP 5.4). So, on average,
0731  // a function call is cheaper.
0732  function _twig_default_filter($value, $default = '')
0733  {
0734      if (twig_test_empty($value)) {
0735          return $default;
0736      }
0737   
0738      return $value;
0739  }
0740   
0741  /**
0742   * Returns the keys for the given array.
0743   *
0744   * It is useful when you want to iterate over the keys of an array:
0745   *
0746   * <pre>
0747   *  {% for key in array|keys %}
0748   *      {# ... #}
0749   *  {% endfor %}
0750   * </pre>
0751   *
0752   * @param array $array An array
0753   *
0754   * @return array The keys
0755   */
0756  function twig_get_array_keys_filter($array)
0757  {
0758      if (is_object($array) && $array instanceof Traversable) {
0759          return array_keys(iterator_to_array($array));
0760      }
0761   
0762      if (!is_array($array)) {
0763          return array();
0764      }
0765   
0766      return array_keys($array);
0767  }
0768   
0769  /**
0770   * Reverses a variable.
0771   *
0772   * @param Twig_Environment         $env          A Twig_Environment instance
0773   * @param array|Traversable|string $item         An array, a Traversable instance, or a string
0774   * @param Boolean                  $preserveKeys Whether to preserve key or not
0775   *
0776   * @return mixed The reversed input
0777   */
0778  function twig_reverse_filter(Twig_Environment $env, $item, $preserveKeys = false)
0779  {
0780      if (is_object($item) && $item instanceof Traversable) {
0781          return array_reverse(iterator_to_array($item), $preserveKeys);
0782      }
0783   
0784      if (is_array($item)) {
0785          return array_reverse($item, $preserveKeys);
0786      }
0787   
0788      if (null !== $charset = $env->getCharset()) {
0789          $string = (string) $item;
0790   
0791          if ('UTF-8' != $charset) {
0792              $item = twig_convert_encoding($string, 'UTF-8', $charset);
0793          }
0794   
0795          preg_match_all('/./us', $item, $matches);
0796   
0797          $string = implode('', array_reverse($matches[0]));
0798   
0799          if ('UTF-8' != $charset) {
0800              $string = twig_convert_encoding($string, $charset, 'UTF-8');
0801          }
0802   
0803          return $string;
0804      }
0805   
0806      return strrev((string) $item);
0807  }
0808   
0809  /**
0810   * Sorts an array.
0811   *
0812   * @param array $array An array
0813   */
0814  function twig_sort_filter($array)
0815  {
0816      asort($array);
0817   
0818      return $array;
0819  }
0820   
0821  /* used internally */
0822  function twig_in_filter($value, $compare)
0823  {
0824      if (is_array($compare)) {
0825          return in_array($value, $compare, is_object($value));
0826      } elseif (is_string($compare)) {
0827          if (!strlen($value)) {
0828              return empty($compare);
0829          }
0830   
0831          return false !== strpos($compare, (string) $value);
0832      } elseif ($compare instanceof Traversable) {
0833          return in_array($value, iterator_to_array($compare, false), is_object($value));
0834      }
0835   
0836      return false;
0837  }
0838   
0839  /**
0840   * Escapes a string.
0841   *
0842   * @param Twig_Environment $env        A Twig_Environment instance
0843   * @param string           $string     The value to be escaped
0844   * @param string           $strategy   The escaping strategy
0845   * @param string           $charset    The charset
0846   * @param Boolean          $autoescape Whether the function is called by the auto-escaping feature (true) or by the developer (false)
0847   */
0848  function twig_escape_filter(Twig_Environment $env, $string, $strategy = 'html', $charset = null, $autoescape = false)
0849  {
0850      if ($autoescape && $string instanceof Twig_Markup) {
0851          return $string;
0852      }
0853   
0854      if (!is_string($string)) {
0855          if (is_object($string) && method_exists($string, '__toString')) {
0856              $string = (string) $string;
0857          } else {
0858              return $string;
0859          }
0860      }
0861   
0862      if (null === $charset) {
0863          $charset = $env->getCharset();
0864      }
0865   
0866      switch ($strategy) {
0867          case 'html':
0868              // see http://php.net/htmlspecialchars
0869   
0870              // Using a static variable to avoid initializing the array
0871              // each time the function is called. Moving the declaration on the
0872              // top of the function slow downs other escaping strategies.
0873              static $htmlspecialcharsCharsets = array(
0874                  'ISO-8859-1' => true, 'ISO8859-1' => true,
0875                  'ISO-8859-15' => true, 'ISO8859-15' => true,
0876                  'utf-8' => true, 'UTF-8' => true,
0877                  'CP866' => true, 'IBM866' => true, '866' => true,
0878                  'CP1251' => true, 'WINDOWS-1251' => true, 'WIN-1251' => true,
0879                  '1251' => true,
0880                  'CP1252' => true, 'WINDOWS-1252' => true, '1252' => true,
0881                  'KOI8-R' => true, 'KOI8-RU' => true, 'KOI8R' => true,
0882                  'BIG5' => true, '950' => true,
0883                  'GB2312' => true, '936' => true,
0884                  'BIG5-HKSCS' => true,
0885                  'SHIFT_JIS' => true, 'SJIS' => true, '932' => true,
0886                  'EUC-JP' => true, 'EUCJP' => true,
0887                  'ISO8859-5' => true, 'ISO-8859-5' => true, 'MACROMAN' => true,
0888              );
0889   
0890              if (isset($htmlspecialcharsCharsets[$charset])) {
0891                  return htmlspecialchars($string, ENT_QUOTES | ENT_SUBSTITUTE, $charset);
0892              }
0893   
0894              if (isset($htmlspecialcharsCharsets[strtoupper($charset)])) {
0895                  // cache the lowercase variant for future iterations
0896                  $htmlspecialcharsCharsets[$charset] = true;
0897   
0898                  return htmlspecialchars($string, ENT_QUOTES | ENT_SUBSTITUTE, $charset);
0899              }
0900   
0901              $string = twig_convert_encoding($string, 'UTF-8', $charset);
0902              $string = htmlspecialchars($string, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
0903   
0904              return twig_convert_encoding($string, $charset, 'UTF-8');
0905   
0906          case 'js':
0907              // escape all non-alphanumeric characters
0908              // into their \xHH or \uHHHH representations
0909              if ('UTF-8' != $charset) {
0910                  $string = twig_convert_encoding($string, 'UTF-8', $charset);
0911              }
0912   
0913              if (0 == strlen($string) ? false : (1 == preg_match('/^./su', $string) ? false : true)) {
0914                  throw new Twig_Error_Runtime('The string to escape is not a valid UTF-8 string.');
0915              }
0916   
0917              $string = preg_replace_callback('#[^a-zA-Z0-9,\._]#Su', '_twig_escape_js_callback', $string);
0918   
0919              if ('UTF-8' != $charset) {
0920                  $string = twig_convert_encoding($string, $charset, 'UTF-8');
0921              }
0922   
0923              return $string;
0924   
0925          case 'css':
0926              if ('UTF-8' != $charset) {
0927                  $string = twig_convert_encoding($string, 'UTF-8', $charset);
0928              }
0929   
0930              if (0 == strlen($string) ? false : (1 == preg_match('/^./su', $string) ? false : true)) {
0931                  throw new Twig_Error_Runtime('The string to escape is not a valid UTF-8 string.');
0932              }
0933   
0934              $string = preg_replace_callback('#[^a-zA-Z0-9]#Su', '_twig_escape_css_callback', $string);
0935   
0936              if ('UTF-8' != $charset) {
0937                  $string = twig_convert_encoding($string, $charset, 'UTF-8');
0938              }
0939   
0940              return $string;
0941   
0942          case 'html_attr':
0943              if ('UTF-8' != $charset) {
0944                  $string = twig_convert_encoding($string, 'UTF-8', $charset);
0945              }
0946   
0947              if (0 == strlen($string) ? false : (1 == preg_match('/^./su', $string) ? false : true)) {
0948                  throw new Twig_Error_Runtime('The string to escape is not a valid UTF-8 string.');
0949              }
0950   
0951              $string = preg_replace_callback('#[^a-zA-Z0-9,\.\-_]#Su', '_twig_escape_html_attr_callback', $string);
0952   
0953              if ('UTF-8' != $charset) {
0954                  $string = twig_convert_encoding($string, $charset, 'UTF-8');
0955              }
0956   
0957              return $string;
0958   
0959          case 'url':
0960              // hackish test to avoid version_compare that is much slower, this works unless PHP releases a 5.10.*
0961              // at that point however PHP 5.2.* support can be removed
0962              if (PHP_VERSION < '5.3.0') {
0963                  return str_replace('%7E', '~', rawurlencode($string));
0964              }
0965   
0966              return rawurlencode($string);
0967   
0968          default:
0969              throw new Twig_Error_Runtime(sprintf('Invalid escaping strategy "%s" (valid ones: html, js, url, css, and html_attr).', $strategy));
0970      }
0971  }
0972   
0973  /* used internally */
0974  function twig_escape_filter_is_safe(Twig_Node $filterArgs)
0975  {
0976      foreach ($filterArgs as $arg) {
0977          if ($arg instanceof Twig_Node_Expression_Constant) {
0978              return array($arg->getAttribute('value'));
0979          }
0980   
0981          return array();
0982      }
0983   
0984      return array('html');
0985  }
0986   
0987  if (function_exists('mb_convert_encoding')) {
0988      function twig_convert_encoding($string, $to, $from)
0989      {
0990          return mb_convert_encoding($string, $to, $from);
0991      }
0992  } elseif (function_exists('iconv')) {
0993      function twig_convert_encoding($string, $to, $from)
0994      {
0995          return iconv($from, $to, $string);
0996      }
0997  } else {
0998      function twig_convert_encoding($string, $to, $from)
0999      {
1000          throw new Twig_Error_Runtime('No suitable convert encoding function (use UTF-8 as your encoding or install the iconv or mbstring extension).');
1001      }
1002  }
1003   
1004  function _twig_escape_js_callback($matches)
1005  {
1006      $char = $matches[0];
1007   
1008      // \xHH
1009      if (!isset($char[1])) {
1010          return '\\x'.strtoupper(substr('00'.bin2hex($char), -2));
1011      }
1012   
1013      // \uHHHH
1014      $char = twig_convert_encoding($char, 'UTF-16BE', 'UTF-8');
1015   
1016      return '\\u'.strtoupper(substr('0000'.bin2hex($char), -4));
1017  }
1018   
1019  function _twig_escape_css_callback($matches)
1020  {
1021      $char = $matches[0];
1022   
1023      // \xHH
1024      if (!isset($char[1])) {
1025          $hex = ltrim(strtoupper(bin2hex($char)), '0');
1026          if (0 === strlen($hex)) {
1027              $hex = '0';
1028          }
1029   
1030          return '\\'.$hex.' ';
1031      }
1032   
1033      // \uHHHH
1034      $char = twig_convert_encoding($char, 'UTF-16BE', 'UTF-8');
1035   
1036      return '\\'.ltrim(strtoupper(bin2hex($char)), '0').' ';
1037  }
1038   
1039  /**
1040   * This function is adapted from code coming from Zend Framework.
1041   *
1042   * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
1043   * @license   http://framework.zend.com/license/new-bsd New BSD License
1044   */
1045  function _twig_escape_html_attr_callback($matches)
1046  {
1047      /*
1048       * While HTML supports far more named entities, the lowest common denominator
1049       * has become HTML5's XML Serialisation which is restricted to the those named
1050       * entities that XML supports. Using HTML entities would result in this error:
1051       *     XML Parsing Error: undefined entity
1052       */
1053      static $entityMap = array(
1054          34 => 'quot', /* quotation mark */
1055          38 => 'amp',  /* ampersand */
1056          60 => 'lt',   /* less-than sign */
1057          62 => 'gt',   /* greater-than sign */
1058      );
1059   
1060      $chr = $matches[0];
1061      $ord = ord($chr);
1062   
1063      /**
1064       * The following replaces characters undefined in HTML with the
1065       * hex entity for the Unicode replacement character.
1066       */
1067      if (($ord <= 0x1f && $chr != "\t" && $chr != "\n" && $chr != "\r") || ($ord >= 0x7f && $ord <= 0x9f)) {
1068          return '&#xFFFD;';
1069      }
1070   
1071      /**
1072       * Check if the current character to escape has a name entity we should
1073       * replace it with while grabbing the hex value of the character.
1074       */
1075      if (strlen($chr) == 1) {
1076          $hex = strtoupper(substr('00'.bin2hex($chr), -2));
1077      } else {
1078          $chr = twig_convert_encoding($chr, 'UTF-16BE', 'UTF-8');
1079          $hex = strtoupper(substr('0000'.bin2hex($chr), -4));
1080      }
1081   
1082      $int = hexdec($hex);
1083      if (array_key_exists($int, $entityMap)) {
1084          return sprintf('&%s;', $entityMap[$int]);
1085      }
1086   
1087      /**
1088       * Per OWASP recommendations, we'll use hex entities for any other
1089       * characters where a named entity does not exist.
1090       */
1091   
1092      return sprintf('&#x%s;', $hex);
1093  }
1094   
1095  // add multibyte extensions if possible
1096  if (function_exists('mb_get_info')) {
1097      /**
1098       * Returns the length of a variable.
1099       *
1100       * @param Twig_Environment $env   A Twig_Environment instance
1101       * @param mixed            $thing A variable
1102       *
1103       * @return integer The length of the value
1104       */
1105      function twig_length_filter(Twig_Environment $env, $thing)
1106      {
1107          return is_scalar($thing) ? mb_strlen($thing, $env->getCharset()) : count($thing);
1108      }
1109   
1110      /**
1111       * Converts a string to uppercase.
1112       *
1113       * @param Twig_Environment $env    A Twig_Environment instance
1114       * @param string           $string A string
1115       *
1116       * @return string The uppercased string
1117       */
1118      function twig_upper_filter(Twig_Environment $env, $string)
1119      {
1120          if (null !== ($charset = $env->getCharset())) {
1121              return mb_strtoupper($string, $charset);
1122          }
1123   
1124          return strtoupper($string);
1125      }
1126   
1127      /**
1128       * Converts a string to lowercase.
1129       *
1130       * @param Twig_Environment $env    A Twig_Environment instance
1131       * @param string           $string A string
1132       *
1133       * @return string The lowercased string
1134       */
1135      function twig_lower_filter(Twig_Environment $env, $string)
1136      {
1137          if (null !== ($charset = $env->getCharset())) {
1138              return mb_strtolower($string, $charset);
1139          }
1140   
1141          return strtolower($string);
1142      }
1143   
1144      /**
1145       * Returns a titlecased string.
1146       *
1147       * @param Twig_Environment $env    A Twig_Environment instance
1148       * @param string           $string A string
1149       *
1150       * @return string The titlecased string
1151       */
1152      function twig_title_string_filter(Twig_Environment $env, $string)
1153      {
1154          if (null !== ($charset = $env->getCharset())) {
1155              return mb_convert_case($string, MB_CASE_TITLE, $charset);
1156          }
1157   
1158          return ucwords(strtolower($string));
1159      }
1160   
1161      /**
1162       * Returns a capitalized string.
1163       *
1164       * @param Twig_Environment $env    A Twig_Environment instance
1165       * @param string           $string A string
1166       *
1167       * @return string The capitalized string
1168       */
1169      function twig_capitalize_string_filter(Twig_Environment $env, $string)
1170      {
1171          if (null !== ($charset = $env->getCharset())) {
1172              return mb_strtoupper(mb_substr($string, 0, 1, $charset), $charset).
1173                           mb_strtolower(mb_substr($string, 1, mb_strlen($string, $charset), $charset), $charset);
1174          }
1175   
1176          return ucfirst(strtolower($string));
1177      }
1178  }
1179  // and byte fallback
1180  else {
1181      /**
1182       * Returns the length of a variable.
1183       *
1184       * @param Twig_Environment $env   A Twig_Environment instance
1185       * @param mixed            $thing A variable
1186       *
1187       * @return integer The length of the value
1188       */
1189      function twig_length_filter(Twig_Environment $env, $thing)
1190      {
1191          return is_scalar($thing) ? strlen($thing) : count($thing);
1192      }
1193   
1194      /**
1195       * Returns a titlecased string.
1196       *
1197       * @param Twig_Environment $env    A Twig_Environment instance
1198       * @param string           $string A string
1199       *
1200       * @return string The titlecased string
1201       */
1202      function twig_title_string_filter(Twig_Environment $env, $string)
1203      {
1204          return ucwords(strtolower($string));
1205      }
1206   
1207      /**
1208       * Returns a capitalized string.
1209       *
1210       * @param Twig_Environment $env    A Twig_Environment instance
1211       * @param string           $string A string
1212       *
1213       * @return string The capitalized string
1214       */
1215      function twig_capitalize_string_filter(Twig_Environment $env, $string)
1216      {
1217          return ucfirst(strtolower($string));
1218      }
1219  }
1220   
1221  /* used internally */
1222  function twig_ensure_traversable($seq)
1223  {
1224      if ($seq instanceof Traversable || is_array($seq)) {
1225          return $seq;
1226      }
1227   
1228      return array();
1229  }
1230   
1231  /**
1232   * Checks if a variable is empty.
1233   *
1234   * <pre>
1235   * {# evaluates to true if the foo variable is null, false, or the empty string #}
1236   * {% if foo is empty %}
1237   *     {# ... #}
1238   * {% endif %}
1239   * </pre>
1240   *
1241   * @param mixed $value A variable
1242   *
1243   * @return Boolean true if the value is empty, false otherwise
1244   */
1245  function twig_test_empty($value)
1246  {
1247      if ($value instanceof Countable) {
1248          return 0 == count($value);
1249      }
1250   
1251      return '' === $value || false === $value || null === $value || array() === $value;
1252  }
1253   
1254  /**
1255   * Checks if a variable is traversable.
1256   *
1257   * <pre>
1258   * {# evaluates to true if the foo variable is an array or a traversable object #}
1259   * {% if foo is traversable %}
1260   *     {# ... #}
1261   * {% endif %}
1262   * </pre>
1263   *
1264   * @param mixed $value A variable
1265   *
1266   * @return Boolean true if the value is traversable
1267   */
1268  function twig_test_iterable($value)
1269  {
1270      return $value instanceof Traversable || is_array($value);
1271  }
1272   
1273  /**
1274   * Renders a template.
1275   *
1276   * @param string  $template       The template to render
1277   * @param array   $variables      The variables to pass to the template
1278   * @param Boolean $with_context   Whether to pass the current context variables or not
1279   * @param Boolean $ignore_missing Whether to ignore missing templates or not
1280   * @param Boolean $sandboxed      Whether to sandbox the template or not
1281   *
1282   * @return string The rendered template
1283   */
1284  function twig_include(Twig_Environment $env, $context, $template, $variables = array(), $withContext = true, $ignoreMissing = false, $sandboxed = false)
1285  {
1286      if ($withContext) {
1287          $variables = array_merge($context, $variables);
1288      }
1289   
1290      if ($isSandboxed = $sandboxed && $env->hasExtension('sandbox')) {
1291          $sandbox = $env->getExtension('sandbox');
1292          if (!$alreadySandboxed = $sandbox->isSandboxed()) {
1293              $sandbox->enableSandbox();
1294          }
1295      }
1296   
1297      try {
1298          return $env->resolveTemplate($template)->render($variables);
1299      } catch (Twig_Error_Loader $e) {
1300          if (!$ignoreMissing) {
1301              throw $e;
1302          }
1303      }
1304   
1305      if ($isSandboxed && !$alreadySandboxed) {
1306          $sandbox->disableSandbox();
1307      }
1308  }
1309   
1310  /**
1311   * Provides the ability to get constants from instances as well as class/global constants.
1312   *
1313   * @param string      $constant The name of the constant
1314   * @param null|object $object   The object to get the constant from
1315   *
1316   * @return string
1317   */
1318  function twig_constant($constant, $object = null)
1319  {
1320      if (null !== $object) {
1321          $constant = get_class($object).'::'.$constant;
1322      }
1323   
1324      return constant($constant);
1325  }
1326   
1327  /**
1328   * Batches item.
1329   *
1330   * @param array   $items An array of items
1331   * @param integer $size  The size of the batch
1332   * @param string  $fill  A string to fill missing items
1333   *
1334   * @return array
1335   */
1336  function twig_array_batch($items, $size, $fill = null)
1337  {
1338      if ($items instanceof Traversable) {
1339          $items = iterator_to_array($items, false);
1340      }
1341   
1342      $size = ceil($size);
1343   
1344      $result = array_chunk($items, $size, true);
1345   
1346      if (null !== $fill) {
1347          $last = count($result) - 1;
1348          $result[$last] = array_merge(
1349              $result[$last],
1350              array_fill(0, $size - count($result[$last]), $fill)
1351          );
1352      }
1353   
1354      return $result;
1355  }
1356