Passed
Push — develop ( 3cabcb...ccd080 )
by Jens
03:29
created

Application::redirectMatching()   B

Complexity

Conditions 6
Paths 8

Size

Total Lines 24
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

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