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 ( cd79dd...2b01cb )
by Freek
01:19
created

ArrayToXml::removeControlCharacters()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
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
            $value = htmlspecialchars($value);
102
103
            $value = $this->removeControlCharacters($value);
104
105
            $element->nodeValue = $value;
106
107
            return;
108
        }
109
110
        foreach ($value as $key => $data) {
111
            if (! $sequential) {
112
                if (($key === '_attributes') || ($key === '@attributes')) {
113
                    $this->addAttributes($element, $data);
114
                } elseif ((($key === '_value') || ($key === '@value')) && is_string($data)) {
115
                    $element->nodeValue = htmlspecialchars($data);
116
                } elseif ((($key === '_cdata') || ($key === '@cdata')) && is_string($data)) {
117
                    $element->appendChild($this->document->createCDATASection($data));
118
                } else {
119
                    $this->addNode($element, $key, $data);
120
                }
121
            } elseif (is_array($data)) {
122
                $this->addCollectionNode($element, $data);
123
            } else {
124
                $this->addSequentialNode($element, $data);
125
            }
126
        }
127
    }
128
129
    /**
130
     * Add node.
131
     *
132
     * @param DOMElement $element
133
     * @param string $key
134
     * @param string|string[] $value
135
     */
136
    protected function addNode(DOMElement $element, $key, $value)
137
    {
138
        if ($this->replaceSpacesByUnderScoresInKeyNames) {
139
            $key = str_replace(' ', '_', $key);
140
        }
141
142
        $child = $this->document->createElement($key);
143
        $element->appendChild($child);
144
        $this->convertElement($child, $value);
145
    }
146
147
    /**
148
     * Add collection node.
149
     *
150
     * @param DOMElement $element
151
     * @param string|string[] $value
152
     *
153
     * @internal param string $key
154
     */
155
    protected function addCollectionNode(DOMElement $element, $value)
156
    {
157
        if ($element->childNodes->length === 0 && $element->attributes->length === 0) {
0 ignored issues
show
Bug introduced by
The property length does not seem to exist in DOMNamedNodeMap.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

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