XmlMerger::addXml()   A
last analyzed

Complexity

Conditions 4
Paths 4

Size

Total Lines 18
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 4.3244

Importance

Changes 0
Metric Value
cc 4
eloc 11
nc 4
nop 1
dl 0
loc 18
ccs 8
cts 11
cp 0.7272
crap 4.3244
rs 9.9
c 0
b 0
f 0
1
<?php
2
declare(strict_types=1);
3
4
5
namespace Xervice\DataProvider\Business\Model\Parser;
6
7
use Xervice\DataProvider\Business\Model\DataProvider\DataProviderInterface;
8
9
class XmlMerger implements XmlMergerInterface
10
{
11
    /**
12
     * @var array
13
     */
14
    private $mergedXml = [];
15
16
    /**
17
     * @var string
18
     */
19
    private $namespace;
20
21
    /**
22
     * @param string $namespace
23
     */
24 10
    public function __construct(string $namespace)
25
    {
26 10
        $this->namespace = $namespace;
27 10
    }
28
29
    /**
30
     * @param string $xmlContent
31
     */
32 10
    public function addXml(string $xmlContent): void
33
    {
34 10
        $xml = \simplexml_load_string($xmlContent);
35
36 10
        foreach ($xml->DataProvider as $xmlDataProvider) {
37 10
            $dataProvider = $this->parseDataProvider($xmlDataProvider);
0 ignored issues
show
Bug introduced by
It seems like $xmlDataProvider can also be of type null; however, parameter $xmlDataProvider of Xervice\DataProvider\Bus...er::parseDataProvider() does only seem to accept SimpleXMLElement, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

37
            $dataProvider = $this->parseDataProvider(/** @scrutinizer ignore-type */ $xmlDataProvider);
Loading history...
38
39 10
            foreach ($xmlDataProvider->DataElement as $element) {
40 10
                $fieldName = (string)$element->attributes()['name'];
0 ignored issues
show
Bug introduced by
The method attributes() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

40
                $fieldName = (string)$element->/** @scrutinizer ignore-call */ attributes()['name'];

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
41
42 10
                if (isset($this->mergedXml[$dataProvider]['elements'][$fieldName])) {
43
                    $this->mergedXml[$dataProvider]['elements'][$fieldName] = array_merge(
44
                        $this->mergedXml[$dataProvider]['elements'][$fieldName],
45
                        $this->getElementData($element, $this->mergedXml[$dataProvider])
0 ignored issues
show
Bug introduced by
It seems like $element can also be of type null; however, parameter $element of Xervice\DataProvider\Bus...erger::getElementData() does only seem to accept SimpleXMLElement, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

45
                        $this->getElementData(/** @scrutinizer ignore-type */ $element, $this->mergedXml[$dataProvider])
Loading history...
46
                    );
47
                }
48
                else {
49 10
                    $this->mergedXml[$dataProvider]['elements'][$fieldName] = $this->getElementData($element, $this->mergedXml[$dataProvider]);
50
                }
51
            }
52
        }
53
54
55 10
    }
56
57
    /**
58
     * @return array
59
     */
60 10
    public function getData(): array
61
    {
62 10
        return $this->mergedXml;
63
    }
64
65
    /**
66
     * @param \SimpleXMLElement $xmlDataProvider
67
     *
68
     * @return string
69
     */
70 10
    private function parseDataProvider(\SimpleXMLElement $xmlDataProvider): string
71
    {
72 10
        $dataProvider = (string)$xmlDataProvider->attributes()['name'];
73 10
        if (!isset($this->mergedXml[$dataProvider])) {
74 10
            $this->mergedXml[$dataProvider] = [
75 10
                'configs' => [
76 10
                    'convertUnderlines' => (bool)$xmlDataProvider->attributes()['ConvertUnderlines'] ?? false,
77 10
                    'deprecated' => (bool)$xmlDataProvider->attributes()['deprecated'] ?? false
78
                ],
79
                'elements' => []
80
            ];
81
        }
82
83 10
        return $dataProvider;
84
    }
85
86
    /**
87
     * @param \SimpleXMLElement $element
88
     *
89
     * @return array
90
     */
91 10
    private function getElementData(\SimpleXMLElement $element, array $dataProvider): array
92
    {
93 10
        $type = (string)$element->attributes()['type'];
94
95 10
        $type = ($type !== 'double') ? $type : 'float';
96
97 10
        $allowNull = (bool)$element->attributes()['allownull'];
98 10
        $default = (string)$element->attributes()['default'];
99
100 10
        if ($type === 'object') {
101 10
            $allowNull = true;
102 10
            $default = null;
103
        }
104
105
        $data = [
106 10
            'name' => (string)$element->attributes()['name'],
107 10
            'allownull' => $allowNull,
108 10
            'default' => $default,
109 10
            'type' => $this->getVariableType($type),
110 10
            'is_collection' => $this->isCollection($type),
111 10
            'is_dataprovider' => $this->isDataProvider($type),
112 10
            'isCamelCase' => $dataProvider['configs']['convertUnderlines']
113
        ];
114
115 10
        $singleton = (string)$element->attributes()['singleton'];
116 10
        if ($singleton !== '') {
117 10
            $data['singleton'] = (string)$element->attributes()['singleton'];
118 10
            $data['singleton_type'] = $this->getSingleVariableType($type);
119
        }
120
121 10
        return $data;
122
    }
123
124
    /**
125
     * @param string $type
126
     *
127
     * @return bool
128
     */
129 10
    private function isDataProvider(string $type): bool
130
    {
131 10
        return (!$this->isSimpleType($type) && !$this->isCollection($type));
132
    }
133
134
    /**
135
     * @param string $type
136
     *
137
     * @return bool
138
     */
139 10
    private function isCollection(string $type): bool
140
    {
141 10
        return strpos($type, '[]') !== false;
142
    }
143
144
    /**
145
     * @param string $type
146
     *
147
     * @return bool
148
     */
149 10
    private function isSimpleType(string $type): bool
150
    {
151
        $validTypes = [
152 10
            'int',
153
            'string',
154
            'bool',
155
            'double',
156
            'float',
157
            'array',
158
            'object',
159
            'DataProviderInterface',
160
            'DataProviderInterface[]',
161
            DataProviderInterface::class,
162
            DataProviderInterface::class . '[]'
163
        ];
164
165 10
        return \in_array($type, $validTypes, true);
166
    }
167
168
    /**
169
     * @param string $type
170
     *
171
     * @return string
172
     */
173 10
    private function getVariableType(string $type): string
174
    {
175 10
        if (!$this->isSimpleType($type)) {
176 10
            $namespace = ltrim($this->namespace, '\\');
177 10
            $type =  '\\' . $namespace .'\\' . $type . 'DataProvider';
178
        }
179
180 10
        if ($type === 'DataProviderInterface') {
181 10
            $type = '\\' . DataProviderInterface::class;
182
        }
183
184 10
        if ($type === 'DataProviderInterface[]') {
185 10
            $type = '\\' . DataProviderInterface::class . '[]';
186
        }
187
188 10
        if (strpos($type, '[]') !== false) {
189 10
            $type = str_replace('[]', '', $type) . '[]';
190
        }
191
192 10
        return $type;
193
    }
194
195
    /**
196
     * @param string $type
197
     *
198
     * @return string
199
     */
200 10
    private function getSingleVariableType(string $type): string
201
    {
202 10
        if (!$this->isSimpleType($type)) {
203 10
            $namespace = ltrim($this->namespace, '\\');
204 10
            $type = '\\' . $namespace .'\\' . $type . 'DataProvider';
205
        }
206
207 10
        if ($type === 'DataProviderInterface') {
208
            $type = '\\' . DataProviderInterface::class;
209
        }
210
211 10
        if ($type === 'DataProviderInterface[]') {
212 10
            $type = '\\' . DataProviderInterface::class . '[]';
213
        }
214
215 10
        if (strpos($type, '[]') !== false) {
216 10
            $type = str_replace('[]', '', $type);
217
        }
218
219 10
        return $type;
220
    }
221
}
222