forked from geertw/yii2-translatable-url-rule
-
Notifications
You must be signed in to change notification settings - Fork 0
/
TranslatableUrlRule.php
154 lines (125 loc) · 4.45 KB
/
TranslatableUrlRule.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
<?php
namespace geertw\Yii2\TranslatableUrlRule;
use Yii;
use yii\base\InvalidConfigException;
use yii\base\BaseObject;
use yii\web\Request;
use yii\web\UrlManager;
use yii\web\UrlRule;
use yii\web\UrlRuleInterface;
/**
* Class TranslatableUrlRule
* @package geertw\Yii2\TranslatableUrlRule
*/
class TranslatableUrlRule extends BaseObject implements UrlRuleInterface {
/**
* @var string[] URL patterns. Key is language ID
*/
public $patterns;
/**
* @var string Route
*/
public $route;
/**
* @var UrlRule[] Conventional URL rule objects, key is language ID
*/
protected $rules;
/**
* @var string Parameter for determining which language to use (instead of app language)
*/
public $languageParam = 'url-language';
/**
* @var bool If to force search in all language rules
*/
public $forceRuleSearch = false;
/**
* Initialize TranslatableUrlRule
* @throws InvalidConfigException
*/
public function init() {
parent::init();
if ($this->patterns === null || !is_array($this->patterns) || count($this->patterns) == 0) {
throw new InvalidConfigException('TranslatableUrlRule::patterns must be set.');
}
if ($this->route === null) {
throw new InvalidConfigException('TranslatableUrlRule::route must be set.');
}
$this->updateRules();
}
/**
* Update URL rules per language
*/
protected function updateRules() {
foreach ($this->patterns as $language => $pattern) {
$this->rules[$language] = new UrlRule(['pattern' => $pattern, 'route' => $this->route]);
}
}
/**
* Parses the given request and returns the corresponding route and parameters.
* @param UrlManager $manager the URL manager
* @param Request $request the request component
* @return array|bool the parsing result. The route and the parameters are returned as an array.
* If false, it means this rule cannot be used to parse this path info.
*/
public function parseRequest($manager, $request) {
$this->updateRules();
$language = Yii::$app->language;
if (isset($this->rules[$language])) {
$rule = $this->rules[$language];
} else {
// Fall back to first rule:
$rule = array_values($this->rules)[0];
}
$result = $rule->parseRequest($manager, $request);
if (!$result && $this->forceRuleSearch) {
return $this->parseRequestForAllRules($manager, $request, $rule);
}
return $result;
}
/**
* User can change language by typing in URL. Normal case will return 404, but
* we can force the search in all language rules and redirect user to desired page.
*
* @param UrlManager $manager the URL manager
* @param Request $request the request component
* @param UrlRule $parsedRule Url Rule Already parsed
*
* @return array|bool
*/
protected function parseRequestForAllRules($manager, $request, $parsedRule) {
foreach ($this->rules as $rule) {
if ($rule->name == $parsedRule->name) {
continue;
}
$result = $rule->parseRequest($manager, $request);
if ($result) {
list($route, $params) = $result;
array_unshift($params, $route);
Yii::$app->response->redirect($params);
Yii::$app->end();
}
}
return false;
}
/**
* Creates a URL according to the given route and parameters.
* @param UrlManager $manager the URL manager
* @param string $route the route. It should not have slashes at the beginning or the end.
* @param array $params the parameters
* @return string|bool the created URL, or false if this rule cannot be used for creating this URL.
*/
public function createUrl($manager, $route, $params) {
$language = Yii::$app->language;
if (isset($params[$this->languageParam])) {
$language = $params[$this->languageParam];
unset($params[$this->languageParam]);
}
if (isset($this->rules[$language])) {
$rule = $this->rules[$language];
} else {
// Fall back to first rule:
$rule = array_values($this->rules)[0];
}
return $rule->createUrl($manager, $route, $params);
}
}