Completed
Push — master ( 013ef7...4604a2 )
by Radu
07:01
created

Application::start()   A

Complexity

Conditions 2
Paths 4

Size

Total Lines 10
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 5
Bugs 0 Features 0
Metric Value
eloc 6
c 5
b 0
f 0
dl 0
loc 10
rs 10
cc 2
nc 4
nop 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace WebServCo\Framework;
6
7
use WebServCo\Framework\Exceptions\ApplicationException;
8
use WebServCo\Framework\Exceptions\NotFoundException;
9
use WebServCo\Framework\Helpers\PhpHelper;
10
use WebServCo\Framework\Interfaces\ResponseInterface;
11
12
class Application extends \WebServCo\Framework\AbstractApplication
13
{
14
    use \WebServCo\Framework\Traits\ExposeLibrariesTrait;
15
16
    /**
17
     * Runs the application.
18
     */
19
    public function run(): void
20
    {
21
        try {
22
            ErrorHandler::set();
23
24
            \register_shutdown_function([$this, 'shutdown']);
25
26
            $this->loadEnvironmentSettings();
27
28
            $response = $this->execute();
29
            $statusCode = 0;
30
            if ($response instanceof ResponseInterface) {
0 ignored issues
show
introduced by
$response is always a sub-type of WebServCo\Framework\Interfaces\ResponseInterface.
Loading history...
31
                $statusCode = $response->send();
32
            }
33
            $this->shutdown(null, true, PhpHelper::isCli() ? $statusCode : 0);
34
        } catch (\Throwable $e) {
35
            $this->shutdown($e, true);
36
        }
37
    }
38
39
    /**
40
     * Finishes the execution of the Application.
41
     *
42
     * This method is also registered as a shutdown handler.
43
     */
44
    final public function shutdown(?\Throwable $exception = null, bool $manual = false, int $statusCode = 0): void
45
    {
46
        $hasError = $this->handleErrors($exception);
47
        if ($hasError) {
48
            $statusCode = 1;
49
        }
50
51
        if (!$manual) { // if shutdown handler
52
            /**
53
             * Warning: this part will always be executed,
54
             * independent of the outcome of the script.
55
             */
56
            ErrorHandler::restore();
57
        }
58
        exit($statusCode);
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
59
    }
60
61
    final protected function execute(): ResponseInterface
62
    {
63
        $classType = PhpHelper::isCli()
64
            ? 'Command'
65
            : 'Controller';
66
        $target = $this->request()->getTarget();
67
        // \WebServCo\Framework\Objects\Route
68
        $route = $this->router()->getRoute(
69
            $target,
70
            $this->router()->setting('routes'),
71
            $this->request()->getArgs(),
72
        );
73
74
        $className = \sprintf("\\%s\\Domain\\%s\\%s", $this->projectNamespace, $route->class, $classType);
75
        if (!\class_exists($className)) {
76
            if ('Controller' !== $classType) {
77
                throw new NotFoundException(
78
                    \sprintf('No matching %s found. Target: "%s"', $classType, $target),
79
                );
80
            }
81
            // Class type is "Controller", so check for 404 route
82
            // throws \WebServCo\Framework\Exceptions\NotFoundException
83
            $route = $this->router()->getFourOhfourRoute();
84
            $className = \sprintf("\\%s\\Domain\\%s\\%s", $this->projectNamespace, $route->class, $classType);
85
        }
86
87
        $object = new $className();
88
        $parent = \get_parent_class($object);
89
        if (\method_exists((string) $parent, $route->method) || !\is_callable([$className, $route->method])) {
90
            throw new NotFoundException(\sprintf('No matching Action found. Target: "%s".', $target));
91
        }
92
        $callable = [$object, $route->method];
93
        if (!\is_callable($callable)) {
94
            throw new ApplicationException(\sprintf('Method not found. Target: "%s"', $target));
95
        }
96
97
        return \call_user_func_array($callable, $route->arguments);
98
    }
99
}
100