Passed
Push — develop ( e0e89d...f9519a )
by Jens
02:44
created

Application::storage()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace CloudControl\Cms\cc {
4
5
    use CloudControl\Cms\components\Component;
6
    use CloudControl\Cms\storage\Storage;
7
    use Whoops\Handler\PrettyPageHandler;
8
    use Whoops\Run;
9
10
    class Application
11
    {
12
        /**
13
         * @var string
14
         */
15
        protected $rootDir;
16
        /**
17
         * @var string
18
         */
19
        protected $configPath;
20
        /**
21
         * @var \stdClass
22
         */
23
        private $config;
24
        /**
25
         * @var \CloudControl\Cms\storage\Storage
26
         */
27
        private $storage;
28
29
        /**
30
         * @var \CloudControl\Cms\cc\Request
31
         */
32
        private $request;
33
34
        /**
35
         * @var array
36
         */
37
        private $matchedSitemapItems = array();
38
39
        /**
40
         * @var array
41
         */
42
        private $applicationComponents = array();
43
44
        /**
45
         * Application constructor.
46
         * @param string $rootDir
47
         * @param string $configPath
48
         */
49
        public function __construct($rootDir, $configPath)
50
        {
51
            $this->rootDir = $rootDir;
52
            $this->configPath = $configPath;
53
54
            $this->config();
55
            $this->storage();
56
57
            $this->request = new Request();
58
59
            $whoops = new Run;
60
            $whoops->pushHandler(new PrettyPageHandler);
0 ignored issues
show
Documentation introduced by
new \Whoops\Handler\PrettyPageHandler() is of type object<Whoops\Handler\PrettyPageHandler>, but the function expects a callable.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
61
            $whoops->register();
62
63
            $this->redirectMatching($this->request);
64
            $this->sitemapMatching($this->request);
65
66
            $this->getApplicationComponents();
67
68
            $this->runApplicationComponents();
69
            $this->runSitemapComponents();
70
71
            $this->renderApplicationComponents();
72
            $this->renderSitemapComponents();
73
        }
74
75
        /**
76
         * Initialize the config
77
         *
78
         * @throws \Exception
79
         */
80
        private function config()
81
        {
82
            if (realpath($this->configPath) !== false) {
83
                $json = file_get_contents($this->configPath);
84
                $this->config = json_decode($json);
85
                $this->config->rootDir = $this->rootDir;
86
            } else {
87
                throw new \Exception('Framework not initialized yet. Consider running composer install');
88
            }
89
        }
90
91
        /**
92
         * Initialize the storage
93
         */
94
        private function storage()
95
        {
96
            $this->storage = new Storage($this->config->rootDir . DIRECTORY_SEPARATOR . $this->config->storageDir, $this->config->rootDir . DIRECTORY_SEPARATOR . $this->config->imagesDir, $this->config->filesDir);
97
        }
98
99
        /**
100
         * @param Request $request
101
         * @throws \Exception
102
         */
103
        private function redirectMatching($request)
104
        {
105
            $redirects = $this->storage->getRedirects()->getRedirects();
106
            $relativeUri = '/' . $request::$relativeUri;
107
108
            foreach ($redirects as $redirect) {
109
                if (preg_match_all($redirect->fromUrl, $relativeUri, $matches)) {
110
                    $toUrl = preg_replace($redirect->fromUrl, $redirect->toUrl, $relativeUri);
111
                    if (substr($toUrl, 0, 1) == '/') {
112
                        $toUrl = substr($toUrl, 1);
113
                    }
114
                    if ($redirect->type == '301') {
115
                        header('HTTP/1.1 301 Moved Permanently');
116
                        header('Location: ' . $request::$subfolders . $toUrl);
117
                        exit;
118
                    } elseif ($redirect->type == '302') {
119
                        header('Location: ' . $request::$subfolders . $toUrl, true, 302);
120
                        exit;
121
                    } else {
122
                        throw new \Exception('Invalid redirect type.');
123
                    }
124
                }
125
            }
126
        }
127
128
        /**
129
         * Loop through sitemap items and see if one matches the requestUri.
130
         * If it does, add it tot the matchedSitemapItems array
131
         *
132
         * @param Request $request
133
         */
134
        private function sitemapMatching($request)
135
        {
136
            $sitemap = $this->storage->getSitemap()->getSitemap();
137
            $relativeUri = '/' . $request::$relativeUri;
138
139
            foreach ($sitemap as $sitemapItem) {
140
                if ($sitemapItem->regex) {
141
                    $matches = array();
142
                    if (preg_match_all($sitemapItem->url, $relativeUri, $matches)) {
143
                        // Make a clone, so it doesnt add the matches to the original
144
                        $matchedClone = clone $sitemapItem;
145
                        $matchedClone->matches = $matches;
146
                        $this->matchedSitemapItems[] = $matchedClone;
147
                        return;
148
                    }
149
                } else {
150
                    if ($sitemapItem->url == $relativeUri) {
151
                        $this->matchedSitemapItems[] = $sitemapItem;
152
                        return;
153
                    }
154
                }
155
            }
156
        }
157
158
        /**
159
         * Loop through all application components and run them
160
         *
161
         * @throws \Exception
162
         */
163
        private function runApplicationComponents()
164
        {
165
            foreach ($this->applicationComponents as $key => $applicationComponent) {
166
                $class = $applicationComponent->component;
167
                $parameters = $applicationComponent->parameters;
168
                $this->applicationComponents[$key]->{'object'} = $this->getComponentObject($class, null, $parameters, null);
169
                $this->applicationComponents[$key]->{'object'}->run($this->storage);
170
            }
171
        }
172
173
        /**
174
         * Loop through all (matched) sitemap components and run them
175
         *
176
         * @throws \Exception
177
         */
178
        private function runSitemapComponents()
179
        {
180
            foreach ($this->matchedSitemapItems as $key => $sitemapItem) {
181
                $class = $sitemapItem->component;
182
                $template = $sitemapItem->template;
183
                $parameters = $sitemapItem->parameters;
184
185
                $this->matchedSitemapItems[$key]->object = $this->getComponentObject($class, $template, $parameters, $sitemapItem);
186
187
                $this->matchedSitemapItems[$key]->object->run($this->storage);
188
            }
189
        }
190
191
        /**
192
         * @param string $class
193
         * @param string $template
194
         * @param array $parameters
195
         * @param \stdClass|null $matchedSitemapItem
196
         *
197
         * @return Component
198
         * @throws \Exception
199
         */
200
        private function getComponentObject($class = '', $template = '', $parameters = array(), $matchedSitemapItem)
201
        {
202
            $libraryComponentName = '\\CloudControl\Cms\\components\\' . $class;
203
            $userComponentName = '\\components\\' . $class;
204
205
            if (!class_exists($libraryComponentName, false)) {
206
                $component = new $libraryComponentName($template, $this->request, $parameters, $matchedSitemapItem);
207
            } elseif (!class_exists($userComponentName, false)) {
208
                $component = new $userComponentName($template, $this->request, $parameters, $matchedSitemapItem);
209
            } else {
210
                throw new \Exception('Could not load component ' . $class);
211
            }
212
213
            if (!$component instanceof Component) {
214
                throw new \Exception('Component not of type Component. Must inherit \CloudControl\Cms\components\Component');
215
            }
216
217
            return $component;
218
        }
219
220
        /**
221
         * Loop through all application components and render them
222
         */
223
        private function renderApplicationComponents()
224
        {
225
            foreach ($this->applicationComponents as $applicationComponent) {
226
                $applicationComponent->{'object'}->render();
227
            }
228
        }
229
230
        /**
231
         * Loop through all (matched) sitemap components and render them
232
         */
233
        private function renderSitemapComponents()
234
        {
235
            foreach ($this->matchedSitemapItems as $sitemapItem) {
236
                $this->setCachingHeaders();
237
                $sitemapItem->object->render($this);
238
                ob_clean();
239
                echo $sitemapItem->object->get();
240
                ob_end_flush();
241
                exit;
242
            }
243
        }
244
245
        public function getAllApplicationComponentParameters()
246
        {
247
            $allParameters = array();
248
            foreach ($this->applicationComponents as $applicationComponent) {
249
                $parameters = $applicationComponent->{'object'}->getParameters();
250
                $allParameters[] = $parameters;
251
            }
252
            return $allParameters;
253
        }
254
255
        public function unlockApplicationComponentParameters()
256
        {
257
            foreach ($this->applicationComponents as $applicationComponent) {
258
                $parameters = $applicationComponent->{'object'}->getParameters();
259
                extract($parameters);
260
            }
261
        }
262
263
        /**
264
         * Set the default caching of pages to 2 days
265
         */
266
        public function setCachingHeaders()
267
        {
268
            header('Expires: ' . gmdate('D, d M Y H:i:s \G\M\T', time() + (60 * 60 * 24 * 2))); // 2 days
269
            header("Cache-Control: max-age=" . (60 * 60 * 24 * 2));
270
        }
271
272
        /**
273
         * @return string
274
         */
275
        public function getTemplateDir()
276
        {
277
            return $this->config->templateDir;
278
        }
279
280
        public function getStorageDir()
281
        {
282
            return $this->config->storageDir;
283
        }
284
285
        public function getApplicationComponents()
286
        {
287
            $this->applicationComponents = $this->storage->getApplicationComponents()->getApplicationComponents();
288
        }
289
290
        public function getRootDir()
291
        {
292
            return $this->config->rootDir;
293
        }
294
    }
295
}