Passed
Push — master ( 74fd5b...33a7b7 )
by
unknown
18:37 queued 09:15
created

IndexBlocksController::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 13
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
c 0
b 0
f 0
nc 1
nop 10
dl 0
loc 13
rs 10

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
declare(strict_types=1);
6
7
namespace Chamilo\CoreBundle\Controller\Admin;
8
9
use AppPlugin;
10
use Chamilo\CoreBundle\Controller\BaseController;
11
use Chamilo\CoreBundle\Entity\Page;
12
use Chamilo\CoreBundle\Entity\PageCategory;
13
use Chamilo\CoreBundle\Entity\SequenceResource;
14
use Chamilo\CoreBundle\Event\AbstractEvent;
15
use Chamilo\CoreBundle\Event\AdminBlockDisplayedEvent;
16
use Chamilo\CoreBundle\Event\Events;
17
use Chamilo\CoreBundle\Helpers\AccessUrlHelper;
18
use Chamilo\CoreBundle\Helpers\AuthenticationConfigHelper;
19
use Chamilo\CoreBundle\Repository\Node\AccessUrlRepository;
20
use Chamilo\CoreBundle\Repository\PageCategoryRepository;
21
use Chamilo\CoreBundle\Repository\PageRepository;
22
use Chamilo\CoreBundle\Repository\PluginRepository;
23
use Chamilo\CoreBundle\Settings\SettingsManager;
24
use Plugin;
25
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
26
use Symfony\Component\ExpressionLanguage\Expression;
27
use Symfony\Component\HttpFoundation\JsonResponse;
28
use Symfony\Component\Routing\Attribute\Route;
29
use Symfony\Component\Security\Http\Attribute\IsGranted;
30
use Symfony\Component\Serializer\SerializerInterface;
31
use Symfony\Contracts\Translation\TranslatorInterface;
32
use Throwable;
33
34
#[IsGranted(new Expression('is_granted("ROLE_ADMIN") or is_granted("ROLE_SESSION_MANAGER")'))]
35
#[Route('/admin/index', name: 'admin_index_blocks')]
36
class IndexBlocksController extends BaseController
37
{
38
    private bool $isAdmin = false;
39
    private bool $isSessionAdmin = false;
40
    private bool $isLdapActive;
41
42
    public function __construct(
43
        private readonly TranslatorInterface $translator,
44
        private readonly SettingsManager $settingsManager,
45
        private readonly PageRepository $pageRepository,
46
        private readonly PageCategoryRepository $pageCategoryRepository,
47
        private readonly SerializerInterface $serializer,
48
        private readonly EventDispatcherInterface $eventDispatcher,
49
        private readonly PluginRepository $pluginRepository,
50
        private readonly AccessUrlHelper $accessUrlHelper,
51
        private readonly AccessUrlRepository $accessUrlRepository,
52
        AuthenticationConfigHelper $authConfigHelper,
53
    ) {
54
        $this->isLdapActive = $authConfigHelper->getLdapConfig()['enabled'];
55
    }
56
57
    public function __invoke(): JsonResponse
58
    {
59
        $this->isAdmin = $this->isGranted('ROLE_ADMIN');
60
        $this->isSessionAdmin = $this->isGranted('ROLE_SESSION_MANAGER');
61
62
        $json = [];
63
64
        $adminBlockEvent = new AdminBlockDisplayedEvent($json, AbstractEvent::TYPE_PRE);
65
66
        $this->eventDispatcher->dispatch($adminBlockEvent, Events::ADMIN_BLOCK_DISPLAYED);
67
68
        $json = $adminBlockEvent->getData();
69
70
        $json['users'] = [
71
            'id' => 'block-admin-users',
72
            'searchUrl' => '/main/admin/user_list.php',
73
            'editable' => $this->isAdmin,
74
            'items' => $this->getItemsUsers(),
75
            'extraContent' => $this->getExtraContent('block-admin-users'),
76
        ];
77
78
        if ($this->isAdmin) {
79
            $json['courses'] = [
80
                'id' => 'block-admin-courses',
81
                'searchUrl' => '/main/admin/course_list.php',
82
                'editable' => true,
83
                'items' => $this->getItemsCourses(),
84
                'extraContent' => $this->getExtraContent('block-admin-courses'),
85
            ];
86
87
            $json['platform'] = [
88
                'id' => 'block-admin-platform',
89
                'searchUrl' => $this->generateUrl('chamilo_platform_settings_search'),
90
                'editable' => true,
91
                'items' => $this->getItemsPlatform(),
92
                'extraContent' => $this->getExtraContent('block-admin-platform'),
93
            ];
94
95
            /* Settings */
96
            $json['settings'] = [
97
                'id' => 'block-admin-settings',
98
                'editable' => false,
99
                'items' => $this->getItemsSettings(),
100
                'extraContent' => $this->getExtraContent('block-admin-settings'),
101
            ];
102
103
            // Skills
104
            if ('true' === $this->settingsManager->getSetting('skill.allow_skills_tool')) {
105
                $json['skills'] = [
106
                    'id' => 'block-admin-skills',
107
                    'editable' => false,
108
                    'items' => $this->getItemsSkills(),
109
                    'extraContent' => $this->getExtraContent('block-admin-skills'),
110
                ];
111
            }
112
113
            if ('true' === $this->settingsManager->getSetting('gradebook.gradebook_dependency')) {
114
                $json['gradebook'] = [
115
                    'id' => 'block-admin-gradebook',
116
                    'editable' => false,
117
                    'items' => $this->getItemsGradebook(),
118
                    'extraContent' => $this->getExtraContent('block-admin-gradebook'),
119
                ];
120
            }
121
122
            // Data protection
123
            if ('true' !== $this->settingsManager->getSetting('privacy.disable_gdpr')) {
124
                $json['data_privacy'] = [
125
                    'id' => 'block-admin-privacy',
126
                    'editable' => false,
127
                    'items' => $this->getItemsPrivacy(),
128
                    'extraContent' => $this->getExtraContent('block-admin-privacy'),
129
                ];
130
            }
131
132
            $json['security'] = [
133
                'id' => 'block-admin-security',
134
                'editable' => false,
135
                'items' => $this->getItemsSecurity(),
136
                'extraContent' => $this->getExtraContent('block-admin-security'),
137
            ];
138
139
            /* Chamilo.org */
140
            $json['chamilo'] = [
141
                'id' => 'block-admin-chamilo',
142
                'editable' => false,
143
                'items' => $this->getItemsChamilo(),
144
                'extraContent' => $this->getExtraContent('block-admin-chamilo'),
145
            ];
146
147
            $json['plugins'] = [
148
                'id' => 'block-admin-plugins',
149
                'editable' => false,
150
                'items' => $this->getItemsPlugins(),
151
            ];
152
153
            /* Health check */
154
            $json['health_check'] = [
155
                'id' => 'block-admin-health-check',
156
                'editable' => false,
157
                'items' => $this->getItemsHealthCheck(),
158
            ];
159
        }
160
161
        /* Sessions */
162
        $json['sessions'] = [
163
            'id' => 'block-admin-sessions',
164
            'searchUrl' => '/main/session/session_list.php',
165
            'editable' => $this->isAdmin,
166
            'items' => $this->getItemsSessions(),
167
            'extraContent' => $this->getExtraContent('block-admin-sessions'),
168
        ];
169
170
        $adminBlockEvent = new AdminBlockDisplayedEvent($json, AbstractEvent::TYPE_POST);
171
172
        $this->eventDispatcher->dispatch($adminBlockEvent, Events::ADMIN_BLOCK_DISPLAYED);
173
174
        $json = $adminBlockEvent->getData();
175
176
        return $this->json($json);
177
    }
178
179
    private function getItemsSecurity(): array
180
    {
181
        return [
182
            [
183
                'class' => 'item-security-login-attempts',
184
                'url' => $this->generateUrl('admin_security_login_attempts'),
185
                'label' => $this->translator->trans('Login attempts'),
186
            ],
187
        ];
188
    }
189
190
    private function getItemsUsers(): array
191
    {
192
        $items = [];
193
        $items[] = [
194
            'class' => 'item-user-list',
195
            'url' => '/main/admin/user_list.php',
196
            'label' => $this->translator->trans('User list'),
197
        ];
198
        $items[] = [
199
            'class' => 'item-user-add',
200
            'url' => '/main/admin/user_add.php',
201
            'label' => $this->translator->trans('Add a user'),
202
        ];
203
204
        if ($this->isAdmin) {
205
            $items[] = [
206
                'class' => 'item-user-export',
207
                'url' => '/main/admin/user_export.php',
208
                'label' => $this->translator->trans('Export users list'),
209
            ];
210
            $items[] = [
211
                'class' => 'item-user-import',
212
                'url' => '/main/admin/user_import.php',
213
                'label' => $this->translator->trans('Import users list'),
214
            ];
215
            $items[] = [
216
                'class' => 'item-user-import-update',
217
                'url' => '/main/admin/user_update_import.php',
218
                'label' => $this->translator->trans('Edit users list'),
219
            ];
220
            $items[] = [
221
                'class' => 'item-user-import-anonymize',
222
                'url' => '/main/admin/user_anonymize_import.php',
223
                'label' => $this->translator->trans('Anonymise users list'),
224
            ];
225
226
            if ($this->isLdapActive) {
227
                $items[] = [
228
                    'class' => 'item-user-ldap-list',
229
                    'url' => '/main/admin/ldap_users_list.php',
230
                    'label' => $this->translator->trans('Import LDAP users into the platform'),
231
                ];
232
            }
233
234
            $items[] = [
235
                'class' => 'item-user-field',
236
                'url' => '/main/admin/extra_fields.php?'.http_build_query(['type' => 'user']),
237
                'label' => $this->translator->trans('Profiling'),
238
            ];
239
            $items[] = [
240
                'class' => 'item-user-groups',
241
                'url' => '/main/admin/usergroups.php',
242
                'label' => $this->translator->trans('Classes'),
243
            ];
244
245
            if ('true' === $this->settingsManager->getSetting('admin.show_link_request_hrm_user')) {
246
                $items[] = [
247
                    'class' => 'item-user-linking-requests',
248
                    'url' => '/main/admin/user_linking_requests.php',
249
                    'label' => $this->translator->trans('Student linking requests'),
250
                ];
251
            }
252
        } else {
253
            $items[] = [
254
                'class' => 'item-user-import',
255
                'url' => '/main/admin/user_import.php',
256
                'label' => $this->translator->trans('Import users list'),
257
            ];
258
            $items[] = [
259
                'class' => 'item-user-groups',
260
                'url' => '/main/admin/usergroups.php',
261
                'label' => $this->translator->trans('Classes'),
262
            ];
263
264
            if ('true' === $this->settingsManager->getSetting('session.limit_session_admin_role')) {
265
                $items = array_filter($items, function (array $item) {
266
                    $urls = [
267
                        '/main/admin/user_list.php',
268
                        '/main/admin/user_add.php',
269
                    ];
270
271
                    return \in_array($item['url'], $urls, true);
272
                });
273
            }
274
275
            if ('true' === $this->settingsManager->getSetting('session.limit_session_admin_list_users')) {
276
                $items = array_filter($items, function (array $item): bool {
277
                    $urls = [
278
                        '/main/admin/user_list.php',
279
                    ];
280
281
                    return !\in_array($item['url'], $urls, true);
282
                });
283
            }
284
285
            if ('true' === $this->settingsManager->getSetting('session.allow_session_admin_extra_access')) {
286
                $items[] = [
287
                    'class' => 'item-user-import-update',
288
                    'url' => '/main/admin/user_update_import.php',
289
                    'label' => $this->translator->trans('Edit users list'),
290
                ];
291
                $items[] = [
292
                    'class' => 'item-user-export',
293
                    'url' => '/main/admin/user_export.php',
294
                    'label' => $this->translator->trans('Export users list'),
295
                ];
296
            }
297
        }
298
299
        return array_values($items);
300
    }
301
302
    private function getExtraContent(string $title): ?array
303
    {
304
        /** @var Page|null $page */
305
        $page = $this->pageRepository->findOneBy(['title' => $title]);
306
307
        $pageJsonld = $this->serializer->serialize($page, 'jsonld', ['groups' => ['adminblock:read']]);
308
        $pageArray = json_decode($pageJsonld, true);
309
310
        if ($page) {
311
            return $pageArray;
312
        }
313
314
        /** @var PageCategory $category */
315
        $category = $this->pageCategoryRepository->findOneBy(['title' => $title]);
316
        $categoryJsonld = $this->serializer->serialize($category, 'jsonld', ['groups' => ['page:read']]);
317
        $categoryArray = json_decode($categoryJsonld, true);
318
319
        if (empty($categoryArray)) {
320
            return [];
321
        }
322
323
        return [
324
            'category' => $categoryArray['@id'],
325
        ];
326
    }
327
328
    private function getItemsCourses(): array
329
    {
330
        $items = [];
331
        $items[] = [
332
            'class' => 'item-course-list',
333
            'url' => '/main/admin/course_list.php',
334
            'label' => $this->translator->trans('Course list'),
335
        ];
336
        $items[] = [
337
            'class' => 'item-course-add',
338
            'url' => '/main/admin/course_add.php',
339
            'label' => $this->translator->trans('Add course'),
340
        ];
341
342
        if ('true' === $this->settingsManager->getSetting('course.course_validation')) {
343
            $items[] = [
344
                'class' => 'item-course-request',
345
                'url' => '/main/admin/course_request_review.php',
346
                'label' => $this->translator->trans('Review incoming course requests'),
347
            ];
348
            $items[] = [
349
                'class' => 'item-course-request-accepted',
350
                'url' => '/main/admin/course_request_accepted.php',
351
                'label' => $this->translator->trans('Accepted course requests'),
352
            ];
353
            $items[] = [
354
                'class' => 'item-course-request-rejected',
355
                'url' => '/main/admin/course_request_rejected.php',
356
                'label' => $this->translator->trans('Rejected course requests'),
357
            ];
358
        }
359
360
        $items[] = [
361
            'class' => 'item-course-export',
362
            'url' => '/main/admin/course_export.php',
363
            'label' => $this->translator->trans('Export courses'),
364
        ];
365
        $items[] = [
366
            'class' => 'item-course-import',
367
            'url' => '/main/admin/course_import.php',
368
            'label' => $this->translator->trans('Import courses list'),
369
        ];
370
        $items[] = [
371
            'class' => 'item-course-category',
372
            'url' => '/main/admin/course_category.php',
373
            'label' => $this->translator->trans('Course categories'),
374
        ];
375
        $items[] = [
376
            'class' => 'item-course-subscription',
377
            'url' => '/main/admin/subscribe_user2course.php',
378
            'label' => $this->translator->trans('Add a user to a course'),
379
        ];
380
        $items[] = [
381
            'class' => 'item-course-subscription-import',
382
            'url' => '/main/admin/course_user_import.php',
383
            'label' => $this->translator->trans('Import users list'),
384
        ];
385
        // $items[] = [
386
        //    'url'=>'course_intro_pdf_import.php',
387
        //    'label' => $this->translator->$this->trans('Import PDF introductions into courses'),
388
        // ];
389
390
        if ('true' === $this->settingsManager->getSetting('gradebook.gradebook_enable_grade_model')) {
391
            $items[] = [
392
                'class' => 'item-grade-model',
393
                'url' => '/main/admin/grade_models.php',
394
                'label' => $this->translator->trans('Grading model'),
395
            ];
396
        }
397
398
        if ($this->isLdapActive) {
399
            $items[] = [
400
                'class' => 'item-course-subscription-ldap',
401
                'url' => '/main/admin/ldap_import_students.php',
402
                'label' => $this->translator->trans('Import LDAP users into a course'),
403
            ];
404
        }
405
406
        $items[] = [
407
            'class' => 'item-course-field',
408
            'url' => '/main/admin/extra_fields.php?'.http_build_query(['type' => 'course']),
409
            'label' => $this->translator->trans('Manage extra fields for courses'),
410
        ];
411
        $items[] = [
412
            'class' => 'item-question-bank',
413
            'url' => '/main/admin/questions.php',
414
            'label' => $this->translator->trans('Questions'),
415
        ];
416
        $items[] = [
417
            'class' => 'item-resource-sequence',
418
            'url' => '/main/admin/resource_sequence.php?'.http_build_query(['type' => SequenceResource::COURSE_TYPE]),
419
            'label' => $this->translator->trans('Resources sequencing'),
420
        ];
421
422
        return $items;
423
    }
424
425
    private function getItemsPlatform(): array
426
    {
427
        $items = [];
428
        $items[] = [
429
            'class' => 'item-setting-list',
430
            'url' => $this->generateUrl('admin_settings'),
431
            'label' => $this->translator->trans('Configuration settings'),
432
        ];
433
        $items[] = [
434
            'class' => 'item-language-list',
435
            'url' => '/main/admin/languages.php',
436
            'label' => $this->translator->trans('Languages'),
437
        ];
438
        $items[] = [
439
            'class' => 'item-plugin-list',
440
            'url' => '/main/admin/settings.php?'.http_build_query(['category' => 'Plugins']),
441
            'label' => $this->translator->trans('Plugins'),
442
        ];
443
        $items[] = [
444
            'class' => 'item-region-list',
445
            'url' => '/main/admin/settings.php?'.http_build_query(['category' => 'Regions']),
446
            'label' => $this->translator->trans('Regions'),
447
        ];
448
        $items[] = [
449
            'class' => 'item-global-announcement',
450
            'url' => '/main/admin/system_announcements.php',
451
            'label' => $this->translator->trans('Portal news'),
452
        ];
453
        $items[] = [
454
            'class' => 'item-global-agenda',
455
            'route' => ['name' => 'CCalendarEventList', 'query' => ['type' => 'global']],
456
            'label' => $this->translator->trans('Global agenda'),
457
        ];
458
        $items[] = [
459
            'class' => 'item-agenda-reminders',
460
            'url' => '/main/admin/import_course_agenda_reminders.php',
461
            'label' => $this->translator->trans('Import course events'),
462
        ];
463
        $items[] = [
464
            'class' => 'item-pages-list',
465
            'route' => ['name' => 'PageList'],
466
            'label' => $this->translator->trans('Pages'),
467
        ];
468
        /*
469
         * Disabled until differentiated with Pages, and reviewed - see GH#6404
470
        $items[] = [
471
            'class' => 'item-page-layouts',
472
            'route' => ['name' => 'PageLayoutList'],
473
            'label' => $this->translator->trans('Page layouts'),
474
        ];
475
        */
476
        $items[] = [
477
            'class' => 'item-registration-page',
478
            'url' => '/main/auth/registration.php?'.http_build_query(['create_intro_page' => 1]),
479
            'label' => $this->translator->trans('Setting the registration page'),
480
        ];
481
        $items[] = [
482
            'class' => 'item-stats',
483
            'url' => '/main/admin/statistics/index.php',
484
            'label' => $this->translator->trans('Statistics'),
485
        ];
486
        $items[] = [
487
            'class' => 'item-stats-report',
488
            'url' => '/main/my_space/company_reports.php',
489
            'label' => $this->translator->trans('Reports'),
490
        ];
491
        $items[] = [
492
            'class' => 'item-teacher-time-report',
493
            'url' => '/main/admin/teacher_time_report.php',
494
            'label' => $this->translator->trans('Teachers time report'),
495
        ];
496
497
        if (api_get_configuration_value('chamilo_cms')) {
498
            $items[] = [
499
                'class' => 'item-cms',
500
                'url' => api_get_path(WEB_PATH).'web/app_dev.php/administration/dashboard',
501
                'label' => $this->translator->trans('CMS'),
502
            ];
503
        }
504
505
        /* Event settings */
506
507
        $items[] = [
508
            'class' => 'item-field',
509
            'url' => '/main/admin/extra_field_list.php',
510
            'label' => $this->translator->trans('Extra fields'),
511
        ];
512
513
        if (api_is_global_platform_admin()) {
514
            $items[] = [
515
                'class' => 'item-access-url',
516
                'url' => '/main/admin/access_urls.php',
517
                'label' => $this->translator->trans('Configure multiple access URL'),
518
            ];
519
        }
520
521
        if ('true' === api_get_plugin_setting('dictionary', 'enable_plugin_dictionary')) {
522
            $items[] = [
523
                'class' => 'item-dictionary',
524
                'url' => api_get_path(WEB_PLUGIN_PATH).'Dictionary/terms.php',
525
                'label' => $this->translator->trans('Dictionary'),
526
            ];
527
        }
528
529
        if ('true' === $this->settingsManager->getSetting('registration.allow_terms_conditions', true)) {
530
            $items[] = [
531
                'class' => 'item-terms-and-conditions',
532
                'route' => ['name' => 'TermsConditionsList'],
533
                'label' => $this->translator->trans('Terms and Conditions'),
534
            ];
535
        }
536
537
        $items[] = [
538
            'class' => 'item-mail-template',
539
            'url' => '/main/mail_template/list.php',
540
            'label' => $this->translator->trans('Mail templates'),
541
        ];
542
543
        if ('true' === api_get_setting('platform.notification_event')) {
544
            $items[] = [
545
                'class' => 'item-notification-list',
546
                'url' => '/main/notification_event/list.php',
547
                'label' => $this->translator->trans('Notifications'),
548
            ];
549
        }
550
551
        $allowJustification = 'true' === api_get_plugin_setting('justification', 'tool_enable');
552
553
        if ($allowJustification) {
554
            $items[] = [
555
                'class' => 'item-justification-list',
556
                'url' => api_get_path(WEB_PLUGIN_PATH).'Justification/list.php',
557
                'label' => $this->translator->trans('Justification'),
558
            ];
559
        }
560
561
        $items[] = [
562
            'class' => 'item-lti-admin',
563
            'url' => $this->generateUrl('chamilo_lti_admin'),
564
            'label' => $this->translator->trans('External tools (LTI)'),
565
        ];
566
567
        $items[] = [
568
            'class' => 'item-contact-category-admin',
569
            'url' => $this->generateUrl('chamilo_contact_category_index'),
570
            'label' => $this->translator->trans('Contact form categories'),
571
        ];
572
573
        $items[] = [
574
            'class' => 'item-system-template-admin',
575
            'url' => '/main/admin/settings.php?'.http_build_query(['category' => 'Templates']),
576
            'label' => $this->translator->trans('System templates'),
577
        ];
578
579
        return $items;
580
    }
581
582
    private function getItemsSettings(): array
583
    {
584
        $items = [];
585
        $items[] = [
586
            'class' => 'item-cleanup-temp-uploads',
587
            'url' => '/admin/cleanup-temp-uploads',
588
            'label' => $this->translator->trans('Clean temporary files'),
589
        ];
590
591
        $items[] = [
592
            'class' => 'item-special-export',
593
            'url' => '/main/admin/special_exports.php',
594
            'label' => $this->translator->trans('Special exports'),
595
        ];
596
        /*$items[] = [
597
            'url' => '/main/admin/periodic_export.php',
598
            'label' => $this->translator->$this->trans('Periodic export'),
599
        ];*/
600
        $items[] = [
601
            'class' => 'item-system-status',
602
            'url' => '/main/admin/system_status.php',
603
            'label' => $this->translator->trans('System status'),
604
        ];
605
        if (is_dir(api_get_path(SYS_TEST_PATH).'datafiller/')) {
606
            $items[] = [
607
                'class' => 'item-data-filler',
608
                'url' => '/main/admin/filler.php',
609
                'label' => $this->translator->trans('Data filler'),
610
            ];
611
        }
612
613
        if (is_dir(api_get_path(SYS_TEST_PATH))) {
614
            $items[] = [
615
                'class' => 'item-email-tester',
616
                'url' => '/admin/email_tester',
617
                'label' => $this->translator->trans('E-mail tester'),
618
            ];
619
        }
620
621
        $items[] = [
622
            'class' => 'item-ticket-system',
623
            'url' => '/main/ticket/tickets.php',
624
            'label' => $this->translator->trans('Tickets'),
625
        ];
626
627
        $items[] = [
628
            'url' => '/main/session/cron_status.php',
629
            'label' => $this->translator->trans('Update session status'),
630
        ];
631
632
        $items[] = [
633
            'class' => 'item-colors',
634
            'route' => ['name' => 'AdminConfigurationColors'],
635
            'label' => $this->translator->trans('Colors'),
636
        ];
637
638
        $items[] = [
639
            'class' => 'item-file-info',
640
            'url' => '/admin/files_info',
641
            'label' => $this->translator->trans('File info'),
642
        ];
643
644
        $items[] = [
645
            'class' => 'item-resources-info',
646
            'url' => '/admin/resources_info',
647
            'label' => $this->translator->trans('Resources by type'),
648
        ];
649
650
        return $items;
651
    }
652
653
    private function getItemsSkills(): array
654
    {
655
        $items = [];
656
        $items[] = [
657
            'class' => 'item-skill-wheel',
658
            'route' => ['name' => 'SkillWheel'],
659
            'label' => $this->translator->trans('Skills wheel'),
660
        ];
661
        $items[] = [
662
            'class' => 'item-skill-import',
663
            'url' => '/main/skills/skills_import.php',
664
            'label' => $this->translator->trans('Skills import'),
665
        ];
666
        $items[] = [
667
            'class' => 'item-skill-list',
668
            'url' => '/main/skills/skill_list.php',
669
            'label' => $this->translator->trans('Manage skills'),
670
        ];
671
        $items[] = [
672
            'class' => 'item-skill-level',
673
            'url' => '/main/skills/skill.php',
674
            'label' => $this->translator->trans('Manage skills levels'),
675
        ];
676
677
        $items[] = [
678
            'class' => 'item-skill-ranking',
679
            'url' => '/main/social/skills_ranking.php?origin=admin',
680
            'label' => $this->translator->trans('Skills ranking'),
681
        ];
682
        $items[] = [
683
            'class' => 'item-skill-gradebook',
684
            'url' => '/main/skills/skills_gradebook.php',
685
            'label' => $this->translator->trans('Skills and assessments'),
686
        ];
687
688
        /*$items[] = [
689
            'url' => '/main/admin/skill_badge.php',
690
            'label' => $this->translator->trans('Badges'),
691
        ];*/
692
693
        return $items;
694
    }
695
696
    private function getItemsGradebook(): array
697
    {
698
        $items = [];
699
        $items[] = [
700
            'class' => 'item-gradebook-list',
701
            'url' => '/main/admin/gradebook_list.php',
702
            'label' => $this->translator->trans('List'),
703
        ];
704
705
        return $items;
706
    }
707
708
    private function getItemsPrivacy(): array
709
    {
710
        $items = [];
711
        $items[] = [
712
            'class' => 'item-privacy-consent',
713
            'url' => '/main/admin/user_list_consent.php',
714
            'label' => $this->translator->trans('User list'),
715
        ];
716
        $items[] = [
717
            'class' => 'item-gdpr-parties',
718
            'route' => ['name' => 'ThirdPartyManager'],
719
            'label' => $this->translator->trans('Third parties (GDPR)'),
720
        ];
721
722
        return $items;
723
    }
724
725
    private function getItemsChamilo(): array
726
    {
727
        $languageInterface = api_get_language_isocode();
728
729
        $items = [];
730
        $items[] = [
731
            'class' => 'item-software-homepage',
732
            'url' => 'https://chamilo.org/',
733
            'label' => $this->translator->trans('Chamilo homepage'),
734
        ];
735
736
        // Custom linking to user guides in the existing languages
737
        /*$guideLinks = [
738
            'french' => 'v/1.11.x-fr/',
739
            'spanish' => 'v/1.11.x-es/',
740
            'dutch' => 'v/1.11.x-nl/',
741
            'galician' => 'v/1.11.x-ga/',
742
        ];*/
743
744
        $guideLink = 'https://docs.chamilo.org/';
745
746
        /*if (!empty($guideLinks[$languageInterface])) {
747
            $guideLink .= $guideLinks[$languageInterface];
748
        }*/
749
750
        $items[] = [
751
            'class' => 'item-user-guides',
752
            'url' => $guideLink,
753
            'label' => $this->translator->trans('User guides'),
754
        ];
755
        $items[] = [
756
            'class' => 'item-forum',
757
            'url' => 'https://github.com/chamilo/chamilo-lms/discussions/',
758
            'label' => $this->translator->trans('Chamilo forum'),
759
        ];
760
        $items[] = [
761
            'class' => 'item-installation-guide',
762
            'url' => '/documentation/installation_guide.html',
763
            'label' => $this->translator->trans('Installation guide'),
764
        ];
765
        $items[] = [
766
            'class' => 'item-changelog',
767
            'url' => '/documentation/changelog.html',
768
            'label' => $this->translator->trans('Changes in last version'),
769
        ];
770
        $items[] = [
771
            'class' => 'item-credits',
772
            'url' => '/documentation/credits.html',
773
            'label' => $this->translator->trans('Contributors list'),
774
        ];
775
        $items[] = [
776
            'class' => 'item-security',
777
            'url' => '/documentation/security.html',
778
            'label' => $this->translator->trans('Security guide'),
779
        ];
780
        $items[] = [
781
            'class' => 'item-optimization',
782
            'url' => '/documentation/optimization.html',
783
            'label' => $this->translator->trans('Optimization guide'),
784
        ];
785
        /*
786
        $items[] = [
787
            'class' => 'item-extensions',
788
            'url' => 'https://chamilo.org/extensions',
789
            'label' => $this->translator->trans('Chamilo extensions'),
790
        ];
791
        */
792
        $items[] = [
793
            'class' => 'item-providers',
794
            'url' => 'https://chamilo.org/providers',
795
            'label' => $this->translator->trans('Chamilo official services providers'),
796
        ];
797
798
        return $items;
799
    }
800
801
    private function getItemsSessions(): array
802
    {
803
        $items = [];
804
        $items[] = [
805
            'class' => 'item-session-list',
806
            'url' => '/main/session/session_list.php',
807
            'label' => $this->translator->trans('Training sessions list'),
808
        ];
809
        $items[] = [
810
            'class' => 'item-session-add',
811
            'url' => '/main/session/session_add.php',
812
            'label' => $this->translator->trans('Add a training session'),
813
        ];
814
        $items[] = [
815
            'class' => 'item-session-category',
816
            'url' => '/main/session/session_category_list.php',
817
            'label' => $this->translator->trans('Sessions categories list'),
818
        ];
819
        $items[] = [
820
            'class' => 'item-session-import',
821
            'url' => '/main/session/session_import.php',
822
            'label' => $this->translator->trans('Import sessions list'),
823
        ];
824
        $items[] = [
825
            'class' => 'item-session-import-hr',
826
            'url' => '/main/session/session_import_drh.php',
827
            'label' => $this->translator->trans('Import list of HR directors into sessions'),
828
        ];
829
830
        if ($this->isLdapActive) {
831
            $items[] = [
832
                'class' => 'item-session-subscription-ldap-import',
833
                'url' => '/main/admin/ldap_import_students_to_session.php',
834
                'label' => $this->translator->trans('Import LDAP users into a session'),
835
            ];
836
        }
837
838
        $items[] = [
839
            'class' => 'item-session-export',
840
            'url' => '/main/session/session_export.php',
841
            'label' => $this->translator->trans('Export sessions list'),
842
        ];
843
844
        $items[] = [
845
            'class' => 'item-session-course-copy',
846
            'url' => '/main/course_copy/copy_course_session.php',
847
            'label' => $this->translator->trans('Copy from course in session to another session'),
848
        ];
849
850
        $allowCareer = $this->settingsManager->getSetting('session.allow_session_admin_read_careers');
851
852
        if ($this->isAdmin || ('true' === $allowCareer && $this->isSessionAdmin)) {
853
            // Disabled until it is reemplemented to work with Chamilo 2
854
            /*                $items[] = [
855
                                'class' => 'item-session-user-move-stats',
856
                                'url' => '/main/admin/user_move_stats.php',
857
                                'label' => $this->translator->trans('Move users results from/to a session'),
858
                            ];
859
             */
860
            $items[] = [
861
                'class' => 'item-session-user-move',
862
                'url' => '/main/coursecopy/move_users_from_course_to_session.php',
863
                'label' => $this->translator->trans('Move users results from base course to a session'),
864
            ];
865
866
            $items[] = [
867
                'class' => 'item-career-dashboard',
868
                'url' => '/main/admin/career_dashboard.php',
869
                'label' => $this->translator->trans('Careers and promotions'),
870
            ];
871
            $items[] = [
872
                'class' => 'item-session-field',
873
                'url' => '/main/admin/extra_fields.php?'.http_build_query(['type' => 'session']),
874
                'label' => $this->translator->trans('Manage session fields'),
875
            ];
876
            $items[] = [
877
                'class' => 'item-resource-sequence',
878
                'url' => '/main/admin/resource_sequence.php?'.http_build_query(['type' => SequenceResource::SESSION_TYPE]),
879
                'label' => $this->translator->trans('Resources sequencing'),
880
            ];
881
            $items[] = [
882
                'class' => 'item-export-exercise-results',
883
                'url' => '/main/admin/export_exercise_results.php',
884
                'label' => $this->translator->trans('Export all results from an exercise'),
885
            ];
886
        }
887
888
        return $items;
889
    }
890
891
    private function getItemsPlugins(): array
892
    {
893
        $items = [];
894
895
        $accessUrl = $this->accessUrlHelper->getCurrent();
896
        $appPlugin = new AppPlugin();
897
        $plugins = $this->pluginRepository->getInstalledPlugins();
898
899
        foreach ($plugins as $plugin) {
900
            // getPluginInfo() might fail to build the plugin object; never assume 'obj' exists
901
            $pluginInfo = $appPlugin->getPluginInfo($plugin->getTitle());
902
903
            // Normalize/fallbacks
904
            if (!\is_array($pluginInfo)) {
905
                // Defensive: unexpected structure → skip
906
                error_log(\sprintf('[admin:index] Plugin "%s" has no pluginInfo array, skipping.', $plugin->getTitle()));
907
908
                continue;
909
            }
910
911
            /** @var Plugin|null $objPlugin */
912
            $objPlugin = $pluginInfo['obj'] ?? null;
913
914
            if (!$objPlugin instanceof Plugin) {
915
                // Defensive: plugin could not be instantiated (e.g. throws in constructor)
916
                error_log(\sprintf('[admin:index] Plugin "%s" has no valid "obj" (instance of Plugin), skipping.', $plugin->getTitle()));
917
918
                continue;
919
            }
920
921
            // Per-URL configuration
922
            $pluginInUrl = $plugin->getOrCreatePluginConfiguration($accessUrl);
923
            $configuration = $pluginInUrl->getConfiguration() ?: [];
924
925
            if (!$configuration || !isset($configuration['regions'])) {
926
                continue;
927
            }
928
929
            // Only show plugins that declare the admin menu region
930
            if (!\in_array('menu_administrator', $configuration['regions'], true)) {
931
                continue;
932
            }
933
934
            // Build admin URL defensively (some plugins may throw when building URLs)
935
            try {
936
                $adminUrl = $objPlugin->getAdminUrl();
937
            } catch (Throwable $e) {
938
                error_log(\sprintf('[admin:index] Plugin "%s" getAdminUrl() failed: %s', $plugin->getTitle(), $e->getMessage()));
939
940
                continue;
941
            }
942
943
            // Label fallback to DB title if pluginInfo misses 'title'
944
            $label = (string) ($pluginInfo['title'] ?? $plugin->getTitle());
945
946
            $items[] = [
947
                'class' => 'item-plugin-'.strtolower($plugin->getTitle()),
948
                'url' => $adminUrl,
949
                'label' => $label,
950
            ];
951
        }
952
953
        return $items;
954
    }
955
956
    private function getItemsHealthCheck(): array
957
    {
958
        $items = [];
959
960
        // Check if dsn or email is defined :
961
        $mailDsn = $this->settingsManager->getSetting('mail.mailer_dsn', true);
962
        $mailSender = $this->settingsManager->getSetting('mail.mailer_from_email', true);
963
        $nameSender = $this->settingsManager->getSetting('mail.mailer_from_name', true);
964
        if ((empty($mailDsn) || 'null://null' == $mailDsn) || empty($mailSender) || empty($nameSender)) {
965
            $items[] = [
966
                'className' => 'item-health-check-mail-settings text-error',
967
                'url' => '/admin/settings/mail',
968
                'label' => $this->translator->trans('E-mail settings need to be configured'),
969
            ];
970
        } else {
971
            $items[] = [
972
                'className' => 'item-health-check-mail-settings text-success',
973
                'url' => '/admin/settings/mail',
974
                'label' => $this->translator->trans('E-mail settings are OK'),
975
            ];
976
        }
977
978
        // Check if the admin user has access to all URLs
979
        if (api_is_admin_in_all_active_urls()) {
980
            $items[] = [
981
                'className' => 'item-health-check-admin-urls text-success',
982
                'url' => '/main/admin/access_urls.php',
983
                'label' => $this->translator->trans('All URLs have at least one admin assigned'),
984
            ];
985
        } else {
986
            $items[] = [
987
                'className' => 'item-health-check-admin-urls text-error',
988
                'url' => '/main/admin/access_url_edit_users_to_url.php',
989
                'label' => $this->translator->trans('At least one URL has no admin assigned'),
990
            ];
991
        }
992
993
        // ---------------------------------------------------------------------
994
        // File permissions checks
995
        // ---------------------------------------------------------------------
996
        $projectDir = (string) $this->getParameter('kernel.project_dir');
997
998
        // Help links (optional but avoids null URLs)
999
        $securityGuideUrl = '/documentation/security.html';
1000
        $optimizationGuideUrl = '/documentation/optimization.html';
1001
1002
        // .env should NOT be writable by the web server user
1003
        $envPath = $projectDir.'/.env';
1004
        $envIsWritable = is_file($envPath) && is_writable($envPath);
1005
1006
        $items[] = [
1007
            'className' => 'item-health-check-env-perms '.($envIsWritable ? 'text-error' : 'text-success'),
1008
            'url' => $securityGuideUrl,
1009
            'label' => sprintf(
1010
                $this->translator->trans($envIsWritable ? '%s is writeable' : '%s is not writeable'),
1011
                '.env'
1012
            ),
1013
        ];
1014
1015
        // config/ should NOT be writable by the web server user
1016
        $configPath = $projectDir.'/config';
1017
        $configIsWritable = is_dir($configPath) && is_writable($configPath);
1018
1019
        $items[] = [
1020
            'className' => 'item-health-check-config-perms '.($configIsWritable ? 'text-error' : 'text-success'),
1021
            'url' => $securityGuideUrl,
1022
            'label' => sprintf(
1023
                $this->translator->trans($configIsWritable ? '%s is writeable' : '%s is not writeable'),
1024
                'config/'
1025
            ),
1026
        ];
1027
1028
        // var/cache MUST be writable (Symfony cache)
1029
        $cachePath = $projectDir.'/var/cache';
1030
        $cacheIsWritable = is_dir($cachePath) && is_writable($cachePath);
1031
1032
        $items[] = [
1033
            'className' => 'item-health-check-cache-perms '.($cacheIsWritable ? 'text-success' : 'text-error'),
1034
            'url' => $optimizationGuideUrl,
1035
            'label' => sprintf(
1036
                $this->translator->trans($cacheIsWritable ? '%s is writeable' : '%s is not writeable'),
1037
                'var/cache'
1038
            ),
1039
        ];
1040
1041
        // public/main/install existence -> orange if present
1042
        $installPath = $projectDir.'/public/main/install';
1043
        $installExists = is_dir($installPath);
1044
1045
        $items[] = [
1046
            'className' => 'item-health-check-install-folder '.($installExists ? 'text-warning' : 'text-success'),
1047
            'url' => $securityGuideUrl,
1048
            'label' => $this->translator->trans($installExists ? 'Install folder is still present' : 'Install folder is not present'),
1049
        ];
1050
1051
        return $items;
1052
    }
1053
}
1054