diff --git a/src/Extension/CoreExtension.php b/src/Extension/CoreExtension.php index 260735abb..5f3b753c1 100644 --- a/src/Extension/CoreExtension.php +++ b/src/Extension/CoreExtension.php @@ -1474,25 +1474,31 @@ final class CoreExtension extends AbstractExtension /** * Provides the ability to get constants from instances as well as class/global constants. * - * @param string $constant The name of the constant - * @param object|null $object The object to get the constant from + * @param string $constant The name of the constant + * @param object|null $object The object to get the constant from + * @param bool $checkDefined Whether to check if the constant is defined or not * * @return mixed Class constants can return many types like scalars, arrays, and * objects depending on the PHP version (\BackedEnum, \UnitEnum, etc.) + * When $checkDefined is true, returns true when the constant is defined, false otherwise * * @internal */ - public static function constant($constant, $object = null) + public static function constant($constant, $object = null, bool $checkDefined = false) { if (null !== $object) { if ('class' === $constant) { - return \get_class($object); + return $checkDefined ? true : \get_class($object); } $constant = \get_class($object).'::'.$constant; } if (!\defined($constant)) { + if ($checkDefined) { + return false; + } + if ('::class' === strtolower(substr($constant, -7))) { throw new RuntimeError(\sprintf('You cannot use the Twig function "constant()" to access "%s". You could provide an object and call constant("class", $object) or use the class name directly as a string.', $constant)); } @@ -1500,28 +1506,7 @@ final class CoreExtension extends AbstractExtension throw new RuntimeError(\sprintf('Constant "%s" is undefined.', $constant)); } - return \constant($constant); - } - - /** - * Checks if a constant exists. - * - * @param string $constant The name of the constant - * @param object|null $object The object to get the constant from - * - * @internal - */ - public static function constantIsDefined($constant, $object = null): bool - { - if (null !== $object) { - if ('class' === $constant) { - return true; - } - - $constant = \get_class($object).'::'.$constant; - } - - return \defined($constant); + return $checkDefined ? true : \constant($constant); } /** diff --git a/src/Node/Expression/FunctionExpression.php b/src/Node/Expression/FunctionExpression.php index b7136f6f7..763a0b44d 100644 --- a/src/Node/Expression/FunctionExpression.php +++ b/src/Node/Expression/FunctionExpression.php @@ -12,7 +12,6 @@ namespace Twig\Node\Expression; use Twig\Compiler; -use Twig\Extension\CoreExtension; use Twig\Node\Node; class FunctionExpression extends CallExpression @@ -31,14 +30,14 @@ class FunctionExpression extends CallExpression $this->setAttribute('needs_environment', $function->needsEnvironment()); $this->setAttribute('needs_context', $function->needsContext()); $this->setAttribute('arguments', $function->getArguments()); - $callable = $function->getCallable(); - if ('constant' === $name && $this->getAttribute('is_defined_test')) { - $callable = [CoreExtension::class, 'constantIsDefined']; - } - $this->setAttribute('callable', $callable); + $this->setAttribute('callable', $function->getCallable()); $this->setAttribute('is_variadic', $function->isVariadic()); $this->setAttribute('dynamic_name', $function->getDynamicName()); + if ('constant' === $name && $this->getAttribute('is_defined_test')) { + $this->getNode('arguments')->setNode('checkDefined', new ConstantExpression(true, $this->getTemplateLine())); + } + $this->compileCallable($compiler); } } diff --git a/src/Resources/core.php b/src/Resources/core.php index e5372cda4..6e2fcfb07 100644 --- a/src/Resources/core.php +++ b/src/Resources/core.php @@ -441,7 +441,7 @@ function twig_constant_is_defined($constant, $object = null) { trigger_deprecation('twig/twig', '3.9', 'Using the internal "%s" function is deprecated.', __FUNCTION__); - return CoreExtension::constantIsDefined($constant, $object); + return CoreExtension::constant($constant, $object, true); } /**