Completed
Pull Request — master (#4235)
by Craig
07:58 queued 02:36
created

LocaleApi::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 19
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
cc 1
eloc 10
c 1
b 1
f 0
nc 1
nop 6
dl 0
loc 19
rs 9.9332
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the Zikula package.
7
 *
8
 * Copyright Zikula - https://ziku.la/
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace Zikula\SettingsModule\Api;
15
16
use Symfony\Component\Finder\Finder;
17
use Symfony\Component\HttpFoundation\RequestStack;
18
use Symfony\Component\Intl\Locales;
19
use Zikula\Bundle\CoreBundle\HttpKernel\ZikulaHttpKernelInterface;
20
use Zikula\ExtensionsModule\Api\ApiInterface\VariableApiInterface;
21
use Zikula\ExtensionsModule\Api\VariableApi;
22
use Zikula\SettingsModule\Api\ApiInterface\LocaleApiInterface;
23
use Zikula\SettingsModule\Helper\LocaleConfigHelper;
24
25
class LocaleApi implements LocaleApiInterface
26
{
27
    /**
28
     * Locales with translations present
29
     * @var array
30
     */
31
    private $supportedLocales = [];
32
33
    /**
34
     * @var ZikulaHttpKernelInterface
35
     */
36
    private $kernel;
37
38
    /**
39
     * @var RequestStack
40
     */
41
    private $requestStack;
42
43
    /**
44
     * @var VariableApiInterface
45
     */
46
    private $variableApi;
47
48
    /**
49
     * @var LocaleConfigHelper
50
     */
51
    private $localeConfigHelper;
52
53
    /**
54
     * @var string
55
     */
56
    private $defaultLocale;
57
58
    /**
59
     * @var bool
60
     */
61
    private $installed;
62
63
    /**
64
     * @var string
65
     */
66
    private $translationPath;
67
68
    /**
69
     * @var string
70
     */
71
    private $sectionKey;
72
73
    public function __construct(
74
        ZikulaHttpKernelInterface $kernel,
75
        RequestStack $requestStack,
76
        VariableApiInterface $variableApi,
77
        LocaleConfigHelper $localeConfigHelper,
78
        string $defaultLocale = 'en',
79
        string $installed = '0.0.0'
80
    ) {
81
        $this->supportedLocales = [
82
            'withRegions' => [],
83
            'withoutRegions' => []
84
        ];
85
        $this->kernel = $kernel;
86
        $this->requestStack = $requestStack;
87
        $this->variableApi = $variableApi;
88
        $this->localeConfigHelper = $localeConfigHelper;
89
        $this->defaultLocale = $defaultLocale;
90
        $this->installed = '0.0.0' !== $installed;
91
        $this->translationPath = $this->kernel->getProjectDir() . '/translations';
92
    }
93
94
    public function getSupportedLocales(bool $includeRegions = true): array
95
    {
96
        $this->sectionKey = $includeRegions ? 'withRegions' : 'withoutRegions';
97
98
        if (!empty($this->supportedLocales[$this->sectionKey])) {
99
            return $this->supportedLocales[$this->sectionKey];
100
        }
101
102
        $this->supportedLocales[$this->sectionKey][] = $this->defaultLocale;
103
        if (!$this->installed) {
104
            return $this->supportedLocales[$this->sectionKey];
105
        }
106
107
        if (!is_dir($this->translationPath)) {
108
            return $this->supportedLocales[$this->sectionKey];
109
        }
110
111
        $multiLingualEnabled = (bool) $this->variableApi->get(VariableApi::CONFIG, 'multilingual', 1);
112
        if ($multiLingualEnabled) {
113
            // read in locales from translation path
114
            $this->collectLocales($includeRegions);
115
        }
116
117
        // ensure config file is still in sync
118
        if (true === $includeRegions) {
119
            $syncConfig = true;
120
            if (null !== $this->requestStack) {
121
                $request = $this->requestStack->getCurrentRequest();
122
                if (null === $request) {
123
                    $syncConfig = false;
124
                } elseif ($request->isXmlHttpRequest()) {
125
                    $syncConfig = false;
126
                } elseif ($request !== $this->requestStack->getMasterRequest()) {
127
                    $syncConfig = false;
128
                }
129
            }
130
            if ($syncConfig) {
131
                $this->localeConfigHelper->updateConfiguration($this->supportedLocales[$this->sectionKey]);
132
            }
133
        }
134
135
        return $this->supportedLocales[$this->sectionKey];
136
    }
137
138
    public function getSupportedLocaleNames(string $region = null, string $displayLocale = null, bool $includeRegions = true): array
139
    {
140
        $locales = $this->getSupportedLocales($includeRegions);
141
        $namedLocales = [];
142
        foreach ($locales as $locale) {
143
            $localeName = Locales::getName($locale, $displayLocale);
144
            $namedLocales[$localeName] = $locale;
145
        }
146
        ksort($namedLocales);
147
148
        return $namedLocales;
149
    }
150
151
    public function getBrowserLocale(string $default = 'en'): string
152
    {
153
        $request = null !== $this->requestStack ? $this->requestStack->getCurrentRequest() : null;
154
        if (null === $request || 'cli' === PHP_SAPI) {
155
            return $default;
156
        }
157
158
        return $request->getPreferredLanguage($this->getSupportedLocales()) ?? $default;
159
    }
160
161
    private function getTranslationFiles(): Finder
162
    {
163
        $finder = new Finder();
164
        $files = $finder->files()
165
            ->in([$this->translationPath])
166
            ->depth(0)
167
            ->name(['*.csv', '*.dat', '*.ini', '*.mo', '*.php', '*.po', '*.qt', '*.xlf', '*.json', '*.yaml', '*.yml'])
168
            ->notName('*.template.*')
169
        ;
170
171
        return $files;
172
    }
173
174
    private function collectLocales(bool $includeRegions = true): void
175
    {
176
        $files = $this->getTranslationFiles();
177
        foreach ($files as $file) {
178
            $fileName = $file->getBasename($file->getExtension());
179
            if (false === mb_strpos($fileName, '.')) {
180
                continue;
181
            }
182
            list(, $locale) = explode('.', $fileName);
183
            if (!$includeRegions && false !== mb_strpos($locale, '_')) {
184
                $localeParts = explode('_', $locale);
185
                $locale = $localeParts[0];
186
            }
187
            if (!in_array($locale, $this->supportedLocales[$this->sectionKey], true)) {
188
                $this->supportedLocales[$this->sectionKey][] = $locale;
189
            }
190
        }
191
    }
192
}
193