New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deprecation notices #1769

Merged
merged 13 commits into from Aug 18, 2015
View
@@ -1,28 +1,33 @@
language: php
php:
- 5.2
- 5.3
- 5.4
- 5.5
- 5.6
- hhvm
- nightly
- 5.2
- 5.3
- 5.4
- 5.5
- 5.6
- hhvm
- nightly
allow_failures:
- php: nightly
env:
- TWIG_EXT=no
- TWIG_EXT=yes
- TWIG_EXT=no
- TWIG_EXT=yes
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 && sudo 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
install:
# Composer is not available on PHP 5.2
- if [ ${TRAVIS_PHP_VERSION:0:3} != "5.2" ]; then travis_retry composer install; fi
matrix:
exclude:
- php: hhvm
env: TWIG_EXT=yes
- php: nightly
env: TWIG_EXT=yes
exclude:
- php: hhvm
env: TWIG_EXT=yes
- php: nightly
env: TWIG_EXT=yes
View
@@ -1,6 +1,7 @@
* 1.20.1 (2015-XX-XX)
* 1.21.0 (2015-XX-XX)
* n/a
* added deprecation notices for deprecated features
* added a deprecation "framework" for filters/functions/tests and test fixtures
* 1.20.0 (2015-08-12)
View
@@ -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/"
View
@@ -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.

This comment has been minimized.

@sstok

sstok Aug 18, 2015

Not sure if this is a problem, but normally you have an empty line after the block start.
From what I know the first contains options like :lineno: but I'm not sure if Sphixdoc will accept tex directly after the block start :)

.. versionadded:: 1.21

    Support for deprecated filters was added in Twig 1.21.
@sstok

sstok Aug 18, 2015

Not sure if this is a problem, but normally you have an empty line after the block start.
From what I know the first contains options like :lineno: but I'm not sure if Sphixdoc will accept tex directly after the block start :)

.. versionadded:: 1.21

    Support for deprecated filters was added in Twig 1.21.

This comment has been minimized.

@stof

stof Aug 18, 2015

Contributor

AFAIK, versionadded is special and does not work if you put an empty line before the directive body

@stof

stof Aug 18, 2015

Contributor

AFAIK, versionadded is special and does not work if you put an empty line before the directive body

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
---------
View
@@ -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
-------------
View
@@ -1,6 +1,64 @@
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

This comment has been minimized.

@sstok

sstok Aug 18, 2015

like using some deprecated Twig instead of like using deprecated some Twig

@sstok

sstok Aug 18, 2015

like using some deprecated Twig instead of 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
---------------------------
View
@@ -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 @@
/**
* 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
*/
View
@@ -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(
@@ -448,6 +450,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 +715,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 +836,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 +927,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 +987,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 +1079,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));

This comment has been minimized.

@Taluu

Taluu Aug 18, 2015

Contributor

I don't really see the point here, to use a deprecated error notice instead of an exception and then suggest to actually use the same exception (unless I read it wrong) in 2.0 ?

@Taluu

Taluu Aug 18, 2015

Contributor

I don't really see the point here, to use a deprecated error notice instead of an exception and then suggest to actually use the same exception (unless I read it wrong) in 2.0 ?

This comment has been minimized.

@stof

stof Aug 18, 2015

Contributor

@Taluu the deprecation does not prevent it from working in 1.x. We are deprecating this possibility but not breaking it.
2.0 will forbid it, which will allow to simplify some code (as we will have the list of globals known without allowing to add new ones)

@stof

stof Aug 18, 2015

Contributor

@Taluu the deprecation does not prevent it from working in 1.x. We are deprecating this possibility but not breaking it.
2.0 will forbid it, which will allow to simplify some code (as we will have the list of globals known without allowing to add new ones)

This comment has been minimized.

@Taluu

Taluu Aug 18, 2015

Contributor

Ah, my bad, didn't see that this condition was commented (see removed line 1072), I thought that previously this exception was already thrown, that is what was bothering me.

@Taluu

Taluu Aug 18, 2015

Contributor

Ah, my bad, didn't see that this condition was commented (see removed line 1072), I thought that previously this exception was already thrown, that is what was bothering me.

}
*/
}
if ($this->extensionInitialized || $this->runtimeInitialized) {
@@ -1186,7 +1198,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();
@@ -1206,6 +1218,8 @@ protected function initExtension(Twig_ExtensionInterface $extension)
foreach ($extension->getFilters() as $name => $filter) {
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;
@@ -1215,6 +1229,8 @@ protected function initExtension(Twig_ExtensionInterface $extension)
foreach ($extension->getFunctions() as $name => $function) {
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($filter), $name), E_USER_DEPRECATED);
}
$this->functions[$name] = $function;
@@ -1224,6 +1240,8 @@ protected function initExtension(Twig_ExtensionInterface $extension)
foreach ($extension->getTests() as $name => $test) {
if ($test instanceof Twig_SimpleTest) {
$name = $test->getName();
} else {
@trigger_error(sprintf('Using an instance of "%s" for test "%s" is deprecated. Use Twig_SimpleTest instead.', get_class($filter), $name), E_USER_DEPRECATED);
}
$this->tests[$name] = $test;
@@ -1234,6 +1252,8 @@ protected function initExtension(Twig_ExtensionInterface $extension)
if ($parser instanceof Twig_TokenParserInterface) {
$this->parsers->addTokenParser($parser);
} elseif ($parser instanceof Twig_TokenParserBrokerInterface) {
@trigger_error('Registering a Twig_TokenParserBrokerInterface instance is deprecated.', E_USER_DEPRECATED);
$this->parsers->addTokenParserBroker($parser);
} else {
throw new LogicException('getTokenParsers() must return an array of Twig_TokenParserInterface or Twig_TokenParserBrokerInterface instances');
@@ -578,6 +578,16 @@ protected function getFunctionNodeClass($name, $line)
throw new Twig_Error_Syntax($message, $line, $this->parser->getFilename());
}
if ($function instanceof Twig_SimpleFunction && $function->isDeprecated()) {
$message = sprintf('Twig Function "%s" is deprecated', $function->getName());
if ($test->getAlternative()) {
$message .= sprintf('. Use "%s" instead', $function->getAlternative());
}
$message .= sprintf(' in %s at line %d.', $this->parser->getFilename(), $line);
@trigger_error($message, E_USER_DEPRECATED);
}
if ($function instanceof Twig_SimpleFunction) {
return $function->getNodeClass();
}
@@ -598,6 +608,16 @@ protected function getFilterNodeClass($name, $line)
throw new Twig_Error_Syntax($message, $line, $this->parser->getFilename());
}
if ($filter instanceof Twig_SimpleFilter && $filter->isDeprecated()) {
$message = sprintf('Twig Filter "%s" is deprecated', $filter->getName());
if ($test->getAlternative()) {
$message .= sprintf('. Use "%s" instead', $filter->getAlternative());
}
$message .= sprintf(' in %s at line %d.', $this->parser->getFilename(), $line);
@trigger_error($message, E_USER_DEPRECATED);
}
if ($filter instanceof Twig_SimpleFilter) {
return $filter->getNodeClass();
}
Oops, something went wrong.
ProTip! Use n and p to navigate between commits in a pull request.