Commit e648812d authored by webchick's avatar webchick

Issue #2400407 by hussainweb: Upgrade Twig to latest version

parent fbb6e926
......@@ -18,7 +18,7 @@
"symfony/validator": "2.7.*",
"symfony/process": "2.7.*",
"symfony/yaml": "2.7.*",
"twig/twig": "1.20.*",
"twig/twig": "~1.20",
"doctrine/common": "2.5.*",
"doctrine/annotations": "1.2.*",
"guzzlehttp/guzzle": "dev-master#1879fbe853b0c64d109e369c7aeff09849e62d1e",
......
......@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
"hash": "32a7f1295f8f5ccdf8b5759f9eb6e626",
"hash": "d39a311bc4d6e7db527d6a43a8ac34d4",
"packages": [
{
"name": "behat/mink",
......@@ -3106,25 +3106,29 @@
},
{
"name": "twig/twig",
"version": "v1.20.0",
"version": "v1.21.1",
"source": {
"type": "git",
"url": "https://github.com/twigphp/Twig.git",
"reference": "1ea4e5f81c6d005fe84d0b38e1c4f1955eb86844"
"reference": "ca8d3aa90b6a01c82e07909fe815d6b443e75a23"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/twigphp/Twig/zipball/1ea4e5f81c6d005fe84d0b38e1c4f1955eb86844",
"reference": "1ea4e5f81c6d005fe84d0b38e1c4f1955eb86844",
"url": "https://api.github.com/repos/twigphp/Twig/zipball/ca8d3aa90b6a01c82e07909fe815d6b443e75a23",
"reference": "ca8d3aa90b6a01c82e07909fe815d6b443e75a23",
"shasum": ""
},
"require": {
"php": ">=5.2.7"
},
"require-dev": {
"symfony/debug": "~2.7",
"symfony/phpunit-bridge": "~2.7"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.20-dev"
"dev-master": "1.21-dev"
}
},
"autoload": {
......@@ -3159,7 +3163,7 @@
"keywords": [
"templating"
],
"time": "2015-08-12 15:56:39"
"time": "2015-08-26 08:58:31"
},
{
"name": "zendframework/zend-diactoros",
......
......@@ -1415,65 +1415,6 @@
"validator"
]
},
{
"name": "twig/twig",
"version": "v1.20.0",
"version_normalized": "1.20.0.0",
"source": {
"type": "git",
"url": "https://github.com/twigphp/Twig.git",
"reference": "1ea4e5f81c6d005fe84d0b38e1c4f1955eb86844"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/twigphp/Twig/zipball/1ea4e5f81c6d005fe84d0b38e1c4f1955eb86844",
"reference": "1ea4e5f81c6d005fe84d0b38e1c4f1955eb86844",
"shasum": ""
},
"require": {
"php": ">=5.2.7"
},
"time": "2015-08-12 15:56:39",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.20-dev"
}
},
"installation-source": "dist",
"autoload": {
"psr-0": {
"Twig_": "lib/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com",
"homepage": "http://fabien.potencier.org",
"role": "Lead Developer"
},
{
"name": "Armin Ronacher",
"email": "armin.ronacher@active-4.com",
"role": "Project Founder"
},
{
"name": "Twig Team",
"homepage": "http://twig.sensiolabs.org/contributors",
"role": "Contributors"
}
],
"description": "Twig, the flexible, fast, and secure template language for PHP",
"homepage": "http://twig.sensiolabs.org",
"keywords": [
"templating"
]
},
{
"name": "symfony/class-loader",
"version": "v2.7.3",
......@@ -3482,5 +3423,68 @@
"psr",
"psr-7"
]
},
{
"name": "twig/twig",
"version": "v1.21.1",
"version_normalized": "1.21.1.0",
"source": {
"type": "git",
"url": "https://github.com/twigphp/Twig.git",
"reference": "ca8d3aa90b6a01c82e07909fe815d6b443e75a23"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/twigphp/Twig/zipball/ca8d3aa90b6a01c82e07909fe815d6b443e75a23",
"reference": "ca8d3aa90b6a01c82e07909fe815d6b443e75a23",
"shasum": ""
},
"require": {
"php": ">=5.2.7"
},
"require-dev": {
"symfony/debug": "~2.7",
"symfony/phpunit-bridge": "~2.7"
},
"time": "2015-08-26 08:58:31",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.21-dev"
}
},
"installation-source": "dist",
"autoload": {
"psr-0": {
"Twig_": "lib/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com",
"homepage": "http://fabien.potencier.org",
"role": "Lead Developer"
},
{
"name": "Armin Ronacher",
"email": "armin.ronacher@active-4.com",
"role": "Project Founder"
},
{
"name": "Twig Team",
"homepage": "http://twig.sensiolabs.org/contributors",
"role": "Contributors"
}
],
"description": "Twig, the flexible, fast, and secure template language for PHP",
"homepage": "http://twig.sensiolabs.org",
"keywords": [
"templating"
]
}
]
language: php
php:
- 5.2
- 5.3
- 5.4
- 5.5
- 5.6
- hhvm
- nightly
sudo: false
cache:
directories:
- vendor
- $HOME/.composer/cache
allow_failures:
- php: nightly
php:
- 5.2
- 5.3
- 5.4
- 5.5
- 5.6
- 7.0
- hhvm
env:
- TWIG_EXT=no
- TWIG_EXT=yes
- TWIG_EXT=no
- TWIG_EXT=yes
install:
# Composer is not available on PHP 5.2
- if [ ${TRAVIS_PHP_VERSION:0:3} != "5.2" ]; then travis_retry composer install; fi
before_script:
- if [ "$TWIG_EXT" == "yes" ]; then sh -c "cd ext/twig && phpize && ./configure --enable-twig && make && sudo make install"; fi
- if [ "$TWIG_EXT" == "yes" ]; then echo "extension=twig.so" >> `php --ini | grep "Loaded Configuration" | sed -e "s|.*:\s*||"`; fi
- if [ "$TWIG_EXT" == "yes" ]; then sh -c "cd ext/twig && phpize && ./configure --enable-twig && make && make install"; fi
- if [ "$TWIG_EXT" == "yes" ]; then echo "extension=twig.so" >> `php --ini | grep "Loaded Configuration" | sed -e "s|.*:\s*||"`; fi
- if [ ${TRAVIS_PHP_VERSION:0:3} == "5.2" ]; then sed -i.bak "s|vendor/autoload.php|test/bootstrap.php|" phpunit.xml.dist; fi
matrix:
exclude:
- php: hhvm
env: TWIG_EXT=yes
- php: nightly
env: TWIG_EXT=yes
fast_finish: true
exclude:
- php: hhvm
env: TWIG_EXT=yes
allow_failures:
- php: 7.0
env: TWIG_EXT=yes
* 1.21.1 (2015-08-26)
* fixed regression when using the deprecated Twig_Test_* classes
* 1.21.0 (2015-08-24)
* added deprecation notices for deprecated features
* added a deprecation "framework" for filters/functions/tests and test fixtures
* 1.20.0 (2015-08-12)
* forbid access to the Twig environment from templates and internal parts of Twig_Template
......
......@@ -29,6 +29,10 @@
"require": {
"php": ">=5.2.7"
},
"require-dev": {
"symfony/phpunit-bridge": "~2.7",
"symfony/debug": "~2.7"
},
"autoload": {
"psr-0" : {
"Twig_" : "lib/"
......@@ -36,7 +40,7 @@
},
"extra": {
"branch-alias": {
"dev-master": "1.20-dev"
"dev-master": "1.21-dev"
}
}
}
......@@ -267,6 +267,23 @@ arguments, but after the environment and the context. For instance, a call to
``'foo'|a_path_b()`` will result in the following arguments to be passed to
the filter: ``('a', 'b', 'foo')``.
Deprecated Filters
~~~~~~~~~~~~~~~~~~
.. versionadded:: 1.21
Support for deprecated filters was added in Twig 1.21.
You can mark a filter as being deprecated by setting the ``deprecated`` option
to ``true``. You can also give an alternative filter that replaces the
deprecated one when that makes sense::
$filter = new Twig_SimpleFilter('obsolete', function () {
// ...
}, array('deprecated' => true, 'alternative' => 'new_one'));
When a filter is deprecated, Twig emits a deprecation notice when compiling a
template using it. See :ref:`deprecation-notices` for more information.
Functions
---------
......
......@@ -5,6 +5,12 @@ This document lists all deprecated features in Twig. Deprecated features are
kept for backward compatibility and removed in the next major release (a
feature that was deprecated in Twig 1.x is removed in Twig 2.0).
Deprecation Notices
-------------------
As of Twig 1.21, Twig generates deprecation notices when a template uses
deprecated features. See :ref:`deprecation-notices` for more information.
Token Parsers
-------------
......@@ -80,6 +86,12 @@ Tests
* The ``sameas`` and ``divisibleby`` tests are deprecated in favor of ``same
as`` and ``divisible by`` respectively.
Tags
----
* As of Twig 1.x, the ``raw`` tag is deprecated. You should use ``verbatim``
instead.
Nodes
-----
......
Recipes
=======
.. _deprecation-notices:
Displaying Deprecation Notices
------------------------------
.. versionadded:: 1.21
This works as of Twig 1.21.
Deprecated features generate deprecation notices (via a call to the
``trigger_error()`` PHP function). By default, they are silenced and never
displayed nor logged.
To easily remove all deprecated feature usages from your templates, write and
run a script along the lines of the following::
require_once __DIR__.'/vendor/autoload.php';
$twig = create_your_twig_env();
$deprecations = new Twig_Util_DeprecationCollector($twig);
print_r($deprecations->collectDir(__DIR__.'/templates'));
The ``collectDir()`` method compiles all templates found in a directory,
catches deprecation notices, and return them.
.. tip::
If your templates are not stored on the filesystem, use the ``collect()``
method instead which takes an ``Iterator``; the iterator must return
template names as keys and template contents as values (as done by
``Twig_Util_TemplateDirIterator``).
However, this code won't find all deprecations (like using deprecated some Twig
classes). To catch all notices, register a custom error handler like the one
below::
$deprecations = array();
set_error_handler(function ($type, $msg) use (&$deprecations) {
if (E_USER_DEPRECATED === $type) {
$deprecations[] = $msg;
}
});
// run your application
print_r($deprecations);
Note that most deprecation notices are triggered during **compilation**, so
they won't be generated when templates are already cached.
.. tip::
If you want to manage the deprecation notices from your PHPUnit tests, have
a look at the `symfony/phpunit-bridge
<https://github.com/symfony/phpunit-bridge>`_ package, which eases the
process a lot.
Making a Layout conditional
---------------------------
......@@ -274,13 +332,14 @@ If you iterate over a set of files, you can pass the filename to the
is enforced during template rendering (as Twig needs the context for some
checks like allowed methods on objects).
Refreshing modified Templates when APC is enabled and apc.stat = 0
------------------------------------------------------------------
Refreshing modified Templates when OPcache or APC is enabled
------------------------------------------------------------
When using APC with ``apc.stat`` set to ``0`` and Twig cache enabled, clearing
the template cache won't update the APC cache. To get around this, one can
extend ``Twig_Environment`` and force the update of the APC cache when Twig
rewrites the cache::
When using OPcache with ``opcache.validate_timestamps`` set to ``0`` or APC
with ``apc.stat`` set to ``0`` and Twig cache enabled, clearing the template
cache won't update the cache. To get around this, one can extend
``Twig_Environment`` and force the update of the cache when Twig rewrites the
cache::
class Twig_Environment_APC extends Twig_Environment
{
......@@ -289,7 +348,11 @@ rewrites the cache::
parent::writeCacheFile($file, $content);
// Compile cached file into bytecode cache
apc_compile_file($file);
if (extension_loaded('Zend OPcache') && ini_get('opcache.enable')) {
opcache_compile_file($file);
} elseif (extension_loaded('apc') && ini_get('apc.enabled')) {
apc_compile_file($file);
}
}
}
......
......@@ -60,6 +60,9 @@ Many IDEs support syntax highlighting and auto-completion for Twig:
* *Emacs* via `web-mode.el`_
* *Atom* via the `PHP-twig for atom`_
Also, `TwigFiddle`_ is an online service that allows you to execute Twig templates
from a browser; it supports all versions of Twig.
Variables
---------
......@@ -882,3 +885,4 @@ Extension<creating_extensions>` chapter.
.. _`web-mode.el`: http://web-mode.org/
.. _`regular expressions`: http://php.net/manual/en/pcre.pattern.php
.. _`PHP-twig for atom`: https://github.com/reesef/php-twig
.. _`TwigFiddle`: http://twigfiddle.com/
......@@ -15,7 +15,7 @@
#ifndef PHP_TWIG_H
#define PHP_TWIG_H
#define PHP_TWIG_VERSION "1.20.0"
#define PHP_TWIG_VERSION "1.21.1"
#include "php.h"
......
......@@ -9,10 +9,14 @@
* file that was distributed with this source code.
*/
@trigger_error('The Twig_Autoloader class is deprecated and will be removed in 2.0. Use Composer instead.', E_USER_DEPRECATED);
/**
* Autoloads Twig classes.
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @deprecated Use Composer instead. Will be removed in Twig 2.0.
*/
class Twig_Autoloader
{
......@@ -23,6 +27,8 @@ class Twig_Autoloader
*/
public static function register($prepend = false)
{
@trigger_error('Using Twig_Autoloader is deprecated. Use Composer instead.', E_USER_DEPRECATED);
if (PHP_VERSION_ID < 50300) {
spl_autoload_register(array(__CLASS__, 'autoload'));
} else {
......
......@@ -43,8 +43,8 @@ abstract class Twig_BaseNodeVisitor implements Twig_NodeVisitorInterface
/**
* Called before child nodes are visited.
*
* @param Twig_Node $node The node to visit
* @param Twig_Environment $env The Twig environment instance
* @param Twig_Node $node The node to visit
* @param Twig_Environment $env The Twig environment instance
*
* @return Twig_Node The modified node
*/
......
......@@ -21,7 +21,7 @@ class Twig_Compiler implements Twig_CompilerInterface
protected $source;
protected $indentation;
protected $env;
protected $debugInfo;
protected $debugInfo = array();
protected $sourceOffset;
protected $sourceLine;
protected $filename;
......@@ -34,7 +34,6 @@ class Twig_Compiler implements Twig_CompilerInterface
public function __construct(Twig_Environment $env)
{
$this->env = $env;
$this->debugInfo = array();
}
public function getFilename()
......
......@@ -16,7 +16,7 @@
*/
class Twig_Environment
{
const VERSION = '1.20.0';
const VERSION = '1.21.1';
protected $charset;
protected $loader;
......@@ -34,15 +34,15 @@ class Twig_Environment
protected $tests;
protected $functions;
protected $globals;
protected $runtimeInitialized;
protected $extensionInitialized;
protected $runtimeInitialized = false;
protected $extensionInitialized = false;
protected $loadedTemplates;
protected $strictVariables;
protected $unaryOperators;
protected $binaryOperators;
protected $templateClassPrefix = '__TwigTemplate_';
protected $functionCallbacks;
protected $filterCallbacks;
protected $functionCallbacks = array();
protected $filterCallbacks = array();
protected $staging;
/**
......@@ -86,6 +86,8 @@ public function __construct(Twig_LoaderInterface $loader = null, $options = arra
{
if (null !== $loader) {
$this->setLoader($loader);
} else {
@trigger_error('Not passing a Twig_LoaderInterface as the first constructor argument of Twig_Environment is deprecated.', E_USER_DEPRECATED);
}
$options = array_merge(array(
......@@ -104,15 +106,11 @@ public function __construct(Twig_LoaderInterface $loader = null, $options = arra
$this->baseTemplateClass = $options['base_template_class'];
$this->autoReload = null === $options['auto_reload'] ? $this->debug : (bool) $options['auto_reload'];
$this->strictVariables = (bool) $options['strict_variables'];
$this->runtimeInitialized = false;
$this->setCache($options['cache']);
$this->functionCallbacks = array();
$this->filterCallbacks = array();
$this->addExtension(new Twig_Extension_Core());
$this->addExtension(new Twig_Extension_Escaper($options['autoescape']));
$this->addExtension(new Twig_Extension_Optimizer($options['optimizations']));
$this->extensionInitialized = false;
$this->staging = new Twig_Extension_Staging();
}
......@@ -448,6 +446,8 @@ public function resolveTemplate($names)
*/
public function clearTemplateCache()
{
@trigger_error(sprintf('The %s method is deprecated and will be removed in Twig 2.0.', __METHOD__), E_USER_DEPRECATED);
$this->loadedTemplates = array();
}
......@@ -711,6 +711,8 @@ public function addExtension(Twig_ExtensionInterface $extension)
*/
public function removeExtension($name)
{
@trigger_error(sprintf('The %s method is deprecated and will be removed in Twig 2.0.', __METHOD__), E_USER_DEPRECATED);
if ($this->extensionInitialized) {
throw new LogicException(sprintf('Unable to remove extension "%s" as extensions have already been initialized.', $name));
}
......@@ -830,6 +832,8 @@ public function addFilter($name, $filter = null)
if ($name instanceof Twig_SimpleFilter) {
$filter = $name;
$name = $filter->getName();
} else {
@trigger_error(sprintf('Passing a name as a first argument to the %s method is deprecated. Pass an instance of "Twig_SimpleFilter" instead when defining filter "%s".', __METHOD__, $name), E_USER_DEPRECATED);
}
if ($this->extensionInitialized) {
......@@ -919,6 +923,8 @@ public function addTest($name, $test = null)
if ($name instanceof Twig_SimpleTest) {
$test = $name;
$name = $test->getName();
} else {
@trigger_error(sprintf('Passing a name as a first argument to the %s method is deprecated. Pass an instance of "Twig_SimpleTest" instead when defining test "%s".', __METHOD__, $name), E_USER_DEPRECATED);
}
if ($this->extensionInitialized) {
......@@ -977,6 +983,8 @@ public function addFunction($name, $function = null)
if ($name instanceof Twig_SimpleFunction) {
$function = $name;
$name = $function->getName();
} else {
@trigger_error(sprintf('Passing a name as a first argument to the %s method is deprecated. Pass an instance of "Twig_SimpleFunction" instead when defining function "%s".', __METHOD__, $name), E_USER_DEPRECATED);
}
if ($this->extensionInitialized) {
......@@ -1067,11 +1075,11 @@ public function addGlobal($name, $value)
$this->globals = $this->initGlobals();
}
/* This condition must be uncommented in Twig 2.0
if (!array_key_exists($name, $this->globals)) {
throw new LogicException(sprintf('Unable to add global "%s" as the runtime or the extensions have already been initialized.', $name));
// The deprecation notice must be turned into the following exception in Twig 2.0
@trigger_error(sprintf('Registering global variable "%s" at runtime or when the extensions have already been initialized is deprecated.', $name), E_USER_DEPRECATED);
//throw new LogicException(sprintf('Unable to add global "%s" as the runtime or the extensions have already been initialized.', $name));
}
*/
}
if ($this->extensionInitialized || $this->runtimeInitialized) {
......@@ -1186,7 +1194,7 @@ protected function initExtensions()
}
$this->extensionInitialized = true;
$this->parsers = new Twig_TokenParserBroker();
$this->parsers = new Twig_TokenParserBroker(array(), array(), false);
$this->filters = array();
$this->functions = array();
$this->tests = array();
......@@ -1204,11 +1212,10 @@ protected function initExtension(Twig_ExtensionInterface $extension)
{
// filters
foreach ($extension->getFilters() as $name => $filter) {
if ($name instanceof Twig_SimpleFilter) {
$filter = $name;
$name = $filter->getName();
} elseif ($filter instanceof Twig_SimpleFilter) {
if ($filter instanceof Twig_SimpleFilter) {
$name = $filter->getName();
} else {
@trigger_error(sprintf('Using an instance of "%s" for filter "%s" is deprecated. Use Twig_SimpleFilter instead.', get_class($filter), $name), E_USER_DEPRECATED);
}
$this->filters[$name] = $filter;
......@@ -1216,11 +1223,10 @@ protected function initExtension(Twig_ExtensionInterface $extension)
// functions
foreach ($extension->getFunctions() as $name => $function) {
if ($name instanceof Twig_SimpleFunction) {
$function = $name;
$name = $function->getName();
} elseif ($function instanceof Twig_SimpleFunction) {
if ($function instanceof Twig_SimpleFunction) {
$name = $function->getName();
} else {
@trigger_error(sprintf('Using an instance of "%s" for function "%s" is deprecated. Use Twig_SimpleFunction instead.', get_class($function), $name), E_USER_DEPRECATED);
}
$this->functions[$name] = $function;
......@@ -1228,11 +1234,10 @@ protected function initExtension(Twig_ExtensionInterface $extension)