AbstractController   A
last analyzed

Complexity

Total Complexity 27

Size/Duplication

Total Lines 231
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Test Coverage

Coverage 89.19%

Importance

Changes 0
Metric Value
wmc 27
c 0
b 0
f 0
lcom 1
cbo 5
dl 0
loc 231
ccs 66
cts 74
cp 0.8919
rs 10

8 Methods

Rating   Name   Duplication   Size   Complexity  
A parseParameters() 0 15 4
B parseAnnotations() 0 20 8
A getControllerSettings() 0 17 2
A hasAction() 0 4 1
B call() 0 27 3
A getControllerSimpleName() 0 4 1
B addControls() 0 24 5
A redirect() 0 12 3
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();
0 ignored issues
show
Coding Style Compatibility introduced by
The method redirect() contains an exit expression.

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.

Loading history...
251
    }
252
}
253