Update Twig to 3.4.3
This commit is contained in:
+5
-5
@@ -38,11 +38,11 @@ use Twig\TokenParser\TokenParserInterface;
|
||||
*/
|
||||
class Environment
|
||||
{
|
||||
public const VERSION = '3.3.8';
|
||||
public const VERSION_ID = 30308;
|
||||
public const VERSION = '3.4.3';
|
||||
public const VERSION_ID = 30403;
|
||||
public const MAJOR_VERSION = 3;
|
||||
public const MINOR_VERSION = 3;
|
||||
public const RELEASE_VERSION = 8;
|
||||
public const MINOR_VERSION = 4;
|
||||
public const RELEASE_VERSION = 3;
|
||||
public const EXTRA_VERSION = '';
|
||||
|
||||
private $charset;
|
||||
@@ -228,7 +228,7 @@ class Environment
|
||||
{
|
||||
if (\is_string($cache)) {
|
||||
$this->originalCache = $cache;
|
||||
$this->cache = new FilesystemCache($cache);
|
||||
$this->cache = new FilesystemCache($cache, $this->autoReload ? FilesystemCache::FORCE_BYTECODE_INVALIDATION : 0);
|
||||
} elseif (false === $cache) {
|
||||
$this->originalCache = $cache;
|
||||
$this->cache = new NullCache();
|
||||
|
||||
@@ -485,7 +485,7 @@ class ExpressionParser
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw new SyntaxError('Expected name or number.', $lineno, $stream->getSourceContext());
|
||||
throw new SyntaxError(sprintf('Expected name or number, got value "%s" of type %s.', $token->getValue(), Token::typeToEnglish($token->getType())), $lineno, $stream->getSourceContext());
|
||||
}
|
||||
|
||||
if ($node instanceof NameExpression && null !== $this->parser->getImportedSymbol('template', $node->getAttribute('name'))) {
|
||||
|
||||
@@ -1359,6 +1359,10 @@ function twig_source(Environment $env, $name, $ignoreMissing = false)
|
||||
function twig_constant($constant, $object = null)
|
||||
{
|
||||
if (null !== $object) {
|
||||
if ('class' === $constant) {
|
||||
return \get_class($object);
|
||||
}
|
||||
|
||||
$constant = \get_class($object).'::'.$constant;
|
||||
}
|
||||
|
||||
@@ -1376,6 +1380,10 @@ function twig_constant($constant, $object = null)
|
||||
function twig_constant_is_defined($constant, $object = null)
|
||||
{
|
||||
if (null !== $object) {
|
||||
if ('class' === $constant) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$constant = \get_class($object).'::'.$constant;
|
||||
}
|
||||
|
||||
|
||||
@@ -387,13 +387,8 @@ function twig_escape_filter(Environment $env, $string, $strategy = 'html', $char
|
||||
return rawurlencode($string);
|
||||
|
||||
default:
|
||||
static $escapers;
|
||||
|
||||
if (null === $escapers) {
|
||||
$escapers = $env->getExtension(EscaperExtension::class)->getEscapers();
|
||||
}
|
||||
|
||||
if (isset($escapers[$strategy])) {
|
||||
$escapers = $env->getExtension(EscaperExtension::class)->getEscapers();
|
||||
if (array_key_exists($strategy, $escapers)) {
|
||||
return $escapers[$strategy]($env, $string, $charset);
|
||||
}
|
||||
|
||||
|
||||
@@ -91,11 +91,11 @@ final class SandboxExtension extends AbstractExtension
|
||||
}
|
||||
}
|
||||
|
||||
public function checkPropertyAllowed($obj, $method, int $lineno = -1, Source $source = null): void
|
||||
public function checkPropertyAllowed($obj, $property, int $lineno = -1, Source $source = null): void
|
||||
{
|
||||
if ($this->isSandboxed()) {
|
||||
try {
|
||||
$this->policy->checkPropertyAllowed($obj, $method);
|
||||
$this->policy->checkPropertyAllowed($obj, $property);
|
||||
} catch (SecurityNotAllowedPropertyError $e) {
|
||||
$e->setSourceContext($source);
|
||||
$e->setTemplateLine($lineno);
|
||||
|
||||
@@ -183,9 +183,9 @@ class FilesystemLoader implements LoaderInterface
|
||||
}
|
||||
|
||||
try {
|
||||
$this->validateName($name);
|
||||
|
||||
list($namespace, $shortname) = $this->parseName($name);
|
||||
|
||||
$this->validateName($shortname);
|
||||
} catch (LoaderError $e) {
|
||||
if (!$throw) {
|
||||
return null;
|
||||
|
||||
@@ -24,19 +24,20 @@ abstract class CallExpression extends AbstractExpression
|
||||
{
|
||||
$callable = $this->getAttribute('callable');
|
||||
|
||||
$closingParenthesis = false;
|
||||
$isArray = false;
|
||||
if (\is_string($callable) && false === strpos($callable, '::')) {
|
||||
$compiler->raw($callable);
|
||||
} else {
|
||||
list($r, $callable) = $this->reflectCallable($callable);
|
||||
if ($r instanceof \ReflectionMethod && \is_string($callable[0])) {
|
||||
if ($r->isStatic()) {
|
||||
[$r, $callable] = $this->reflectCallable($callable);
|
||||
|
||||
if (\is_string($callable)) {
|
||||
$compiler->raw($callable);
|
||||
} elseif (\is_array($callable) && \is_string($callable[0])) {
|
||||
if (!$r instanceof \ReflectionMethod || $r->isStatic()) {
|
||||
$compiler->raw(sprintf('%s::%s', $callable[0], $callable[1]));
|
||||
} else {
|
||||
$compiler->raw(sprintf('$this->env->getRuntime(\'%s\')->%s', $callable[0], $callable[1]));
|
||||
}
|
||||
} elseif ($r instanceof \ReflectionMethod && $callable[0] instanceof ExtensionInterface) {
|
||||
} elseif (\is_array($callable) && $callable[0] instanceof ExtensionInterface) {
|
||||
$class = \get_class($callable[0]);
|
||||
if (!$compiler->getEnvironment()->hasExtension($class)) {
|
||||
// Compile a non-optimized call to trigger a \Twig\Error\RuntimeError, which cannot be a compile-time error
|
||||
@@ -47,17 +48,11 @@ abstract class CallExpression extends AbstractExpression
|
||||
|
||||
$compiler->raw(sprintf('->%s', $callable[1]));
|
||||
} else {
|
||||
$closingParenthesis = true;
|
||||
$isArray = true;
|
||||
$compiler->raw(sprintf('call_user_func_array($this->env->get%s(\'%s\')->getCallable(), ', ucfirst($this->getAttribute('type')), $this->getAttribute('name')));
|
||||
$compiler->raw(sprintf('$this->env->get%s(\'%s\')->getCallable()', ucfirst($this->getAttribute('type')), $this->getAttribute('name')));
|
||||
}
|
||||
}
|
||||
|
||||
$this->compileArguments($compiler, $isArray);
|
||||
|
||||
if ($closingParenthesis) {
|
||||
$compiler->raw(')');
|
||||
}
|
||||
$this->compileArguments($compiler);
|
||||
}
|
||||
|
||||
protected function compileArguments(Compiler $compiler, $isArray = false): void
|
||||
@@ -244,10 +239,7 @@ abstract class CallExpression extends AbstractExpression
|
||||
|
||||
private function getCallableParameters($callable, bool $isVariadic): array
|
||||
{
|
||||
list($r) = $this->reflectCallable($callable);
|
||||
if (null === $r) {
|
||||
return [[], false];
|
||||
}
|
||||
[$r, , $callableName] = $this->reflectCallable($callable);
|
||||
|
||||
$parameters = $r->getParameters();
|
||||
if ($this->hasNode('node')) {
|
||||
@@ -274,11 +266,6 @@ abstract class CallExpression extends AbstractExpression
|
||||
array_pop($parameters);
|
||||
$isPhpVariadic = true;
|
||||
} else {
|
||||
$callableName = $r->name;
|
||||
if ($r instanceof \ReflectionMethod) {
|
||||
$callableName = $r->getDeclaringClass()->name.'::'.$callableName;
|
||||
}
|
||||
|
||||
throw new \LogicException(sprintf('The last parameter of "%s" for %s "%s" must be an array with default value, eg. "array $arg = []".', $callableName, $this->getAttribute('type'), $this->getAttribute('name')));
|
||||
}
|
||||
}
|
||||
@@ -292,29 +279,41 @@ abstract class CallExpression extends AbstractExpression
|
||||
return $this->reflector;
|
||||
}
|
||||
|
||||
if (\is_array($callable)) {
|
||||
if (!method_exists($callable[0], $callable[1])) {
|
||||
// __call()
|
||||
return [null, []];
|
||||
}
|
||||
$r = new \ReflectionMethod($callable[0], $callable[1]);
|
||||
} elseif (\is_object($callable) && !$callable instanceof \Closure) {
|
||||
$r = new \ReflectionObject($callable);
|
||||
$r = $r->getMethod('__invoke');
|
||||
$callable = [$callable, '__invoke'];
|
||||
} elseif (\is_string($callable) && false !== $pos = strpos($callable, '::')) {
|
||||
$class = substr($callable, 0, $pos);
|
||||
$method = substr($callable, $pos + 2);
|
||||
if (!method_exists($class, $method)) {
|
||||
// __staticCall()
|
||||
return [null, []];
|
||||
}
|
||||
$r = new \ReflectionMethod($callable);
|
||||
$callable = [$class, $method];
|
||||
} else {
|
||||
$r = new \ReflectionFunction($callable);
|
||||
if (\is_string($callable) && false !== $pos = strpos($callable, '::')) {
|
||||
$callable = [substr($callable, 0, $pos), substr($callable, 2 + $pos)];
|
||||
}
|
||||
|
||||
return $this->reflector = [$r, $callable];
|
||||
if (\is_array($callable) && method_exists($callable[0], $callable[1])) {
|
||||
$r = new \ReflectionMethod($callable[0], $callable[1]);
|
||||
|
||||
return $this->reflector = [$r, $callable, $r->class.'::'.$r->name];
|
||||
}
|
||||
|
||||
$checkVisibility = $callable instanceof \Closure;
|
||||
try {
|
||||
$closure = \Closure::fromCallable($callable);
|
||||
} catch (\TypeError $e) {
|
||||
throw new \LogicException(sprintf('Callback for %s "%s" is not callable in the current scope.', $this->getAttribute('type'), $this->getAttribute('name')), 0, $e);
|
||||
}
|
||||
$r = new \ReflectionFunction($closure);
|
||||
|
||||
if (false !== strpos($r->name, '{closure}')) {
|
||||
return $this->reflector = [$r, $callable, 'Closure'];
|
||||
}
|
||||
|
||||
if ($object = $r->getClosureThis()) {
|
||||
$callable = [$object, $r->name];
|
||||
$callableName = (\function_exists('get_debug_type') ? get_debug_type($object) : \get_class($object)).'::'.$r->name;
|
||||
} elseif ($class = $r->getClosureScopeClass()) {
|
||||
$callableName = (\is_array($callable) ? $callable[0] : $class->name).'::'.$r->name;
|
||||
} else {
|
||||
$callable = $callableName = $r->name;
|
||||
}
|
||||
|
||||
if ($checkVisibility && \is_array($callable) && method_exists(...$callable) && !(new \ReflectionMethod(...$callable))->isPublic()) {
|
||||
$callable = $r->getClosure();
|
||||
}
|
||||
|
||||
return $this->reflector = [$r, $callable, $callableName];
|
||||
}
|
||||
}
|
||||
|
||||
+1
-2
@@ -58,7 +58,7 @@ class Parser
|
||||
public function parse(TokenStream $stream, $test = null, bool $dropNeedle = false): ModuleNode
|
||||
{
|
||||
$vars = get_object_vars($this);
|
||||
unset($vars['stack'], $vars['env'], $vars['handlers'], $vars['visitors'], $vars['expressionParser'], $vars['reservedMacroNames']);
|
||||
unset($vars['stack'], $vars['env'], $vars['handlers'], $vars['visitors'], $vars['expressionParser'], $vars['reservedMacroNames'], $vars['varNameSalt']);
|
||||
$this->stack[] = $vars;
|
||||
|
||||
// node visitors
|
||||
@@ -78,7 +78,6 @@ class Parser
|
||||
$this->blockStack = [];
|
||||
$this->importedSymbols = [[]];
|
||||
$this->embeddedTemplates = [];
|
||||
$this->varNameSalt = 0;
|
||||
|
||||
try {
|
||||
$body = $this->subparse($test, $dropNeedle);
|
||||
|
||||
@@ -19,17 +19,27 @@ namespace Twig\Sandbox;
|
||||
interface SecurityPolicyInterface
|
||||
{
|
||||
/**
|
||||
* @param string[] $tags
|
||||
* @param string[] $filters
|
||||
* @param string[] $functions
|
||||
*
|
||||
* @throws SecurityError
|
||||
*/
|
||||
public function checkSecurity($tags, $filters, $functions): void;
|
||||
|
||||
/**
|
||||
* @param object $obj
|
||||
* @param string $method
|
||||
*
|
||||
* @throws SecurityNotAllowedMethodError
|
||||
*/
|
||||
public function checkMethodAllowed($obj, $method): void;
|
||||
|
||||
/**
|
||||
* @param object $obj
|
||||
* @param string $property
|
||||
*
|
||||
* @throws SecurityNotAllowedPropertyError
|
||||
*/
|
||||
public function checkPropertyAllowed($obj, $method): void;
|
||||
public function checkPropertyAllowed($obj, $property): void;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user