ModuleDomainTrait::getServiceContainer()
last analyzed

Size

Total Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 1
nc 1
1
<?php
2
namespace keeko\core\domain\base;
3
4
use keeko\core\event\ModuleEvent;
5
use keeko\core\model\ActionQuery;
6
use keeko\core\model\ModuleQuery;
7
use keeko\core\model\Module;
8
use keeko\framework\domain\payload\Created;
9
use keeko\framework\domain\payload\Deleted;
10
use keeko\framework\domain\payload\Found;
11
use keeko\framework\domain\payload\NotDeleted;
12
use keeko\framework\domain\payload\NotFound;
13
use keeko\framework\domain\payload\NotUpdated;
14
use keeko\framework\domain\payload\NotValid;
15
use keeko\framework\domain\payload\PayloadInterface;
16
use keeko\framework\domain\payload\Updated;
17
use keeko\framework\exceptions\ErrorsException;
18
use keeko\framework\service\ServiceContainer;
19
use keeko\framework\utils\NameUtils;
20
use keeko\framework\utils\Parameters;
21
use phootwork\collection\Map;
22
23
/**
24
 */
25
trait ModuleDomainTrait {
26
27
	/**
28
	 */
29
	protected $pool;
30
31
	/**
32
	 * Adds Actions to Module
33
	 * 
34
	 * @param mixed $id
35
	 * @param mixed $data
36
	 * @return PayloadInterface
37
	 */
38
	public function addActions($id, $data) {
39
		// find
40
		$model = $this->get($id);
41
42
		if ($model === null) {
43
			return new NotFound(['message' => 'Module not found.']);
44
		}
45
46
		// pass add to internal logic
47
		try {
48
			$this->doAddActions($model, $data);
49
		} 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...
50
			return new NotValid(['errors' => $e->getErrors()]);
51
		}
52
53
		// save and dispatch events
54
		$this->dispatch(ModuleEvent::PRE_ACTIONS_ADD, $model, $data);
55
		$this->dispatch(ModuleEvent::PRE_SAVE, $model, $data);
56
		$rows = $model->save();
57
		$this->dispatch(ModuleEvent::POST_ACTIONS_ADD, $model, $data);
58
		$this->dispatch(ModuleEvent::POST_SAVE, $model, $data);
59
60
		if ($rows > 0) {
61
			return Updated(['model' => $model]);
62
		}
63
64
		return NotUpdated(['model' => $model]);
65
	}
66
67
	/**
68
	 * Creates a new Module with the provided data
69
	 * 
70
	 * @param mixed $data
71
	 * @return PayloadInterface
72
	 */
73
	public function create($data) {
74
		// hydrate
75
		$serializer = Module::getSerializer();
76
		$model = $serializer->hydrate(new Module(), $data);
77
		$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...
78
79
		// dispatch pre save hooks
80
		$this->dispatch(ModuleEvent::PRE_CREATE, $model, $data);
81
		$this->dispatch(ModuleEvent::PRE_SAVE, $model, $data);
82
83
		// validate
84
		$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...
85
		if ($validator !== null && !$validator->validate($model)) {
86
			return new NotValid([
87
				'errors' => $validator->getValidationFailures()
88
			]);
89
		}
90
91
		// save and dispatch post save hooks
92
		$model->save();
93
		$this->dispatch(ModuleEvent::POST_CREATE, $model, $data);
94
		$this->dispatch(ModuleEvent::POST_SAVE, $model, $data);
95
96
		return new Created(['model' => $model]);
97
	}
98
99
	/**
100
	 * Deletes a Module with the given id
101
	 * 
102
	 * @param mixed $id
103
	 * @return PayloadInterface
104
	 */
105
	public function delete($id) {
106
		// find
107
		$model = $this->get($id);
108
109
		if ($model === null) {
110
			return new NotFound(['message' => 'Module not found.']);
111
		}
112
113
		// delete
114
		$this->dispatch(ModuleEvent::PRE_DELETE, $model);
115
		$model->delete();
116
117
		if ($model->isDeleted()) {
118
			$this->dispatch(ModuleEvent::POST_DELETE, $model);
119
			return new Deleted(['model' => $model]);
120
		}
121
122
		return new NotDeleted(['message' => 'Could not delete Module']);
123
	}
124
125
	/**
126
	 * Returns a paginated result
127
	 * 
128
	 * @param Parameters $params
129
	 * @return PayloadInterface
130
	 */
