ActionDomainTrait::doAddApis()   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\ActionEvent;
5
use keeko\core\model\ActionQuery;
6
use keeko\core\model\Action;
7
use keeko\core\model\ApiQuery;
8
use keeko\core\model\GroupActionQuery;
9
use keeko\core\model\GroupQuery;
10
use keeko\framework\domain\payload\Created;
11
use keeko\framework\domain\payload\Deleted;
12
use keeko\framework\domain\payload\Found;
13
use keeko\framework\domain\payload\NotDeleted;
14
use keeko\framework\domain\payload\NotFound;
15
use keeko\framework\domain\payload\NotUpdated;
16
use keeko\framework\domain\payload\NotValid;
17
use keeko\framework\domain\payload\PayloadInterface;
18
use keeko\framework\domain\payload\Updated;
19
use keeko\framework\exceptions\ErrorsException;
20
use keeko\framework\service\ServiceContainer;
21
use keeko\framework\utils\NameUtils;
22
use keeko\framework\utils\Parameters;
23
use phootwork\collection\Map;
24
25
/**
26
 */
27
trait ActionDomainTrait {
28
29
	/**
30
	 */
31
	protected $pool;
32
33
	/**
34
	 * Adds Apis to Action
35
	 * 
36
	 * @param mixed $id
37
	 * @param mixed $data
38
	 * @return PayloadInterface
39
	 */
40
	public function addApis($id, $data) {
41
		// find
42
		$model = $this->get($id);
43
44
		if ($model === null) {
45
			return new NotFound(['message' => 'Action not found.']);
46
		}
47
48
		// pass add to internal logic
49
		try {
50
			$this->doAddApis($model, $data);
51
		} 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...
52
			return new NotValid(['errors' => $e->getErrors()]);
53
		}
54
55
		// save and dispatch events
56
		$this->dispatch(ActionEvent::PRE_APIS_ADD, $model, $data);
57
		$this->dispatch(ActionEvent::PRE_SAVE, $model, $data);
58
		$rows = $model->save();
59
		$this->dispatch(ActionEvent::POST_APIS_ADD, $model, $data);
60
		$this->dispatch(ActionEvent::POST_SAVE, $model, $data);
61
62
		if ($rows > 0) {
63
			return Updated(['model' => $model]);
64
		}
65
66
		return NotUpdated(['model' => $model]);
67
	}
68
69
	/**
70
	 * Adds Groups to Action
71
	 * 
72
	 * @param mixed $id
73
	 * @param mixed $data
74
	 * @return PayloadInterface
75
	 */
76
	public function addGroups($id, $data) {
77
		// find
78
		$model = $this->get($id);
79
80
		if ($model === null) {
81
			return new NotFound(['message' => 'Action not found.']);
82
		}
83
84
		// pass add to internal logic
85
		try {
86
			$this->doAddGroups($model, $data);
87
		} 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...
88
			return new NotValid(['errors' => $e->getErrors()]);
89
		}
90
91
		// save and dispatch events
92
		$this->dispatch(ActionEvent::PRE_GROUPS_ADD, $model, $data);
93
		$this->dispatch(ActionEvent::PRE_SAVE, $model, $data);
94
		$rows = $model->save();
95
		$this->dispatch(ActionEvent::POST_GROUPS_ADD, $model, $data);
96
		$this->dispatch(ActionEvent::POST_SAVE, $model, $data);
97
98
		if ($rows > 0) {
99
			return Updated(['model' => $model]);
100
		}
101
102
		return NotUpdated(['model' => $model]);
103
	}
104
105
	/**
106
	 * Creates a new Action with the provided data
107
	 * 
108
	 * @param mixed $data
109
	 * @return PayloadInterface
110
	 */
111
	public function create($data) {
112
		// hydrate
113
		$serializer = Action::getSerializer();
114
		$model = $serializer->hydrate(new Action(), $data);
115
		$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...
116
117
		// dispatch pre save hooks
118
		$this->dispatch(ActionEvent::PRE_CREATE, $model, $data);
119
		$this->dispatch(ActionEvent::PRE_SAVE, $model, $data);
120
121
		// validate
122
		$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...
123
		if ($validator !== null && !$validator->validate($model)) {
124
			return new NotValid([
125
				'errors' => $validator->getValidationFailures()
126
			]);
127
		}
128
129
		// save and dispatch post save hooks
130
		$model->save();
131
		$this->dispatch(ActionEvent::POST_CREATE, $model, $data);
132
		$this->dispatch(ActionEvent::POST_SAVE, $model, $data);
133
134
		return new Created(['model' => $model]);
135
	}
