This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | ar_pinp::allow( 'ar_xml' ); |
||
4 | ar_pinp::allow( 'ar_xmlElement' ); |
||
5 | ar_pinp::allow( 'ar_xmlNode' ); |
||
6 | ar_pinp::allow( 'ar_xmlNodes' ); |
||
7 | ar_pinp::allow( 'ar_xmlDataBinding' ); |
||
8 | |||
9 | class ar_xml extends arBase { |
||
10 | |||
11 | public static $indenting = true; |
||
12 | private static $comments = true; |
||
13 | public static $indent = "\t"; |
||
14 | public static $strict = false; |
||
15 | public static $preserveWhiteSpace = false; |
||
16 | public static $autoparse = true; |
||
17 | |||
18 | public static function configure( $option, $value ) { |
||
19 | switch ( $option ) { |
||
20 | case 'autoparse': |
||
21 | self::$autoparse = (bool) $value; |
||
22 | break; |
||
23 | case 'indent': |
||
24 | if ( is_bool( $value ) ) { |
||
25 | self::$indenting = (bool) $value; |
||
26 | } else if ( is_string( $value ) ) { |
||
27 | self::$indenting = true; |
||
28 | self::$indent = $value; |
||
29 | } else if (!$value) { |
||
30 | self::$indenting = false; |
||
31 | } |
||
32 | break; |
||
33 | case 'comments': |
||
34 | self::$comments = (bool)$value; |
||
35 | break; |
||
36 | case 'strict': |
||
37 | self::$strict = (bool)$value; |
||
38 | break; |
||
39 | case 'preserveWhiteSpace': |
||
40 | self::$preserveWhiteSpace = (bool) $value; |
||
41 | break; |
||
42 | } |
||
43 | } |
||
44 | |||
45 | public function __set( $name, $value ) { |
||
46 | ar_xml::configure( $name, $value ); |
||
47 | } |
||
48 | |||
49 | public function __get( $name ) { |
||
50 | if ( isset( ar_xml::${$name} ) ) { |
||
51 | return ar_xml::${$name}; |
||
52 | } |
||
53 | } |
||
54 | |||
55 | public static function preamble( $version = '1.0', $encoding = 'UTF-8', $standalone = null ) { |
||
56 | if ( isset($standalone) ) { |
||
57 | if ( $standalone === 'false' ) { |
||
58 | $standalone = 'no'; |
||
59 | } else if ( $standalone === 'true' ) { |
||
60 | $standalone = 'yes'; |
||
61 | } |
||
62 | $standalone = self::attribute( 'standalone', $standalone ); |
||
63 | } else { |
||
64 | $standalone = ''; |
||
65 | } |
||
66 | return new ar_xmlNode('<?xml version="' . self::value($version) |
||
67 | . '" encoding="' . self::value($encoding) . '"' . $standalone . ' ?'.'>'); |
||
68 | } |
||
69 | |||
70 | public static function comment( $comment ) { |
||
71 | return ( self::$comments ? new ar_xmlNode('<!-- '.self::value( $comment ).' -->') : '' ); |
||
72 | } |
||
73 | |||
74 | public static function name( $name ) { |
||
75 | ar::untaint($name, FILTER_UNSAFE_RAW); |
||
76 | if (self::$strict) { |
||
77 | $newname = preg_replace( '/[^-.0-9:a-z_]/isU', '', $name); |
||
78 | $newname = preg_replace( '/^[^:a-z_]*/isU', '', $newname); |
||
79 | //FIXME: throw an error here or something if newname !== name |
||
80 | $name = $newname; |
||
81 | } |
||
82 | return $name; |
||
83 | } |
||
84 | |||
85 | public static function value( $value, $current = 0 ) { |
||
86 | ar::untaint( $value, FILTER_UNSAFE_RAW ); |
||
87 | if ( is_array( $value ) ) { |
||
88 | $content = ''; |
||
89 | foreach( $value as $subvalue ) { |
||
90 | $content = rtrim($content) . ' ' . ltrim( self::value( $subvalue, $current ) ); |
||
91 | } |
||
92 | $content = trim( $content ); |
||
93 | } else if ( is_bool( $value ) ) { |
||
94 | $content = $value ? 'true' : 'false'; |
||
95 | } else if ( $value instanceof ar_listExpression ) { |
||
96 | $content = self::value( $value->item( $current ) ); |
||
97 | } else { |
||
98 | if ( preg_match( '/^\s*<!\[CDATA\[/', $value ) ) { |
||
99 | $content = $value; |
||
100 | } else { |
||
101 | $content = htmlspecialchars( $value, ENT_QUOTES, 'UTF-8' ); |
||
102 | } |
||
103 | } |
||
104 | return $content; |
||
105 | } |
||
106 | |||
107 | public static function attribute( $name, $value, $current = 0 ) { |
||
108 | if ( is_numeric( $name ) ) { |
||
109 | return ' ' . self::name( $value ); |
||
110 | } else { |
||
111 | return ' ' . self::name( $name ) . '="' . self::value( $value, $current ) . '"'; |
||
112 | } |
||
113 | } |
||
114 | |||
115 | public static function attributes( $attributes ) { |
||
116 | $content = ''; |
||
117 | if ( is_array( $attributes ) ) { |
||
118 | foreach( $attributes as $key => $value ) { |
||
119 | $content .= self::attribute( $key, $value ); |
||
120 | } |
||
121 | } |
||
122 | return $content; |
||
123 | } |
||
124 | |||
125 | public static function cdata( $value ) { |
||
126 | ar::untaint( $value, FILTER_UNSAFE_RAW ); |
||
127 | return new ar_xmlNode($value, null, true); |
||
128 | } |
||
129 | |||
130 | public static function tag() { |
||
131 | $args = func_get_args(); |
||
132 | return call_user_func_array( array( 'ar_xml', 'el' ), $args ); |
||
133 | } |
||
134 | |||
135 | public static function element() { |
||
136 | $args = func_get_args(); |
||
137 | return call_user_func_array( array( 'ar_xml', 'el' ), $args ); |
||
138 | } |
||
139 | |||
140 | View Code Duplication | public static function el() { |
|
141 | $args = func_get_args(); |
||
142 | $name = array_shift($args); |
||
143 | $attributes = array(); |
||
144 | $content = array(); |
||
145 | foreach ($args as $arg) { |
||
146 | if ( is_array( $arg ) ) { |
||
147 | $attributes = array_merge($attributes, $arg); |
||
148 | } else if ($arg instanceof ar_xmlNodes) { |
||
149 | $content = array_merge( $content, (array) $arg); |
||
150 | } else { |
||
151 | $content[] = $arg; |
||
152 | } |
||
153 | } |
||
154 | if ( !count( $content ) ) { |
||
155 | $content = null; |
||
156 | } else { |
||
157 | $content = new ar_xmlNodes( $content ); |
||
158 | } |
||
159 | return new ar_xmlElement($name, $attributes, $content); |
||
160 | } |
||
161 | |||
162 | public static function indent( $content, $indent=null ) { |
||
163 | if ( ( isset($indent) || self::$indenting ) && preg_match( '/^(\s*)</', $content) ) { |
||
164 | if ( !isset($indent) ) { |
||
165 | $indent = self::$indent; |
||
166 | } |
||
167 | return "\n" . preg_replace( '/^(\s*)</m', $indent . '$1<', $content ); |
||
168 | } else { |
||
169 | return $content; |
||
170 | } |
||
171 | } |
||
172 | |||
173 | public static function nodes() { |
||
174 | $args = func_get_args(); |
||
175 | $nodes = call_user_func_array( array( 'ar_xmlNodes', 'mergeArguments' ), $args ); |
||
176 | return new ar_xmlNodes( $nodes ); |
||
177 | } |
||
178 | |||
179 | protected static function parseAttributes( $DOMElement ) { |
||
180 | // get all attributes including namespaced ones and namespaces themselves... |
||
181 | // this is the best I could do given the many bugs and oversights in php's |
||
182 | // DOM implementation. |
||
183 | |||
184 | $declaredns = array(); |
||
185 | $allns = array(); |
||
186 | |||
187 | // this part retrieves all available namespaces on the parent |
||
188 | // xpath is the only reliable way |
||
189 | $x = new DOMXPath( $DOMElement->ownerDocument ); |
||
190 | $p = $DOMElement->parentNode; |
||
191 | if ($p && $p instanceof DOMNode ) { |
||
192 | $pns = $x->query('namespace::*', $p ); |
||
193 | foreach( $pns as $node ) { |
||
194 | $allns[$node->localName] = $p->lookupNamespaceURI( $node->localName ); |
||
195 | } |
||
196 | } |
||
197 | // this retrieves all namespaces on the current node |
||
198 | // all 'new' namespace must have been declared on this node |
||
199 | $ns = $x->query('namespace::*', $DOMElement); |
||
200 | foreach( $ns as $node) { |
||
201 | $uri = $DOMElement->lookupNamespaceURI( $node->localName ); |
||
202 | if ($allns[$node->localName]!=$uri && $node->localName!='xmlns') { |
||
203 | $declaredns['xmlns:'.$node->localName] = $uri; |
||
204 | } |
||
205 | } |
||
206 | |||
207 | // finally check if the default namespace has been altered |
||
208 | $dns = $DOMElement->getAttribute('xmlns'); |
||
209 | if ($dns) { |
||
210 | $declaredns['xmlns'] = $dns; |
||
211 | } |
||
212 | |||
213 | $result = $declaredns; |
||
214 | |||
215 | $length = $DOMElement->attributes->length; |
||
216 | for ($i=0; $i<$length; $i++) { |
||
217 | $a = $DOMElement->attributes->item($i); |
||
218 | $prefix = ''; |
||
219 | if ($a->prefix) { |
||
220 | $prefix = $a->prefix.':'; |
||
221 | } |
||
222 | $result[$prefix.$a->name] = $a->value; |
||
223 | } |
||
224 | |||
225 | return $result; |
||
226 | } |
||
227 | |||
228 | protected static function parseChildren( $DOMElement ) { |
||
229 | $result = array(); |
||
230 | foreach ( $DOMElement->childNodes as $child ) { |
||
231 | if ( $child instanceof DOMComment ) { |
||
232 | if ( self::$preserveWhiteSpace || trim( $child->data )!=='' ) { |
||
233 | $result[] = new ar_xmlNode('<!--'.$child->data.'-->'); |
||
234 | } |
||
235 | View Code Duplication | } else if ( $child instanceof DOMCharacterData ) { |
|
236 | if ( self::$preserveWhiteSpace || trim( $child->data )!=='' ) { |
||
237 | $result[] = new ar_xmlNode($child->data); |
||
238 | } |
||
239 | } else if ( $child instanceof DOMCdataSection ) { |
||
240 | if ( self::$preserveWhiteSpace || trim( $child->data )!=='' ) { |
||
241 | $result[] = self::cdata( $child->data ); |
||
242 | } |
||
243 | } else if ( $child instanceof DOMElement ) { |
||
244 | $result[] = self::el( $child->tagName, self::parseAttributes( $child ), self::parseChildren( $child ) ); |
||
245 | } |
||
246 | } |
||
247 | return self::nodes( $result ); |
||
248 | } |
||
249 | |||
250 | protected static function parseHead( DOMDocument $dom ) { |
||
251 | $result = self::nodes(); |
||
252 | if ($dom->xmlVersion && $dom->xmlEncoding) { |
||
253 | $result[] = self::preamble( $dom->xmlVersion, $dom->xmlEncoding, $dom->xmlStandalone ); |
||
254 | } |
||
255 | if ($dom->doctype) { |
||
256 | $doctype = '<!DOCTYPE '.$dom->doctype->name; |
||
257 | if ($dom->doctype->publicId) { |
||
258 | $doctype .= ' PUBLIC "'.$dom->doctype->publicId.'"'; |
||
259 | } |
||
260 | if ($dom->doctype->systemId) { |
||
261 | $doctype .= ' "'.$dom->doctype->systemId.'"'; |
||
262 | } |
||
263 | $doctype .= '>'; |
||
264 | $result[] = new ar_xmlNode($doctype); |
||
265 | } |
||
266 | return $result; |
||
267 | } |
||
268 | |||
269 | public static function parse( $xml, $encoding = null ) { |
||
270 | // important: parse must never return results with simple string values, but must always |
||
271 | // wrap them in an ar_xmlNode, or tryToParse may get called, which will call parse, which |
||
272 | // will... etc. |
||
273 | $dom = new DOMDocument(); |
||
274 | if ( $encoding ) { |
||
275 | $xml = '<?xml encoding="' . $encoding . '">' . $xml; |
||
276 | } |
||
277 | $prevErrorSetting = libxml_use_internal_errors(true); |
||
278 | if ( $dom->loadXML( $xml ) ) { |
||
279 | View Code Duplication | if ( $encoding ) { |
|
280 | foreach( $dom->childNodes as $item ) { |
||
281 | if ( $item->nodeType == XML_PI_NODE ) { |
||
282 | $dom->removeChild( $item ); |
||
283 | break; |
||
284 | } |
||
285 | } |
||
286 | $dom->encoding = $encoding; |
||
287 | } |
||
288 | $domroot = $dom->documentElement; |
||
289 | if ( $domroot ) { |
||
290 | $result = self::parseHead( $dom ); |
||
291 | $root = self::el( $domroot->tagName, self::parseAttributes( $domroot ), self::parseChildren( $domroot ) ); |
||
292 | $s = simplexml_import_dom( $dom ); |
||
293 | $n = $s->getDocNamespaces(); |
||
294 | foreach( $n as $prefix => $ns ) { |
||
295 | if ($prefix) { |
||
296 | $prefix = ':'.$prefix; |
||
297 | } |
||
298 | $root->setAttribute('xmlns'.$prefix, $ns); |
||
299 | } |
||
300 | $result[] = $root; |
||
301 | return $result; |
||
302 | } |
||
303 | } |
||
304 | $errors = libxml_get_errors(); |
||
305 | libxml_clear_errors(); |
||
306 | libxml_use_internal_errors( $prevErrorSetting ); |
||
307 | return ar_error::raiseError( 'Incorrect xml passed', ar_exceptions::ILLEGAL_ARGUMENT, $errors ); |
||
308 | } |
||
309 | |||
310 | public static function tryToParse( $xml ) { |
||
311 | $result = $xml; |
||
312 | if ( ! ($xml instanceof ar_xmlNodeInterface ) ) { |
||
313 | if ($xml && strpos( $xml, '<' ) !== false ) { |
||
314 | try { |
||
315 | $result = self::parse( '<root>'.$xml.'</root>' ); |
||
316 | if ( ar_error::isError($result) ) { |
||
317 | $result = new ar_xmlNode( (string) $xml ); |
||
318 | } else { |
||
319 | $result = $result->firstChild->childNodes; |
||
320 | } |
||
321 | } catch( Exception $e ) { |
||
322 | $result = new ar_xmlNode( (string) $xml ); |
||
323 | } |
||
324 | } else { |
||
325 | $result = new ar_xmlNode( (string) $xml ); |
||
326 | } |
||
327 | } |
||
328 | return $result; |
||
329 | } |
||
330 | |||
331 | } |
||
332 | |||
333 | /* |
||
334 | This class is used for generic nodelists as well as childNodes |
||
335 | The difference is in whether or not parentNode is set. As a |
||
336 | generic nodelist the child nodes can have any parentNode, so the |
||
337 | list is an in memory reference to a set of nodes. As a childNodes |
||
338 | list the child nodes must have the same parentNode as the list. |
||
339 | If you set the parentNode of the nodes list, it will also set the |
||
340 | parentNode of all the childNodes and remove them from any other parent |
||
341 | */ |
||
342 | interface ar_xmlNodeInterface { } |
||
343 | |||
344 | class ar_xmlNodes extends ArrayObject implements ar_xmlNodeInterface { |
||
345 | |||
346 | private $parentNode = null; |
||
347 | public $attributes = array(); |
||
348 | public $isDocumentFragment = true; |
||
349 | private $nodeValue = ''; // needed for __get to function |
||
0 ignored issues
–
show
|
|||
350 | |||
351 | public static function mergeArguments(){ |
||
352 | $args = func_get_args(); |
||
353 | $nodes = array(); |
||
354 | foreach ( $args as $input ) { |
||
355 | if ( is_array( $input ) || $input instanceof ar_xmlNodes ) { //FIXME: accept other array like objects as well? |
||
356 | $nodes = array_merge( $nodes, (array) $input ); |
||
357 | } else if ($input) { // skip empty and NULL arguments |
||
358 | $nodes[] = $input; |
||
359 | } |
||
360 | } |
||
361 | return $nodes; |
||
362 | } |
||
363 | |||
364 | protected function _tryToParse( $node ) { |
||
365 | $node = ar_xml::tryToParse( $node ); |
||
366 | return $node; |
||
367 | } |
||
368 | |||
369 | public function _normalizeNodes( $nodes ) { |
||
370 | $result = array(); |
||
371 | if ( is_array($nodes) || $nodes instanceof Traversable ) { |
||
372 | foreach ( $nodes as $node ) { |
||
373 | View Code Duplication | if ( !$node instanceof ar_xmlNodeInterface ) { |
|
374 | if ( ar_xml::$autoparse ) { |
||
375 | $node = $this->_tryToParse( $node ); |
||
376 | } else { |
||
377 | $node = new ar_xmlNode( $node ); |
||
378 | } |
||
379 | } |
||
380 | if ( is_array($node) || $node instanceof Traversable ) { |
||
381 | $subnodes = $this->_normalizeNodes( $node ); |
||
382 | foreach ( $subnodes as $subnode ) { |
||
383 | $result[] = $subnode; |
||
384 | } |
||
385 | } else { |
||
386 | $result[] = $node; |
||
387 | } |
||
388 | } |
||
389 | } else { |
||
390 | View Code Duplication | if ( !$nodes instanceof ar_xmlNode ) { |
|
391 | if ( ar_xml::$autoparse ) { |
||
392 | $nodes = $this->_tryToParse( $nodes ); |
||
393 | } else { |
||
394 | $nodes = new ar_xmlNode( $nodes ); |
||
395 | } |
||
396 | } |
||
397 | $result[] = $nodes; |
||
398 | } |
||
399 | return $result; |
||
400 | } |
||
401 | |||
402 | public function __construct() { |
||
403 | $args = func_get_args(); |
||
404 | $nodes = call_user_func_array( array( 'ar_xmlNodes', 'mergeArguments' ), $args ); |
||
405 | $nodes = $this->_normalizeNodes( $nodes ); |
||
406 | parent::__construct($nodes); |
||
407 | } |
||
408 | |||
409 | public function offsetSet($offset, $value) { |
||
410 | if (!$value instanceof ar_xmlNodeInterface) { |
||
411 | $value = new ar_xmlNode( $value ); |
||
412 | } |
||
413 | parent::offsetSet($offset, $value); |
||
414 | } |
||
415 | |||
416 | public function __toString() { |
||
417 | return $this->toString(); |
||
418 | } |
||
419 | |||
420 | public function toString( $indentWith = null ) { |
||
421 | foreach ( $this->attributes as $name => $value ) { |
||
422 | $position = 0; |
||
423 | View Code Duplication | foreach ( $this as $node ) { |
|
424 | if ($node instanceof ar_xmlElement) { |
||
425 | $appliedValue = $this->_applyValues($value, $position); |
||
426 | $node->setAttribute( $name, $appliedValue ); |
||
427 | $position++; |
||
428 | } |
||
429 | } |
||
430 | } |
||
431 | $result = ''; |
||
432 | |||
433 | $position = 0; |
||
434 | foreach ( $this as $node) { |
||
435 | if ( $node instanceof ar_xmlElement) { |
||
436 | $result .= $node->toString($indentWith, $position); |
||
437 | $position++; |
||
438 | } else if ( $node instanceof ar_xmlNode) { |
||
439 | $stringValue = (string) $node; |
||
440 | if ( trim($stringValue) !== "" ) { |
||
441 | $result .= $stringValue; |
||
442 | } |
||
443 | } else if ( $node instanceof ar_xmlNodes) { |
||
444 | $result .= $node->toString( $indentWith ); |
||
445 | } else if ( is_string($node) ) { |
||
446 | $node = trim($node); |
||
447 | if( $node !== "" ) { |
||
448 | $result .= ar_xml::indent( (string) $node, $indentWith); |
||
449 | } |
||
450 | } |
||
451 | } |
||
452 | return $result; |
||
453 | } |
||
454 | |||
455 | |||
456 | public function setAttributes( array $attributes, $dynamic = true ) { |
||
457 | foreach ($attributes as $name => $value) { |
||
458 | $this->setAttribute( $name, $value, $dynamic ); |
||
459 | } |
||
460 | return $this; |
||
461 | } |
||
462 | |||
463 | private function _runPatterns( $value ) { |
||
464 | if ($value instanceof ar_listExpression_Pattern) { |
||
465 | $count = 0; |
||
466 | foreach ( $this as $key => $node ) { |
||
467 | if ($node instanceof ar_xmlElement) { |
||
468 | $count++; |
||
469 | } |
||
470 | } |
||
471 | $value = ar::listExpression( $count )->pattern( $value->patterns ); |
||
472 | } else if ( is_array( $value ) ) { |
||
473 | $newvalue = array(); |
||
474 | foreach ($value as $key => $subvalue ) { |
||
475 | $newvalue[$key] = $this->_runPatterns( $subvalue ); |
||
476 | } |
||
477 | $value = $newvalue; |
||
478 | } |
||
479 | return $value; |
||
480 | } |
||
481 | |||
482 | private function _applyValues( $value, $position = 0 ) { |
||
483 | if ($value instanceof ar_listExpression) { |
||
484 | $result = $value->item( $position ); |
||
485 | } else if ( is_array($value) ) { |
||
486 | $result = array(); |
||
487 | foreach( $value as $key => $subvalue ) { |
||
488 | $result[$key] = $this->_applyValues( $subvalue, $position ); |
||
489 | } |
||
490 | } else { |
||
491 | $result = $value; |
||
492 | } |
||
493 | return $result; |
||
494 | } |
||
495 | |||
496 | public function getAttribute( $name ) { |
||
497 | return $this->attributes[$name]; |
||
498 | } |
||
499 | |||
500 | public function setAttribute( $name, $value, $dynamic = true ) { |
||
501 | $value = $this->_runPatterns($value); |
||
502 | View Code Duplication | if ($dynamic) { |
|
503 | if ( isset($this->attributes[$name]) && is_array($value) && !isset($value[0]) ) { |
||
504 | if (!is_array($this->attributes[$name])) { |
||
505 | $this->attributes[$name] = array( $this->attributes[$name] ); |
||
506 | } |
||
507 | $this->attributes[$name] = array_merge( (array) $this->attributes[$name], $value ); |
||
508 | } else { |
||
509 | $this->attributes[$name] = $value; |
||
510 | } |
||
511 | } |
||
512 | $position = 0; |
||
513 | View Code Duplication | foreach ( $this as $node ) { |
|
514 | if ($node instanceof ar_xmlElement) { |
||
515 | $appliedValue = $this->_applyValues($value, $position); |
||
516 | $node->setAttribute( $name, $appliedValue ); |
||
517 | $position++; |
||
518 | } |
||
519 | } |
||
520 | return $this; |
||
521 | } |
||
522 | |||
523 | public function removeAttribute( $name ) { |
||
524 | if ( isset( $this->attributes[$name] ) ) { |
||
525 | unset( $this->attributes[$name] ); |
||
526 | } |
||
527 | foreach ( $this as $node ) { |
||
528 | if ( $node instanceof ar_xmlElement ) { |
||
529 | $node->removeAttribute( $name ); |
||
530 | } |
||
531 | } |
||
532 | } |
||
533 | |||
534 | public function __get( $name ) { |
||
535 | switch ( $name ) { |
||
536 | case 'parentNode': |
||
537 | return $this->parentNode; |
||
538 | break; |
||
539 | case 'firstChild': |
||
540 | return $this[0]; |
||
541 | break; |
||
542 | case 'lastChild': |
||
543 | return $this[count($this)-1]; |
||
544 | break; |
||
545 | case 'childNodes': |
||
546 | return $this; |
||
547 | break; |
||
548 | case 'nodeValue': |
||
549 | if ( count($this)==1 ) { |
||
550 | return $this[0]->nodeValue; |
||
551 | } else { |
||
552 | $result = array(); |
||
553 | foreach($this as $node) { |
||
554 | $result[] = $node->nodeValue; |
||
555 | } |
||
556 | return $result; |
||
557 | } |
||
558 | break; |
||
559 | case 'attributes': |
||
560 | if ( count($this)==1 ) { |
||
561 | return $this[0]->attributes; |
||
562 | } else { |
||
563 | $result = array(); |
||
564 | foreach($this as $node) { |
||
565 | if ($node instanceof ar_xmlElement || $node instanceof ar_xmlNodes ) { |
||
566 | $result[] = $node->attributes; |
||
567 | } |
||
568 | } |
||
569 | return $result; |
||
570 | } |
||
571 | break; |
||
572 | default: |
||
573 | if (!isset($this->parentNode) && !$this->isDocumentFragment ) { |
||
574 | $result = array(); |
||
575 | foreach ($this as $node) { |
||
576 | if ($node instanceof ar_xmlElement || $node instanceof ar_xmlNodes ) { |
||
577 | $temp = $node->getElementsByTagName( $name, false ); |
||
578 | $result = array_merge( $result, (array) $temp); |
||
579 | } |
||
580 | } |
||
581 | $result = $this->getNodeList( $result ); |
||
582 | $result->isDocumentFragment = false; |
||
583 | return $result; |
||
584 | } else { |
||
585 | return $this->getElementsByTagName( $name, false ); |
||
586 | } |
||
587 | break; |
||
588 | } |
||
589 | } |
||
590 | |||
591 | public function __call( $name, $params ) { |
||
592 | if (($name[0]==='_')) { |
||
593 | $realName = substr($name, 1); |
||
594 | if (ar_pinp::isAllowed($this, $realName)) { |
||
595 | return call_user_func_array(array($this, $realName), $params); |
||
596 | } else { |
||
597 | trigger_error("Method $realName not found in class ".get_class($this), E_USER_ERROR); |
||
598 | } |
||
599 | } else if (isset($this[0]) && is_object($this[0]) ) { |
||
600 | $el = $this[0]; |
||
601 | return call_user_func_array( array( $el, $name ), $params ); |
||
602 | } else { |
||
603 | return null; |
||
604 | } |
||
605 | } |
||
606 | |||
607 | public function __unset( $name ) { |
||
608 | // e.g. unset( $xml->root->child ) |
||
609 | // __unset is called on $xml->root with 'child' as $name |
||
610 | // so find all tags with name 'child' and remove them |
||
611 | // or unset( $xml->root->child[2] ) |
||
612 | // |
||
613 | if (is_numeric($name)) { |
||
614 | $node = $this->childNodes[$name]; |
||
0 ignored issues
–
show
The property
childNodes does not exist on object<ar_xmlNodes> . Since you implemented __get , maybe consider adding a @property annotation.
Since your code implements the magic getter <?php
/**
* @property int $x
* @property int $y
* @property string $text
*/
class MyLabel
{
private $properties;
private $allowedProperties = array('x', 'y', 'text');
public function __get($name)
{
if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
return $properties[$name];
} else {
return null;
}
}
public function __set($name, $value)
{
if (in_array($name, $this->allowedProperties)) {
$properties[$name] = $value;
} else {
throw new \LogicException("Property $name is not defined.");
}
}
}
If the property has read access only, you can use the @property-read annotation instead. Of course, you may also just have mistyped another name, in which case you should fix the error. See also the PhpDoc documentation for @property. ![]() |
|||
615 | $this->removeChild($node); |
||
616 | } else { |
||
617 | $nodes = $this->getElementsByTagname( $name, false ); |
||
618 | $this->removeChild($nodes); |
||
619 | } |
||
620 | } |
||
621 | |||
622 | public function __set( $name, $value ) { |
||
623 | switch( $name ) { |
||
624 | case 'parentNode': |
||
625 | $this->setParentNode($value); |
||
626 | break; |
||
627 | default: |
||
628 | if (is_numeric($name)) { |
||
629 | $node = $this->childNodes[$name]; |
||
0 ignored issues
–
show
The property
childNodes does not exist on object<ar_xmlNodes> . Since you implemented __get , maybe consider adding a @property annotation.
Since your code implements the magic getter <?php
/**
* @property int $x
* @property int $y
* @property string $text
*/
class MyLabel
{
private $properties;
private $allowedProperties = array('x', 'y', 'text');
public function __get($name)
{
if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
return $properties[$name];
} else {
return null;
}
}
public function __set($name, $value)
{
if (in_array($name, $this->allowedProperties)) {
$properties[$name] = $value;
} else {
throw new \LogicException("Property $name is not defined.");
}
}
}
If the property has read access only, you can use the @property-read annotation instead. Of course, you may also just have mistyped another name, in which case you should fix the error. See also the PhpDoc documentation for @property. ![]() |
|||
630 | $this->replaceChild($node, $value); |
||
631 | } else { |
||
632 | switch ( $name ) { |
||
633 | case 'nodeValue': |
||
634 | foreach( $this->childNodes as $node ) { |
||
0 ignored issues
–
show
The property
childNodes does not exist on object<ar_xmlNodes> . Since you implemented __get , maybe consider adding a @property annotation.
Since your code implements the magic getter <?php
/**
* @property int $x
* @property int $y
* @property string $text
*/
class MyLabel
{
private $properties;
private $allowedProperties = array('x', 'y', 'text');
public function __get($name)
{
if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
return $properties[$name];
} else {
return null;
}
}
public function __set($name, $value)
{
if (in_array($name, $this->allowedProperties)) {
$properties[$name] = $value;
} else {
throw new \LogicException("Property $name is not defined.");
}
}
}
If the property has read access only, you can use the @property-read annotation instead. Of course, you may also just have mistyped another name, in which case you should fix the error. See also the PhpDoc documentation for @property. ![]() |
|||
635 | $node->nodeValue = $value; |
||
636 | } |
||
637 | break; |
||
638 | default: |
||
639 | $nodes = $this->getElementsByTagname( $name, false ); |
||
640 | $this->replaceChild($value, $nodes); |
||
641 | break; |
||
642 | } |
||
643 | } |
||
644 | break; |
||
645 | } |
||
646 | } |
||
647 | |||
648 | public function cloneNode( $recurse = false ) { |
||
649 | if (!$recurse) { |
||
650 | $result = $this->getNodeList(); |
||
651 | } else { |
||
652 | $result = clone $this; |
||
653 | $result->parentNode = null; |
||
654 | foreach ( $result as $pos => $el ) { |
||
655 | $result[$pos] = $el->cloneNode($recurse); |
||
656 | } |
||
657 | } |
||
658 | return $result; |
||
659 | } |
||
660 | |||
661 | protected function getNodeList() { |
||
662 | $params = func_get_args(); |
||
663 | return call_user_func_array( array( 'ar_xml', 'nodes'), $params ); |
||
664 | } |
||
665 | |||
666 | function getElementsByTagName( $name, $recurse = true ) { |
||
667 | $nodeList = array(); |
||
668 | foreach ($this as $node) { |
||
669 | if ( $node instanceof ar_xmlElement ) { |
||
670 | if ( $name == '*' || $node->tagName == $name) { |
||
671 | $nodeList[] = $node; |
||
672 | } |
||
673 | if ($recurse) { |
||
674 | $nodeList = array_merge( $nodeList, (array) $node->getElementsByTagName( $name ) ); |
||
675 | } |
||
676 | } |
||
677 | } |
||
678 | $result = $this->getNodeList( $nodeList ); |
||
679 | $result->isDocumentFragment = false; |
||
680 | return $result; |
||
681 | } |
||
682 | |||
683 | function getElementById( $id ) { |
||
684 | if (isset($this->parentNode)) { |
||
685 | return $this->parentNode->getElementById($id); |
||
686 | } else { |
||
687 | foreach ($this as $node ) { |
||
688 | if ( $node instanceof ar_xmlElement ) { |
||
689 | $el = $node->getElementById($id); |
||
690 | if ( isset($el) ) { |
||
691 | return $el; |
||
692 | } |
||
693 | } |
||
694 | } |
||
695 | return null; |
||
696 | } |
||
697 | } |
||
698 | |||
699 | function __clearAllNodes() { |
||
700 | self::__construct(); |
||
701 | } |
||
702 | |||
703 | function setParentNode( ar_xmlElement $el ) { |
||
704 | if ( $el === $this ) { |
||
705 | return false; |
||
706 | } |
||
707 | $this->parentNode = $el; |
||
708 | foreach ($this as $node) { |
||
709 | if ($node instanceof ar_xmlElement) { |
||
710 | if ( isset($node->parentNode) ) { |
||
711 | if ( $node->parentNode !== $el ) { |
||
712 | $node->parentNode->removeChild($node); |
||
713 | } |
||
714 | } else { |
||
715 | $node->parentNode = $el; |
||
0 ignored issues
–
show
The property
$parentNode is declared private in ar_xmlElement . Since you implemented __set() , maybe consider adding a @property or @property-write annotation. This makes it easier for IDEs to provide auto-completion.
Since your code implements the magic setter <?php
/**
* @property int $x
* @property int $y
* @property string $text
*/
class MyLabel
{
private $properties;
private $allowedProperties = array('x', 'y', 'text');
public function __get($name)
{
if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
return $properties[$name];
} else {
return null;
}
}
public function __set($name, $value)
{
if (in_array($name, $this->allowedProperties)) {
$properties[$name] = $value;
} else {
throw new \LogicException("Property $name is not defined.");
}
}
}
Since the property has write access only, you can use the @property-write annotation instead. Of course, you may also just have mistyped another name, in which case you should fix the error. See also the PhpDoc documentation for @property. ![]() |
|||
716 | } |
||
717 | } |
||
718 | } |
||
719 | $this->isDocumentFragment = false; |
||
720 | } |
||
721 | |||
722 | function getPreviousSibling( ar_xmlNode $el ) { |
||
723 | $pos = $this->_getPosition( $el ); |
||
724 | if ( $pos > 0 ) { |
||
725 | return $this[ $pos - 1 ]; |
||
726 | } else { |
||
727 | return null; |
||
728 | } |
||
729 | } |
||
730 | |||
731 | function getNextSibling( ar_xmlNode $el ) { |
||
732 | $pos = $this->_getLastPosition( $el ); |
||
733 | if ( $pos <= count( $this ) ) { |
||
734 | return $this[ $pos ]; |
||
735 | } else { |
||
736 | return null; |
||
737 | } |
||
738 | } |
||
739 | |||
740 | View Code Duplication | function _getPosition( $el ) { |
|
741 | if ( is_array($el) || $el instanceof Traversable ) { |
||
742 | return $this->_getPosition( reset($el) ); |
||
743 | } else { |
||
744 | foreach ( $this as $pos => $node ) { |
||
745 | if ( $node === $el ) { |
||
746 | return $pos; |
||
747 | } |
||
748 | } |
||
749 | } |
||
750 | } |
||
751 | |||
752 | View Code Duplication | function _getLastPosition( $el ) { |
|
753 | if ( is_array($el) || $el instanceof Traversable ) { |
||
754 | return $this->_getLastPosition( end($el) ); |
||
755 | } else { |
||
756 | foreach ( $this as $pos => $node ) { |
||
757 | if ( $node === $el ) { |
||
758 | return $pos+1; |
||
759 | } |
||
760 | } |
||
761 | } |
||
762 | } |
||
763 | |||
764 | private function _removeChildNodes( $el ) { |
||
765 | if ( isset( $this->parentNode ) ) { |
||
766 | if ( is_array( $el ) || $el instanceof Traversable ) { |
||
767 | foreach ( $el as $subEl ) { |
||
768 | if ( isset($subEl->parentNode) ) { |
||
769 | $subEl->parentNode->removeChild( $subEl ); |
||
770 | } |
||
771 | } |
||
772 | } else { |
||
773 | if ( isset($el->parentNode) ) { |
||
774 | $el->parentNode->removeChild( $el ); |
||
775 | } |
||
776 | } |
||
777 | } |
||
778 | } |
||
779 | |||
780 | private function _setParentNodes( $el ) { |
||
781 | if ( isset( $this->parentNode ) ) { |
||
782 | if ( is_array( $el ) || $el instanceof Traversable ) { |
||
783 | foreach ( $el as $subEl ) { |
||
784 | $this->_setParentNodes( $subEl ); |
||
785 | } |
||
786 | } else if ( $el instanceof ar_xmlNode) { |
||
787 | $el->__clearParentIdCache(); |
||
788 | $el->parentNode = $this->parentNode; |
||
0 ignored issues
–
show
The property
$parentNode is declared private in ar_xmlNode . Since you implemented __set() , maybe consider adding a @property or @property-write annotation. This makes it easier for IDEs to provide auto-completion.
Since your code implements the magic setter <?php
/**
* @property int $x
* @property int $y
* @property string $text
*/
class MyLabel
{
private $properties;
private $allowedProperties = array('x', 'y', 'text');
public function __get($name)
{
if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
return $properties[$name];
} else {
return null;
}
}
public function __set($name, $value)
{
if (in_array($name, $this->allowedProperties)) {
$properties[$name] = $value;
} else {
throw new \LogicException("Property $name is not defined.");
}
}
}
Since the property has write access only, you can use the @property-write annotation instead. Of course, you may also just have mistyped another name, in which case you should fix the error. See also the PhpDoc documentation for @property. ![]() |
|||
789 | $el->__restoreParentIdCache(); |
||
790 | } |
||
791 | } |
||
792 | } |
||
793 | |||
794 | function appendChild( $el ) { |
||
795 | $this->_removeChildNodes( $el ); |
||
796 | $result = $this->_appendChild( $el ); |
||
797 | return $result; |
||
798 | } |
||
799 | |||
800 | private function _appendChild( $el ) { |
||
801 | $this->_setParentNodes( $el ); |
||
802 | if ( !is_array( $el ) && !( $el instanceof ArrayObject ) ) { |
||
803 | $list = array( $el ); |
||
804 | } else { |
||
805 | $list = (array) $el; |
||
806 | } |
||
807 | self::__construct( array_merge( (array) $this, $list ) ); |
||
808 | return $el; |
||
809 | } |
||
810 | |||
811 | function insertBefore( $el, ar_xmlNodeInterface $referenceEl = null ) { |
||
812 | $this->_removeChildNodes( $el ); |
||
813 | if ( !isset($referenceEl) ) { |
||
814 | return $this->_appendChild( $el ); |
||
815 | } else { |
||
816 | $pos = $this->_getPosition( $referenceEl ); |
||
817 | View Code Duplication | if ( !isset($pos) ) { |
|
818 | $this->_appendChild( $el ); |
||
819 | } else { |
||
820 | $this->_setParentNodes( $el ); |
||
821 | if ( !is_array( $el ) ) { |
||
822 | $list = array( $el ); |
||
823 | } else { |
||
824 | $list = (array) $el; |
||
825 | } |
||
826 | $arr = (array) $this; |
||
827 | array_splice( $arr, $pos, 0, $list ); |
||
828 | self::__construct( $arr ); |
||
829 | } |
||
830 | } |
||
831 | return $el; |
||
832 | } |
||
833 | |||
834 | function replaceChild( $el, ar_xmlNodeInterface $referenceEl ) { |
||
835 | $this->_removeChildNodes( $el ); |
||
836 | $pos = $this->_getPosition( $referenceEl ); |
||
837 | View Code Duplication | if ( !isset($pos) ) { |
|
838 | return null; |
||
839 | } else { |
||
840 | $this->_setParentNodes( $el ); |
||
841 | if ( !is_array( $el ) ) { |
||
842 | $list = array( $el ); |
||
843 | } else { |
||
844 | $list = (array) $el; |
||
845 | } |
||
846 | $arr = (array) $this; |
||
847 | array_splice( $arr, $pos, 0, $list ); |
||
848 | self::__construct( $arr ); |
||
849 | return $this->removeChild( $referenceEl ); |
||
850 | } |
||
851 | } |
||
852 | |||
853 | public function removeChild( $el ) { |
||
854 | // Warning: must never ever call _removeChildNodes, can be circular. |
||
855 | if ( is_array( $el ) || $el instanceof Traversable) { |
||
856 | foreach( $el as $subEl ) { |
||
857 | $this->removeChild( $subEl ); |
||
858 | } |
||
859 | } else { |
||
860 | $pos = $this->_getPosition( $el ); |
||
861 | if ( isset($pos) ) { |
||
862 | $oldEl = $this[$pos]; |
||
863 | $arr = (array) $this; |
||
864 | array_splice( $arr, $pos, 1); |
||
865 | self::__construct( $arr ); |
||
866 | if ( isset($this->parentNode) ) { |
||
867 | $oldEl->__clearParentIdCache(); |
||
868 | $oldEl->parentNode = null; |
||
869 | } |
||
870 | } else { |
||
871 | return null; |
||
872 | } |
||
873 | } |
||
874 | return $el; |
||
875 | } |
||
876 | |||
877 | public function bind( $nodes, $name, $type = 'string' ) { |
||
878 | $b = new ar_xmlDataBinding( ); |
||
879 | return $b->bind( $nodes, $name, $type ); |
||
880 | } |
||
881 | |||
882 | public function bindAsArray( $nodes, $type = 'string' ) { |
||
883 | $b = new ar_xmlDataBinding( ); |
||
884 | return $b->bindAsArray( $nodes, 'list', $type)->list; |
||
0 ignored issues
–
show
The property
list does not seem to exist in ar_xmlDataBinding .
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. ![]() |
|||
885 | } |
||
886 | |||
887 | } |
||
888 | |||
889 | class ar_xmlNode extends arBase implements ar_xmlNodeInterface { |
||
890 | private $parentNode = null; |
||
891 | private $nodeValue = ''; |
||
892 | public $cdata = false; |
||
893 | |||
894 | function __construct($value, $parentNode = null, $cdata = false) { |
||
895 | $this->nodeValue = $value; |
||
896 | $this->parentNode = $parentNode; |
||
897 | $this->cdata = $cdata; |
||
898 | } |
||
899 | |||
900 | function __toString() { |
||
901 | return $this->toString(); |
||
902 | } |
||
903 | |||
904 | function toString() { |
||
905 | if ($this->cdata) { |
||
906 | return "<![CDATA[" . str_replace("]]>", "]]>", $this->nodeValue) . "]]>"; |
||
907 | } else { |
||
908 | return (string) $this->nodeValue; |
||
909 | } |
||
910 | } |
||
911 | |||
912 | function __get( $name ) { |
||
913 | switch( $name ) { |
||
914 | case 'parentNode': |
||
915 | return $this->parentNode; |
||
916 | break; |
||
917 | case 'previousSibling': |
||
918 | if (isset($this->parentNode)) { |
||
919 | return $this->parentNode->childNodes->getPreviousSibling($this); |
||
920 | } |
||
921 | break; |
||
922 | case 'nextSibling': |
||
923 | if (isset($this->parentNode)) { |
||
924 | return $this->parentNode->childNodes->getNextSibling($this); |
||
925 | } |
||
926 | break; |
||
927 | case 'nodeValue': |
||
928 | return $this->nodeValue; |
||
929 | break; |
||
930 | } |
||
931 | } |
||
932 | |||
933 | function __set( $name, $value ) { |
||
934 | switch ($name) { |
||
935 | case 'nodeValue': |
||
936 | $this->nodeValue = $value; |
||
937 | break; |
||
938 | View Code Duplication | case 'parentNode': |
|
939 | if ( $value === $this || !( $value instanceof ar_xmlElement ) ) { |
||
940 | $this->parentNode = null; |
||
941 | } else { |
||
942 | $this->parentNode = $value; |
||
943 | } |
||
944 | break; |
||
945 | } |
||
946 | } |
||
947 | |||
948 | function __isset( $name ) { |
||
949 | $value = $this->__get($name); |
||
950 | return isset($value); |
||
951 | } |
||
952 | |||
953 | function __clone() { |
||
954 | $this->parentNode = null; |
||
955 | } |
||
956 | |||
957 | function cloneNode( $recurse = false ) { |
||
958 | return clone($this); |
||
959 | } |
||
960 | |||
961 | public function __clearParentIdCache() { |
||
962 | } |
||
963 | |||
964 | public function __restoreParentIdCache() { |
||
965 | } |
||
966 | |||
967 | } |
||
968 | |||
969 | class ar_xmlElement extends ar_xmlNode implements ar_xmlNodeInterface { |
||
970 | public $tagName = null; |
||
971 | public $attributes = array(); |
||
972 | private $childNodes = null; |
||
973 | private $parentNode = null; |
||
0 ignored issues
–
show
|
|||
974 | private $idCache = array(); |
||
975 | private $nodeValue = ''; |
||
0 ignored issues
–
show
|
|||
976 | |||
977 | function __construct($name, $attributes = null, $childNodes = null, $parentNode = null) { |
||
978 | $this->tagName = $name; |
||
979 | $this->parentNode = $parentNode; |
||
980 | $this->childNodes = $this->getNodeList(); |
||
981 | $this->childNodes->setParentNode( $this ); |
||
982 | if ($childNodes) { |
||
983 | $this->appendChild( $childNodes ); |
||
984 | } |
||
985 | if ($attributes) { |
||
986 | $this->setAttributes( $attributes ); |
||
987 | } |
||
988 | } |
||
989 | |||
990 | View Code Duplication | public function __clearParentIdCache() { |
|
991 | if ( isset($this->parentNode) && count( $this->idCache ) ) { |
||
992 | foreach( $this->idCache as $id => $value ) { |
||
993 | $this->parentNode->__updateIdCache($id, null, $value); |
||
994 | } |
||
995 | } |
||
996 | } |
||
997 | |||
998 | View Code Duplication | public function __restoreParentIdCache() { |
|
999 | if ( isset($this->parentNode) && count( $this->idCache ) ) { |
||
1000 | foreach( $this->idCache as $id => $value ) { |
||
1001 | $this->parentNode->__updateIdCache($id, $value); |
||
1002 | } |
||
1003 | } |
||
1004 | } |
||
1005 | |||
1006 | public function __updateIdCache($id, $el, $oldEl = null) { |
||
1007 | if ( !isset($el) ) { |
||
1008 | // remove id cache entry |
||
1009 | if ( isset($this->idCache[$id]) && ($this->idCache[$id]===$oldEl) ) { |
||
1010 | // only remove id cache pointers to the correct element |
||
1011 | unset($this->idCache[$id]); |
||
1012 | } |
||
1013 | } else { |
||
1014 | $this->idCache[$id] = $el; |
||
1015 | } |
||
1016 | if (isset($this->parentNode) && $this->parentNode !== $this) { // Prevent loops if the parentNode is this object. |
||
1017 | $this->parentNode->__updateIdCache($id, $el, $oldEl); |
||
1018 | } |
||
1019 | } |
||
1020 | |||
1021 | function setAttributes( $attributes ) { |
||
1022 | foreach ( $attributes as $name => $value ) { |
||
1023 | $this->setAttribute( $name, $value ); |
||
1024 | } |
||
1025 | return $this; |
||
1026 | } |
||
1027 | |||
1028 | function getAttribute( $name ) { |
||
1029 | return $this->attributes[$name]; |
||
1030 | } |
||
1031 | |||
1032 | function setAttribute( $name, $value ) { |
||
1033 | if ( $name == 'id' ) { |
||
1034 | $oldId = null; |
||
1035 | if (isset($this->attributes['id'])) { |
||
1036 | $oldId = $this->attributes['id']; |
||
1037 | } |
||
1038 | } |
||
1039 | View Code Duplication | if ( is_array($value) && !isset($value[0]) ) { |
|
1040 | // this bit of magic allows ar_xmlNodes->setAttribute to override only |
||
1041 | // specific attribute values, leaving others alone, by specifying a |
||
1042 | // non-number key. |
||
1043 | if ( !is_array($this->attributes[$name]) ) { |
||
1044 | $this->attributes[$name] = array( $this->attributes[$name] ); |
||
1045 | } |
||
1046 | $this->attributes[$name] = array_merge( $this->attributes[$name], $value ); |
||
1047 | } else { |
||
1048 | $this->attributes[$name] = $value; |
||
1049 | } |
||
1050 | if ('id'==(string)$name) { // string cast is necessary, otherwise if $name is 0, 'id' will be cast to int, which is also 0... |
||
1051 | if ( isset($oldId) ) { |
||
1052 | $this->__updateIdCache( $oldId, null, $this ); |
||
1053 | } |
||
1054 | $this->__updateIdCache($value, $this); |
||
1055 | } |
||
1056 | return $this; |
||
1057 | } |
||
1058 | |||
1059 | function removeAttribute( $name ) { |
||
1060 | if ( isset( $this->attributes[$name] ) ) { |
||
1061 | unset( $this->attributes[$name] ); |
||
1062 | } |
||
1063 | } |
||
1064 | |||
1065 | function __toString() { |
||
1066 | return $this->toString(); |
||
1067 | } |
||
1068 | |||
1069 | function toString( $indent = '', $current = 0 ) { |
||
1070 | $indent = ar_xml::$indenting ? $indent : ''; |
||
1071 | $result = "\n" . $indent . '<' . ar_xml::name( $this->tagName ); |
||
1072 | View Code Duplication | if ( is_array($this->attributes) ) { |
|
1073 | foreach ( $this->attributes as $name => $value ) { |
||
1074 | $result .= ar_xml::attribute($name, $value, $current); |
||
1075 | } |
||
1076 | } else if ( is_string($this->attributes) ) { |
||
1077 | $result .= ltrim(' '.$this->attributes); |
||
1078 | } |
||
1079 | if ( $this->childNodes instanceof ar_xmlNodes && count($this->childNodes) ) { |
||
1080 | $result .= '>'; |
||
1081 | $result .= $this->childNodes->toString( ar_xml::$indent . $indent ); |
||
1082 | if ( substr($result, -1) == ">") { |
||
1083 | $result .= "\n" . $indent; |
||
1084 | } |
||
1085 | $result .= '</' . ar_xml::name( $this->tagName ) . '>'; |
||
1086 | } else { |
||
1087 | $result .= ' />'; |
||
1088 | } |
||
1089 | return $result; |
||
1090 | } |
||
1091 | |||
1092 | public function getNodeList() { |
||
1093 | $params = func_get_args(); |
||
1094 | return call_user_func_array( array( 'ar_xml', 'nodes'), $params ); |
||
1095 | } |
||
1096 | |||
1097 | function __get( $name ) { |
||
1098 | switch( $name ) { |
||
1099 | case 'parentNode': |
||
1100 | return $this->parentNode; |
||
1101 | break; |
||
1102 | case 'firstChild': |
||
1103 | if (isset($this->childNodes) && count($this->childNodes)) { |
||
1104 | return $this->childNodes[0]; |
||
1105 | } |
||
1106 | break; |
||
1107 | case 'lastChild': |
||
1108 | if (isset($this->childNodes) && count($this->childNodes)) { |
||
1109 | return $this->childNodes[count($this->childNodes)-1]; |
||
1110 | } |
||
1111 | break; |
||
1112 | case 'childNodes': |
||
1113 | return $this->childNodes; |
||
1114 | break; |
||
1115 | case 'nodeValue': |
||
1116 | //echo get_class($this->childNodes[0]).'('.$this->childNodes[0].')'; |
||
1117 | if (isset($this->childNodes) && count($this->childNodes) ) { |
||
1118 | return $this->childNodes->nodeValue; |
||
1119 | } |
||
1120 | break; |
||
1121 | } |
||
1122 | $result = parent::__get( $name ); |
||
1123 | if ( isset($result) ) { |
||
1124 | return $result; |
||
1125 | } |
||
1126 | return $this->getElementsByTagName( $name, false ); |
||
1127 | } |
||
1128 | |||
1129 | function __set( $name, $value ) { |
||
1130 | switch ( $name ) { |
||
1131 | case 'previousSibling': |
||
1132 | case 'nextSibling': |
||
1133 | break; |
||
1134 | View Code Duplication | case 'parentNode': |
|
1135 | if ( $value === $this || !($value instanceof ar_xmlElement) ) { |
||
1136 | $this->parentNode = null; |
||
1137 | } else { |
||
1138 | $this->parentNode = $value; |
||
1139 | } |
||
1140 | break; |
||
1141 | case 'nodeValue': |
||
1142 | if ( isset($this->childNodes) && count($this->childNodes) ) { |
||
1143 | $this->removeChild( $this->childNodes ); |
||
1144 | } |
||
1145 | $this->appendChild( $value ); |
||
1146 | break; |
||
1147 | case 'childNodes': |
||
1148 | if ( !isset($value) ) { |
||
1149 | $value = $this->getNodeList(); |
||
1150 | } else if ( !($value instanceof ar_xmlNodes) ) { |
||
1151 | $value = $this->getNodeList($value); |
||
1152 | } |
||
1153 | $this->childNodes->setParentNode( null ); |
||
1154 | $this->childNodes = $value; |
||
1155 | $this->childNodes->setParentNode( $this ); |
||
1156 | break; |
||
1157 | default: |
||
1158 | $nodeList = $this->__get( $name ); |
||
1159 | $this->replaceChild( $value, $nodeList ); |
||
1160 | break; |
||
1161 | } |
||
1162 | } |
||
1163 | |||
1164 | function __clone() { |
||
1165 | parent::__clone(); |
||
1166 | $this->childNodes = $this->getNodeList(); |
||
1167 | } |
||
1168 | |||
1169 | function cloneNode( $recurse = false ) { |
||
1170 | $childNodes = $this->childNodes->cloneNode( $recurse ); |
||
1171 | $result = parent::cloneNode( $recurse ); |
||
1172 | $result->childNodes = $childNodes; |
||
1173 | return $result; |
||
1174 | } |
||
1175 | |||
1176 | function getElementsByTagName( $name , $recurse = true ) { |
||
1177 | if ( isset( $this->childNodes ) ) { |
||
1178 | return $this->childNodes->getElementsByTagName( $name, $recurse ); |
||
1179 | } |
||
1180 | } |
||
1181 | |||
1182 | function getElementById( $id ) { |
||
1183 | if (isset($this->idCache[ (string) $id ])) { |
||
1184 | return $this->idCache[ (string) $id ]; |
||
1185 | } |
||
1186 | } |
||
1187 | |||
1188 | function appendChild( $el ) { |
||
1189 | return $this->childNodes->appendChild( $el ); |
||
1190 | } |
||
1191 | |||
1192 | function insertBefore( $el, $referenceEl = null ) { |
||
1193 | return $this->childNodes->insertBefore( $el, $referenceEl ); |
||
1194 | } |
||
1195 | |||
1196 | function replaceChild( $el, $referenceEl ) { |
||
1197 | return $this->childNodes->replaceChild( $el, $referenceEl ); |
||
1198 | } |
||
1199 | |||
1200 | function removeChild( $el ) { |
||
1201 | return $this->childNodes->removeChild( $el ); |
||
1202 | } |
||
1203 | |||
1204 | public function bind( $nodes, $name, $type = 'string' ) { |
||
1205 | $b = new ar_xmlDataBinding( ); |
||
1206 | return $b->bind( $nodes, $name, $type ); |
||
1207 | } |
||
1208 | |||
1209 | public function bindAsArray( $nodes, $type = 'string' ) { |
||
1210 | $b = new ar_xmlDataBinding( ); |
||
1211 | return $b->bindAsArray( $nodes, 'list', $type)->list; |
||
0 ignored issues
–
show
The property
list does not seem to exist in ar_xmlDataBinding .
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. ![]() |
|||
1212 | } |
||
1213 | |||
1214 | } |
||
1215 | |||
1216 | class ar_xmlDataBinding extends arBase { |
||
1217 | |||
1218 | public function bindAsArray( $nodes, $name, $type='string') { |
||
1219 | $this->{$name} = array(); |
||
1220 | |||
1221 | foreach ( $nodes as $key => $node ) { |
||
1222 | $this->{$name}[$key] = $this->bindValue( $node, $type); |
||
1223 | } |
||
1224 | return $this; |
||
1225 | } |
||
1226 | |||
1227 | public function bind( $node, $name, $type='string' ) { |
||
1228 | if ( ( is_array($node) || ( $node instanceof Countable ) ) && count($node)>1 ) { |
||
1229 | return $this->bindAsArray( $node, $name, $type ); |
||
1230 | } |
||
1231 | $this->{$name} = $this->bindValue( $node, $type ); |
||
1232 | return $this; |
||
1233 | } |
||
1234 | |||
1235 | public function __toString() { |
||
1236 | return $this->source->toString(); |
||
0 ignored issues
–
show
The property
source does not exist. Did you maybe forget to declare it?
In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code: class MyClass { }
$x = new MyClass();
$x->foo = true;
Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion: class MyClass {
public $foo;
}
$x = new MyClass();
$x->foo = true;
![]() |
|||
1237 | } |
||
1238 | |||
1239 | protected function bindValue( $source, $type ) { |
||
1240 | if ( $source instanceof ar_xmlNode || $source instanceof ar_xmlNodes ) { |
||
1241 | $nodeValue = $source->nodeValue; |
||
1242 | if (is_array($nodeValue) && !count($nodeValue)) { |
||
1243 | $nodeValue = null; |
||
1244 | } |
||
1245 | } else { |
||
1246 | $nodeValue = $source; |
||
1247 | } |
||
1248 | if ( is_callable($type) ) { |
||
1249 | $nodeValue = call_user_func( $type, $source ); |
||
1250 | } else { |
||
1251 | switch ($type) { |
||
1252 | case 'int': |
||
1253 | $nodeValue = (int) $nodeValue; |
||
1254 | break; |
||
1255 | case 'float': |
||
1256 | $nodeValue = (float) $nodeValue; |
||
1257 | break; |
||
1258 | case 'string': |
||
1259 | $nodeValue = (string) $nodeValue; |
||
1260 | break; |
||
1261 | case 'bool': |
||
1262 | $nodeValue = (bool) $nodeValue; |
||
1263 | break; |
||
1264 | case 'url': |
||
1265 | $nodeValue = ar::url( $nodeValue ); |
||
1266 | break; |
||
1267 | case 'xml': |
||
1268 | case 'html': |
||
1269 | if ($source instanceof ar_xmlNode || $source instanceof ar_xmlNodes) { |
||
1270 | $nodeValue = (string) $source; |
||
1271 | } |
||
1272 | break; |
||
1273 | default: |
||
1274 | if ( is_string($type) && class_exists($type) && ar_pinp::isAllowed($type, '__construct') ) { |
||
1275 | $nodeValue = new $type($nodeValue); |
||
1276 | } |
||
1277 | break; |
||
1278 | } |
||
1279 | } |
||
1280 | return $nodeValue; |
||
1281 | } |
||
1282 | |||
1283 | } |
||
1284 |
This check marks private properties in classes that are never used. Those properties can be removed.