GroupDomainTrait::doRemoveActions()   A
last analyzed

Complexity

Conditions 4
Paths 6

Size

Total Lines 15
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 15
rs 9.2
cc 4
eloc 10
nc 6
nop 2
1
<?php
2
namespace keeko\core\domain\base;
3
4
use keeko\core\event\GroupEvent;
5
use keeko\core\model\ActionQuery;
6
use keeko\core\model\GroupActionQuery;
7
use keeko\core\model\GroupQuery;
8
use keeko\core\model\Group;
9
use keeko\core\model\UserGroupQuery;
10
use keeko\core\model\UserQuery;
11
use keeko\framework\domain\payload\Created;
12
use keeko\framework\domain\payload\Deleted;
13
use keeko\framework\domain\payload\Found;
14
use keeko\framework\domain\payload\NotDeleted;
15
use keeko\framework\domain\payload\NotFound;
16
use keeko\framework\domain\payload\NotUpdated;
17
use keeko\framework\domain\payload\NotValid;
18
use keeko\framework\domain\payload\PayloadInterface;
19
use keeko\framework\domain\payload\Updated;
20
use keeko\framework\exceptions\ErrorsException;
21
use keeko\framework\service\ServiceContainer;
22
use keeko\framework\utils\NameUtils;
23
use keeko\framework\utils\Parameters;
24
use phootwork\collection\Map;
25
26
/**
27
 */