136
137
	/**
138
	 * Deletes a Action with the given id
139
	 * 
140
	 * @param mixed $id
141
	 * @return PayloadInterface
142
	 */
143
	public function delete($id) {
144
		// find
145
		$model = $this->get($id);
146
147
		if ($model === null) {
148
			return new NotFound(['message' => 'Action not found.']);
149
		}
150
151
		// delete
152
		$this->dispatch(ActionEvent::PRE_DELETE, $model);
153
		$model->delete();
154
155
		if ($model->isDeleted()) {
156
			$this->dispatch(ActionEvent::POST_DELETE, $model);
157
			return new Deleted(['model' => $model]);
158
		}
159
160
		return new NotDeleted(['message' => 'Could not delete Action']);
161
	}
162
163
	/**
164
	 * Returns a paginated result
165
	 * 
166
	 * @param Parameters $params
167
	 * @return PayloadInterface
168
	 */
169
	public function paginate(Parameters $params) {
170
		$sysPrefs = $this->getServiceContainer()->getPreferenceLoader()->getSystemPreferences();
171
		$defaultSize = $sysPrefs->getPaginationSize();
172
		$page = $params->getPage('number');
173
		$size = $params->getPage('size', $defaultSize);
174
175
		$query = ActionQuery::create();
176
177
		// sorting
178
		$sort = $params->getSort(Action::getSerializer()->getSortFields());
179
		foreach ($sort as $field => $order) {
180
			$method = 'orderBy' . NameUtils::toStudlyCase($field);
181
			$query->$method($order);
182
		}
183
184
		// filtering
185
		$filter = $params->getFilter();
186
		if (!empty($filter)) {
187
			$this->applyFilter($query, $filter);
188
		}
189
190
		// paginate
191
		$model = $query->paginate($page, $size);
192
193
		// run response
194
		return new Found(['model' => $model]);
195
	}
196
197
	/**
198
	 * Returns one Action with the given id
199
	 * 
200
	 * @param mixed $id
201
	 * @return PayloadInterface
202
	 */
203
	public function read($id) {
204
		// read
205
		$model = $this->get($id);
206
207
		// check existence
208
		if ($model === null) {
209
			return new NotFound(['message' => 'Action not found.']);
210
		}
211
212
		return new Found(['model' => $model]);
213
	}
214
215
	/**
216
	 * Removes Apis from Action
217
	 * 
218
	 * @param mixed $id
219
	 * @param mixed $data
220
	 * @return PayloadInterface
221
	 */
222
	public function removeApis($id, $data) {
223
		// find
224
		$model = $this->get($id);
225
226
		if ($model === null) {
227
			return new NotFound(['message' => 'Action not found.']);
228
		}
229
230
		// pass remove to internal logic
231
		try {
232
			$this->doRemoveApis($model, $data);
233
		} 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...
234
			return new NotValid(['errors' => $e->getErrors()]);
235
		}
236
237
		// save and dispatch events
238
		$this->dispatch(ActionEvent::PRE_APIS_REMOVE, $model, $data);
239
		$this->dispatch(ActionEvent::PRE_SAVE, $model, $data);
240
		$rows = $model->save();
241
		$this->dispatch(ActionEvent::POST_APIS_REMOVE, $model, $data);
242
		$this->dispatch(ActionEvent::POST_SAVE, $model, $data);
243
244
		if ($rows > 0) {
245
			return Updated(['model' => $model]);
246
		}
247
248
		return NotUpdated(['model' => $model]);
249
	}
250
251
	/**
252
	 * Removes Groups from Action
253
	 * 
254
	 * @param mixed $id
255
	 * @param mixed $data
256
	 * @return PayloadInterface
257
	 */
258
	public function removeGroups($id, $data) {
259
		// find
260
		$model = $this->get($id);
261
262
		if ($model === null) {
263
			return new NotFound(['message' => 'Action not found.']);
264
		}
265
266
		// pass remove to internal logic
267
		try {
268
			$this->doRemoveGroups($model, $data);
269
		} 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...
270
			return new NotValid(['errors' => $e->getErrors()]);
271
		}
