Completed
Push — develop ( 9a607f...a83719 )
by
unknown
07:31
created

TreeSelectStrategy::setAttachedLeafs()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
rs 9.4285
c 0
b 0
f 0
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
    private $shouldUseNames = false;
53
54
    /**
55
     * Set the selected leafs.
56
     *
57
     * @param AbstractLeafs $attachedLeafs
58
     *
59
     * @return self
60
     */
61
    public function setAttachedLeafs(AbstractLeafs $attachedLeafs)
62
    {
63
        $this->attachedLeafs = $attachedLeafs;
64
65
        return $this;
66
    }
67
68
    /**
69
     * Get the selected leafs.
70
     *
71
     * @return AbstractLeafs
72
     */
73
    public function getAttachedLeafs()
74
    {
75
        return $this->attachedLeafs ?: new EmbeddedLeafs();
76
    }
77
78
    /**
79
     * Set the root node.
80
     *
81
     * @param NodeInterface $treeRoot
82
     *
83
     * @return self
84
     */
85
    public function setTreeRoot(NodeInterface $treeRoot)
86
    {
87
        $this->treeRoot = $treeRoot;
88
89
        return $this;
90
    }
91
92
    /**
93
     * Get the root node.
94
     *
95
     * @return NodeInterface
96
     */
97
    public function getTreeRoot()
98
    {
99
        return $this->treeRoot;
100
    }
101
102
    /**
103
     * Set the allow multiple selections flag.
104
     *
105
     * @param Callable|bool $flagOrCallback When a Callable is passed, it must return bool.
106
     *
107
     * @return self
108
     */
109
    public function setAllowSelectMultipleItems($flagOrCallback)
110
    {
111
        $this->allowSelectMultipleItems = $flagOrCallback;
112
113
        return $this;
114
    }
115
116
    /**
117
     * Are multiple selections allowed?
118
     *
119
     * @return bool
120
     */
121
    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...
122
    {
123
        $flagOrCallback = $this->allowSelectMultipleItems;
124
125
        return is_callable($flagOrCallback) ? (bool) $flagOrCallback() : (bool) $flagOrCallback;
126
    }
127
128
    public function setShouldCreateLeafs($flagOrCallback)
129
    {
130
        $this->shouldCreateLeafs = $flagOrCallback;
131
132
        return $this;
133
    }
134
135
    public function shouldCreateLeafs()
136
    {
137
        $flagOrCallback = $this->shouldCreateLeafs;
138
139
        return is_callable($flagOrCallback) ? (bool) $flagOrCallback() : (bool) $flagOrCallback;
140
    }
141
142
    /**
143
     * @return bool
144
     */
145
    public function shouldUseNames()
146
    {
147
        return $this->shouldUseNames;
148
    }
149
150
    /**
151
     * @param bool $flag
152
     *
153
     * @return self
154
     */
155
    public function setShouldUseNames($flag)
156
    {
157
        $this->shouldUseNames = (bool) $flag;
158
159
        return $this;
160
    }
161
162
163
    public function extract($value)
164
    {
165
        if (empty($value)) {
166
            return $this->allowSelectMultipleItems() ? [] : null;
167
        }
168
169
        if (!$value instanceOf AbstractLeafs) {
170
            return $value;
171
        }
172
173
        /* @var AbstractLeafs $value
174
         * @var NodeInterface $item */
175
176
        $this->setAttachedLeafs($value);
177
178
        if (!$this->allowSelectMultipleItems()) {
179
            $item = $value->getItems()->first();
180
            return $item ? $item->getValueWithParents(false, $this->shouldUseNames()) : null;
181
        }
182
183
        $data = [];
184
        foreach ($value->getItems() as $item) {
185
            $data[] = $item->getValueWithParents(false, $this->shouldUseNames());
186
        }
187
188
        return $data;
189
    }
190
191
    public function hydrate($value)
192
    {
193
        $object = $this->getAttachedLeafs();
194
195
        $root = $this->getTreeRoot();
196
        $items = new ArrayCollection();
197
198
        if (!$this->allowSelectMultipleItems()) {
199
            $value = [$value];
200
        }
201
202
        foreach ($value as $itemValue) {
203
            $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...
204
205
            if ($leaf) {
206
                $items->add($leaf);
207
            }
208
        }
209
210
        $object->setItems($items);
211
212
        return $object;
213
    }
214
215
    /**
216
     * Find a leaf with a concrete value in the tree.
217
     *
218
     * @param NodeInterface $leaf
219
     * @param string        $value
220
     *
221
     * @return NodeInterface|null
222
     */
223
    private function findLeaf(NodeInterface $leaf, $value)
224
    {
225
        $parts = is_array($value) ? $value : explode($this->shouldUseNames() ? ' | ': '-', $value);
226
        $value = array_shift($parts);
227
228
        /* @var NodeInterface $item */
229
        foreach ($leaf->getChildren() as $item) {
230
            $compare = $this->shouldUseNames() ? $item->getName() : $item->getValue();
231
            if ($compare == $value) {
232
                if (count($parts)) {
233
                    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...
234
                }
235
236
                return $item;
237
            }
238
        }
239
240
        if ($this->shouldCreateLeafs()) {
241
            $nodeClass = get_class($leaf);
242
            $node = new $nodeClass($value);
243
            $leaf->addChild($node);
244
            if (count($parts)) {
245
                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...
246
            }
247
248
            return $node;
249
        }
250
251
        return null;
252
    }
253
}
254