Skip to content

Commit

Permalink
Added "deprecated" tag
Browse files Browse the repository at this point in the history
  • Loading branch information
yceruto committed Jul 31, 2018
1 parent a14d249 commit 2ab4338
Show file tree
Hide file tree
Showing 12 changed files with 270 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG
@@ -1,5 +1,6 @@
* 1.36.0 (2018-XX-XX)

* added the "deprecated" tag
* added support for dynamically named tests
* fixed filesystem loader throwing an exception instead of returning false

Expand Down
30 changes: 30 additions & 0 deletions doc/tags/deprecated.rst
@@ -0,0 +1,30 @@
``deprecated``
==============

.. versionadded:: 1.36 and 2.6
The ``deprecated`` tag was added in Twig 1.36 and 2.6.

Twig generates a deprecation notice (via a call to the ``trigger_error()``
PHP function) where the ``deprecated`` tag is used in a template:

.. code-block:: jinja
{# base.twig #}
{% deprecated 'The "base.twig" template is deprecated, use "layout.twig" instead.' %}
{% extends 'layout.twig' %}
Also you can deprecate a block in the following way:

.. code-block:: jinja
{% block hey %}
{% deprecated 'The "hey" block is deprecated, use "greet" instead.' %}
{{ block('greet') }}
{% endblock %}
{% block greet %}
Hey you!
{% endblock %}
Note that by default, the deprecation notices are silenced and never displayed nor logged.
See :ref:`deprecation-notices` to learn how to handle them.
1 change: 1 addition & 0 deletions doc/tags/index.rst
Expand Up @@ -23,3 +23,4 @@ Tags
use
verbatim
with
deprecated
1 change: 1 addition & 0 deletions lib/Twig/Extension/Core.php
Expand Up @@ -136,6 +136,7 @@ public function getTokenParsers()
new Twig_TokenParser_Do(),
new Twig_TokenParser_Embed(),
new Twig_TokenParser_With(),
new Twig_TokenParser_Deprecated(),
);
}

Expand Down
49 changes: 49 additions & 0 deletions lib/Twig/Node/Deprecated.php
@@ -0,0 +1,49 @@
<?php

/*
* This file is part of Twig.
*
* (c) Fabien Potencier
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

/**
* Represents a deprecated node.
*
* @author Yonel Ceruto <yonelceruto@gmail.com>
*/
class Twig_Node_Deprecated extends Twig_Node
{
public function __construct(Twig_Node_Expression $expr, $lineno, $tag = null)
{
parent::__construct(array('expr' => $expr), array(), $lineno, $tag);
}

public function compile(Twig_Compiler $compiler)
{
$compiler->addDebugInfo($this);

$expr = $this->getNode('expr');

if ($expr instanceof Twig_Node_Expression_Constant) {
$compiler->write('@trigger_error(')
->subcompile($expr);
} else {
$varName = $compiler->getVarName();
$compiler->write(sprintf('$%s = ', $varName))
->subcompile($expr)
->raw(";\n")
->write(sprintf('@trigger_error($%s', $varName));
}

$compiler
->raw('.')
->string(sprintf(' ("%s" at line %d).', $this->getTemplateName(), $this->getTemplateLine()))
->raw(", E_USER_DEPRECATED);\n")
;
}
}

class_alias('Twig_Node_Deprecated', 'Twig\Node\DeprecatedNode', false);
42 changes: 42 additions & 0 deletions lib/Twig/TokenParser/Deprecated.php
@@ -0,0 +1,42 @@
<?php

/*
* This file is part of Twig.
*
* (c) Fabien Potencier
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

/**
* Deprecates a section of a template.
*
* <pre>
* {% deprecated 'The "base.twig" template is deprecated, use "layout.twig" instead.' %}
*
* {% extends 'layout.html.twig' %}
* </pre>
*
* @author Yonel Ceruto <yonelceruto@gmail.com>
*
* @final
*/
class Twig_TokenParser_Deprecated extends Twig_TokenParser
{
public function parse(Twig_Token $token)
{
$expr = $this->parser->getExpressionParser()->parseExpression();

$this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);

return new Twig_Node_Deprecated($expr, $token->getLine(), $this->getTag());
}

public function getTag()
{
return 'deprecated';
}
}

class_alias('Twig_TokenParser_Deprecated', 'Twig\TokenParser\DeprecatedTokenParser', false);
11 changes: 11 additions & 0 deletions src/Node/DeprecatedNode.php
@@ -0,0 +1,11 @@
<?php

namespace Twig\Node;

