Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
52.94% covered (warning)
52.94%
18 / 34
66.67% covered (warning)
66.67%
2 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
LanguageFallbacks
52.94% covered (warning)
52.94%
18 / 34
66.67% covered (warning)
66.67%
2 / 3
14.67
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 loadFallbacks
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getFallbacks
50.00% covered (danger)
50.00%
16 / 32
0.00% covered (danger)
0.00%
0 / 1
10.50
1<?php
2/**
3 * @license GPL-2.0-or-later
4 * @file
5 */
6
7namespace Wikimedia\Leximorph\Provider;
8
9use Psr\Log\LoggerInterface;
10use Wikimedia\Leximorph\Util\JsonLoader;
11
12/**
13 * Provides functionality to retrieve fallback language codes for a given language.
14 *
15 * @since     1.45
16 * @author    Doğu Abaris (abaris@null.net)
17 */
18class LanguageFallbacks {
19
20    /**
21     * Path to the fallback language mappings JSON file.
22     */
23    private const FALLBACKS_PATH = __DIR__ . '/../data/language-fallback-mappings.json';
24
25    /**
26     * The fallback language codes for this instance's language.
27     *
28     * @var string[]|null
29     */
30    private ?array $fallbacks = null;
31
32    /**
33     * Initializes the LanguageFallbacks.
34     *
35     * @param string $langCode The language code.
36     * @param LoggerInterface $logger The logger instance to use.
37     * @param JsonLoader $jsonLoader The json loader to load data.
38     *
39     * @since 1.45
40     */
41    public function __construct(
42        private readonly string $langCode,
43        private readonly LoggerInterface $logger,
44        private readonly JsonLoader $jsonLoader,
45    ) {
46    }
47
48    /**
49     * Loads the fallback mappings from the JSON file.
50     *
51     * @since 1.45
52     * @return array<int|string, mixed> The entire fallback mapping.
53     */
54    private function loadFallbacks(): array {
55        return $this->jsonLoader->load( self::FALLBACKS_PATH, 'language fallback mappings' );
56    }
57
58    /**
59     * Returns fallback language codes for the instance's language code.
60     *
61     * @since 1.45
62     * @return string[] Fallback language codes.
63     */
64    public function getFallbacks(): array {
65        if ( $this->fallbacks === null ) {
66            $allFallbacks = $this->loadFallbacks();
67
68            $langNode = $allFallbacks[$this->langCode] ?? null;
69            $this->fallbacks = [];
70
71            if ( !is_array( $langNode ) ) {
72                $this->logger->warning(
73                    'Language fallback node missing or invalid.',
74                    [ 'langCode' => $this->langCode, 'type' => gettype( $langNode ) ]
75                );
76                return $this->fallbacks;
77            }
78
79            $fallbackValues = $langNode['values'] ?? null;
80
81            if ( !is_array( $fallbackValues ) ) {
82                $this->logger->warning(
83                    'Language fallback values missing or invalid.',
84                    [
85                        'langCode' => $this->langCode,
86                        'type' => gettype( $fallbackValues ),
87                    ]
88                );
89                return $this->fallbacks;
90            }
91
92            foreach ( $fallbackValues as $index => $value ) {
93                if ( is_string( $value ) ) {
94                    $this->fallbacks[] = $value;
95                } else {
96                    $this->logger->warning(
97                        'Invalid fallback value. Expected string, got {type}.',
98                        [
99                            'type' => gettype( $value ),
100                            'langCode' => $this->langCode,
101                            'index' => $index,
102                        ]
103                    );
104                }
105            }
106        }
107
108        return $this->fallbacks;
109    }
110}