Completed
Push — master ( 1ece6c...656998 )
by Jan Philipp
13s queued 11s
created

XmlConfigFileLoader::extractNodes()   A

Complexity

Conditions 5
Paths 6

Size

Total Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 16
rs 9.4222
c 0
b 0
f 0
cc 5
nc 6
nop 2
1
<?php declare(strict_types=1);
2
3
namespace Shopware\Psh\Config;
4
5
use DOMElement;
6
use DOMXPath;
7
use Symfony\Component\Config\Util\XmlUtils;
8
9
/**
10
 * Load the config data from an xml file
11
 */
12
class XmlConfigFileLoader extends ConfigFileLoader
13
{
14
    const NODE_HEADER = 'header';
15
16
    const NODE_PLACEHOLDER = 'placeholder';
17
18
    const NODE_PLACEHOLDER_DYNAMIC = 'dynamic';
19
20
    const NODE_PLACEHOLDER_CONST = 'const';
21
22
    const NODE_PLACEHOLDER_DOTENV = 'dotenv';
23
24
    const NODE_PATH = 'path';
25
26
    const NODE_ENVIRONMENT = 'environment';
27
28
    const NODE_TEMPLATE = 'template';
29
30
    const NODE_TEMPLATE_SOURCE = 'source';
31
32
    const NODE_TEMPLATE_DESTINATION = 'destination';
33
34
    /**
35
     * @var ConfigBuilder
36
     */
37
    private $configBuilder;
38
39
    /**
40
     * @var string
41
     */
42
    private $applicationRootDirectory;
43
44
    /**
45
     * @param ConfigBuilder $configBuilder
46
     * @param string $applicationRootDirectory
47
     */
48
    public function __construct(ConfigBuilder $configBuilder, string $applicationRootDirectory)
49
    {
50
        $this->configBuilder = $configBuilder;
51
        $this->applicationRootDirectory = $applicationRootDirectory;
52
    }
53
54
    /**
55
     * @inheritdoc
56
     */
57
    public function isSupported(string $file): bool
58
    {
59
        return in_array(pathinfo($file, PATHINFO_BASENAME), ['.psh.xml', '.psh.xml.dist', '.psh.xml.override'], true);
60
    }
61
62
    /**
63
     * @inheritdoc
64
     */
65 View Code Duplication
    public function load(string $file, array $params): Config
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
66
    {
67
        $pshConfigNode = $this->loadXmlRoot($file);
68
        $this->configBuilder->start();
69
70
        $headers = $this->extractNodes(self::NODE_HEADER, $pshConfigNode);
71
72
        foreach ($headers as $header) {
73
            $this->configBuilder
74
                ->setHeader($header->nodeValue);
75
        }
76
77
        $this->setConfigData($file, $pshConfigNode);
78
79
        $environments = $this->extractNodes(self::NODE_ENVIRONMENT, $pshConfigNode);
80
81
        foreach ($environments as $node) {
82
            $this->configBuilder->start($node->getAttribute('name'));
83
            $this->setConfigData($file, $node);
84
        }
85
86
        return $this->configBuilder
87
            ->create($params);
88
    }
89
90
    /**
91
     * @param string $file
92
     * @param array $pshConfigNode
93
     */
94
    private function setConfigData(string $file, DOMElement $pshConfigNode)
95
    {
96
        $this->configBuilder->setCommandPaths(
97
            $this->extractCommandPaths($file, $pshConfigNode)
98
        );
99
100
        $placeholders = $this->extractNodes(self::NODE_PLACEHOLDER, $pshConfigNode);
101
102
        foreach ($placeholders as $placeholder) {
103
            $this->extractPlaceholders($file, $placeholder);
104
        }
105
106
        $this->configBuilder->setTemplates(
107
            $this->extractTemplates($file, $pshConfigNode)
108
        );
109
    }
110
111
    /**
112
     * @param string $key
113
     * @param DOMElement $parent
114
     * @return DOMElement[]
115
     */
116
    private function extractNodes(string $key, DOMElement $parent): array
117
    {
118
        $nodes = [];
119
120
        foreach ($parent->childNodes as $childNode) {
121
            if ($childNode instanceof DOMElement && $childNode->localName === $key) {
122
                $nodes[] = $childNode;
123
            }
124
        }
125
126
        if (count($nodes) === 0) {
127
            return [];
128
        }
129
130
        return $nodes;
131
    }
132
133
    /**
134
     * @param string $file
135
     * @param $pshConfigNode
136
     * @return array
137
     */
138
    private function extractCommandPaths(string $file, DOMElement $pshConfigNode): array
139
    {
140
        $pathNodes = $this->extractNodes(self::NODE_PATH, $pshConfigNode);
141
142
        return array_map(function (DOMElement $path) use ($file) {
143
            return $this->fixPath($this->applicationRootDirectory, $path->nodeValue, $file);
144
        }, $pathNodes);
145
    }
146
147
    /**
148
     * @param string $file
149
     * @param array $pshConfigNodes
150
     * @return array
151
     */
152
    private function extractTemplates(string $file, DOMElement $pshConfigNodes): array
153
    {
154
        $templates = $this->extractNodes(self::NODE_TEMPLATE, $pshConfigNodes);
155
156
        return array_map(function (DOMElement $template) use ($file) {
157
            return [
158
                'source' => $this->fixPath(
159
                    $this->applicationRootDirectory,
160
                    $template->getAttribute(self::NODE_TEMPLATE_SOURCE),
161
                    $file
162
                ),
163
                'destination' => $this->makeAbsolutePath(
164
                    $file,
165
                    $template->getAttribute(self::NODE_TEMPLATE_DESTINATION)
166
                )
167
            ];
168
        }, $templates);
169
    }
170
171
    /**
172
     * @param DOMElement $placeholder
173
     */
174
    private function extractPlaceholders(string $file, DOMElement $placeholder)
175
    {
176
        foreach ($this->extractNodes(self::NODE_PLACEHOLDER_DYNAMIC, $placeholder) as $dynamic) {
177
            $this->configBuilder->setDynamicVariable($dynamic->getAttribute('name'), $dynamic->nodeValue);
178
        }
179
180
        foreach ($this->extractNodes(self::NODE_PLACEHOLDER_CONST, $placeholder) as $const) {
181
            $this->configBuilder->setConstVariable($const->getAttribute('name'), $const->nodeValue);
182
        }
183
184
        foreach ($this->extractNodes(self::NODE_PLACEHOLDER_DOTENV, $placeholder) as $dotenv) {
185
            $this->configBuilder->setDotenvPath($this->fixPath($this->applicationRootDirectory, $dotenv->nodeValue, $file));
186
        }
187
    }
188
189
    /**
190
     * @param string $file
191
     * @return DOMElement
192
     */
193
    private function loadXmlRoot(string $file): DOMElement
194
    {
195
        $xml = XmlUtils::loadFile($file, __DIR__ . '/../../resource/config.xsd');
196
        $xPath = new DOMXPath($xml);
197
198
        /** @var \DOMNodeList $pshConfigNodes */
199
        $pshConfigNodes = $xPath->query('//psh');
200
201
        return $pshConfigNodes[0];
202
    }
203
}
204