XML::data2Xml()   B
last analyzed

Complexity

Conditions 7
Paths 10

Size

Total Lines 22
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 7

Importance

Changes 0
Metric Value
cc 7
eloc 12
nc 10
nop 3
dl 0
loc 22
ccs 12
cts 12
cp 1
crap 7
rs 8.8333
c 0
b 0
f 0
1
<?php
2
3
/*
4
 * This file is part of the overtrue/wechat.
5
 *
6
 * (c) overtrue <[email protected]>
7
 *
8
 * This source file is subject to the MIT license that is bundled
9
 * with this source code in the file LICENSE.
10
 */
11
12
namespace EasyWeChat\Kernel\Support;
13
14
use SimpleXMLElement;
15
16
/**
17
 * Class XML.
18
 */
19
class XML
20
{
21
    /**
22
     * XML to array.
23
     *
24
     * @param string $xml XML string
25
     *
26
     * @return array
27
     */
28 31
    public static function parse($xml)
29
    {
30 31
        $backup = libxml_disable_entity_loader(true);
31
32 31
        $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 EasyWeChat\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

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