Completed
Push — qa-cumulative-ezp-31278-31279-... ( cb92e6...b59938 )
by
unknown
21:37
created

Contextualizer::mergeSettingsForSiteAccess()   C

Complexity

Conditions 13
Paths 4

Size

Total Lines 63

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 13
nc 4
nop 5
dl 0
loc 63
rs 6.1006
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
88
            $mergedSettings = $this->mergeSettingsForSiteAccessGroup(
89
                $options,
90
                $defaultSettings,
91
                $scopeSettings,
92
                $globalSettings
93
            );
94
95
            $this->container->setParameter("$this->namespace.$scope.$id", $mergedSettings);
96
        }
97
98
        foreach ($this->availableSiteAccesses as $scope) {
99
            // for a siteaccess, we have to merge the default value,
100
            // the group value(s), the siteaccess value and the global
101
            // value of the settings.
102
            $groupsSettings = [];
103
            if (isset($this->groupsBySiteAccess[$scope]) && is_array($this->groupsBySiteAccess[$scope])) {
104
                $groupsSettings = $this->groupsArraySetting(
105
                    $this->groupsBySiteAccess[$scope],
106
                    $id,
107
                    $config,
108
                    $options & static::MERGE_FROM_SECOND_LEVEL
109
                );
110
            }
111
112
            $scopeSettings = [];
113
            if (isset($config[$this->siteAccessNodeName][$scope][$id])) {
114
                $scopeSettings = $config[$this->siteAccessNodeName][$scope][$id];
115
            }
116
117
            if (empty($groupsSettings) && empty($scopeSettings)) {
118
                continue;
119
            }
120
121
            $mergedSettings = $this->mergeSettingsForSiteAccess(
122
                $options,
123
                $defaultSettings,
124
                $groupsSettings,
125
                $scopeSettings,
126
                $globalSettings
127
            );
128
129
            $this->container->setParameter("$this->namespace.$scope.$id", $mergedSettings);
130
        }
131
    }
132
133
    /**
134
     * Returns the value under the $id in the $container. if the container does
135
     * not known this $id, returns $default.
136
     *
137
     * @param string $id
138
     * @param mixed $default
139
     *
140
     * @return mixed
141
     */
142
    protected function getContainerParameter($id, $default = null)
143
    {
144
        if ($this->container->hasParameter($id)) {
145
            return $this->container->getParameter($id);
146
        }
147
148
        return $default;
149
    }
150
151
    /**
152
     * Merges setting array for a set of groups.
153
     *
154
     * @param array $groups array of group name
155
     * @param string $id id of the setting array under ezpublish.<base_key>.<group_name>
156
     * @param array $config the full configuration array
157
     * @param int $options only static::MERGE_FROM_SECOND_LEVEL or static::UNIQUE are recognized
158
     *
159
     * @return array
160
     */
161
    private function groupsArraySetting(array $groups, $id, array $config, $options = 0)
162
    {
163
        $groupsSettings = [];
164
        sort($groups);
165
        foreach ($groups as $group) {
166
            if (isset($config[$this->siteAccessNodeName][$group][$id])) {
167
                if ($options & static::MERGE_FROM_SECOND_LEVEL) {
168
                    foreach (array_keys($config[$this->siteAccessNodeName][$group][$id]) as $key) {
169
                        if (!isset($groupsSettings[$key])) {
170
                            $groupsSettings[$key] = $config[$this->siteAccessNodeName][$group][$id][$key];
171
                        } else {
172
                            // array_merge() has to be used because we don't
173
                            // know whether we have a hash or a plain array
174
                            $groupsSettings[$key] = array_merge(
175
                                $groupsSettings[$key],
176
                                $config[$this->siteAccessNodeName][$group][$id][$key]
177
                            );
178
                        }
179
                    }
180
                } else {
181
                    // array_merge() has to be used because we don't
182
                    // know whether we have a hash or a plain array
183
                    $groupsSettings = array_merge(
184
                        $groupsSettings,
185
                        $config[$this->siteAccessNodeName][$group][$id]
186
                    );
187
                }
188
            }
189
        }
190
191
        return $groupsSettings;
192
    }
193
194
    /**
195
     * Ensures settings array defined in a given "reserved scope" are registered properly.
196
     * "Reserved scope" can typically be ConfigResolver::SCOPE_DEFAULT or ConfigResolver::SCOPE_GLOBAL.
197
     *
198
     * @param string $id
199
     * @param string $scope
200
     */
201
    private function mapReservedScopeArray($id, array $config, $scope)
202
    {
203
        if (
204
            isset($config[$this->siteAccessNodeName][$scope][$id])
205
            && !empty($config[$this->siteAccessNodeName][$scope][$id])
206
        ) {
207
            $key = "$this->namespace.$scope.$id";
208
            $value = $config[$this->siteAccessNodeName][$scope][$id];
209
            if ($this->container->hasParameter($key)) {
210
                $value = array_merge(
211
                    $this->container->getParameter($key),
212
                    $value
213
                );
214
            }
215
            $this->container->setParameter($key, $value);
216
        }
217
    }
218
219
    public function setContainer(ContainerInterface $container)
220
    {
221
        $this->container = $container;
222
    }
223
224
    public function getContainer()
225
    {
226
        return $this->container;
227
    }
228
229
    public function setSiteAccessNodeName($scopeNodeName)
230
    {
231
        $this->siteAccessNodeName = $scopeNodeName;
232
    }
