Passed
Push — develop ( 6305d1...602320 )
by Jens
02:48
created

JsonStorage::addApplicationComponent()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 1
eloc 4
c 1
b 0
f 1
nc 1
nop 1
dl 0
loc 7
rs 9.4285
1
<?php
2
namespace library\storage
3
{
4
5
	use library\crypt\Crypt;
6
	use library\images\ImageResizer;
7
8
	/**
9
	 * Class JsonStorage
10
	 * @package library\storage
11
	 */
12
	class JsonStorage implements Storage
13
	{
14
		private $storagePath;
15
		private $repository;
16
17
		/**
18
		 * JsonStorage constructor.
19
		 *
20
		 * @param $storagePath
21
		 */
22
		public function __construct($storagePath)
23
		{
24
			$this->storagePath = $storagePath;
25
			$this->config();
26
		}
27
28
		/**
29
		 * Retrieve the data from the storagepath
30
		 * so it can be interacted with
31
		 *
32
		 * @throws \Exception
33
		 */
34
		private function config()
35
		{
36
			$storagePath = __DIR__ . $this->storagePath;
37
			if (realpath($storagePath) !== false) {
38
				$jsonString = file_get_contents($storagePath);
39
				$this->repository = json_decode($jsonString);
40
			} else {
41
				// Here is some logic for the initialisation of a new clone of the framework
42
				initFramework($storagePath);
43
			}
44
		}
45
46
47
48
		/**
49
		 * Get user by username
50
		 *
51
		 * @param $username
52
		 *
53
		 * @return array
54
		 */
55
		public function getUserByUsername($username)
56
		{
57
			$return = array();
58
			
59
			$users = $this->repository->users;
60
			foreach ($users as $user) {
61
				if ($user->username == $username) {
62
					$return = $user;
63
					break;
64
				}
65
			}
66
			
67
			return $return;
68
		}
69
70
		public function getUserBySlug($slug)
71
		{
72
			$return = array();
73
74
			$users = $this->repository->users;
75
			foreach ($users as $user) {
76
				if ($user->slug == $slug) {
77
					$return = $user;
78
					break;
79
				}
80
			}
81
82
			return $return;
83
		}
84
85
		public function getUsers()
86
		{
87
			return $this->repository->users;
88
		}
89
90
		public function saveUser($slug, $postValues)
91
		{
92
			$userObj = $this->createUserFromPostValues($postValues);
93
			if ($userObj->slug != $slug) {
94
				// If the username changed, check for duplicates
95
				$doesItExist = $this->getUserBySlug($userObj->slug);
96
				if (!empty($doesItExist)) {
97
					throw new \Exception('Trying to rename user to existing username');
98
				}
99
			}
100
			$users = $this->getUsers();
101
			foreach ($users as $key => $user) {
102
				if ($user->slug == $slug) {
103
					$users[$key] = $userObj;
104
				}
105
			}
106
			$this->repository->users = $users;
107
			$this->save();
108
		}
109
110
		public function addUser($postValues)
111
		{
112
			$userObj = $this->createUserFromPostValues($postValues);
113
114
			$doesItExist = $this->getUserBySlug($userObj->slug);
115
			if (!empty($doesItExist)) {
116
				throw new \Exception('Trying to add username that already exists.');
117
			}
118
			$this->repository->users[] = $userObj;
119
			$this->save();
120
		}
121
122
		public function deleteUserBySlug($slug)
123
		{
124
			$userToDelete = $this->getUserBySlug($slug);
125
			if (empty($userToDelete)) {
126
				throw new \Exception('Trying to delete a user that doesn\'t exist.');
127
			}
128
			$users = $this->getUsers();
129
			foreach ($users as $key => $user) {
130
				if ($user->slug == $userToDelete->slug) {
131
					unset($users[$key]);
132
					$this->repository->users = array_values($users);
133
				}
134
			}
135
			$this->save();
136
		}
137
138
		private function createUserFromPostValues($postValues)
139
		{
140
			if (isset($postValues['username'])) {
141
				$user = new \stdClass();
142
				$user->username = $postValues['username'];
143
				$user->slug = slugify($postValues['username']);
144
				$user->rights = array();
145
				if (isset($postValues['rights'])) {
146
					$user->rights = $postValues['rights'];
147
				}
148
149
				if (isset($postValues['password']) && empty($postValues['password']) === false) {
150
					$crypt = new Crypt();
151
					$user->password = $crypt->encrypt($postValues['password'], 16);
152
					$user->salt = $crypt->getLastSalt();
153
				} else {
154
					$user->password = $postValues['passHash'];
155
					$user->salt = $postValues['salt'];
156
				}
157
158
				return $user;
159
			} else {
160
				throw new \Exception('Trying to create user with invalid data.');
161
			}
162
		}
163
164
		/*
165
		 *
166
		 * Documents
167
		 *
168
		 */
169
		/**
170
		 * Get documents
171
		 *
172
		 * @return array
173
		 */
174
		public function getDocuments()
175
		{
176
			return $this->repository->documents;
177
		}
178
179
		/**
180
		 * @param string $slug
181
		 * @return mixed
182
		 * @throws \Exception
183
		 */
184
		public function getDocumentBySlug($slug)
185
		{
186
			$documentContainer = $this->getDocumentContainerByPath('/' . $slug);
187
			$indices = $documentContainer['indices'];
188
189
			if ($indices === null) {
190
				$emptyReturn = new \stdClass();
191
				$emptyReturn->title = 'Not found';
192
				$emptyReturn->type = null;
193
				$emptyReturn->state = 'published';
194
				return $emptyReturn;
195
			}
196
197
			$folder = $this->repository->documents;
198
			foreach ($indices as $index) {
199
				if ($folder === $this->repository->documents) {
200
					$folder = $folder[$index];
201
				} else {
202
					$folder = $folder->content[$index];
203
				}
204
			}
205
206
			return $folder;
207
		}
208
209
		public function saveDocument($postValues)
210
		{
211
			$documentFolderObject = $this->createDocumentFromPostValues($postValues);
212
213
			$documentContainer = $this->getDocumentContainerByPath($_GET['slug']);
214
			$indices = $documentContainer['indices'];
215
216
			$folder = $this->repository->documents;
217
			$previousFolder = $this->repository->documents;
218
			foreach ($indices as $index) {
219
				if ($folder === $this->repository->documents) {
220
					$folder = $folder[$index];
221
				} else {
222
					$previousFolder = $folder;
223
					$folder = $folder->content[$index];
224
				}
225
			}
226
227
			if ($previousFolder === $this->repository->documents) {
228
				// Check for duplicates
229
				foreach ($this->repository->documents as $index => $document) {
230
					if (end($indices) !== $index && $document->slug == $documentFolderObject->slug && $document->type == 'document') {
231
						throw new \Exception('Duplicate slug: ' . $document->slug . ' in folder ' . $postValues['path']);
232
					}
233
				}
234
				$this->repository->documents[end($indices)] = $documentFolderObject;
235
			} else {
236
				// Check for duplicates
237
				foreach ($previousFolder->content as $index => $document) {
238
					if (end($indices) !== $index && $document->slug == $documentFolderObject->slug && $document->type == 'document') {
239
						throw new \Exception('Duplicate slug: ' . $document->slug . ' in folder ' . $postValues['path']);
240
					}
241
				}
242
				$previousFolder->content[end($indices)] = $documentFolderObject ;
243
			}
244
245
			$this->save();
246
		}
247
248
		public function addDocument($postValues)
249
		{
250
			$documentFolderObject = $this->createDocumentFromPostValues($postValues);
251
			if ($postValues['path'] == '' || $postValues['path'] == '/') {
252
				// Check folder duplicate child
253
				foreach ($this->repository->documents as $document) {
254
					if ($document->slug == $documentFolderObject->slug && $document->type == 'document') {
255
						// TODO make it so it doesnt throw an exception, but instead shows a warning
256
						throw new \Exception('Duplicate slug: ' . $document->slug . ' in folder ' . $postValues['path']);
257
					}
258
				}
259
				$this->repository->documents[] = $documentFolderObject;
260
			} else {
261
				// Check folder duplicate child
262
				$containerFolder = $this->getDocumentFolderBySlug($postValues['path']);
263
				if (isset($containerFolder->content)) {
264
					foreach ($containerFolder->content as $document) {
265
						if ($document->slug == $documentFolderObject->slug && $document->type == 'document') {
266
							// TODO make it so it doesnt throw an exception, but instead shows a warning
267
							throw new \Exception('Duplicate slug: ' . $document->slug . ' in folder ' . $postValues['path']);
268
						}
269
					}
270
				}
271
				$containerFolder->content[] = $documentFolderObject;
272
			}
273
			$this->save();
274
		}
275
276
		public function deleteDocumentBySlug($slug)
277
		{
278
			$documentContainer = $this->getDocumentContainerByPath($slug);
279
			$indices = $documentContainer['indices'];
280
281
			$folder = $this->repository->documents;
282
			$previousFolder = $this->repository->documents;
283
			foreach ($indices as $index) {
284
				if ($folder === $this->repository->documents) {
285
					$folder = $folder[$index];
286
				} else {
287
					$previousFolder = $folder;
288
					$folder = $folder->content[$index];
289
				}
290
			}
291
292
			if ($previousFolder === $this->repository->documents) {
293
				unset($this->repository->documents[end($indices)]);
294
				$this->repository->documents = array_values($this->repository->documents);
295
			} else {
296
				unset($previousFolder->content[end($indices)]);
297
				$previousFolder->content = array_values($previousFolder->content);
298
			}
299
300
			$this->save();
301
		}
302
303
		private function createDocumentFromPostValues($postValues)
304
		{
305
			$documentType = $this->getDocumentTypeBySlug($postValues['documentType']);
306
307
			$staticBricks = $documentType->bricks;
308
309
			$documentObj = new \stdClass();
310
			$documentObj->title = $postValues['title'];
311
			$documentObj->slug = slugify($postValues['title']);
312
			$documentObj->type = 'document';
313
			$documentObj->documentType = $documentType->title;
314
			$documentObj->documentTypeSlug = $documentType->slug;
315
			$documentObj->state = isset($postValues['state']) ? 'published' : 'unpublished';
316
			$documentObj->lastModificationDate = time();
317
			$documentObj->creationDate = isset($postValues['creationDate']) ? intval($postValues['creationDate']) : time();
318
			$documentObj->lastModifiedBy = $_SESSION['cloudcontrol']->username;
319
320
			$documentObj->fields = isset($postValues['fields']) ? $postValues['fields'] : array();
321
			$documentObj->bricks = array();
322
			if (isset($postValues['bricks'])) {
323
				foreach ($postValues['bricks'] as $brickSlug => $brick) {
324
					// Check if its multiple
325
					$multiple = false;
326
					foreach ($staticBricks as $staticBrick) {
327
						if ($staticBrick->slug === $brickSlug) {
328
							$multiple = $staticBrick->multiple;
329
							break;
330
						}
331
					}
332
333
					if ($multiple) {
334
						$brickArray = array();
335
						foreach ($brick as $brickInstance) {
336
							$brickObj = new \stdClass();
337
							$brickObj->fields = new \stdClass();
338
							$brickObj->type = $staticBrick->brickSlug;
0 ignored issues
show
Bug introduced by
The variable $staticBrick seems to be defined by a foreach iteration on line 326. Are you sure the iterator is never empty, otherwise this variable is not defined?

It seems like you are relying on a variable being defined by an iteration:

foreach ($a as $b) {
}

// $b is defined here only if $a has elements, for example if $a is array()
// then $b would not be defined here. To avoid that, we recommend to set a
// default value for $b.


// Better
$b = 0; // or whatever default makes sense in your context
foreach ($a as $b) {
}

// $b is now guaranteed to be defined here.
Loading history...
339
340
							foreach ($brickInstance['fields'] as $fieldName => $fieldValues) {
341
								$brickObj->fields->$fieldName = $fieldValues;
342
							}
343
344
							$brickArray[] = $brickObj;
345
						}
346
347
						$documentObj->bricks[$brickSlug] = $brickArray;
348
					} else {
349
						$documentObj->bricks[$brickSlug] = $brick;
350
					}
351
				}
352
			}
353
			$documentObj->dynamicBricks = array();
354
			if (isset($postValues['dynamicBricks'])) {
355
				foreach ($postValues['dynamicBricks'] as $brickTypeSlug => $brick) {
356
					foreach ($brick as $brickContent) {
357
						$brickObj = new \stdClass();
358
						$brickObj->type = $brickTypeSlug;
359
						$brickObj->fields = $brickContent;
360
						$documentObj->dynamicBricks[] = $brickObj;
361
					}
362
				}
363
			}
364
			return $documentObj;
365
		}
366
367
		/**
368
		 * Add new document in given path
369
		 *
370
		 * @param array $postValues
371
		 *
372
		 * @throws \Exception
373
		 */
374
		public function addDocumentFolder($postValues)
375
		{
376
			$documentFolderObject = $this->createDocumentFolderFromPostValues($postValues);
377
			if ($postValues['path'] == '' || $postValues['path'] == '/') {
378
				// Check folder duplicate child
379
				foreach ($this->repository->documents as $document) {
380
					if ($document->slug == $documentFolderObject->slug && $document->type == 'folder') {
381
						// TODO make it so it doesnt throw an exception, but instead shows a warning
382
						throw new \Exception('Duplicate slug: ' . $document->slug . ' in folder ' . $postValues['path']);
383
					}
384
				}
385
				$this->repository->documents[] = $documentFolderObject;
386
			} else {
387
				$documentContainer = $this->getDocumentContainerByPath($postValues['path']);
388
				$documentContainerArray = $documentContainer['indices'];
389
				$containerFolder = $documentContainer['containerFolder'];
390
				$folder = $this->repository->documents;
391
				foreach ($documentContainerArray as $index) {
392
					if ($folder === $this->repository->documents) {
393
						$folder = $folder[$index];
394
					} else {
395
						$folder = $folder->content[$index];
396
					}
397
398
				}
399
				// Check folder duplicate child
400
				foreach ($containerFolder->content as $document) {
401
					if ($document->slug == $documentFolderObject->slug && $document->type == 'folder') {
402
						// TODO make it so it doesnt throw an exception, but instead shows a warning
403
						throw new \Exception('Duplicate slug: ' . $document->slug . ' in folder ' . $postValues['path']);
404
					}
405
				}
406
				$folder->content[] = $documentFolderObject;
407
			}
408
			$this->save();
409
		}
410
411
		/**
412
		 * Delete a folder by its compound slug
413
		 *
414
		 * @param $slug
415
		 *
416
		 * @throws \Exception
417
		 */
418
		public function deleteDocumentFolderBySlug($slug)
419
		{
420
			$documentContainer = $this->getDocumentContainerByPath($slug);
421
			$indices = $documentContainer['indices'];
422
423
			$folder = $this->repository->documents;
424
			$previousFolder = $this->repository->documents;
425
			foreach ($indices as $index) {
426
				if ($folder === $this->repository->documents) {
427
					$folder = $folder[$index];
428
				} else {
429
					$previousFolder = $folder;
430
					$folder = $folder->content[$index];
431
				}
432
			}
433
434
			if ($previousFolder === $this->repository->documents) {
435
				unset($this->repository->documents[end($indices)]);
436
				$this->repository->documents = array_values($this->repository->documents);
437
			} else {
438
				unset($previousFolder->content[end($indices)]);
439
				$previousFolder->content = array_values($previousFolder->content);
440
			}
441
442
			$this->save();
443
		}
444
445
		/**
446
		 * Retrieve a folder by its compound slug
447
		 *
448
		 * @param $slug
449
		 *
450
		 * @return mixed
451
		 * @throws \Exception
452
		 */
453
		public function getDocumentFolderBySlug($slug)
454
		{
455
			$documentContainer = $this->getDocumentContainerByPath('/' . $slug);
456
			$indices = $documentContainer['indices'];
457
458
			$folder = $this->repository->documents;
459
			foreach ($indices as $index) {
460
				if ($folder === $this->repository->documents) {
461
					$folder = $folder[$index];
462
				} else {
463
					$folder = $folder->content[$index];
464
				}
465
			}
466
467
			return $folder;
468
		}
469
470
		/**
471
		 * Save changes to folder
472
		 *
473
		 * @param $postValues
474
		 *
475
		 * @throws \Exception
476
		 */
477
		public function saveDocumentFolder($postValues)
478
		{
479
			$documentFolderObject = $this->createDocumentFolderFromPostValues($postValues);
480
481
			$documentContainer = $this->getDocumentContainerByPath($_GET['slug']);
482
			$indices = $documentContainer['indices'];
483
484
			$folder = $this->repository->documents;
485
			$previousFolder = $this->repository->documents;
486
			foreach ($indices as $index) {
487
				if ($folder === $this->repository->documents) {
488
					$folder = $folder[$index];
489
				} else {
490
					$previousFolder = $folder;
491
					$folder = $folder->content[$index];
492
				}
493
			}
494
495
			if ($previousFolder === $this->repository->documents) {
496
				// Check for duplicates
497
				foreach ($this->repository->documents as $index => $document) {
498
					if (end($indices) !== $index && $document->slug == $documentFolderObject->slug && $document->type == 'folder') {
499
						throw new \Exception('Duplicate slug: ' . $document->slug . ' in folder ' . $postValues['path']);
500
					}
501
				}
502
				$this->repository->documents[end($indices)] = $documentFolderObject;
503
			} else {
504
				// Check for duplicates
505
				foreach ($previousFolder->content as $index => $document) {
506
					if (end($indices) !== $index && $document->slug == $documentFolderObject->slug && $document->type == 'folder') {
507
						throw new \Exception('Duplicate slug: ' . $document->slug . ' in folder ' . $postValues['path']);
508
					}
509
				}
510
				$previousFolder->content[end($indices)] = $documentFolderObject ;
511
			}
512
513
			$this->save();
514
		}
515
516
		/**
517
		 * Convert path to indeces
518
		 *
519
		 * @param $path
520
		 *
521
		 * @return array
522
		 * @throws \Exception
523
		 */
524
		private function getDocumentContainerByPath($path)
525
		{
526
			$slugs = explode('/', $path);
527
			$slugs = array_filter($slugs);
528
			end($slugs);
529
			$lastKey = key($slugs);
530
			$root = $this->repository->documents;
531
			$i = 0;
532
			$returnArray = array();
533
			$noMatches = 0;
534
			$foundDocument = null;
535
			$document = null;
536
			$previousDocument = null;
537
			foreach ($slugs as $slug) {
538
				$matched = false;
539
				$previousDocument = null;
540
				end($root);
541
				$lastSubKey = key($root);
542
				foreach ($root as $index => $document) {
543
					if ($slug == $document->slug) {
544
						if ($i != $lastKey && $document->type == 'folder') {
545
							$returnArray[] = $index;
546
							$root = $root[$index]->content;
547
							$matched = true;
548
						} else {
549
							$foundDocument = $document;
550
							$returnArray[] = $index;
551
							$matched = true;
552
						}
553
					}
554
555
					if ($lastSubKey != $index) {
556
						$previousDocument = $document;
557
					}
558
				}
559
				if ($matched === true) {
560
					$noMatches += 1;
561
				} else {
562
					//throw new \Exception('Unknown folder "' . $slug . '" in path: ' . $path);
0 ignored issues
show
Unused Code Comprehensibility introduced by
43% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
563
					return array(
564
							'containerFolder' => new \stdClass(),
565
							'indices' => null,
566
							'document' => new \stdClass(),
567
							'previousDocument' => new \stdClass()
568
					);
569
				}
570
				$i += 1;
571
			}
572
			if ($noMatches > 0) {
573
				return array(
574
					'containerFolder' => $document,
575
					'indices' => $returnArray,
576
					'document' => $foundDocument,
577
					'previousDocument' => $previousDocument
578
				);
579
			} else {
580
				throw new \Exception('Invalid path: ' . $path);
581
			}
582
		}
583
584
		/**
585
		 * Create folder from post values
586
		 *
587
		 * @param $postValues
588
		 *
589
		 * @return \stdClass
590
		 * @throws \Exception
591
		 */
592
		private function createDocumentFolderFromPostValues($postValues)
593
		{
594
			if (isset($postValues['title'], $postValues['path'], $postValues['content'])) {
595
				$documentFolderObject = new \stdClass();
596
				$documentFolderObject->title = $postValues['title'];
597
				$documentFolderObject->slug = slugify($postValues['title']);
598
				$documentFolderObject->type = 'folder';
599
				$documentFolderObject->content = json_decode($postValues['content']);
600
601
				return $documentFolderObject;
602
			} else {
603
				throw new \Exception('Trying to create document folder with invalid data.');
604
			}
605
		}
606
607
		/*
608
		 * 
609
		 * Sitemap
610
		 *
611
		 */
612
		/**
613
		 * @return array
614
		 */
615
		public function getSitemap()
616
		{
617
			return $this->repository->sitemap;
618
		}
619
620
		/**
621
		 * Add a sitemap item
622
		 *
623
		 * @param $postValues
624
		 *
625
		 * @throws \Exception
626
		 */
627
		public function addSitemapItem($postValues) 
628
		{
629
			$sitemapObject = $this->createSitemapItemFromPostValues($postValues);
630
			
631
			$this->repository->sitemap[] = $sitemapObject;
632
			$this->save();
633
		}
634
635
		/**
636
		 * Save changes to a sitemap item
637
		 *
638
		 * @param $slug
639
		 * @param $postValues
640
		 *
641
		 * @throws \Exception
642
		 */
643
		public function saveSitemapItem($slug, $postValues)
644
		{
645
			$sitemapObject = $this->createSitemapItemFromPostValues($postValues);
646
			
647
			$sitemap = $this->repository->sitemap;
648
			foreach ($sitemap as $key => $sitemapItem) {
649
				if ($sitemapItem->slug == $slug) {
650
					$sitemap[$key] = $sitemapObject;
651
				}
652
			}
653
			$this->repository->sitemap = $sitemap;
654
			$this->save();
655
		}
656
657
		/**
658
		 * Delete a sitemap item by its slug
659
		 *
660
		 * @param $slug
661
		 *
662
		 * @throws \Exception
663
		 */
664
		public function deleteSitemapItemBySlug($slug)
665
		{
666
			$sitemap = $this->repository->sitemap;
667
			foreach ($sitemap as $key => $sitemapItem) {
668
				if ($sitemapItem->slug == $slug) {
669
					unset($sitemap[$key]);
670
				}
671
			}
672
			$sitemap = array_values($sitemap);
673
			$this->repository->sitemap = $sitemap;
674
			$this->save();
675
		}
676
677
		/**
678
		 * Create a sitemap item from post values
679
		 *
680
		 * @param $postValues
681
		 *
682
		 * @return \stdClass
683
		 * @throws \Exception
684
		 */
685
		private function createSitemapItemFromPostValues($postValues)
686
		{
687
			if (isset($postValues['title'], $postValues['url'], $postValues['component'], $postValues['template'])) {
688
				$sitemapObject = new \stdClass();
689
				$sitemapObject->title = $postValues['title'];
690
				$sitemapObject->slug = slugify($postValues['title']);
691
				$sitemapObject->url = $postValues['url'];
692
				$sitemapObject->component = $postValues['component'];
693
				$sitemapObject->template = $postValues['template'];
694
				$sitemapObject->regex = isset($postValues['regex']);
695
				$sitemapObject->parameters = new \stdClass();
696
				if (isset($postValues['parameterNames'], $postValues['parameterValues'])) {
697
					foreach ($postValues['parameterNames'] as $key => $value) {
698
						$sitemapObject->parameters->$value = $postValues['parameterValues'][$key];
699
					}
700
				}
701
				return $sitemapObject;
702
			} else {
703
				throw new \Exception('Trying to create sitemap item with invalid data.');
704
			}
705
		}
706
707
		/**
708
		 * Save changes to a sitemap item
709
		 *
710
		 * @param $postValues
711
		 *
712
		 * @throws \Exception
713
		 */
714
		public function saveSitemap($postValues)
715
		{
716
			if (isset($postValues['sitemapitem']) && is_array($postValues['sitemapitem'])) {
717
				$sitemap = array();
718
				foreach ($postValues['sitemapitem'] as $sitemapItem) {
719
					$sitemapItemObject = json_decode($sitemapItem);
720
					if (isset($sitemapItemObject->object)) {
721
						unset($sitemapItemObject->object);
722
					}
723
					$sitemap[] = $sitemapItemObject;
724
				}
725
				$this->repository->sitemap = $sitemap;
726
				$this->save();
727
			}
728
		}
729
730
		/**
731
		 * Get a sitemap item by its slug
732
		 *
733
		 * @param $slug
734
		 *
735
		 * @return mixed
736
		 */
737
		public function getSitemapItemBySlug($slug)
738
		{
739
			$sitemap = $this->repository->sitemap;
740
			foreach ($sitemap as $sitemapItem) {
741
				if ($sitemapItem->slug == $slug) {
742
					return $sitemapItem;
743
				}
744
			}
745
			return null;
746
		}
747
748
		/*
749
		 *
750
		 * Images
751
		 *
752
		 */
753
		/**
754
		 * Get all images
755
		 *
756
		 * @return array
757
		 */
758
		public function getImages()
759
		{
760
			return $this->repository->images;
761
		}
762
763
		public function addImage($postValues)
764
		{
765
			$destinationPath = realpath(__DIR__ . '/../../www/images/');
766
767
			$filename = $this->validateFilename($postValues['name'], $destinationPath);
768
			$destination = $destinationPath . '/' . $filename;
769
770
			if ($postValues['error'] != '0') {
771
				throw new \Exception('Error uploading file. Error code: ' . $postValues['error']);
772
			}
773
774
			if (move_uploaded_file($postValues['tmp_name'], $destination)) {
775
				$imageResizer = new ImageResizer($this->getImageSet());
776
				$fileNames = $imageResizer->applyImageSetToImage($destination);
777
				$fileNames['original'] = $filename;
778
				$imageObject = new \stdClass();
779
				$imageObject->file = $filename;
780
				$imageObject->type = $postValues['type'];
781
				$imageObject->size = $postValues['size'];
782
				$imageObject->set = $fileNames;
783
784
				$this->repository->images[] = $imageObject;
785
				$this->save();
786
			} else {
787
				throw new \Exception('Error moving uploaded file');
788
			}
789
		}
790
791
		public function deleteImageByName($filename)
792
		{
793
			$destinationPath = realpath(__DIR__ . '/../../www/images/');
794
795
			$images = $this->getImages();
796
797
			foreach ($images as $key => $image) {
798
				if ($image->file == $filename) {
799
					foreach ($image->set as $imageSetFilename) {
800
						$destination = $destinationPath . '/' . $imageSetFilename;
801
						if (file_exists($destination)) {
802
							unlink($destination);
803
						} else {
804
							dump($destination);
805
						}
806
					}
807
					unset($images[$key]);
808
				}
809
			}
810
811
			$this->repository->images = $images;
812
			$this->save();
813
		}
814
815
		/**
816
		 * @param $filename
817
		 * @return null
818
         */
819
		public function getImageByName($filename)
820
		{
821
			$images = $this->getImages();
822
			foreach ($images as $image) {
823
				if ($image->file == $filename) {
824
					return $image;
825
				}
826
			}
827
			return null;
828
		}
829
830
		/*
831
		 *
832
		 * Files
833
		 *
834
		 */
835
		/**
836
		 * Get all files
837
		 *
838
		 * @return array
839
		 */
840
		public function getFiles()
841
		{
842
			$files =  $this->repository->files;
843
			usort($files, array($this, 'compareFiles'));
844
			return $files;
845
		}
846
847
		private function compareFiles($a, $b)
848
		{
849
			return strcmp($a->file, $b->file);
850
		}
851
852
		public function addFile($postValues)
853
		{
854
			$destinationPath = realpath(__DIR__ . '/../../www/files/');
855
856
			$filename = $this->validateFilename($postValues['name'], $destinationPath);
857
			$destination = $destinationPath . '/' . $filename;
858
859
			if ($postValues['error'] != '0') {
860
				throw new \Exception('Error uploading file. Error code: ' . $postValues['error']);
861
			}
862
863
			if (move_uploaded_file($postValues['tmp_name'], $destination)) {
864
				$file = new \stdClass();
865
				$file->file = $filename;
866
				$file->type = $postValues['type'];
867
				$file->size = $postValues['size'];
868
869
				$this->repository->files[] = $file;
870
				$this->save();
871
			} else {
872
				throw new \Exception('Error moving uploaded file');
873
			}
874
		}
875
876
		private function validateFilename($filename, $path)
877
		{
878
			$fileParts = explode('.', $filename);
879
			if (count($fileParts) > 1) {
880
				$extension = end($fileParts);
881
				array_pop($fileParts);
882
				$fileNameWithoutExtension = implode('-', $fileParts);
883
				$fileNameWithoutExtension = slugify($fileNameWithoutExtension);
884
				$filename = $fileNameWithoutExtension . '.' . $extension;
885
			} else {
886
				$filename = slugify($filename);
887
			}
888
889
			if (file_exists($path . '/' . $filename)) {
890
				$fileParts = explode('.', $filename);
891
				if (count($fileParts) > 1) {
892
					$extension = end($fileParts);
893
					array_pop($fileParts);
894
					$fileNameWithoutExtension = implode('-', $fileParts);
895
					$fileNameWithoutExtension .= '-copy';
896
					$filename = $fileNameWithoutExtension . '.' . $extension;
897
				} else {
898
					$filename .= '-copy';
899
				}
900
				return $this->validateFilename($filename,$path);
901
			}
902
			return $filename;
903
		}
904
905
		/**
906
		 * @param $filename
907
		 * @return null
908
         */
909
		public function getFileByName($filename)
910
		{
911
			$files = $this->getFiles();
912
			foreach ($files as $file) {
913
				if ($filename == $file->file) {
914
					return $file;
915
				}
916
			}
917
			return null;
918
		}
919
920
		/**
921
		 * @param $filename
922
		 * @throws \Exception
923
         */
924
		public function deleteFileByName($filename)
925
		{
926
			$destinationPath = realpath(__DIR__ . '/../../www/files/');
927
			$destination = $destinationPath . '/' . $filename;
928
929
			if (file_exists($destination)) {
930
				$files = $this->getFiles();
931
				foreach ($files as $key => $file) {
932
					if ($file->file == $filename) {
933
						unlink($destination);
934
						unset($files[$key]);
935
					}
936
				}
937
938
				$files = array_values($files);
939
				$this->repository->files = $files;
940
				$this->save();
941
			}
942
		}
943
944
		/*
945
		 * 
946
		 * Configuration
947
		 *
948
		 */
949
		/**
950
		 * @return array
951
		 */
952
		public function getDocumentTypes()
953
		{
954
			return $this->repository->documentTypes;
955
		}
956
957
		/**
958
		 * Add a document type from post values
959
		 *
960
		 * @param $postValues
961
		 *
962
		 * @throws \Exception
963
		 */
964
		public function addDocumentType($postValues)
965
		{
966
			$documentTypeObject = $this->createDocumentTypeFromPostValues($postValues);
967
			
968
			$this->repository->documentTypes[] = $documentTypeObject;
969
			$this->save();
970
		}
971
972
		/**
973
		 * Create a document type from post values
974
		 *
975
		 * @param $postValues
976
		 *
977
		 * @return \stdClass
978
		 * @throws \Exception
979
		 */
980
		public function createDocumentTypeFromPostValues($postValues)
981
		{
982
			if (isset($postValues['title'])) {
983
				$documentTypeObject = new \stdClass();
984
				$documentTypeObject->title = $postValues['title'];
985
				$documentTypeObject->slug = slugify($postValues['title']);
986
				$documentTypeObject->fields = array();
987
				$documentTypeObject->bricks = array();
988
				$documentTypeObject->dynamicBricks = isset($postValues['dynamicBricks']) ? $postValues['dynamicBricks'] : array();
989
				if (isset($postValues['fieldTitles'], $postValues['fieldTypes'], $postValues['fieldRequired'], $postValues['fieldMultiple'])) {
990
					foreach ($postValues['fieldTitles'] as $key => $value) {
991
						$fieldObject = new \stdClass();
992
						$fieldObject->title = $value;
993
						$fieldObject->slug = slugify($value);
994
						$fieldObject->type = $postValues['fieldTypes'][$key];
995
						$fieldObject->required = ($postValues['fieldRequired'][$key] === 'true');
996
						$fieldObject->multiple = ($postValues['fieldMultiple'][$key] === 'true');
997
						
998
						$documentTypeObject->fields[] = $fieldObject;
999
					}
1000
				}
1001
				if (isset($postValues['brickTitles'], $postValues['brickBricks'])) {
1002
					foreach ($postValues['brickTitles'] as $key => $value) {
1003
						$brickObject = new \stdClass();
1004
						$brickObject->title = $value;
1005
						$brickObject->slug = slugify($value);
1006
						$brickObject->brickSlug = $postValues['brickBricks'][$key];
1007
						$brickObject->multiple = ($postValues['brickMultiples'][$key] === 'true');
1008
1009
						$documentTypeObject->bricks[] = $brickObject;
1010
					}
1011
				}
1012
				return $documentTypeObject;
1013
			} else {
1014
				throw new \Exception('Trying to create document type with invalid data.');
1015
			}
1016
		}
1017
1018
		/**
1019
		 * Delete document type
1020
		 *
1021
		 * @param $slug
1022
		 *
1023
		 * @throws \Exception
1024
		 */
1025
		public function deleteDocumentTypeBySlug($slug)
1026
		{
1027
			$documentTypes = $this->repository->documentTypes;
1028
			foreach ($documentTypes as $key => $documentTypeObject) {
1029
				if ($documentTypeObject->slug == $slug) {
1030
					unset($documentTypes[$key]);
1031
				}
1032
			}
1033
			$documentTypes = array_values($documentTypes);
1034
			$this->repository->documentTypes = $documentTypes;
1035
			$this->save();
1036
		}
1037
1038
		/**
1039
		 * Get document type by its slug
1040
		 *
1041
		 * @param      $slug
1042
		 * @param bool $getBricks
1043
		 *
1044
		 * @return mixed
1045
		 */
1046
		public function getDocumentTypeBySlug($slug, $getBricks = false)
1047
		{
1048
			$documentTypes = $this->repository->documentTypes;
1049
			foreach ($documentTypes as $documentType) {
1050
				if ($documentType->slug == $slug) {
1051
					if ($getBricks === true) {
1052
						foreach ($documentType->bricks as $key => $brick) {
1053
							$brickStructure = $this->getBrickBySlug($brick->brickSlug);
1054
							$documentType->bricks[$key]->structure = $brickStructure;
1055
						}
1056
						foreach ($documentType->dynamicBricks as $key => $brickSlug) {
1057
							$brickStructure = $this->getBrickBySlug($brickSlug);
1058
							$documentType->dynamicBricks[$key] = $brickStructure;
1059
						}
1060
					}
1061
					return $documentType;
1062
				}
1063
			}
1064
			return null;
1065
		}
1066
1067
		/**
1068
		 * Save changes to a document type
1069
		 *
1070
		 * @param $slug
1071
		 * @param $postValues
1072
		 *
1073
		 * @throws \Exception
1074
		 */
1075
		public function saveDocumentType($slug, $postValues)
1076
		{
1077
			$documentTypeObject = $this->createDocumentTypeFromPostValues($postValues);
1078
			
1079
			$documentTypes = $this->repository->documentTypes;
1080
			foreach ($documentTypes as $key => $documentType) {
1081
				if ($documentType->slug == $slug) {
1082
					$documentTypes[$key] = $documentTypeObject;
1083
				}
1084
			}
1085
			$this->repository->documentTypes = $documentTypes;
1086
			$this->save();
1087
		}
1088
		
1089
		/*
1090
		 *
1091
		 * Bricks
1092
		 *
1093
		 */
1094
		/**
1095
		 * @return array
1096
		 */
1097
		public function getBricks()
1098
		{
1099
			return $this->repository->bricks;
1100
		}
1101
1102
		/**
1103
		 * Add a brick
1104
		 *
1105
		 * @param $postValues
1106
		 *
1107
		 * @throws \Exception
1108
		 */
1109
		public function addBrick($postValues)
1110
		{
1111
			$brickObject = $this->createBrickFromPostValues($postValues);
1112
			
1113
			$this->repository->bricks[] = $brickObject;
1114
			$this->save();
1115
		}
1116
1117
		/**
1118
		 * Create a brick from post values
1119
		 *
1120
		 * @param $postValues
1121
		 *
1122
		 * @return \stdClass
1123
		 * @throws \Exception
1124
		 */
1125
		public function createBrickFromPostValues($postValues)
1126
		{
1127
			if (isset($postValues['title'])) {
1128
				$brickObject = new \stdClass();
1129
				$brickObject->title = $postValues['title'];
1130
				$brickObject->slug = slugify($postValues['title']);
1131
				$brickObject->fields = array();
1132
				if (isset($postValues['fieldTitles'], $postValues['fieldTypes'], $postValues['fieldRequired'], $postValues['fieldMultiple'])) {
1133
					foreach ($postValues['fieldTitles'] as $key => $value) {
1134
						$fieldObject = new \stdClass();
1135
						$fieldObject->title = $value;
1136
						$fieldObject->slug = slugify($value);
1137
						$fieldObject->type = $postValues['fieldTypes'][$key];
1138
						$fieldObject->required = ($postValues['fieldRequired'][$key] === 'true');
1139
						$fieldObject->multiple = ($postValues['fieldMultiple'][$key] === 'true');
1140
						
1141
						$brickObject->fields[] = $fieldObject;
1142
					}
1143
				}
1144
				return $brickObject;
1145
			} else {
1146
				throw new \Exception('Trying to create document type with invalid data.');
1147
			}
1148
		}
1149
1150
		/**
1151
		 * Get a brick by its slug
1152
		 *
1153
		 * @param $slug
1154
		 *
1155
		 * @return \stdClass
1156
		 */
1157
		public function getBrickBySlug($slug)
1158
		{
1159
			$bricks = $this->repository->bricks;
1160
			foreach ($bricks as $brick) {
1161
				if ($brick->slug == $slug) {
1162
					return $brick;
1163
				}
1164
			}
1165
			return null;
1166
		}
1167
1168
		/**
1169
		 * Save changes to a brick
1170
		 *
1171
		 * @param $slug
1172
		 * @param $postValues
1173
		 *
1174
		 * @throws \Exception
1175
		 */
1176
		public function saveBrick($slug, $postValues)
1177
		{
1178
			$brickObject = $this->createBrickFromPostValues($postValues);
1179
			
1180
			$bricks = $this->repository->bricks;
1181
			foreach ($bricks as $key => $brick) {
1182
				if ($brick->slug == $slug) {
1183
					$bricks[$key] = $brickObject;
1184
				}
1185
			}
1186
			$this->repository->bricks = $bricks;
1187
			$this->save();
1188
		}
1189
1190
		/**
1191
		 * Delete a brick by its slug
1192
		 *
1193
		 * @param $slug
1194
		 *
1195
		 * @throws \Exception
1196
		 */
1197
		public function deleteBrickBySlug($slug)
1198
		{
1199
			$bricks = $this->repository->bricks;
1200
			foreach ($bricks as $key => $brickObject) {
1201
				if ($brickObject->slug == $slug) {
1202
					unset($bricks[$key]);
1203
				}
1204
			}
1205
			
1206
			$bricks = array_values($bricks);
1207
			$this->repository->bricks = $bricks;
1208
			$this->save();
1209
		}
1210
		
1211
		/*
1212
		 * 
1213
		 * Misc
1214
		 *
1215
		 */
1216
		/**
1217
		 * Save changes made to the repository
1218
		 * in the storagepath
1219
		 *
1220
		 * @throws \Exception
1221
		 */
1222
		private function save() {
1223
			$storagePath = __DIR__ . $this->storagePath;
1224
			if (realpath($storagePath) !== false) {
1225
				copy($storagePath, $storagePath . '.bak');
1226
				file_put_contents($storagePath, json_encode($this->repository));
1227
			} else {
1228
				throw new \Exception('Couldnt find storagePath ' . $storagePath);
1229
			}
1230
		}
1231
1232
		/*
1233
		 *
1234
		 * Image Set
1235
		 *
1236
		 */
1237
1238
		/**
1239
		 * Get the image set
1240
		 *
1241
		 * @return array
1242
		 */
1243
		public function getImageSet()
1244
		{
1245
			return $this->repository->imageSet;
1246
		}
1247
1248
		/**
1249
		 * Get Image by slug
1250
		 *
1251
		 * @param $slug
1252
		 *
1253
		 * @return \stdClass
1254
		 */
1255
		public function getImageSetBySlug($slug)
1256
		{
1257
			$imageSet = $this->getImageSet();
1258
			foreach ($imageSet as $set) {
1259
				if ($set->slug == $slug) {
1260
					return $set;
1261
				}
1262
			}
1263
			return null;
1264
		}
1265
1266
		/**
1267
		 * Save Image Set by it's slug
1268
		 *
1269
		 * @param $slug
1270
		 * @param $postValues
1271
		 *
1272
		 * @throws \Exception
1273
		 */
1274
		public function saveImageSet($slug, $postValues)
1275
		{
1276
			$imageSetObject = $this->createImageSetFromPostValues($postValues);
1277
1278
			$imageSet = $this->repository->imageSet;
1279
			foreach ($imageSet as $key => $set) {
1280
				if ($set->slug == $slug) {
1281
					$imageSet[$key] = $imageSetObject;
1282
				}
1283
			}
1284
			$this->repository->imageSet = $imageSet;
1285
			$this->save();
1286
		}
1287
1288
		/**
1289
		 * Ceate image set from post values
1290
		 *
1291
		 * @param $postValues
1292
		 *
1293
		 * @return \stdClass
1294
		 * @throws \Exception
1295
		 */
1296
		private function createImageSetFromPostValues($postValues)
1297
		{
1298
			if (isset($postValues['title'], $postValues['width'], $postValues['height'], $postValues['method'])) {
1299
				$imageSetObject = new \stdClass();
1300
1301
				$imageSetObject->title = $postValues['title'];
1302
				$imageSetObject->slug = slugify($postValues['title']);
1303
				$imageSetObject->width = $postValues['width'];
1304
				$imageSetObject->height = $postValues['height'];
1305
				$imageSetObject->method = $postValues['method'];
1306
1307
				return $imageSetObject;
1308
			} else {
1309
				throw new \Exception('Trying to create image set with invalid data.');
1310
			}
1311
		}
1312
1313
		/**
1314
		 * Add image set
1315
		 *
1316
		 * @param $postValues
1317
		 *
1318
		 * @throws \Exception
1319
		 */
1320
		public function addImageSet($postValues)
1321
		{
1322
			$imageSetObject = $this->createImageSetFromPostValues($postValues);
1323
1324
			$this->repository->imageSet[] = $imageSetObject;
1325
1326
			$this->save();
1327
		}
1328
1329
		/**
1330
		 * Delete Image Set by its slug
1331
		 *
1332
		 * @param $slug
1333
		 *
1334
		 * @throws \Exception
1335
		 */
1336
		public function deleteImageSetBySlug($slug)
1337
		{
1338
			$imageSet = $this->getImageSet();
1339
1340
			foreach ($imageSet as $key => $set) {
1341
				if ($set->slug == $slug) {
1342
					unset($imageSet[$key]);
1343
				}
1344
			}
1345
			$imageSet = array_values($imageSet);
1346
			$this->repository->imageSet = $imageSet;
1347
			$this->save();
1348
		}
1349
1350
		/**
1351
		 * Get the image set with the smallest size
1352
		 *
1353
		 * @return \stdClass
1354
		 */
1355
		public function getSmallestImageSet()
1356
		{
1357
			$imageSet = $this->getImageSet();
1358
1359
			$returnSize = PHP_INT_MAX;
1360
			$returnSet = null;
1361
1362
			foreach ($imageSet as $set) {
1363
				$size = $set->width * $set->height;
1364
				if ($size < $returnSize) {
1365
					$returnSize = $size;
1366
					$returnSet = $set;
1367
				}
1368
			}
1369
1370
			if ($returnSet === null) {
1371
				$returnSet = new \stdClass();
1372
				$returnSet->slug = 'original';
1373
			}
1374
1375
			return $returnSet;
1376
		}
1377
1378
		/**
1379
		 * @return array
1380
		 */
1381
		public function getApplicationComponents()
1382
		{
1383
			return $this->repository->applicationComponents;
1384
		}
1385
1386
		public function addApplicationComponent($postValues)
1387
		{
1388
			$applicationComponent = $this->createApplicationComponentFromPostValues($postValues);
1389
1390
			$this->repository->applicationComponents[] = $applicationComponent;
1391
			$this->save();
1392
		}
1393
1394
		private function createApplicationComponentFromPostValues($postValues)
1395
		{
1396
			if (isset($postValues['title'], $postValues['component'])) {
1397
				$applicationComponent = new \stdClass();
1398
				$applicationComponent->title = $postValues['title'];
1399
				$applicationComponent->slug = slugify($postValues['title']);
1400
				$applicationComponent->component = $postValues['component'];
1401
				$applicationComponent->parameters = new \stdClass();
1402
				if (isset($postValues['parameterNames'], $postValues['parameterValues'])) {
1403
					foreach ($postValues['parameterNames'] as $key => $value) {
1404
						$applicationComponent->parameters->$value = $postValues['parameterValues'][$key];
1405
					}
1406
				}
1407
				return $applicationComponent;
1408
			} else {
1409
				throw new \Exception('Trying to create application component with invalid data.');
1410
			}
1411
		}
1412
1413
		public function getApplicationComponentBySlug($slug)
1414
		{
1415
			$applicationComponents = $this->getApplicationComponents();
1416
			foreach ($applicationComponents as $applicationComponent) {
1417
				if ($applicationComponent->slug == $slug) {
1418
					return $applicationComponent;
1419
				}
1420
			}
1421
			return null;
1422
		}
1423
1424
		public function saveApplicationComponent($slug, $postValues)
1425
		{
1426
			$newApplicationComponent = $this->createApplicationComponentFromPostValues($postValues);
1427
1428
			$applicationComponents = $this->getApplicationComponents();
1429
			foreach ($applicationComponents as $key => $applicationComponent) {
1430
				if ($applicationComponent->slug == $slug) {
1431
					$applicationComponents[$key] = $newApplicationComponent;
1432
				}
1433
			}
1434
			$this->repository->applicationComponents = $applicationComponents;
1435
			$this->save();
1436
		}
1437
1438
		public function deleteApplicationComponentBySlug($slug)
1439
		{
1440
			$applicationComponents = $this->getApplicationComponents();
1441
			foreach ($applicationComponents as $key => $applicationComponent) {
1442
				if ($applicationComponent->slug == $slug) {
1443
					unset($applicationComponents[$key]);
1444
				}
1445
			}
1446
			$applicationComponents = array_values($applicationComponents);
1447
			$this->repository->applicationComponents = $applicationComponents;
1448
			$this->save();
1449
		}
1450
	}
1451
}