Passed
Push — master ( 37d2df...2b69b2 )
by Andrew
02:12
created

XMLReaderElement::children()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

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