Completed
Push — dynamic_siteaccesses ( 16c7ff )
by
unknown
20:23
created

Contextualizer::mapConfigArray()   F

Complexity

Conditions 32
Paths 231

Size

Total Lines 155

Duplication

Lines 6
Ratio 3.87 %

Importance

Changes 0
Metric Value
cc 32
nc 231
nop 3
dl 6
loc 155
rs 2.3565
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 $groupsBySiteAccess;
34
35
    /**
36
     * @var array
37
     */
38
    private $availableSiteAccessGroups;
39
40
    public function __construct(
41
        ContainerInterface $containerBuilder,
42
        $namespace,
43
        $siteAccessNodeName,
44
        array $availableSiteAccesses,
45
        array $availableSiteAccessGroups,
46
        array $groupsBySiteAccess
47
    ) {
48
        $this->container = $containerBuilder;
49
        $this->namespace = $namespace;
50
        $this->siteAccessNodeName = $siteAccessNodeName;
51
        $this->availableSiteAccesses = $availableSiteAccesses;
52
        $this->availableSiteAccessGroups = $availableSiteAccessGroups;
53
        $this->groupsBySiteAccess = $groupsBySiteAccess;
54
    }
55
56
    public function setContextualParameter($parameterName, $scope, $value)
57
    {
58
        $this->container->setParameter("$this->namespace.$scope.$parameterName", $value);
59
    }
60
61
    public function mapSetting($id, array $config)
62
    {
63
        foreach ($config[$this->siteAccessNodeName] as $currentScope => $scopeSettings) {
64
            if (isset($scopeSettings[$id])) {
65
                $this->setContextualParameter($id, $currentScope, $scopeSettings[$id]);
66
            }
67
        }
68
    }
69
70
    public function mapConfigArray($id, array $config, $options = 0)
