|
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])) { |
|
|
|
|
|
|
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])) { |
|
|
|
|
|
|
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
|
|
|
|
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.