Completed
Push — EZP-31047 ( 8fc0e8 )
by
unknown
15:06
created

Contextualizer::mapConfigArray()   F

Complexity

Conditions 28
Paths 126

Size

Total Lines 149

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 28
nc 126
nop 3
dl 0
loc 149
rs 3.16
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * File containing the Contextualizer class.
5
 *
6
 * @copyright Copyright (C) eZ Systems AS. All rights reserved.
7
 * @license For full copyright and license information view LICENSE file distributed with this source code.
8
 */
9
namespace eZ\Bundle\EzPublishCoreBundle\DependencyInjection\Configuration\SiteAccessAware;
10
11
use eZ\Bundle\EzPublishCoreBundle\DependencyInjection\Configuration\ConfigResolver;
12
use Symfony\Component\DependencyInjection\ContainerInterface;
13
14
class Contextualizer implements ContextualizerInterface
15
{
16
    /** @var \Symfony\Component\DependencyInjection\ContainerInterface */
17
    private $container;
18
19
    /** @var string */
20
    private $namespace;
21
22
    /**
23
     * Name of the node under which scope based (semantic) configuration takes place.
24
     *
25
     * @var string
26
     */
27
    private $siteAccessNodeName;
28
29
    /** @var array */
30
    private $availableSiteAccesses;
31
32
    /** @var array */
33
    private $availableSiteAccessGroups;
34
35
    /** @var array */
36
    private $groupsBySiteAccess;
37
38
    public function __construct(
39
        ContainerInterface $containerBuilder,
40
        $namespace,
41
        $siteAccessNodeName,
42
        array $availableSiteAccesses,
43
        array $availableSiteAccessGroups,
44
        array $groupsBySiteAccess
45
    ) {
46
        $this->container = $containerBuilder;
47
        $this->namespace = $namespace;
48
        $this->siteAccessNodeName = $siteAccessNodeName;
49
        $this->availableSiteAccesses = $availableSiteAccesses;
50
        $this->availableSiteAccessGroups = $availableSiteAccessGroups;
51
        $this->groupsBySiteAccess = $groupsBySiteAccess;
52
    }
53
54
    public function setContextualParameter($parameterName, $scope, $value)
55
    {
56
        $this->container->setParameter("$this->namespace.$scope.$parameterName", $value);
57
    }
58
59
    public function mapSetting($id, array $config)
60
    {
61
        foreach ($config[$this->siteAccessNodeName] as $currentScope => $scopeSettings) {
62
            if (isset($scopeSettings[$id])) {
63
                $this->setContextualParameter($id, $currentScope, $scopeSettings[$id]);
64
            }
65
        }
66
    }
67
68
    public function mapConfigArray($id, array $config, $options = 0)
69
    {
70
        $this->mapReservedScopeArray($id, $config, ConfigResolver::SCOPE_DEFAULT);
71
        $this->mapReservedScopeArray($id, $config, ConfigResolver::SCOPE_GLOBAL);
72
        $defaultSettings = $this->getContainerParameter(
73
            $this->namespace . '.' . ConfigResolver::SCOPE_DEFAULT . '.' . $id,
74
            []
75
        );
76
        $globalSettings = $this->getContainerParameter(
77
            $this->namespace . '.' . ConfigResolver::SCOPE_GLOBAL . '.' . $id,
78
            []
79
        );
80
81
        // (!) Keep siteaccess group settings
82
        foreach (array_keys($this->availableSiteAccessGroups) as $scope) {
83
            $scopeSettings = $config[$this->siteAccessNodeName][$scope][$id] ?? [];
84
            if (empty($scopeSettings)) {
85
                continue;
86
            }
87
            if ($options & static::MERGE_FROM_SECOND_LEVEL) {
88
                $mergedSettings = [];
89
90
                // array_merge() has to be used because we don't
91
                // know whether we have a hash or a plain array
92
                $keys = array_unique(
93
                    array_merge(
94
                        array_keys($defaultSettings),
95
                        array_keys($scopeSettings),
96
                        array_keys($globalSettings)
97
                    )
98
                );
99
                foreach ($keys as $key) {
100
                    // Only merge if actual setting is an array.
101
                    // We assume default setting to be a clear reference for this.
102
                    // If the setting is not an array, we copy the right value, in respect to the precedence:
103
                    // 1. global
104
                    // 3. Group
105
                    // 4. default
106
                    if (array_key_exists($key, $defaultSettings) && !is_array($defaultSettings[$key])) {
107
                        if (array_key_exists($key, $globalSettings)) {
108
                            $mergedSettings[$key] = $globalSettings[$key];
109
                        } elseif (array_key_exists($key, $scopeSettings)) {
110
                            $mergedSettings[$key] = $scopeSettings[$key];
111
                        } else {
112
                            $mergedSettings[$key] = $defaultSettings[$key];
113
                        }
114
                    } else {
115
                        $mergedSettings[$key] = array_merge(
116
                            $defaultSettings[$key] ?? [],
117
                            $scopeSettings[$key] ?? [],
118
                            $globalSettings[$key] ?? []
119
                        );
120
                    }
121
                }
122
            } else {
123
                $mergedSettings = array_merge(
124
                    $defaultSettings,
125
                    $scopeSettings,
126
                    $globalSettings
127
                );
128
            }
129
            if ($options & static::UNIQUE) {
130
                $mergedSettings = array_values(
131
                    array_unique($mergedSettings)
132
                );
133
            }
134
            $this->container->setParameter("$this->namespace.$scope.$id", $mergedSettings);
135
        }
136
137
        foreach ($this->availableSiteAccesses as $scope) {
138
            // for a siteaccess, we have to merge the default value,
139
            // the group value(s), the siteaccess value and the global
140
            // value of the settings.
141
            $groupsSettings = [];
142
            if (isset($this->groupsBySiteAccess[$scope]) && is_array($this->groupsBySiteAccess[$scope])) {
143
                $groupsSettings = $this->groupsArraySetting(
144
                    $this->groupsBySiteAccess[$scope],
145
                    $id,
146
                    $config,
147
                    $options & static::MERGE_FROM_SECOND_LEVEL
148
                );
149
            }
150
151
            $scopeSettings = [];
152
            if (isset($config[$this->siteAccessNodeName][$scope][$id])) {
153
                $scopeSettings = $config[$this->siteAccessNodeName][$scope][$id];
154
            }
155
156
            if (empty($groupsSettings) && empty($scopeSettings)) {
157
                continue;
158
            }
159
160
            if ($options & static::MERGE_FROM_SECOND_LEVEL) {
161
                // array_merge() has to be used because we don't
162
                // know whether we have a hash or a plain array
163
                $keys1 = array_unique(
164
                    array_merge(
165
                        array_keys($defaultSettings),
166
                        array_keys($groupsSettings),
167
                        array_keys($scopeSettings),
168
                        array_keys($globalSettings)
169
                    )
170
                );
171
                $mergedSettings = [];
172
                foreach ($keys1 as $key) {
173
                    // Only merge if actual setting is an array.
174
                    // We assume default setting to be a clear reference for this.
175
                    // If the setting is not an array, we copy the right value, in respect to the precedence:
176
                    // 1. global
177
                    // 2. SiteAccess
178
                    // 3. Group
179
                    // 4. default
180
                    if (array_key_exists($key, $defaultSettings) && !is_array($defaultSettings[$key])) {
181
                        if (array_key_exists($key, $globalSettings)) {
182
                            $mergedSettings[$key] = $globalSettings[$key];
183
                        } elseif (array_key_exists($key, $scopeSettings)) {
184
                            $mergedSettings[$key] = $scopeSettings[$key];
185
                        } elseif (array_key_exists($key, $groupsSettings)) {
186
                            $mergedSettings[$key] = $groupsSettings[$key];
187
                        } else {
188
                            $mergedSettings[$key] = $defaultSettings[$key];
189
                        }
190
                    } else {
191
                        $mergedSettings[$key] = array_merge(
192
                            isset($defaultSettings[$key]) ? $defaultSettings[$key] : [],
193
                            isset($groupsSettings[$key]) ? $groupsSettings[$key] : [],
194
                            isset($scopeSettings[$key]) ? $scopeSettings[$key] : [],
195
                            isset($globalSettings[$key]) ? $globalSettings[$key] : []
196
                        );
197
                    }
198
                }
199
            } else {
200
                $mergedSettings = array_merge(
201
                    $defaultSettings,
202
                    $groupsSettings,
203
                    $scopeSettings,
204
                    $globalSettings
205
                );
206
            }
207
208
            if ($options & static::UNIQUE) {
209
                $mergedSettings = array_values(
210
                    array_unique($mergedSettings)
211
                );
212
            }
213
214
            $this->container->setParameter("$this->namespace.$scope.$id", $mergedSettings);
215
        }
216
    }
217
218
    /**
219
     * Returns the value under the $id in the $container. if the container does
220
     * not known this $id, returns $default.
221
     *
222
     * @param string $id
223
     * @param mixed $default
224
     *
225
     * @return mixed
226
     */
227
    protected function getContainerParameter($id, $default = null)
228
    {
229
        if ($this->container->hasParameter($id)) {
230
            return $this->container->getParameter($id);
231
        }
232
233
        return $default;
234
    }
235
236
    /**
237
     * Merges setting array for a set of groups.
238
     *
239
     * @param array $groups array of group name
240
     * @param string $id id of the setting array under ezpublish.<base_key>.<group_name>
241
     * @param array $config the full configuration array
242
     * @param int $options only static::MERGE_FROM_SECOND_LEVEL or static::UNIQUE are recognized
243
     *
244
     * @return array
245
     */
246
    private function groupsArraySetting(array $groups, $id, array $config, $options = 0)
247
    {
248
        $groupsSettings = [];
249
        sort($groups);
250
        foreach ($groups as $group) {
251
            if (isset($config[$this->siteAccessNodeName][$group][$id])) {
252
                if ($options & static::MERGE_FROM_SECOND_LEVEL) {
253
                    foreach (array_keys($config[$this->siteAccessNodeName][$group][$id]) as $key) {
254
                        if (!isset($groupsSettings[$key])) {
255
                            $groupsSettings[$key] = $config[$this->siteAccessNodeName][$group][$id][$key];
256
                        } else {
257
                            // array_merge() has to be used because we don't
258
                            // know whether we have a hash or a plain array
259
                            $groupsSettings[$key] = array_merge(
260
                                $groupsSettings[$key],
261
                                $config[$this->siteAccessNodeName][$group][$id][$key]
262
                            );
263
                        }
264
                    }
265
                } else {
266
                    // array_merge() has to be used because we don't
267
                    // know whether we have a hash or a plain array
268
                    $groupsSettings = array_merge(
269
                        $groupsSettings,
270
                        $config[$this->siteAccessNodeName][$group][$id]
271
                    );
272
                }
273
            }
274
        }
275
276
        return $groupsSettings;
277
    }
278
279
    /**
280
     * Ensures settings array defined in a given "reserved scope" are registered properly.
281
     * "Reserved scope" can typically be ConfigResolver::SCOPE_DEFAULT or ConfigResolver::SCOPE_GLOBAL.
282
     *
283
     * @param string $id
284
     * @param array $config
285
     * @param string $scope
286
     */
287
    private function mapReservedScopeArray($id, array $config, $scope)
288
    {
289
        if (
290
            isset($config[$this->siteAccessNodeName][$scope][$id])
291
            && !empty($config[$this->siteAccessNodeName][$scope][$id])
292
        ) {
293
            $key = "$this->namespace.$scope.$id";
294
            $value = $config[$this->siteAccessNodeName][$scope][$id];
295
            if ($this->container->hasParameter($key)) {
296
                $value = array_merge(
297
                    $this->container->getParameter($key),
298
                    $value
299
                );
300
            }
301
            $this->container->setParameter($key, $value);
302
        }
303
    }
304
305
    public function setContainer(ContainerInterface $container)
306
    {
307
        $this->container = $container;
308
    }
309
310
    public function getContainer()
311
    {
312
        return $this->container;
313
    }
314
315
    public function setSiteAccessNodeName($scopeNodeName)
316
    {
317
        $this->siteAccessNodeName = $scopeNodeName;
318
    }
319
320
    public function getSiteAccessNodeName()
321
    {
322
        return $this->siteAccessNodeName;
323
    }
324
325
    public function setNamespace($namespace)
326
    {
327
        $this->namespace = $namespace;
328
    }
329
330
    public function getNamespace()
331
    {
332
        return $this->namespace;
333
    }
334
335
    public function setAvailableSiteAccesses(array $availableSiteAccesses)
336
    {
337
        $this->availableSiteAccesses = $availableSiteAccesses;
338
    }
339
340
    public function getAvailableSiteAccesses()
341
    {
342
        return $this->availableSiteAccesses;
343
    }
344
345
    public function setGroupsBySiteAccess(array $groupsBySiteAccess)
346
    {
347
        $this->groupsBySiteAccess = $groupsBySiteAccess;
348
    }
349
350
    public function getGroupsBySiteAccess()
351
    {
352
        return $this->groupsBySiteAccess;
353
    }
354
}
355