Completed
Push — feature/issue-41 ( e1ed04...1cc60c )
by Mikaël
24:28
created

AbstractElementHandler::getAttribute()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
cc 2
eloc 2
nc 2
nop 1
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 584
    public function __construct(\DOMElement $element, AbstractDomDocumentHandler $domDocument, $index = -1)
13
    {
14 584
        parent::__construct($element, $domDocument, $index);
15 584
    }
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 52
    public function getAttributeValue($name, $withNamespace = false, $withinItsType = true, $asType = AbstractAttributeHandler::DEFAULT_VALUE_TYPE)
53 3
    {
54 52
        $value = null;
55 52
        $attribute = $this->getAttribute($name);
56 52
        if ($attribute instanceof AbstractAttributeHandler) {
57 52
            $value = $attribute->getValue($withNamespace, $withinItsType, $asType);
58 39
        }
59 52
        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 16
    public function getMaxOccurs()
110
    {
111 16
        $maxOccurs = $this->getAttributeValue(AbstractAttributeHandler::ATTRIBUTE_MAX_OCCURS);
112 16
        if ($maxOccurs === AbstractAttributeHandler::VALUE_UNBOUNDED) {
113 8
            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 8
        if (!is_numeric($maxOccurs)) {
116
            return AbstractAttributeHandler::DEFAULT_OCCURENCE_VALUE;
117
        }
118 8
        return (int) $maxOccurs;
119
    }
120
    /**
121
     * Info at {@link https://www.w3.org/TR/xmlschema-0/#OccurrenceConstraints}
122
     * @return int
123
     */
124 32
    public function getMinOccurs()
125
    {
126 32
        $minOccurs = $this->getAttributeValue(AbstractAttributeHandler::ATTRIBUTE_MIN_OCCURS);
127 32
        if (!is_numeric($minOccurs)) {
128
            return AbstractAttributeHandler::DEFAULT_OCCURENCE_VALUE;
129
        }
130 32
        return (int) $minOccurs;
131
    }
132
    /**
133
     * Info at {@link https://www.w3.org/TR/xmlschema-0/#OccurrenceConstraints}
134
     * @return bool
135
     */
136 4
    public function canOccurSeveralTimes()
137
    {
138 4
        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