GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — master ( ceff26...ceffc9 )
by Freek
01:09
created

ArrayToXml::__construct()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 15
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 15
rs 9.4285
cc 3
eloc 8
nc 2
nop 5
1
<?php
2
3
namespace Spatie\ArrayToXml;
4
5
use DOMElement;
6
use DOMDocument;
7
use DOMException;
8
9
class ArrayToXml
10
{
11
    /**
12
     * The root DOM Document.
13
     *
14
     * @var \DOMDocument
15
     */
16
    protected $document;
17
18
    /**
19
     * Set to enable replacing space with underscore.
20
     *
21
     * @var bool
22
     */
23
    protected $replaceSpacesByUnderScoresInKeyNames = true;
24
25
    /**
26
     * Construct a new instance.
27
     *
28
     * @param string[]     $array
29
     * @param string|array $rootElement
30
     * @param bool         $replaceSpacesByUnderScoresInKeyNames
31
     * @param string       $xmlEncoding
32
     * @param string       $xmlVersion
33
     *
34
     * @throws DOMException
35
     */
36
    public function __construct(array $array, $rootElement = '', $replaceSpacesByUnderScoresInKeyNames = true, $xmlEncoding = null, $xmlVersion = '1.0')
37
    {
38
        $this->document = new DOMDocument($xmlVersion, $xmlEncoding);
39
        $this->replaceSpacesByUnderScoresInKeyNames = $replaceSpacesByUnderScoresInKeyNames;
40
41
        if ($this->isArrayAllKeySequential($array) && ! empty($array)) {
42
            throw new DOMException('Invalid Character Error');
43
        }
44
45
        $root = $this->createRootElement($rootElement);
46
47
        $this->document->appendChild($root);
48
49
        $this->convertElement($root, $array);
50
    }
51
52
    /**
53
     * Convert the given array to an xml string.
54
     *
55
     * @param string[] $array
56
     * @param string   $rootElementName
57
     * @param bool     $replaceSpacesByUnderScoresInKeyNames
58
     * @param string   $xmlEncoding
59
     * @param string   $xmlVersion
60
     *
61
     * @return string
62
     */
63
    public static function convert(array $array, $rootElementName = '', $replaceSpacesByUnderScoresInKeyNames = true, $xmlEncoding = null, $xmlVersion = '1.0')
64
    {
65
        $converter = new static($array, $rootElementName, $replaceSpacesByUnderScoresInKeyNames, $xmlEncoding, $xmlVersion);
66
67
        return $converter->toXml();
68
    }
69
70
    /**
71
     * Return as XML.
72
     *
73
     * @return string
74
     */
75
    public function toXml()
76
    {
77
        return $this->document->saveXML();
78
    }
79
80
    /**
81
     * Return as DOM object.
82
     *
83
     * @return DOMDocument
84
     */
85
    public function toDom()
86
    {
87
        return $this->document;
88
    }
89
90
    /**
91
     * Parse individual element.
92
     *
93
     * @param \DOMElement     $element
94
     * @param string|string[] $value
95
     */
96
    private function convertElement(DOMElement $element, $value)
97
    {
98
        $sequential = $this->isArrayAllKeySequential($value);
99
100
        if (! is_array($value)) {
101
            $element->nodeValue = htmlspecialchars($value);
102
103
            return;
104
        }
105
106
        foreach ($value as $key => $data) {
107
            if (! $sequential) {
108
                if (($key === '_attributes') || ($key === '@attributes')) {
109
                    $this->addAttributes($element, $data);
110
                } elseif ((($key === '_value') || ($key === '@value')) && is_string($data)) {
111
                    $element->nodeValue = htmlspecialchars($data);
112
                } else {
113
                    $this->addNode($element, $key, $data);
114
                }
115
            } elseif (is_array($data)) {
116
                $this->addCollectionNode($element, $data);
117
            } else {
118
                $this->addSequentialNode($element, $data);
119
            }
120
        }
121
    }
122
123
    /**
124
     * Add node.
125
     *
126
     * @param \DOMElement     $element
127
     * @param string          $key
128
     * @param string|string[] $value
129
     */
130
    protected function addNode(DOMElement $element, $key, $value)
131
    {
132
        if ($this->replaceSpacesByUnderScoresInKeyNames) {
133
            $key = str_replace(' ', '_', $key);
134
        }
135
136
        $child = $this->document->createElement($key);
137
        $element->appendChild($child);
138
        $this->convertElement($child, $value);
139
    }
140
141
    /**
142
     * Add collection node.
143
     *
144
     * @param \DOMElement     $element
145
     * @param string|string[] $value
146
     *
147
     * @internal param string $key
148
     */
149
    protected function addCollectionNode(DOMElement $element, $value)
150
    {
151
        if ($element->childNodes->length == 0) {
152
            $this->convertElement($element, $value);
153
154
            return;
155
        }
156
157
        $child = $element->cloneNode();
158
        $element->parentNode->appendChild($child);
159
        $this->convertElement($child, $value);
0 ignored issues
show
Compatibility introduced by
$child of type object<DOMNode> is not a sub-type of object<DOMElement>. It seems like you assume a child class of the class DOMNode to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
160
    }
161
162
    /**
163
     * Add sequential node.
164
     *
165
     * @param \DOMElement     $element
166
     * @param string|string[] $value
167
     *
168
     * @internal param string $key
169
     */
170
    protected function addSequentialNode(DOMElement $element, $value)
171
    {
172
        if (empty($element->nodeValue)) {
173
            $element->nodeValue = htmlspecialchars($value);
174
175
            return;
176
        }
177
178
        $child = $element->cloneNode();
179
        $child->nodeValue = htmlspecialchars($value);
180
        $element->parentNode->appendChild($child);
181
    }
182
183
    /**
184
     * Check if array are all sequential.
185
     *
186
     * @param array|string $value
187
     *
188
     * @return bool
189
     */
190
    protected function isArrayAllKeySequential($value)
191
    {
192
        if (! is_array($value)) {
193
            return false;
194
        }
195
196
        if (count($value) <= 0) {
197
            return true;
198
        }
199
200
        return array_unique(array_map('is_int', array_keys($value))) === [true];
201
    }
202
203
    /**
204
     * Add attributes.
205
     *
206
     * @param \DOMElement $element
207
     * @param string[]    $data
208
     */
209
    protected function addAttributes($element, $data)
210
    {
211
        foreach ($data as $attrKey => $attrVal) {
212
            $element->setAttribute($attrKey, $attrVal);
213
        }
214
    }
215
216
    /**
217
     * Create the root element.
218
     *
219
     * @param  string|array $rootElement
220
     * @return DOMElement
221
     */
222
    protected function createRootElement($rootElement)
223
    {
224
        $rootElementName = is_array($rootElement)
225
            ? $rootElement['rootElementName'] ?? ''
226
            : $rootElement;
227
228
        $element = $this->document->createElement($rootElementName == '' ? 'root' : $rootElementName);
229
230
        if (is_array($rootElement)) {
231
            foreach ($rootElement as $key => $value) {
232
                if ($key !== '_attributes' && $key !== '@attributes') {
233
                    continue;
234
                }
235
236
                $this->addAttributes($element, $rootElement[$key]);
237
            }
238
        }
239
240
        return $element;
241
    }
242
}
243