CompositeUrlRule.php
4.36 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
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
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\web;
use Yii;
use yii\base\Object;
/**
* CompositeUrlRule is the base class for URL rule classes that consist of multiple simpler rules.
*
* @property null|int $createUrlStatus Status of the URL creation after the last [[createUrl()]] call. `null`
* if rule does not provide info about create status. This property is read-only.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
abstract class CompositeUrlRule extends Object implements UrlRuleInterface
{
/**
* @var UrlRuleInterface[] the URL rules contained in this composite rule.
* This property is set in [[init()]] by the return value of [[createRules()]].
*/
protected $rules = [];
/**
* @var int|null status of the URL creation after the last [[createUrl()]] call.
* @since 2.0.12
*/
protected $createStatus;
/**
* Creates the URL rules that should be contained within this composite rule.
* @return UrlRuleInterface[] the URL rules
*/
abstract protected function createRules();
/**
* @inheritdoc
*/
public function init()
{
parent::init();
$this->rules = $this->createRules();
}
/**
* @inheritdoc
*/
public function parseRequest($manager, $request)
{
foreach ($this->rules as $rule) {
/* @var $rule UrlRule */
$result = $rule->parseRequest($manager, $request);
if (YII_DEBUG) {
Yii::trace([
'rule' => method_exists($rule, '__toString') ? $rule->__toString() : get_class($rule),
'match' => $result !== false,
'parent' => self::className()
], __METHOD__);
}
if ($result !== false) {
return $result;
}
}
return false;
}
/**
* @inheritdoc
*/
public function createUrl($manager, $route, $params)
{
$this->createStatus = UrlRule::CREATE_STATUS_SUCCESS;
$url = $this->iterateRules($this->rules, $manager, $route, $params);
if ($url !== false) {
return $url;
}
if ($this->createStatus === UrlRule::CREATE_STATUS_SUCCESS) {
// create status was not changed - there is no rules configured
$this->createStatus = UrlRule::CREATE_STATUS_PARSING_ONLY;
}
return false;
}
/**
* Iterates through specified rules and calls [[createUrl()]] for each of them.
*
* @param UrlRuleInterface[] $rules rules to iterate.
* @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 bool|string the created URL, or `false` if none of specified rules cannot be used for creating this URL.
* @see createUrl()
* @since 2.0.12
*/
protected function iterateRules($rules, $manager, $route, $params)
{
/* @var $rule UrlRule */
foreach ($rules as $rule) {
$url = $rule->createUrl($manager, $route, $params);
if ($url !== false) {
$this->createStatus = UrlRule::CREATE_STATUS_SUCCESS;
return $url;
}
if (
$this->createStatus === null
|| !method_exists($rule, 'getCreateUrlStatus')
|| $rule->getCreateUrlStatus() === null
) {
$this->createStatus = null;
} else {
$this->createStatus |= $rule->getCreateUrlStatus();
}
}
return false;
}
/**
* Returns status of the URL creation after the last [[createUrl()]] call.
*
* For multiple rules statuses will be combined by bitwise `or` operator
* (e.g. `UrlRule::CREATE_STATUS_PARSING_ONLY | UrlRule::CREATE_STATUS_PARAMS_MISMATCH`).
*
* @return null|int Status of the URL creation after the last [[createUrl()]] call. `null` if rule does not provide
* info about create status.
* @see $createStatus
* @see http://php.net/manual/en/language.operators.bitwise.php
* @since 2.0.12
*/
public function getCreateUrlStatus()
{
return $this->createStatus;
}
}