|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
/** |
|
4
|
|
|
* File containing the Configuration 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; |
|
10
|
|
|
|
|
11
|
|
|
use eZ\Bundle\EzPublishCoreBundle\DependencyInjection\Configuration\ParserInterface; |
|
12
|
|
|
use eZ\Bundle\EzPublishCoreBundle\DependencyInjection\Configuration\SiteAccessAware\Configuration as SiteAccessConfiguration; |
|
13
|
|
|
use eZ\Bundle\EzPublishCoreBundle\DependencyInjection\Configuration\Suggestion\Collector\SuggestionCollectorInterface; |
|
14
|
|
|
use Symfony\Component\Config\Definition\Builder\NodeBuilder; |
|
15
|
|
|
use Symfony\Component\Config\Definition\Builder\TreeBuilder; |
|
16
|
|
|
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; |
|
17
|
|
|
|
|
18
|
|
|
class Configuration extends SiteAccessConfiguration |
|
19
|
|
|
{ |
|
20
|
|
|
const CUSTOM_TAG_ATTRIBUTE_TYPES = ['number', 'string', 'boolean', 'choice']; |
|
21
|
|
|
|
|
22
|
|
|
/** |
|
23
|
|
|
* @var \eZ\Bundle\EzPublishCoreBundle\DependencyInjection\Configuration\ParserInterface |
|
24
|
|
|
*/ |
|
25
|
|
|
private $mainConfigParser; |
|
26
|
|
|
|
|
27
|
|
|
/** |
|
28
|
|
|
* @var Configuration\Suggestion\Collector\SuggestionCollectorInterface |
|
29
|
|
|
*/ |
|
30
|
|
|
private $suggestionCollector; |
|
31
|
|
|
|
|
32
|
|
|
/** |
|
33
|
|
|
* @var \eZ\Bundle\EzPublishCoreBundle\SiteAccess\SiteAccessConfigurationFilter[] |
|
34
|
|
|
*/ |
|
35
|
|
|
private $siteAccessConfigurationFilters; |
|
36
|
|
|
|
|
37
|
|
|
public function __construct(ParserInterface $mainConfigParser, SuggestionCollectorInterface $suggestionCollector) |
|
38
|
|
|
{ |
|
39
|
|
|
$this->suggestionCollector = $suggestionCollector; |
|
40
|
|
|
$this->mainConfigParser = $mainConfigParser; |
|
41
|
|
|
} |
|
42
|
|
|
|
|
43
|
|
|
public function setSiteAccessConfigurationFilters(array $filters) |
|
44
|
|
|
{ |
|
45
|
|
|
$this->siteAccessConfigurationFilters = $filters; |
|
46
|
|
|
} |
|
47
|
|
|
|
|
48
|
|
|
/** |
|
49
|
|
|
* Generates the configuration tree builder. |
|
50
|
|
|
* |
|
51
|
|
|
* @return \Symfony\Component\Config\Definition\Builder\TreeBuilder The tree builder |
|
52
|
|
|
*/ |
|
53
|
|
|
public function getConfigTreeBuilder() |
|
54
|
|
|
{ |
|
55
|
|
|
$treeBuilder = new TreeBuilder(); |
|
56
|
|
|
$rootNode = $treeBuilder->root('ezpublish'); |
|
|
|
|
|
|
57
|
|
|
|
|
58
|
|
|
$this->addRepositoriesSection($rootNode); |
|
59
|
|
|
$this->addSiteaccessSection($rootNode); |
|
60
|
|
|
$this->addImageMagickSection($rootNode); |
|
61
|
|
|
$this->addHttpCacheSection($rootNode); |
|
62
|
|
|
$this->addRouterSection($rootNode); |
|
63
|
|
|
$this->addRichTextSection($rootNode); |
|
64
|
|
|
$this->addUrlAliasSection($rootNode); |
|
65
|
|
|
$this->addImagePlaceholderSection($rootNode); |
|
66
|
|
|
$this->addUrlWildcardsSection($rootNode); |
|
67
|
|
|
|
|
68
|
|
|
// Delegate SiteAccess config to configuration parsers |
|
69
|
|
|
$this->mainConfigParser->addSemanticConfig($this->generateScopeBaseNode($rootNode)); |
|
70
|
|
|
|
|
71
|
|
|
return $treeBuilder; |
|
72
|
|
|
} |
|
73
|
|
|
|
|
74
|
|
|
public function addRepositoriesSection(ArrayNodeDefinition $rootNode) |
|
75
|
|
|
{ |
|
76
|
|
|
$rootNode |
|
77
|
|
|
->children() |
|
78
|
|
|
->arrayNode('repositories') |
|
79
|
|
|
->info('Content repositories configuration') |
|
80
|
|
|
->example( |
|
81
|
|
|
array( |
|
82
|
|
|
'main' => array( |
|
83
|
|
|
'storage' => array( |
|
84
|
|
|
'engine' => 'legacy', |
|
85
|
|
|
'connection' => 'my_doctrine_connection_name', |
|
86
|
|
|
), |
|
87
|
|
|
), |
|
88
|
|
|
) |
|
89
|
|
|
) |
|
90
|
|
|
->useAttributeAsKey('alias') |
|
91
|
|
|
->prototype('array') |
|
92
|
|
|
->beforeNormalization() |
|
93
|
|
|
->always( |
|
94
|
|
|
// Handling deprecated structure by mapping it to new one |
|
95
|
|
|
function ($v) { |
|
96
|
|
|
if (isset($v['storage'])) { |
|
97
|
|
|
return $v; |
|
98
|
|
|
} |
|
99
|
|
|
|
|
100
|
|
|
if (isset($v['engine'])) { |
|
101
|
|
|
$v['storage']['engine'] = $v['engine']; |
|
102
|
|
|
unset($v['engine']); |
|
103
|
|
|
} |
|
104
|
|
|
|
|
105
|
|
|
if (isset($v['connection'])) { |
|
106
|
|
|
$v['storage']['connection'] = $v['connection']; |
|
107
|
|
|
unset($v['connection']); |
|
108
|
|
|
} |
|
109
|
|
|
|
|
110
|
|
|
if (isset($v['config'])) { |
|
111
|
|
|
$v['storage']['config'] = $v['config']; |
|
112
|
|
|
unset($v['config']); |
|
113
|
|
|
} |
|
114
|
|
|
|
|
115
|
|
|
return $v; |
|
116
|
|
|
} |
|
117
|
|
|
) |
|
118
|
|
|
->end() |
|
119
|
|
|
->beforeNormalization() |
|
120
|
|
|
->always( |
|
121
|
|
|
// Setting default values |
|
122
|
|
|
function ($v) { |
|
123
|
|
|
if ($v === null) { |
|
124
|
|
|
$v = array(); |
|
125
|
|
|
} |
|
126
|
|
|
|
|
127
|
|
|
if (!isset($v['storage'])) { |
|
128
|
|
|
$v['storage'] = array(); |
|
129
|
|
|
} |
|
130
|
|
|
|
|
131
|
|
|
if (!isset($v['search'])) { |
|
132
|
|
|
$v['search'] = array(); |
|
133
|
|
|
} |
|
134
|
|
|
|
|
135
|
|
|
if (!isset($v['fields_groups']['list'])) { |
|
136
|
|
|
$v['fields_groups']['list'] = []; |
|
137
|
|
|
} |
|
138
|
|
|
|
|
139
|
|
|
if (!isset($v['options'])) { |
|
140
|
|
|
$v['options'] = []; |
|
141
|
|
|
} |
|
142
|
|
|
|
|
143
|
|
|
return $v; |
|
144
|
|
|
} |
|
145
|
|
|
) |
|
146
|
|
|
->end() |
|
147
|
|
|
->children() |
|
148
|
|
|
->arrayNode('storage') |
|
149
|
|
|
->children() |
|
150
|
|
|
->scalarNode('engine') |
|
151
|
|
|
->defaultValue('%ezpublish.api.storage_engine.default%') |
|
152
|
|
|
->info('The storage engine to use') |
|
153
|
|
|
->end() |
|
154
|
|
|
->scalarNode('connection') |
|
155
|
|
|
->defaultNull() |
|
156
|
|
|
->info('The connection name, if applicable (e.g. Doctrine connection name). If not set, the default connection will be used.') |
|
157
|
|
|
->end() |
|
158
|
|
|
->arrayNode('config') |
|
159
|
|
|
->info('Arbitrary configuration options, supported by your storage engine') |
|
160
|
|
|
->useAttributeAsKey('key') |
|
161
|
|
|
->prototype('variable')->end() |
|
162
|
|
|
->end() |
|
163
|
|
|
->end() |
|
164
|
|
|
->end() |
|
165
|
|
|
->arrayNode('search') |
|
166
|
|
|
->children() |
|
167
|
|
|
->scalarNode('engine') |
|
168
|
|
|
->defaultValue('%ezpublish.api.search_engine.default%') |
|
169
|
|
|
->info('The search engine to use') |
|
170
|
|
|
->end() |
|
171
|
|
|
->scalarNode('connection') |
|
172
|
|
|
->defaultNull() |
|
173
|
|
|
->info('The connection name, if applicable (e.g. Doctrine connection name). If not set, the default connection will be used.') |
|
174
|
|
|
->end() |
|
175
|
|
|
->arrayNode('config') |
|
176
|
|
|
->info('Arbitrary configuration options, supported by your search engine') |
|
177
|
|
|
->useAttributeAsKey('key') |
|
178
|
|
|
->prototype('variable')->end() |
|
179
|
|
|
->end() |
|
180
|
|
|
->end() |
|
181
|
|
|
->end() |
|
182
|
|
|
->arrayNode('fields_groups') |
|
183
|
|
|
->info('Definitions of fields groups.') |
|
184
|
|
|
->children() |
|
185
|
|
|
->arrayNode('list')->prototype('scalar')->end()->end() |
|
186
|
|
|
->scalarNode('default')->defaultValue('%ezsettings.default.content.field_groups.default%')->end() |
|
187
|
|
|
->end() |
|
188
|
|
|
->end() |
|
189
|
|
|
->arrayNode('options') |
|
190
|
|
|
->info('Options for repository.') |
|
191
|
|
|
->children() |
|
192
|
|
|
->scalarNode('default_version_archive_limit') |
|
193
|
|
|
->defaultValue(5) |
|
194
|
|
|
->info('Default version archive limit (0-50), only enforced on publish, not on un-publish.') |
|
195
|
|
|
->end() |
|
196
|
|
|
->end() |
|
197
|
|
|
->end() |
|
198
|
|
|
->end() |
|
199
|
|
|
->end() |
|
200
|
|
|
->end() |
|
201
|
|
|
->end(); |
|
202
|
|
|
} |
|
203
|
|
|
|
|
204
|
|
|
public function addSiteaccessSection(ArrayNodeDefinition $rootNode) |
|
205
|
|
|
{ |
|
206
|
|
|
$rootNode |
|
207
|
|
|
->children() |
|
208
|
|
|
->arrayNode('siteaccess') |
|
209
|
|
|
->info('SiteAccess configuration') |
|
210
|
|
|
->children() |
|
211
|
|
|
->arrayNode('list') |
|
212
|
|
|
->info('Available SiteAccess list') |
|
213
|
|
|
->example(array('ezdemo_site', 'ezdemo_site_admin')) |
|
214
|
|
|
->isRequired() |
|
215
|
|
|
->requiresAtLeastOneElement() |
|
216
|
|
|
->prototype('scalar')->end() |
|
217
|
|
|
->end() |
|
218
|
|
|
->arrayNode('groups') |
|
219
|
|
|
->useAttributeAsKey('key') |
|
220
|
|
|
->info('SiteAccess groups. Useful to share settings between Siteaccess') |
|
221
|
|
|
->example(array('ezdemo_group' => array('ezdemo_site', 'ezdemo_site_admin'))) |
|
222
|
|
|
->prototype('array') |
|
223
|
|
|
->requiresAtLeastOneElement() |
|
224
|
|
|
->prototype('scalar')->end() |
|
225
|
|
|
->end() |
|
226
|
|
|
->end() |
|
227
|
|
|
->scalarNode('default_siteaccess')->isRequired()->info('Name of the default siteaccess')->end() |
|
228
|
|
|
->arrayNode('match') |
|
229
|
|
|
->info('Siteaccess match configuration. First key is the matcher class, value is passed to the matcher. Key can be a service identifier (prepended by "@"), or a FQ class name (prepended by "\\")') |
|
230
|
|
|
->example( |
|
231
|
|
|
array( |
|
232
|
|
|
'Map\\URI' => array( |
|
233
|
|
|
'foo' => 'ezdemo_site', |
|
234
|
|
|
'ezdemo_site' => 'ezdemo_site', |
|
235
|
|
|
'ezdemo_site_admin' => 'ezdemo_site_admin', |
|
236
|
|
|
), |
|
237
|
|
|
'Map\\Host' => array( |
|
238
|
|
|
'ezpublish.dev' => 'ezdemo_site', |
|
239
|
|
|
'admin.ezpublish.dev' => 'ezdemo_site_admin', |
|
240
|
|
|
), |
|
241
|
|
|
'\\My\\Custom\\Matcher' => array( |
|
242
|
|
|
'some' => 'configuration', |
|
243
|
|
|
), |
|
244
|
|
|
'@my.custom.matcher' => array( |
|
245
|
|
|
'some' => 'other_configuration', |
|
246
|
|
|
), |
|
247
|
|
|
) |
|
248
|
|
|
) |
|
249
|
|
|
->isRequired() |
|
250
|
|
|
->useAttributeAsKey('key') |
|
251
|
|
|
->normalizeKeys(false) |
|
252
|
|
|
->prototype('array') |
|
253
|
|
|
->useAttributeAsKey('key') |
|
254
|
|
|
->beforeNormalization() |
|
255
|
|
|
->always( |
|
256
|
|
|
function ($v) { |
|
257
|
|
|
// Value passed to the matcher should always be an array. |
|
258
|
|
|
// If value is not an array, we transform it to a hash, with 'value' as key. |
|
259
|
|
|
if (!is_array($v)) { |
|
260
|
|
|
return array('value' => $v); |
|
261
|
|
|
} |
|
262
|
|
|
|
|
263
|
|
|
// If passed value is a numerically indexed array, we must convert it into a hash. |
|
264
|
|
|
// See https://jira.ez.no/browse/EZP-21876 |
|
265
|
|
|
if (array_keys($v) === range(0, count($v) - 1)) { |
|
266
|
|
|
$final = array(); |
|
267
|
|
|
foreach ($v as $i => $val) { |
|
268
|
|
|
$final["i$i"] = $val; |
|
269
|
|
|
} |
|
270
|
|
|
|
|
271
|
|
|
return $final; |
|
272
|
|
|
} |
|
273
|
|
|
|
|
274
|
|
|
return $v; |
|
275
|
|
|
} |
|
276
|
|
|
) |
|
277
|
|
|
->end() |
|
278
|
|
|
->normalizeKeys(false) |
|
279
|
|
|
->prototype('variable')->end() |
|
280
|
|
|
->end() |
|
281
|
|
|
->end() |
|
282
|
|
|
->end() |
|
283
|
|
|
->beforeNormalization() |
|
284
|
|
|
->always()->then(function ($v) { |
|
285
|
|
|
if (isset($this->siteAccessConfigurationFilters)) { |
|
286
|
|
|
foreach ($this->siteAccessConfigurationFilters as $filter) { |
|
287
|
|
|
$v = $filter->filter($v); |
|
288
|
|
|
} |
|
289
|
|
|
} |
|
290
|
|
|
|
|
291
|
|
|
return $v; |
|
292
|
|
|
}) |
|
293
|
|
|
->end() |
|
294
|
|
|
->end() |
|
295
|
|
|
->arrayNode('locale_conversion') |
|
296
|
|
|
->info('Locale conversion map between eZ Publish format (i.e. fre-FR) to POSIX (i.e. fr_FR). The key is the eZ Publish locale. Check locale.yml in EzPublishCoreBundle to see natively supported locales.') |
|
297
|
|
|
->example(array('fre-FR' => 'fr_FR')) |
|
298
|
|
|
->useAttributeAsKey('key') |
|
299
|
|
|
->normalizeKeys(false) |
|
300
|
|
|
->prototype('scalar')->end() |
|
301
|
|
|
->end() |
|
302
|
|
|
->end(); |
|
303
|
|
|
} |
|
304
|
|
|
|
|
305
|
|
|
private function addImageMagickSection(ArrayNodeDefinition $rootNode) |
|
306
|
|
|
{ |
|
307
|
|
|
$filtersInfo = |
|
308
|
|
|
<<<EOT |
|
309
|
|
|
DEPRECATED. |
|
310
|
|
|
This is only used for legacy injection. |
|
311
|
|
|
You may use imagick/gmagick liip_imagine bundle drivers. |
|
312
|
|
|
|
|
313
|
|
|
Hash of filters to be used for your image variations config. |
|
314
|
|
|
# Key is the filter name, value is an argument passed to "convert" binary. |
|
315
|
|
|
# You can use numbered placeholders (aka input variables) that will be replaced by defined parameters in your image variations config |
|
316
|
|
|
EOT; |
|
317
|
|
|
|
|
318
|
|
|
$rootNode |
|
319
|
|
|
->children() |
|
320
|
|
|
->arrayNode('imagemagick') |
|
321
|
|
|
->info('ImageMagick configuration') |
|
322
|
|
|
->children() |
|
323
|
|
|
->booleanNode('enabled')->defaultTrue()->end() |
|
324
|
|
|
->scalarNode('path') |
|
325
|
|
|
->info('Absolute path of ImageMagick / GraphicsMagick "convert" binary.') |
|
326
|
|
|
->beforeNormalization() |
|
327
|
|
|
->ifTrue( |
|
328
|
|
|
function ($v) { |
|
329
|
|
|
$basename = basename($v); |
|
330
|
|
|
// If there is a space in the basename, just drop it and everything after it. |
|
331
|
|
|
if (($wsPos = strpos($basename, ' ')) !== false) { |
|
332
|
|
|
$basename = substr($basename, 0, $wsPos); |
|
333
|
|
|
} |
|
334
|
|
|
|
|
335
|
|
|
return !is_executable(dirname($v) . DIRECTORY_SEPARATOR . $basename); |
|
336
|
|
|
} |
|
337
|
|
|
) |
|
338
|
|
|
->thenInvalid('Please provide full path to ImageMagick / GraphicsMagick "convert" binary. Please also check that it is executable.') |
|
339
|
|
|
->end() |
|
340
|
|
|
->end() |
|
341
|
|
|
->arrayNode('filters') |
|
342
|
|
|
->info($filtersInfo) |
|
343
|
|
|
->example(array('geometry/scaledownonly' => '"-geometry {1}x{2}>"')) |
|
344
|
|
|
->prototype('scalar')->end() |
|
345
|
|
|
->end() |
|
346
|
|
|
->end() |
|
347
|
|
|
->end() |
|
348
|
|
|
->end(); |
|
349
|
|
|
} |
|
350
|
|
|
|
|
351
|
|
|
private function addHttpCacheSection(ArrayNodeDefinition $rootNode) |
|
352
|
|
|
{ |
|
353
|
|
|
$purgeTypeInfo = <<<EOT |
|
354
|
|
|
Http cache purge type. |
|
355
|
|
|
|
|
356
|
|
|
Cache purge for content/locations is triggered when needed (e.g. on publish) and will result in one or several Http PURGE requests. |
|
357
|
|
|
Can be "local", "http" or a valid symfony service id: |
|
358
|
|
|
- If "local" is used, an Http PURGE request will be emulated when needed (e.g. when using Symfony internal reverse proxy). |
|
359
|
|
|
- If "http" is used, a full HTTP PURGE/BAN is done to a real reverse proxy (Varnish, ..) depending on your config |
|
360
|
|
|
- If custom symfony service id is used, then check documentation on that service for how it behaves and how you need to configure your system for it. |
|
361
|
|
|
|
|
362
|
|
|
If ezplatform-http-cache package is enabled (default as of 1.12 and up), then go to documentation on this package for further |
|
363
|
|
|
info on how it supports multiple response tagging, purges and allow plugins for custom purge types. |
|
364
|
|
|
|
|
365
|
|
|
If that is not enabled, then the (deprecated as of 1.8) default BAN based system will be used instead. |
|
366
|
|
|
Where ressponses can be tagged by a single X-Location-Id header, and for purges a single Http BAN request will be sent, |
|
367
|
|
|
where X-Location-Id header consists of a Regexp containing locationIds to ban. |
|
368
|
|
|
BAN Examples: |
|
369
|
|
|
- (123|456|789) => Purge locations #123, #456, #789. |
|
370
|
|
|
- .* => Purge all locations. |
|
371
|
|
|
EOT; |
|
372
|
|
|
|
|
373
|
|
|
$rootNode |
|
374
|
|
|
->children() |
|
375
|
|
|
->arrayNode('http_cache') |
|
376
|
|
|
->children() |
|
377
|
|
|
->scalarNode('purge_type') |
|
378
|
|
|
->info($purgeTypeInfo) |
|
379
|
|
|
->defaultValue('local') |
|
380
|
|
|
->beforeNormalization() |
|
381
|
|
|
->ifTrue( |
|
382
|
|
|
function ($v) { |
|
383
|
|
|
$http = array('multiple_http' => true, 'single_http' => true); |
|
384
|
|
|
|
|
385
|
|
|
return isset($http[$v]); |
|
386
|
|
|
} |
|
387
|
|
|
) |
|
388
|
|
|
->then( |
|
389
|
|
|
function () { |
|
390
|
|
|
return 'http'; |
|
391
|
|
|
} |
|
392
|
|
|
) |
|
393
|
|
|
->end() |
|
394
|
|
|
->end() |
|
395
|
|
|
->scalarNode('timeout')->info('DEPRECATED')->end() |
|
396
|
|
|
->end() |
|
397
|
|
|
->end() |
|
398
|
|
|
->end(); |
|
399
|
|
|
} |
|
400
|
|
|
|
|
401
|
|
|
private function addRouterSection(ArrayNodeDefinition $rootNode) |
|
402
|
|
|
{ |
|
403
|
|
|
$nonSAAwareInfo = <<<EOT |
|
404
|
|
|
Route names that are not supposed to be SiteAccess aware, i.e. Routes pointing to asset generation (like assetic). |
|
405
|
|
|
Note that you can just specify a prefix to match a selection of routes. |
|
406
|
|
|
e.g. "_assetic_" will match "_assetic_*" |
|
407
|
|
|
Defaults to ['_assetic_', '_wdt', '_profiler', '_configurator_'] |
|
408
|
|
|
EOT; |
|
409
|
|
|
$rootNode |
|
410
|
|
|
->children() |
|
411
|
|
|
->arrayNode('router') |
|
412
|
|
|
->children() |
|
413
|
|
|
->arrayNode('default_router') |
|
414
|
|
|
->children() |
|
415
|
|
|
->arrayNode('non_siteaccess_aware_routes') |
|
416
|
|
|
->prototype('scalar')->end() |
|
417
|
|
|
->info($nonSAAwareInfo) |
|
418
|
|
|
->example(array('my_route_name', 'some_prefix_')) |
|
419
|
|
|
->end() |
|
420
|
|
|
->end() |
|
421
|
|
|
->end() |
|
422
|
|
|
->end() |
|
423
|
|
|
->info('Router related settings') |
|
424
|
|
|
->end() |
|
425
|
|
|
->end(); |
|
426
|
|
|
} |
|
427
|
|
|
|
|
428
|
|
|
/** |
|
429
|
|
|
* Define global Semantic Configuration for RichText. |
|
430
|
|
|
* |
|
431
|
|
|
* @param \Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition $rootNode |
|
432
|
|
|
*/ |
|
433
|
|
|
private function addRichTextSection(ArrayNodeDefinition $rootNode) |
|
434
|
|
|
{ |
|
435
|
|
|
$ezRichTextNode = $rootNode->children()->arrayNode('ezrichtext')->children(); |
|
436
|
|
|
$this->addCustomTagsSection($ezRichTextNode); |
|
437
|
|
|
$this->addCustomStylesSection($ezRichTextNode); |
|
438
|
|
|
$ezRichTextNode->end()->end()->end(); |
|
439
|
|
|
} |
|
440
|
|
|
|
|
441
|
|
|
/** |
|
442
|
|
|
* Define RichText Custom Tags Semantic Configuration. |
|
443
|
|
|
* |
|
444
|
|
|
* The configuration is available at: |
|
445
|
|
|
* <code> |
|
446
|
|
|
* ezpublish: |
|
447
|
|
|
* ezrichtext: |
|
448
|
|
|
* custom_tags: |
|
449
|
|
|
* </code> |
|
450
|
|
|
* |
|
451
|
|
|
* @param \Symfony\Component\Config\Definition\Builder\NodeBuilder $ezRichTextNode |
|
452
|
|
|
* |
|
453
|
|
|
* @return \Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition |
|
454
|
|
|
*/ |
|
455
|
|
|
private function addCustomTagsSection(NodeBuilder $ezRichTextNode) |
|
456
|
|
|
{ |
|
457
|
|
|
return $ezRichTextNode |
|
458
|
|
|
->arrayNode('custom_tags') |
|
459
|
|
|
// workaround: take into account Custom Tag names when merging configs |
|
460
|
|
|
->useAttributeAsKey('tag') |
|
461
|
|
|
->arrayPrototype() |
|
462
|
|
|
->children() |
|
463
|
|
|
->scalarNode('template') |
|
464
|
|
|
->isRequired() |
|
465
|
|
|
->end() |
|
466
|
|
|
->scalarNode('icon') |
|
467
|
|
|
->defaultNull() |
|
468
|
|
|
->end() |
|
469
|
|
|
->arrayNode('attributes') |
|
470
|
|
|
->useAttributeAsKey('attribute') |
|
471
|
|
|
->isRequired() |
|
472
|
|
|
->arrayPrototype() |
|
473
|
|
|
->beforeNormalization() |
|
474
|
|
|
->always( |
|
475
|
|
|
function ($v) { |
|
476
|
|
|
// Workaround: set empty value to be able to unset it later on (see validation for "choices") |
|
477
|
|
|
if (!isset($v['choices'])) { |
|
478
|
|
|
$v['choices'] = []; |
|
479
|
|
|
} |
|
480
|
|
|
|
|
481
|
|
|
return $v; |
|
482
|
|
|
} |
|
483
|
|
|
) |
|
484
|
|
|
->end() |
|
485
|
|
|
->validate() |
|
486
|
|
|
->ifTrue( |
|
487
|
|
|
function ($v) { |
|
488
|
|
|
return $v['type'] === 'choice' && !empty($v['required']) && empty($v['choices']); |
|
489
|
|
|
} |
|
490
|
|
|
) |
|
491
|
|
|
->thenInvalid('List of choices for required choice type attribute has to be non-empty') |
|
492
|
|
|
->end() |
|
493
|
|
|
->validate() |
|
494
|
|
|
->ifTrue( |
|
495
|
|
|
function ($v) { |
|
496
|
|
|
return !empty($v['choices']) && $v['type'] !== 'choice'; |
|
497
|
|
|
} |
|
498
|
|
|
) |
|
499
|
|
|
->thenInvalid('List of choices is supported by choices type only.') |
|
500
|
|
|
->end() |
|
501
|
|
|
->children() |
|
502
|
|
|
->enumNode('type') |
|
503
|
|
|
->isRequired() |
|
504
|
|
|
->values(static::CUSTOM_TAG_ATTRIBUTE_TYPES) |
|
505
|
|
|
->end() |
|
506
|
|
|
->booleanNode('required') |
|
507
|
|
|
->defaultFalse() |
|
508
|
|
|
->end() |
|
509
|
|
|
->scalarNode('default_value') |
|
510
|
|
|
->defaultNull() |
|
511
|
|
|
->end() |
|
512
|
|
|
->arrayNode('choices') |
|
513
|
|
|
->scalarPrototype()->end() |
|
514
|
|
|
->performNoDeepMerging() |
|
515
|
|
|
->validate() |
|
516
|
|
|
->ifEmpty()->thenUnset() |
|
517
|
|
|
->end() |
|
518
|
|
|
->end() |
|
519
|
|
|
->end() |
|
520
|
|
|
->end() |
|
521
|
|
|
->end() |
|
522
|
|
|
->end() |
|
523
|
|
|
->end() |
|
524
|
|
|
->end() |
|
525
|
|
|
; |
|
526
|
|
|
} |
|
527
|
|
|
|
|
528
|
|
|
/** |
|
529
|
|
|
* Define RichText Custom Styles Semantic Configuration. |
|
530
|
|
|
* |
|
531
|
|
|
* The configuration is available at: |
|
532
|
|
|
* <code> |
|
533
|
|
|
* ezpublish: |
|
534
|
|
|
* ezrichtext: |
|
535
|
|
|
* custom_styles: |
|
536
|
|
|
* </code> |
|
537
|
|
|
* |
|
538
|
|
|
* @param \Symfony\Component\Config\Definition\Builder\NodeBuilder $ezRichTextNode |
|
539
|
|
|
* |
|
540
|
|
|
* @return \Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition |
|
541
|
|
|
*/ |
|
542
|
|
|
private function addCustomStylesSection(NodeBuilder $ezRichTextNode) |
|
543
|
|
|
{ |
|
544
|
|
|
return $ezRichTextNode |
|
545
|
|
|
->arrayNode('custom_styles') |
|
546
|
|
|
// workaround: take into account Custom Styles names when merging configs |
|
547
|
|
|
->useAttributeAsKey('style') |
|
548
|
|
|
->arrayPrototype() |
|
549
|
|
|
->children() |
|
550
|
|
|
->scalarNode('template') |
|
551
|
|
|
->defaultNull() |
|
552
|
|
|
->end() |
|
553
|
|
|
->scalarNode('inline') |
|
554
|
|
|
->defaultFalse() |
|
555
|
|
|
->end() |
|
556
|
|
|
->end() |
|
557
|
|
|
->end() |
|
558
|
|
|
->end() |
|
559
|
|
|
; |
|
560
|
|
|
} |
|
561
|
|
|
|
|
562
|
|
|
/** |
|
563
|
|
|
* Defines configuration the images placeholder generation. |
|
564
|
|
|
* |
|
565
|
|
|
* @param \Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition $rootNode |
|
566
|
|
|
*/ |
|
567
|
|
|
private function addImagePlaceholderSection(ArrayNodeDefinition $rootNode) |
|
568
|
|
|
{ |
|
569
|
|
|
$rootNode |
|
570
|
|
|
->children() |
|
571
|
|
|
->arrayNode('image_placeholder') |
|
572
|
|
|
->info('Configuration for strategy of replacing missing images') |
|
573
|
|
|
->useAttributeAsKey('name') |
|
574
|
|
|
->arrayPrototype() |
|
575
|
|
|
->children() |
|
576
|
|
|
->scalarNode('provider') |
|
577
|
|
|
->end() |
|
578
|
|
|
->variableNode('options') |
|
579
|
|
|
->defaultValue([]) |
|
580
|
|
|
->end() |
|
581
|
|
|
->end() |
|
582
|
|
|
->end() |
|
583
|
|
|
->end() |
|
584
|
|
|
->end(); |
|
585
|
|
|
} |
|
586
|
|
|
|
|
587
|
|
|
/** |
|
588
|
|
|
* Define Url Alias Slug converter Semantic Configuration. |
|
589
|
|
|
* |
|
590
|
|
|
* The configuration is available at: |
|
591
|
|
|
* <code> |
|
592
|
|
|
* ezpublish: |
|
593
|
|
|
* url_alias: |
|
594
|
|
|
* slug_converter: |
|
595
|
|
|
* transformation: name_of_transformation_group_to_use |
|
596
|
|
|
* separator: name_of_separator_to_use |
|
597
|
|
|
* transformation_groups: |
|
598
|
|
|
* transformation_group_name: name of existing or new transformation group |
|
599
|
|
|
* commands : [] array of commands which will be added to group |
|
600
|
|
|
* cleanup_method: name_of_cleanup_method |
|
601
|
|
|
* </code> |
|
602
|
|
|
* |
|
603
|
|
|
* @param \Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition $rootNode |
|
604
|
|
|
* |
|
605
|
|
|
* @return \Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition |
|
606
|
|
|
*/ |
|
607
|
|
|
private function addUrlAliasSection(ArrayNodeDefinition $rootNode) |
|
608
|
|
|
{ |
|
609
|
|
|
return $rootNode |
|
610
|
|
|
->children() |
|
611
|
|
|
->arrayNode('url_alias') |
|
612
|
|
|
->children() |
|
613
|
|
|
->arrayNode('slug_converter') |
|
614
|
|
|
->children() |
|
615
|
|
|
->scalarNode('transformation')->end() |
|
616
|
|
|
->scalarNode('separator')->end() |
|
617
|
|
|
->arrayNode('transformation_groups') |
|
618
|
|
|
->arrayPrototype() |
|
619
|
|
|
->children() |
|
620
|
|
|
->arrayNode('commands') |
|
621
|
|
|
->scalarPrototype()->end() |
|
622
|
|
|
->end() |
|
623
|
|
|
->scalarNode('cleanup_method')->end() |
|
624
|
|
|
->end() |
|
625
|
|
|
->end() |
|
626
|
|
|
->end() |
|
627
|
|
|
->end() |
|
628
|
|
|
->end() |
|
629
|
|
|
->end() |
|
630
|
|
|
->end() |
|
631
|
|
|
->end(); |
|
632
|
|
|
} |
|
633
|
|
|
|
|
634
|
|
|
/** |
|
635
|
|
|
* Defines configuration for Url Wildcards. |
|
636
|
|
|
* |
|
637
|
|
|
* The configuration is available at: |
|
638
|
|
|
* <code> |
|
639
|
|
|
* ezpublish: |
|
640
|
|
|
* url_wildcards: |
|
641
|
|
|
* enabled: true |
|
642
|
|
|
* </code> |
|
643
|
|
|
* |
|
644
|
|
|
* @param \Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition $rootNode |
|
645
|
|
|
* |
|
646
|
|
|
* @return \Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition |
|
647
|
|
|
*/ |
|
648
|
|
|
private function addUrlWildcardsSection($rootNode): ArrayNodeDefinition |
|
649
|
|
|
{ |
|
650
|
|
|
return $rootNode |
|
651
|
|
|
->children() |
|
652
|
|
|
->arrayNode('url_wildcards') |
|
653
|
|
|
->children() |
|
654
|
|
|
->booleanNode('enabled') |
|
655
|
|
|
->info('Enable UrlWildcards support') |
|
656
|
|
|
->defaultFalse() |
|
657
|
|
|
->end() |
|
658
|
|
|
->end() |
|
659
|
|
|
->end() |
|
660
|
|
|
->end(); |
|
661
|
|
|
} |
|
662
|
|
|
} |
|
663
|
|
|
|
This method has been deprecated. The supplier of the class has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.