272
273
		// save and dispatch events
274
		$this->dispatch(ActionEvent::PRE_GROUPS_REMOVE, $model, $data);
275
		$this->dispatch(ActionEvent::PRE_SAVE, $model, $data);
276
		$rows = $model->save();
277
		$this->dispatch(ActionEvent::POST_GROUPS_REMOVE, $model, $data);
278
		$this->dispatch(ActionEvent::POST_SAVE, $model, $data);
279
280
		if ($rows > 0) {
281
			return Updated(['model' => $model]);
282
		}
283
284
		return NotUpdated(['model' => $model]);
285
	}
286
287
	/**
288
	 * Sets the Module id
289
	 * 
290
	 * @param mixed $id
291
	 * @param mixed $relatedId
292
	 * @return PayloadInterface
293
	 */
294
	public function setModuleId($id, $relatedId) {
295
		// find
296
		$model = $this->get($id);
297
298
		if ($model === null) {
299
			return new NotFound(['message' => 'Action not found.']);
300
		}
301
302
		// update
303
		if ($this->doSetModuleId($model, $relatedId)) {
304
			$this->dispatch(ActionEvent::PRE_MODULE_UPDATE, $model);
305
			$this->dispatch(ActionEvent::PRE_SAVE, $model);
306
			$model->save();
307
			$this->dispatch(ActionEvent::POST_MODULE_UPDATE, $model);
308
			$this->dispatch(ActionEvent::POST_SAVE, $model);
309
310
			return Updated(['model' => $model]);
311
		}
312
313
		return NotUpdated(['model' => $model]);
314
	}
315
316
	/**
317
	 * Updates a Action with the given idand the provided data
318
	 * 
319
	 * @param mixed $id
320
	 * @param mixed $data
321
	 * @return PayloadInterface
322
	 */
323
	public function update($id, $data) {
324
		// find
325
		$model = $this->get($id);
326
327
		if ($model === null) {
328
			return new NotFound(['message' => 'Action not found.']);
329
		}
330
331
		// hydrate
332
		$serializer = Action::getSerializer();
333
		$model = $serializer->hydrate($model, $data);
334
		$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...
335
336
		// dispatch pre save hooks
337
		$this->dispatch(ActionEvent::PRE_UPDATE, $model, $data);
338
		$this->dispatch(ActionEvent::PRE_SAVE, $model, $data);
339
340
		// validate
341
		$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...
342
		if ($validator !== null && !$validator->validate($model)) {
343
			return new NotValid([
344
				'errors' => $validator->getValidationFailures()
345
			]);
346
		}
347
348
		// save and dispath post save hooks
349
		$rows = $model->save();
350
		$this->dispatch(ActionEvent::POST_UPDATE, $model, $data);
351
		$this->dispatch(ActionEvent::POST_SAVE, $model, $data);
352
353
		$payload = ['model' => $model];
354
355
		if ($rows === 0) {
356
			return new NotUpdated($payload);
357
		}
358
359
		return new Updated($payload);
360
	}
361
362
	/**
363
	 * Updates Apis on Action
364
	 * 
365
	 * @param mixed $id
366
	 * @param mixed $data
367
	 * @return PayloadInterface
368
	 */
369
	public function updateApis($id, $data) {
370
		// find
371
		$model = $this->get($id);
372
373
		if ($model === null) {
374
			return new NotFound(['message' => 'Action not found.']);
375
		}
376
377
		// pass update to internal logic
378
		try {
379
			$this->doUpdateApis($model, $data);
380
		} 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...
381
			return new NotValid(['errors' => $e->getErrors()]);
382
		}
383
384
		// save and dispatch events
385
		$this->dispatch(ActionEvent::PRE_APIS_UPDATE, $model, $data);
386
		$this->dispatch(ActionEvent::PRE_SAVE, $model, $data);
387
		$rows = $model->save();
388
		$this->dispatch(ActionEvent::POST_APIS_UPDATE, $model, $data);
389
		$this->dispatch(ActionEvent::POST_SAVE, $model, $data);
390
391
		if ($rows > 0) {
392
			return Updated(['model' => $model]);
393
		}
