Passed
Push — develop ( 94d0ee...15e467 )
by BENARD
02:27
created

ArticleLocaleSubscriber::getSubscribedEvents()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 5
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace ProjetNormandie\ArticleBundle\EventSubscriber;
6
7
use ApiPlatform\Symfony\EventListener\EventPriorities;
8
use ProjetNormandie\ArticleBundle\Entity\Article;
9
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
10
use Symfony\Component\HttpFoundation\Request;
11
use Symfony\Component\HttpFoundation\RequestStack;
12
use Symfony\Component\HttpKernel\Event\ViewEvent;
13
use Symfony\Component\HttpKernel\KernelEvents;
14
15
/**
16
 * Event subscriber that sets the current locale on Article entities
17
 * based on the HTTP_ACCEPT_LANGUAGE header
18
 */
19
class ArticleLocaleSubscriber implements EventSubscriberInterface
20
{
21
    private array $supportedLocales;
22
    private string $defaultLocale;
23
24
    public function __construct(
25
        array $supportedLocales = ['en'],
26
        string $defaultLocale = 'en'
27
    ) {
28
        $this->supportedLocales = $supportedLocales;
29
        $this->defaultLocale = $defaultLocale;
30
    }
31
32
33
    /**
34
     * {@inheritdoc}
35
     */
36
    public static function getSubscribedEvents(): array
37
    {
38
        return [
39
            // This event is triggered right before the serialization process
40
            KernelEvents::VIEW => ['setLocale', EventPriorities::PRE_SERIALIZE],
41
        ];
42
    }
43
44
    /**
45
     * Set the appropriate locale on Article entities based on HTTP_ACCEPT_LANGUAGE
46
     *
47
     * @param ViewEvent $event The event
48
     */
49
    public function setLocale(ViewEvent $event): void
50
    {
51
        $request = $event->getRequest();
52
        $result = $event->getControllerResult();
53
54
        // Only process GET requests targeting Article entities
55
        if (!$this->shouldProcess($request, $result)) {
56
            return;
57
        }
58
59
        // Get preferred locale from HTTP_ACCEPT_LANGUAGE header
60
        $locale = $this->getPreferredLocale($request);
61
62
        // Set locale on one or more Article entities
63
        $this->applyLocaleToResult($result, $locale);
64
    }
65
66
    /**
67
     * Determine if this request should be processed
68
     *
69
     * @param Request $request The HTTP request
70
     * @param mixed $result The controller result
71
     * @return bool Whether the request should be processed
72
     */
73
    private function shouldProcess(Request $request, $result): bool
74
    {
75
        // Only process GET requests
76
        if (!in_array($request->getMethod(), ['GET'])) {
77
            return false;
78
        }
79
80
        // Process single Article
81
        if ($result instanceof Article) {
82
            return true;
83
        }
84
85
        // Process collections containing Articles
86
        if (is_array($result) || $result instanceof \Traversable) {
87
            foreach ($result as $item) {
88
                if ($item instanceof Article) {
89
                    return true;
90
                }
91
            }
92
        }
93
94
        return false;
95
    }
96
97
    /**
98
     * Extract preferred locale from the HTTP_ACCEPT_LANGUAGE header
99
     *
100
     * @param Request $request The HTTP request
101
     * @return string The preferred locale (defaulting to 'en')
102
     */
103
    private function getPreferredLocale(Request $request): string
104
    {
105
        // Check for HTTP_ACCEPT_LANGUAGE header
106
        $acceptLanguage = $request->headers->get('Accept-Language');
107
        if (!$acceptLanguage) {
108
            return $this->defaultLocale; // Default to English
109
        }
110
111
        // Extract primary language code (fr-FR -> fr, en-US -> en, etc.)
112
        $locale = substr($acceptLanguage, 0, 2);
113
114
        // Only accept supported locales
115
        if (in_array($locale, $this->supportedLocales, true)) {
116
            return $locale;
117
        }
118
        return $this->defaultLocale;
119
    }
120
121
    /**
122
     * Apply the preferred locale to Article entities in the result
123
     *
124
     * @param mixed $result The controller result
125
     * @param string $locale The preferred locale
126
     */
127
    private function applyLocaleToResult($result, string $locale): void
128
    {
129
        // Single Article
130
        if ($result instanceof Article) {
131
            $result->setCurrentLocale($locale);
132
            return;
133
        }
134
135
        // Collection of Articles
136
        if (is_array($result) || $result instanceof \Traversable) {
137
            foreach ($result as $item) {
138
                if ($item instanceof Article) {
139
                    $item->setCurrentLocale($locale);
140
                }
141
            }
142
        }
143
    }
144
}
145