71
    {
72
        $this->mapReservedScopeArray($id, $config, ConfigResolver::SCOPE_DEFAULT);
73
        $this->mapReservedScopeArray($id, $config, ConfigResolver::SCOPE_GLOBAL);
74
        $defaultSettings = $this->getContainerParameter(
75
            $this->namespace . '.' . ConfigResolver::SCOPE_DEFAULT . '.' . $id,
76
            []
77
        );
78
        $globalSettings = $this->getContainerParameter(
79
            $this->namespace . '.' . ConfigResolver::SCOPE_GLOBAL . '.' . $id,
80
            []
81
        );
82
83
        // (!) Keep siteaccess group settings
84
        foreach (array_keys($this->availableSiteAccessGroups) as $scope) {
85
            $scopeSettings = array();
86 View Code Duplication
            if (isset($config[$this->siteAccessNodeName][$scope][$id])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
87
                $scopeSettings = $config[$this->siteAccessNodeName][$scope][$id];
88
            }
89
90
            if (empty($scopeSettings)) {
91
                continue;
92
            }
93
94
            if ($options & static::MERGE_FROM_SECOND_LEVEL) {
95
                // array_merge() has to be used because we don't
96
                // know whether we have a hash or a plain array
97
                $keys1 = array_unique(
98
                    array_merge(
99
                        array_keys($defaultSettings),
100
                        array_keys($scopeSettings),
101
                        array_keys($globalSettings)
102
                    )
103
                );
104
                $mergedSettings = array();
105
                foreach ($keys1 as $key) {
106
                    // Only merge if actual setting is an array.
107
                    // We assume default setting to be a clear reference for this.
108
                    // If the setting is not an array, we copy the right value, in respect to the precedence:
109
                    // 1. global
110
                    // 3. Group
111
                    // 4. default
112
                    if (array_key_exists($key, $defaultSettings) && !is_array($defaultSettings[$key])) {
113
                        if (array_key_exists($key, $globalSettings)) {
114
                            $mergedSettings[$key] = $globalSettings[$key];
115
                        } elseif (array_key_exists($key, $scopeSettings)) {
116
                            $mergedSettings[$key] = $scopeSettings[$key];
117
                        } else {
118
                            $mergedSettings[$key] = $defaultSettings[$key];
119
                        }
120
                    } else {
121
                        $mergedSettings[$key] = array_merge(
122
                            isset($defaultSettings[$key]) ? $defaultSettings[$key] : array(),
123
                            isset($scopeSettings[$key]) ? $scopeSettings[$key] : array(),
124
                            isset($globalSettings[$key]) ? $globalSettings[$key] : array()
125
                        );
126
                    }
127
                }
128
            } else {
129
                $mergedSettings = array_merge(
130
                    $defaultSettings,
131
                    $scopeSettings,
132
                    $globalSettings
133
                );
134
            }
135
136
            if ($options & static::UNIQUE) {
137
                $mergedSettings = array_values(
138
                    array_unique($mergedSettings)
139
                );
140
            }
141
142
            $this->container->setParameter("$this->namespace.$scope.$id", $mergedSettings);
143
        }
144
145
        foreach ($this->availableSiteAccesses as $scope) {
146
            // for a siteaccess, we have to merge the default value,
147
            // the group value(s), the siteaccess value and the global
148
            // value of the settings.
149
            $groupsSettings = [];
150
            if (isset($this->groupsBySiteAccess[$scope]) && is_array($this->groupsBySiteAccess[$scope])) {
151
                $groupsSettings = $this->groupsArraySetting(
152
                    $this->groupsBySiteAccess[$scope],
153
                    $id,
154
                    $config,
155
                    $options & static::MERGE_FROM_SECOND_LEVEL
156
                );
157
            }
158
159
            $scopeSettings = [];
160 View Code Duplication
            if (isset($config[$this->siteAccessNodeName][$scope][$id])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
161
                $scopeSettings = $config[$this->siteAccessNodeName][$scope][$id];
162
            }
163
164
            if (empty($groupsSettings) && empty($scopeSettings)) {
165
                continue;
166
            }
167
168
            if ($options & static::MERGE_FROM_SECOND_LEVEL) {
169
                // array_merge() has to be used because we don't
170
                // know whether we have a hash or a plain array
171
                $keys1 = array_unique(
172
                    array_merge(
173
                        array_keys($defaultSettings),
174
                        array_keys($groupsSettings),
175
                        array_keys($scopeSettings),
176
                        array_keys($globalSettings)
177
                    )
178
                );
179
                $mergedSettings = [];
180
                foreach ($keys1 as $key) {
181
                    // Only merge if actual setting is an array.
182
                    // We assume default setting to be a clear reference for this.
183
                    // If the setting is not an array, we copy the right value, in respect to the precedence:
184
                    // 1. global
185
                    // 2. SiteAccess
186
                    // 3. Group
187
                    // 4. default
188
                    if (array_key_exists($key, $defaultSettings) && !is_array($defaultSettings[$key])) {
189
                        if (array_key_exists($key, $globalSettings)) {
190
                            $mergedSettings[$key] = $globalSettings[$key];
191
                        } elseif (array_key_exists($key, $scopeSettings)) {
192
                            $mergedSettings[$key] = $scopeSettings[$key];
193
                        } elseif (array_key_exists($key, $groupsSettings)) {
194
                            $mergedSettings[$key] = $groupsSettings[$key];
195
                        } else {
196
                            $mergedSettings[$key] = $defaultSettings[$key];
197
                        }
198
                    } else {
199
                        $mergedSettings[$key] = array_merge(
200
                            isset($defaultSettings[$key]) ? $defaultSettings[$key] : [],
201
                            isset($groupsSettings[$key]) ? $groupsSettings[$key] : [],
202
                            isset($scopeSettings[$key]) ? $scopeSettings[$key] : [],
203
                            isset($globalSettings[$key]) ? $globalSettings[$key] : []
204
                        );
205
                    }
206
                }
207
            } else {
208
                $mergedSettings = array_merge(
209
                    $defaultSettings,
210
                    $groupsSettings,
211
                    $scopeSettings,
212
                    $globalSettings
213
                );
214
            }
215
216
            if ($options & static::UNIQUE) {
217
                $mergedSettings = array_values(
218
                    array_unique($mergedSettings)
219
                );
220
            }
221
222
            $this->container->setParameter("$this->namespace.$scope.$id", $mergedSettings);
223
        }
224
    }
225
226
    /**
227
     * Returns the value under the $id in the $container. if the container does
228
     * not known this $id, returns $default.
229
     *
230
     * @param string $id
231
     * @param mixed $default
232
     *
233
     * @return mixed
234
     */
