Passed
Push — master ( 9c6499...c22bc5 )
by Jens
04:52 queued 02:21
created

Application::sitemapMatching()   B

Complexity

Conditions 5
Paths 5

Size

Total Lines 23
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

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