131
	public function paginate(Parameters $params) {
132
		$sysPrefs = $this->getServiceContainer()->getPreferenceLoader()->getSystemPreferences();
133
		$defaultSize = $sysPrefs->getPaginationSize();
134
		$page = $params->getPage('number');
135
		$size = $params->getPage('size', $defaultSize);
136
137
		$query = ModuleQuery::create();
138
139
		// sorting
140
		$sort = $params->getSort(Module::getSerializer()->getSortFields());
141
		foreach ($sort as $field => $order) {
142
			$method = 'orderBy' . NameUtils::toStudlyCase($field);
143
			$query->$method($order);
144
		}
145
146
		// filtering
147
		$filter = $params->getFilter();
148
		if (!empty($filter)) {
149
			$this->applyFilter($query, $filter);
150
		}
151
152
		// paginate
153
		$model = $query->paginate($page, $size);
154
155
		// run response
156
		return new Found(['model' => $model]);
157
	}
158
159
	/**
160
	 * Returns one Module with the given id
161
	 * 
162
	 * @param mixed $id
163
	 * @return PayloadInterface
164
	 */
165
	public function read($id) {
166
		// read
167
		$model = $this->get($id);
168
169
		// check existence
170
		if ($model === null) {
171
			return new NotFound(['message' => 'Module not found.']);
172
		}
173
174
		return new Found(['model' => $model]);
175
	}
176
177
	/**
178
	 * Removes Actions from Module
179
	 * 
180
	 * @param mixed $id
181
	 * @param mixed $data
182
	 * @return PayloadInterface
183
	 */
184
	public function removeActions($id, $data) {
185
		// find
186
		$model = $this->get($id);
187
188
		if ($model === null) {
189
			return new NotFound(['message' => 'Module not found.']);
190
		}
191
192
		// pass remove to internal logic
193
		try {
194
			$this->doRemoveActions($model, $data);
195
		} 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...
196
			return new NotValid(['errors' => $e->getErrors()]);
197
		}
198
199
		// save and dispatch events
200
		$this->dispatch(ModuleEvent::PRE_ACTIONS_REMOVE, $model, $data);
201
		$this->dispatch(ModuleEvent::PRE_SAVE, $model, $data);
202
		$rows = $model->save();
203
		$this->dispatch(ModuleEvent::POST_ACTIONS_REMOVE, $model, $data);
204
		$this->dispatch(ModuleEvent::POST_SAVE, $model, $data);
205
206
		if ($rows > 0) {
207
			return Updated(['model' => $model]);
208
		}
209
210
		return NotUpdated(['model' => $model]);
211
	}
212
213
	/**
214
	 * Updates a Module with the given idand the provided data
215
	 * 
216
	 * @param mixed $id
217
	 * @param mixed $data
218
	 * @return PayloadInterface
219
	 */
220
	public function update($id, $data) {
221
		// find
222
		$model = $this->get($id);
223
224
		if ($model === null) {
225
			return new NotFound(['message' => 'Module not found.']);
226
		}
227
228
		// hydrate
229
		$serializer = Module::getSerializer();
230
		$model = $serializer->hydrate($model, $data);
231
		$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...
232
233
		// dispatch pre save hooks
234
		$this->dispatch(ModuleEvent::PRE_UPDATE, $model, $data);
235
		$this->dispatch(ModuleEvent::PRE_SAVE, $model, $data);
236
237
		// validate
238
		$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...
239
		if ($validator !== null && !$validator->validate($model)) {
240
			return new NotValid([
241
				'errors' => $validator->getValidationFailures()
242
			]);
243
		}
244
245
		// save and dispath post save hooks
246
		$rows = $model->save();
247
		$this->dispatch(ModuleEvent::POST_UPDATE, $model, $data);
248
		$this->dispatch(ModuleEvent::POST_SAVE, $model, $data);
249
250
		$payload = ['model' => $model];
251
252
		if ($rows === 0) {
253
			return new NotUpdated($payload);
254
		}
255
256
		return new Updated($payload);
257
	}
258
259
	/**
260
	 * Updates Actions on Module
261
	 * 
262
	 * @param mixed $id
263
	 * @param mixed $data
264
	 * @return PayloadInterface
265
	 */
266
	public function updateActions($id, $data) {
267
		// find
268
		$model = $this->get($id);
269
270
		if ($model === null) {
271
			return new NotFound(['message' => 'Module not found.']);
272
		}
273
274
		// pass update to internal logic
275
		try {
276
			$this->doUpdateActions($model, $data);
277
		} 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...
278
			return new NotValid(['errors' => $e->getErrors()]);
279
		}
280
281
		// save and dispatch events
282
		$this->dispatch(ModuleEvent::PRE_ACTIONS_UPDATE, $model, $data);
283
		$this->dispatch(ModuleEvent::PRE_SAVE, $model, $data);
284
		$rows = $model->save();
285
		$this->dispatch(ModuleEvent::POST_ACTIONS_UPDATE, $model, $data);
286
		$this->dispatch(ModuleEvent::POST_SAVE, $model, $data);
287
288
		if ($rows > 0) {
289
			return Updated(['model' => $model]);
290
		}
291
292
		return NotUpdated(['model' => $model]);
