Completed
Pull Request — master (#18)
by Auke
02:15
created

Proxy::_getTargetProperty()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 12
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 3

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 12
ccs 10
cts 10
cp 1
rs 9.4285
cc 3
eloc 9
nc 3
nop 1
crap 3
1
<?php
2
/*
3
 * This file is part of the Ariadne Component Library.
4
 *
5
 * (c) Muze <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
11
namespace arc\xml;
12
13
/**
14
 * This class is a proxy for both the SimpleXMLElement and DOMElement 
15
 * properties and methods.
16
 */
17
class Proxy extends \ArrayObject implements DOMElement, SimpleXMLElement {
18
19
    use \arc\traits\Proxy {
20
        \arc\traits\Proxy::__construct as private ProxyConstruct;
21
        \arc\traits\Proxy::__call as private ProxyCall;
22
    }
23
24
    private $parser = null;
25
26 5
    public function __construct( $node, $parser) {
27 5
        $this->ProxyConstruct( $node );
28 5
        $this->parser = $parser;
29 5
    }
30
31 1
    public function __toString() {
32 1
        return $this->target->asXML();
33
    }
34
35 2
    private function _isDomProperty( $name ) {
36
        $domProperties = [
37 2
            'tagName', 'nodeType', 'parentNode', 
38 2
            'firstChild', 'lastChild', 'previousSibling', 'nextSibling',
39 2
            'ownerDocument', 'namespaceURI', 'prefix', 
40 2
            'localName', 'baseURI', 'textContent'
41 2
        ];
42 2
        return in_array( $name, $domProperties );
43
    }
44
45 2
    private function _getTargetProperty($name) {
46 2
        $value = null;
47 2
        if ( !$this->_isDomProperty($name) ) {
48 2
            $value = $this->target->{$name};
49 2
        } else {
50 1
            $dom = dom_import_simplexml($this->target);
51 1
            if ( isset($dom) ) {
52 1
                $value = $dom->{$name};
53 1
            }
54
        }
55 2
        return $value;
56
    }
57
58 2
    private function _proxyResult( $value ) {
59 2
        if ( $value instanceof \DOMElement ) {
60
            $value = simplexml_import_dom($value);
61
        }
62 2
        if ( $value instanceof \SimpleXMLElement ) {
63 2
            return new static( $value, $this->parser );
64
        } else {
65 1
            return $value;
66
        }
67
    }
68
69 4
    public function __get( $name) {
70 4
        if ($name == 'nodeValue') {
71 4
            return $this->target;
72
        }
73 2
        return $this->_proxyResult( $this->_getTargetProperty($name) );
74
    }
75
    
76 2
    private function _domCall( $name, $args ) {
77 2
        $dom = dom_import_simplexml($this->target);
78 2
        foreach ( $args as $index => $arg ) {
79 2
            if ( $arg instanceof \arc\xml\Proxy ) {
80 1
                $args[$index] = dom_import_simplexml( $arg->nodeValue );
0 ignored issues
show
Documentation introduced by
The property nodeValue does not exist on object<arc\xml\Proxy>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?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.

Loading history...
81 2
            } else if ( $arg instanceof \SimpleXMLElement ) {
82
                $args[$index] = dom_import_simplexml( $arg );
83
            }
84 2
        }
85
        $importMethods = [
86 2
            'appendChild', 'insertBefore', 'replaceChild'
87 2
        ];
88 2
        if ( in_array( $name, $importMethods ) ) {
89 1
            if ( isset($args[0]) && $args[0] instanceof \DOMNode ) {
90 1
                if ( $args[0]->ownerDocument !== $this->ownerDocument ) {
0 ignored issues
show
Documentation introduced by
The property ownerDocument does not exist on object<arc\xml\Proxy>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?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.

Loading history...
91 1
                    $args[0] = $this->ownerDocument->importNode( $args[0], true);
0 ignored issues
show
Documentation introduced by
The property ownerDocument does not exist on object<arc\xml\Proxy>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?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.

Loading history...
92 1
                }
93 1
            }
94 1
        }
95 2
        $result = call_user_func_array( [ $dom, $name], $args );
96 2
        if ( isset($result) && is_object($result) ) {
97 1
            if ( $result instanceof \DOMElement ) {
98 1
                return new static( $result, $this->parser );
99
            }
100
            if ( $result instanceof \DOMNodeList ) {
101
                $resultArray = [];
102
                for ( $i=0, $l=$result->length; $i<$l; $i ++ ) {
103
                    $resultArray[$i] = new static( simplexml_import_dom($result->item($i)), $this->parser );
104
                }
105
                return $resultArray;
106
            }
107
        }
108 1
        return $result;
109
    }
110
111 2
    public function __call( $name, $args ) {
112 2
        if ( !method_exists($this->target, $name) ) {
113 2
            return $this->_domCall( $name, $args );
114
        } else {
115 2
            return $this->ProxyCall($name, $args);
116
        }
117
    }
118
119
    /**
120
     * Search through the XML DOM with a single CSS selector
121
     * @param string $query the CSS selector, most CSS 2 selectors work
122
     * @return Proxy
123
     */
124 2
    public function find( $query) {
125 2
        $xpath = \arc\xml::css2Xpath( $query );
126 2
        $temp = $this->target->xpath( $xpath );
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 2 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
127 2
        foreach ($temp as $key => $value) {
128 2
            $temp[ $key ] = new static( $value, $this->parser );
129 2
        }
130 2
        return $temp;
131
    }
132
    
133 2
    public function offsetGet( $offset )
134
    {
135 2
        return (string) $this->target[$offset];
136
    }
137
    
138 1
    public function offsetSet( $offset, $value )
139
    {
140 1
        $this->target[$offset] = $value;
141 1
    }
142
    
143
    public function offsetUnset( $offset )
144
    {
145
        unset( $this->target[$offset] );
146
    }
147
}
148