class_exists('Twig_Node_Deprecated');

if (\false) {
class DeprecatedNode extends \Twig_Node_Deprecated
{
}
}
11 changes: 11 additions & 0 deletions src/TokenParser/DeprecatedTokenParser.php
@@ -0,0 +1,11 @@
<?php

namespace Twig\TokenParser;

class_exists('Twig_TokenParser_Deprecated');

if (\false) {
class DeprecatedTokenParser extends \Twig_TokenParser_Deprecated
{
}
}
20 changes: 20 additions & 0 deletions test/Twig/Tests/Fixtures/tags/deprecated/block.legacy.test
@@ -0,0 +1,20 @@
--TEST--
Deprecating a block with "deprecated" tag
--TEMPLATE--
{% use 'greeting.twig' %}

{{ block('welcome') }}

--TEMPLATE(greeting.twig)--
{% block welcome %}
{% deprecated 'The "welcome" block is deprecated, use "hello" instead.' %}
{{ block('hello') }}
{% endblock %}

{% block hello %}
Hello Fabien
{% endblock %}
--DATA--
return array()
--EXPECT--
Hello Fabien
21 changes: 21 additions & 0 deletions test/Twig/Tests/Fixtures/tags/deprecated/macro.legacy.test
@@ -0,0 +1,21 @@
--TEST--
Deprecating a macro with "deprecated" tag
--TEMPLATE--
{% import 'greeting.twig' as greeting %}

{{ greeting.welcome('Fabien') }}

--TEMPLATE(greeting.twig)--
{% macro welcome(name) %}
{% deprecated 'The "welcome" macro is deprecated, use "hello" instead.' %}
{% import _self as self %}
{{ self.hello(name) }}
{% endmacro %}

{% macro hello(name) %}
Hello {{ name }}
{% endmacro %}
--DATA--
return array()
--EXPECT--
Hello Fabien
12 changes: 12 additions & 0 deletions test/Twig/Tests/Fixtures/tags/deprecated/template.legacy.test
@@ -0,0 +1,12 @@
--TEST--
Deprecating a template with "deprecated" tag
--TEMPLATE--
{% extends 'greeting.twig' %}

{% deprecated 'The "index.twig" template is deprecated, use "greeting.twig" instead.' %}
--TEMPLATE(greeting.twig)--
Hello Fabien
--DATA--
return array()
--EXPECT--
Hello Fabien
71 changes: 71 additions & 0 deletions test/Twig/Tests/Node/DeprecatedTest.php
@@ -0,0 +1,71 @@
<?php

/*
* This file is part of Twig.
*
* (c) Fabien Potencier
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

class Twig_Tests_Node_DeprecatedTest extends Twig_Test_NodeTestCase
{
public function testConstructor()
{
$expr = new Twig_Node_Expression_Constant('foo', 1);
$node = new Twig_Node_Deprecated($expr, 1);

$this->assertEquals($expr, $node->getNode('expr'));
}

public function getTests()
{
$tests = array();

$expr = new Twig_Node_Expression_Constant('This section is deprecated', 1);
$node = new Twig_Node_Deprecated($expr, 1, 'deprecated');
$node->setTemplateName('foo.twig');

$tests[] = array($node, <<<EOF
// line 1
@trigger_error("This section is deprecated"." (\"foo.twig\" at line 1).", E_USER_DEPRECATED);
EOF
);

$t = new Twig_Node(array(
new Twig_Node_Expression_Constant(true, 1),
new Twig_Node_Deprecated($expr, 2, 'deprecated'),
), array(), 1);
$node = new Twig_Node_If($t, null, 1);
$node->setTemplateName('foo.twig');

$tests[] = array($node, <<<EOF
// line 1
if (true) {
// line 2
@trigger_error("This section is deprecated"." (\"foo.twig\" at line 2).", E_USER_DEPRECATED);
}
EOF
);

$environment = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock());
$environment->addFunction(new Twig_SimpleFunction('foo', 'foo', array()));

$expr = new Twig_Node_Expression_Function('foo', new Twig_Node(), 1);
$node = new Twig_Node_Deprecated($expr, 1, 'deprecated');
$node->setTemplateName('foo.twig');

$compiler = $this->getCompiler($environment);
$varName = $compiler->getVarName();

$tests[] = array($node, <<<EOF
// line 1
\$$varName = foo();
@trigger_error(\$$varName." (\"foo.twig\" at line 1).", E_USER_DEPRECATED);
EOF
, $environment);

return $tests;
}
}

0 comments on commit 2ab4338

Please sign in to comment.