233
234
    public function getSiteAccessNodeName()
235
    {
236
        return $this->siteAccessNodeName;
237
    }
238
239
    public function setNamespace($namespace)
240
    {
241
        $this->namespace = $namespace;
242
    }
243
244
    public function getNamespace()
245
    {
246
        return $this->namespace;
247
    }
248
249
    public function setAvailableSiteAccesses(array $availableSiteAccesses)
250
    {
251
        $this->availableSiteAccesses = $availableSiteAccesses;
252
    }
253
254
    public function getAvailableSiteAccesses()
255
    {
256
        return $this->availableSiteAccesses;
257
    }
258
259
    public function setGroupsBySiteAccess(array $groupsBySiteAccess)
260
    {
261
        $this->groupsBySiteAccess = $groupsBySiteAccess;
262
    }
263
264
    public function getGroupsBySiteAccess()
265
    {
266
        return $this->groupsBySiteAccess;
267
    }
268
269
    private function mergeSettingsForSiteAccessGroup(
270
        int $options,
271
        array $defaultSettings,
272
        array $scopeSettings,
273
        array $globalSettings
274
    ): array {
275
        if ($options & static::MERGE_FROM_SECOND_LEVEL) {
276
            $mergedSettings = [];
277
278
            // array_merge() has to be used because we don't
279
            // know whether we have a hash or a plain array
280
            $keys = array_unique(
281
                array_merge(
282
                    array_keys($defaultSettings),
283
                    array_keys($scopeSettings),
284
                    array_keys($globalSettings)
285
                )
286
            );
287
            foreach ($keys as $key) {
288
                // Only merge if actual setting is an array.
289
                // We assume default setting to be a clear reference for this.
290
                // If the setting is not an array, we copy the right value, in respect to the precedence:
291
                // 1. global
292
                // 3. Group
293
                // 4. default
294
                if (array_key_exists($key, $defaultSettings) && !is_array($defaultSettings[$key])) {
295
                    if (array_key_exists($key, $globalSettings)) {
296
                        $mergedSettings[$key] = $globalSettings[$key];
297
                    } elseif (array_key_exists($key, $scopeSettings)) {
298
                        $mergedSettings[$key] = $scopeSettings[$key];
299
                    } else {
300
                        $mergedSettings[$key] = $defaultSettings[$key];
301
                    }
302
                } else {
303
                    $mergedSettings[$key] = array_merge(
304
                        $defaultSettings[$key] ?? [],
305
                        $scopeSettings[$key] ?? [],
306
                        $globalSettings[$key] ?? []
307
                    );
308
                }
309
            }
310
        } else {
311
            $mergedSettings = array_merge(
312
                $defaultSettings,
313
                $scopeSettings,
314
                $globalSettings
315
            );
316
        }
317
        if ($options & static::UNIQUE) {
318
            $mergedSettings = array_values(
319
                array_unique($mergedSettings)
320
            );
321
        }
322
323
        return $mergedSettings;
324
    }
325
326
    private function mergeSettingsForSiteAccess(
327
        int $options,
328
        array $defaultSettings,
329
        array $groupsSettings,
330
        array $scopeSettings,
331
        array $globalSettings
332
    ): array {
333
        if ($options & static::MERGE_FROM_SECOND_LEVEL) {
334
            // array_merge() has to be used because we don't
335
            // know whether we have a hash or a plain array
336
            $keys1 = array_unique(
337
                array_merge(
338
                    array_keys($defaultSettings),
339
                    array_keys($groupsSettings),
340
                    array_keys($scopeSettings),
341
                    array_keys($globalSettings)
342
                )
343
            );
344
            $mergedSettings = [];
345
            foreach ($keys1 as $key) {
346
                // Only merge if actual setting is an array.
347
                // We assume default setting to be a clear reference for this.
348
                // If the setting is not an array, we copy the right value, in respect to the precedence:
349
                // 1. global
350
                // 2. SiteAccess
351
                // 3. Group
352
                // 4. default
353
                if (array_key_exists($key, $defaultSettings) && !is_array($defaultSettings[$key])) {
354
                    if (array_key_exists($key, $globalSettings)) {
355
                        $mergedSettings[$key] = $globalSettings[$key];
356
                    } elseif (array_key_exists($key, $scopeSettings)) {
357
                        $mergedSettings[$key] = $scopeSettings[$key];
358
                    } elseif (array_key_exists($key, $groupsSettings)) {
359
                        $mergedSettings[$key] = $groupsSettings[$key];
360
                    } else {
361
                        $mergedSettings[$key] = $defaultSettings[$key];
362
                    }
363
                } else {
364
                    $mergedSettings[$key] = array_merge(
365
                        isset($defaultSettings[$key]) ? $defaultSettings[$key] : [],
366
                        isset($groupsSettings[$key]) ? $groupsSettings[$key] : [],
367
                        isset($scopeSettings[$key]) ? $scopeSettings[$key] : [],
368
                        isset($globalSettings[$key]) ? $globalSettings[$key] : []
369
                    );
370
                }
371
            }
372
        } else {
373
            $mergedSettings = array_merge(
374
                $defaultSettings,
375
                $groupsSettings,
376
                $scopeSettings,
377
                $globalSettings
378
            );
379
        }
380
381
        if ($options & static::UNIQUE) {
382
            $mergedSettings = array_values(
383
                array_unique($mergedSettings)
384
            );
385
        }
386
387
        return $mergedSettings;
388
    }
389
}
390