Completed
Push — master ( 3c8880...e2c218 )
by Dmitry
06:42 queued 02:46
created

LanguageUrlManager::saveLanguageIntoCookie()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 6
c 0
b 0
f 0
nc 1
nop 1
dl 0
loc 9
ccs 0
cts 4
cp 0
crap 2
rs 9.6666
1
<?php
2
3
/*
4
 * HiPanel core package
5
 *
6
 * @link      https://hipanel.com/
7
 * @package   hipanel-core
8
 * @license   BSD-3-Clause
9
 * @copyright Copyright (c) 2014-2016, HiQDev (http://hiqdev.com/)
10
 */
11
12
namespace hipanel\base;
13
14
use Yii;
15
use yii\helpers\Url;
16
use yii\web\Cookie;
17
use yii\web\UrlManager;
18
19
class LanguageUrlManager extends UrlManager
20
{
21
    /**
22
     * @var array list of available language codes. More specific patterns should come first, e.g. 'en_us'
23
     * before 'en'. This can also contain mapping of <url_value> => <language>, e.g. 'english' => 'en'.
24
     */
25
    public $languages = [];
26
27
    /**
28
     * @var string the name of the session key that is used to store the language. Default is '_language'.
29
     */
30
    public $languageSessionKey = '_language';
31
32
    /**
33
     * @var string the name of the language cookie. Default is '_language'.
34
     */
35
    public $languageCookieName = '_language';
36
37
    /**
38
     * @var string the language that was initially set in the application configuration
39
     */
40
    protected $_defaultLanguage;
41
42
    /**
43
     * @var int number of seconds how long the language information should be stored in cookie,
44
     * if `$enableLanguagePersistence` is true. Set to `false` to disable the language cookie completely.
45
     * Default is 30 days.
46
     */
47
    public $languageCookieDuration = 2592000;
48
49
    /**
50
     * @var integer expiration date of the cookie storing the language of the site.
51
     */
52
    public $expireDays = 30;
53
54
    /**
55
     * @var string if a parameter with this name is passed to any `createUrl()` method, the created URL
56
     * will use the language specified there. URLs created this way can be used to switch to a different
57
     * language. If no such parameter is used, the currently detected application language is used.
58
     */
59
    public $languageParam = 'language';
60
61
    /**
62
     * @var \Closure function to execute after changing the language of the site.
63
     */
64
    public $callback;
65
66
    /**
67
     * @var string Name of the cookie.
68
     */
69
    public $cookieName = 'language';
70
71
    /**
72
     * @var \yii\web\Request
73
     */
74
    protected $_request;
75
76
    /**
77
     * {@inheritdoc}
78
     */
79
    public function init()
80
    {
81
        $this->initLanguage();
82
        return parent::init();
83
    }
84
85
    /**
86
     * Setting the language of the site.
87
     */
88
    public function initLanguage()
89
    {
90
        $language = Yii::$app->request->get($this->languageParam);
91
        if ($language) {
92
            if (isset($this->languages[$language])) {
93
                $language = $this->languages[$language];
94
            }
95
            if ($this->_isValidLanguage($language)) {
96
                return $this->saveLanguage($language);
97
            } elseif (!Yii::$app->request->isAjax) {
98
                return $this->_redirect();
99
            }
100
        } elseif (Yii::$app->request->cookies->has($this->cookieName)) {
101
            if ($this->_isValidLanguage(Yii::$app->request->cookies->getValue($this->cookieName))) {
102
                //                Yii::$app->language = Yii::$app->request->cookies->getValue($this->cookieName);
0 ignored issues
show
Unused Code Comprehensibility introduced by
55% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
103
                $this->applyLanguage(Yii::$app->request->cookies->getValue($this->cookieName));
104
                return;
105
            } else {
106
                Yii::$app->response->cookies->remove($this->cookieName);
107
            }
108
        }
109
        $this->detectLanguage();
110
    }
111
112
    /**
113
     * Saving language into cookie and database.
114
     * @param string $language - The language to save.
115
     * @return static
116
     */
117
    public function saveLanguage($language)
118
    {
119
        //        Yii::$app->language = $language;
0 ignored issues
show
Unused Code Comprehensibility introduced by
46% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
120
        $this->applyLanguage($language);
121
        $this->saveLanguageIntoCookie($language);
122
        if (is_callable($this->callback)) {
123
            call_user_func($this->callback);
124
        }
125
        if (Yii::$app->request->isAjax) {
126
            Yii::$app->end();
127
        }
128
        return $this->_redirect();
129
    }
130
131
    /**
132
     * Determine language based on UserAgent.
133
     */
134
    public function detectLanguage()
135
    {
136
        $acceptableLanguages = Yii::$app->getRequest()->getAcceptableLanguages();
137
        foreach ($acceptableLanguages as $language) {
138
            if ($this->_isValidLanguage($language)) {
139
                //                Yii::$app->language = $language;
0 ignored issues
show
Unused Code Comprehensibility introduced by
46% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
140
                $this->applyLanguage($language);
141
                $this->saveLanguageIntoCookie($language);
142
                return;
143
            }
144
        }
145
        foreach ($acceptableLanguages as $language) {
146
            $pattern = preg_quote(substr($language, 0, 2), '/');
147
            foreach ($this->languages as $key => $value) {
148
                if (preg_match('/^' . $pattern . '/', $value) || preg_match('/^' . $pattern . '/', $key)) {
149
                    //                    Yii::$app->language = $this->_isValidLanguage($key) ? $key : $value;
0 ignored issues
show
Unused Code Comprehensibility introduced by
55% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
150
                    $this->applyLanguage($this->_isValidLanguage($key) ? $key : $value);
151
                    $this->saveLanguageIntoCookie(Yii::$app->language);
152
                    return;
153
                }
154
            }
155
        }
156
    }
157
158
    /**
159
     * Save language into cookie.
160
     * @param string $language
161
     */
162
    public function saveLanguageIntoCookie($language)
163
    {
164
        $cookie = new \yii\web\Cookie([
165
            'name' => $this->cookieName,
166
            'value' => $language,
167
            'expire' => time() + 86400 * $this->expireDays,
168
        ]);
169
        Yii::$app->response->cookies->add($cookie);
170
    }
171
172
    /**
173
     * Redirects the browser to the referer URL.
174
     * @return static
175
     */
176
    private function _redirect()
177
    {
178
        $redirect = Yii::$app->request->absoluteUrl === Yii::$app->request->referrer ? '/' : Yii::$app->request->referrer;
179
        return Yii::$app->response->redirect($redirect);
180
    }
181
182
    /**
183
     * Determines whether the language received as a parameter can be processed.
184
     * @param string $language
185
     * @return boolean
186
     */
187
    private function _isValidLanguage($language)
188
    {
189
        return is_string($language) && (isset($this->languages[$language]) || in_array($language, $this->languages, true));
190
    }
191
192
    protected function applyLanguage($language)
193
    {
194
        Yii::$app->language = $language;
195
        Yii::$app->formatter->locale = $language;
196
    }
197
198
199
200
201
//    /**
202
//     * @inheritdoc
203
//     */
204
//    public function parseRequest($request)
205
//    {
206
207
//        $this->detectLanguage($request);
0 ignored issues
show
Unused Code Comprehensibility introduced by
75% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
208
209
//        return parent::parseRequest($request);
0 ignored issues
show
Unused Code Comprehensibility introduced by
62% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
210
//    }
211
212
//    protected function setUpLanguage($language)
0 ignored issues
show
Unused Code Comprehensibility introduced by
45% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
213
//    {
214
//        Yii::$app->language = $language;
215
//    }
216
217
//    /**
0 ignored issues
show
Unused Code Comprehensibility introduced by
48% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
218
//     * Checks for a language or locale parameter in the URL and rewrites the pathInfo if found.
219
//     * If no parameter is found it will try to detect the language from persistent storage (session /
220
//     * cookie) or from browser settings.
221
//     *
222
//     * @var \yii\web\Request $request
223
//     */
224
//    protected function detectLanguage($request)
225
//    {
226
//        $this->_request = $request;
227
//        $pathInfo = $request->getPathInfo();
228
//        $parts = [];
229
//        foreach ($this->languages as $k => $v) {
230
//            $value = is_string($k) ? $k : $v;
231
//            if (substr($value, -2)==='-*') {
232
//                $lng = substr($value, 0, -2);
233
//                $parts[] = "$lng\-[a-z]{2,3}";
234
//                $parts[] = $lng;
235
//            } else {
236
//                $parts[] = $value;
237
//            }
238
//        }
239
//        $pattern = implode('|', $parts);
240
//        if ($request->get($this->languageParam) && preg_match("#^($pattern)\b(/?)#i", $request->get($this->languageParam), $m)) {
241
//            $request->setPathInfo(mb_substr($pathInfo, mb_strlen($m[1].$m[2])));
242
//            $code = $m[1];
243
//            if (isset($this->languages[$code])) {
244
//                // Replace alias with language code
245
//                $language = $this->languages[$code];
246
//            } else {
247
//                list($language,$country) = $this->matchCode($code);
248
//                if ($country!==null) {
249
//                    if ($code==="$language-$country") {
250
//                        $this->redirectToLanguage('');
251
//                    } else {
252
//                        $language = "$language-$country";
253
//                    }
254
//                }
255
//                if ($language===null) {
256
//                    $language = $code;
257
//                }
258
//            }
259
//            Yii::$app->language = $language;
260
//            Yii::$app->session[$this->languageSessionKey] = $language;
261
//            if ($this->languageCookieDuration) {
262
//                $cookie = new Cookie([
263
//                    'name' => $this->languageCookieName,
264
//                    'httpOnly' => true
265
//                ]);
266
//                $cookie->value = $language;
267
//                $cookie->expire = time() + (int) $this->languageCookieDuration;
268
//                Yii::$app->getResponse()->getCookies()->add($cookie);
269
//            }
270
//            $this->redirectToLanguage('');
271
//        } else {
272
//            $language = null;
273
//            $language = Yii::$app->session->get($this->languageSessionKey);
274
//            if ($language===null) {
275
//                $language = $request->getCookies()->getValue($this->languageCookieName);
276
//            }
277
//            if ($language===null) {
278
//                foreach ($request->getAcceptableLanguages() as $acceptable) {
279
//                    list($language,$country) = $this->matchCode($acceptable);
280
//                    if ($language!==null) {
281
//                        $language = $country===null ? $language : "$language-$country";
282
//                        break;
283
//                    }
284
//                }
285
//            }
286
//            if ($language===null || $language===$this->_defaultLanguage) {
287
//                return;
288
//            }
289
//            // #35: Only redirect if a valid language was found
290
//            if ($this->matchCode($language)===[null, null]) {
291
//                return;
292
//            }
293
294
//            $key = array_search($language, $this->languages);
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
295
//            if ($key && is_string($key)) {
296
//                $language = $key;
297
//            }
298
299
//            $this->setUpLanguage($language);
0 ignored issues
show
Unused Code Comprehensibility introduced by
61% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
300
//            $this->redirectToLanguage('');
301
//        }
302
//    }
303
304
//    /**
305
//     * Tests whether the given code matches any of the configured languages.
306
//     *
307
//     * If the code is a single language code, and matches either
308
//     *
309
//     *  - an exact language as configured (ll)
310
//     *  - a language with a country wildcard (ll-*)
311
//     *
312
//     * this language code is returned.
313
//     *
314
//     * If the code also contains a country code, and matches either
315
//     *
316
//     *  - an exact language/country code as configured (ll-CC)
317
//     *  - a language with a country wildcard (ll-*)
318
//     *
319
//     * the code with uppercase country is returned. If only the language part matches
320
//     * a configured language, that language is returned.
321
//     *
322
//     * @param string $code the code to match
323
//     * @return array of [language, country] where both can be null if no match
324
//     */
325
//    protected function matchCode($code)
326
//    {
327
//        $language = $code;
328
//        $country = null;
329
//        $parts = explode('-', $code);
330
//        if (count($parts)===2) {
331
//            $language = $parts[0];
332
//            $country = strtoupper($parts[1]);
333
//        }
334
335
//        if (in_array($code, $this->languages)) {
0 ignored issues
show
Unused Code Comprehensibility introduced by
57% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
336
//            return [$language, $country];
337
//        } elseif (
338
//            $country && in_array("$language-$country", $this->languages) ||
339
//            in_array("$language-*", $this->languages)
340
//        ) {
341
//            return [$language, $country];
342
//        } elseif (in_array($language, $this->languages)) {
343
//            return [$language, null];
344
//        } else {
345
//            return [null, null];
346
//        }
347
//    }
348
349
//    /**
350
//     * Redirect to the current URL with given language code applied
351
//     *
352
//     * @param string $language the language code to add. Can also be empty to not add any language code.
353
//     */
354
//    protected function redirectToLanguage($language)
355
//    {
356
//        // Examples:
357
//        // 1) /baseurl/index.php/some/page?q=foo
358
//        // 2) /baseurl/some/page?q=foo
359
//        // 3)
360
//        // 4) /some/page?q=foo
361
//        if ($this->showScriptName) {
362
//            // 1) /baseurl/index.php
363
//            // 2) /baseurl/index.php
364
//            // 3) /index.php
365
//            // 4) /index.php
366
//            $redirectUrl = $this->_request->getScriptUrl();
367
//        } else {
368
//            // 1) /baseurl
369
//            // 2) /baseurl
370
//            // 3)
371
//            // 4)
372
//            $redirectUrl = $this->_request->getBaseUrl();
373
//        }
374
//        if ($language) {
375
//            $redirectUrl .= '/'.$language;
376
//        }
377
//        // 1) some/page
378
//        // 2) some/page
379
//        // 3)
380
//        // 4) some/page
381
//        $pathInfo = $this->_request->getPathInfo();
382
//        if ($pathInfo) {
383
//            $redirectUrl .= '/'.$pathInfo;
384
//        }
385
//        if ($redirectUrl === '') {
386
//            $redirectUrl = '/';
387
//        }
388
//        // 1) q=foo
389
//        // 2) q=foo
390
//        // 3)
391
//        // 4) q=foo
392
//        $queryString = $this->_request->getQueryString();
393
//        if ($queryString) {
394
//            $redirectUrl .= '?'.$queryString;
395
//        }
396
//        Yii::$app->getResponse()->redirect($redirectUrl);
397
//        if (YII_ENV_TEST) {
398
//            // Response::redirect($url) above will call `Url::to()` internally. So to really
399
//            // test for the same final redirect URL here, we need to call Url::to(), too.
400
//            throw new \yii\base\Exception(\yii\helpers\Url::to($redirectUrl));
401
//        } else {
402
//            Yii::$app->end();
403
//        }
404
//    }
405
}
406