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

AbstractApplication::__construct()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 23
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 9
c 1
b 0
f 0
dl 0
loc 23
rs 9.9666
cc 2
nc 2
nop 3
1
<?php
2
3
declare(strict_types=1);
4
5
namespace WebServCo\Framework;
6
7
use WebServCo\Framework\Environment\Value;
8
9
abstract class AbstractApplication
10
{
11
12
    protected string $projectNamespace;
13
    protected string $projectPath;
14
15
    abstract protected function config(): \WebServCo\Framework\Interfaces\ConfigInterface;
16
17
    abstract protected function request(): \WebServCo\Framework\Interfaces\RequestInterface;
18
19
    public function __construct(string $publicPath, ?string $projectPath, ?string $projectNamespace)
20
    {
21
        // If no custom namespace is set, use "Project".
22
        $this->projectNamespace = $projectNamespace ?? 'Project';
23
24
        // Make sure path ends with a slash.
25
        $publicPath = \rtrim($publicPath, \DIRECTORY_SEPARATOR) . \DIRECTORY_SEPARATOR;
26
27
        if (!\is_readable($publicPath . 'index.php')) {
28
            throw new \WebServCo\Framework\Exceptions\ApplicationException('Public web path is not readable.');
29
        }
30
31
        // If no custom project path is set, use parent directory of public.
32
        $projectPath ??= (string) \realpath(\sprintf('%s..', $publicPath));
33
34
        // Make sure path ends with a slash.
35
        $this->projectPath = \rtrim($projectPath, \DIRECTORY_SEPARATOR) . \DIRECTORY_SEPARATOR;
36
37
        // Add environment settings.
38
39
        \WebServCo\Framework\Environment\Setting::set('APP_PATH_WEB', $publicPath);
40
        \WebServCo\Framework\Environment\Setting::set('APP_PATH_PROJECT', $this->projectPath);
41
        \WebServCo\Framework\Environment\Setting::set('APP_PATH_LOG', \sprintf('%svar/log/', $this->projectPath));
42
    }
43
44
    /**
45
     * Handle Errors.
46
     */
47
    final protected function handleErrors(?\Throwable $exception = null): bool
48
    {
49
        $errorInfo = \WebServCo\Framework\ErrorHandler::getErrorInfo($exception);
50
        if (!empty($errorInfo['message'])) {
51
            return $this->halt($errorInfo);
52
        }
53
        return false;
54
    }
55
56
    /**
57
    * @param array<string,mixed> $errorInfo
58
    */
59
    final protected function halt(array $errorInfo = []): bool
60
    {
61
        return \WebServCo\Framework\Helpers\PhpHelper::isCli()
62
            ? $this->haltCli($errorInfo)
63
            : $this->haltHttp($errorInfo);
64
    }
65
66
    /**
67
     * Handle HTTP errors.
68
     *
69
     * @param array<string,mixed> $errorInfo
70
     */
71
    protected function haltHttp(array $errorInfo = []): bool
72
    {
73
        switch ($errorInfo['code']) {
74
            case 404:
75
                $statusCode = 404; //not found
76
                $title = 'Resource not found';
77
                break;
78
            case 500: //application
79
            case 0: //default
80
            default:
81
                $statusCode = 500;
82
                $title = 'Boo boo';
83
                break;
84
        }
85
86
        $output = '<!doctype html>
87
            <html>
88
            <head>
89
                <meta name="viewport" content="width=device-width, initial-scale=1.0">
90
                <title>Oops</title>
91
                <style>
92
                * {background: #f2dede; color: #a94442; overflow-wrap: break-word;}
93
                .i {margin-left: auto; margin-right: auto; text-align: center; width: auto;}
94
                small {font-size: 0.8em;}
95
                </style>
96
            </head>
97
            <body><div class="i"><br>' .
98
            "<h1>{$title}</h1>";
99
        // not using "Config" here because we just want to stop and display a message, not do more validation.
100
        if (Value::DEVELOPMENT === ($_SERVER['APP_ENVIRONMENT'] ?? Value::DEVELOPMENT)) {
101
            $output .= \sprintf(
102
                '<p><i>%s</i></p><p>%s:%s</p>',
103
                $errorInfo['message'],
104
                \basename($errorInfo['file']),
105
                $errorInfo['line'],
106
            );
107
            if (!empty($errorInfo['trace'])) {
108
                $output .= "<p>";
109
                $output .= "<small>";
110
                foreach ($errorInfo['trace'] as $item) {
111
                    if (!empty($item['class'])) {
112
                        $output .= \sprintf('%s%s', $item['class'], $item['type']);
113
                        $output .= "";
114
                    }
115
                    if (!empty($item['function'])) {
116
                        $output .= \sprintf('%s', $item['function']);
117
                        $output .= "";
118
                    }
119
                    if (!empty($item['file'])) {
120
                        $output .= \sprintf(
121
                            ' [%s:%s]',
122
                            \basename($item['file']),
123
                            $item['line'],
124
                        );
125
                        $output .= " ";
126
                    }
127
                    $output .= "<br>";
128
                }
129
                $output .= "</small></p>";
130
            }
131
        }
132
        $output .= '</div></body></html>';
133
134
        $response = new \WebServCo\Framework\Http\Response(
135
            $output,
136
            $statusCode,
137
            ['Content-Type' => ['text/html']],
138
        );
139
        $response->send();
140
        return true;
141
    }
142
143
    /**
144
    * @param array<string,mixed> $errorInfo
145
    */
146
    protected function haltCli(array $errorInfo = []): bool
147
    {
148
        $output = 'Boo boo' . \PHP_EOL;
149
        $output .= $errorInfo['message'] . \PHP_EOL;
150
        $output .= "$errorInfo[file]:$errorInfo[line]" . \PHP_EOL;
151
        $response = new \WebServCo\Framework\Cli\Response($output, 1);
152
        $response->send();
153
        return true;
154
    }
155
156
    protected function loadEnvironmentSettings(): bool
157
    {
158
        return \WebServCo\Framework\Environment\Settings::load($this->projectPath);
159
    }
160
}
161