LoaderTest::testDetectEnv()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 34
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 25
c 1
b 0
f 0
dl 0
loc 34
rs 9.52
cc 3
nc 3
nop 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace PhpMyAdmin\MoTranslator\Tests;
6
7
use PhpMyAdmin\MoTranslator\Cache\CacheFactoryInterface;
8
use PhpMyAdmin\MoTranslator\Cache\CacheInterface;
9
use PhpMyAdmin\MoTranslator\Loader;
10
use PhpMyAdmin\MoTranslator\MoParser;
11
use PHPUnit\Framework\MockObject\MockObject;
12
use PHPUnit\Framework\TestCase;
13
14
use function getenv;
15
use function putenv;
16
17
/**
18
 * Test for mo loading.
19
 */
20
class LoaderTest extends TestCase
21
{
22
    /**
23
     * @param list<string> $expected
0 ignored issues
show
Bug introduced by
The type PhpMyAdmin\MoTranslator\Tests\list was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
24
     *
25
     * @dataProvider localeList
26
     */
27
    public function testListLocales(string $locale, array $expected): void
28
    {
29
        self::assertSame($expected, Loader::listLocales($locale));
30
    }
31
32
    /** @return list<array{string, list<string>}> */
33
    public static function localeList(): array
34
    {
35
        return [
36
            [
37
                'cs_CZ',
38
                [
39
                    'cs_CZ',
40
                    'cs',
41
                ],
42
            ],
43
            [
44
                'sr_CS.UTF-8@latin',
45
                [
46
                    'sr_CS.UTF-8@latin',
47
                    'sr_CS@latin',
48
                    'sr@latin',
49
                    'sr_CS.UTF-8',
50
                    'sr_CS',
51
                    'sr',
52
                ],
53
            ],
54
            // For a locale containing country code, we prefer
55
            // full locale name, but if that's not found, fall back
56
            // to the language only locale name.
57
            [
58
                'sr_RS',
59
                [
60
                    'sr_RS',
61
                    'sr',
62
                ],
63
            ],
64
            // If language code is used, it's the only thing returned.
65
            [
66
                'sr',
67
                ['sr'],
68
            ],
69
            // There is support for language and charset only.
70
            [
71
                'sr.UTF-8',
72
                [
73
                    'sr.UTF-8',
74
                    'sr',
75
                ],
76
            ],
77
78
            // It can also split out character set from the full locale name.
79
            [
80
                'sr_RS.UTF-8',
81
                [
82
                    'sr_RS.UTF-8',
83
                    'sr_RS',
84
                    'sr',
85
                ],
86
            ],
87
88
            // There is support for @modifier in locale names as well.
89
            [
90
                'sr_RS.UTF-8@latin',
91
                [
92
                    'sr_RS.UTF-8@latin',
93
                    'sr_RS@latin',
94
                    'sr@latin',
95
                    'sr_RS.UTF-8',
96
                    'sr_RS',
97
                    'sr',
98
                ],
99
            ],
100
            [
101
                'sr.UTF-8@latin',
102
                [
103
                    'sr.UTF-8@latin',
104
                    'sr@latin',
105
                    'sr.UTF-8',
106
                    'sr',
107
                ],
108
            ],
109
110
            // We can pass in only language and modifier.
111
            [
112
                'sr@latin',
113
                [
114
                    'sr@latin',
115
                    'sr',
116
                ],
117
            ],
118
119
            // If locale name is not following the regular POSIX pattern,
120
            // it's used verbatim.
121
            [
122
                'something',
123
                ['something'],
124
            ],
125
126
            // Passing in an empty string returns an empty array.
127
            [
128
                '',
129
                [],
130
            ],
131
        ];
132
    }
133
134
    private function getLoader(string $domain, string $locale): Loader
135
    {
136
        $loader = new Loader();
137
        $loader->setlocale($locale);
138
        $loader->textdomain($domain);
139
        $loader->bindtextdomain($domain, __DIR__ . '/data/locale/');
140
141
        return $loader;
142
    }
143
144
    public function testLocaleChange(): void
145
    {
146
        $loader = new Loader();
147
        $loader->setlocale('cs');
148
        $loader->textdomain('phpmyadmin');
149
        $loader->bindtextdomain('phpmyadmin', __DIR__ . '/data/locale/');
150
        $translator = $loader->getTranslator('phpmyadmin');
151
        self::assertSame('Typ', $translator->gettext('Type'));
152
        $loader->setlocale('be_BY');
153
        $translator = $loader->getTranslator('phpmyadmin');
154
        self::assertSame('Тып', $translator->gettext('Type'));
155
    }
156
157
    /** @dataProvider translatorData */
158
    public function testGetTranslator(string $domain, string $locale, string $otherdomain, string $expected): void
159
    {
160
        $loader = $this->getLoader($domain, $locale);
161
        $translator = $loader->getTranslator($otherdomain);
162
        self::assertSame(
163
            $expected,
164
            $translator->gettext('Type'),
165
        );
166
    }
167
168
    /** @return list<array{string, string, string, string}> */
169
    public static function translatorData(): array
170
    {
171
        return [
0 ignored issues
show
Bug Best Practice introduced by
The expression return array(array('phpm... 'phpmyadmin', 'Type')) returns the type array<integer,array<integer,string>> which is incompatible with the documented return type PhpMyAdmin\MoTranslator\Tests\list.
Loading history...
172
            [
173
                'phpmyadmin',
174
                'cs',
175
                '',
176
                'Typ',
177
            ],
178
            [
179
                'phpmyadmin',
180
                'cs_CZ',
181
                '',
182
                'Typ',
183
            ],
184
            [
185
                'phpmyadmin',
186
                'be_BY',
187
                '',
188
                'Тып',
189
            ],
190
            [
191
                'phpmyadmin',
192
                'be@latin',
193
                '',
194
                'Typ',
195
            ],
196
            [
197
                'phpmyadmin',
198
                'cs',
199
                'other',
200
                'Type',
201
            ],
202
            [
203
                'other',
204
                'cs',
205
                'phpmyadmin',
206
                'Type',
207
            ],
208
        ];
209
    }
210
211
    public function testInstance(): void
212
    {
213
        $loader = Loader::getInstance();
214
        $loader->setlocale('cs');
215
        $loader->textdomain('phpmyadmin');
216
        $loader->bindtextdomain('phpmyadmin', __DIR__ . '/data/locale/');
217
218
        $translator = $loader->getTranslator();
219
        self::assertSame(
220
            'Typ',
221
            $translator->gettext('Type'),
222
        );
223
224
        /* Ensure the object survives */
225
        $loader = Loader::getInstance();
226
        $translator = $loader->getTranslator();
227
        self::assertSame(
228
            'Typ',
229
            $translator->gettext('Type'),
230
        );
231
232
        /* Ensure the object can support different locale files for the same domain */
233
        $loader = Loader::getInstance();
234
        $loader->setlocale('be_BY');
235
        $loader->bindtextdomain('phpmyadmin', __DIR__ . '/data/locale/');
236
        $translator = $loader->getTranslator();
237
        self::assertSame(
238
            'Тып',
239
            $translator->gettext('Type'),
240
        );
241
    }
242
243
    public function testDetect(): void
244
    {
245
        $GLOBALS['lang'] = 'foo';
246
        $loader = Loader::getInstance();
247
        self::assertSame(
248
            'foo',
249
            $loader->detectlocale(),
250
        );
251
        unset($GLOBALS['lang']);
252
    }
253
254
    public function testDetectEnv(): void
255
    {
256
        $loader = Loader::getInstance();
257
        foreach (['LC_MESSAGES', 'LC_ALL', 'LANG'] as $var) {
258
            putenv($var);
259
            if (getenv($var) === false) {
260
                continue;
261
            }
262
263
            $this->markTestSkipped('Unsetting environment does not work');
264
        }
265
266
        unset($GLOBALS['lang']);
267
        putenv('LC_ALL=baz');
268
        self::assertSame(
269
            'baz',
270
            $loader->detectlocale(),
271
        );
272
        putenv('LC_ALL');
273
        putenv('LC_MESSAGES=bar');
274
        self::assertSame(
275
            'bar',
276
            $loader->detectlocale(),
277
        );
278
        putenv('LC_MESSAGES');
279
        putenv('LANG=barr');
280
        self::assertSame(
281
            'barr',
282
            $loader->detectlocale(),
283
        );
284
        putenv('LANG');
285
        self::assertSame(
286
            'en',
287
            $loader->detectlocale(),
288
        );
289
    }
290
291
    public function testSetCacheFactory(): void
292
    {
293
        $expected = 'Foo';
294
        $locale = 'be_BY';
295
        $domain = 'apcu';
296
297
        $cache = $this->createMock(CacheInterface::class);
298
        $cache->method('get')
299
            ->willReturn($expected);
300
        /** @var CacheFactoryInterface&MockObject $factory */
301
        $factory = $this->createMock(CacheFactoryInterface::class);
302
        $factory->expects($this->once())
303
            ->method('getInstance')
304
            ->with($this->isInstanceOf(MoParser::class), $locale, $domain)
305
            ->willReturn($cache);
306
307
        Loader::setCacheFactory($factory);
308
        $loader = Loader::getInstance();
309
        $loader->setlocale($locale);
310
        $loader->bindtextdomain($domain, __DIR__ . '/data/locale/');
311
        $translator = $loader->getTranslator($domain);
312
313
        $actual = $translator->gettext('Type');
314
        self::assertSame($expected, $actual);
315
    }
316
}
317