Test Failed
Pull Request — master (#19)
by Flo
02:58
created

AbstractController::route()   C

Complexity

Conditions 7
Paths 21

Size

Total Lines 48
Code Lines 25

Duplication

Lines 19
Ratio 39.58 %

Importance

Changes 0
Metric Value
dl 19
loc 48
rs 6.7272
c 0
b 0
f 0
cc 7
eloc 25
nc 21
nop 3
1
<?php
2
3
namespace Faulancer\Controller;
4
5
use Faulancer\Exception\PluginException;
6
use Faulancer\Exception\RouteInvalidException;
7
use Faulancer\Http\Request;
8
use Faulancer\Http\Response;
9
use Faulancer\Plugin\AbstractPlugin;
10
use Faulancer\Service\AuthenticatorService;
11
use Faulancer\Service\Config;
12
use Faulancer\Service\DbService;
13
use Faulancer\Service\HttpService;
14
use Faulancer\Service\RequestService;
15
use Faulancer\Service\SessionManagerService;
16
use Faulancer\ServiceLocator\ServiceInterface;
17
use Faulancer\View\ViewController;
18
use Faulancer\ServiceLocator\ServiceLocator;
19
20
/**
21
 * Class AbstractController
22
 *
23
 * @category Controller
24
 * @package  Faulancer\AbstractController
25
 * @author   Florian Knapp <[email protected]>
26
 * @license  MIT License
27
 * @link     none
28
 */
29
abstract class AbstractController
30
{
31
32
    /**
33
     * Holds the views per controller request
34
     *
35
     * @var array
36
     */
37
    private $_viewArray = [];
38
39
    /**
40
     * Holds the plugin per controller request
41
     *
42
     * @var array
43
     */
44
    private $_pluginArray = [];
45
46
    /**
47
     * Holds the request
48
     *
49
     * @var Request
50
     */
51
    protected $request;
52
53
    /**
54
     * AbstractController constructor.
55
     *
56
     * @param Request $request The request object
57
     */
58
    public function __construct(Request $request)
59
    {
60
        $this->request = $request;
61
    }
62
63
    /**
64
     * Returns the service locator
65
     *
66
     * @return ServiceLocator
67
     */
68
    public function getServiceLocator() :ServiceLocator
69
    {
70
        return ServiceLocator::instance();
71
    }
72
73
    /**
74
     * Returns the session manager
75
     *
76
     * @return SessionManagerService|ServiceInterface
77
     */
78
    public function getSessionManager() :SessionManagerService
79
    {
80
        return $this->getServiceLocator()->get(SessionManagerService::class);
81
    }
82
83
    /**
84
     * Returns the view controller
85
     *
86
     * @return ViewController
87
     */
88
    public function getView() :ViewController
89
    {
90
        $calledClass = get_called_class();
91
92
        if (in_array($calledClass, array_keys($this->_viewArray), true)) {
93
            return $this->_viewArray[$calledClass];
94
        }
95
96
        $viewController = new ViewController();
97
98
        $this->_viewArray[$calledClass] = $viewController;
99
100
        return $viewController;
101
102
    }
103
104
    /**
105
     * Returns the orm/entity manager
106
     *
107
     * @return DbService|ServiceInterface
108
     */
109
    public function getDb() :DbService
110
    {
111
        return $this->getServiceLocator()->get(DbService::class);
112
    }
113
114
    /**
115
     * Render view with given template
116
     *
117
     * @param string $template  The template to be rendered
118
     * @param array  $variables The variables for the template
119
     *
120
     * @return Response
121
     */
122
    public function render(string $template = '', $variables = []) :Response
123
    {
124
        return new Response(
125
            $this->getView()
126
                ->setTemplate($template)
127
                ->setVariables($variables)
128
                ->render()
129
        );
130
    }
131
132
    /**
133
     * Check if user is permitted based on his role(s)
134
     *
135
     * @param array $roles The corresponding user roles
136
     *
137
     * @return bool|null
138
     */
139
    public function isPermitted($roles = [])
140
    {
141
        /** @var AuthenticatorService $authService */
142
        $authService = $this->getServiceLocator()->get(AuthenticatorService::class);
143
144
        return $authService->isPermitted($roles);
145
    }
146
147
    /**
148
     * Redirect to specific uri
149
     *
150
     * @param string $uri The target uri
151
     *
152
     * @return bool
153
     */
154
    public function redirect(string $uri) :bool
155
    {
156
        /** @var HttpService $httpService */
157
        $httpService = $this->getServiceLocator()->get(HttpService::class);
158
        return $httpService->redirect($uri);
159
    }
160
161
    /**
162
     * Set a universal text token which is valid for exactly one request/call
163
     *
164
     * @param string $key     Key for the flash message
165
     * @param string $message Content for the flash message
166
     *
167
     * @return void
168
     */
169
    public function setFlashMessage(string $key, string $message)
170
    {
171
        $sessionManager = $this->getSessionManager();
172
        $sessionManager->setFlashMessage($key, $message);
173
    }
174
175
    /**
176
     * Retrieve a flash message
177
     *
178
     * @param string $key The flash message key
179
     *
180
     * @return string|null
181
     */
182
    public function getFlashMessage(string $key)
183
    {
184
        $sessionManager = $this->getSessionManager();
185
        return $sessionManager->getFlashMessage($key);
186
    }
187
188
    /**
189
     * Get the url for a specific route name
190
     *
191
     * @param string $name       Name of the route
192
     * @param array  $parameters Apply parameters where necessary
193
     * @param bool   $absolute   Return an absolute url with host as prefix
194
     *
195
     * @return string
196
     * @throws RouteInvalidException
197
     */
198
    public function route(string $name, array $parameters = [], $absolute = false)
199
    {
200
        /** @var Config $config */
201
        $config    = ServiceLocator::instance()->get(Config::class);
202
        $routes    = $config->get('routes');
203
        $apiRoutes = $config->get('routes:rest');
204
        $routes    = array_merge($routes, $apiRoutes);
205
        $path      = '';
206
207 View Code Duplication
        foreach ($routes as $routeName => $data) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
208
209
            if ($routeName === $name) {
210
                $path = preg_replace('|/\((.*)\)|', '', $data['path']);
211
                break;
212
            }
213
214
        }
215
216
        if (empty($path)) {
217
218
            throw new RouteInvalidException(
219
                'No route for name "' . $name . '" found'
220
            );
221
222
        }
223
224 View Code Duplication
        if (!empty($parameters)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
225
226
            if (in_array('query', array_keys($parameters), true)) {
227
                $query = $parameters['query'];
228
                $query = http_build_query($query);
229
                $path  = $path . '?' . $query;
230
            } else {
231
                $path = $path . '/' . implode('/', $parameters);
232
            }
233
234
        }
235
236
        if ($absolute) {
237
238
            $path = $this->request->getScheme()
239
                . $this->request->getHost()
240
                . $path;
241
242
        }
243
244
        return $path;
245
    }
246
247
    /**
248
     * Return the current request object
249
     *
250
     * @return Request
251
     */
252
    public function getRequest() :Request
253
    {
254
        return $this->request;
255
    }
256
257
    /**
258
     * Magic method for providing a view helper
259
     *
260
     * @param string $name      The class name
261
     * @param array  $arguments Arguments if given
262
     *
263
     * @return AbstractPlugin
264
     * @throws PluginException
265
     *
266
     * @codeCoverageIgnore Not implemented yet
267
     */
268
    public function __call($name, $arguments)
269
    {
270
        // Search in core view helpers first
271
        $corePlugin = 'Faulancer\Plugin\\' . ucfirst($name);
272
273 View Code Duplication
        if (class_exists($corePlugin)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
274
275
            $class = new $corePlugin;
276
            array_unshift($arguments, $this);
277
278
            return call_user_func_array($class, $arguments);
279
280
        }
281
282
        // No core implementations found; search in custom view helpers
283
284
        /** @var Config $config */
285
        $config = ServiceLocator::instance()->get(Config::class);
286
        $namespace = '\\' . $config->get('namespacePrefix');
287
288
        $customPlugin = $namespace . '\Plugin\\' . ucfirst($name);
289
290 View Code Duplication
        if (class_exists($customPlugin)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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
            $class = new $customPlugin;
293
            array_unshift($arguments, $this);
294
295
            return call_user_func_array($class, $arguments);
296
297
        }
298
299
        throw new PluginException('No plugin for "' . $name . '" found.');
300
    }
301
302
}