Completed
Pull Request — master (#439)
by Anton
27:34
created

Controller::getParams()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 4
ccs 0
cts 2
cp 0
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * Bluz Framework Component
4
 *
5
 * @copyright Bluz PHP Team
6
 * @link      https://github.com/bluzphp/framework
7
 */
8
9
declare(strict_types=1);
10
11
namespace Bluz\Controller;
12
13
use Bluz\Application\Application;
14
use Bluz\Auth\EntityInterface;
15
use Bluz\Common\Exception\CommonException;
16
use Bluz\Common\Exception\ComponentException;
17
use Bluz\Common\Helper;
18
use Bluz\Proxy\Cache;
19
use Bluz\Proxy\Logger;
20
use Bluz\Response\ResponseTrait;
21
use Bluz\View\View;
22
23
/**
24
 * Statement
25
 *
26
 * @package  Bluz\Controller
27
 * @author   Anton Shevchuk
28
 *
29
 * @method void attachment(string $file)
30
 * @method void checkHttpAccept()
31
 * @method void checkHttpMethod()
32
 * @method void checkPrivilege()
33
 * @method void denied()
34
 * @method void disableLayout()
35
 * @method void disableView()
36
 * @method Controller dispatch(string $module, string $controller, array $params = [])
37
 * @method void redirect(string $url)
38
 * @method void redirectTo(string $module, string $controller, array $params = [])
39
 * @method void reload()
40
 * @method bool isAllowed($privilege)
41
 * @method void useJson()
42
 * @method void useLayout($layout)
43
 * @method EntityInterface user()
44
 */
45
class Controller implements \JsonSerializable
46
{
47
    use Helper;
48
    use ResponseTrait;
49
50
    /**
51
     * @var string
52
     */
53
    protected $module;
54
55
    /**
56
     * @var string
57
     */
58
    protected $controller;
59
60
    /**
61
     * @var array
62
     */
63
    protected $params;
64
65
    /**
66
     * @var string Cache key
67
     */
68
    protected $key;
69
70
    /**
71
     * @var string Template name, by default is equal to controller name
72
     */
73
    protected $template;
74
75
    /**
76
     * @var string
77
     */
78
    protected $file;
79
80
    /**
81
     * @var Meta
82
     */
83
    protected $meta;
84
85
    /**
86
     * @var Data
87
     */
88
    protected $data;
89
90
    /**
91
     * Constructor of Statement
92
     *
93
     * @param string $module
94
     * @param string $controller
95
     * @param array  $params
96
     *
97
     * @throws CommonException
98
     */
99 556
    public function __construct($module, $controller, array $params = [])
100
    {
101
        // initial default helper path
102 556
        $this->addHelperPath(__DIR__ . '/Helper/');
103
104 556
        $this->setModule($module);
105 556
        $this->setController($controller);
106 556
        $this->setParams($params);
107 556
        $this->setTemplate($controller . '.phtml');
108
109 556
        $this->key = "data.$module.$controller." . md5(http_build_query($params));
110 556
    }
111
112
    /**
113
     * @return string
114
     */
115
    public function getModule(): string
116
    {
117
        return $this->module;
118
    }
119
120
    /**
121
     * @param string $module
122
     */
123 556
    protected function setModule(string $module)
124
    {
125 556
        $this->module = $module;
126 556
    }
127
128
    /**
129
     * @return string
130
     */
131
    public function getController(): string
132
    {
133
        return $this->controller;
134
    }
135
136
    /**
137
     * @param string $controller
138
     */
139 556
    protected function setController(string $controller)
140
    {
141 556
        $this->controller = $controller;
142 556
    }
143
144
    /**
145
     * @return array
146
     */
147
    public function getParams(): array
148
    {
149
        return $this->params;
150
    }
151
152
    /**
153
     * @param array $params
154
     */
155 556
    protected function setParams(array $params)
156
    {
157 556
        $this->params = $params;
158 556
    }
159
160
    /**
161
     * @return string
162
     */
163 2
    public function getTemplate()
164
    {
165 2
        return $this->template;
166
    }
167
168
    /**
169
     * @param string $template
170
     */
171 556
    protected function setTemplate(string $template)
172
    {
173 556
        $this->template = $template;
174 556
    }
175
176
    /**
177
     * Run controller logic
178
     *
179
     * @return Data
180
     * @throws ComponentException
181
     * @throws ControllerException
182
     */
183 31
    public function run(): Data
184
    {
185 31
        if (!$this->loadData()) {
186 31
            $this->process();
187 29
            $this->saveData();
188
        }
189 29
        return $this->data;
190
    }
191
192
    /**
193
     * Controller run
194
     *
195
     * @return Data
196
     * @throws ComponentException
197
     * @throws ControllerException
198
     */
199 31
    protected function process(): Data
200
    {
201
        // initial variables for use inside controller
202 31
        $module = $this->module;
203 31
        $controller = $this->controller;
204 31
        $params = $this->params;
205
206
        /**
207
         * @var \closure $controllerClosure
208
         */
209 31
        $controllerClosure = include $this->getFile();
210
211 31
        if (!is_callable($controllerClosure)) {
212
            throw new ControllerException("Controller is not callable '{$module}/{$controller}'");
213
        }
214
215
        // process params
216 31
        $params = $this->getMeta()->params($params);
217
218
        // call Closure or Controller
219 31
        $result = $controllerClosure(...$params);
220
221
        // switch statement for result of Closure run
222
        switch (true) {
223 29
            case ($result === false):
224
                // return "false" is equal to disable view and layout
225 11
                $this->disableLayout();
226 11
                $this->disableView();
227 11
                break;
228 19
            case is_string($result):
229
                // return string variable is equal to change view template
230
                $this->setTemplate($result);
231
                break;
232 19
            case is_array($result):
233
                // return associative array is equal to setup view data
234 6
                $this->getData()->setFromArray($result);
235 6
                break;
236 13
            case ($result instanceof Controller):
237
                // return Controller - just extract data from it
238
                $this->getData()->setFromArray($result->getData()->toArray());
239
                break;
240
        }
241
242 29
        return $this->getData();
243
    }
244
245
    /**
246
     * Setup controller file
247
     *
248
     * @return void
249
     * @throws ControllerException
250
     */
251 556
    protected function findFile()
252
    {
253 556
        $path = Application::getInstance()->getPath();
254 556
        $file = "$path/modules/{$this->module}/controllers/{$this->controller}.php";
255
256 556
        if (!file_exists($file)) {
257 3
            throw new ControllerException("Controller file not found '{$this->module}/{$this->controller}'", 404);
258
        }
259
260 556
        $this->file = $file;
261 556
    }
262
263
    /**
264
     * Get controller file path
265
     *
266
     * @return string
267
     * @throws ControllerException
268
     */
269 556
    protected function getFile(): string
270
    {
271 556
        if (!$this->file) {
272 556
            $this->findFile();
273
        }
274 556
        return $this->file;
275
    }
276
277
    /**
278
     * Retrieve reflection for anonymous function
279
     *
280
     * @return void
281
     * @throws ComponentException
282
     * @throws ControllerException
283
     */
284 556
    protected function initMeta()
285
    {
286
        // cache for reflection data
287 556
        $cacheKey = "meta.{$this->module}.{$this->controller}";
288
289 556
        if (!$meta = Cache::get($cacheKey)) {
290 556
            $meta = new Meta($this->getFile());
291 556
            $meta->process();
292
293 556
            Cache::set(
294 556
                $cacheKey,
295 556
                $meta,
296 556
                Cache::TTL_NO_EXPIRY,
297 556
                ['system', 'meta']
298
            );
299
        }
300 556
        $this->meta = $meta;
301 556
    }
302
303
    /**
304
     * Get meta information
305
     *
306
     * @return Meta
307
     * @throws ControllerException
308
     * @throws ComponentException
309
     */
310 556
    public function getMeta(): Meta
311
    {
312 556
        if (!$this->meta) {
313 556
            $this->initMeta();
314
        }
315 556
        return $this->meta;
316
    }
317
318
    /**
319
     * Assign key/value pair to Data object
320
     *
321
     * @param  string $key
322
     * @param  mixed  $value
323
     *
324
     * @return void
325
     */
326 1
    public function assign($key, $value)
327
    {
328 1
        $this->getData()->set($key, $value);
329 1
    }
330
331
    /**
332
     * Get controller Data container
333
     *
334
     * @return Data
335
     */
336 29
    public function getData(): Data
337
    {
338 29
        if (!$this->data) {
339 29
            $this->data = new Data();
340
        }
341 29
        return $this->data;
342
    }
343
344
    /**
345
     * Load Data from cache
346
     *
347
     * @return bool
348
     * @throws ComponentException
349
     * @throws ControllerException
350
     */
351 31
    private function loadData(): bool
352
    {
353 31
        $cacheTime = $this->getMeta()->getCache();
354
355 31
        if ($cacheTime && $cached = Cache::get($this->key)) {
356
            $this->data = $cached;
357
            return true;
358
        }
359 31
        return false;
360
    }
361
362
    /**
363
     * Save Data to cache
364
     *
365
     * @return bool
366
     * @throws ComponentException
367
     * @throws ControllerException
368
     */
369 29
    private function saveData(): bool
370
    {
371 29
        if ($cacheTime = $this->getMeta()->getCache()) {
372
            return Cache::set(
373
                $this->key,
374
                $this->getData(),
375
                $cacheTime,
376
                ['system', 'data']
377
            );
378
        }
379 29
        return false;
380
    }
381
382
    /**
383
     * Specify data which should be serialized to JSON
384
     *
385
     * @return Data
386
     */
387
    public function jsonSerialize()
388
    {
389
        return $this->getData();
390
    }
391
392
    /**
393
     * Magic cast to string
394
     *
395
     * @return string
396
     */
397 3
    public function __toString()
398
    {
399 3
        if (!$this->template) {
400
            return '';
401
        }
402
403
        try {
404
            // $view for use in closure
405 3
            $view = new View();
406
407 3
            $path = Application::getInstance()->getPath();
408
409
            // setup additional helper path
410 3
            $view->addHelperPath($path . '/layouts/helpers');
411
412
            // setup additional partial path
413 3
            $view->addPartialPath($path . '/layouts/partial');
414
415
            // setup default path
416 3
            $view->setPath($path . '/modules/' . $this->module . '/views');
417
418
            // setup template
419 3
            $view->setTemplate($this->template);
420
421
            // setup data
422 3
            $view->setFromArray($this->getData()->toArray());
423 3
            return $view->render();
424
        } catch (\Exception $e) {
425
            // save log
426
            Logger::error($e->getMessage());
427
            return '';
428
        }
429
    }
430
}
431