From 1ee4210ba9f81b7bafe66a3dd7253ed91ee46575 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Fri, 23 Aug 2024 19:44:16 +0200 Subject: [PATCH 1/2] Deprecate node names that are not strings or integers --- CHANGELOG | 1 + doc/deprecated.rst | 5 +++++ src/Node/Node.php | 26 ++++++++++++++++++++++---- 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 30e00839f..627423370 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,6 @@ # 3.12.0 (2024-XX-XX) + * Add support for integers in methods of `Twig\Node\Node` that take a Node name * Deprecate `OptimizerNodeVisitor::OPTIMIZE_TEXT_NODES` * Fix performance regression when `use_yield` is `false` (which is the default) * Improve compatibility when `use_yield` is `false` (as extensions still using `echo` will work as is) diff --git a/doc/deprecated.rst b/doc/deprecated.rst index 8320a2290..f5fa4a77e 100644 --- a/doc/deprecated.rst +++ b/doc/deprecated.rst @@ -35,6 +35,11 @@ Extensions Nodes ----- +* The following ``Twig\Node\Node`` methods will take a string or an integer + (instead of just a string) in Twig 4.0 for their "name" argument: + ``getNode()``, ``hasNode()``, ``setNode()``, ``removeNode()``, and + ``deprecateNode()``. + * The second argument of the ``Twig\Node\Expression\CallExpression::compileArguments()`` method is deprecated. diff --git a/src/Node/Node.php b/src/Node/Node.php index 770cdaf43..b23906056 100644 --- a/src/Node/Node.php +++ b/src/Node/Node.php @@ -24,6 +24,9 @@ use Twig\Source; #[YieldReady] class Node implements \Countable, \IteratorAggregate { + /** + * @var array + */ protected $nodes; protected $attributes; protected $lineno; @@ -36,10 +39,10 @@ class Node implements \Countable, \IteratorAggregate private $attributeNameDeprecations = []; /** - * @param array $nodes An array of named nodes - * @param array $attributes An array of attributes (should not be nodes) - * @param int $lineno The line number - * @param string $tag The tag name associated with the Node + * @param array $nodes An array of named nodes + * @param array $attributes An array of attributes (should not be nodes) + * @param int $lineno The line number + * @param string $tag The tag name associated with the Node */ public function __construct(array $nodes = [], array $attributes = [], int $lineno = 0, ?string $tag = null) { @@ -158,11 +161,17 @@ class Node implements \Countable, \IteratorAggregate unset($this->attributes[$name]); } + /** + * @param string|int $name + */ public function hasNode(string $name): bool { return isset($this->nodes[$name]); } + /** + * @param string|int $name + */ public function getNode(string $name): self { if (!isset($this->nodes[$name])) { @@ -182,6 +191,9 @@ class Node implements \Countable, \IteratorAggregate return $this->nodes[$name]; } + /** + * @param string|int $name + */ public function setNode(string $name, self $node): void { $triggerDeprecation = \func_num_args() > 2 ? func_get_arg(2) : true; @@ -200,11 +212,17 @@ class Node implements \Countable, \IteratorAggregate $this->nodes[$name] = $node; } + /** + * @param string|int $name + */ public function removeNode(string $name): void { unset($this->nodes[$name]); } + /** + * @param string|int $name + */ public function deprecateNode(string $name, NameDeprecation $dep): void { $this->nodeNameDeprecations[$name] = $dep; From 094892aa3ba1c5778e5030c00d32ecbd1f6f1e8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20Andr=C3=A9?= Date: Sat, 24 Aug 2024 10:03:24 +0200 Subject: [PATCH 2/2] Remove `Template::*_CALL` const optimisations * Template::ANY_CALL * Template::ARRAY_CALL * Template::METHOD_CALL --- src/Extension/CoreExtension.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Extension/CoreExtension.php b/src/Extension/CoreExtension.php index 73caf8a5d..3a6a2e655 100644 --- a/src/Extension/CoreExtension.php +++ b/src/Extension/CoreExtension.php @@ -1565,10 +1565,10 @@ final class CoreExtension extends AbstractExtension * * @internal */ - public static function getAttribute(Environment $env, Source $source, $object, $item, array $arguments = [], $type = /* Template::ANY_CALL */ 'any', $isDefinedTest = false, $ignoreStrictCheck = false, $sandboxed = false, int $lineno = -1) + public static function getAttribute(Environment $env, Source $source, $object, $item, array $arguments = [], $type = Template::ANY_CALL, $isDefinedTest = false, $ignoreStrictCheck = false, $sandboxed = false, int $lineno = -1) { // array - if (/* Template::METHOD_CALL */ 'method' !== $type) { + if (Template::METHOD_CALL !== $type) { $arrayItem = \is_bool($item) || \is_float($item) ? (int) $item : $item; if (((\is_array($object) || $object instanceof \ArrayObject) && (isset($object[$arrayItem]) || \array_key_exists($arrayItem, (array) $object))) @@ -1581,7 +1581,7 @@ final class CoreExtension extends AbstractExtension return $object[$arrayItem]; } - if (/* Template::ARRAY_CALL */ 'array' === $type || !\is_object($object)) { + if (Template::ARRAY_CALL === $type || !\is_object($object)) { if ($isDefinedTest) { return false; } @@ -1600,7 +1600,7 @@ final class CoreExtension extends AbstractExtension } else { $message = \sprintf('Key "%s" for sequence/mapping with keys "%s" does not exist.', $arrayItem, implode(', ', array_keys($object))); } - } elseif (/* Template::ARRAY_CALL */ 'array' === $type) { + } elseif (Template::ARRAY_CALL === $type) { if (null === $object) { $message = \sprintf('Impossible to access a key ("%s") on a null variable.', $item); } else { @@ -1641,7 +1641,7 @@ final class CoreExtension extends AbstractExtension } // object property - if (/* Template::METHOD_CALL */ 'method' !== $type) { + if (Template::METHOD_CALL !== $type) { if (isset($object->$item) || \array_key_exists((string) $item, (array) $object)) { if ($isDefinedTest) { return true;