Passed
Push — master ( 20e747...679572 )
by Ivan
01:59
created

NavigationItemConfig::addManualMatchesToArray()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
c 0
b 0
f 0
rs 9.4285
cc 2
eloc 3
nc 2
nop 2
1
<?php
2
3
declare(strict_types = 1);
4
5
namespace Everlution\Navigation\Factory\Build;
6
7
use Everlution\Navigation\Extension\ManualMatch;
8
use Everlution\Navigation\Item;
9
use Everlution\Navigation\Factory\ItemFactory;
10
use Symfony\Component\OptionsResolver\OptionsResolver;
11
12
/**
13
 * Class NavigationItemConfig.
14
 * @author Ivan Barlog <[email protected]>
15
 */
16
abstract class NavigationItemConfig implements Config
17
{
18
    const OPTION_CLASS = 'class';
19
    const OPTION_LABEL = 'label';
20
    const OPTION_IDENTIFIER = 'identifier';
21
    const OPTION_CHILDREN = 'children';
22
    const OPTION_MATCHES = 'matches';
23
24
    /** @var OptionsResolver */
25
    protected $resolver;
26
    /** @var array */
27
    protected $supportedClasses = [];
28
29
    public function __construct()
30
    {
31
        $this->resolver = new OptionsResolver();
32
33
        $this->resolver->setRequired(
34
            [
35
                self::OPTION_CLASS,
36
                self::OPTION_LABEL,
37
                self::OPTION_IDENTIFIER,
38
                self::OPTION_CHILDREN,
39
                self::OPTION_MATCHES,
40
            ]
41
        );
42
        $this->resolver->setAllowedTypes(self::OPTION_CLASS, 'string');
43
        $this->resolver->setAllowedTypes(self::OPTION_LABEL, 'string');
44
        $this->resolver->setAllowedTypes(self::OPTION_IDENTIFIER, 'string');
45
        $this->resolver->setAllowedTypes(self::OPTION_CHILDREN, 'array');
46
        $this->resolver->setAllowedTypes(self::OPTION_MATCHES, 'array');
47
48
        $this->resolver->setDefault(self::OPTION_CHILDREN, []);
49
        $this->resolver->setDefault(self::OPTION_MATCHES, []);
50
51
        $this->config();
52
    }
53
54
    /**
55
     * @param Item $item
56
     * @param ItemFactory $factory
57
     * @return array
58
     */
59
    public function toArray(Item $item, ItemFactory $factory): array
60
    {
61
        $this->checkIfSupport(get_class($item));
62
63
        $result = $this->getArray($item);
64
        $this->addManualMatchesToArray($result, $item);
65
66
        foreach ($item->getChildren() as $child) {
67
            $result[static::OPTION_CHILDREN][] = $factory->flatten($child);
68
        }
69
70
        return $result;
71
    }
72
73
    /**
74
     * @param array $config
75
     * @param ItemFactory $factory
76
     * @return Item
77
     * @throws NavigationItemClassDoesNotExistException
78
     */
79
    public function toObject(array $config, ItemFactory $factory): Item
80
    {
81
        $className = $this->popClassName($config);
82
        $this->checkIfSupport($className);
83
84
        $config = $this->resolve($config);
85
86
        if (false === class_exists($className)) {
87
            throw new NavigationItemClassDoesNotExistException($className);
88
        }
89
90
        $object = $this->getObject($className, $config);
91
        $this->addManualMatchesToObject($object, $config);
92
93
        foreach ($config[self::OPTION_CHILDREN] as $item) {
94
            $child = $factory->create($item);
95
            $object->addChild($child);
96
        }
97
98
        return $object;
99
    }
100
101
    /**
102
     * @param array $config
103
     * @return array
104
     */
105
    protected function resolve(array $config): array
106
    {
107
        return $this->resolver->resolve($config);
108
    }
109
110
    /**
111
     * @param string $class
112
     */
113
    protected function checkIfSupport(string $class)
114
    {
115
        if (false === in_array($class, $this->supportedClasses)) {
116
            throw new UnsupportedItemClassException($class, $this->supportedClasses);
117
        }
118
    }
119
120
    /**
121
     * Specifies how the object should be created
122
     *
123
     * @param string $className
124
     * @param array $arguments
125
     * @return Item
126
     */
127
    abstract protected function getObject(string $className, array $arguments);
128
129
    /**
130
     * Specifies how should object be transformed to an array
131
     *
132
     * @param Item $item
133
     * @return array
134
     */
135
    abstract protected function getArray($item): array;
136
137
    /**
138
     * Specifies additional options
139
     * This method is called after initial OptionsResolver setup
140
     * Use OptionsResolver within this method
141
     *
142
     * @return void
143
     */
144
    abstract protected function config();
145
146
    /**
147
     * @param array $config
148
     * @return string
149
     */
150
    private function popClassName(array $config): string
151
    {
152
        $class = $config[self::OPTION_CLASS];
153
        unset($config[self::OPTION_CLASS]);
154
155
        return $class;
156
    }
157
158
    private function addManualMatchesToArray(array $result, Item $item)
159
    {
160
        if ($item instanceof ManualMatch) {
161
            $result[self::OPTION_MATCHES] = $item->getMatches();
162
        }
163
    }
164
165
    private function addManualMatchesToObject(Item $object, array $config)
166
    {
167
        if ($object instanceof ManualMatch) {
168
            $object->setMatches($config[self::OPTION_MATCHES]);
169
        }
170
    }
171
}
172