Passed
Pull Request — master (#7060)
by
unknown
09:02
created

SettingsManager::createSettingForCurrentUrl()   F

Complexity

Conditions 16
Paths 260

Size

Total Lines 75
Code Lines 39

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 16
eloc 39
c 1
b 0
f 0
nc 260
nop 3
dl 0
loc 75
rs 3.9833

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
declare(strict_types=1);
4
5
/* For licensing terms, see /license.txt */
6
7
namespace Chamilo\CoreBundle\Settings;
8
9
use Chamilo\CoreBundle\Entity\AccessUrl;
10
use Chamilo\CoreBundle\Entity\Course;
11
use Chamilo\CoreBundle\Entity\SettingsCurrent;
12
use Chamilo\CoreBundle\Helpers\SettingsManagerHelper;
13
use Chamilo\CoreBundle\Search\SearchEngineFieldSynchronizer;
14
use Doctrine\ORM\EntityManager;
15
use Doctrine\ORM\EntityRepository;
16
use InvalidArgumentException;
17
use Sylius\Bundle\SettingsBundle\Manager\SettingsManagerInterface;
18
use Sylius\Bundle\SettingsBundle\Model\Settings;
19
use Sylius\Bundle\SettingsBundle\Model\SettingsInterface;
20
use Sylius\Bundle\SettingsBundle\Registry\ServiceRegistryInterface;
21
use Sylius\Bundle\SettingsBundle\Schema\SchemaInterface;
22
use Sylius\Bundle\SettingsBundle\Schema\SettingsBuilder;
23
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
24
use Symfony\Component\HttpFoundation\RequestStack;
25
use Symfony\Component\Validator\Exception\ValidatorException;
26
27
use const ARRAY_FILTER_USE_KEY;
28
29
/**
30
 * Handles the platform settings.
31
 */
32
class SettingsManager implements SettingsManagerInterface
33
{
34
    protected ?AccessUrl $url = null;
35
36
    protected ServiceRegistryInterface $schemaRegistry;
37
38
    protected EntityManager $manager;
39
40
    protected EntityRepository $repository;
41
42
    protected EventDispatcherInterface $eventDispatcher;
43
44
    /**
45
     * Runtime cache for resolved parameters.
46
     *
47
     * @var Settings[]
48
     */
49
    protected array $resolvedSettings = [];
50
51
    /**
52
     * @var null|array<string, Settings>|mixed[]
53
     */
54
    protected ?array $schemaList;
55
56
    protected RequestStack $request;
57
58
    public function __construct(
59
        ServiceRegistryInterface $schemaRegistry,
60
        EntityManager $manager,
61
        EntityRepository $repository,
62
        EventDispatcherInterface $eventDispatcher,
63
        RequestStack $request,
64
        protected readonly SettingsManagerHelper $settingsManagerHelper,
65
        private readonly SearchEngineFieldSynchronizer $searchEngineFieldSynchronizer,
66
    ) {
67
        $this->schemaRegistry = $schemaRegistry;
68
        $this->manager = $manager;
69
        $this->repository = $repository;
70
        $this->eventDispatcher = $eventDispatcher;
71
        $this->request = $request;
72
        $this->schemaList = [];
73
    }
74
75
    public function getUrl(): ?AccessUrl
76
    {
77
        return $this->url;
78
    }
79
80
    public function setUrl(AccessUrl $url): void
81
    {
82
        $this->url = $url;
83
    }
84
85
    public function updateSchemas(AccessUrl $url): void
86
    {
87
        $this->url = $url;
88
        $schemas = array_keys($this->getSchemas());
89
        foreach ($schemas as $schema) {
90
            $settings = $this->load($this->convertServiceToNameSpace($schema));
91
            $this->update($settings);
92
        }
93
    }
94
95
    public function installSchemas(AccessUrl $url): void
96
    {
97
        $this->url = $url;
98
        $schemas = array_keys($this->getSchemas());
99
        foreach ($schemas as $schema) {
100
            $settings = $this->load($this->convertServiceToNameSpace($schema));
101
            $this->save($settings);
102
        }
103
    }
104
105
    /**
106
     * @return array|AbstractSettingsSchema[]
107
     */
108
    public function getSchemas(): array
109
    {
110
        return $this->schemaRegistry->all();
111
    }
112
113
    public function convertNameSpaceToService(string $category): string
114
    {
115
        return 'chamilo_core.settings.'.$category;
116
    }
117
118
    public function convertServiceToNameSpace(string $category): string
119
    {
120
        return str_replace('chamilo_core.settings.', '', $category);
121
    }
122
123
    public function updateSetting(string $name, $value): void
124
    {
125
        $name = $this->validateSetting($name);
126
127
        [$category, $name] = explode('.', $name);
128
        $settings = $this->load($category);
129
130
        if (!$settings->has($name)) {
131
            $message = \sprintf("Parameter %s doesn't exists.", $name);
132
133
            throw new InvalidArgumentException($message);
134
        }
135
136
        $settings->set($name, $value);
137
        $this->update($settings);
138
    }
139
140
    /**
141
     * Get a specific configuration setting, getting from the previously stored
142
     * PHP session data whenever possible.
143
     *
144
     * @param string $name       The setting name (composed if in a category, i.e. 'platform.institution')
145
     * @param bool   $loadFromDb Whether to load from the database
146
     */
147
    public function getSetting(string $name, bool $loadFromDb = false): mixed
148
    {
149
        $name = $this->validateSetting($name);
150
151
        $overridden = $this->settingsManagerHelper->getOverride($name);
152
153
        if (null !== $overridden) {
154
            return $overridden;
155
        }
156
157
        [$category, $name] = explode('.', $name);
158
159
        if ($loadFromDb) {
160
            $settings = $this->load($category, $name);
161
            if ($settings->has($name)) {
162
                return $settings->get($name);
163
            }
164
165
            return null;
166
        }
167
168
        $this->loadAll();
169
170
        if (!empty($this->schemaList) && isset($this->schemaList[$category])) {
171
            $settings = $this->schemaList[$category];
172
            if ($settings->has($name)) {
173
                return $settings->get($name);
174
            }
175
            error_log("Attempted to access undefined setting '$name' in category '$category'.");
176
177
            return null;
178
        }
179
180
        throw new InvalidArgumentException(\sprintf('Category %s not found', $category));
181
    }
182
183
    public function loadAll(): void
184
    {
185
        $session = null;
186
187
        if ($this->request->getCurrentRequest()) {
188
            $session = $this->request->getCurrentRequest()->getSession();
189
            $schemaList = $session->get('schemas');
190
            if (!empty($schemaList)) {
191
                $this->schemaList = $schemaList;
192
193
                return;
194
            }
195
        }
196
197
        $schemas = array_keys($this->getSchemas());
198
        $schemaList = [];
199
        $settingsBuilder = new SettingsBuilder();
200
        $all = $this->getAllParametersByCategory();
201
202
        foreach ($schemas as $schema) {
203
            $schemaRegister = $this->schemaRegistry->get($schema);
204
            $schemaRegister->buildSettings($settingsBuilder);
205
            $name = $this->convertServiceToNameSpace($schema);
206
            $settings = new Settings();
207
208
            /** @var array<string, mixed> $parameters */
209
            $parameters = $all[$name] ?? [];
210
211
            $knownParameters = array_filter(
212
                $parameters,
213
                fn ($key): bool => $settingsBuilder->isDefined($key),
214
                ARRAY_FILTER_USE_KEY
215
            );
216
217
            $transformers = $settingsBuilder->getTransformers();
218
            foreach ($transformers as $parameter => $transformer) {
219
                if (\array_key_exists($parameter, $knownParameters)) {
220
                    if ('course_creation_use_template' === $parameter) {
221
                        if (empty($knownParameters[$parameter])) {
222
                            $knownParameters[$parameter] = null;
223
                        }
224
                    } else {
225
                        $knownParameters[$parameter] = $transformer->reverseTransform($knownParameters[$parameter]);
226
                    }
227
                }
228
            }
229
230
            $knownParameters = $this->normalizeNullsBeforeResolve($knownParameters, $settingsBuilder);
231
            $parameters = $settingsBuilder->resolve($knownParameters);
232
            $settings->setParameters($parameters);
233
            $schemaList[$name] = $settings;
234
        }
235
        $this->schemaList = $schemaList;
236
        if ($session && $this->request->getCurrentRequest()) {
237
            $session->set('schemas', $schemaList);
238
        }
239
    }
240
241
    public function load(string $schemaAlias, ?string $namespace = null, bool $ignoreUnknown = true): SettingsInterface
242
    {
243
        $settings = new Settings();
244
        $schemaAliasNoPrefix = $schemaAlias;
245
        $schemaAlias = 'chamilo_core.settings.'.$schemaAlias;
246
        if ($this->schemaRegistry->has($schemaAlias)) {
247
            /** @var SchemaInterface $schema */
248
            $schema = $this->schemaRegistry->get($schemaAlias);
249
        } else {
250
            return $settings;
251
        }
252
253
        $settings->setSchemaAlias($schemaAlias);
254
255
        // We need to get a plain parameters array since we use the options resolver on it
256
        $parameters = $this->getParameters($schemaAliasNoPrefix);
257
        $settingsBuilder = new SettingsBuilder();
258
        $schema->buildSettings($settingsBuilder);
259
260
        // Remove unknown settings' parameters (e.g. From a previous version of the settings schema)
261
        if (true === $ignoreUnknown) {
262
            foreach ($parameters as $name => $value) {
263
                if (!$settingsBuilder->isDefined($name)) {
264
                    unset($parameters[$name]);
265
                }
266
            }
267
        }
268
269
        foreach ($settingsBuilder->getTransformers() as $parameter => $transformer) {
270
            if (\array_key_exists($parameter, $parameters)) {
271
                $parameters[$parameter] = $transformer->reverseTransform($parameters[$parameter]);
272
            }
273
        }
274
        $parameters = $this->normalizeNullsBeforeResolve($parameters, $settingsBuilder);
275
        $parameters = $settingsBuilder->resolve($parameters);
276
        $settings->setParameters($parameters);
277
278
        return $settings;
279
    }
280
281
    public function update(SettingsInterface $settings): void
282
    {
283
        $namespace = $settings->getSchemaAlias();
284
285
        /** @var SchemaInterface $schema */
286
        $schema = $this->schemaRegistry->get($settings->getSchemaAlias());
287
288
        $settingsBuilder = new SettingsBuilder();
289
        $schema->buildSettings($settingsBuilder);
290
        $raw = $settings->getParameters();
291
        $raw = $this->normalizeNullsBeforeResolve($raw, $settingsBuilder);
292
        $parameters = $settingsBuilder->resolve($raw);
293
        // Transform value. Example array to string using transformer. Example:
294
        // 1. Setting "tool_visible_by_default_at_creation" it's a multiple select
295
        // 2. Is defined as an array in class DocumentSettingsSchema
296
        // 3. Add transformer for that variable "ArrayToIdentifierTransformer"
297
        // 4. Here we recover the transformer and convert the array to string
298
        foreach ($parameters as $parameter => $value) {
299
            $parameters[$parameter] = $this->transformToString($value);
300
        }
301
302
        $settings->setParameters($parameters);
303
        $category = $this->convertServiceToNameSpace($settings->getSchemaAlias());
304
305
        // Restrict lookup to current URL so we do not override settings from other URLs.
306
        $criteria = [
307
            'category' => $category,
308
        ];
309
310
        if (null !== $this->url) {
311
            $criteria['url'] = $this->url;
312
        }
313
314
        $persistedParameters = $this->repository->findBy($criteria);
315
316
        $persistedParametersMap = [];
317
318
        /** @var SettingsCurrent $parameter */
319
        foreach ($persistedParameters as $parameter) {
320
            $persistedParametersMap[$parameter->getVariable()] = $parameter;
321
        }
322
323
        $url = $this->getUrl();
324
        $simpleCategoryName = str_replace('chamilo_core.settings.', '', $namespace);
325
326
        foreach ($parameters as $name => $value) {
327
            // MultiURL: respect access_url_changeable defined on main URL.
328
            if (!$this->isSettingChangeableForCurrentUrl($simpleCategoryName, $name)) {
329
                continue;
330
            }
331
332
            if (isset($persistedParametersMap[$name])) {
333
                $parameter = $persistedParametersMap[$name];
334
                $parameter->setSelectedValue($value);
335
                $parameter->setCategory($simpleCategoryName);
336
                $this->manager->persist($parameter);
337
            } else {
338
                $parameter = (new SettingsCurrent())
339
                    ->setVariable($name)
340
                    ->setCategory($simpleCategoryName)
341
                    ->setTitle($name)
342
                    ->setSelectedValue($value)
343
                    ->setUrl($url)
344
                    ->setAccessUrlChangeable(1)
345
                    ->setAccessUrlLocked(0)
346
                ;
347
348
                $this->manager->persist($parameter);
349
            }
350
        }
351
352
        $this->applySearchEngineFieldsSyncIfNeeded($simpleCategoryName, $parameters);
353
354
        $this->manager->flush();
355
    }
356
357
    /**
358
     * @throws ValidatorException
359
     */
360
    public function save(SettingsInterface $settings): void
361
    {
362
        $namespace = $settings->getSchemaAlias();
363
364
        /** @var SchemaInterface $schema */
365
        $schema = $this->schemaRegistry->get($settings->getSchemaAlias());
366
367
        $settingsBuilder = new SettingsBuilder();
368
        $schema->buildSettings($settingsBuilder);
369
        $raw = $settings->getParameters();
370
        $raw = $this->normalizeNullsBeforeResolve($raw, $settingsBuilder);
371
        $parameters = $settingsBuilder->resolve($raw);
372
        // Transform value. Example array to string using transformer. Example:
373
        // 1. Setting "tool_visible_by_default_at_creation" it's a multiple select
374
        // 2. Is defined as an array in class DocumentSettingsSchema
375
        // 3. Add transformer for that variable "ArrayToIdentifierTransformer"
376
        // 4. Here we recover the transformer and convert the array to string
377
        foreach ($parameters as $parameter => $value) {
378
            $parameters[$parameter] = $this->transformToString($value);
379
        }
380
        $settings->setParameters($parameters);
381
        $criteria = [
382
            'category' => $this->convertServiceToNameSpace($settings->getSchemaAlias()),
383
        ];
384
385
        // Limit to current URL so we do not write across all URLs.
386
        if (null !== $this->url) {
387
            $criteria['url'] = $this->url;
388
        }
389
390
        $persistedParameters = $this->repository->findBy($criteria);
391
        $persistedParametersMap = [];
392
        foreach ($persistedParameters as $parameter) {
393
            $persistedParametersMap[$parameter->getVariable()] = $parameter;
394
        }
395
396
        $url = $this->getUrl();
397
        $simpleCategoryName = str_replace('chamilo_core.settings.', '', $namespace);
398
399
        foreach ($parameters as $name => $value) {
400
            // MultiURL: respect access_url_changeable defined on main URL.
401
            if (!$this->isSettingChangeableForCurrentUrl($simpleCategoryName, $name)) {
402
                continue;
403
            }
404
405
            if (isset($persistedParametersMap[$name])) {
406
                $parameter = $persistedParametersMap[$name];
407
                $parameter->setSelectedValue($value);
408
            } else {
409
                $parameter = (new SettingsCurrent())
410
                    ->setVariable($name)
411
                    ->setCategory($simpleCategoryName)
412
                    ->setTitle($name)
413
                    ->setSelectedValue($value)
414
                    ->setUrl($url)
415
                    ->setAccessUrlChangeable(1)
416
                    ->setAccessUrlLocked(0)
417
                ;
418
419
                $this->manager->persist($parameter);
420
            }
421
        }
422
423
        $this->applySearchEngineFieldsSyncIfNeeded($simpleCategoryName, $parameters);
424
425
        $this->manager->flush();
426
    }
427
428
    /**
429
     * Sync JSON-defined search fields into search_engine_field table.
430
     */
431
    private function applySearchEngineFieldsSyncIfNeeded(string $category, array $parameters): void
432
    {
433
        if ('search' !== $category) {
434
            return;
435
        }
436
437
        if (!\array_key_exists('search_prefilter_prefix', $parameters)) {
438
            return;
439
        }
440
441
        $json = (string) $parameters['search_prefilter_prefix'];
442
443
        // Non-destructive by default (no deletes)
444
        $this->searchEngineFieldSynchronizer->syncFromJson($json, true);
445
    }
446
447
    /**
448
     * @param string $keyword
449
     */
450
    public function getParametersFromKeywordOrderedByCategory($keyword): array
451
    {
452
        $qb = $this->repository->createQueryBuilder('s')
453
            ->where('s.variable LIKE :keyword OR s.title LIKE :keyword')
454
            ->setParameter('keyword', "%{$keyword}%");
455
456
        // Restrict search to current URL when available.
457
        if (null !== $this->url) {
458
            $qb
459
                ->andWhere('s.url = :url')
460
                ->setParameter('url', $this->url);
461
        }
462
463
        $parametersFromDb = $qb->getQuery()->getResult();
464
        $parameters = [];
465
466
        foreach ($parametersFromDb as $parameter) {
467
            /** @var SettingsCurrent $parameter */
468
            $category = $parameter->getCategory();
469
            $variable = $parameter->getVariable();
470
471
            $hidden = [];
472
            $serviceKey = 'chamilo_core.settings.'.$category;
473
            if ($this->schemaRegistry->has($serviceKey)) {
474
                $schema = $this->schemaRegistry->get($serviceKey);
475
                if (method_exists($schema, 'getHiddenSettings')) {
476
                    $hidden = $schema->getHiddenSettings();
477
                }
478
            }
479
480
            if (\in_array($variable, $hidden, true)) {
481
                continue;
482
            }
483
484
            $parameters[$category][] = $parameter;
485
        }
486
487
        return $parameters;
488
    }
489
490
    /**
491
     * @param string $namespace
492
     * @param string $keyword
493
     * @param bool   $returnObjects
494
     *
495
     * @return array
496
     */
497
    public function getParametersFromKeyword($namespace, $keyword = '', $returnObjects = false)
498
    {
499
        if (empty($keyword)) {
500
            $criteria = [
501
                'category' => $namespace,
502
            ];
503
504
            if (null !== $this->url) {
505
                $criteria['url'] = $this->url;
506
            }
507
508
            $parametersFromDb = $this->repository->findBy($criteria);
509
        } else {
510
            $qb = $this->repository->createQueryBuilder('s')
511
                ->where('s.variable LIKE :keyword')
512
                ->setParameter('keyword', "%{$keyword}%");
513
514
            if (null !== $this->url) {
515
                $qb
516
                    ->andWhere('s.url = :url')
517
                    ->setParameter('url', $this->url);
518
            }
519
520
            $parametersFromDb = $qb->getQuery()->getResult();
521
        }
522
523
        if ($returnObjects) {
524
            return $parametersFromDb;
525
        }
526
        $parameters = [];
527
528
        /** @var SettingsCurrent $parameter */
529
        foreach ($parametersFromDb as $parameter) {
530
            $parameters[$parameter->getVariable()] = $parameter->getSelectedValue();
531
        }
532
533
        return $parameters;
534
    }
535
536
    private function validateSetting(string $name): string
537
    {
538
        if (!str_contains($name, '.')) {
539
            // throw new \InvalidArgumentException(sprintf('Parameter must be in format "namespace.name", "%s" given.', $name));
540
541
            // This code allows the possibility of calling
542
            // api_get_setting('allow_skills_tool') instead of
543
            // the "correct" way api_get_setting('platform.allow_skills_tool')
544
            $items = $this->getVariablesAndCategories();
545
546
            if (isset($items[$name])) {
547
                $originalName = $name;
548
                $name = $this->renameVariable($name);
549
                $category = $this->fixCategory(
550
                    strtolower($name),
551
                    strtolower($items[$originalName])
552
                );
553
                $name = $category.'.'.$name;
554
            } else {
555
                $message = \sprintf('Parameter must be in format "category.name", "%s" given.', $name);
556
557
                throw new InvalidArgumentException($message);
558
            }
559
        }
560
561
        return $name;
562
    }
563
564
    /**
565
     * Load parameter from database.
566
     *
567
     * @param string $namespace
568
     *
569
     * @return array
570
     */
571
    private function getParameters($namespace)
572
    {
573
        $parameters = [];
574
575
        $criteria = ['category' => $namespace];
576
577
        // MultiURL: only parameters for current URL (if set).
578
        if (null !== $this->url) {
579
            $criteria['url'] = $this->url;
580
        }
581
582
        $category = $this->repository->findBy($criteria);
583
584
        /** @var SettingsCurrent $parameter */
585
        foreach ($category as $parameter) {
586
            $parameters[$parameter->getVariable()] = $parameter->getSelectedValue();
587
        }
588
589
        return $parameters;
590
    }
591
592
    private function getAllParametersByCategory()
593
    {
594
        $parameters = [];
595
596
        // MultiURL: either all parameters (single URL mode) or only for current URL.
597
        if (null !== $this->url) {
598
            $all = $this->repository->findBy(['url' => $this->url]);
599
        } else {
600
            $all = $this->repository->findAll();
601
        }
602
603
        /** @var SettingsCurrent $parameter */
604
        foreach ($all as $parameter) {
605
            $parameters[$parameter->getCategory()][$parameter->getVariable()] = $parameter->getSelectedValue();
606
        }
607
608
        return $parameters;
609
    }
610
611
    /**
612
     * Check if a setting is changeable for the current URL, using the
613
     * access_url_changeable flag from the main URL (ID = 1).
614
     */
615
    private function isSettingChangeableForCurrentUrl(string $category, string $variable): bool
616
    {
617
        // No URL bound: behave as legacy single-URL platform.
618
        if (null === $this->url) {
619
            return true;
620
        }
621
622
        // Main URL can always edit settings. UI already restricts who can see/edit fields.
623
        if (1 === $this->url->getId()) {
624
            return true;
625
        }
626
627
        // Try to load main (canonical) URL.
628
        $mainUrl = $this->manager->getRepository(AccessUrl::class)->find(1);
629
        if (null === $mainUrl) {
630
            // If main URL is missing, fallback to permissive behaviour.
631
            return true;
632
        }
633
634
        /** @var SettingsCurrent|null $mainSetting */
635
        $mainSetting = $this->repository->findOneBy([
636
            'category' => $category,
637
            'variable' => $variable,
638
            'url' => $mainUrl,
639
        ]);
640
641
        if (null === $mainSetting) {
642
            // If there is no canonical row, do not block changes.
643
            return true;
644
        }
645
646
        // When access_url_changeable is false/0 on main URL,
647
        // secondary URLs must not override the value.
648
        return (bool) $mainSetting->getAccessUrlChangeable();
649
    }
650
651
    private function createSettingForCurrentUrl(string $category, string $variable, string $value): SettingsCurrent
0 ignored issues
show
Unused Code introduced by
The method createSettingForCurrentUrl() is not used, and could be removed.

This check looks for private methods that have been defined, but are not used inside the class.

Loading history...
652
    {
653
        $url = $this->getUrl();
654
655
        // Try to reuse metadata from main URL (ID = 1) as canonical definition.
656
        $mainUrl = $this->manager->getRepository(AccessUrl::class)->find(1);
657
658
        $reference = null;
659
660
        if (null !== $mainUrl) {
661
            $reference = $this->repository->findOneBy([
662
                'category' => $category,
663
                'variable' => $variable,
664
                'url' => $mainUrl,
665
            ]);
666
        }
667
668
        if (!$reference instanceof SettingsCurrent) {
669
            // Fallback: any existing row for this category + variable (legacy / no-URL case).
670
            $reference = $this->repository->findOneBy([
671
                'category' => $category,
672
                'variable' => $variable,
673
            ]);
674
        }
675
676
        $setting = (new SettingsCurrent())
677
            ->setVariable($variable)
678
            ->setCategory($category)
679
            ->setSelectedValue($value)
680
            ->setUrl($url)
681
        ;
682
683
        if ($reference instanceof SettingsCurrent) {
684
            // Copy descriptive metadata so the new URL row behaves like the canonical one.
685
            $setting->setTitle($reference->getTitle());
686
687
            // These fields may or may not exist in the entity in Chamilo 2,
688
            // so we check for method existence to stay safe.
689
            if (method_exists($setting, 'setType') && method_exists($reference, 'getType')) {
690
                $setting->setType($reference->getType());
691
            }
692
693
            if (method_exists($setting, 'setComment') && method_exists($reference, 'getComment')) {
694
                $setting->setComment($reference->getComment());
695
            }
696
697
            if (method_exists($setting, 'setScope') && method_exists($reference, 'getScope')) {
698
                $setting->setScope($reference->getScope());
699
            }
700
701
            if (method_exists($setting, 'setSubkey') && method_exists($reference, 'getSubkey')) {
702
                $setting->setSubkey($reference->getSubkey());
703
            }
704
705
            if (method_exists($setting, 'setSubkeytext') && method_exists($reference, 'getSubkeytext')) {
706
                $setting->setSubkeytext($reference->getSubkeytext());
707
            }
708
709
            // Copy flags and template; the "changeable" flag is still interpreted from main URL.
710
            $setting->setAccessUrlChangeable($reference->getAccessUrlChangeable());
711
            $setting->setAccessUrlLocked($reference->getAccessUrlLocked());
712
713
            if (method_exists($setting, 'setValueTemplate') && method_exists($reference, 'getValueTemplate')) {
714
                $setting->setValueTemplate($reference->getValueTemplate());
715
            }
716
        } else {
717
            // Fallback: minimal metadata if no canonical definition was found.
718
            $setting
719
                ->setTitle($variable)
720
                ->setAccessUrlChangeable(1)
721
                ->setAccessUrlLocked(1)
722
            ;
723
        }
724
725
        return $setting;
726
    }
727
728
    /*private function transformParameters(SettingsBuilder $settingsBuilder, array $parameters)
729
     * {
730
     * $transformedParameters = $parameters;
731
     * foreach ($settingsBuilder->getTransformers() as $parameter => $transformer) {
732
     * if (array_key_exists($parameter, $parameters)) {
733
     * $transformedParameters[$parameter] = $transformer->reverseTransform($parameters[$parameter]);
734
     * }
735
     * }
736
     * return $transformedParameters;
737
     * }*/
738
739
    /**
740
     * Get variables and categories as in 1.11.x.
741
     */
742
    private function getVariablesAndCategories(): array
743
    {
744
        return [
745
            'Institution' => 'Platform',
746
            'InstitutionUrl' => 'Platform',
747
            'siteName' => 'Platform',
748
            'site_name' => 'Platform',
749
            'emailAdministrator' => 'admin',
750
            // 'emailAdministrator' => 'Platform',
751
            'administratorSurname' => 'admin',
752
            'administratorTelephone' => 'admin',
753
            'administratorName' => 'admin',
754
            'show_administrator_data' => 'Platform',
755
            'show_tutor_data' => 'Session',
756
            'show_teacher_data' => 'Platform',
757
            'show_toolshortcuts' => 'Course',
758
            'allow_group_categories' => 'Course',
759
            'server_type' => 'Platform',
760
            'platformLanguage' => 'Language',
761
            'showonline' => 'Platform',
762
            'profile' => 'User',
763
            'default_document_quotum' => 'Course',
764
            'registration' => 'User',
765
            'default_group_quotum' => 'Course',
766
            'allow_registration' => 'Platform',
767
            'allow_registration_as_teacher' => 'Platform',
768
            'allow_lostpassword' => 'Platform',
769
            'allow_user_headings' => 'Course',
770
            'allow_personal_agenda' => 'agenda',
771
            'display_coursecode_in_courselist' => 'Platform',
772
            'display_teacher_in_courselist' => 'Platform',
773
            'permanently_remove_deleted_files' => 'Tools',
774
            'dropbox_allow_overwrite' => 'Tools',
775
            'dropbox_max_filesize' => 'Tools',
776
            'dropbox_allow_just_upload' => 'Tools',
777
            'dropbox_allow_student_to_student' => 'Tools',
778
            'dropbox_allow_group' => 'Tools',
779
            'dropbox_allow_mailing' => 'Tools',
780
            'extended_profile' => 'User',
781
            'student_view_enabled' => 'Platform',
782
            'show_navigation_menu' => 'Course',
783
            'enable_tool_introduction' => 'course',
784
            'page_after_login' => 'Platform',
785
            'time_limit_whosonline' => 'Platform',
786
            'breadcrumbs_course_homepage' => 'Course',
787
            'example_material_course_creation' => 'Platform',
788
            'account_valid_duration' => 'Platform',
789
            'use_session_mode' => 'Session',
790
            'allow_email_editor' => 'Tools',
791
            // 'registered' => null',
792
            // 'donotlistcampus' =>'null',
793
            'show_email_addresses' => 'Platform',
794
            'service_ppt2lp' => 'NULL',
795
            'upload_extensions_list_type' => 'Security',
796
            'upload_extensions_blacklist' => 'Security',
797
            'upload_extensions_whitelist' => 'Security',
798
            'upload_extensions_skip' => 'Security',
799
            'upload_extensions_replace_by' => 'Security',
800
            'show_number_of_courses' => 'Platform',
801
            'show_empty_course_categories' => 'Platform',
802
            'show_back_link_on_top_of_tree' => 'Platform',
803
            'show_different_course_language' => 'Platform',
804
            'split_users_upload_directory' => 'Tuning',
805
            'display_categories_on_homepage' => 'Platform',
806
            'permissions_for_new_directories' => 'Security',
807
            'permissions_for_new_files' => 'Security',
808
            'show_tabs' => 'Platform',
809
            'default_forum_view' => 'Course',
810
            'platform_charset' => 'Languages',
811
            'survey_email_sender_noreply' => 'Course',
812
            'gradebook_enable' => 'Gradebook',
813
            'gradebook_score_display_coloring' => 'Gradebook',
814
            'gradebook_score_display_custom' => 'Gradebook',
815
            'gradebook_score_display_colorsplit' => 'Gradebook',
816
            'gradebook_score_display_upperlimit' => 'Gradebook',
817
            'gradebook_number_decimals' => 'Gradebook',
818
            'user_selected_theme' => 'Platform',
819
            'allow_course_theme' => 'Course',
820
            'show_closed_courses' => 'Platform',
821
            'extendedprofile_registration' => 'User',
822
            'extendedprofile_registrationrequired' => 'User',
823
            'add_users_by_coach' => 'Session',
824
            'extend_rights_for_coach' => 'Security',
825
            'extend_rights_for_coach_on_survey' => 'Security',
826
            'course_create_active_tools' => 'Tools',
827
            'show_session_coach' => 'Session',
828
            'allow_users_to_create_courses' => 'Platform',
829
            'allow_message_tool' => 'Tools',
830
            'allow_social_tool' => 'Tools',
831
            'show_session_data' => 'Session',
832
            'allow_use_sub_language' => 'language',
833
            'show_glossary_in_documents' => 'Course',
834
            'allow_terms_conditions' => 'Platform',
835
            'search_enabled' => 'Search',
836
            'search_prefilter_prefix' => 'Search',
837
            'search_show_unlinked_results' => 'Search',
838
            'allow_coach_to_edit_course_session' => 'Session',
839
            'show_glossary_in_extra_tools' => 'Course',
840
            'send_email_to_admin_when_create_course' => 'Platform',
841
            'go_to_course_after_login' => 'Course',
842
            'math_asciimathML' => 'Editor',
843
            'enabled_asciisvg' => 'Editor',
844
            'include_asciimathml_script' => 'Editor',
845
            'youtube_for_students' => 'Editor',
846
            'block_copy_paste_for_students' => 'Editor',
847
            'more_buttons_maximized_mode' => 'Editor',
848
            'students_download_folders' => 'Document',
849
            'users_copy_files' => 'Tools',
850
            'allow_students_to_create_groups_in_social' => 'Tools',
851
            'allow_send_message_to_all_platform_users' => 'Message',
852
            'message_max_upload_filesize' => 'Tools',
853
            'use_users_timezone' => 'profile',
854
            // 'use_users_timezone' => 'Timezones',
855
            'timezone_value' => 'platform',
856
            // 'timezone_value' => 'Timezones',
857
            'allow_user_course_subscription_by_course_admin' => 'Security',
858
            'show_link_bug_notification' => 'Platform',
859
            'show_link_ticket_notification' => 'Platform',
860
            'course_validation' => 'course',
861
            // 'course_validation' => 'Platform',
862
            'course_validation_terms_and_conditions_url' => 'Platform',
863
            'enabled_wiris' => 'Editor',
864
            'allow_spellcheck' => 'Editor',
865
            'force_wiki_paste_as_plain_text' => 'Editor',
866
            'enabled_googlemaps' => 'Editor',
867
            'enabled_imgmap' => 'Editor',
868
            'enabled_support_svg' => 'Tools',
869
            'pdf_export_watermark_enable' => 'Platform',
870
            'pdf_export_watermark_by_course' => 'Platform',
871
            'pdf_export_watermark_text' => 'Platform',
872
            'enabled_insertHtml' => 'Editor',
873
            'students_export2pdf' => 'Document',
874
            'exercise_min_score' => 'Course',
875
            'exercise_max_score' => 'Course',
876
            'show_users_folders' => 'Tools',
877
            'show_default_folders' => 'Tools',
878
            'show_chat_folder' => 'Tools',
879
            'course_hide_tools' => 'Course',
880
            'show_groups_to_users' => 'Group',
881
            'accessibility_font_resize' => 'Platform',
882
            'hide_courses_in_sessions' => 'Session',
883
            'enable_quiz_scenario' => 'Course',
884
            'filter_terms' => 'Security',
885
            'header_extra_content' => 'Tracking',
886
            'footer_extra_content' => 'Tracking',
887
            'show_documents_preview' => 'Tools',
888
            'htmlpurifier_wiki' => 'Editor',
889
            'cas_activate' => 'CAS',
890
            'cas_server' => 'CAS',
891
            'cas_server_uri' => 'CAS',
892
            'cas_port' => 'CAS',
893
            'cas_protocol' => 'CAS',
894
            'cas_add_user_activate' => 'CAS',
895
            'update_user_info_cas_with_ldap' => 'CAS',
896
            'student_page_after_login' => 'Platform',
897
            'teacher_page_after_login' => 'Platform',
898
            'drh_page_after_login' => 'Platform',
899
            'sessionadmin_page_after_login' => 'Session',
900
            'student_autosubscribe' => 'Platform',
901
            'teacher_autosubscribe' => 'Platform',
902
            'drh_autosubscribe' => 'Platform',
903
            'sessionadmin_autosubscribe' => 'Session',
904
            'scorm_cumulative_session_time' => 'Course',
905
            'allow_hr_skills_management' => 'Gradebook',
906
            'enable_help_link' => 'Platform',
907
            'teachers_can_change_score_settings' => 'Gradebook',
908
            'allow_users_to_change_email_with_no_password' => 'User',
909
            'show_admin_toolbar' => 'display',
910
            'allow_global_chat' => 'Platform',
911
            'languagePriority1' => 'language',
912
            'languagePriority2' => 'language',
913
            'languagePriority3' => 'language',
914
            'languagePriority4' => 'language',
915
            'login_is_email' => 'Platform',
916
            'courses_default_creation_visibility' => 'Course',
917
            'gradebook_enable_grade_model' => 'Gradebook',
918
            'teachers_can_change_grade_model_settings' => 'Gradebook',
919
            'gradebook_default_weight' => 'Gradebook',
920
            'ldap_description' => 'LDAP',
921
            'shibboleth_description' => 'Shibboleth',
922
            'facebook_description' => 'Facebook',
923
            'gradebook_locking_enabled' => 'Gradebook',
924
            'gradebook_default_grade_model_id' => 'Gradebook',
925
            'allow_session_admins_to_manage_all_sessions' => 'Session',
926
            'allow_skills_tool' => 'Platform',
927
            'allow_public_certificates' => 'Course',
928
            'platform_unsubscribe_allowed' => 'Platform',
929
            'enable_iframe_inclusion' => 'Editor',
930
            'show_hot_courses' => 'Platform',
931
            'enable_webcam_clip' => 'Tools',
932
            'use_custom_pages' => 'Platform',
933
            'tool_visible_by_default_at_creation' => 'Tools',
934
            'prevent_session_admins_to_manage_all_users' => 'Session',
935
            'documents_default_visibility_defined_in_course' => 'Tools',
936
            'enabled_mathjax' => 'Editor',
937
            'meta_twitter_site' => 'Tracking',
938
            'meta_twitter_creator' => 'Tracking',
939
            'meta_title' => 'Tracking',
940
            'meta_description' => 'Tracking',
941
            'meta_image_path' => 'Tracking',
942
            'allow_teachers_to_create_sessions' => 'Session',
943
            'institution_address' => 'Platform',
944
            'chamilo_database_version' => 'null',
945
            'cron_remind_course_finished_activate' => 'Crons',
946
            'cron_remind_course_expiration_frequency' => 'Crons',
947
            'cron_remind_course_expiration_activate' => 'Crons',
948
            'allow_coach_feedback_exercises' => 'Session',
949
            'allow_my_files' => 'Platform',
950
            'ticket_allow_student_add' => 'Ticket',
951
            'ticket_send_warning_to_all_admins' => 'Ticket',
952
            'ticket_warn_admin_no_user_in_category' => 'Ticket',
953
            'ticket_allow_category_edition' => 'Ticket',
954
            'load_term_conditions_section' => 'Platform',
955
            'show_terms_if_profile_completed' => 'Profile',
956
            'hide_home_top_when_connected' => 'Platform',
957
            'hide_global_announcements_when_not_connected' => 'Platform',
958
            'course_creation_use_template' => 'Course',
959
            'allow_strength_pass_checker' => 'Security',
960
            'allow_captcha' => 'Security',
961
            'captcha_number_mistakes_to_block_account' => 'Security',
962
            'captcha_time_to_block' => 'Security',
963
            'drh_can_access_all_session_content' => 'Session',
964
            'display_groups_forum_in_general_tool' => 'Tools',
965
            'allow_tutors_to_assign_students_to_session' => 'Session',
966
            'allow_lp_return_link' => 'Course',
967
            'hide_scorm_export_link' => 'Course',
968
            'hide_scorm_copy_link' => 'Course',
969
            'hide_scorm_pdf_link' => 'Course',
970
            'session_days_before_coach_access' => 'Session',
971
            'session_days_after_coach_access' => 'Session',
972
            'pdf_logo_header' => 'Course',
973
            'order_user_list_by_official_code' => 'Platform',
974
            'email_alert_manager_on_new_quiz' => 'exercise',
975
            'show_official_code_exercise_result_list' => 'Tools',
976
            'auto_detect_language_custom_pages' => 'Platform',
977
            'lp_show_reduced_report' => 'Course',
978
            'allow_session_course_copy_for_teachers' => 'Session',
979
            'hide_logout_button' => 'Platform',
980
            'redirect_admin_to_courses_list' => 'Platform',
981
            'course_images_in_courses_list' => 'Course',
982
            'student_publication_to_take_in_gradebook' => 'Gradebook',
983
            'certificate_filter_by_official_code' => 'Gradebook',
984
            'exercise_max_ckeditors_in_page' => 'Tools',
985
            'document_if_file_exists_option' => 'Tools',
986
            'add_gradebook_certificates_cron_task_enabled' => 'Gradebook',
987
            'openbadges_backpack' => 'Gradebook',
988
            'cookie_warning' => 'Tools',
989
            'hide_course_group_if_no_tools_available' => 'Tools',
990
            'registration.soap.php.decode_utf8' => 'Platform',
991
            'allow_delete_attendance' => 'Tools',
992
            'gravatar_enabled' => 'Platform',
993
            'gravatar_type' => 'Platform',
994
            'limit_session_admin_role' => 'Session',
995
            'show_session_description' => 'Session',
996
            'hide_certificate_export_link_students' => 'Gradebook',
997
            'hide_certificate_export_link' => 'Gradebook',
998
            'dropbox_hide_course_coach' => 'Tools',
999
            'dropbox_hide_general_coach' => 'Tools',
1000
            'session_course_ordering' => 'Session',
1001
            'gamification_mode' => 'Platform',
1002
            'prevent_multiple_simultaneous_login' => 'Security',
1003
            'gradebook_detailed_admin_view' => 'Gradebook',
1004
            'user_reset_password' => 'Security',
1005
            'user_reset_password_token_limit' => 'Security',
1006
            'my_courses_view_by_session' => 'Session',
1007
            'show_full_skill_name_on_skill_wheel' => 'Platform',
1008
            'messaging_allow_send_push_notification' => 'WebServices',
1009
            'messaging_gdc_project_number' => 'WebServices',
1010
            'messaging_gdc_api_key' => 'WebServices',
1011
            'teacher_can_select_course_template' => 'Course',
1012
            'allow_show_skype_account' => 'Platform',
1013
            'allow_show_linkedin_url' => 'Platform',
1014
            'enable_profile_user_address_geolocalization' => 'User',
1015
            'show_official_code_whoisonline' => 'Profile',
1016
            'icons_mode_svg' => 'display',
1017
            'default_calendar_view' => 'agenda',
1018
            'exercise_invisible_in_session' => 'exercise',
1019
            'configure_exercise_visibility_in_course' => 'exercise',
1020
            'allow_download_documents_by_api_key' => 'Webservices',
1021
            'profiling_filter_adding_users' => 'course',
1022
            'donotlistcampus' => 'platform',
1023
            'course_creation_splash_screen' => 'Course',
1024
            'translate_html' => 'Editor',
1025
        ];
1026
    }
1027
1028
    /**
1029
     * Rename old variable with variable used in Chamilo 2.0.
1030
     *
1031
     * @param string $variable
1032
     */
1033
    private function renameVariable($variable)
1034
    {
1035
        $list = [
1036
            'timezone_value' => 'timezone',
1037
            'Institution' => 'institution',
1038
            'SiteName' => 'site_name',
1039
            'siteName' => 'site_name',
1040
            'InstitutionUrl' => 'institution_url',
1041
            'registration' => 'required_profile_fields',
1042
            'platformLanguage' => 'platform_language',
1043
            'languagePriority1' => 'language_priority_1',
1044
            'languagePriority2' => 'language_priority_2',
1045
            'languagePriority3' => 'language_priority_3',
1046
            'languagePriority4' => 'language_priority_4',
1047
            'gradebook_score_display_coloring' => 'my_display_coloring',
1048
            'ProfilingFilterAddingUsers' => 'profiling_filter_adding_users',
1049
            'course_create_active_tools' => 'active_tools_on_create',
1050
            'emailAdministrator' => 'administrator_email',
1051
            'administratorSurname' => 'administrator_surname',
1052
            'administratorName' => 'administrator_name',
1053
            'administratorTelephone' => 'administrator_phone',
1054
            'registration.soap.php.decode_utf8' => 'decode_utf8',
1055
            'profile' => 'changeable_options',
1056
        ];
1057
1058
        return $list[$variable] ?? $variable;
1059
    }
1060
1061
    /**
1062
     * Replace old Chamilo 1.x category with 2.0 version.
1063
     *
1064
     * @param string $variable
1065
     * @param string $defaultCategory
1066
     */
1067
    private function fixCategory($variable, $defaultCategory)
1068
    {
1069
        $settings = [
1070
            'cookie_warning' => 'platform',
1071
            'donotlistcampus' => 'platform',
1072
            'administrator_email' => 'admin',
1073
            'administrator_surname' => 'admin',
1074
            'administrator_name' => 'admin',
1075
            'administrator_phone' => 'admin',
1076
            'exercise_max_ckeditors_in_page' => 'exercise',
1077
            'allow_hr_skills_management' => 'skill',
1078
            'accessibility_font_resize' => 'display',
1079
            'account_valid_duration' => 'profile',
1080
            'allow_global_chat' => 'chat',
1081
            'allow_lostpassword' => 'registration',
1082
            'allow_registration' => 'registration',
1083
            'allow_registration_as_teacher' => 'registration',
1084
            'required_profile_fields' => 'registration',
1085
            'allow_skills_tool' => 'skill',
1086
            'allow_terms_conditions' => 'registration',
1087
            'allow_users_to_create_courses' => 'course',
1088
            'auto_detect_language_custom_pages' => 'language',
1089
            'platform_language' => 'language',
1090
            'course_validation' => 'course',
1091
            'course_validation_terms_and_conditions_url' => 'course',
1092
            'display_categories_on_homepage' => 'display',
1093
            'display_coursecode_in_courselist' => 'course',
1094
            'display_teacher_in_courselist' => 'course',
1095
            'drh_autosubscribe' => 'registration',
1096
            'drh_page_after_login' => 'registration',
1097
            'enable_help_link' => 'display',
1098
            'example_material_course_creation' => 'course',
1099
            'login_is_email' => 'profile',
1100
            'noreply_email_address' => 'mail',
1101
            'pdf_export_watermark_by_course' => 'document',
1102
            'pdf_export_watermark_enable' => 'document',
1103
            'pdf_export_watermark_text' => 'document',
1104
            'platform_unsubscribe_allowed' => 'registration',
1105
            'send_email_to_admin_when_create_course' => 'course',
1106
            'show_admin_toolbar' => 'display',
1107
            'show_administrator_data' => 'display',
1108
            'show_back_link_on_top_of_tree' => 'display',
1109
            'show_closed_courses' => 'display',
1110
            'show_different_course_language' => 'display',
1111
            'show_email_addresses' => 'display',
1112
            'show_empty_course_categories' => 'display',
1113
            'show_full_skill_name_on_skill_wheel' => 'skill',
1114
            'show_hot_courses' => 'display',
1115
            'show_link_bug_notification' => 'display',
1116
            'show_number_of_courses' => 'display',
1117
            'show_teacher_data' => 'display',
1118
            'showonline' => 'display',
1119
            'student_autosubscribe' => 'registration',
1120
            'student_page_after_login' => 'registration',
1121
            'student_view_enabled' => 'course',
1122
            'teacher_autosubscribe' => 'registration',
1123
            'teacher_page_after_login' => 'registration',
1124
            'time_limit_whosonline' => 'display',
1125
            'user_selected_theme' => 'profile',
1126
            'hide_global_announcements_when_not_connected' => 'announcement',
1127
            'hide_home_top_when_connected' => 'display',
1128
            'hide_logout_button' => 'display',
1129
            'institution_address' => 'platform',
1130
            'redirect_admin_to_courses_list' => 'admin',
1131
            'use_custom_pages' => 'platform',
1132
            'allow_group_categories' => 'group',
1133
            'allow_user_headings' => 'display',
1134
            'default_document_quotum' => 'document',
1135
            'default_forum_view' => 'forum',
1136
            'default_group_quotum' => 'document',
1137
            'enable_quiz_scenario' => 'exercise',
1138
            'exercise_max_score' => 'exercise',
1139
            'exercise_min_score' => 'exercise',
1140
            'pdf_logo_header' => 'platform',
1141
            'show_glossary_in_documents' => 'document',
1142
            'show_glossary_in_extra_tools' => 'glossary',
1143
            'survey_email_sender_noreply' => 'survey',
1144
            'allow_coach_feedback_exercises' => 'exercise',
1145
            'sessionadmin_autosubscribe' => 'registration',
1146
            'sessionadmin_page_after_login' => 'registration',
1147
            'show_tutor_data' => 'display',
1148
            'allow_social_tool' => 'social',
1149
            'allow_message_tool' => 'message',
1150
            'allow_email_editor' => 'editor',
1151
            'show_link_ticket_notification' => 'display',
1152
            'permissions_for_new_directories' => 'document',
1153
            'enable_profile_user_address_geolocalization' => 'profile',
1154
            'allow_show_skype_account' => 'profile',
1155
            'allow_show_linkedin_url' => 'profile',
1156
            'allow_students_to_create_groups_in_social' => 'social',
1157
            'default_calendar_view' => 'agenda',
1158
            'documents_default_visibility_defined_in_course' => 'document',
1159
            'message_max_upload_filesize' => 'message',
1160
            'course_create_active_tools' => 'course',
1161
            'tool_visible_by_default_at_creation' => 'document',
1162
            'show_users_folders' => 'document',
1163
            'show_default_folders' => 'document',
1164
            'show_chat_folder' => 'chat',
1165
            'enabled_support_svg' => 'editor',
1166
            'enable_webcam_clip' => 'document',
1167
            'permanently_remove_deleted_files' => 'document',
1168
            'allow_delete_attendance' => 'attendance',
1169
            'display_groups_forum_in_general_tool' => 'forum',
1170
            'dropbox_allow_overwrite' => 'dropbox',
1171
            'allow_user_course_subscription_by_course_admin' => 'course',
1172
            'hide_course_group_if_no_tools_available' => 'group',
1173
            'extend_rights_for_coach_on_survey' => 'survey',
1174
            'show_official_code_exercise_result_list' => 'exercise',
1175
            'dropbox_max_filesize' => 'dropbox',
1176
            'dropbox_allow_just_upload' => 'dropbox',
1177
            'dropbox_allow_student_to_student' => 'dropbox',
1178
            'dropbox_allow_group' => 'dropbox',
1179
            'dropbox_allow_mailing' => 'dropbox',
1180
            'upload_extensions_list_type' => 'document',
1181
            'upload_extensions_blacklist' => 'document',
1182
            'upload_extensions_skip' => 'document',
1183
            'changeable_options' => 'profile',
1184
            'users_copy_files' => 'document',
1185
            'document_if_file_exists_option' => 'document',
1186
            'permissions_for_new_files' => 'document',
1187
            'extended_profile' => 'profile',
1188
            'split_users_upload_directory' => 'profile',
1189
            'show_documents_preview' => 'document',
1190
            'messaging_allow_send_push_notification' => 'webservice',
1191
            'messaging_gdc_project_number' => 'webservice',
1192
            'messaging_gdc_api_key' => 'webservice',
1193
            'allow_download_documents_by_api_key' => 'webservice',
1194
            'profiling_filter_adding_users' => 'course',
1195
            'active_tools_on_create' => 'course',
1196
        ];
1197
1198
        return $settings[$variable] ?? $defaultCategory;
1199
    }
1200
1201
    private function transformToString($value): string
1202
    {
1203
        if (\is_array($value)) {
1204
            return implode(',', $value);
1205
        }
1206
1207
        if ($value instanceof Course) {
1208
            return (string) $value->getId();
1209
        }
1210
1211
        if (\is_bool($value)) {
1212
            return $value ? 'true' : 'false';
1213
        }
1214
1215
        if (null === $value) {
1216
            return '';
1217
        }
1218
1219
        return (string) $value;
1220
    }
1221
1222
    private function normalizeNullsBeforeResolve(array $parameters, SettingsBuilder $settingsBuilder): array
1223
    {
1224
        foreach ($parameters as $k => $v) {
1225
            if (null === $v && $settingsBuilder->isDefined($k)) {
1226
                unset($parameters[$k]);
1227
            }
1228
        }
1229
1230
        return $parameters;
1231
    }
1232
}
1233