blob: e6a75ce940437fe4ab94bf0576d536a2c7b8b429 [file] [log] [blame]
Matthias Andreas Benkard12a57352021-12-28 18:02:04 +01001<?php
2
3/*
4 * This file is part of Twig.
5 *
6 * (c) Fabien Potencier
7 * (c) Armin Ronacher
8 *
9 * For the full copyright and license information, please view the LICENSE
10 * file that was distributed with this source code.
11 */
12
13namespace Twig\Node\Expression;
14
15use Twig\Compiler;
16use Twig\Extension\SandboxExtension;
17use Twig\Template;
18
19class GetAttrExpression extends AbstractExpression
20{
21 public function __construct(AbstractExpression $node, AbstractExpression $attribute, ?AbstractExpression $arguments, string $type, int $lineno)
22 {
23 $nodes = ['node' => $node, 'attribute' => $attribute];
24 if (null !== $arguments) {
25 $nodes['arguments'] = $arguments;
26 }
27
28 parent::__construct($nodes, ['type' => $type, 'is_defined_test' => false, 'ignore_strict_check' => false, 'optimizable' => true], $lineno);
29 }
30
31 public function compile(Compiler $compiler): void
32 {
33 $env = $compiler->getEnvironment();
34
35 // optimize array calls
36 if (
37 $this->getAttribute('optimizable')
38 && (!$env->isStrictVariables() || $this->getAttribute('ignore_strict_check'))
39 && !$this->getAttribute('is_defined_test')
40 && Template::ARRAY_CALL === $this->getAttribute('type')
41 ) {
42 $var = '$'.$compiler->getVarName();
43 $compiler
44 ->raw('(('.$var.' = ')
45 ->subcompile($this->getNode('node'))
46 ->raw(') && is_array(')
47 ->raw($var)
48 ->raw(') || ')
49 ->raw($var)
50 ->raw(' instanceof ArrayAccess ? (')
51 ->raw($var)
52 ->raw('[')
53 ->subcompile($this->getNode('attribute'))
54 ->raw('] ?? null) : null)')
55 ;
56
57 return;
58 }
59
60 $compiler->raw('twig_get_attribute($this->env, $this->source, ');
61
62 if ($this->getAttribute('ignore_strict_check')) {
63 $this->getNode('node')->setAttribute('ignore_strict_check', true);
64 }
65
66 $compiler
67 ->subcompile($this->getNode('node'))
68 ->raw(', ')
69 ->subcompile($this->getNode('attribute'))
70 ;
71
72 if ($this->hasNode('arguments')) {
73 $compiler->raw(', ')->subcompile($this->getNode('arguments'));
74 } else {
75 $compiler->raw(', []');
76 }
77
78 $compiler->raw(', ')
79 ->repr($this->getAttribute('type'))
80 ->raw(', ')->repr($this->getAttribute('is_defined_test'))
81 ->raw(', ')->repr($this->getAttribute('ignore_strict_check'))
82 ->raw(', ')->repr($env->hasExtension(SandboxExtension::class))
83 ->raw(', ')->repr($this->getNode('node')->getTemplateLine())
84 ->raw(')')
85 ;
86 }
87}