Passed
Pull Request — master (#6623)
by
unknown
12:05 queued 02:42
created

SettingsManager::normalizeNullsBeforeResolve()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 4
c 1
b 0
f 0
nc 3
nop 2
dl 0
loc 8
rs 10
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 Doctrine\ORM\EntityManager;
14
use Doctrine\ORM\EntityRepository;
15
use InvalidArgumentException;
16
use Sylius\Bundle\SettingsBundle\Manager\SettingsManagerInterface;
17
use Sylius\Bundle\SettingsBundle\Model\Settings;
18
use Sylius\Bundle\SettingsBundle\Model\SettingsInterface;
19
use Sylius\Bundle\SettingsBundle\Registry\ServiceRegistryInterface;
20
use Sylius\Bundle\SettingsBundle\Schema\SchemaInterface;
21
use Sylius\Bundle\SettingsBundle\Schema\SettingsBuilder;
22
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
23
use Symfony\Component\HttpFoundation\RequestStack;
24
use Symfony\Component\Validator\Exception\ValidatorException;
25
26
use const ARRAY_FILTER_USE_KEY;
27
28
/**
29
 * Handles the platform settings.
30
 */
31
class SettingsManager implements SettingsManagerInterface
32
{
33
    protected ?AccessUrl $url = null;
34
35
    protected ServiceRegistryInterface $schemaRegistry;
36
37
    protected EntityManager $manager;
38
39
    protected EntityRepository $repository;
40
41
    protected EventDispatcherInterface $eventDispatcher;
42
43
    /**
44
     * Runtime cache for resolved parameters.
45
     *
46
     * @var Settings[]
47
     */
48
    protected array $resolvedSettings = [];
49
50
    /**
51
     * @var null|array<string, Settings>|mixed[]
52
     */
53
    protected ?array $schemaList;
54
55
    protected RequestStack $request;
56
57
    public function __construct(
58
        ServiceRegistryInterface $schemaRegistry,
59
        EntityManager $manager,
60
        EntityRepository $repository,
61
        EventDispatcherInterface $eventDispatcher,
62
        RequestStack $request,
63
        protected readonly SettingsManagerHelper $settingsManagerHelper,
64
    ) {
65
        $this->schemaRegistry = $schemaRegistry;
66
        $this->manager = $manager;
67
        $this->repository = $repository;
68
        $this->eventDispatcher = $eventDispatcher;
69
        $this->request = $request;
70
        $this->schemaList = [];
71
    }
72
73
    public function getUrl(): ?AccessUrl
74
    {
75
        return $this->url;
76
    }
77
78
    public function setUrl(AccessUrl $url): void
79
    {
80
        $this->url = $url;
81
    }
82
83
    public function updateSchemas(AccessUrl $url): void
84
    {
85
        $this->url = $url;
86
        $schemas = array_keys($this->getSchemas());
87
        foreach ($schemas as $schema) {
88
            $settings = $this->load($this->convertServiceToNameSpace($schema));
89
            $this->update($settings);
90
        }
91
    }
92
93
    public function installSchemas(AccessUrl $url): void
94
    {
95
        $this->url = $url;
96
        $schemas = array_keys($this->getSchemas());
97
        foreach ($schemas as $schema) {
98
            $settings = $this->load($this->convertServiceToNameSpace($schema));
99
            $this->save($settings);
100
        }
101
    }
102
103
    /**
104
     * @return array|AbstractSettingsSchema[]
105
     */
106
    public function getSchemas(): array
107
    {
108
        return $this->schemaRegistry->all();
109
    }
110
111
    public function convertNameSpaceToService(string $category): string
112
    {
113
        return 'chamilo_core.settings.'.$category;
114
    }
115
116
    public function convertServiceToNameSpace(string $category): string
117
    {
118
        return str_replace('chamilo_core.settings.', '', $category);
119
    }
120
121
    public function updateSetting(string $name, $value): void
122
    {
123
        $name = $this->validateSetting($name);
124
125
        [$category, $name] = explode('.', $name);
126
        $settings = $this->load($category);
127
128
        if (!$settings->has($name)) {
129
            $message = \sprintf("Parameter %s doesn't exists.", $name);
130
131
            throw new InvalidArgumentException($message);
132
        }
133
134
        $settings->set($name, $value);
135
        $this->update($settings);
136
    }
137
138
    /**
139
     * Get a specific configuration setting, getting from the previously stored
140
     * PHP session data whenever possible.
141
     *
142
     * @param string $name       The setting name (composed if in a category, i.e. 'platform.institution')
143
     * @param bool   $loadFromDb Whether to load from the database
144
     */
145
    public function getSetting(string $name, bool $loadFromDb = false): mixed
146
    {
147
        $name = $this->validateSetting($name);
148
149
        $overridden = $this->settingsManagerHelper->getOverride($name);
150
151
        if (null !== $overridden) {
152
            return $overridden;
153
        }
154
155
        [$category, $name] = explode('.', $name);
156
157
        if ($loadFromDb) {
158
            $settings = $this->load($category, $name);
159
            if ($settings->has($name)) {
160
                return $settings->get($name);
161
            }
162
163
            return null;
164
        }
165
166
        $this->loadAll();
167
168
        if (!empty($this->schemaList) && isset($this->schemaList[$category])) {
169
            $settings = $this->schemaList[$category];
170
            if ($settings->has($name)) {
171
                return $settings->get($name);
172
            }
173
            error_log("Attempted to access undefined setting '$name' in category '$category'.");
174
175
            return null;
176
        }
177
178
        throw new InvalidArgumentException(\sprintf('Category %s not found', $category));
179
    }
180
181
    public function loadAll(): void
182
    {
183
        $session = null;
184
185
        if ($this->request->getCurrentRequest()) {
186
            $session = $this->request->getCurrentRequest()->getSession();
187
            $schemaList = $session->get('schemas');
188
            if (!empty($schemaList)) {
189
                $this->schemaList = $schemaList;
190
191
                return;
192
            }
193
        }
194
195
        $schemas = array_keys($this->getSchemas());
196
        $schemaList = [];
197
        $settingsBuilder = new SettingsBuilder();
198
        $all = $this->getAllParametersByCategory();
199
200
        foreach ($schemas as $schema) {
201
            $schemaRegister = $this->schemaRegistry->get($schema);
202
            $schemaRegister->buildSettings($settingsBuilder);
203
            $name = $this->convertServiceToNameSpace($schema);
204
            $settings = new Settings();
205
206
            /** @var array<string, mixed> $parameters */
207
            $parameters = $all[$name] ?? [];
208
209
            $knownParameters = array_filter(
210
                $parameters,
211
                fn ($key): bool => $settingsBuilder->isDefined($key),
212
                ARRAY_FILTER_USE_KEY
213
            );
214
215
            $transformers = $settingsBuilder->getTransformers();
216
            foreach ($transformers as $parameter => $transformer) {
217
                if (\array_key_exists($parameter, $knownParameters)) {
218
                    if ('course_creation_use_template' === $parameter) {
219
                        if (empty($knownParameters[$parameter])) {
220
                            $knownParameters[$parameter] = null;
221
                        }
222
                    } else {
223
                        $knownParameters[$parameter] = $transformer->reverseTransform($knownParameters[$parameter]);
224
                    }
225
                }
226
            }
227
228
            $knownParameters = $this->normalizeNullsBeforeResolve($knownParameters, $settingsBuilder);
229
            $parameters = $settingsBuilder->resolve($knownParameters);
230
            $settings->setParameters($parameters);
231
            $schemaList[$name] = $settings;
232
        }
233
        $this->schemaList = $schemaList;
234
        if ($session && $this->request->getCurrentRequest()) {
235
            $session->set('schemas', $schemaList);
236
        }
237
    }
238
239
    public function load(string $schemaAlias, ?string $namespace = null, bool $ignoreUnknown = true): SettingsInterface
240
    {
241
        $settings = new Settings();
242
        $schemaAliasNoPrefix = $schemaAlias;
243
        $schemaAlias = 'chamilo_core.settings.'.$schemaAlias;
244
        if ($this->schemaRegistry->has($schemaAlias)) {
245
            /** @var SchemaInterface $schema */
246
            $schema = $this->schemaRegistry->get($schemaAlias);
247
        } else {
248
            return $settings;
249
        }
250
251
        $settings->setSchemaAlias($schemaAlias);
252
253
        // We need to get a plain parameters array since we use the options resolver on it
254
        $parameters = $this->getParameters($schemaAliasNoPrefix);
255
        $settingsBuilder = new SettingsBuilder();
256
        $schema->buildSettings($settingsBuilder);
257
258
        // Remove unknown settings' parameters (e.g. From a previous version of the settings schema)
259
        if (true === $ignoreUnknown) {
260
            foreach ($parameters as $name => $value) {
261
                if (!$settingsBuilder->isDefined($name)) {
262
                    unset($parameters[$name]);
263
                }
264
            }
265
        }
266
267
        foreach ($settingsBuilder->getTransformers() as $parameter => $transformer) {
268
            if (\array_key_exists($parameter, $parameters)) {
269
                $parameters[$parameter] = $transformer->reverseTransform($parameters[$parameter]);
270
            }
271
        }
272
        $parameters = $this->normalizeNullsBeforeResolve($parameters, $settingsBuilder);
273
        $parameters = $settingsBuilder->resolve($parameters);
274
        $settings->setParameters($parameters);
275
276
        return $settings;
277
    }
278
279
    public function update(SettingsInterface $settings): void
280
    {
281
        $namespace = $settings->getSchemaAlias();
282
283
        /** @var SchemaInterface $schema */
284
        $schema = $this->schemaRegistry->get($settings->getSchemaAlias());
285
286
        $settingsBuilder = new SettingsBuilder();
287
        $schema->buildSettings($settingsBuilder);
288
        $raw = $settings->getParameters();
289
        $raw = $this->normalizeNullsBeforeResolve($raw, $settingsBuilder);
290
        $parameters = $settingsBuilder->resolve($raw);
291
        // Transform value. Example array to string using transformer. Example:
292
        // 1. Setting "tool_visible_by_default_at_creation" it's a multiple select
293
        // 2. Is defined as an array in class DocumentSettingsSchema
294
        // 3. Add transformer for that variable "ArrayToIdentifierTransformer"
295
        // 4. Here we recover the transformer and convert the array to string
296
        foreach ($parameters as $parameter => $value) {
297
            $parameters[$parameter] = $this->transformToString($value);
298
        }
299
300
        $settings->setParameters($parameters);
301
        $category = $this->convertServiceToNameSpace($settings->getSchemaAlias());
302
        $persistedParameters = $this->repository->findBy([
303
            'category' => $category,
304
        ]);
305
306
        $persistedParametersMap = [];
307
308
        /** @var SettingsCurrent $parameter */
309
        foreach ($persistedParameters as $parameter) {
310
            $persistedParametersMap[$parameter->getVariable()] = $parameter;
311
        }
312
313
        $url = $this->getUrl();
314
        $simpleCategoryName = str_replace('chamilo_core.settings.', '', $namespace);
315
316
        foreach ($parameters as $name => $value) {
317
            if (isset($persistedParametersMap[$name])) {
318
                $parameter = $persistedParametersMap[$name];
319
                $parameter->setSelectedValue($value);
320
                $parameter->setCategory($simpleCategoryName);
321
                $this->manager->persist($parameter);
322
            } else {
323
                $parameter = (new SettingsCurrent())
324
                    ->setVariable($name)
325
                    ->setCategory($simpleCategoryName)
326
                    ->setTitle($name)
327
                    ->setSelectedValue($value)
328
                    ->setUrl($url)
329
                    ->setAccessUrlChangeable(1)
330
                    ->setAccessUrlLocked(1)
331
                ;
332
333
                $this->manager->persist($parameter);
334
            }
335
        }
336
337
        $this->manager->flush();
338
    }
339
340
    /**
341
     * @throws ValidatorException
342
     */
343
    public function save(SettingsInterface $settings): void
344
    {
345
        $namespace = $settings->getSchemaAlias();
346
347
        /** @var SchemaInterface $schema */
348
        $schema = $this->schemaRegistry->get($settings->getSchemaAlias());
349
350
        $settingsBuilder = new SettingsBuilder();
351
        $schema->buildSettings($settingsBuilder);
352
        $raw = $settings->getParameters();
353
        $raw = $this->normalizeNullsBeforeResolve($raw, $settingsBuilder);
354
        $parameters = $settingsBuilder->resolve($raw);
355
        // Transform value. Example array to string using transformer. Example:
356
        // 1. Setting "tool_visible_by_default_at_creation" it's a multiple select
357
        // 2. Is defined as an array in class DocumentSettingsSchema
358
        // 3. Add transformer for that variable "ArrayToIdentifierTransformer"
359
        // 4. Here we recover the transformer and convert the array to string
360
        foreach ($parameters as $parameter => $value) {
361
            $parameters[$parameter] = $this->transformToString($value);
362
        }
363
        $settings->setParameters($parameters);
364
        $persistedParameters = $this->repository->findBy([
365
            'category' => $this->convertServiceToNameSpace($settings->getSchemaAlias()),
366
        ]);
367
        $persistedParametersMap = [];
368
        foreach ($persistedParameters as $parameter) {
369
            $persistedParametersMap[$parameter->getVariable()] = $parameter;
370
        }
371
372
        $url = $this->getUrl();
373
        $simpleCategoryName = str_replace('chamilo_core.settings.', '', $namespace);
374
375
        foreach ($parameters as $name => $value) {
376
            if (isset($persistedParametersMap[$name])) {
377
                $parameter = $persistedParametersMap[$name];
378
                $parameter->setSelectedValue($value);
379
            } else {
380
                $parameter = (new SettingsCurrent())
381
                    ->setVariable($name)
382
                    ->setCategory($simpleCategoryName)
383
                    ->setTitle($name)
384
                    ->setSelectedValue($value)
385
                    ->setUrl($url)
386
                    ->setAccessUrlChangeable(1)
387
                    ->setAccessUrlLocked(1)
388
                ;
389
390
                $this->manager->persist($parameter);
391
            }
392
        }
393
394
        $this->manager->flush();
395
    }
396
397
    /**
398
     * @param string $keyword
399
     */
400
    public function getParametersFromKeywordOrderedByCategory($keyword): array
401
    {
402
        $query = $this->repository->createQueryBuilder('s')
403
            ->where('s.variable LIKE :keyword OR s.title LIKE :keyword')
404
            ->setParameter('keyword', "%{$keyword}%")
405
        ;
406
        $parametersFromDb = $query->getQuery()->getResult();
407
        $parameters = [];
408
409
        foreach ($parametersFromDb as $parameter) {
410
            /** @var SettingsCurrent $parameter */
411
            $category = $parameter->getCategory();
412
            $variable = $parameter->getVariable();
413
414
            $hidden = [];
415
            $serviceKey = 'chamilo_core.settings.'.$category;
416
            if ($this->schemaRegistry->has($serviceKey)) {
417
                $schema = $this->schemaRegistry->get($serviceKey);
418
                if (method_exists($schema, 'getHiddenSettings')) {
419
                    $hidden = $schema->getHiddenSettings();
420
                }
421
            }
422
423
            if (\in_array($variable, $hidden, true)) {
424
                continue;
425
            }
426
427
            $parameters[$category][] = $parameter;
428
        }
429
430
        return $parameters;
431
    }
432
433
    /**
434
     * @param string $namespace
435
     * @param string $keyword
436
     * @param bool   $returnObjects
437
     *
438
     * @return array
439
     */
440
    public function getParametersFromKeyword($namespace, $keyword = '', $returnObjects = false)
441
    {
442
        if (empty($keyword)) {
443
            $criteria = [
444
                'category' => $namespace,
445
            ];
446
            $parametersFromDb = $this->repository->findBy($criteria);
447
        } else {
448
            $query = $this->repository->createQueryBuilder('s')
449
                ->where('s.variable LIKE :keyword')
450
                ->setParameter('keyword', "%{$keyword}%")
451
            ;
452
            $parametersFromDb = $query->getQuery()->getResult();
453
        }
454
455
        if ($returnObjects) {
456
            return $parametersFromDb;
457
        }
458
        $parameters = [];
459
460
        /** @var SettingsCurrent $parameter */
461
        foreach ($parametersFromDb as $parameter) {
462
            $parameters[$parameter->getVariable()] = $parameter->getSelectedValue();
463
        }
464
465
        return $parameters;
466
    }
467
468
    private function validateSetting(string $name): string
469
    {
470
        if (!str_contains($name, '.')) {
471
            // throw new \InvalidArgumentException(sprintf('Parameter must be in format "namespace.name", "%s" given.', $name));
472
473
            // This code allows the possibility of calling
474
            // api_get_setting('allow_skills_tool') instead of
475
            // the "correct" way api_get_setting('platform.allow_skills_tool')
476
            $items = $this->getVariablesAndCategories();
477
478
            if (isset($items[$name])) {
479
                $originalName = $name;
480
                $name = $this->renameVariable($name);
481
                $category = $this->fixCategory(
482
                    strtolower($name),
483
                    strtolower($items[$originalName])
484
                );
485
                $name = $category.'.'.$name;
486
            } else {
487
                $message = \sprintf('Parameter must be in format "category.name", "%s" given.', $name);
488
489
                throw new InvalidArgumentException($message);
490
            }
491
        }
492
493
        return $name;
494
    }
495
496
    /**
497
     * Load parameter from database.
498
     *
499
     * @param string $namespace
500
     *
501
     * @return array
502
     */
503
    private function getParameters($namespace)
504
    {
505
        $parameters = [];
506
        $category = $this->repository->findBy(['category' => $namespace]);
507
508
        /** @var SettingsCurrent $parameter */
509
        foreach ($category as $parameter) {
510
            $parameters[$parameter->getVariable()] = $parameter->getSelectedValue();
511
        }
512
513
        return $parameters;
514
    }
515
516
    private function getAllParametersByCategory()
517
    {
518
        $parameters = [];
519
        $all = $this->repository->findAll();
520
521
        /** @var SettingsCurrent $parameter */
522
        foreach ($all as $parameter) {
523
            $parameters[$parameter->getCategory()][$parameter->getVariable()] = $parameter->getSelectedValue();
524
        }
525
526
        return $parameters;
527
    }
528
529
    /*private function transformParameters(SettingsBuilder $settingsBuilder, array $parameters)
530
     * {
531
     * $transformedParameters = $parameters;
532
     * foreach ($settingsBuilder->getTransformers() as $parameter => $transformer) {
533
     * if (array_key_exists($parameter, $parameters)) {
534
     * $transformedParameters[$parameter] = $transformer->reverseTransform($parameters[$parameter]);
535
     * }
536
     * }
537
     * return $transformedParameters;
538
     * }*/
539
540
    /**
541
     * Get variables and categories as in 1.11.x.
542
     */
543
    private function getVariablesAndCategories(): array
544
    {
545
        return [
546
            'Institution' => 'Platform',
547
            'InstitutionUrl' => 'Platform',
548
            'siteName' => 'Platform',
549
            'site_name' => 'Platform',
550
            'emailAdministrator' => 'admin',
551
            // 'emailAdministrator' => 'Platform',
552
            'administratorSurname' => 'admin',
553
            'administratorTelephone' => 'admin',
554
            'administratorName' => 'admin',
555
            'show_administrator_data' => 'Platform',
556
            'show_tutor_data' => 'Session',
557
            'show_teacher_data' => 'Platform',
558
            'show_toolshortcuts' => 'Course',
559
            'allow_group_categories' => 'Course',
560
            'server_type' => 'Platform',
561
            'platformLanguage' => 'Language',
562
            'showonline' => 'Platform',
563
            'profile' => 'User',
564
            'default_document_quotum' => 'Course',
565
            'registration' => 'User',
566
            'default_group_quotum' => 'Course',
567
            'allow_registration' => 'Platform',
568
            'allow_registration_as_teacher' => 'Platform',
569
            'allow_lostpassword' => 'Platform',
570
            'allow_user_headings' => 'Course',
571
            'allow_personal_agenda' => 'agenda',
572
            'display_coursecode_in_courselist' => 'Platform',
573
            'display_teacher_in_courselist' => 'Platform',
574
            'permanently_remove_deleted_files' => 'Tools',
575
            'dropbox_allow_overwrite' => 'Tools',
576
            'dropbox_max_filesize' => 'Tools',
577
            'dropbox_allow_just_upload' => 'Tools',
578
            'dropbox_allow_student_to_student' => 'Tools',
579
            'dropbox_allow_group' => 'Tools',
580
            'dropbox_allow_mailing' => 'Tools',
581
            'extended_profile' => 'User',
582
            'student_view_enabled' => 'Platform',
583
            'show_navigation_menu' => 'Course',
584
            'enable_tool_introduction' => 'course',
585
            'page_after_login' => 'Platform',
586
            'time_limit_whosonline' => 'Platform',
587
            'breadcrumbs_course_homepage' => 'Course',
588
            'example_material_course_creation' => 'Platform',
589
            'account_valid_duration' => 'Platform',
590
            'use_session_mode' => 'Session',
591
            'allow_email_editor' => 'Tools',
592
            // 'registered' => null',
593
            // 'donotlistcampus' =>'null',
594
            'show_email_addresses' => 'Platform',
595
            'service_ppt2lp' => 'NULL',
596
            'upload_extensions_list_type' => 'Security',
597
            'upload_extensions_blacklist' => 'Security',
598
            'upload_extensions_whitelist' => 'Security',
599
            'upload_extensions_skip' => 'Security',
600
            'upload_extensions_replace_by' => 'Security',
601
            'show_number_of_courses' => 'Platform',
602
            'show_empty_course_categories' => 'Platform',
603
            'show_back_link_on_top_of_tree' => 'Platform',
604
            'show_different_course_language' => 'Platform',
605
            'split_users_upload_directory' => 'Tuning',
606
            'hide_dltt_markup' => 'Languages',
607
            'display_categories_on_homepage' => 'Platform',
608
            'permissions_for_new_directories' => 'Security',
609
            'permissions_for_new_files' => 'Security',
610
            'show_tabs' => 'Platform',
611
            'default_forum_view' => 'Course',
612
            'platform_charset' => 'Languages',
613
            'survey_email_sender_noreply' => 'Course',
614
            'gradebook_enable' => 'Gradebook',
615
            'gradebook_score_display_coloring' => 'Gradebook',
616
            'gradebook_score_display_custom' => 'Gradebook',
617
            'gradebook_score_display_colorsplit' => 'Gradebook',
618
            'gradebook_score_display_upperlimit' => 'Gradebook',
619
            'gradebook_number_decimals' => 'Gradebook',
620
            'user_selected_theme' => 'Platform',
621
            'allow_course_theme' => 'Course',
622
            'show_closed_courses' => 'Platform',
623
            'extendedprofile_registration' => 'User',
624
            'extendedprofile_registrationrequired' => 'User',
625
            'add_users_by_coach' => 'Session',
626
            'extend_rights_for_coach' => 'Security',
627
            'extend_rights_for_coach_on_survey' => 'Security',
628
            'course_create_active_tools' => 'Tools',
629
            'show_session_coach' => 'Session',
630
            'allow_users_to_create_courses' => 'Platform',
631
            'allow_message_tool' => 'Tools',
632
            'allow_social_tool' => 'Tools',
633
            'show_session_data' => 'Session',
634
            'allow_use_sub_language' => 'language',
635
            'show_glossary_in_documents' => 'Course',
636
            'allow_terms_conditions' => 'Platform',
637
            'search_enabled' => 'Search',
638
            'search_prefilter_prefix' => 'Search',
639
            'search_show_unlinked_results' => 'Search',
640
            'allow_coach_to_edit_course_session' => 'Session',
641
            'show_glossary_in_extra_tools' => 'Course',
642
            'send_email_to_admin_when_create_course' => 'Platform',
643
            'go_to_course_after_login' => 'Course',
644
            'math_asciimathML' => 'Editor',
645
            'enabled_asciisvg' => 'Editor',
646
            'include_asciimathml_script' => 'Editor',
647
            'youtube_for_students' => 'Editor',
648
            'block_copy_paste_for_students' => 'Editor',
649
            'more_buttons_maximized_mode' => 'Editor',
650
            'students_download_folders' => 'Document',
651
            'users_copy_files' => 'Tools',
652
            'allow_students_to_create_groups_in_social' => 'Tools',
653
            'allow_send_message_to_all_platform_users' => 'Message',
654
            'message_max_upload_filesize' => 'Tools',
655
            'use_users_timezone' => 'profile',
656
            // 'use_users_timezone' => 'Timezones',
657
            'timezone_value' => 'platform',
658
            // 'timezone_value' => 'Timezones',
659
            'allow_user_course_subscription_by_course_admin' => 'Security',
660
            'show_link_bug_notification' => 'Platform',
661
            'show_link_ticket_notification' => 'Platform',
662
            'course_validation' => 'course',
663
            // 'course_validation' => 'Platform',
664
            'course_validation_terms_and_conditions_url' => 'Platform',
665
            'enabled_wiris' => 'Editor',
666
            'allow_spellcheck' => 'Editor',
667
            'force_wiki_paste_as_plain_text' => 'Editor',
668
            'enabled_googlemaps' => 'Editor',
669
            'enabled_imgmap' => 'Editor',
670
            'enabled_support_svg' => 'Tools',
671
            'pdf_export_watermark_enable' => 'Platform',
672
            'pdf_export_watermark_by_course' => 'Platform',
673
            'pdf_export_watermark_text' => 'Platform',
674
            'enabled_insertHtml' => 'Editor',
675
            'students_export2pdf' => 'Document',
676
            'exercise_min_score' => 'Course',
677
            'exercise_max_score' => 'Course',
678
            'show_users_folders' => 'Tools',
679
            'show_default_folders' => 'Tools',
680
            'show_chat_folder' => 'Tools',
681
            'course_hide_tools' => 'Course',
682
            'show_groups_to_users' => 'Session',
683
            'accessibility_font_resize' => 'Platform',
684
            'hide_courses_in_sessions' => 'Session',
685
            'enable_quiz_scenario' => 'Course',
686
            'filter_terms' => 'Security',
687
            'header_extra_content' => 'Tracking',
688
            'footer_extra_content' => 'Tracking',
689
            'show_documents_preview' => 'Tools',
690
            'htmlpurifier_wiki' => 'Editor',
691
            'cas_activate' => 'CAS',
692
            'cas_server' => 'CAS',
693
            'cas_server_uri' => 'CAS',
694
            'cas_port' => 'CAS',
695
            'cas_protocol' => 'CAS',
696
            'cas_add_user_activate' => 'CAS',
697
            'update_user_info_cas_with_ldap' => 'CAS',
698
            'student_page_after_login' => 'Platform',
699
            'teacher_page_after_login' => 'Platform',
700
            'drh_page_after_login' => 'Platform',
701
            'sessionadmin_page_after_login' => 'Session',
702
            'student_autosubscribe' => 'Platform',
703
            'teacher_autosubscribe' => 'Platform',
704
            'drh_autosubscribe' => 'Platform',
705
            'sessionadmin_autosubscribe' => 'Session',
706
            'scorm_cumulative_session_time' => 'Course',
707
            'allow_hr_skills_management' => 'Gradebook',
708
            'enable_help_link' => 'Platform',
709
            'teachers_can_change_score_settings' => 'Gradebook',
710
            'allow_users_to_change_email_with_no_password' => 'User',
711
            'show_admin_toolbar' => 'display',
712
            'allow_global_chat' => 'Platform',
713
            'languagePriority1' => 'language',
714
            'languagePriority2' => 'language',
715
            'languagePriority3' => 'language',
716
            'languagePriority4' => 'language',
717
            'login_is_email' => 'Platform',
718
            'courses_default_creation_visibility' => 'Course',
719
            'gradebook_enable_grade_model' => 'Gradebook',
720
            'teachers_can_change_grade_model_settings' => 'Gradebook',
721
            'gradebook_default_weight' => 'Gradebook',
722
            'ldap_description' => 'LDAP',
723
            'shibboleth_description' => 'Shibboleth',
724
            'facebook_description' => 'Facebook',
725
            'gradebook_locking_enabled' => 'Gradebook',
726
            'gradebook_default_grade_model_id' => 'Gradebook',
727
            'allow_session_admins_to_manage_all_sessions' => 'Session',
728
            'allow_skills_tool' => 'Platform',
729
            'allow_public_certificates' => 'Course',
730
            'platform_unsubscribe_allowed' => 'Platform',
731
            'enable_iframe_inclusion' => 'Editor',
732
            'show_hot_courses' => 'Platform',
733
            'enable_webcam_clip' => 'Tools',
734
            'use_custom_pages' => 'Platform',
735
            'tool_visible_by_default_at_creation' => 'Tools',
736
            'prevent_session_admins_to_manage_all_users' => 'Session',
737
            'documents_default_visibility_defined_in_course' => 'Tools',
738
            'enabled_mathjax' => 'Editor',
739
            'meta_twitter_site' => 'Tracking',
740
            'meta_twitter_creator' => 'Tracking',
741
            'meta_title' => 'Tracking',
742
            'meta_description' => 'Tracking',
743
            'meta_image_path' => 'Tracking',
744
            'allow_teachers_to_create_sessions' => 'Session',
745
            'institution_address' => 'Platform',
746
            'chamilo_database_version' => 'null',
747
            'cron_remind_course_finished_activate' => 'Crons',
748
            'cron_remind_course_expiration_frequency' => 'Crons',
749
            'cron_remind_course_expiration_activate' => 'Crons',
750
            'allow_coach_feedback_exercises' => 'Session',
751
            'allow_my_files' => 'Platform',
752
            'ticket_allow_student_add' => 'Ticket',
753
            'ticket_send_warning_to_all_admins' => 'Ticket',
754
            'ticket_warn_admin_no_user_in_category' => 'Ticket',
755
            'ticket_allow_category_edition' => 'Ticket',
756
            'load_term_conditions_section' => 'Platform',
757
            'show_terms_if_profile_completed' => 'Ticket',
758
            'hide_home_top_when_connected' => 'Platform',
759
            'hide_global_announcements_when_not_connected' => 'Platform',
760
            'course_creation_use_template' => 'Course',
761
            'allow_strength_pass_checker' => 'Security',
762
            'allow_captcha' => 'Security',
763
            'captcha_number_mistakes_to_block_account' => 'Security',
764
            'captcha_time_to_block' => 'Security',
765
            'drh_can_access_all_session_content' => 'Session',
766
            'display_groups_forum_in_general_tool' => 'Tools',
767
            'allow_tutors_to_assign_students_to_session' => 'Session',
768
            'allow_lp_return_link' => 'Course',
769
            'hide_scorm_export_link' => 'Course',
770
            'hide_scorm_copy_link' => 'Course',
771
            'hide_scorm_pdf_link' => 'Course',
772
            'session_days_before_coach_access' => 'Session',
773
            'session_days_after_coach_access' => 'Session',
774
            'pdf_logo_header' => 'Course',
775
            'order_user_list_by_official_code' => 'Platform',
776
            'email_alert_manager_on_new_quiz' => 'exercise',
777
            'show_official_code_exercise_result_list' => 'Tools',
778
            'auto_detect_language_custom_pages' => 'Platform',
779
            'lp_show_reduced_report' => 'Course',
780
            'allow_session_course_copy_for_teachers' => 'Session',
781
            'hide_logout_button' => 'Platform',
782
            'redirect_admin_to_courses_list' => 'Platform',
783
            'course_images_in_courses_list' => 'Course',
784
            'student_publication_to_take_in_gradebook' => 'Gradebook',
785
            'certificate_filter_by_official_code' => 'Gradebook',
786
            'exercise_max_ckeditors_in_page' => 'Tools',
787
            'document_if_file_exists_option' => 'Tools',
788
            'add_gradebook_certificates_cron_task_enabled' => 'Gradebook',
789
            'openbadges_backpack' => 'Gradebook',
790
            'cookie_warning' => 'Tools',
791
            'hide_course_group_if_no_tools_available' => 'Tools',
792
            'registration.soap.php.decode_utf8' => 'Platform',
793
            'allow_delete_attendance' => 'Tools',
794
            'gravatar_enabled' => 'Platform',
795
            'gravatar_type' => 'Platform',
796
            'limit_session_admin_role' => 'Session',
797
            'show_session_description' => 'Session',
798
            'hide_certificate_export_link_students' => 'Gradebook',
799
            'hide_certificate_export_link' => 'Gradebook',
800
            'dropbox_hide_course_coach' => 'Tools',
801
            'dropbox_hide_general_coach' => 'Tools',
802
            'session_course_ordering' => 'Session',
803
            'gamification_mode' => 'Platform',
804
            'prevent_multiple_simultaneous_login' => 'Security',
805
            'gradebook_detailed_admin_view' => 'Gradebook',
806
            'user_reset_password' => 'Security',
807
            'user_reset_password_token_limit' => 'Security',
808
            'my_courses_view_by_session' => 'Session',
809
            'show_full_skill_name_on_skill_wheel' => 'Platform',
810
            'messaging_allow_send_push_notification' => 'WebServices',
811
            'messaging_gdc_project_number' => 'WebServices',
812
            'messaging_gdc_api_key' => 'WebServices',
813
            'teacher_can_select_course_template' => 'Course',
814
            'allow_show_skype_account' => 'Platform',
815
            'allow_show_linkedin_url' => 'Platform',
816
            'enable_profile_user_address_geolocalization' => 'User',
817
            'show_official_code_whoisonline' => 'Profile',
818
            'icons_mode_svg' => 'display',
819
            'default_calendar_view' => 'agenda',
820
            'exercise_invisible_in_session' => 'exercise',
821
            'configure_exercise_visibility_in_course' => 'exercise',
822
            'allow_download_documents_by_api_key' => 'Webservices',
823
            'profiling_filter_adding_users' => 'profile',
824
            'donotlistcampus' => 'platform',
825
            'course_creation_splash_screen' => 'Course',
826
            'translate_html' => 'Editor',
827
            'enable_bootstrap_in_documents_html' => 'Course',
828
        ];
829
    }
830
831
    /**
832
     * Rename old variable with variable used in Chamilo 2.0.
833
     *
834
     * @param string $variable
835
     */
836
    private function renameVariable($variable)
837
    {
838
        $list = [
839
            'timezone_value' => 'timezone',
840
            'Institution' => 'institution',
841
            'SiteName' => 'site_name',
842
            'siteName' => 'site_name',
843
            'InstitutionUrl' => 'institution_url',
844
            'registration' => 'required_profile_fields',
845
            'platformLanguage' => 'platform_language',
846
            'languagePriority1' => 'language_priority_1',
847
            'languagePriority2' => 'language_priority_2',
848
            'languagePriority3' => 'language_priority_3',
849
            'languagePriority4' => 'language_priority_4',
850
            'gradebook_score_display_coloring' => 'my_display_coloring',
851
            'ProfilingFilterAddingUsers' => 'profiling_filter_adding_users',
852
            'course_create_active_tools' => 'active_tools_on_create',
853
            'emailAdministrator' => 'administrator_email',
854
            'administratorSurname' => 'administrator_surname',
855
            'administratorName' => 'administrator_name',
856
            'administratorTelephone' => 'administrator_phone',
857
            'registration.soap.php.decode_utf8' => 'decode_utf8',
858
            'profile' => 'changeable_options',
859
        ];
860
861
        return $list[$variable] ?? $variable;
862
    }
863
864
    /**
865
     * Replace old Chamilo 1.x category with 2.0 version.
866
     *
867
     * @param string $variable
868
     * @param string $defaultCategory
869
     */
870
    private function fixCategory($variable, $defaultCategory)
871
    {
872
        $settings = [
873
            'cookie_warning' => 'platform',
874
            'donotlistcampus' => 'platform',
875
            'administrator_email' => 'admin',
876
            'administrator_surname' => 'admin',
877
            'administrator_name' => 'admin',
878
            'administrator_phone' => 'admin',
879
            'exercise_max_ckeditors_in_page' => 'exercise',
880
            'allow_hr_skills_management' => 'skill',
881
            'accessibility_font_resize' => 'display',
882
            'account_valid_duration' => 'profile',
883
            'allow_global_chat' => 'chat',
884
            'allow_lostpassword' => 'registration',
885
            'allow_registration' => 'registration',
886
            'allow_registration_as_teacher' => 'registration',
887
            'required_profile_fields' => 'registration',
888
            'allow_skills_tool' => 'skill',
889
            'allow_terms_conditions' => 'registration',
890
            'allow_users_to_create_courses' => 'course',
891
            'auto_detect_language_custom_pages' => 'language',
892
            'platform_language' => 'language',
893
            'course_validation' => 'course',
894
            'course_validation_terms_and_conditions_url' => 'course',
895
            'display_categories_on_homepage' => 'display',
896
            'display_coursecode_in_courselist' => 'course',
897
            'display_teacher_in_courselist' => 'course',
898
            'drh_autosubscribe' => 'registration',
899
            'drh_page_after_login' => 'registration',
900
            'enable_help_link' => 'display',
901
            'example_material_course_creation' => 'course',
902
            'login_is_email' => 'profile',
903
            'noreply_email_address' => 'mail',
904
            'pdf_export_watermark_by_course' => 'document',
905
            'pdf_export_watermark_enable' => 'document',
906
            'pdf_export_watermark_text' => 'document',
907
            'platform_unsubscribe_allowed' => 'registration',
908
            'send_email_to_admin_when_create_course' => 'course',
909
            'show_admin_toolbar' => 'display',
910
            'show_administrator_data' => 'display',
911
            'show_back_link_on_top_of_tree' => 'display',
912
            'show_closed_courses' => 'display',
913
            'show_different_course_language' => 'display',
914
            'show_email_addresses' => 'display',
915
            'show_empty_course_categories' => 'display',
916
            'show_full_skill_name_on_skill_wheel' => 'skill',
917
            'show_hot_courses' => 'display',
918
            'show_link_bug_notification' => 'display',
919
            'show_number_of_courses' => 'display',
920
            'show_teacher_data' => 'display',
921
            'showonline' => 'display',
922
            'student_autosubscribe' => 'registration',
923
            'student_page_after_login' => 'registration',
924
            'student_view_enabled' => 'course',
925
            'teacher_autosubscribe' => 'registration',
926
            'teacher_page_after_login' => 'registration',
927
            'time_limit_whosonline' => 'display',
928
            'user_selected_theme' => 'profile',
929
            'hide_global_announcements_when_not_connected' => 'announcement',
930
            'hide_home_top_when_connected' => 'display',
931
            'hide_logout_button' => 'display',
932
            'institution_address' => 'platform',
933
            'redirect_admin_to_courses_list' => 'admin',
934
            'use_custom_pages' => 'platform',
935
            'allow_group_categories' => 'group',
936
            'allow_user_headings' => 'display',
937
            'default_document_quotum' => 'document',
938
            'default_forum_view' => 'forum',
939
            'default_group_quotum' => 'document',
940
            'enable_quiz_scenario' => 'exercise',
941
            'exercise_max_score' => 'exercise',
942
            'exercise_min_score' => 'exercise',
943
            'pdf_logo_header' => 'platform',
944
            'show_glossary_in_documents' => 'document',
945
            'show_glossary_in_extra_tools' => 'glossary',
946
            'survey_email_sender_noreply' => 'survey',
947
            'allow_coach_feedback_exercises' => 'exercise',
948
            'sessionadmin_autosubscribe' => 'registration',
949
            'sessionadmin_page_after_login' => 'registration',
950
            'show_tutor_data' => 'display',
951
            'allow_social_tool' => 'social',
952
            'allow_message_tool' => 'message',
953
            'allow_email_editor' => 'editor',
954
            'show_link_ticket_notification' => 'display',
955
            'permissions_for_new_directories' => 'document',
956
            'enable_profile_user_address_geolocalization' => 'profile',
957
            'allow_show_skype_account' => 'profile',
958
            'allow_show_linkedin_url' => 'profile',
959
            'allow_students_to_create_groups_in_social' => 'social',
960
            'default_calendar_view' => 'agenda',
961
            'documents_default_visibility_defined_in_course' => 'document',
962
            'message_max_upload_filesize' => 'message',
963
            'course_create_active_tools' => 'course',
964
            'tool_visible_by_default_at_creation' => 'document',
965
            'show_users_folders' => 'document',
966
            'show_default_folders' => 'document',
967
            'show_chat_folder' => 'chat',
968
            'enabled_support_svg' => 'editor',
969
            'enable_webcam_clip' => 'document',
970
            'permanently_remove_deleted_files' => 'document',
971
            'allow_delete_attendance' => 'attendance',
972
            'display_groups_forum_in_general_tool' => 'forum',
973
            'dropbox_allow_overwrite' => 'dropbox',
974
            'allow_user_course_subscription_by_course_admin' => 'course',
975
            'hide_course_group_if_no_tools_available' => 'group',
976
            'extend_rights_for_coach_on_survey' => 'survey',
977
            'show_official_code_exercise_result_list' => 'exercise',
978
            'dropbox_max_filesize' => 'dropbox',
979
            'dropbox_allow_just_upload' => 'dropbox',
980
            'dropbox_allow_student_to_student' => 'dropbox',
981
            'dropbox_allow_group' => 'dropbox',
982
            'dropbox_allow_mailing' => 'dropbox',
983
            'upload_extensions_list_type' => 'document',
984
            'upload_extensions_blacklist' => 'document',
985
            'upload_extensions_skip' => 'document',
986
            'changeable_options' => 'profile',
987
            'users_copy_files' => 'document',
988
            'document_if_file_exists_option' => 'document',
989
            'permissions_for_new_files' => 'document',
990
            'extended_profile' => 'profile',
991
            'split_users_upload_directory' => 'profile',
992
            'show_documents_preview' => 'document',
993
            'messaging_allow_send_push_notification' => 'webservice',
994
            'messaging_gdc_project_number' => 'webservice',
995
            'messaging_gdc_api_key' => 'webservice',
996
            'allow_download_documents_by_api_key' => 'webservice',
997
            'profiling_filter_adding_users' => 'profile',
998
            'hide_dltt_markup' => 'language',
999
            'active_tools_on_create' => 'course',
1000
        ];
1001
1002
        return $settings[$variable] ?? $defaultCategory;
1003
    }
1004
1005
    private function transformToString($value): string
1006
    {
1007
        if (\is_array($value)) {
1008
            return implode(',', $value);
1009
        }
1010
1011
        if ($value instanceof Course) {
1012
            return (string) $value->getId();
1013
        }
1014
1015
        if (\is_bool($value)) {
1016
            return $value ? 'true' : 'false';
1017
        }
1018
1019
        if (null === $value) {
1020
            return '';
1021
        }
1022
1023
        return (string) $value;
1024
    }
1025
1026
    private function normalizeNullsBeforeResolve(array $parameters, SettingsBuilder $settingsBuilder): array
1027
    {
1028
        foreach ($parameters as $k => $v) {
1029
            if ($v === null && $settingsBuilder->isDefined($k)) {
1030
                unset($parameters[$k]);
1031
            }
1032
        }
1033
        return $parameters;
1034
    }
1035
}
1036