293
	}
294
295
	/**
296
	 * @param mixed $query
297
	 * @param mixed $filter
298
	 * @return void
299
	 */
300
	protected function applyFilter($query, $filter) {
301
		foreach ($filter as $column => $value) {
302
			$pos = strpos($column, '.');
303
			if ($pos !== false) {
304
				$rel = NameUtils::toStudlyCase(substr($column, 0, $pos));
305
				$col = substr($column, $pos + 1);
306
				$method = 'use' . $rel . 'Query';
307
				if (method_exists($query, $method)) {
308
					$sub = $query->$method();
309
					$this->applyFilter($sub, [$col => $value]);
310
					$sub->endUse();
311
				}
312
			} else {
313
				$method = 'filterBy' . NameUtils::toStudlyCase($column);
314
				if (method_exists($query, $method)) {
315
					$query->$method($value);
316
				}
317
			}
318
		}
319
	}
320
321
	/**
322
	 * @param string $type
323
	 * @param Module $model
324
	 * @param array $data
325
	 */
326
	protected function dispatch($type, Module $model, array $data = []) {
327
		$methods = [
328
			ModuleEvent::PRE_CREATE => 'preCreate',
329
			ModuleEvent::POST_CREATE => 'postCreate',
330
			ModuleEvent::PRE_UPDATE => 'preUpdate',
331
			ModuleEvent::POST_UPDATE => 'postUpdate',
332
			ModuleEvent::PRE_DELETE => 'preDelete',
333
			ModuleEvent::POST_DELETE => 'postDelete',
334
			ModuleEvent::PRE_SAVE => 'preSave',
335
			ModuleEvent::POST_SAVE => 'postSave'
336
		];
337
338
		if (isset($methods[$type])) {
339
			$method = $methods[$type];
340
			if (method_exists($this, $method)) {
341
				$this->$method($model, $data);
342
			}
343
		}
344
345
		$dispatcher = $this->getServiceContainer()->getDispatcher();
346
		$dispatcher->dispatch($type, new ModuleEvent($model));
347
	}
348
349
	/**
350
	 * Interal mechanism to add Actions to Module
351
	 * 
352
	 * @param Module $model
353
	 * @param mixed $data
354
	 */
355
	protected function doAddActions(Module $model, $data) {
356
		$errors = [];
357
		foreach ($data as $entry) {
358
			if (!isset($entry['id'])) {
359
				$errors[] = 'Missing id for Action';
360
			} else {
361
				$related = ActionQuery::create()->findOneById($entry['id']);
362
				$model->addAction($related);
363
			}
364
		}
365
366
		if (count($errors) > 0) {
367
			return new ErrorsException($errors);
368
		}
369
	}
370
371
	/**
372
	 * Interal mechanism to remove Actions from Module
373
	 * 
374
	 * @param Module $model
375
	 * @param mixed $data
376
	 */
377
	protected function doRemoveActions(Module $model, $data) {
378
		$errors = [];
379
		foreach ($data as $entry) {
380
			if (!isset($entry['id'])) {
381
				$errors[] = 'Missing id for Action';
382
			} else {
383
				$related = ActionQuery::create()->findOneById($entry['id']);
384
				$model->removeAction($related);
385
			}
386
		}
387
388
		if (count($errors) > 0) {
389
			return new ErrorsException($errors);
390
		}
391
	}
392
393
	/**
394
	 * Internal update mechanism of Actions on Module
395
	 * 
396
	 * @param Module $model
397
	 * @param mixed $data
398
	 */
399
	protected function doUpdateActions(Module $model, $data) {
400
		// remove all relationships before
401
		ActionQuery::create()->filterByModule($model)->delete();
402
403
		// add them
404
		$errors = [];
405
		foreach ($data as $entry) {
406
			if (!isset($entry['id'])) {
407
				$errors[] = 'Missing id for Action';
408
			} else {
409
				$related = ActionQuery::create()->findOneById($entry['id']);
410
				$model->addAction($related);
411
			}
412
		}
413
414
		if (count($errors) > 0) {
415
			throw new ErrorsException($errors);
416
		}
417
	}
418
419
	/**
420
	 * Returns one Module with the given id from cache
421
	 * 
422
	 * @param mixed $id
423
	 * @return Module|null
424
	 */
425
	protected function get($id) {
426
		if ($this->pool === null) {
427
			$this->pool = new Map();
428
		} else if ($this->pool->has($id)) {
429
			return $this->pool->get($id);
430
		}
431
432
		$model = ModuleQuery::create()->findOneById($id);
433
		$this->pool->set($id, $model);
434
435
		return $model;
436
	}
437
438
	/**
439
	 * Returns the service container
440
	 * 
441
	 * @return ServiceContainer
442
	 */
443
	abstract protected function getServiceContainer();
444
}
445