hiqdev /
yii2-language
This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
| 1 | <?php |
||
| 2 | /** |
||
| 3 | * Yii2 module for language switching. |
||
| 4 | * |
||
| 5 | * @link https://github.com/hiqdev/yii2-language |
||
| 6 | * @package yii2-language |
||
| 7 | * @license BSD-3-Clause |
||
| 8 | * @copyright Copyright (c) 2016-2017, HiQDev (http://hiqdev.com/) |
||
| 9 | */ |
||
| 10 | |||
| 11 | namespace hiqdev\yii2\language; |
||
| 12 | |||
| 13 | use hiqdev\yii2\language\events\LanguageWasChanged; |
||
| 14 | use Yii; |
||
| 15 | use yii\base\BootstrapInterface; |
||
| 16 | use yii\web\Cookie; |
||
| 17 | |||
| 18 | /** |
||
| 19 | * Language Module. |
||
| 20 | * |
||
| 21 | * Example application configuration: |
||
| 22 | * |
||
| 23 | * ```php |
||
| 24 | * 'modules' => [ |
||
| 25 | * 'language' => [ |
||
| 26 | * 'class' => \hiqdev\yii2\language\Module::class, |
||
| 27 | * 'languages' => [ |
||
| 28 | * 'en' => 'English', |
||
| 29 | * 'ru' => 'Русский', |
||
| 30 | * ], |
||
| 31 | * ], |
||
| 32 | * ], |
||
| 33 | * ``` |
||
| 34 | */ |
||
| 35 | class Module extends \yii\base\Module implements BootstrapInterface |
||
| 36 | { |
||
| 37 | /** |
||
| 38 | * @var array list of available language codes. More specific patterns should come first, e.g. 'en_us' before 'en'. |
||
| 39 | * Key is a language code, value is a name of language. For example: |
||
| 40 | * |
||
| 41 | * ```php |
||
| 42 | * [ |
||
| 43 | * 'ru' => 'Русский', |
||
| 44 | * 'en' => 'English', |
||
| 45 | * ] |
||
| 46 | * ``` |
||
| 47 | */ |
||
| 48 | protected $_languages = []; |
||
| 49 | |||
| 50 | public function setLanguages(array $list) |
||
| 51 | { |
||
| 52 | $this->_languages = array_filter($list); |
||
| 53 | } |
||
| 54 | |||
| 55 | public function getLanguages() |
||
| 56 | { |
||
| 57 | if (!$this->_languages) { |
||
|
0 ignored issues
–
show
|
|||
| 58 | $this->_languages = [ |
||
| 59 | Yii::$app->language => Yii::$app->language, |
||
| 60 | ]; |
||
| 61 | } |
||
| 62 | |||
| 63 | return $this->_languages; |
||
| 64 | } |
||
| 65 | |||
| 66 | /** |
||
| 67 | * @var string name of the cookie |
||
| 68 | */ |
||
| 69 | public $cookieName = 'language'; |
||
| 70 | |||
| 71 | /** |
||
| 72 | * @var integer expiration date of the cookie storing the language of the site |
||
| 73 | */ |
||
| 74 | public $expireDays = 30; |
||
| 75 | |||
| 76 | public function bootstrap($app) |
||
| 77 | { |
||
| 78 | $this->initLanguage(); |
||
| 79 | } |
||
| 80 | |||
| 81 | /** |
||
| 82 | * Saving language into cookie and database. |
||
| 83 | * @param string $language - The language to save |
||
| 84 | * @return static |
||
| 85 | */ |
||
| 86 | public function saveLanguage($language): self |
||
| 87 | { |
||
| 88 | $oldLanguage = Yii::$app->language; |
||
| 89 | $this->applyLanguage($language); |
||
| 90 | $this->saveLanguageIntoCookie($language); |
||
| 91 | $this->trigger( |
||
| 92 | LanguageWasChanged::EVENT_NAME, |
||
| 93 | LanguageWasChanged::betweenLanguages($oldLanguage, $language) |
||
| 94 | ); |
||
| 95 | |||
| 96 | return $this; |
||
| 97 | } |
||
| 98 | |||
| 99 | private function initLanguage() |
||
| 100 | { |
||
| 101 | if (($language = Yii::$app->request->get('language')) && $this->isValidLanguage($language)) { |
||
| 102 | $this->saveLanguage($language); |
||
| 103 | } else if ($this->isValidLanguage(Yii::$app->request->cookies->getValue($this->cookieName))) { |
||
| 104 | $this->applyLanguage(Yii::$app->request->cookies->getValue($this->cookieName)); |
||
| 105 | } else { |
||
| 106 | Yii::$app->response->cookies->remove($this->cookieName); |
||
| 107 | |||
| 108 | if (($language = $this->detectLanguage()) !== false) { |
||
| 109 | $this->saveLanguage($language); |
||
| 110 | } |
||
| 111 | } |
||
| 112 | } |
||
| 113 | |||
| 114 | /** |
||
| 115 | * Determine language based on UserAgent. |
||
| 116 | */ |
||
| 117 | public function detectLanguage() |
||
| 118 | { |
||
| 119 | $acceptableLanguages = Yii::$app->getRequest()->getAcceptableLanguages(); |
||
| 120 | foreach ($acceptableLanguages as $language) { |
||
| 121 | if ($this->isValidLanguage($language)) { |
||
| 122 | return $language; |
||
| 123 | } |
||
| 124 | } |
||
| 125 | foreach ($acceptableLanguages as $language) { |
||
| 126 | $pattern = preg_quote(substr($language, 0, 2), '/'); |
||
| 127 | foreach ($this->languages as $key => $value) { |
||
| 128 | if (preg_match('/^' . $pattern . '/', $value) || preg_match('/^' . $pattern . '/', $key)) { |
||
| 129 | return $this->isValidLanguage($key) ? $key : $value; |
||
| 130 | } |
||
| 131 | } |
||
| 132 | } |
||
| 133 | |||
| 134 | return false; |
||
| 135 | } |
||
| 136 | |||
| 137 | /** |
||
| 138 | * Save language into cookie. |
||
| 139 | * @param string $language |
||
| 140 | */ |
||
| 141 | private function saveLanguageIntoCookie($language) |
||
| 142 | { |
||
| 143 | $cookie = new Cookie([ |
||
| 144 | 'name' => $this->cookieName, |
||
| 145 | 'value' => $language, |
||
| 146 | 'expire' => time() + 86400 * $this->expireDays, |
||
| 147 | ]); |
||
| 148 | Yii::$app->response->cookies->add($cookie); |
||
| 149 | } |
||
| 150 | |||
| 151 | /** |
||
| 152 | * Determines whether the language received as a parameter can be processed. |
||
| 153 | * @param string $language |
||
| 154 | * @return boolean |
||
| 155 | */ |
||
| 156 | public function isValidLanguage($language) |
||
| 157 | { |
||
| 158 | return is_string($language) && isset($this->languages[$language]); |
||
| 159 | } |
||
| 160 | |||
| 161 | /** |
||
| 162 | * @param $language |
||
| 163 | * @return bool whether the language is correct and saved |
||
| 164 | */ |
||
| 165 | public function setLanguage($language) |
||
| 166 | { |
||
| 167 | if ($this->isValidLanguage($language)) { |
||
| 168 | $this->saveLanguage($language); |
||
| 169 | |||
| 170 | return true; |
||
| 171 | } |
||
| 172 | |||
| 173 | return false; |
||
| 174 | } |
||
| 175 | |||
| 176 | /** |
||
| 177 | * @param string $language |
||
| 178 | */ |
||
| 179 | 1 | private function applyLanguage($language) |
|
| 180 | { |
||
| 181 | 1 | Yii::$app->language = $language; |
|
| 182 | Yii::$app->getFormatter()->locale = $language; |
||
| 183 | } |
||
| 184 | |||
| 185 | public static $MODULE_ID = 'language'; |
||
| 186 | |||
| 187 | public static function getInstance() |
||
| 188 | { |
||
| 189 | return Yii::$app->getModule(static::$MODULE_ID); |
||
| 190 | } |
||
| 191 | } |
||
| 192 |
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)or! empty(...)instead.