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