1<?php
2
3namespace PrestaShop\TranslationToolsBundle\Translation\Extractor\Visitor\Translation;
4
5use PhpParser\Node;
6use PhpParser\Node\Scalar\String_;
7use PhpParser\NodeVisitorAbstract;
8use PrestaShop\TranslationToolsBundle\Translation\Extractor\Util\TranslationCollection;
9
10/**
11 * This class looks for arrays like this:
12 *
13 * ```php
14 * [
15 *     'key' => 'This text is lonely',
16 *     'parameters' => [],
17 *     'domain' => 'Admin.Notifications.Error',
18 * ]
19 *
20 * [
21 *     'key' => 'This text is lonely',
22 *     'domain' => 'Admin.Notifications.Error',
23 * ]
24 * ```
25 *
26 * Parameters can be in any order
27 */
28class ArrayTranslationDefinition extends AbstractTranslationNodeVisitor
29{
30    public function leaveNode(Node $node)
31    {
32        $this->translations->add($this->extractFrom($node));
33    }
34
35    /**
36     * @param Node $node
37     *
38     * @return array Array of translations to add
39     */
40    public function extractFrom(Node $node)
41    {
42        if (!$this->appliesFor($node)) {
43            return [];
44        }
45
46        /** @var $node Node\Expr\Array_ */
47
48        $translation = [
49            'source' => null,
50            'domain' => null,
51            'line'   => $node->getAttribute('startLine')
52        ];
53
54        $parametersFound = false;
55        foreach ($node->items as $item) {
56            if (!($item instanceof Node\Expr\ArrayItem && $item->key instanceof String_)) {
57                return [];
58            }
59
60            switch ($item->key->value) {
61                case 'key':
62                    if (!$item->value instanceof String_) {
63                        return [];
64                    }
65                    $translation['source'] = $item->value->value;
66                    continue 2;
67
68                case 'domain':
69                    if (!$item->value instanceof String_) {
70                        return [];
71                    }
72                    $translation['domain'] = $item->value->value;
73                    continue 2;
74
75                case 'parameters':
76                    $parametersFound = true;
77                    continue 2;
78            }
79
80            // break if the key isn't one of the three above
81            return [];
82        }
83
84        if ($translation['source'] === null
85            || $translation['domain'] === null
86            || (count($node->items) === 3 && !$parametersFound)
87        ) {
88            return [];
89        }
90
91        return [$translation];
92    }
93
94    /**
95     * @param Node $node
96     *
97     * @return bool
98     */
99    private function appliesFor(Node $node)
100    {
101        return (
102            $node instanceof Node\Expr\Array_
103            && (in_array(count($node->items), [2, 3]))
104        );
105    }
106}
107