394
395
		return NotUpdated(['model' => $model]);
396
	}
397
398
	/**
399
	 * Updates Groups on Action
400
	 * 
401
	 * @param mixed $id
402
	 * @param mixed $data
403
	 * @return PayloadInterface
404
	 */
405
	public function updateGroups($id, $data) {
406
		// find
407
		$model = $this->get($id);
408
409
		if ($model === null) {
410
			return new NotFound(['message' => 'Action not found.']);
411
		}
412
413
		// pass update to internal logic
414
		try {
415
			$this->doUpdateGroups($model, $data);
416
		} 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...
417
			return new NotValid(['errors' => $e->getErrors()]);
418
		}
419
420
		// save and dispatch events
421
		$this->dispatch(ActionEvent::PRE_GROUPS_UPDATE, $model, $data);
422
		$this->dispatch(ActionEvent::PRE_SAVE, $model, $data);
423
		$rows = $model->save();
424
		$this->dispatch(ActionEvent::POST_GROUPS_UPDATE, $model, $data);
425
		$this->dispatch(ActionEvent::POST_SAVE, $model, $data);
426
427
		if ($rows > 0) {
428
			return Updated(['model' => $model]);
429
		}
430
431
		return NotUpdated(['model' => $model]);
432
	}
433
434
	/**
435
	 * @param mixed $query
436
	 * @param mixed $filter
437
	 * @return void
438
	 */
439
	protected function applyFilter($query, $filter) {
440
		foreach ($filter as $column => $value) {
441
			$pos = strpos($column, '.');
442
			if ($pos !== false) {
443
				$rel = NameUtils::toStudlyCase(substr($column, 0, $pos));
444
				$col = substr($column, $pos + 1);
445
				$method = 'use' . $rel . 'Query';
446
				if (method_exists($query, $method)) {
447
					$sub = $query->$method();
448
					$this->applyFilter($sub, [$col => $value]);
449
					$sub->endUse();
450
				}
451
			} else {
452
				$method = 'filterBy' . NameUtils::toStudlyCase($column);
453
				if (method_exists($query, $method)) {
454
					$query->$method($value);
455
				}
456
			}
457
		}
458
	}
459
460
	/**
461
	 * @param string $type
462
	 * @param Action $model
463
	 * @param array $data
464
	 */
465
	protected function dispatch($type, Action $model, array $data = []) {
466
		$methods = [
467
			ActionEvent::PRE_CREATE => 'preCreate',
468
			ActionEvent::POST_CREATE => 'postCreate',
469
			ActionEvent::PRE_UPDATE => 'preUpdate',
470
			ActionEvent::POST_UPDATE => 'postUpdate',
471
			ActionEvent::PRE_DELETE => 'preDelete',
472
			ActionEvent::POST_DELETE => 'postDelete',
473
			ActionEvent::PRE_SAVE => 'preSave',
474
			ActionEvent::POST_SAVE => 'postSave'
475
		];
476
477
		if (isset($methods[$type])) {
478
			$method = $methods[$type];
479
			if (method_exists($this, $method)) {
480
				$this->$method($model, $data);
481
			}
482
		}
483
484
		$dispatcher = $this->getServiceContainer()->getDispatcher();
485
		$dispatcher->dispatch($type, new ActionEvent($model));
486
	}
487
488
	/**
489
	 * Interal mechanism to add Apis to Action
490
	 * 
491
	 * @param Action $model
492
	 * @param mixed $data
493
	 */
494
	protected function doAddApis(Action $model, $data) {
495
		$errors = [];
496
		foreach ($data as $entry) {
497
			if (!isset($entry['id'])) {
498
				$errors[] = 'Missing id for Api';
499
			} else {
500
				$related = ApiQuery::create()->findOneById($entry['id']);
501
				$model->addApi($related);
502
			}
503
		}
504
505
		if (count($errors) > 0) {
506
			return new ErrorsException($errors);
507
		}
508
	}
509
510
	/**
511
	 * Interal mechanism to add Groups to Action
512
	 * 
513
	 * @param Action $model
514
	 * @param mixed $data
515
	 */
