Completed
Pull Request — master (#317)
by Anton
06:14 queued 04:30
created

Bootstrap::end()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
cc 2
nc 2
nop 0
dl 0
loc 6
ccs 0
cts 6
cp 0
crap 6
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * @copyright Bluz PHP Team
4
 * @link      https://github.com/bluzphp/skeleton
5
 */
6
7
declare(strict_types=1);
8
9
namespace Application;
10
11
use Application\Auth;
12
use Bluz\Application\Application;
13
use Bluz\Auth\AuthException;
14
use Bluz\Controller\Controller;
15
use Bluz\Http\Exception\ForbiddenException;
16
use Bluz\Http\Exception\RedirectException;
17
use Bluz\Proxy\Auth as AuthProxy;
18
use Bluz\Proxy\Config;
19
use Bluz\Proxy\Layout;
20
use Bluz\Proxy\Logger;
21
use Bluz\Proxy\Messages;
22
use Bluz\Proxy\Request;
23
use Bluz\Proxy\Response;
24
use Bluz\Proxy\Router;
25
use Bluz\Proxy\Session;
26
use Bluz\Proxy\Translator;
27
28
/**
29
 * Bootstrap
30
 *
31
 * @category Application
32
 * @package  Bootstrap
33
 *
34
 * @author   Anton Shevchuk
35
 * @created  20.07.11 17:38
36
 */
37
class Bootstrap extends Application
0 ignored issues
show
Coding Style introduced by
Since you have declared the constructor as private, maybe you should also declare the class as final.
Loading history...
38
{
39
    /**
40
     * {@inheritdoc}
41
     */
42
    protected function initTranslator(): void
43
    {
44
        $translator = new \Bluz\Translator\Translator();
45
        $translator->setOptions(Config::get('translator'));
46
47
        // supported locales
48
        // en_US, ru_RU, uk_UA
49
        $locales = [
50
            'en' => 'en_US',
51
            'ru' => 'ru_RU',
52
            'uk' => 'uk_UA',
53
        ];
54
55
        // try to check locale from cookies
56
        $locale = Request::getCookie('locale');
57
58
        // try to get locale from browser
59
        if (!$locale) {
60
            $languages = Request::getAcceptLanguage();
61
            foreach ($languages as $language => $priority) {
62
                if (array_key_exists($language, $locales)) {
63
                    $locale = $language;
64
                    break;
65
                }
66
            }
67
        }
68
69
        // normalize locale
70
        if (array_key_exists($locale, $locales)) {
71
            $translator->setLocale($locales[$locale]);
72
        }
73
74
        $translator->init();
75
76
        Translator::setInstance($translator);
77
    }
78
79
    /**
80
     * {@inheritdoc}
81
     *
82
     * @param Controller $controller
83
     *
84
     * @return void
85
     * @throws \Application\Exception
86
     * @throws \Bluz\Auth\AuthException
87
     * @throws \InvalidArgumentException
88
     */
89
    protected function preDispatch($controller): void
90
    {
91
        // example of setup default title
92
        Layout::title('Bluz Skeleton');
93
94
        if (!AuthProxy::getIdentity() && $controller->getModule() !== Router::getErrorModule()) {
95
            if ($token = Request::getCookie('Auth-Token')) {
96
                // try to login by token from cookies
97
                try {
98
                    Auth\Provider\Cookie::authenticate($token);
99
                } catch (AuthException $e) {
100
                    $this->getResponse()->setCookie('Auth-Token', '', 1, '/');
101
                }
102
            } elseif ($token = Request::getHeader('Auth-Token')) {
103
                // try to login by token from headers
104
                Auth\Provider\Token::authenticate($token);
105
            }
106
        }
107
        parent::preDispatch($controller);
108
    }
109
110
    /**
111
     * Denied access
112
     *
113
     * @param ForbiddenException $exception
114
     *
115
     * @return \Bluz\Controller\Controller|null
116
     */
117
    public function forbidden(ForbiddenException $exception): ?Controller
118
    {
119
        // for AJAX and API calls (over JSON)
120
        $jsonOrApi = Request::isXmlHttpRequest()
121
            || (Request::checkAccept([Request::TYPE_HTML, Request::TYPE_JSON]) === Request::TYPE_JSON);
122
123
        // for guest, for requests
124
        if (!$jsonOrApi && !AuthProxy::getIdentity()) {
125
            // save URL to session and redirect make sense if presentation is null
126
            Session::set('rollback', Request::getUri()->__toString());
127
            // add error notice
128
            Messages::addError('You don\'t have permissions, please sign in');
129
            // redirect to Sign In page
130
            $redirect = new RedirectException();
131
            $redirect->setUrl(Router::getUrl('users', 'signin'));
132
            return $this->redirect($redirect);
133
        }
134
        return $this->error($exception);
135
    }
136
137
    /**
138
     * Render with debug headers
139
     *
140
     * @return void
141
     */
142
    public function render(): void
143
    {
144
        Logger::info('app:render');
145
        Logger::info('app:files:' . count(get_included_files()));
146
147
        if ($this->isDebug()) {
148
            if (!headers_sent()) {
149
                $this->sendInfoHeaders();
150
            }
151
            if (ob_get_level() > 0 && ob_get_length() > 0) {
152
                Logger::error('Output has been sent previously');
153
                return;
154
            }
155
        }
156
        parent::render();
157
    }
158
159
    /**
160
     * Finish it
161
     *
162
     * @return void
163
     */
164
    public function end(): void
165
    {
166
        if ($errors = Logger::get('error')) {
167
            $this->sendErrors($errors);
168
        }
169
    }
170
171
    /**
172
     * Send information headers
173
     *
174
     * @return void
175
     */
176
    protected function sendInfoHeaders(): void
177
    {
178
        $debugString = sprintf(
179
            '%fsec; %skb',
180
            microtime(true) - $_SERVER['REQUEST_TIME_FLOAT'],
181
            ceil(memory_get_usage() / 1024)
182
        );
183
        $debugString .= '; ' . Request::getModule() . '/' . Request::getController();
184
185
        Response::setHeader('Bluz-Debug', $debugString);
186
187
        if ($info = Logger::get('info')) {
188
            Response::setHeader('Bluz-Bar', json_encode($info));
189
        } else {
190
            Response::setHeader('Bluz-Bar', '{"!":"Logger is disabled"}');
191
        }
192
    }
193
194
    /**
195
     * sendErrorBody
196
     *
197
     * @param  array $errors
198
     *
199
     * @return void
200
     */
201
    protected function sendErrors($errors): void
202
    {
203
        foreach ($errors as $message) {
204
            errorLog(new \ErrorException($message, 0, E_USER_ERROR));
205
        }
206
    }
207
}
208