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
Pull Request — master (#94)
by Vladimir
03:40 queued 24s
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
     * Prefix for the tags with numeric names.
27
     *
28
     * @var string
29
     */
30
    protected $numericTagNamePrefix = 'num_';
31
32
    /**
33
     * Construct a new instance.
34
     *
35
     * @param string[] $array
36
     * @param string|array $rootElement
37
     * @param bool $replaceSpacesByUnderScoresInKeyNames
38
     * @param string $xmlEncoding
39
     * @param string $xmlVersion
40
     *
41
     * @throws DOMException
42
     */
43
    public function __construct(array $array, $rootElement = '', $replaceSpacesByUnderScoresInKeyNames = true, $xmlEncoding = null, $xmlVersion = '1.0')
44
    {
45
        $this->document = new DOMDocument($xmlVersion, $xmlEncoding);
46
        $this->replaceSpacesByUnderScoresInKeyNames = $replaceSpacesByUnderScoresInKeyNames;
47
48
        if ($t = $this->isArrayAllKeySequential($array) && ! empty($array)) {
0 ignored issues
show
Unused Code introduced by
$t is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
Comprehensibility introduced by
Consider adding parentheses for clarity. Current Interpretation: $t = ($this->isArrayAllK...ray) && !empty($array)), Probably Intended Meaning: ($t = $this->isArrayAllK...ray)) && !empty($array)
Loading history...
49
            throw new DOMException('Invalid Character Error');
50
        }
51
52
        $root = $this->createRootElement($rootElement);
53
54
        $this->document->appendChild($root);
55
56
        $this->convertElement($root, $array);
57
    }
58
59
    public function setNumericTagNamePrefix(string $prefix)
60
    {
61
        $this->numericTagNamePrefix = $prefix;
62
    }
63
64
    /**
65
     * Convert the given array to an xml string.
66
     *
67
     * @param string[] $array
68
     * @param string|array $rootElement
69
     * @param bool $replaceSpacesByUnderScoresInKeyNames
70
     * @param string $xmlEncoding
71
     * @param string $xmlVersion
72
     *
73
     * @return string
74
     */
75
    public static function convert(array $array, $rootElement = '', $replaceSpacesByUnderScoresInKeyNames = true, $xmlEncoding = null, $xmlVersion = '1.0')
76
    {
77
        $converter = new static($array, $rootElement, $replaceSpacesByUnderScoresInKeyNames, $xmlEncoding, $xmlVersion);
78
79
        return $converter->toXml();
80
    }
81
82
    /**
83
     * Return as XML.
84
     *
85
     * @return string
86
     */
87
    public function toXml()
88
    {
89
        return $this->document->saveXML();
90
    }
91
92
    /**
93
     * Return as DOM object.
94
     *
95
     * @return DOMDocument
96
     */
97
    public function toDom()
98
    {
99
        return $this->document;
100
    }
101
102
    /**
103
     * Parse individual element.
104
     *
105
     * @param DOMElement $element
106
     * @param string|string[] $value
107
     */
108
    private function convertElement(DOMElement $element, $value)
109
    {
110
        $sequential = $this->isArrayAllKeySequential($value);
111
112
        if (! is_array($value)) {
113
            $value = htmlspecialchars($value);
114
115
            $value = $this->removeControlCharacters($value);
116
117
            $element->nodeValue = $value;
118
119
            return;
120
        }
121
122
        foreach ($value as $key => $data) {
123
            if (! $sequential) {
124
                if (($key === '_attributes') || ($key === '@attributes')) {
125
                    $this->addAttributes($element, $data);
126
                } elseif ((($key === '_value') || ($key === '@value')) && is_string($data)) {
127
                    $element->nodeValue = htmlspecialchars($data);
128
                } elseif ((($key === '_cdata') || ($key === '@cdata')) && is_string($data)) {
129
                    $element->appendChild($this->document->createCDATASection($data));
130
                } elseif ((($key === '_mixed') || ($key === '@mixed')) && is_string($data)) {
131
                    $fragment = $this->document->createDocumentFragment();
132
                    $fragment->appendXML($data);
133
                    $element->appendChild($fragment);
134
                } elseif (is_int($key)) {
135
                    $this->addNode($element, $this->numericTagNamePrefix . $key, $data);
136
                } else {
137
                    $this->addNode($element, $key, $data);
138
                }
139
            } elseif (is_array($data)) {
140
                $this->addCollectionNode($element, $data);
141
            } else {
142
                $this->addSequentialNode($element, $data);
143
            }
144
        }
145
    }
