Passed
Push — master ( 8a1e6f...7a5ba5 )
by Christian
10:28 queued 12s
created

ConfigReader::getCardFlag()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 12
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 6
nc 3
nop 1
dl 0
loc 12
rs 10
c 0
b 0
f 0
1
<?php declare(strict_types=1);
2
3
namespace Shopware\Core\System\SystemConfig\Util;
4
5
use Shopware\Core\Framework\Bundle;
6
use Shopware\Core\Framework\Util\XmlReader;
7
use Shopware\Core\System\SystemConfig\Exception\BundleConfigNotFoundException;
8
9
class ConfigReader extends XmlReader
10
{
11
    private const FALLBACK_LOCALE = 'en-GB';
12
13
    /**
14
     * @var string
15
     */
16
    protected $xsdFile = __DIR__ . '/../Schema/config.xsd';
17
18
    /**
19
     * @throws BundleConfigNotFoundException
20
     */
21
    public function getConfigFromBundle(Bundle $bundle, ?string $bundleConfigName = null): array
22
    {
23
        if ($bundleConfigName === null) {
24
            $bundleConfigName = 'Resources/config/config.xml';
25
        } else {
26
            $bundleConfigName = 'Resources/config/' . preg_replace('/\\.xml$/i', '', $bundleConfigName) . '.xml';
27
        }
28
        $configPath = $bundle->getPath() . '/' . ltrim($bundleConfigName, '/');
29
30
        if (!is_file($configPath)) {
31
            throw new BundleConfigNotFoundException($bundleConfigName, $bundle->getName());
32
        }
33
34
        return $this->read($configPath);
35
    }
36
37
    /**
38
     * This method is the main entry point to parse a xml file.
39
     */
40
    protected function parseFile(\DOMDocument $xml): array
41
    {
42
        return $this->getCardDefinitions($xml);
43
    }
44
45
    private function getCardDefinitions(\DOMDocument $xml): array
46
    {
47
        $cardDefinitions = [];
48
49
        foreach ($xml->getElementsByTagName('card') as $index => $element) {
50
            $cardDefinitions[] = [
51
                'title' => $this->getCardTitles($element),
52
                'name' => $this->getCardName($element),
53
                'elements' => $this->getElements($element),
54
            ];
55
56
            if ($this->getCardFlag($element) !== null) {
57
                $cardDefinitions[$index]['flag'] = $this->getCardFlag($element);
58
            }
59
        }
60
61
        return $cardDefinitions;
62
    }
63
64
    private function getCardTitles(\DOMElement $element): array
65
    {
66
        $titles = [];
67
        foreach ($element->getElementsByTagName('title') as $title) {
68
            $titles[$this->getLocaleCodeFromElement($title)] = $title->nodeValue;
69
        }
70
71
        return $titles;
72
    }
73
74
    private function getElements(\DOMElement $xml): array
75
    {
76
        $elements = [];
77
        $count = 0;
78
        /** @var \DOMElement $element */
79
        foreach (static::getAllChildren($xml) as $element) {
80
            $nodeName = $element->nodeName;
81
            if ($nodeName === 'title' || $nodeName === 'name' || $nodeName === 'flag') {
82
                continue;
83
            }
84
85
            $elements[$count] = $this->elementToArray($element);
86
            ++$count;
87
        }
88
89
        return $elements;
90
    }
91
92
    private function getCardName(\DOMElement $element): ?string
93
    {
94
        foreach ($element->getElementsByTagName('name') as $name) {
95
            $parentNode = $name->parentNode;
96
            if (($parentNode !== null) && $parentNode->nodeName !== 'card') {
97
                continue;
98
            }
99
100
            return $name->nodeValue;
101
        }
102
103
        return null;
104
    }
105
106
    private function getCardFlag(\DOMElement $element): ?string
107
    {
108
        foreach ($element->getElementsByTagName('flag') as $flag) {
109
            $parentNode = $flag->parentNode;
110
            if (($parentNode !== null) && $parentNode->nodeName !== 'card') {
111
                continue;
112
            }
113
114
            return $flag->nodeValue;
115
        }
116
117
        return null;
118
    }
119
120
    private function elementToArray(\DOMElement $element): array
121
    {
122
        $options = static::getAllChildren($element);
123
124
        if ($element->nodeName === 'component') {
125
            return $this->getElementDataForComponent($element, $options);
126
        }
127
128
        return $this->getElementDataForInputField($element, $options);
129
    }
130
131
    /**
132
     * @param array<\DOMElement> $options
133
     */
134
    private function getElementDataForComponent(\DOMElement $element, array $options): array
135
    {
136
        $elementData = [
137
            'componentName' => $element->getAttribute('name'),
138
        ];
139
140
        return $this->setOptionsToElementData($options, $elementData);
141
    }
142
143
    private function getElementDataForInputField(\DOMElement $element, array $options): array
144
    {
145
        $swFieldType = $element->getAttribute('type') ?: 'text';
146
147
        $elementData = [
148
            'type' => $swFieldType,
149
        ];
150
151
        return $this->setOptionsToElementData($options, $elementData);
152
    }
153
154
    /**
155
     * @param array<\DOMElement> $options
156
     */
157
    private function setOptionsToElementData(array $options, array $elementData): array
158
    {
159
        foreach ($options as $option) {
160
            if ($this->isTranslateAbleOption($option)) {
161
                $elementData[$option->nodeName][$this->getLocaleCodeFromElement($option)] = $option->nodeValue;
162
163
                continue;
164
            }
165
166
            if ($this->isBoolOption($option)) {
167
                $elementData[$option->nodeName] = filter_var($option->nodeValue, FILTER_VALIDATE_BOOLEAN);
168
169
                continue;
170
            }
171
172
            if ($this->elementIsOptions($option)) {
173
                $elementData['options'] = $this->optionsToArray($option);
174
175
                continue;
176
            }
177
178
            $elementData[$option->nodeName] = $option->nodeValue;
179
        }
180
181
        return $elementData;
182
    }
183
184
    private function optionsToArray(\DOMElement $element): array
185
    {
186
        $options = [];
187
188
        foreach ($element->getElementsByTagName('option') as $option) {
189
            /* @var \DOMElement $option */
190
            $idTag = $option->getElementsByTagName('id')->item(0);
191
            if ($idTag === null) {
192
                continue;
193
            }
194
195
            $options[] = [
196
                'id' => $idTag->nodeValue,
197
                'name' => $this->getOptionLabels($option),
198
            ];
199
        }
200
201
        return $options;
202
    }
203
204
    private function getOptionLabels(\DOMElement $option): array
205
    {
206
        $optionLabels = [];
207
208
        foreach ($option->getElementsByTagName('name') as $label) {
209
            $optionLabels[$this->getLocaleCodeFromElement($label)] = $label->nodeValue;
210
        }
211
212
        return $optionLabels;
213
    }
214
215
    private function getLocaleCodeFromElement(\DOMElement $element): string
216
    {
217
        return $element->getAttribute('lang') ?: self::FALLBACK_LOCALE;
218
    }
219
220
    private function isTranslateAbleOption(\DOMElement $option): bool
221
    {
222
        return \in_array($option->nodeName, ['label', 'placeholder', 'helpText'], true);
223
    }
224
225
    private function isBoolOption(\DOMElement $option): bool
226
    {
227
        return \in_array($option->nodeName, ['copyable', 'disabled', 'required'], true);
228
    }
229
230
    private function elementIsOptions(\DOMElement $option): bool
231
    {
232
        return $option->nodeName === 'options';
233
    }
234
}
235