1<?php
2
3/*
4 * This file is part of Twig.
5 *
6 * (c) Fabien Potencier
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Twig\Node\Expression\Binary;
13
14use Twig\Compiler;
15use Twig\Error\SyntaxError;
16use Twig\Extension\SandboxExtension;
17use Twig\Node\Expression\AbstractExpression;
18use Twig\Node\Expression\ArrayExpression;
19use Twig\Node\Expression\Variable\ContextVariable;
20use Twig\Node\Node;
21
22/**
23 * @internal
24 */
25class ObjectDestructuringSetBinary extends AbstractBinary
26{
27    /** @var list<array{property: string, variable: string}> */
28    private array $mappings = [];
29
30    /**
31     * @param ArrayExpression    $left  The array expression containing object/mapping destructuring properties
32     * @param AbstractExpression $right The expression providing values for assignment
33     */
34    public function __construct(Node $left, Node $right, int $lineno)
35    {
36        if (!$left instanceof ArrayExpression) {
37            throw new \LogicException('Left side must be ArrayExpression for object/mapping destructuring.');
38        }
39        foreach ($left->getKeyValuePairs() as $pair) {
40            if (!$pair['value'] instanceof ContextVariable) {
41                throw new SyntaxError(\sprintf('Cannot assign to "%s", only variables can be assigned in object/mapping destructuring.', $pair['value']::class), $lineno);
42            }
43
44            $this->mappings[] = [
45                'property' => $pair['key']->getAttribute('value'),
46                'variable' => $pair['value']->getAttribute('name'),
47            ];
48        }
49
50        parent::__construct($left, $right, $lineno);
51    }
52
53    public function compile(Compiler $compiler): void
54    {
55        $compiler->addDebugInfo($this);
56        $compiler->raw('[');
57        foreach ($this->mappings as $i => $mapping) {
58            if ($i) {
59                $compiler->raw(', ');
60            }
61            $compiler->raw('$context[')->repr($mapping['variable'])->raw(']');
62        }
63        $compiler->raw('] = [');
64        foreach ($this->mappings as $i => $mapping) {
65            if ($i) {
66                $compiler->raw(', ');
67            }
68            $compiler->raw('CoreExtension::getAttribute($this->env, $this->source, ')->subcompile($this->getNode('right'))->raw(', ')->repr($mapping['property'])->raw(', [], \\Twig\\Template::ANY_CALL, false, false, ')->repr($compiler->getEnvironment()->hasExtension(SandboxExtension::class))->raw(', ')->repr($this->getNode('right')->getTemplateLine())->raw(')');
69        }
70        $compiler->raw(']');
71    }
72
73    public function operator(Compiler $compiler): Compiler
74    {
75        return $compiler->raw('=');
76    }
77}
78