Completed
Push — master ( 01779b...d69358 )
by Dmitry
05:35
created

LanguageSwitcher::detectLanguage()   B

Complexity

Conditions 8
Paths 11

Size

Total Lines 19
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 72

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 8
eloc 11
c 1
b 0
f 1
nc 11
nop 0
dl 0
loc 19
ccs 0
cts 15
cp 0
crap 72
rs 7.7777
1
<?php
2
3
namespace hipanel\components;
4
5
use Yii;
6
use yii\base\BootstrapInterface;
7
use yii\base\Component;
8
use yii\web\Cookie;
9
10
class LanguageSwitcher extends Component implements BootstrapInterface
11
{
12
    /**
13
     * @var string Name of the cookie.
14
     */
15
    public $cookieName = 'language';
16
17
    /**
18
     * @var array list of available language codes. More specific patterns should come first, e.g. 'en_us' before 'en'.
19
     * Key is a language code, value is a name of language. For example:
20
     *
21
     * ```php
22
     * [
23
     *     'ru' => 'Русский',
24
     *     'en' => 'English',
25
     * ]
26
     * ```
27
     *
28
     */
29
    public $languages = [];
30
31
    /**
32
     * @var integer expiration date of the cookie storing the language of the site.
33
     */
34
    public $expireDays = 30;
35
36
    public function bootstrap($app)
37
    {
38
        $this->initLanguage();
39
    }
40
41
    /**
42
     * Saving language into cookie and database.
43
     * @param string $language - The language to save.
44
     * @return static
45
     */
46
    public function saveLanguage($language)
47
    {
48
        $this->applyLanguage($language);
49
        $this->saveLanguageIntoCookie($language);
50
    }
51
52
    private function initLanguage()
53
    {
54
        if ($this->isValidLanguage(Yii::$app->request->cookies->getValue($this->cookieName))) {
55
            $this->applyLanguage(Yii::$app->request->cookies->getValue($this->cookieName));
56
        } else {
57
            Yii::$app->response->cookies->remove($this->cookieName);
58
59
            if (($language = $this->detectLanguage()) !== false) {
60
                $this->saveLanguage($language);
61
            }
62
        }
63
    }
64
65
    /**
66
     * Determine language based on UserAgent.
67
     */
68
    public function detectLanguage()
69
    {
70
        $acceptableLanguages = Yii::$app->getRequest()->getAcceptableLanguages();
71
        foreach ($acceptableLanguages as $language) {
72
            if ($this->isValidLanguage($language)) {
73
                return $language;
74
            }
75
        }
76
        foreach ($acceptableLanguages as $language) {
77
            $pattern = preg_quote(substr($language, 0, 2), '/');
78
            foreach ($this->languages as $key => $value) {
79
                if (preg_match('/^' . $pattern . '/', $value) || preg_match('/^' . $pattern . '/', $key)) {
80
                    return $this->isValidLanguage($key) ? $key : $value;
81
                }
82
            }
83
        }
84
85
        return false;
86
    }
87
88
    /**
89
     * Save language into cookie.
90
     * @param string $language
91
     */
92
    private function saveLanguageIntoCookie($language)
93
    {
94
        $cookie = new Cookie([
95
            'name' => $this->cookieName,
96
            'value' => $language,
97
            'expire' => time() + 86400 * $this->expireDays,
98
        ]);
99
        Yii::$app->response->cookies->add($cookie);
100
    }
101
102
    /**
103
     * Determines whether the language received as a parameter can be processed.
104
     * @param string $language
105
     * @return boolean
106
     */
107
    public function isValidLanguage($language)
108
    {
109
        return is_string($language) && isset($this->languages[$language]);
110
    }
111
112
    /**
113
     * @param $language
114
     * @return bool whether the language is correct and saved
115
     */
116
    public function setLanguage($language)
117
    {
118
        if ($this->isValidLanguage($language)) {
119
            $this->saveLanguage($language);
120
            return true;
121
        }
122
123
        return false;
124
    }
125
126
    /**
127
     * @param string $language
128
     */
129
    private function applyLanguage($language)
130
    {
131
        Yii::$app->language = $language;
132
        Yii::$app->getFormatter()->locale = $language;
133
    }
134
}
135