Passed
Push — develop ( 7a79ec...b37dd3 )
by Jens
06:50
created

Application::setHeaders()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 15
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 13
nc 2
nop 0
dl 0
loc 15
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
namespace CloudControl\Cms\cc;
4
5
use CloudControl\Cms\cc\application\ApplicationRenderer;
6
use CloudControl\Cms\cc\application\ApplicationRunner;
7
use CloudControl\Cms\cc\application\UrlMatcher;
8
use CloudControl\Cms\services\FileService;
9
use CloudControl\Cms\services\ImageService;
10
use CloudControl\Cms\services\ValuelistService;
11
use CloudControl\Cms\storage\Cache;
12
use CloudControl\Cms\storage\Storage;
13
use Whoops\Handler\PrettyPageHandler;
14
use Whoops\Run;
15
16
class Application
17
{
18
    /**
19
     * @var string
20
     */
21
    protected $rootDir;
22
    /**
23
     * @var string
24
     */
25
    protected $configPath;
26
    /**
27
     * @var \stdClass
28
     */
29
    private $config;
30
    /**
31
     * @var \CloudControl\Cms\storage\Storage
32
     */
33
    private $storage;
34
35
    /**
36
     * @var \CloudControl\Cms\cc\Request
37
     */
38
    private $request;
39
40
    /**
41
     * @var array
42
     */
43
    private $matchedSitemapItems = array();
44
45
    /**
46
     * @var array
47
     */
48
    private $applicationComponents = array();
49
50
    const HEADER_X_POWERED_BY = 'X-Powered-By: ';
51
    const HEADER_X_POWERED_BY_CONTENT = 'Cloud Control - https://getcloudcontrol.org';
52
    const HEADER_X_FRAME_OPTIONS = "X-Frame-Options: ";
53
    const HEADER_X_FRAME_OPTIONS_CONTENT = "SAMEORIGIN";
54
    const HEADER_X_CONTENT_TYPE_OPTIONS = 'X-Content-Type-Options: ';
55
    const HEADER_X_CONTENT_TYPE_OPTIONS_CONTENT = 'nosniff';
56
    const HEADER_REFERRER_POLICY = 'Referrer-Policy: ';
57
    const HEADER_REFERRER_POLICY_CONTENT = 'strict-origin-when-cross-origin';
58
    const HEADER_X_XSS_PROTECTION = 'X-XSS-Protection: ';
59
    const HEADER_X_XSS_PROTECTION_CONTENT = '1; mode=block';
60
    const HEADER_SET_COOKIE = 'Set-Cookie: ';
61
    const HEADER_CONTENT_SECURITY_POLICY = 'Content-Security-Policy: ';
62
    const HEADER_CONTENT_SECURITY_POLICY_CONTENT_SECURE = 'default-src https: \'unsafe-inline\' \'unsafe-eval\'';
63
    const HEADER_CONTENT_SECURITY_POLICY_CONTENT_INSECURE = 'default-src \'self\' https: \'unsafe-inline\' \'unsafe-eval\'';
64
    const HEADER_X_CONTENT_SECURITY_POLICY = 'X-Content-Security-Policy: '; // For IE
65
    const HEADER_STRICT_TRANSPORT_SECURITY = 'Strict-Transport-Security: ';
66
    const HEADER_STRICT_TRANSPORT_SECURITY_CONTENT = 'max-age=31536000;';
67
68
    /**
69
     * Application constructor.
70
     * @param string $rootDir
71
     * @param string $configPath
72
     * @throws \Exception
73
     */
74
    public function __construct($rootDir, $configPath)
75
    {
76
        $this->rootDir = $rootDir;
77
        $this->configPath = $configPath;
78
79
        $this->config();
80
        $this->storage();
81
82
        Cache::getInstance()->setStoragePath($this->config->rootDir . DIRECTORY_SEPARATOR . $this->config->storageDir);
83
84
        $this->request = new Request();
85
86
        $this->setExceptionHandler();
87
88
        $this->startServices();
89
90
        $this->urlMatching();
91
92
        $this->getApplicationComponents();
93
94
        $this->run();
95
        $this->setHeaders();
96
        $this->render();
97
    }
98
99
    /**
100
     * Initialize the config
101
     *
102
     * @throws \Exception
103
     */
104
    private function config()
105
    {
106
        if (realpath($this->configPath) !== false) {
107
            $json = file_get_contents($this->configPath);
108
            $this->config = json_decode($json);
109
            $this->config->rootDir = $this->rootDir;
110
        } else {
111
            throw new \RuntimeException('Framework not initialized yet. Consider running composer install');
112
        }
113
    }
114
115
    /**
116
     * Initialize the storage
117
     */
118
    private function storage()
119
    {
120
        $this->storage = new Storage($this->config->rootDir . DIRECTORY_SEPARATOR . $this->config->storageDir, $this->config->rootDir . DIRECTORY_SEPARATOR . $this->config->imagesDir, $this->config->filesDir);
121
    }
122
123
    public function getAllApplicationComponentParameters()
124
    {
125
        $allParameters = array();
126
        foreach ($this->applicationComponents as $applicationComponent) {
127
            $parameters = $applicationComponent->{'object'}->getParameters();
128
            $allParameters[] = $parameters;
129
        }
130
        return $allParameters;
131
    }
132
133
    public function unlockApplicationComponentParameters()
134
    {
135
        foreach ($this->applicationComponents as $applicationComponent) {
136
            $parameters = $applicationComponent->{'object'}->getParameters();
137
            extract($parameters, EXTR_OVERWRITE);
138
        }
139
    }
140
141
    /**
142
     * @return string
143
     */
144
    public function getTemplateDir()
145
    {
146
        return $this->config->templateDir;
147
    }
148
149
    /**
150
     * @return string
151
     */
152
    public function getStorageDir()
153
    {
154
        return $this->config->storageDir;
155
    }
156
157
    public function getApplicationComponents()
158
    {
159
        $this->applicationComponents = $this->storage->getApplicationComponents()->getApplicationComponents();
160
    }
161
162
    /**
163
     * @return string
164
     */
165
    public function getRootDir()
166
    {
167
        return $this->config->rootDir;
168
    }
169
170
    private function setExceptionHandler()
171
    {
172
        $whoops = new Run;
173
        $whoops->pushHandler(new PrettyPageHandler);
174
        $whoops->register();
175
    }
176
177
    /**
178
     * @throws \Exception
179
     */
180
    private function urlMatching()
181
    {
182
        $urlMatcher = new UrlMatcher($this, $this->storage);
183
        $urlMatcher->redirectMatching($this->request);
184
        $urlMatcher->sitemapMatching($this->request);
185
    }
186
187
    private function run()
188
    {
189
        $applicationRunner = new ApplicationRunner($this->storage, $this->request);
190
        $applicationRunner->runApplicationComponents($this->applicationComponents);
191
        $applicationRunner->runSitemapComponents($this->matchedSitemapItems);
192
    }
193
194
    /**
195
     * @throws \Exception
196
     */
197
    private function render()
198
    {
199
        $applicationRenderer = new ApplicationRenderer($this, $this->storage, $this->request);
200
        $applicationRenderer->renderApplicationComponents($this->applicationComponents);
201
        $applicationRenderer->renderSitemapComponents($this->matchedSitemapItems);
202
    }
203
204
    private function startServices()
205
    {
206
        FileService::getInstance()->init($this->storage);
207
        ImageService::getInstance()->init($this->storage);
208
        ValuelistService::getInstance()->init($this->storage);
209
    }
210
211
    public function addMatchedSitemapItem($matchedClone)
212
    {
213
        $this->matchedSitemapItems[] = $matchedClone;
214
    }
215
216
    /**
217
     * Sets default headers. Please note that caching headers are set
218
     * here: \CloudControl\Cms\cc\application\ApplicationRenderer::setCachingHeaders
219
     * and here: \CloudControl\Cms\cc\application\ApplicationRenderer::setNotCachingHeaders
220
     */
221
    private function setHeaders()
222
    {
223
        header(self::HEADER_X_POWERED_BY . self::HEADER_X_POWERED_BY_CONTENT);
224
        header(self::HEADER_X_FRAME_OPTIONS . self::HEADER_X_FRAME_OPTIONS_CONTENT);
225
        header(self::HEADER_X_CONTENT_TYPE_OPTIONS . self::HEADER_X_CONTENT_TYPE_OPTIONS_CONTENT);
226
        header(self::HEADER_REFERRER_POLICY . self::HEADER_REFERRER_POLICY_CONTENT);
227
        header(self::HEADER_X_XSS_PROTECTION . self::HEADER_X_XSS_PROTECTION_CONTENT);
228
        header(self::HEADER_SET_COOKIE . '__Host-sess=' . session_id() . '; path=' . Request::$subfolders . '; Secure; HttpOnly; SameSite');
229
        if (Request::isSecure()) {
230
            header(self::HEADER_CONTENT_SECURITY_POLICY . self::HEADER_CONTENT_SECURITY_POLICY_CONTENT_SECURE);
231
            header(self::HEADER_X_CONTENT_SECURITY_POLICY . self::HEADER_CONTENT_SECURITY_POLICY_CONTENT_SECURE);
232
            header(self::HEADER_STRICT_TRANSPORT_SECURITY . self::HEADER_STRICT_TRANSPORT_SECURITY_CONTENT);
233
        } else {
234
            header(self::HEADER_CONTENT_SECURITY_POLICY . self::HEADER_CONTENT_SECURITY_POLICY_CONTENT_INSECURE);
235
            header(self::HEADER_X_CONTENT_SECURITY_POLICY . self::HEADER_CONTENT_SECURITY_POLICY_CONTENT_INSECURE);
236
        }
237
238
    }
239
}