Lines 100.00% 39 / 39
Methods 100.00% 7 / 7
Classes 100.00% 1 / 1
Covered by tests of size
Name Lines Methods CRAP
 __construct 100.00% 1 / 1 100.00% 1 / 1 1
 isLanguageAvailable 100.00% 15 / 15 100.00% 1 / 1 5
 setLanguageWithDetection 100.00% 4 / 4 100.00% 1 / 1 1
 setLanguageFromConfiguration 100.00% 4 / 4 100.00% 1 / 1 1
 setLanguageByAcceptLanguage 100.00% 2 / 2 100.00% 1 / 1 1
 isASupportedLanguage 100.00% 1 / 1 100.00% 1 / 1 2
 getLanguage 100.00% 12 / 12 100.00% 1 / 1 8
33class Language
34{
35    /**
36     * The current language.
37     */
38    public static string $language = '';
39
40    /**
41     * Detector helper.
42     */
43    private LanguageDetector $languageDetector;
44
45    /**
46     * Constructor.
47     */
48    public function __construct(
49        private readonly Configuration $configuration,
50        private readonly SessionInterface $session,
51    ) {
52        $this->languageDetector = new LanguageDetector($this->session);
53    }
54
55    /**
56     * Returns an array of country codes for a specific FAQ record ID,
57     * specific category ID or all languages used by FAQ records, categories.
58     *
59     * @param int    $identifier ID
60     * @param string $table      Specifies table
61     * @return string[]
62     */
63    public function isLanguageAvailable(int $identifier, string $table = 'faqdata'): array
64    {
65        $output = [];
66
67        // Avoid it else: default values for all records, override if identifier is set
68        $distinct = 'DISTINCT ';
69        $where = '';
70        if ($identifier !== 0) {
71            $distinct = '';
72            $where = ' WHERE id = ' . $identifier;
73        }
74
75        // Correct spacing: "SELECT" then optional DISTINCT
76        $query = 'SELECT ' . $distinct . 'lang FROM ' . Database::getTablePrefix() . $table . $where;
77        $result = $this->configuration->getDb()->query($query);
78
79        if ($this->configuration->getDb()->numRows($result) > 0) {
80            while (true) {
81                $row = $this->configuration->getDb()->fetchObject($result);
82                if (!$row) {
83                    break;
84                }
85
86                $output[] = (string) $row->lang;
87            }
88        }
89
90        return $output;
91    }
92
93    /**
94     * Sets language using browser detection combined with config fallback.
95     */
96    public function setLanguageWithDetection(string $configLanguage): string
97    {
98        $detected = $this->languageDetector->detectAllWithBrowser($configLanguage);
99        self::$language = $this->languageDetector->selectLanguage($detected);
100        $this->session->set(name: 'lang', value: self::$language);
101        return strtolower(self::$language);
102    }
103
104    /**
105     * Sets language only from the provided configuration string.
106     */
107    public function setLanguageFromConfiguration(string $configLanguage): string
108    {
109        $detected = $this->languageDetector->detectAllFromConfig($configLanguage);
110        self::$language = $this->languageDetector->selectLanguage($detected);
111        $this->session->set(name: 'lang', value: self::$language);
112        return strtolower(self::$language);
113    }
114
115    public function setLanguageByAcceptLanguage(): string
116    {
117        $this->languageDetector->detectAllWithBrowser(configLanguage: '');
118        return self::$language = $this->languageDetector->getAcceptLanguage();
119    }
120
121    /**
122     * True if the language is supported by the current phpMyFAQ installation.
123     *
124     * @param string|null $langCode Language code
125     */
126    public static function isASupportedLanguage(?string $langCode): bool
127    {
128        return $langCode !== null && LanguageCodes::getSupported($langCode) !== null;
129    }
130
131    /**
132     * Returns the current language.
133     */
134    public function getLanguage(): string
135    {
136        // If the language is not set, try to get it from session or use default
137        if (self::$language === '') {
138            $sessionLang = $this->session->get('lang');
139            if (is_string($sessionLang) && self::isASupportedLanguage($sessionLang)) {
140                self::$language = $sessionLang;
141            }
142
143            if (self::$language === '') {
144                // Try to fall back to the configured default language
145                try {
146                    $defaultLang = $this->configuration->getDefaultLanguage();
147                    self::$language = $defaultLang !== '' && self::isASupportedLanguage($defaultLang)
148                        ? $defaultLang
149                        : 'en';
150                } catch (\Throwable) {
151                    // If configuration is not available or throws an error, use 'en'
152                    self::$language = 'en';
153                }
154            }
155        }
156
157        return strtolower(self::$language);
158    }
159}