XML::normalize()   A
last analyzed

Complexity

Conditions 6
Paths 4

Size

Total Lines 22
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 6

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 6
eloc 13
c 1
b 0
f 1
nc 4
nop 1
dl 0
loc 22
ccs 11
cts 11
cp 1
crap 6
rs 9.2222
1
<?php
2
3
namespace EasyIM\Kernel\Support;
4
5
use SimpleXMLElement;
6
7
/**
8
 * Class XML.
9
 */
10
class XML
11
{
12
    /**
13
     * XML to array.
14
     *
15
     * @param string $xml XML string
16
     *
17
     * @return array
18
     */
19 2
    public static function parse($xml)
20
    {
21 2
        $backup = libxml_disable_entity_loader(true);
22
23 2
        $result = self::normalize(simplexml_load_string(self::sanitize($xml), 'SimpleXMLElement', LIBXML_COMPACT | LIBXML_NOCDATA | LIBXML_NOBLANKS));
0 ignored issues
show
Bug introduced by
It seems like simplexml_load_string(se...upport\LIBXML_NOBLANKS) can also be of type false; however, parameter $obj of EasyIM\Kernel\Support\XML::normalize() 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

23
        $result = self::normalize(/** @scrutinizer ignore-type */ simplexml_load_string(self::sanitize($xml), 'SimpleXMLElement', LIBXML_COMPACT | LIBXML_NOCDATA | LIBXML_NOBLANKS));
Loading history...
24
25 2
        libxml_disable_entity_loader($backup);
26
27 2
        return $result;
28
    }
29
30
    /**
31
     * XML encode.
32
     *
33
     * @param mixed  $data
34
     * @param string $root
35
     * @param string $item
36
     * @param string $attr
37
     * @param string $id
38
     *
39
     * @return string
40
     */
41 1
    public static function build(
42
        $data,
43
        $root = 'xml',
44
        $item = 'item',
45
        $attr = '',
46
        $id = 'id'
47
    ) {
48 1
        if (is_array($attr)) {
0 ignored issues
show
introduced by
The condition is_array($attr) is always false.
Loading history...
49 1
            $_attr = [];
50
51 1
            foreach ($attr as $key => $value) {
52 1
                $_attr[] = "{$key}=\"{$value}\"";
53
            }
54
55 1
            $attr = implode(' ', $_attr);
56
        }
57
58 1
        $attr = trim($attr);
59 1
        $attr = empty($attr) ? '' : " {$attr}";
60 1
        $xml = "<{$root}{$attr}>";
61 1
        $xml .= self::data2Xml($data, $item, $id);
62 1
        $xml .= "</{$root}>";
63
64 1
        return $xml;
65
    }
66
67
    /**
68
     * Build CDATA.
69
     *
70
     * @param string $string
71
     *
72
     * @return string
73
     */
74 2
    public static function cdata($string)
75
    {
76 2
        return sprintf('<![CDATA[%s]]>', $string);
77
    }
78
79
    /**
80
     * Object to array.
81
     *
82
     *
83
     * @param SimpleXMLElement $obj
84
     *
85
     * @return array
86
     */
87 2
    protected static function normalize($obj)
88
    {
89 2
        $result = null;
90
91 2
        if (is_object($obj)) {
92 2
            $obj = (array) $obj;
93
        }
94
95 2
        if (is_array($obj)) {
96 2
            foreach ($obj as $key => $value) {
97 2
                $res = self::normalize($value);
98 2
                if (('@attributes' === $key) && ($key)) {
99
                    $result = $res; // @codeCoverageIgnore
100
                } else {
101 2
                    $result[$key] = $res;
102
                }
103
            }
104
        } else {
105 2
            $result = $obj;
106
        }
107
108 2
        return $result;
109
    }
110
111
    /**
112
     * Array to XML.
113
     *
114
     * @param array  $data
115
     * @param string $item
116
     * @param string $id
117
     *
118
     * @return string
119
     */
120 1
    protected static function data2Xml($data, $item = 'item', $id = 'id')
121
    {
122 1
        $xml = $attr = '';
123
124 1
        foreach ($data as $key => $val) {
125 1
            if (is_numeric($key)) {
126 1
                $id && $attr = " {$id}=\"{$key}\"";
127 1
                $key = $item;
128
            }
129
130 1
            $xml .= "<{$key}{$attr}>";
131
132 1
            if ((is_array($val) || is_object($val))) {
133 1
                $xml .= self::data2Xml((array) $val, $item, $id);
134
            } else {
135 1
                $xml .= is_numeric($val) ? $val : self::cdata($val);
136
            }
137
138 1
            $xml .= "</{$key}>";
139
        }
140
141 1
        return $xml;
142
    }
143
144
    /**
145
     * Delete invalid characters in XML.
146
     *
147
     * @see https://www.w3.org/TR/2008/REC-xml-20081126/#charsets - XML charset range
148
     * @see http://php.net/manual/en/regexp.reference.escape.php - escape in UTF-8 mode
149
     *
150
     * @param string $xml
151
     *
152
     * @return string
153
     */
154 3
    public static function sanitize($xml)
155
    {
156 3
        return preg_replace('/[^\x{9}\x{A}\x{D}\x{20}-\x{D7FF}\x{E000}-\x{FFFD}\x{10000}-\x{10FFFF}]+/u', '', $xml);
157
    }
158
}
159