Passed
Push — master ( d2168e...d3ce08 )
by Andrew
02:02
created

XMLReaderElement::hasChildren()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
namespace Sabre\Xml;
3
4
class XMLReaderElement implements \Iterator {
5
6
    protected $namespace;
7
    protected $name;
8
    protected $attributes;
9
    protected $value;
10
11
    public function rewind()
12
    {
13
        reset($this->value);
14
    }
15
16
    public function current()
17
    {
18
        return current($this->value);
19
    }
20
21
    public function key()
22
    {
23
        return key($this->value);
24
    }
25
26
    public function next()
27
    {
28
        return next($this->value);
29
    }
30
31
    public function valid()
32
    {
33
        $key = key($this->value);
34
        return ($key !== NULL && $key !== FALSE);
35
    }
36
37
    public function parse($data)
38
    {
39
        $this->parseNameSpace($data);
40
        $this->attributes = (object) $this->convertAttributes($data['attributes']);
41
42
        if ($this->isElementArray($data['value'])) {
43
            $this->value = [];
44
45
            foreach ($data['value'] as $value) {
46
                $this->value[] = (new XMLReaderElement())->parse($value);
47
            }
48
        } elseif ($this->isElementValue($data['value'])) {
49
            $this->value = $this->convertValue($data['value']);
50
        } else {
51
            $this->value = (new XMLReaderElement())->parse($data['value']);
52
        }
53
54
        return $this;
55
    }
56
57
    protected function isElementArray($value) {
58
        return is_array($value) && !array_key_exists('name', $value) && array_key_exists('name', current($value));
59
    }
60
61
    protected function isElementValue($value) {
62
        return !is_array($value) || !array_key_exists('name', $value);
63
    }
64
65
    protected function parseNameSpace($data) {
66
        $namespace = [];
67
        preg_match_all('/{(.*?)}/', $data['name'], $namespace);
68
69
        if (count($namespace) === 2) {
70
            $this->namespace = $namespace[1][0];
71
            $this->name      = str_replace($namespace[0][0], '', $data['name']);
72
        } else {
73
            $this->name      = $data['name'];
74
        }
75
    }
76
77
    protected function convertAttributes($attributes)
78
    {
79
        foreach($attributes as $k=>$attribute)
80
        {
81
            $attributes[$k] = $this->convertValue($attribute);
82
        }
83
84
        return $attributes;
85
    }
86
87
    protected function convertValue($value) {
88
        if (is_string($value))
89
        {
90
            if ($this->isBool($value))
91
            {
92
                return filter_var($value, FILTER_VALIDATE_BOOLEAN);
93
            }
94
95
            if ($this->isInteger($value))
96
            {
97
                return (int) $value;
98
            }
99
        }
100
        return $value;
101
    }
102
103
    /* Very specific type of integer checking to ensure
104
    that we have a number value, and not one that has been
105
    mistakenly casted by PHP. Examples below.
106
107
    var_dump(isInteger(23));    //bool(true)
108
    var_dump(isInteger("23"));  //bool(true)
109
    var_dump(isInteger(23.5));  //bool(false)
110
    var_dump(isInteger(NULL));  //bool(false)
111
    var_dump(isInteger(""));    //bool(false)
112
    */
113
    protected function isInteger($input)
114
    {
115
        return(ctype_digit(strval($input)));
116
    }
117
118
    /* Very specific type of boolean checking to ensure
119
    that we have a bool value, and not one that has been
120
    mistakenly casted by PHP. Examples below.
121
122
    var_dump(isBool(true));     //bool(true)
123
    var_dump(isBool("false"));  //bool(true)
124
    var_dump(isBool(0));        //bool(false)
125
    var_dump(isBool(NULL));     //bool(false)
126
    var_dump(isBool(""));       //bool(false)
127
    */
128
    protected function isBool($input)
129
    {
130
        return in_array(strtolower($input), ['true', 'false']) !== false;
131
    }
132
133
    public function children()
134
    {
135
        if ($this->value instanceof XMLReaderElement) {
136
            return [$this->value];
137
        }
138
139
        if (is_array($this->value)) {
140
            $results = [];
141
            foreach($this->value as $value) {
142
                if ($value instanceof XMLReaderElement) {
143
                    $results[] = $value;
144
                }
145
            }
146
            return $results;
147
        }
148
149
        return [];
150
    }
151
152
    public function hasChildren()
153
    {
154
        return !empty($this->children());
155
    }
156
157
    public function findFirst($search)
158
    {
159
        return current($this->find($search));
160
    }
161
162
    public function find($search) {
163
164
        $results = [];
165
166
        if ($this->name == $search)
167
            $results[] = $this;
168
169
        foreach($this->children() as $child) {
170
            $results = array_merge($results, $child->find($search));
171
        }
172
173
        if ($search[0] == '@') {
174
            $search = substr($search, 1);
175
            if (property_exists($this->attributes, $search))
176
                $results[] = $this->attributes->$search;
177
        }
178
179
        return $results;
180
    }
181
182
    public function __get($name)
183
    {
184
        /* Access the Elements Attributes */
185
        if (is_array($this->value)) {
186
            foreach($this->value as $value) {
187
                if ($value instanceof XMLReaderElement && $value->name == $name) {
188
                    return $value;
189
                }
190
            }
191
        }
192
193
        return $this->$name;
194
    }
195
196
    public function __debugInfo() {
197
198
        $arr = ['name'       => $this->name,
199
                'namespace'  => $this->namespace,
200
                'attributes' => $this->attributes
201
                ];
202
203
        if ($this->hasChildren()) {
204
            $names = [];
205
            foreach($this->children() as $child) {
206
                $names[] = $child->name;
207
            }
208
209
            $arr += ['children' => implode(',', $names)];
210
        } else {
211
            $arr += ['value' => $this->value];
212
        }
213
214
        return $arr;
215
    }
216
}
217