146
147
    /**
148
     * Add node.
149
     *
150
     * @param DOMElement $element
151
     * @param string $key
152
     * @param string|string[] $value
153
     */
154
    protected function addNode(DOMElement $element, $key, $value)
155
    {
156
        if ($this->replaceSpacesByUnderScoresInKeyNames) {
157
            $key = str_replace(' ', '_', $key);
158
        }
159
160
        $child = $this->document->createElement($key);
161
        $element->appendChild($child);
162
        $this->convertElement($child, $value);
163
    }
164
165
    /**
166
     * Add collection node.
167
     *
168
     * @param DOMElement $element
169
     * @param string|string[] $value
170
     *
171
     * @internal param string $key
172
     */
173
    protected function addCollectionNode(DOMElement $element, $value)
174
    {
175
        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...
176
            $this->convertElement($element, $value);
177
178
            return;
179
        }
180
181
        $child = $this->document->createElement($element->tagName);
182
        $element->parentNode->appendChild($child);
183
        $this->convertElement($child, $value);
184
    }
185
186
    /**
187
     * Add sequential node.
188
     *
189
     * @param DOMElement $element
190
     * @param string|string[] $value
191
     *
192
     * @internal param string $key
193
     */
194
    protected function addSequentialNode(DOMElement $element, $value)
195
    {
196
        if (empty($element->nodeValue)) {
197
            $element->nodeValue = htmlspecialchars($value);
198
199
            return;
200
        }
201
202
        $child = new DOMElement($element->tagName);
203
        $child->nodeValue = htmlspecialchars($value);
204
        $element->parentNode->appendChild($child);
205
    }
206
207
    /**
208
     * Check if array are all sequential.
209
     *
210
     * @param array|string $value
211
     *
212
     * @return bool
213
     */
214
    protected function isArrayAllKeySequential($value)
215
    {
216
        if (! is_array($value)) {
217
            return false;
218
        }
219
220
        if (count($value) <= 0) {
221
            return true;
222
        }
223
224
        return ! array_unique(array_map('is_int', array_keys($value))) === [true];
225
    }
226
227
    /**
228
     * Add attributes.
229
     *
230
     * @param DOMElement $element
231
     * @param string[] $data
232
     */
233
    protected function addAttributes($element, $data)
234
    {
235
        foreach ($data as $attrKey => $attrVal) {
236
            $element->setAttribute($attrKey, $attrVal);
237
        }
238
    }
239
240
    /**
241
     * Create the root element.
242
     *
243
     * @param  string|array $rootElement
244
     * @return DOMElement
245
     */
246
    protected function createRootElement($rootElement)
247
    {
248
        if (is_string($rootElement)) {
249
            $rootElementName = $rootElement ?: 'root';
250
251
            return $this->document->createElement($rootElementName);
252
        }
253
254
        $rootElementName = $rootElement['rootElementName'] ?? 'root';
255
256
        $element = $this->document->createElement($rootElementName);
257
258
        foreach ($rootElement as $key => $value) {
259
            if ($key !== '_attributes' && $key !== '@attributes') {
260
                continue;
261
            }
262
263
            $this->addAttributes($element, $rootElement[$key]);
264
        }
265
266
        return $element;
267
    }
268
269
    /**
270
     * @param $valuet
271
     * @return string
272
     */
273
    protected function removeControlCharacters($value)
274
    {
275
        return preg_replace('/[\x00-\x09\x0B\x0C\x0E-\x1F\x7F]/', '', $value);
276
    }
277
}
278