Completed
Push — master ( b286ff...53e76c )
by Adrian
04:28
created

HasChildrenTrait::getFullChildName()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1
Metric Value
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
cc 1
eloc 2
nc 1
nop 1
crap 1
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
    function addElement($nameOrElement, $specs = array())
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
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 19
        } 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 4
        } else {
61 2
            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 18
        }
67 18
        $this->elements[$name] = $element;
68
69 18
        return $this;
70 2
    }
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 1
                }
82 1
            }
83 9
        }
84 9
    }
85
86
    /**
87
     * Retrieve an element by name
88
     *
89
     * @param string $name
90
     *
91
     * @return \Sirius\Input\Element
92
     */
93 9
    function getElement($name)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
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
    function removeElement($name)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
107
    {
108 3
        if (isset($this->elements[$name])) {
109 3
            unset($this->elements[$name]);
110 3
        }
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
    function hasElement($name)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
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 number
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 3
            return - 1;
141
        }
142 7
        if ($posA > $posB) {
143 3
            return 1;
144
        }
145 7
        if ($childA['__index'] > $childB['__index']) {
146
            return - 1;
147
        }
148 7
        if ($childA['__index'] < $childB['__index']) {
149 7
            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
    function getElements()
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
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 1
                $element->setGroup(null);
179 1
            }
180 11
        }
181 11
    }
182
183
}
184