NodeUrlRule.php
4.35 KB
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
<?php
class NodeUrlRule extends CBaseUrlRule
{
public $rules = array();
public $langExpression = '(en|ru)';
public $langVar = 'lang';
public $nodeVar = 'node_id';
/**
* Creates a URL based on this rule.
* @param CUrlManager $manager the manager
* @param string $route the route
* @param array $params list of parameters (name=>value) associated with the route
* @param string $ampersand the token separating name-value pairs in the URL.
* @return mixed the constructed URL. False if this rule does not apply.
*/
public function createUrl($manager, $route, $params, $ampersand)
{
if (!isset($params[$this->nodeVar])) return false;
/** @var $node Node */
$node = Node::model()->findByPk($params[$this->nodeVar]);
if (empty($node)) return false;
if (!isset($this->rules[$node->data_type])) return false;
foreach ($this->rules[$node->data_type] as $k => $v) {
if (is_string($k) && is_string($v)) {
$rule = new CUrlRule($v, $k);
$this->rules[$node->data_type][$k] = $rule;
} else {
$rule = $v;
}
$newParams = $params;
unset($newParams[$this->langVar]);
unset($newParams[$this->nodeVar]);
$url = $rule->createUrl($manager, $route, $newParams, $ampersand);
if ($url !== false) {
$path = "/{$node->link}";
for ($t = $node; $t->node_id != null; $t = $t->node) {
$path = "/{$t->node->link}{$path}";
}
return "{$params[$this->langVar]}{$path}/{$url}";
}
}
return false;
}
/**
* Parses a URL based on this rule.
* @param CUrlManager $manager the URL manager
* @param CHttpRequest $request the request object
* @param string $pathInfo path info part of the URL (URL suffix is already removed based on {@link CUrlManager::urlSuffix})
* @param string $rawPathInfo path info that contains the potential URL suffix
* @return mixed the route that consists of the controller ID and action ID. False if this rule does not apply.
*/
public function parseUrl($manager, $request, $pathInfo, $rawPathInfo)
{
//$rawPathInfo = $request->getPathInfo();
//$pathInfo = $rawPathInfo;
preg_match("#^{$this->langExpression}#", $pathInfo, $langMatches);
if (0 == count($langMatches)) return false;
$lang = $langMatches[0];
//subtract lang prefix
$pathInfo = substr($pathInfo, strlen($lang) + 1);
//subtract at least one node link
$nodes = array();
/** @var $node Node|null */
while (true) {
preg_match('#^([^\/]+)#', $pathInfo, $matches);
if (0 == count($matches)) break;
$link = $matches[0];
$nodeCriteria = new CDbCriteria();
$nodeCriteria->compare('link', $link);
if (!empty($node)) {
$nodeCriteria->compare('node_id', $node->id);
} else {
$nodeCriteria->addCondition('node_id is null');
}
$node = Node::model()->find($nodeCriteria);
if (empty($node)) break;
$nodes[] = $node;
if (strlen($link) == strlen($pathInfo)) {
$pathInfo = '';
break;
}
if ($pathInfo[strlen($link)] == '/') {
$pathInfo = substr($pathInfo, strlen($link) + 1);
} else {
$pathInfo = substr($pathInfo, strlen($link));
}
}
if (0 == count($nodes)) return false; // no matching nodes
$node = end($nodes);
if (!isset($this->rules[$node->data_type])) return false; //no rules for type
//parse rest
foreach ($this->rules[$node->data_type] as $k => $v) {
if (is_string($k) && is_string($v)) {
$rule = new CUrlRule($v, $k);
$this->rules[$node->data_type][$k] = $rule;
} else {
$rule = $v;
}
$route = $rule->parseUrl($manager, $request, $pathInfo, $pathInfo);
if ($route !== false) {
$_GET[$this->langVar] = $lang;
$_GET[$this->nodeVar] = $node->id;
return $route;
}
}
return false;
}
}