516
	protected function doAddGroups(Action $model, $data) {
517
		$errors = [];
518
		foreach ($data as $entry) {
519
			if (!isset($entry['id'])) {
520
				$errors[] = 'Missing id for Group';
521
			} else {
522
				$related = GroupQuery::create()->findOneById($entry['id']);
523
				$model->addGroup($related);
524
			}
525
		}
526
527
		if (count($errors) > 0) {
528
			return new ErrorsException($errors);
529
		}
530
	}
531
532
	/**
533
	 * Interal mechanism to remove Apis from Action
534
	 * 
535
	 * @param Action $model
536
	 * @param mixed $data
537
	 */
538
	protected function doRemoveApis(Action $model, $data) {
539
		$errors = [];
540
		foreach ($data as $entry) {
541
			if (!isset($entry['id'])) {
542
				$errors[] = 'Missing id for Api';
543
			} else {
544
				$related = ApiQuery::create()->findOneById($entry['id']);
545
				$model->removeApi($related);
546
			}
547
		}
548
549
		if (count($errors) > 0) {
550
			return new ErrorsException($errors);
551
		}
552
	}
553
554
	/**
555
	 * Interal mechanism to remove Groups from Action
556
	 * 
557
	 * @param Action $model
558
	 * @param mixed $data
559
	 */
560
	protected function doRemoveGroups(Action $model, $data) {
561
		$errors = [];
562
		foreach ($data as $entry) {
563
			if (!isset($entry['id'])) {
564
				$errors[] = 'Missing id for Group';
565
			} else {
566
				$related = GroupQuery::create()->findOneById($entry['id']);
567
				$model->removeGroup($related);
568
			}
569
		}
570
571
		if (count($errors) > 0) {
572
			return new ErrorsException($errors);
573
		}
574
	}
575
576
	/**
577
	 * Internal mechanism to set the Module id
578
	 * 
579
	 * @param Action $model
580
	 * @param mixed $relatedId
581
	 */
582
	protected function doSetModuleId(Action $model, $relatedId) {
583
		if ($model->getModuleId() !== $relatedId) {
584
			$model->setModuleId($relatedId);
585
586
			return true;
587
		}
588
589
		return false;
590
	}
591
592
	/**
593
	 * Internal update mechanism of Apis on Action
594
	 * 
595
	 * @param Action $model
596
	 * @param mixed $data
597
	 */
598
	protected function doUpdateApis(Action $model, $data) {
599
		// remove all relationships before
600
		ApiQuery::create()->filterByAction($model)->delete();
601
602
		// add them
603
		$errors = [];
604
		foreach ($data as $entry) {
605
			if (!isset($entry['id'])) {
606
				$errors[] = 'Missing id for Api';
607
			} else {
608
				$related = ApiQuery::create()->findOneById($entry['id']);
609
				$model->addApi($related);
610
			}
611
		}
612
613
		if (count($errors) > 0) {
614
			throw new ErrorsException($errors);
615
		}
616
	}
617
618
	/**
619
	 * Internal update mechanism of Groups on Action
620
	 * 
621
	 * @param Action $model
622
	 * @param mixed $data
623
	 */
624
	protected function doUpdateGroups(Action $model, $data) {
625
		// remove all relationships before
626
		GroupActionQuery::create()->filterByAction($model)->delete();
627
628
		// add them
629
		$errors = [];
630
		foreach ($data as $entry) {
631
			if (!isset($entry['id'])) {
632
				$errors[] = 'Missing id for Group';
633
			} else {
634
				$related = GroupQuery::create()->findOneById($entry['id']);
635
				$model->addGroup($related);
636
			}
637
		}
638
639
		if (count($errors) > 0) {
640
			throw new ErrorsException($errors);
641
		}
642
	}
643
644
	/**
645
	 * Returns one Action with the given id from cache
646
	 * 
647
	 * @param mixed $id
648
	 * @return Action|null
649
	 */
650
	protected function get($id) {
651
		if ($this->pool === null) {
652
			$this->pool = new Map();
653
		} else if ($this->pool->has($id)) {
654
			return $this->pool->get($id);
655
		}
656
657
		$model = ActionQuery::create()->findOneById($id);
658
		$this->pool->set($id, $model);
659
660
		return $model;
661
	}
662
663
	/**
664
	 * Returns the service container
665
	 * 
666
	 * @return ServiceContainer
667
	 */
668
	abstract protected function getServiceContainer();
669
}
670