Passed
Pull Request — master (#6790)
by
unknown
11:19
created

LocaleSubscriber   A

Complexity

Total Complexity 25

Size/Duplication

Total Lines 120
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 54
c 1
b 0
f 0
dl 0
loc 120
rs 10
wmc 25

4 Methods

Rating   Name   Duplication   Size   Complexity  
A getSubscribedEvents() 0 5 1
F getCurrentLanguage() 0 80 18
A __construct() 0 7 1
A onKernelRequest() 0 21 5
1
<?php
2
3
declare(strict_types=1);
4
5
/* For licensing terms, see /license.txt */
6
7
namespace Chamilo\CoreBundle\EventSubscriber;
8
9
use Chamilo\CoreBundle\Entity\Course;
10
use Chamilo\CoreBundle\Settings\SettingsManager;
11
use Chamilo\CourseBundle\Settings\SettingsCourseManager;
12
use Doctrine\ORM\EntityManagerInterface;
13
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
14
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
15
use Symfony\Component\HttpFoundation\Request;
16
use Symfony\Component\HttpKernel\Event\RequestEvent;
17
use Symfony\Component\HttpKernel\KernelEvents;
18
19
/**
20
 * Handles locale selection based on platform, user, and course settings.
21
 */
22
class LocaleSubscriber implements EventSubscriberInterface
23
{
24
    public function __construct(
25
        private string $defaultLocale,
26
        private SettingsManager $settingsManager,
27
        private ParameterBagInterface $parameterBag,
28
        private SettingsCourseManager $courseSettingsManager,
29
        private EntityManagerInterface $em,
30
    ) {}
31
32
    public function onKernelRequest(RequestEvent $event): void
33
    {
34
        $request = $event->getRequest();
35
36
        // Skip if not installed or no session is available
37
        $installed = $this->parameterBag->has('installed') && 1 === (int) $this->parameterBag->get('installed');
38
        if (!$installed || !$request->hasSession()) {
39
            return;
40
        }
41
42
        $session = $request->getSession();
43
44
        // Honor explicit override via ?_locale=xx (persist for later requests)
45
        if ($queryLocale = $request->query->get('_locale')) {
46
            $session->set('_selected_locale', $queryLocale);
47
        }
48
49
        // Resolve locale and apply
50
        $locale = $this->getCurrentLanguage($request);
51
        $request->setLocale($locale);
52
        $session->set('_locale', $locale);
53
    }
54
55
    public function getCurrentLanguage(Request $request): string
56
    {
57
        $session = $request->getSession();
58
        $localeList = [];
59
60
        // 1) Platform default
61
        if ($platformLocale = $this->settingsManager->getSetting('language.platform_language')) {
62
            $localeList['platform_lang'] = $platformLocale;
63
        }
64
65
        // 2) User profile (from session)
66
        if ($userLocale = $session->get('_locale_user')) {
67
            $localeList['user_profil_lang'] = $userLocale;
68
        }
69
70
        // 3) Course language, or user language if course allows it
71
        // First try: course already in session
72
        $course = $session->get('course');
73
74
        // Fallback: resolve course from request if not in session yet
75
        if (!$course instanceof Course) {
76
            // Accept both numeric id (?cid=123) and code (?cid=ABC) as well as legacy ?cidReq=CODE
77
            $cid   = $request->query->get('cid');
78
            $cidReq = $request->query->get('cidReq');
79
80
            if ($cid) {
81
                if (ctype_digit((string) $cid)) {
82
                    $course = $this->em->getRepository(Course::class)->find((int) $cid);
83
                } else {
84
                    $course = $this->em->getRepository(Course::class)->findOneBy(['code' => (string) $cid]);
85
                }
86
            }
87
88
            if (!$course && $cidReq) {
89
                $course = $this->em->getRepository(Course::class)->findOneBy(['code' => (string) $cidReq]);
90
            }
91
        }
92
93
        if ($course instanceof Course) {
94
            $userLocale   = $localeList['user_profil_lang'] ?? null;
95
            $courseLocale = $course->getCourseLanguage();
96
97
            // The per-course setting decides whether to use user language
98
            $this->courseSettingsManager->setCourse($course);
99
            $allowUser = $this->courseSettingsManager->getCourseSettingValue('show_course_in_user_language') === '1';
100
101
            if ($allowUser && $userLocale) {
102
                $localeList['course_lang'] = $userLocale;
103
            } elseif ($courseLocale) {
104
                $localeList['course_lang'] = $courseLocale;
105
            }
106
        }
107
108
        // 4) Explicit selection via URL (?_locale=xx) saved earlier in session
109
        if ($selected = $session->get('_selected_locale')) {
110
            $localeList['user_selected_lang'] = $selected;
111
        }
112
113
        // 5) Honor configured priorities language_priority_1..4
114
        foreach ([
115
                     'language_priority_1',
116
                     'language_priority_2',
117
                     'language_priority_3',
118
                     'language_priority_4',
119
                 ] as $settingKey) {
120
            $priority = $this->settingsManager->getSetting("language.$settingKey");
121
            if (!empty($priority) && !empty($localeList[$priority])) {
122
                return $localeList[$priority];
123
            }
124
        }
125
126
        // 6) Fallback order when priorities are absent
127
        foreach (['platform_lang', 'user_profil_lang', 'course_lang', 'user_selected_lang'] as $key) {
128
            if (!empty($localeList[$key])) {
129
                return $localeList[$key];
130
            }
131
        }
132
133
        // 7) Final fallback to system default
134
        return $this->defaultLocale;
135
    }
136
137
    public static function getSubscribedEvents(): array
138
    {
139
        return [
140
            // Must run before Symfony's default Locale listener
141
            KernelEvents::REQUEST => [['onKernelRequest', 20]],
142
        ];
143
    }
144
}
145