GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Pull Request — master (#4)
by Felix
01:39
created

AbstractController   A

Complexity

Total Complexity 35

Size/Duplication

Total Lines 293
Duplicated Lines 5.46 %

Coupling/Cohesion

Components 1
Dependencies 8

Test Coverage

Coverage 98.95%

Importance

Changes 0
Metric Value
wmc 35
lcom 1
cbo 8
dl 16
loc 293
ccs 94
cts 95
cp 0.9895
rs 9.6
c 0
b 0
f 0

14 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 10 1
A init() 0 3 1
A preDispatch() 0 4 1
A setAutoRenderView() 0 4 1
A setAutoRenderViewScript() 0 4 1
A dispatch() 0 24 3
B getCollectedDispatchArgs() 0 36 9
A getDispatchResponse() 0 21 5
A getAutoRenderViewScriptName() 0 6 1
A postDispatch() 0 3 1
A forward() 0 20 4
A getUrl() 0 16 3
A get() 8 8 2
A post() 8 8 2

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
/**
3
 * Starlit App.
4
 *
5
 * @copyright Copyright (c) 2016 Starweb AB
6
 * @license   BSD 3-Clause
7
 */
8
9
namespace Starlit\App;
10
11
use Symfony\Component\HttpFoundation\Request;
12
use Symfony\Component\HttpFoundation\Response;
13
use Symfony\Component\Routing;
14
use Starlit\Utils\Str;
15
use Starlit\Utils\Url;
16
17
/**
18
 * Base action controller.
19
 *
20
 * @author Andreas Nilsson <http://github.com/jandreasn>
21
 */
22
abstract class AbstractController
23
{
24
    /**
25
     * @var BaseApp
26
     */
27
    protected $app;
28
29
    /**
30
     * @var Request
31
     */
32
    protected $request;
33
34
    /**
35
     * @var View
36
     */
37
    protected $view;
38
39
    /**
40
     * @var bool
41
     */
42
    protected $autoRenderView = true;
43
44
    /**
45
     * @var string
46
     */
47
    protected $autoRenderViewScript;
48
49
    /**
50
     * Constructor.
51
     *
52
     * @param BaseApp $app
53
     * @param Request $request
54
     */
55 19
    final public function __construct(BaseApp $app, Request $request)
0 ignored issues
show
Bug introduced by
You have injected the Request via parameter $request. This is generally not recommended as there might be multiple instances during a request cycle (f.e. when using sub-requests). Instead, it is recommended to inject the RequestStack and retrieve the current request each time you need it via getCurrentRequest().
Loading history...
56
    {
57 19
        $this->app = $app;
58 19
        $this->request = $request;
59
60 19
        $this->view = $this->app->getNew(ViewInterface::class);
61 19
        $this->view->setRequest($this->request);
62
63 19
        $this->init();
64 19
    }
65
66
    /**
67
     * Initialization method meant to be overridden in descendant classes (optional).
68
     */
69 19
    protected function init()
70
    {
71 19
    }
72
73
    /**
74
     * Pre dispatch method meant to be overridden in descendant classes (optional).
75
     *
76
     * This method is called right before the actual action method is called/dispatched.
77
     * Override this instead of init() if access to dispatch properties is required (like
78
     * action name) or you need to return a response.
79
     *
80
     * @param string $action
81
     * @return Response|null
82
     */
83 8
    protected function preDispatch($action)
0 ignored issues
show
Unused Code introduced by
The parameter $action is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
84
    {
85 8
        return null;
86
    }
87
88
    /**
89
     * @param bool $autoRenderView
90
     */
91 2
    public function setAutoRenderView($autoRenderView)
92
    {
93 2
        $this->autoRenderView = $autoRenderView;
94 2
    }
95
96
    /**
97
     * @param string $autoRenderViewScript
98
     */
99 1
    public function setAutoRenderViewScript($autoRenderViewScript)
100
    {
101 1
        $this->autoRenderViewScript = $autoRenderViewScript;
102 1
    }
103
104
    /**
105
     * Dispatch the requested action
106
     *
107
     * @param string|null $action action id/name (lowercase, - word separation)
108
     * @param array       $actionArgs
109
     * @return Response
110
     * @throws Routing\Exception\ResourceNotFoundException
111
     */
112 11
    public function dispatch($action = null, array $actionArgs = [])
113
    {
114
        // If not special action is provided, try to get from request
115 11
        $router = $this->app->get(RouterInterface::class);
116 11
        $action = Str::camelToSeparator(
117 11
            $action ?: $router->getRequestAction($this->request),
118 11
            '-'
119
        );
120 11
        $actionMethod = $router->getActionMethod($action);
121 11
        $collectedArgs = $this->getCollectedDispatchArgs($actionMethod, $actionArgs);
122
123
        // Call pre dispatch method and return it's response if there is one (uncommon)
124 8
        $preDispatchResponse = $this->preDispatch($action);
125 8
        if ($preDispatchResponse instanceof Response) {
126 1
            return $preDispatchResponse;
127
        }
128
129
        // Call action method
130 7
        $actionResponse = \call_user_func_array([$this, $actionMethod], $collectedArgs);
131
132 7
        $this->postDispatch();
133
134 7
        return $this->getDispatchResponse($action, $actionResponse);
135
    }
136
137
    /**
138
     * @param string $actionMethod
139
     * @param array $actionArgs
140
     * @return array
141
     * @throws Routing\Exception\ResourceNotFoundException
142
     */
143 11
    protected function getCollectedDispatchArgs($actionMethod, array $actionArgs = [])
144
    {
145
        // Check that method is a valid action method
146
        try {
147 11
            $reflectionMethod = new \ReflectionMethod($this, $actionMethod);
148 10
            if (!$reflectionMethod->isPublic() || $reflectionMethod->isConstructor()) {
149 1
                throw new Routing\Exception\ResourceNotFoundException(
150 10
                    "\"{$actionMethod}\" is not a valid action method."
151
                );
152
            }
153 2
        } catch (\ReflectionException $e) {
154 1
            throw new Routing\Exception\ResourceNotFoundException("\"{$actionMethod}\" action method does not exist.");
155
        }
156
157
158
        // Get action arguments from request or method default values.
159
        // Throws an exception if arguments are not provided.
160 9
        $collectedArgs = [];
161 9
        foreach ($reflectionMethod->getParameters() as $param) {
162 2
            if (array_key_exists($param->name, $actionArgs)) {
163 1
                $collectedArgs[] = $actionArgs[$param->name];
164 2
            } elseif ($this->request->attributes->has($param->name)) {
165 1
                $collectedArgs[] = $this->request->attributes->get($param->name);
166 2
            } elseif ($param->isDefaultValueAvailable()) {
167 1
                $collectedArgs[] = $param->getDefaultValue();
168 1
            } elseif ($param->getClass()) {
169
                $collectedArgs[] = $this->app->resolveInstance($param->getClass()->getName());
170
            } else {
171 1
                throw new \LogicException(
172 2
                    "Action method \"{$actionMethod}\" requires that you provide a value for the \"\${$param->name}\""
173
                );
174
            }
175
        }
176
177 8
        return $collectedArgs;
178
    }
179
180
    /**
181
     * @param string $action
182
     * @param mixed $actionResponse
183
     * @return Response
184
     */
185 7
    protected function getDispatchResponse($action, $actionResponse)
186
    {
187 7
        if ($actionResponse instanceof Response) {
188 4
            return $actionResponse->prepare($this->request);
189 3
        } elseif ($actionResponse !== null) {
190 1
            return $this->app->get(Response::class)->setContent((string) $actionResponse)->prepare($this->request);
191 2
        } elseif ($this->autoRenderView) {
192 1
            $viewScript = $this->autoRenderViewScript ?: $this->getAutoRenderViewScriptName(
193 1
                $action,
194 1
                $this->app->get(RouterInterface::class)->getRequestController($this->request),
195 1
                $this->app->get(RouterInterface::class)->getRequestModule($this->request)
196
            );
197
198 1
            return $this->app->get(Response::class)->setContent($this->view->render($viewScript, true))
199 1
                ->prepare($this->request);
200
        } else {
201
            // Empty response if no other response is set
202 1
            return $this->app->get(Response::class)->setContent('')
203 1
                ->prepare($this->request);
204
        }
205
    }
206
207
    /**
208
     * @param string      $action
209
     * @param string      $controller
210
     * @param string|null $module
211
     * @return string
212
     */
213 1
    public function getAutoRenderViewScriptName($action, $controller, $module = null)
214
    {
215 1
        $viewScriptName = implode('/', array_filter([$module, $controller, $action]));
216
217 1
        return $viewScriptName;
218
    }
219
220
    /**
221
     * Post dispatch method meant to be overridden in descendant classes (optional).
222
     * This method is called right after an action method has returned it's response,
223
     * but before the dispatch method returns the response.
224
     */
225 7
    protected function postDispatch()
226
    {
227 7
    }
228
229
    /**
230
     * Forwards request to another action and/or controller
231
     *
232
     * @param string      $action     Action name as lowercase separated string
233
     * @param string|null $controller Controller name as lowercase separated string
234
     * @param string|null $module     Module name as lowercase separated string
235
     * @param array       $actionArgs
236
     * @return Response
237
     */
238 3
    protected function forward($action, $controller = null, $module = null, array $actionArgs = [])
239
    {
240
        // Forward inside same controller (easy)
241 3
        if (empty($controller)) {
242 1
            return $this->dispatch($action, $actionArgs);
243
        // Forward to another controller
244
        } else {
245 2
            $router = $this->app->get(RouterInterface::class);
246 2
            $controller = $controller ?: $router->getRequestController($this->request);
247 2
            $module = $module ?: $router->getRequestModule($this->request);
248
249 2
            $controllerClass = $router->getControllerClass($controller, $module);
250 2
            $actualController = new $controllerClass($this->app, $this->request);
251
252
            // Set new request properties
253 2
            $this->request->attributes->add(compact('module', 'controller', 'action'));
254
255 2
            return $actualController->dispatch($action, $actionArgs);
256
        }
257
    }
258
259
    /**
260
     * Get current or a new url merged with provided parameters.
261
     *
262
     * @param string $relativeUrl
263
     * @param array  $parameters
264
     * @return string
265
     */
266 2
    protected function getUrl($relativeUrl = null, array $parameters = [])
267
    {
268
        // Make an absolute url of a new one url, or use the current one if none is provided
269 2
        if ($relativeUrl !== null) {
270 1
            $url = $this->request->getSchemeAndHttpHost() . $relativeUrl;
271
        } else {
272 1
            $url = $this->request->getSchemeAndHttpHost() . $this->request->getRequestUri();
273
        }
274
275 2
        if ($parameters) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $parameters of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
276 1
            $mergedParameters = array_merge($this->get(), $parameters);
277 1
            $url = (string) (new Url($url))->addQueryParameters($mergedParameters);
278
        }
279
280 2
        return $url;
281
    }
282
283
    /**
284
     * Shortcut method to access GET/query parameters.
285
     *
286
     * @param string $key
287
     * @param mixed  $default
288
     * @return string|array
289
     */
290 2 View Code Duplication
    protected function get($key = null, $default = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
291
    {
292 2
        if ($key === null) {
293 2
            return $this->request->query->all();
294
        }
295
296 1
        return $this->request->query->get($key, $default);
297
    }
298
299
    /**
300
     * Shortcut method to access POST/request parameters.
301
     *
302
     * @param string $key
303
     * @param mixed  $default
304
     * @return string|array
305
     */
306 1 View Code Duplication
    protected function post($key = null, $default = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
307
    {
308 1
        if ($key === null) {
309 1
            return $this->request->request->all();
310
        }
311
312 1
        return $this->request->request->get($key, $default);
313
    }
314
}
315