Completed
Push — master ( e8b3d2...889b57 )
by Thomas
14:29
created

ActivityDomainTrait::getServiceContainer()

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