Completed
Push — develop ( bec80e...e58249 )
by
unknown
09:35
created

SelectFactory::getItemValue()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 15
Code Lines 8

Duplication

Lines 15
Ratio 100 %

Importance

Changes 0
Metric Value
dl 15
loc 15
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 8
nc 2
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\Factory\Form\Tree;
12
13
use Core\Entity\Tree\NodeInterface;
14
use Core\Form\Hydrator\Strategy\TreeSelectStrategy;
15
use Core\Form\Tree\Select;
16
use Interop\Container\ContainerInterface;
17
use Zend\ServiceManager\FactoryInterface;
18
use Zend\ServiceManager\MutableCreationOptionsInterface;
19
use Zend\ServiceManager\ServiceLocatorInterface;
20
21
/**
22
 * Factory for a tree select form element.
23
 * 
24
 * @author Mathias Gelhausen <[email protected]>
25
 * @since 0.29
26
 */
27
class SelectFactory implements FactoryInterface, MutableCreationOptionsInterface
28
{
29
30
    /**
31
     * Creation options.
32
     *
33
     * @var array
34
     */
35
    protected $options = [];
36
37
38
    /**
39
     * Creates a tree select form element
40
     *
41
     * @param ContainerInterface $container
42
     * @param string             $requestedName
43
     * @param array|null         $options
44
     *
45
     * @return Select
46
     * @throws \RuntimeException
47
     * @throws \DomainException
48
     */
49
    public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
50
    {
51
        if (!is_array($options)
52
            || !isset($options['tree']['entity'])
53
            || (!isset($options['tree']['value']) && !isset($options['tree']['name']))
54
        ) {
55
            throw new \DomainException('You must specify ["tree"]["entity"] and either ["tree"]["value"] or ["tree"]["name"]');
56
        }
57
58
        if (isset($options['tree']['value'])) {
59
            $criteria = ['value' => $options['tree']['value']];
60
        } else {
61
            $criteria = ['name' => $options['tree']['name']];
62
        }
63
64
        $root = $container
65
            ->get('repositories')
66
            ->get($options['tree']['entity'])
67
            ->findOneBy($criteria);
68
69
        if (!$root) {
70
            throw new \RuntimeException('Tree root not found');
71
        }
72
73
        $select = new Select();
74
75
        if (isset($options['name'])) {
76
            $select->setName($options['name']);
77
        }
78
79
        if (isset($options['options'])) {
80
            $select->setOptions($options['options']);
81
        }
82
83
        if (isset($options['attributes'])) {
84
            $select->setAttributes($options['attributes']);
85
        }
86
87
        $valueOptions = $this->createValueOptions($root, isset($options['allow_select_nodes']) && $options['allow_select_nodes']);
88
        if (!isset($options['use_root_item']) || !$options['use_root_item']) {
89
            $valueOptions = array_shift($valueOptions);
90
            $valueOptions = is_array($valueOptions) ? $valueOptions['options'] : [];
91
        }
92
        $select->setValueOptions($valueOptions);
93
94
        $strategy = new TreeSelectStrategy();
95
        $strategy->setTreeRoot($root);
96
        $strategy->setAllowSelectMultipleItems(function() use ($select) {
97
                return $select->isMultiple();
98
        });
99
100
        $select->setHydratorStrategy($strategy);
101
102
        return $select;
103
    }
104
105
    /**
106
     * Set creation options
107
     *
108
     * @param  array $options
109
     *
110
     * @return void
111
     */
112
    public function setCreationOptions(array $options)
113
    {
114
        $this->options = $options;
115
    }
116
117
118
    /**
119
     * Create a tree select form element.
120
     *
121
     * @internal
122
     *      proxies to {@link __invoke}.
123
     *
124
     * @param ServiceLocatorInterface $serviceLocator
125
     * @return Select
126
     */
127
    public function createService(ServiceLocatorInterface $serviceLocator)
128
    {
129
        /* @var \Zend\ServiceManager\AbstractPluginManager $serviceLocator */
130
        $select = $this($serviceLocator->getServiceLocator(), self::class, $this->options);
131
        $this->options = [];
132
133
        return $select;
134
    }
135
136
    /**
137
     * Create value options from a node.
138
     *
139
     * @param NodeInterface $node
140
     * @param bool $allowSelectNodes
141
     * @param bool $isRoot
142
     *
143
     * @return array
144
     */
145
    protected function createValueOptions(NodeInterface $node, $allowSelectNodes = false, $isRoot=true)
146
    {
147
        $key    = $isRoot ? $node->getValue() : $node->getValueWithParents();
148
        $name   = $node->getName();
149
150
        if ($node->hasChildren()) {
151
            $leafOptions = [];
152
153
            if ($allowSelectNodes && !$isRoot) {
154
                $leafOptions[$key] = $name;
155
                $key = "$key-group";
156
            }
157
158
            foreach ($node->getChildren() as $child) {
159
                $leafOptions += $this->createValueOptions($child, $allowSelectNodes, false);
160
            }
161
162
            $value = [
163
                'label' => $name,
164
                'options' => $leafOptions
165
            ];
166
167
        } else {
168
            $value = $name;
169
        }
170
171
        return [$key => $value];
172
    }
173
}