Passed
Push — develop ( 76c0b8...08258a )
by Jens
03:01
created

CmsComponent::valuelistsRouting()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 3
c 0
b 0
f 0
nc 2
nop 2
dl 0
loc 6
rs 9.4285
1
<?php
2
3
namespace CloudControl\Cms\components {
4
5
    use CloudControl\Cms\components\cms\ConfigurationRouting;
6
    use CloudControl\Cms\components\cms\DocumentRouting;
7
    use CloudControl\Cms\components\cms\FilesRouting;
8
    use CloudControl\Cms\components\cms\ImagesRouting;
9
    use CloudControl\Cms\components\cms\SearchRouting;
10
    use CloudControl\Cms\components\cms\SitemapRouting;
11
    use CloudControl\Cms\components\cms\ValuelistRouting;
12
    use CloudControl\Cms\crypt\Crypt;
13
    use CloudControl\Cms\search\Search;
14
    use CloudControl\Cms\storage\Storage;
15
16
    class CmsComponent extends BaseComponent
17
    {
18
        /**
19
         * @var \CloudControl\Cms\storage\Storage
20
         */
21
        public $storage;
22
23
        const INVALID_CREDENTIALS_MESSAGE = 'Invalid username / password combination';
24
25
        const MAIN_NAV_CLASS = 'default';
26
27
        const PARAMETER_APPLICATION_COMPONENT = 'applicationComponent';
28
        const PARAMETER_APPLICATION_COMPONENTS = 'applicationComponents';
29
        const PARAMETER_BLACKLIST_IPS = 'blacklistIps';
30
        const PARAMETER_BODY = 'body';
31
        const PARAMETER_BRICK = 'brick';
32
        const PARAMETER_BRICKS = 'bricks';
33
        const PARAMETER_CMS_PREFIX = 'cmsPrefix';
34
        const PARAMETER_CONFIGURATION = 'configuration';
35
        const PARAMETER_DOCUMENT = 'document';
36
        const PARAMETER_DOCUMENTS = 'documents';
37
        const PARAMETER_DOCUMENT_TYPE = 'documentType';
38
        const PARAMETER_DOCUMENT_TYPES = 'documentTypes';
39
        const PARAMETER_ERROR_MESSAGE = 'errorMsg';
40
        const PARAMETER_FILES = 'files';
41
        const PARAMETER_FOLDER = 'folder';
42
        const PARAMETER_IMAGE = 'image';
43
        const PARAMETER_IMAGES = 'images';
44
        const PARAMETER_IMAGE_SET = 'imageSet';
45
        const PARAMETER_MAIN_NAV_CLASS = 'mainNavClass';
46
        const PARAMETER_MY_BRICK_SLUG = 'myBrickSlug';
47
        const PARAMETER_REDIRECT = 'redirect';
48
        const PARAMETER_REDIRECTS = 'redirects';
49
        const PARAMETER_RETURN_URL = 'returnUrl';
50
        const PARAMETER_SEARCH = 'search';
51
        const PARAMETER_SEARCH_LOG = "searchLog";
52
        const PARAMETER_SEARCH_NEEDS_UPDATE = "searchNeedsUpdate";
53
        const PARAMETER_SITEMAP = 'sitemap';
54
        const PARAMETER_SITEMAP_ITEM = 'sitemapItem';
55
        const PARAMETER_SMALLEST_IMAGE = 'smallestImage';
56
        const PARAMETER_STATIC = 'static';
57
        const PARAMETER_USER = 'user';
58
        const PARAMETER_USERS = 'users';
59
        const PARAMETER_USER_RIGHTS = 'userRights';
60
        const PARAMETER_VALUELIST = "valuelist";
61
        const PARAMETER_VALUELISTS = "valuelists";
62
        const PARAMETER_WHITELIST_IPS = 'whitelistIps';
63
64
        const POST_PARAMETER_COMPONENT = 'component';
65
        const POST_PARAMETER_FROM_URL = "fromUrl";
66
        const POST_PARAMETER_PASSWORD = 'password';
67
        const POST_PARAMETER_SAVE = 'save';
68
        const POST_PARAMETER_TEMPLATE = 'template';
69
        const POST_PARAMETER_TITLE = 'title';
70
        const POST_PARAMETER_TO_URL = "toUrl";
71
        const POST_PARAMETER_USERNAME = 'username';
72
73
        const GET_PARAMETER_PATH = 'path';
74
        const GET_PARAMETER_SLUG = 'slug';
75
76
        const FILES_PARAMETER_FILE = 'file';
77
78
        const SESSION_PARAMETER_CLOUD_CONTROL = 'cloudcontrol';
79
80
        const LOGIN_TEMPLATE_PATH = 'login';
81
82
        const CONTENT_TYPE_APPLICATION_JSON = 'Content-type:application/json';
83
84
        public $subTemplate = null;
85
86
87
        /**
88
         * @param Storage $storage
89
         *
90
         * @return void
91
         */
92
        public function run(Storage $storage)
93
        {
94
            $this->parameters[self::PARAMETER_MAIN_NAV_CLASS] = self::MAIN_NAV_CLASS;
95
            $this->storage = $storage;
96
97
            $remoteAddress = $_SERVER['REMOTE_ADDR'];
98
            $this->checkWhiteList($remoteAddress);
99
            $this->checkBlackList($remoteAddress);
100
101
            $this->checkLogin();
102
103
            $this->parameters[self::PARAMETER_USER_RIGHTS] = $_SESSION[self::SESSION_PARAMETER_CLOUD_CONTROL]->rights;
104
105
            $this->routing();
106
        }
107
108
        /**
109
         * See if a user is logged or wants to log in and
110
         * takes appropriate actions.
111
         *
112
         * @throws \Exception
113
         */
114
        protected function checkLogin()
115
        {
116
            $request = $this->request;
117
118
            if (!isset($_SESSION[self::SESSION_PARAMETER_CLOUD_CONTROL])) {
119
                if (isset($request::$post[self::POST_PARAMETER_USERNAME], $request::$post[self::POST_PARAMETER_PASSWORD])) {
120
                    $this->checkLoginAttempt($request);
121
                } else {
122
                    $this->showLogin();
123
                }
124
            }
125
        }
126
127
        /**
128
         * Overrides normal behaviour and only renders the
129
         * login screen
130
         *
131
         * @throws \Exception
132
         */
133
        protected function showLogin()
134
        {
135
            $loginTemplatePath = self::LOGIN_TEMPLATE_PATH;
136
            $this->renderTemplate($loginTemplatePath);
137
            ob_end_flush();
138
            exit;
139
        }
140
141
        /**
142
         * As an exception, to keep the initial file structure simple
143
         * the cms implements it's own routing, apart from the regular sitemap functionality
144
         *
145
         * @throws \Exception
146
         */
147
        protected function routing()
148
        {
149
            $relativeCmsUri = $this->getRelativeCmsUri($this->request);
150
151
            $userRights = $_SESSION[self::SESSION_PARAMETER_CLOUD_CONTROL]->rights;
152
153
            $this->dashboardRouting($relativeCmsUri);
154
            $this->logOffRouting($this->request, $relativeCmsUri);
155
            $this->apiRouting($relativeCmsUri);
156
            $this->documentRouting($userRights, $relativeCmsUri);
157
            $this->valuelistsRouting($userRights, $relativeCmsUri);
158
            $this->sitemapRouting($userRights, $relativeCmsUri);
159
            $this->imageRouting($userRights, $relativeCmsUri);
160
            $this->filesRouting($userRights, $relativeCmsUri);
161
            $this->configurationRouting($userRights, $relativeCmsUri);
162
            $this->searchRouting($userRights, $relativeCmsUri);
163
164
            $this->renderBody();
165
        }
166
167
        /**
168
         * @param $remoteAddress
169
         *
170
         * @throws \Exception
171
         */
172 View Code Duplication
        private function checkWhiteList($remoteAddress)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
173
        {
174
            if (isset($this->parameters[self::PARAMETER_WHITELIST_IPS])) {
175
                $whitelistIps = explode(',', $this->parameters[self::PARAMETER_WHITELIST_IPS]);
176
                $whitelistIps = array_map("trim", $whitelistIps);
177
                if (!in_array($remoteAddress, $whitelistIps)) {
178
                    throw new \Exception('Ip address ' . $remoteAddress . ' is not on whitelist');
179
                }
180
            }
181
        }
182
183
        /**
184
         * @param $remoteAddress
185
         *
186
         * @throws \Exception
187
         */
188 View Code Duplication
        private function checkBlackList($remoteAddress)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
189
        {
190
            if (isset($this->parameters[self::PARAMETER_BLACKLIST_IPS])) {
191
                $blacklistIps = explode(',', $this->parameters[self::PARAMETER_BLACKLIST_IPS]);
192
                $blacklistIps = array_map("trim", $blacklistIps);
193
                if (in_array($remoteAddress, $blacklistIps)) {
194
                    throw new \Exception('Ip address ' . $remoteAddress . ' is on blacklist');
195
                }
196
            }
197
        }
198
199
        /**
200
         * @param $request
201
         *
202
         * @return mixed|string
203
         */
204
        private function getRelativeCmsUri($request)
205
        {
206
            // TODO Use regex match parameter instead of calculating relative uri
207
            $pos = strpos($request::$relativeUri, $this->parameters[self::PARAMETER_CMS_PREFIX]);
208
            $relativeCmsUri = '/';
209
            if ($pos !== false) {
210
                $relativeCmsUri = substr_replace($request::$relativeUri, '', $pos, strlen($this->parameters[self::PARAMETER_CMS_PREFIX]));
211
            }
212
213
            return $relativeCmsUri;
214
        }
215
216
        /**
217
         * @param $relativeCmsUri
218
         */
219
        private function apiRouting($relativeCmsUri)
220
        {
221
            if ($relativeCmsUri == '/images.json') {
222
                header(self::CONTENT_TYPE_APPLICATION_JSON);
223
                die(json_encode($this->storage->getImages()->getImages()));
224
            } elseif ($relativeCmsUri == '/files.json') {
225
                header(self::CONTENT_TYPE_APPLICATION_JSON);
226
                die(json_encode($this->storage->getFiles()->getFiles()));
227
            } elseif ($relativeCmsUri == '/documents.json') {
228
                header(self::CONTENT_TYPE_APPLICATION_JSON);
229
                die(json_encode($this->storage->getDocuments()->getDocuments()));
230
            }
231
        }
232
233
        private function logOffRouting($request, $relativeCmsUri)
234
        {
235
            if ($relativeCmsUri == '/log-off') {
236
                $this->storage->getActivityLog()->add('logged off', 'user');
237
                $_SESSION[self::SESSION_PARAMETER_CLOUD_CONTROL] = null;
238
                unset($_SESSION[self::SESSION_PARAMETER_CLOUD_CONTROL]);
239
                header('Location: ' . $request::$subfolders . $this->parameters[self::PARAMETER_CMS_PREFIX]);
240
                exit;
241
            }
242
        }
243
244
        public function setParameter($parameterName, $parameterValue)
245
        {
246
            $this->parameters[$parameterName] = $parameterValue;
247
        }
248
249
        public function getParameter($parameterName)
250
        {
251
            return $this->parameters[$parameterName];
252
        }
253
254
        /**
255
         * @param $relativeCmsUri
256
         */
257
        protected function dashboardRouting($relativeCmsUri)
258
        {
259
            if ($relativeCmsUri == '' || $relativeCmsUri == '/') {
260
                $this->subTemplate = 'dashboard';
261
                $this->parameters['activityLog'] = $this->storage->getActivityLog()->getActivityLog();
262
                $documentCount = $this->storage->getDocuments()->getTotalDocumentCount();
263
                $indexer = new Search($this->storage);
264
                $indexedDocuments = $indexer->getIndexedDocuments();
265
                $this->setParameter(CmsComponent::PARAMETER_SEARCH_NEEDS_UPDATE, $documentCount !== $indexedDocuments);
266
            }
267
        }
268
269
        /**
270
         * @param $userRights
271
         * @param $relativeCmsUri
272
         */
273
        protected function documentRouting($userRights, $relativeCmsUri)
274
        {
275
            if (in_array(self::PARAMETER_DOCUMENTS, $userRights)) {
276
                new DocumentRouting($this->request, $relativeCmsUri, $this);
277
            }
278
        }
279
280
        /**
281
         * @param $userRights
282
         * @param $relativeCmsUri
283
         */
284
        protected function valuelistsRouting($userRights, $relativeCmsUri)
285
        {
286
            if (in_array(self::PARAMETER_VALUELISTS, $userRights)) {
287
                new ValuelistRouting($this->request, $relativeCmsUri, $this);
288
            }
289
        }
290
291
        /**
292
         * @param $userRights
293
         * @param $relativeCmsUri
294
         */
295
        protected function sitemapRouting($userRights, $relativeCmsUri)
296
        {
297
            if (in_array(self::PARAMETER_SITEMAP, $userRights)) {
298
                new SitemapRouting($this->request, $relativeCmsUri, $this);
299
            }
300
        }
301
302
        /**
303
         * @param $userRights
304
         * @param $relativeCmsUri
305
         */
306
        protected function imageRouting($userRights, $relativeCmsUri)
307
        {
308
            if (in_array(self::PARAMETER_IMAGES, $userRights)) {
309
                new ImagesRouting($this->request, $relativeCmsUri, $this);
310
            }
311
        }
312
313
        /**
314
         * @param $userRights
315
         * @param $relativeCmsUri
316
         */
317
        protected function filesRouting($userRights, $relativeCmsUri)
318
        {
319
            if (in_array(self::PARAMETER_FILES, $userRights)) {
320
                new FilesRouting($this->request, $relativeCmsUri, $this);
321
            }
322
        }
323
324
        /**
325
         * @param $userRights
326
         * @param $relativeCmsUri
327
         */
328
        protected function configurationRouting($userRights, $relativeCmsUri)
329
        {
330
            if (in_array('configuration', $userRights)) {
331
                new ConfigurationRouting($this->request, $relativeCmsUri, $this);
332
            }
333
        }
334
335
        protected function renderBody()
336
        {
337
            if ($this->subTemplate !== null) {
338
                $this->parameters[self::PARAMETER_BODY] = $this->renderTemplate($this->subTemplate);
339
            }
340
        }
341
342
        /**
343
         * @param $crypt
344
         * @param $request
345
         */
346
        protected function invalidCredentials($crypt, $request)
347
        {
348
            $crypt->encrypt($request::$post[self::POST_PARAMETER_PASSWORD], 16); // Buy time, to avoid brute forcing
349
            $this->parameters[self::PARAMETER_ERROR_MESSAGE] = self::INVALID_CREDENTIALS_MESSAGE;
350
            $this->showLogin();
351
        }
352
353
        /**
354
         * @param $user
355
         * @param $crypt
356
         * @param $request
357
         */
358
        protected function checkPassword($user, $crypt, $request)
359
        {
360
            $salt = $user->salt;
361
            $password = $user->password;
362
363
            $passwordCorrect = $crypt->compare($request::$post[self::POST_PARAMETER_PASSWORD], $password, $salt);
364
365
            if ($passwordCorrect) {
366
                $_SESSION[self::SESSION_PARAMETER_CLOUD_CONTROL] = $user;
367
                $this->storage->getActivityLog()->add('logged in', 'user');
368
            } else {
369
                $this->parameters[self::PARAMETER_ERROR_MESSAGE] = self::INVALID_CREDENTIALS_MESSAGE;
370
                $this->showLogin();
371
            }
372
        }
373
374
        /**
375
         * @param $request
376
         */
377
        protected function checkLoginAttempt($request)
378
        {
379
            $user = $this->storage->getUsers()->getUserByUsername($request::$post[self::POST_PARAMETER_USERNAME]);
380
            $crypt = new Crypt();
381
            if (empty($user)) {
382
                $this->invalidCredentials($crypt, $request);
383
            } else {
384
                $this->checkPassword($user, $crypt, $request);
385
            }
386
        }
387
388
        private function searchRouting($userRights, $relativeCmsUri)
0 ignored issues
show
Unused Code introduced by
The parameter $userRights is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
389
        {
390
            new SearchRouting($this->request, $relativeCmsUri, $this);
391
        }
392
393
        protected function getTemplateDir($template, $application = null)
394
        {
395
            return __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'templates' . DIRECTORY_SEPARATOR . $template . '.php';
396
        }
397
    }
398
}