Completed
Push — master ( 25a367...4e273e )
by Adrian
03:50
created

HasChildrenTrait   A

Complexity

Total Complexity 26

Size/Duplication

Total Lines 175
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 1

Test Coverage

Coverage 90%

Importance

Changes 7
Bugs 1 Features 1
Metric Value
wmc 26
c 7
b 1
f 1
lcom 1
cbo 1
dl 0
loc 175
ccs 45
cts 50
cp 0.9
rs 10

9 Methods

Rating   Name   Duplication   Size   Complexity  
A getFullChildName() 0 4 1
A getElement() 0 4 2
A hasElement() 0 4 1
B addElement() 0 22 4
A createChildren() 0 10 4
A removeElement() 0 8 2
B childComparator() 0 20 7
A getElements() 0 7 1
A cleanUpMissingGroups() 0 9 4
1
<?php
2
3
namespace Sirius\Input\Traits;
4
5
use Sirius\Input\Element;
6
use Sirius\Input\Element\FactoryAwareInterface;
7
use Sirius\Input\Specs;
8
9
trait HasChildrenTrait
10
{
11
    /**
12
     * List of the child element
13
     *
14
     * @var array
15
     */
16
    protected $elements = array();
17
18
    /**
19
     * Value to keep track of the order the elements were added
20
     *
21
     * @var int
22
     */
23
    protected $elementsIndex = PHP_INT_MAX;
24
25
    /**
26
     * Generates the actual name that will be used to identify the element in the input object
27
     * For input objects the name of the child is the same as the name provided,
28
     * For field-sets the name of the child is prefixed/name-spaced with the name of the field-set
29
     * For collections the name of the child is prefixed with the name of the collection and an index placeholder
30
     *
31
     * @param string $name
32
     *
33
     * @return string
34
     */
35 12
    protected function getFullChildName($name)
36
    {
37 12
        return $name;
38
    }
39
40
    /**
41
     * Add an element to the children list
42
     *
43
     * @param string|\Sirius\Input\Element $nameOrElement
44
     * @param array $specs
45
     *
46
     * @throws \RuntimeException
47
     * @return $this
48
     */
49 19
    public function addElement($nameOrElement, $specs = array())
50
    {
51 19
        if (is_string($nameOrElement)) {
52 16
            $name    = $nameOrElement;
53 16
            $element = $this->elementFactory->createFromOptions($this->getFullChildName($nameOrElement), $specs);
0 ignored issues
show
Bug introduced by
The property elementFactory 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;
Loading history...
54
        } elseif ($nameOrElement instanceof Element) {
55 4
            $element = $nameOrElement;
56
            // for an element with the name 'address[street]' we get only the 'street'
57
            // because we assume the element has the name constructed using the rule in getFullChildName()
58 4
            $parts = explode('[', str_replace(']', '', $element->getName()));
59 4
            $name  = array_pop($parts);
60
        } else {
61 1
            throw new \RuntimeException(sprintf('Variable $nameorElement must be a string or an instance of the Element class'));
62
        }
63
        // add the index for sorting
64 18
        if (!isset($element['__index'])) {
65 18
            $element['__index'] = ($this->elementsIndex--);
66
        }
67 18
        $this->elements[$name] = $element;
68
69 18
        return $this;
70
    }
71
72
    /**
73
     *
74
     */
75 9
    protected function createChildren()
76
    {
77 9
        if ($this instanceof FactoryAwareInterface) {
78 9
            if (isset($this[Specs::CHILDREN])) {
79 1
                foreach ($this[Specs::CHILDREN] as $name => $options) {
80 1
                    $this->addElement($name, $options);
81
                }
82
            }
83
        }
84 9
    }
85
86
    /**
87
     * Retrieve an element by name
88
     *
89
     * @param string $name
90
     *
91
     * @return \Sirius\Input\Element
92
     */
93 9
    public function getElement($name)
94
    {
95 9
        return isset($this->elements[$name]) ? $this->elements[$name] : null;
96
    }
97
98
    /**
99
     * Removes an element from the children list
100
     *
101
     * @param string $name
102
     *
103
     * @throws \RuntimeException
104
     * @return $this
105
     */
106 3
    public function removeElement($name)
107
    {
108 3
        if (isset($this->elements[$name])) {
109 3
            unset($this->elements[$name]);
110
        }
111
112 3
        return $this;
113
    }
114
115
    /**
116
     * Returns whether an element exist in the children list
117
     *
118
     * @param string $name
119
     *
120
     * @return boolean
121
     */
122 3
    public function hasElement($name)
123
    {
124 3
        return null !== $this->getElement($name);
125
    }
126
127
    /**
128
     * Input comparator callback
129
     *
130
     * @param \ArrayObject $childA
131
     * @param \ArrayObject $childB
132
     *
133
     * @return integer
134
     */
135 7
    protected function childComparator($childA, $childB)
136
    {
137 7
        $posA = isset($childA[Specs::POSITION]) ? $childA[Specs::POSITION] : 0;
138 7
        $posB = isset($childB[Specs::POSITION]) ? $childB[Specs::POSITION] : 0;
139 7
        if ($posA < $posB) {
140
            return - 1;
141
        }
142 7
        if ($posA > $posB) {
143 3
            return 1;
144
        }
145 7
        if ($childA['__index'] > $childB['__index']) {
146 7
            return - 1;
147
        }
148
        if ($childA['__index'] < $childB['__index']) {
149
            return 1;
150
        }
151
152
        // if the priority is the same, childB is first
153
        return - 1;
154
    }
155
156
    /**
157
     * Returns the list of the elements organized by priority
158
     *
159
     * @return array
160
     */
161 17
    public function getElements()
162
    {
163
        // first sort the children so they are retrieved by priority
164 17
        uasort($this->elements, array($this, 'childComparator'));
165
166 17
        return $this->elements;
167
    }
168
169
170
    /**
171
     * Unset the group property for elements without a valid group (ie: existing group)
172
     */
173 11
    protected function cleanUpMissingGroups()
174
    {
175 11
        foreach ($this->elements as $element) {
176 9
            $group = $element->getGroup();
177 9
            if ($group && !isset($this->elements[$group])) {
178 9
                $element->setGroup(null);
179
            }
180
        }
181 11
    }
182
183
}
184