Completed
Push — feature/issue-41 ( 43d9dd...2e4a51 )
by Mikaël
42:29 queued 19:47
created

AbstractElementHandler::getAttributeValue()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 9
ccs 8
cts 8
cp 1
rs 9.6666
cc 2
eloc 6
nc 2
nop 4
crap 2
1
<?php
2
3
namespace WsdlToPhp\PackageGenerator\DomHandler;
4
5
abstract class AbstractElementHandler extends AbstractNodeHandler
6
{
7
    /**
8
     * @param \DOMElement $element
9
     * @param AbstractDomDocumentHandler $domDocument
10
     * @param int $index
11
     */
12 588
    public function __construct(\DOMElement $element, AbstractDomDocumentHandler $domDocument, $index = -1)
13
    {
14 588
        parent::__construct($element, $domDocument, $index);
15 588
    }
16
    /**
17
     * @see \WsdlToPhp\PackageGenerator\DomHandler\AbstractNodeHandler::getNode()
18
     * @return \DOMElement
19
     */
20 548
    public function getNode()
21
    {
22 548
        return parent::getNode();
23
    }
24
    /**
25
     * Alias to getNode()
26
     * @return \DOMElement
27
     */
28 512
    public function getElement()
29
    {
30 512
        return $this->getNode();
31
    }
32
    /**
33
     * @param string $name
34
     * @return boolean
35
     */
36 504
    public function hasAttribute($name)
37
    {
38 504
        return $this->getElement()->hasAttribute($name);
39
    }
40
    /**
41
     * @param string $name
42
     * @return AttributeHandler|null
43
     */
44 500
    public function getAttribute($name)
45
    {
46 500
        return $this->hasAttribute($name) ? $this->getDomDocumentHandler()->getHandler($this->getNode()->getAttributeNode($name)) : null;
47
    }
48
    /**
49
     * @param string $name
50
     * @return mixed
51
     */
52 284
    public function getAttributeValue($name, $withNamespace = false, $withinItsType = true, $asType = AbstractAttributeHandler::DEFAULT_VALUE_TYPE)
53 3
    {
54 284
        $value = null;
55 284
        $attribute = $this->getAttribute($name);
56 284
        if ($attribute instanceof AbstractAttributeHandler) {
57 248
            $value = $attribute->getValue($withNamespace, $withinItsType, $asType);
58 186
        }
59 284
        return $value;
60
    }
61
    /**
62
     * @param string $name
63
     * @return NodeHandler[]|ElementHandler[]
64
     */
65 264
    public function getChildrenByName($name)
66
    {
67 264
        $children = array();
68 264
        if ($this->hasChildren()) {
69 264
            foreach ($this->getElement()->getElementsByTagName($name) as $index=>$node) {
70 256
                $children[] = $this->getDomDocumentHandler()->getHandler($node, $index);
71 198
            }
72 198
        }
73 264
        return $children;
74
    }
75
    /**
76
     * @return ElementHandler[]
77
     */
78 92
    public function getElementChildren()
79
    {
80 92
        $children = array();
81 92
        if ($this->hasChildren()) {
82 68
            $children = $this->getDomDocumentHandler()->getElementsHandlers($this->getChildNodes());
83 51
        }
84 92
        return $children;
85
    }
86
    /**
87
     * @param string $name
88
     * @param array $attributes
89
     * @return ElementHandler[]
90
     */
91 76
    public function getChildrenByNameAndAttributes($name, array $attributes)
92
    {
93 76
        return $this->getDomDocumentHandler()->getElementsByNameAndAttributes($name, $attributes, $this->getNode());
94
    }
95
    /**
96
     * @param string $name
97
     * @param array $attributes
98
     * @return ElementHandler|null
99
     */
100 76
    public function getChildByNameAndAttributes($name, array $attributes)
101
    {
102 76
        $children = $this->getChildrenByNameAndAttributes($name, $attributes);
103 76
        return empty($children) ? null : array_shift($children);
104
    }
105
    /**
106
     * Info at {@link https://www.w3.org/TR/xmlschema-0/#OccurrenceConstraints}
107
     * @return int
108
     */
109 248
    public function getMaxOccurs()
110
    {
111 248
        $maxOccurs = $this->getAttributeValue(AbstractAttributeHandler::ATTRIBUTE_MAX_OCCURS);
112 248
        if ($maxOccurs === AbstractAttributeHandler::VALUE_UNBOUNDED) {
113 196
            return $maxOccurs;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $maxOccurs; (integer|double|boolean|object|string|array|null) is incompatible with the return type documented by WsdlToPhp\PackageGenerat...ntHandler::getMaxOccurs of type integer.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
114
        }
115 240
        if (!is_numeric($maxOccurs)) {
116 88
            return AbstractAttributeHandler::DEFAULT_OCCURENCE_VALUE;
117
        }
118 168
        return (int) $maxOccurs;
119
    }
120
    /**
121
     * Info at {@link https://www.w3.org/TR/xmlschema-0/#OccurrenceConstraints}
122
     * @return int
123
     */
124 264
    public function getMinOccurs()
125
    {
126 264
        $minOccurs = $this->getAttributeValue(AbstractAttributeHandler::ATTRIBUTE_MIN_OCCURS);
127 264
        if (!is_numeric($minOccurs)) {
128 84
            return AbstractAttributeHandler::DEFAULT_OCCURENCE_VALUE;
129
        }
130 228
        return (int) $minOccurs;
131
    }
132
    /**
133
     * Info at {@link https://www.w3.org/TR/xmlschema-0/#OccurrenceConstraints}
134
     * @return bool
135
     */
136 236
    public function canOccurSeveralTimes()
137
    {
138 236
        return ($this->getMinOccurs() > 1) || ($this->getMaxOccurs() > 1) || ($this->getMaxOccurs() === AbstractAttributeHandler::VALUE_UNBOUNDED);
139
    }
140
    /**
141
     * Info at {@link https://www.w3.org/TR/xmlschema-0/#OccurrenceConstraints}
142
     * @return bool
143
     */
144 8
    public function canOccurOnlyOnce()
145
    {
146 8
        return ($this->getMinOccurs() === 1) || ($this->getMaxOccurs()  === 1);
147
    }
148
    /**
149
     * Info at {@link https://www.w3.org/TR/xmlschema-0/#OccurrenceConstraints}
150
     * @return bool
151
     */
152 4
    public function isOptional()
153
    {
154 4
        return $this->getMinOccurs() === 0;
155
    }
156
    /**
157
     * Info at {@link https://www.w3.org/TR/xmlschema-0/#OccurrenceConstraints}
158
     * @return bool
159
     */
160 8
    public function isRequired()
161
    {
162 8
        return $this->getMinOccurs() >= 1;
163
    }
164
}
165