1
|
|
|
<?php |
2
|
|
|
namespace Nkey\Caribu\Mvc\Controller; |
3
|
|
|
|
4
|
|
|
use \Nkey\Caribu\Mvc\View\View; |
5
|
|
|
use Nkey\Caribu\Mvc\View\Control; |
6
|
|
|
use Nkey\Caribu\Mvc\Application; |
7
|
|
|
|
8
|
|
|
/** |
9
|
|
|
* Basic controller functionality |
10
|
|
|
* |
11
|
|
|
* This class provides the basic functionality each controller |
12
|
|
|
* needs to work correctly. |
13
|
|
|
* |
14
|
|
|
* The controller call will be performed by Application::serve(). |
15
|
|
|
* |
16
|
|
|
* All basic functions are final and cannot be overriden. |
17
|
|
|
* |
18
|
|
|
* @author Maik Greubel <[email protected]> |
19
|
|
|
* |
20
|
|
|
* This file is part of Caribu MVC package |
21
|
|
|
*/ |
22
|
|
|
abstract class AbstractController |
23
|
|
|
{ |
24
|
|
|
|
25
|
|
|
/** |
26
|
|
|
* Class of controller |
27
|
|
|
* |
28
|
|
|
* @var string |
29
|
|
|
*/ |
30
|
|
|
private $controllerClass = ''; |
31
|
|
|
|
32
|
|
|
/** |
33
|
|
|
* Name of controller |
34
|
|
|
* |
35
|
|
|
* @var string |
36
|
|
|
*/ |
37
|
|
|
private $controllerName = ''; |
38
|
|
|
|
39
|
|
|
/** |
40
|
|
|
* List of actions provided by controller |
41
|
|
|
* |
42
|
|
|
* @var array |
43
|
|
|
*/ |
44
|
|
|
private $actions = null; |
45
|
|
|
|
46
|
|
|
/** |
47
|
|
|
* Request |
48
|
|
|
* |
49
|
|
|
* @var \Nkey\Caribu\Mvc\Controller\Request |
50
|
|
|
*/ |
51
|
|
|
private $request; |
52
|
|
|
|
53
|
|
|
/** |
54
|
|
|
* Response |
55
|
|
|
* |
56
|
|
|
* @var \Nkey\Caribu\Mvc\Controller\Response |
57
|
|
|
*/ |
58
|
|
|
protected $response; |
59
|
|
|
|
60
|
|
|
/** |
61
|
|
|
* View parameters |
62
|
|
|
* |
63
|
|
|
* @var array |
64
|
|
|
*/ |
65
|
|
|
protected $viewParams = array(); |
66
|
|
|
|
67
|
|
|
/** |
68
|
|
|
* Parse the parameters of action |
69
|
|
|
* |
70
|
|
|
* @param \ReflectionMethod $action |
71
|
|
|
* |
72
|
|
|
* @return boolean true if parameters meets conditions for a valid action method, false otherwise |
73
|
|
|
*/ |
74
|
29 |
|
private function parseParameters(\ReflectionMethod $action) |
75
|
|
|
{ |
76
|
29 |
|
$params = $action->getParameters(); |
77
|
29 |
|
if (count($params) < 1) { |
78
|
22 |
|
return false; |
79
|
|
|
} |
80
|
|
|
|
81
|
29 |
|
$param = $params[0]; |
82
|
29 |
|
assert($param instanceof \ReflectionParameter); |
83
|
29 |
|
if (! ($class = $param->getClass()) || $class->getName() != 'Nkey\Caribu\Mvc\Controller\Request') { |
84
|
22 |
|
return false; |
85
|
|
|
} |
86
|
|
|
|
87
|
29 |
|
return true; |
88
|
|
|
} |
89
|
|
|
|
90
|
|
|
/** |
91
|
|
|
* Parse the settings out of annotations |
92
|
|
|
* |
93
|
|
|
* @param \ReflectionMethod $action |
94
|
|
|
*/ |
95
|
29 |
|
private function parseAnnotations(\ReflectionMethod $action) |
96
|
|
|
{ |
97
|
29 |
|
if ($action->isConstructor() || $action->isDestructor() || $action->isStatic() || $action->isFinal()) { |
98
|
29 |
|
return; |
99
|
|
|
} |
100
|
|
|
|
101
|
29 |
|
$rfMethod = new \ReflectionMethod($this, $action->name); |
102
|
29 |
|
$anno = $rfMethod->getDocComment(); |
103
|
|
|
|
104
|
29 |
|
if ($anno && preg_match('#@webMethod#', $anno)) { |
105
|
29 |
|
$this->actions[] = $action->name; |
106
|
29 |
|
return; |
107
|
|
|
} |
108
|
|
|
|
109
|
29 |
|
if (! $this->parseParameters($action)) { |
110
|
22 |
|
return; |
111
|
|
|
} |
112
|
|
|
|
113
|
29 |
|
$this->actions[] = $action->name; |
114
|
29 |
|
} |
115
|
|
|
|
116
|
|
|
/** |
117
|
|
|
* Get the controller prepared for service |
118
|
|
|
* |
119
|
|
|
* @return \Nkey\Caribu\Mvc\Controller\AbstractController The controller instance |
120
|
|
|
*/ |
121
|
29 |
|
final public function getControllerSettings() |
122
|
|
|
{ |
123
|
29 |
|
$rf = new \ReflectionClass($this); |
124
|
|
|
|
125
|
29 |
|
$this->response = new Response(); |
126
|
29 |
|
$this->controllerClass = $rf->getShortName(); |
127
|
29 |
|
$this->controllerName = ucfirst(str_replace('Controller', '', $this->controllerClass)); |
128
|
29 |
|
$this->response->setTitle($this->controllerName); |
129
|
|
|
|
130
|
29 |
|
$actions = $rf->getMethods(\ReflectionMethod::IS_PUBLIC); |
131
|
|
|
|
132
|
29 |
|
foreach ($actions as $action) { |
133
|
29 |
|
$this->parseAnnotations($action); |
134
|
|
|
} |
135
|
|
|
|
136
|
29 |
|
return $this; |
137
|
|
|
} |
138
|
|
|
|
139
|
|
|
/** |
140
|
|
|
* Checks whether controller has specific action |
141
|
|
|
* |
142
|
|
|
* @param string $action |
143
|
|
|
* Name of action to search for |
144
|
|
|
* |
145
|
|
|
* @return boolean true if the action exists in controller, false otherwise |
146
|
|
|
*/ |
147
|
19 |
|
final public function hasAction($action) |
148
|
|
|
{ |
149
|
19 |
|
return array_search($action, $this->actions) !== false; |
150
|
|
|
} |
151
|
|
|
|
152
|
|
|
/** |
153
|
|
|
* Call the action |
154
|
|
|
* |
155
|
|
|
* @param string $action |
156
|
|
|
* The name of action to call in controller |
157
|
|
|
* |
158
|
|
|
* @return \Nkey\Caribu\Mvc\Controller\Response The response |
159
|
|
|
*/ |
160
|
20 |
|
final public function call($action, Request $request, View $view) |
161
|
|
|
{ |
162
|
20 |
|
$this->request = $request; |
163
|
|
|
|
164
|
20 |
|
ob_start(); |
165
|
|
|
|
166
|
20 |
|
$rf = new \ReflectionMethod($this, $action); |
167
|
|
|
|
168
|
20 |
|
$anno = $rf->getDocComment(); |
169
|
20 |
|
$matches = array(); |
170
|
20 |
|
if (preg_match('#@responseType ([\w\/]+)#', $anno, $matches)) { |
171
|
2 |
|
$this->response->setType($matches[1]); |
172
|
|
|
} |
173
|
|
|
|
174
|
20 |
|
if (preg_match('#@title ([^\\n]+)#', $anno, $matches)) { |
175
|
3 |
|
$this->response->setTitle($matches[1]); |
176
|
|
|
} |
177
|
|
|
|
178
|
20 |
|
$rf->invoke($this, $this->request); |
179
|
|
|
|
180
|
20 |
|
$this->response->appendBody(ob_get_clean()); |
181
|
|
|
|
182
|
20 |
|
$view->render($this->response, $request, $this->viewParams); |
183
|
20 |
|
$this->addControls($this->response, $request, $view); |
184
|
|
|
|
185
|
20 |
|
return $this->response; |
186
|
|
|
} |
187
|
|
|
|
188
|
|
|
/** |
189
|
|
|
* Retrieve the simple name of controller |
190
|
|
|
* |
191
|
|
|
* @return string Name of controller |
192
|
|
|
*/ |
193
|
29 |
|
final public function getControllerSimpleName() |
194
|
|
|
{ |
195
|
29 |
|
return $this->controllerName; |
196
|
|
|
} |
197
|
|
|
|
198
|
|
|
/** |
199
|
|
|
* Add the controls injected into view parameters |
200
|
|
|
* |
201
|
|
|
* @param Response $response |
202
|
|
|
* The response rendered with controls |
203
|
|
|
* @param Request $request |
204
|
|
|
* The request |
205
|
|
|
* @param View $view |
206
|
|
|
* The View instance to use for rendering |
207
|
|
|
*/ |
208
|
20 |
|
protected function addControls(Response &$response, Request $request, View $view) |
209
|
|
|
{ |
210
|
20 |
|
$matches = array(); |
211
|
|
|
|
212
|
20 |
|
while (preg_match("/\{(\w+)=(\w+)\}/", $response->getBody(), $matches)) { |
213
|
3 |
|
$controlIdentifier = $matches[1]; |
214
|
3 |
|
$controlName = $matches[2]; |
215
|
3 |
|
$currentBody = $response->getBody(); |
216
|
|
|
|
217
|
3 |
|
if (! isset($this->viewParams[$controlIdentifier][$controlName]) |
218
|
3 |
|
|| ! $view->hasControl($controlIdentifier)) { |
219
|
1 |
|
$response->setBody(str_replace($matches[0], '', $currentBody)); |
220
|
1 |
|
continue; |
221
|
|
|
} |
222
|
|
|
|
223
|
2 |
|
if ($this->viewParams[$controlIdentifier][$controlName] instanceof Control) { |
224
|
1 |
|
$repl = $this->viewParams[$controlIdentifier][$controlName]->render($request); |
225
|
|
|
} else { |
226
|
1 |
|
$control = $view->createControl($controlIdentifier); |
227
|
1 |
|
$repl = $control->render($request, $this->viewParams[$controlIdentifier][$controlName]); |
228
|
|
|
} |
229
|
2 |
|
$response->setBody(str_replace($matches[0], $repl, $currentBody)); |
230
|
|
|
} |
231
|
20 |
|
} |
232
|
|
|
|
233
|
|
|
/** |
234
|
|
|
* Redirects the current request to another site |
235
|
|
|
* |
236
|
|
|
* @param string $controller |
237
|
|
|
* The name of Controller to |
238
|
|
|
* @param string $action |
239
|
|
|
*/ |
240
|
|
|
protected function redirect($controller = null, $action = null) |
241
|
|
|
{ |
242
|
|
|
if (null === $controller) { |
243
|
|
|
$controller = Application::getInstance()->getDefaultController(); |
244
|
|
|
} |
245
|
|
|
if (null === $action) { |
246
|
|
|
$action = Application::getInstance()->getDefaultAction(); |
247
|
|
|
} |
248
|
|
|
$destination = sprintf("Location: %s%s/%s", $this->request->getContextPrefix(), $controller, $action); |
249
|
|
|
header($destination); |
250
|
|
|
exit(); |
|
|
|
|
251
|
|
|
} |
252
|
|
|
} |
253
|
|
|
|
An exit expression should only be used in rare cases. For example, if you write a short command line script.
In most cases however, using an
exit
expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.