28
trait GroupDomainTrait {
29
30
	/**
31
	 */
32
	protected $pool;
33
34
	/**
35
	 * Adds Actions to Group
36
	 * 
37
	 * @param mixed $id
38
	 * @param mixed $data
39
	 * @return PayloadInterface
40
	 */
41
	public function addActions($id, $data) {
42
		// find
43
		$model = $this->get($id);
44
45
		if ($model === null) {
46
			return new NotFound(['message' => 'Group not found.']);
47
		}
48
49
		// pass add to internal logic
50
		try {
51
			$this->doAddActions($model, $data);
52
		} catch (ErrorsException $e) {
0 ignored issues
show
Bug introduced by
The class keeko\framework\exceptions\ErrorsException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
53
			return new NotValid(['errors' => $e->getErrors()]);
54
		}
55
56
		// save and dispatch events
57
		$this->dispatch(GroupEvent::PRE_ACTIONS_ADD, $model, $data);
58
		$this->dispatch(GroupEvent::PRE_SAVE, $model, $data);
59
		$rows = $model->save();
60
		$this->dispatch(GroupEvent::POST_ACTIONS_ADD, $model, $data);
61
		$this->dispatch(GroupEvent::POST_SAVE, $model, $data);
62
63
		if ($rows > 0) {
64
			return Updated(['model' => $model]);
65
		}
66
67
		return NotUpdated(['model' => $model]);
68
	}
69
70
	/**
71
	 * Adds Users to Group
72
	 * 
73
	 * @param mixed $id
74
	 * @param mixed $data
75
	 * @return PayloadInterface
76
	 */
77
	public function addUsers($id, $data) {
78
		// find
79
		$model = $this->get($id);
80
81
		if ($model === null) {
82
			return new NotFound(['message' => 'Group not found.']);
83
		}
84
85
		// pass add to internal logic
86
		try {
87
			$this->doAddUsers($model, $data);
88
		} catch (ErrorsException $e) {
0 ignored issues
show
Bug introduced by
The class keeko\framework\exceptions\ErrorsException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
89
			return new NotValid(['errors' => $e->getErrors()]);
90
		}
91
92
		// save and dispatch events
93
		$this->dispatch(GroupEvent::PRE_USERS_ADD, $model, $data);
94
		$this->dispatch(GroupEvent::PRE_SAVE, $model, $data);
95
		$rows = $model->save();
96
		$this->dispatch(GroupEvent::POST_USERS_ADD, $model, $data);
97
		$this->dispatch(GroupEvent::POST_SAVE, $model, $data);
98
99
		if ($rows > 0) {
100
			return Updated(['model' => $model]);
101
		}
102
103
		return NotUpdated(['model' => $model]);
104
	}
105
106
	/**
107
	 * Creates a new Group with the provided data
108
	 * 
109
	 * @param mixed $data
110
	 * @return PayloadInterface
111
	 */
112
	public function create($data) {
113
		// hydrate
114
		$serializer = Group::getSerializer();
115
		$model = $serializer->hydrate(new Group(), $data);
116
		$this->hydrateRelationships($model, $data);
0 ignored issues
show
Bug introduced by
It seems like hydrateRelationships() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
117
118
		// dispatch pre save hooks
119
		$this->dispatch(GroupEvent::PRE_CREATE, $model, $data);
120
		$this->dispatch(GroupEvent::PRE_SAVE, $model, $data);
121
122
		// validate
123
		$validator = $this->getValidator();
0 ignored issues
show
Bug introduced by
It seems like getValidator() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
124
		if ($validator !== null && !$validator->validate($model)) {
125
			return new NotValid([
126
				'errors' => $validator->getValidationFailures()
127
			]);
128
		}
129
130
		// save and dispatch post save hooks
131
		$model->save();
132
		$this->dispatch(GroupEvent::POST_CREATE, $model, $data);
133
		$this->dispatch(GroupEvent::POST_SAVE, $model, $data);
134
135
		return new Created(['model' => $model]);
136
	}
137
138
	/**
139
	 * Deletes a Group with the given id
140
	 * 
141
	 * @param mixed $id
142
	 * @return PayloadInterface
143
	 */
144
	public function delete($id) {
145
		// find
146
		$model = $this->get($id);
147
148
		if ($model === null) {
149
			return new NotFound(['message' => 'Group not found.']);
150
		}
151
152
		// delete
153
		$this->dispatch(GroupEvent::PRE_DELETE, $model);
154
		$model->delete();
155
156
		if ($model->isDeleted()) {
157
			$this->dispatch(GroupEvent::POST_DELETE, $model);
158
			return new Deleted(['model' => $model]);
159
		}
160
161
		return new NotDeleted(['message' => 'Could not delete Group']);
162
	}
163
164
	/**
165
	 * Returns a paginated result
166
	 * 
167
	 * @param Parameters $params
168
	 * @return PayloadInterface
169
	 */
170
	public function paginate(Parameters $params) {
171
		$sysPrefs = $this->getServiceContainer()->getPreferenceLoader()->getSystemPreferences();
172
		$defaultSize = $sysPrefs->getPaginationSize();
173
		$page = $params->getPage('number');
174
		$size = $params->getPage('size', $defaultSize);
175
176
		$query = GroupQuery::create();
177
178
		// sorting
179
		$sort = $params->getSort(Group::getSerializer()->getSortFields());
180
		foreach ($sort as $field => $order) {
181
			$method = 'orderBy' . NameUtils::toStudlyCase($field);
182
			$query->$method($order);
183
		}
184
185
		// filtering
186
		$filter = $params->getFilter();
187
		if (!empty($filter)) {
188
			$this->applyFilter($query, $filter);
189
		}
190
191
		// paginate
192
		$model = $query->paginate($page, $size);
193
194
		// run response
195
		return new Found(['model' => $model]);
196
	}
197
198
	/**
199
	 * Returns one Group with the given id
200
	 * 
201
	 * @param mixed $id
202
	 * @return PayloadInterface
203
	 */
204
	public function read($id) {
205
		// read
206
		$model = $this->get($id);
207
208
		// check existence
209
		if ($model === null) {
210
			return new NotFound(['message' => 'Group not found.']);
211
		}
212
213
		return new Found(['model' => $model]);
214
	}
215
216
	/**
217
	 * Removes Actions from Group
218
	 * 
219
	 * @param mixed $id
220
	 * @param mixed $data
221
	 * @return PayloadInterface
222
	 */
223
	public function removeActions($id, $data) {
224
		// find
225
		$model = $this->get($id);
226
227
		if ($model === null) {
228
			return new NotFound(['message' => 'Group not found.']);
229
		}
230
231
		// pass remove to internal logic
232
		try {
233
			$this->doRemoveActions($model, $data);
234
		} catch (ErrorsException $e) {
0 ignored issues
show
Bug introduced by
The class keeko\framework\exceptions\ErrorsException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
235
			return new NotValid(['errors' => $e->getErrors()]);
236
		}
237
238
		// save and dispatch events
239
		$this->dispatch(GroupEvent::PRE_ACTIONS_REMOVE, $model, $data);
240
		$this->dispatch(GroupEvent::PRE_SAVE, $model, $data);
241
		$rows = $model->save();
242
		$this->dispatch(GroupEvent::POST_ACTIONS_REMOVE, $model, $data);
243
		$this->dispatch(GroupEvent::POST_SAVE, $model, $data);
244
245
		if ($rows > 0) {
246
			return Updated(['model' => $model]);
247
		}
248
249
		return NotUpdated(['model' => $model]);
250
	}
251
252
	/**
253
	 * Removes Users from Group
254
	 * 
255
	 * @param mixed $id
256
	 * @param mixed $data
257
	 * @return PayloadInterface
258
	 */
259
	public function removeUsers($id, $data) {
260
		// find
261
		$model = $this->get($id);
262
263
		if ($model === null) {
264
			return new NotFound(['message' => 'Group not found.']);
265
		}
266
267
		// pass remove to internal logic
268
		try {
269
			$this->doRemoveUsers($model, $data);
270
		} catch (ErrorsException $e) {
0 ignored issues
show
Bug introduced by
The class keeko\framework\exceptions\ErrorsException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
271
			return new NotValid(['errors' => $e->getErrors()]);
272
		}
273
274
		// save and dispatch events
275
		$this->dispatch(GroupEvent::PRE_USERS_REMOVE, $model, $data);
276
		$this->dispatch(GroupEvent::PRE_SAVE, $model, $data);
277
		$rows = $model->save();
278
		$this->dispatch(GroupEvent::POST_USERS_REMOVE, $model, $data);
279
		$this->dispatch(GroupEvent::POST_SAVE, $model, $data);
280
281
		if ($rows > 0) {
282
			return Updated(['model' => $model]);
283
		}
284
285
		return NotUpdated(['model' => $model]);
286
	}
287
288
	/**
289
	 * Updates a Group with the given idand the provided data
290
	 * 
291
	 * @param mixed $id
292
	 * @param mixed $data
293
	 * @return PayloadInterface
294
	 */
295
	public function update($id, $data) {
296
		// find
297
		$model = $this->get($id);
298
299
		if ($model === null) {
300
			return new NotFound(['message' => 'Group not found.']);
301
		}
302
303
		// hydrate
304
		$serializer = Group::getSerializer();
305
		$model = $serializer->hydrate($model, $data);
306
		$this->hydrateRelationships($model, $data);
0 ignored issues
show
Bug introduced by
It seems like hydrateRelationships() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
307
308
		// dispatch pre save hooks
309
		$this->dispatch(GroupEvent::PRE_UPDATE, $model, $data);
310
		$this->dispatch(GroupEvent::PRE_SAVE, $model, $data);
311
312
		// validate
313
		$validator = $this->getValidator();
0 ignored issues
show
Bug introduced by
It seems like getValidator() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
314
		if ($validator !== null && !$validator->validate($model)) {
315
			return new NotValid([
316
				'errors' => $validator->getValidationFailures()
317
			]);
318
		}
319
320
		// save and dispath post save hooks
321
		$rows = $model->save();
322
		$this->dispatch(GroupEvent::POST_UPDATE, $model, $data);
323
		$this->dispatch(GroupEvent::POST_SAVE, $model, $data);
324
325
		$payload = ['model' => $model];
326
327
		if ($rows === 0) {
328
			return new NotUpdated($payload);
329
		}
330
331
		return new Updated($payload);
332
	}
333
334
	/**
335
	 * Updates Actions on Group
336
	 * 
337
	 * @param mixed $id
338
	 * @param mixed $data
339
	 * @return PayloadInterface
340
	 */
341
	public function updateActions($id, $data) {
342
		// find
343
		$model = $this->get($id);
344
345
		if ($model === null) {
346
			return new NotFound(['message' => 'Group not found.']);
347
		}
348
349
		// pass update to internal logic
350
		try {
351
			$this->doUpdateActions($model, $data);
352
		} catch (ErrorsException $e) {
0 ignored issues
show
Bug introduced by
The class keeko\framework\exceptions\ErrorsException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
353
			return new NotValid(['errors' => $e->getErrors()]);
354
		}
355
356
		// save and dispatch events
357
		$this->dispatch(GroupEvent::PRE_ACTIONS_UPDATE, $model, $data);
358
		$this->dispatch(GroupEvent::PRE_SAVE, $model, $data);
359
		$rows = $model->save();
360
		$this->dispatch(GroupEvent::POST_ACTIONS_UPDATE, $model, $data);
361
		$this->dispatch(GroupEvent::POST_SAVE, $model, $data);
362
363
		if ($rows > 0) {
364
			return Updated(['model' => $model]);
365
		}
366
367
		return NotUpdated(['model' => $model]);
368
	}
369
370
	/**
371
	 * Updates Users on Group
372
	 * 
373
	 * @param mixed $id
374
	 * @param mixed $data
375
	 * @return PayloadInterface
376
	 */
377
	public function updateUsers($id, $data) {
378
		// find
379
		$model = $this->get($id);
380
381
		if ($model === null) {
382
			return new NotFound(['message' => 'Group not found.']);
383
		}
384
385
		// pass update to internal logic
386
		try {
387
			$this->doUpdateUsers($model, $data);
388
		} catch (ErrorsException $e) {
0 ignored issues
show
Bug introduced by
The class keeko\framework\exceptions\ErrorsException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
389
			return new NotValid(['errors' => $e->getErrors()]);
390
		}
391
392
		// save and dispatch events
393
		$this->dispatch(GroupEvent::PRE_USERS_UPDATE, $model, $data);
394
		$this->dispatch(GroupEvent::PRE_SAVE, $model, $data);
395
		$rows = $model->save();
396
		$this->dispatch(GroupEvent::POST_USERS_UPDATE, $model, $data);
397
		$this->dispatch(GroupEvent::POST_SAVE, $model, $data);
398
399
		if ($rows > 0) {
400
			return Updated(['model' => $model]);
401
		}
402
403
		return NotUpdated(['model' => $model]);
404
	}
405
406
	/**
407
	 * @param mixed $query
408
	 * @param mixed $filter
409
	 * @return void
410
	 */
411
	protected function applyFilter($query, $filter) {
412
		foreach ($filter as $column => $value) {
413
			$pos = strpos($column, '.');
414
			if ($pos !== false) {
415
				$rel = NameUtils::toStudlyCase(substr($column, 0, $pos));
416
				$col = substr($column, $pos + 1);
417
				$method = 'use' . $rel . 'Query';
418
				if (method_exists($query, $method)) {
419
					$sub = $query->$method();
420
					$this->applyFilter($sub, [$col => $value]);
421
					$sub->endUse();
422
				}
423
			} else {
424
				$method = 'filterBy' . NameUtils::toStudlyCase($column);
425
				if (method_exists($query, $method)) {
426
					$query->$method($value);
427
				}
428
			}
429
		}
430
	}
431
432
	/**
433
	 * @param string $type
434
	 * @param Group $model
435
	 * @param array $data
436
	 */
437
	protected function dispatch($type, Group $model, array $data = []) {
438
		$methods = [
439
			GroupEvent::PRE_CREATE => 'preCreate',
440
			GroupEvent::POST_CREATE => 'postCreate',
441
			GroupEvent::PRE_UPDATE => 'preUpdate',
442
			GroupEvent::POST_UPDATE => 'postUpdate',
443
			GroupEvent::PRE_DELETE => 'preDelete',
444
			GroupEvent::POST_DELETE => 'postDelete',
445
			GroupEvent::PRE_SAVE => 'preSave',
446
			GroupEvent::POST_SAVE => 'postSave'
447
		];
448
449
		if (isset($methods[$type])) {
450
			$method = $methods[$type];
451
			if (method_exists($this, $method)) {
452
				$this->$method($model, $data);
453
			}
454
		}
455
456
		$dispatcher = $this->getServiceContainer()->getDispatcher();
457
		$dispatcher->dispatch($type, new GroupEvent($model));
458
	}
459
460
	/**
461
	 * Interal mechanism to add Actions to Group
462
	 * 
463
	 * @param Group $model
464
	 * @param mixed $data
465
	 */
466
	protected function doAddActions(Group $model, $data) {
467
		$errors = [];
468
		foreach ($data as $entry) {
469
			if (!isset($entry['id'])) {
470
				$errors[] = 'Missing id for Action';
471
			} else {
472
				$related = ActionQuery::create()->findOneById($entry['id']);
473
				$model->addAction($related);
474
			}
475
		}
476
477
		if (count($errors) > 0) {
478
			return new ErrorsException($errors);
479
		}
480
	}
481
482
	/**
483
	 * Interal mechanism to add Users to Group
484
	 * 
485
	 * @param Group $model
486
	 * @param mixed $data
487
	 */
488
	protected function doAddUsers(Group $model, $data) {
489
		$errors = [];
490
		foreach ($data as $entry) {
491
			if (!isset($entry['id'])) {
492
				$errors[] = 'Missing id for User';
493
			} else {
494
				$related = UserQuery::create()->findOneById($entry['id']);
495
				$model->addUser($related);
496
			}
497
		}
498
499
		if (count($errors) > 0) {
500
			return new ErrorsException($errors);
501
		}
502
	}
503
504
	/**
505
	 * Interal mechanism to remove Actions from Group
506
	 * 
507
	 * @param Group $model
508
	 * @param mixed $data
509
	 */
510
	protected function doRemoveActions(Group $model, $data) {
511
		$errors = [];
512
		foreach ($data as $entry) {
513
			if (!isset($entry['id'])) {
514
				$errors[] = 'Missing id for Action';
515
			} else {
516
				$related = ActionQuery::create()->findOneById($entry['id']);
517
				$model->removeAction($related);
518
			}
519
		}
520
521
		if (count($errors) > 0) {
522
			return new ErrorsException($errors);
523
		}
524
	}
525
526
	/**
527
	 * Interal mechanism to remove Users from Group
528
	 * 
529
	 * @param Group $model
530
	 * @param mixed $data
531
	 */
532
	protected function doRemoveUsers(Group $model, $data) {
533
		$errors = [];
534
		foreach ($data as $entry) {
535
			if (!isset($entry['id'])) {
536
				$errors[] = 'Missing id for User';
537
			} else {
538
				$related = UserQuery::create()->findOneById($entry['id']);
539
				$model->removeUser($related);
540
			}
541
		}
542
543
		if (count($errors) > 0) {
544
			return new ErrorsException($errors);
545
		}
546
	}
547
548
	/**
549
	 * Internal update mechanism of Actions on Group
550
	 * 
551
	 * @param Group $model
552
	 * @param mixed $data
553
	 */
554
	protected function doUpdateActions(Group $model, $data) {
555
		// remove all relationships before
556
		GroupActionQuery::create()->filterByGroup($model)->delete();
557
558
		// add them
559
		$errors = [];
560
		foreach ($data as $entry) {
561
			if (!isset($entry['id'])) {
562
				$errors[] = 'Missing id for Action';
563
			} else {
564
				$related = ActionQuery::create()->findOneById($entry['id']);
565
				$model->addAction($related);
566
			}
567
		}
568
569
		if (count($errors) > 0) {
570
			throw new ErrorsException($errors);
571
		}
572
	}
573
574
	/**
575
	 * Internal update mechanism of Users on Group
576
	 * 
577
	 * @param Group $model
578
	 * @param mixed $data
579
	 */
580
	protected function doUpdateUsers(Group $model, $data) {
581
		// remove all relationships before
582
		UserGroupQuery::create()->filterByGroup($model)->delete();
583
584
		// add them
585
		$errors = [];
586
		foreach ($data as $entry) {
587
			if (!isset($entry['id'])) {
588
				$errors[] = 'Missing id for User';
589
			} else {
590
				$related = UserQuery::create()->findOneById($entry['id']);
591
				$model->addUser($related);
592
			}
593
		}
594
595
		if (count($errors) > 0) {
596
			throw new ErrorsException($errors);
597
		}
598
	}
599
600
	/**
601
	 * Returns one Group with the given id from cache
602
	 * 
603
	 * @param mixed $id
604
	 * @return Group|null
605
	 */
606
	protected function get($id) {
607
		if ($this->pool === null) {
608
			$this->pool = new Map();
609
		} else if ($this->pool->has($id)) {
610
			return $this->pool->get($id);
611
		}
612
613
		$model = GroupQuery::create()->findOneById($id);
614
		$this->pool->set($id, $model);
615
616
		return $model;
617
	}
618
619
	/**
620
	 * Returns the service container
621
	 * 
622
	 * @return ServiceContainer
623
	 */
624
	abstract protected function getServiceContainer();
625
}
626