235
    protected function getContainerParameter($id, $default = null)
236
    {
237
        if ($this->container->hasParameter($id)) {
238
            return $this->container->getParameter($id);
239
        }
240
241
        return $default;
242
    }
243
244
    /**
245
     * Merges setting array for a set of groups.
246
     *
247
     * @param array $groups array of group name
248
     * @param string $id id of the setting array under ezpublish.<base_key>.<group_name>
249
     * @param array $config the full configuration array
250
     * @param int $options only static::MERGE_FROM_SECOND_LEVEL or static::UNIQUE are recognized
251
     *
252
     * @return array
253
     */
254
    private function groupsArraySetting(array $groups, $id, array $config, $options = 0)
255
    {
256
        $groupsSettings = [];
257
        sort($groups);
258
        foreach ($groups as $group) {
259
            if (isset($config[$this->siteAccessNodeName][$group][$id])) {
260
                if ($options & static::MERGE_FROM_SECOND_LEVEL) {
261
                    foreach (array_keys($config[$this->siteAccessNodeName][$group][$id]) as $key) {
262
                        if (!isset($groupsSettings[$key])) {
263
                            $groupsSettings[$key] = $config[$this->siteAccessNodeName][$group][$id][$key];
264
                        } else {
265
                            // array_merge() has to be used because we don't
266
                            // know whether we have a hash or a plain array
267
                            $groupsSettings[$key] = array_merge(
268
                                $groupsSettings[$key],
269
                                $config[$this->siteAccessNodeName][$group][$id][$key]
270
                            );
271
                        }
272
                    }
273
                } else {
274
                    // array_merge() has to be used because we don't
275
                    // know whether we have a hash or a plain array
276
                    $groupsSettings = array_merge(
277
                        $groupsSettings,
278
                        $config[$this->siteAccessNodeName][$group][$id]
279
                    );
280
                }
281
            }
282
        }
283
284
        return $groupsSettings;
285
    }
286
287
    /**
288
     * Ensures settings array defined in a given "reserved scope" are registered properly.
289
     * "Reserved scope" can typically be ConfigResolver::SCOPE_DEFAULT or ConfigResolver::SCOPE_GLOBAL.
290
     *
291
     * @param string $id
292
     * @param array $config
293
     * @param string $scope
294
     */
295
    private function mapReservedScopeArray($id, array $config, $scope)
296
    {
297
        if (
298
            isset($config[$this->siteAccessNodeName][$scope][$id])
299
            && !empty($config[$this->siteAccessNodeName][$scope][$id])
300
        ) {
301
            $key = "$this->namespace.$scope.$id";
302
            $value = $config[$this->siteAccessNodeName][$scope][$id];
303
            if ($this->container->hasParameter($key)) {
304
                $value = array_merge(
305
                    $this->container->getParameter($key),
306
                    $value
307
                );
308
            }
309
            $this->container->setParameter($key, $value);
310
        }
311
    }
312
313
    public function setContainer(ContainerInterface $container)
314
    {
315
        $this->container = $container;
316
    }
317
318
    public function getContainer()
319
    {
320
        return $this->container;
321
    }
322
323
    public function setSiteAccessNodeName($scopeNodeName)
324
    {
325
        $this->siteAccessNodeName = $scopeNodeName;
326
    }
327
328
    public function getSiteAccessNodeName()
329
    {
330
        return $this->siteAccessNodeName;
331
    }
332
333
    public function setNamespace($namespace)
334
    {
335
        $this->namespace = $namespace;
336
    }
337
338
    public function getNamespace()
339
    {
340
        return $this->namespace;
341
    }
342
343
    public function setAvailableSiteAccesses(array $availableSiteAccesses)
344
    {
345
        $this->availableSiteAccesses = $availableSiteAccesses;
346
    }
347
348
    public function getAvailableSiteAccesses()
349
    {
350
        return $this->availableSiteAccesses;
351
    }
352
353
    public function setGroupsBySiteAccess(array $groupsBySiteAccess)
354
    {
355
        $this->groupsBySiteAccess = $groupsBySiteAccess;
356
    }
357
358
    public function getGroupsBySiteAccess()
359
    {
360
        return $this->groupsBySiteAccess;
361
    }
362
}
363