Completed
Push — develop ( 515643...e2e58e )
by
unknown
08:08
created

TreeSelectStrategy   A

Complexity

Total Complexity 24

Size/Duplication

Total Lines 177
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Importance

Changes 0
Metric Value
wmc 24
lcom 1
cbo 5
dl 0
loc 177
rs 10
c 0
b 0
f 0

9 Methods

Rating   Name   Duplication   Size   Complexity  
A setAttachedLeafs() 0 6 1
A getAttachedLeafs() 0 4 2
A setTreeRoot() 0 6 1
A getTreeRoot() 0 4 1
A setAllowSelectMultipleItems() 0 6 1
A allowSelectMultipleItems() 0 6 2
C extract() 0 27 7
B hydrate() 0 23 4
B findLeaf() 0 18 5
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
    /**
51
     * Set the selected leafs.
52
     *
53
     * @param AbstractLeafs $attachedLeafs
54
     *
55
     * @return self
56
     */
57
    public function setAttachedLeafs(AbstractLeafs $attachedLeafs)
58
    {
59
        $this->attachedLeafs = $attachedLeafs;
60
61
        return $this;
62
    }
63
64
    /**
65
     * Get the selected leafs.
66
     *
67
     * @return AbstractLeafs
68
     */
69
    public function getAttachedLeafs()
70
    {
71
        return $this->attachedLeafs ?: new EmbeddedLeafs();
72
    }
73
74
    /**
75
     * Set the root node.
76
     *
77
     * @param NodeInterface $treeRoot
78
     *
79
     * @return self
80
     */
81
    public function setTreeRoot(NodeInterface $treeRoot)
82
    {
83
        $this->treeRoot = $treeRoot;
84
85
        return $this;
86
    }
87
88
    /**
89
     * Get the root node.
90
     *
91
     * @return NodeInterface
92
     */
93
    public function getTreeRoot()
94
    {
95
        return $this->treeRoot;
96
    }
97
98
    /**
99
     * Set the allow multiple selections flag.
100
     *
101
     * @param Callable|bool $flagOrCallback When a Callable is passed, it must return bool.
102
     *
103
     * @return self
104
     */
105
    public function setAllowSelectMultipleItems($flagOrCallback)
106
    {
107
        $this->allowSelectMultipleItems = $flagOrCallback;
108
109
        return $this;
110
    }
111
112
    /**
113
     * Are multiple selections allowed?
114
     *
115
     * @return bool
116
     */
117
    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...
118
    {
119
        $flagOrCallback = $this->allowSelectMultipleItems;
120
121
        return is_callable($flagOrCallback) ? (bool) $flagOrCallback() : (bool) $flagOrCallback;
122
    }
123
124
    public function extract($value)
125
    {
126
        if (empty($value)) {
127
            return $this->allowSelectMultipleItems() ? [] : null;
128
        }
129
130
        if (!$value instanceOf AbstractLeafs) {
131
            return $value;
132
        }
133
134
        /* @var AbstractLeafs $value
135
         * @var NodeInterface $item */
136
137
        $this->setAttachedLeafs($value);
138
139
        if (!$this->allowSelectMultipleItems()) {
140
            $item = $value->getItems()->first();
141
            return $item ? $item->getValueWithParents() : null;
142
        }
143
144
        $data = [];
145
        foreach ($value->getItems() as $item) {
146
            $data[] = $item->getValueWithParents();
147
        }
148
149
        return $data;
150
    }
151
152
    public function hydrate($value)
153
    {
154
        $object = $this->getAttachedLeafs();
155
156
        $root = $this->getTreeRoot();
157
        $items = new ArrayCollection();
158
159
        if (!$this->allowSelectMultipleItems()) {
160
            $value = [$value];
161
        }
162
163
        foreach ($value as $itemValue) {
164
            $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...
165
166
            if ($leaf) {
167
                $items->add($leaf);
168
            }
169
        }
170
171
        $object->setItems($items);
172
173
        return $object;
174
    }
175
176
    /**
177
     * Find a leaf with a concrete value in the tree.
178
     *
179
     * @param NodeInterface $leaf
180
     * @param string        $value
181
     *
182
     * @return NodeInterface|null
183
     */
184
    private function findLeaf(NodeInterface $leaf, $value)
185
    {
186
        $parts = is_array($value) ? $value : explode('-', $value);
187
        $value = array_shift($parts);
188
189
        /* @var NodeInterface $item */
190
        foreach ($leaf->getChildren() as $item) {
191
            if ($item->getValue() == $value) {
192
                if (count($parts)) {
193
                    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...
194
                }
195
196
                return $item;
197
            }
198
        }
199
200
        return null;
201
    }
202
}