Completed
Push — develop ( c49811...f64e7c )
by
unknown
07:36
created

TreeSelectStrategy::setShouldCreateLeafs()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 6
rs 9.4285
cc 1
eloc 3
nc 1
nop 1
1
<?php
2
/**
3
 * YAWIK
4
 *
5
 * @filesource
6
 * @license MIT
7
 * @copyright  2013 - 2016 Cross Solution <http://cross-solution.de>
8
 */
9
  
10
/** */
11
namespace Core\Form\Hydrator\Strategy;
12
13
use Core\Entity\Tree\AbstractLeafs;
14
use Core\Entity\Tree\EmbeddedLeafs;
15
use Core\Entity\Tree\NodeInterface;
16
use Doctrine\Common\Collections\ArrayCollection;
17
use Doctrine\Common\Collections\Collection;
18
use Zend\Hydrator\Strategy\StrategyInterface;
19
20
/**
21
 * Hydrator strategy for TreeSelect form element.
22
 * 
23
 * @author Mathias Gelhausen <[email protected]>
24
 * @since 0.29
25
 */
26
class TreeSelectStrategy implements StrategyInterface
27
{
28
29
    /**
30
     * The selected leafs.
31
     *
32
     * @var AbstractLeafs
33
     */
34
    private $attachedLeafs;
35
36
    /**
37
     * The root node.
38
     *
39
     * @var NodeInterface
40
     */
41
    private $treeRoot;
42
43
    /**
44
     * Flag wether multiple selections are allowed.
45
     *
46
     * @var bool|callable
47
     */
48
    private $allowSelectMultipleItems = false;
49
50
    private $shouldCreateLeafs = false;
51
52
    /**
53
     * Set the selected leafs.
54
     *
55
     * @param AbstractLeafs $attachedLeafs
56
     *
57
     * @return self
58
     */
59
    public function setAttachedLeafs(AbstractLeafs $attachedLeafs)
60
    {
61
        $this->attachedLeafs = $attachedLeafs;
62
63
        return $this;
64
    }
65
66
    /**
67
     * Get the selected leafs.
68
     *
69
     * @return AbstractLeafs
70
     */
71
    public function getAttachedLeafs()
72
    {
73
        return $this->attachedLeafs ?: new EmbeddedLeafs();
74
    }
75
76
    /**
77
     * Set the root node.
78
     *
79
     * @param NodeInterface $treeRoot
80
     *
81
     * @return self
82
     */
83
    public function setTreeRoot(NodeInterface $treeRoot)
84
    {
85
        $this->treeRoot = $treeRoot;
86
87
        return $this;
88
    }
89
90
    /**
91
     * Get the root node.
92
     *
93
     * @return NodeInterface
94
     */
95
    public function getTreeRoot()
96
    {
97
        return $this->treeRoot;
98
    }
99
100
    /**
101
     * Set the allow multiple selections flag.
102
     *
103
     * @param Callable|bool $flagOrCallback When a Callable is passed, it must return bool.
104
     *
105
     * @return self
106
     */
107
    public function setAllowSelectMultipleItems($flagOrCallback)
108
    {
109
        $this->allowSelectMultipleItems = $flagOrCallback;
110
111
        return $this;
112
    }
113
114
    /**
115
     * Are multiple selections allowed?
116
     *
117
     * @return bool
118
     */
119
    public function allowSelectMultipleItems()
0 ignored issues
show
Coding Style introduced by
function allowSelectMultipleItems() does not seem to conform to the naming convention (^(?:is|has|should|may|supports)).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
120
    {
121
        $flagOrCallback = $this->allowSelectMultipleItems;
122
123
        return is_callable($flagOrCallback) ? (bool) $flagOrCallback() : (bool) $flagOrCallback;
124
    }
125
126
    public function setShouldCreateLeafs($flagOrCallback)
127
    {
128
        $this->shouldCreateLeafs = $flagOrCallback;
129
130
        return $this;
131
    }
132
133
    public function shouldCreateLeafs()
134
    {
135
        $flagOrCallback = $this->shouldCreateLeafs;
136
137
        return is_callable($flagOrCallback) ? (bool) $flagOrCallback() : (bool) $flagOrCallback;
138
    }
139
140
    public function extract($value)
141
    {
142
        if (empty($value)) {
143
            return $this->allowSelectMultipleItems() ? [] : null;
144
        }
145
146
        if (!$value instanceOf AbstractLeafs) {
147
            return $value;
148
        }
149
150
        /* @var AbstractLeafs $value
151
         * @var NodeInterface $item */
152
153
        $this->setAttachedLeafs($value);
154
155
        if (!$this->allowSelectMultipleItems()) {
156
            $item = $value->getItems()->first();
157
            return $item ? $item->getValueWithParents() : null;
158
        }
159
160
        $data = [];
161
        foreach ($value->getItems() as $item) {
162
            $data[] = $item->getValueWithParents();
163
        }
164
165
        return $data;
166
    }
167
168
    public function hydrate($value)
169
    {
170
        $object = $this->getAttachedLeafs();
171
172
        $root = $this->getTreeRoot();
173
        $items = new ArrayCollection();
174
175
        if (!$this->allowSelectMultipleItems()) {
176
            $value = [$value];
177
        }
178
179
        foreach ($value as $itemValue) {
180
            $leaf = $this->findLeaf($root, $itemValue);
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $leaf is correct as $this->findLeaf($root, $itemValue) (which targets Core\Form\Hydrator\Strat...ectStrategy::findLeaf()) seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
181
182
            if ($leaf) {
183
                $items->add($leaf);
184
            }
185
        }
186
187
        $object->setItems($items);
188
189
        return $object;
190
    }
191
192
    /**
193
     * Find a leaf with a concrete value in the tree.
194
     *
195
     * @param NodeInterface $leaf
196
     * @param string        $value
197
     *
198
     * @return NodeInterface|null
199
     */
200
    private function findLeaf(NodeInterface $leaf, $value)
201
    {
202
        $parts = is_array($value) ? $value : explode('-', $value);
203
        $value = array_shift($parts);
204
205
        /* @var NodeInterface $item */
206
        foreach ($leaf->getChildren() as $item) {
207
            if ($item->getValue() == $value) {
208
                if (count($parts)) {
209
                    return $this->findLeaf($item, $parts);
0 ignored issues
show
Documentation introduced by
$parts is of type array, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
210
                }
211
212
                return $item;
213
            }
214
        }
215
216
        if ($this->shouldCreateLeafs()) {
217
            $nodeClass = get_class($leaf);
218
            $node = new $nodeClass($value);
219
            $leaf->addChild($node);
220
            if (count($parts)) {
221
                return $this->findLeaf($node, $parts);
0 ignored issues
show
Documentation introduced by
$parts is of type array, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
222
            }
223
224
            return $node;
225
        }
226
227
        return null;
228
    }
229
}
230