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

AbstractController::__call()   B

Complexity

Conditions 3
Paths 3

Size

Total Lines 33
Code Lines 14

Duplication

Lines 33
Ratio 100 %

Importance

Changes 0
Metric Value
dl 33
loc 33
rs 8.8571
c 0
b 0
f 0
cc 3
eloc 14
nc 3
nop 2
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 = $this->getServiceLocator()->get(Config::class);
194
        $routes = $config->get('routes');
195
196 View Code Duplication
        foreach ($routes as $routeName => $routeConfig) {
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...
197
198
            if ($routeName === $name) {
199
                $path = preg_replace('|/\((.*)\)|', '', $routeConfig['path']);
200
                break;
201
            }
202
203
        }
204
205
        if (empty($path)) {
206
            throw new RouteInvalidException(
207
                'No route for name "' . $name . '" found'
208
            );
209
        }
210
211
        if (!empty($parameters)) {
212
            $path = $path . '/' . implode('/', $parameters);
213
        }
214
215
        if ($absolute) {
216
217
            $path = $this->getRequest()->getScheme()
218
                . $this->getRequest()->getHost()
219
                . $path;
220
221
        }
222
223
        return $path;
224
    }
225
226
    /**
227
     * Return the current request object
228
     *
229
     * @return Request
230
     */
231
    public function getRequest() :Request
232
    {
233
        return $this->request;
234
    }
235
236
    /**
237
     * Magic method for providing a view helper
238
     *
239
     * @param string $name      The class name
240
     * @param array  $arguments Arguments if given
241
     *
242
     * @return AbstractPlugin
243
     * @throws PluginException
244
     *
245
     * @codeCoverageIgnore Not implemented yet
246
     */
247 View Code Duplication
    public function __call($name, $arguments)
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...
248
    {
249
        // Search in core view helpers first
250
        $corePlugin = 'Faulancer\Plugin\\' . ucfirst($name);
251
252
        if (class_exists($corePlugin)) {
253
254
            $class = new $corePlugin;
255
            array_unshift($arguments, $this);
256
257
            return call_user_func_array($class, $arguments);
258
259
        }
260
261
        // No core implementations found; search in custom view helpers
262
263
        /** @var Config $config */
264
        $config = ServiceLocator::instance()->get(Config::class);
265
        $namespace = '\\' . $config->get('namespacePrefix');
266
267
        $customPlugin = $namespace . '\Plugin\\' . ucfirst($name);
268
269
        if (class_exists($customPlugin)) {
270
271
            $class = new $customPlugin;
272
            array_unshift($arguments, $this);
273
274
            return call_user_func_array($class, $arguments);
275
276
        }
277
278
        throw new PluginException('No plugin for "' . $name . '" found.');
279
    }
280
281
}