SessionDomainTrait   B
last analyzed

Complexity

Total Complexity 32

Size/Duplication

Total Lines 287
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 18

Importance

Changes 12
Bugs 0 Features 0
Metric Value
wmc 32
c 12
b 0
f 0
lcom 1
cbo 18
dl 0
loc 287
rs 7.04

11 Methods

Rating   Name   Duplication   Size   Complexity  
B paginate() 0 27 3
A read() 0 11 2
B create() 0 25 3
A delete() 0 19 3
A setUserId() 0 21 3
B update() 0 38 5
B applyFilter() 0 20 5
A dispatch() 0 22 3
A doSetUserId() 0 9 2
A get() 0 12 3
getServiceContainer() 0 1 ?
1
<?php
2
namespace keeko\core\domain\base;
3
4
use keeko\core\event\SessionEvent;
5
use keeko\core\model\SessionQuery;
6
use keeko\core\model\Session;
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 SessionDomainTrait {
24
25
	/**
26
	 */
27
	protected $pool;
28
29
	/**
30
	 * Creates a new Session with the provided data
31
	 * 
32
	 * @param mixed $data
33
	 * @return PayloadInterface
34
	 */
35
	public function create($data) {
36
		// hydrate
37
		$serializer = Session::getSerializer();
38
		$model = $serializer->hydrate(new Session(), $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
		// dispatch pre save hooks
42
		$this->dispatch(SessionEvent::PRE_CREATE, $model, $data);
43
		$this->dispatch(SessionEvent::PRE_SAVE, $model, $data);
44
45
		// validate
46
		$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...
47
		if ($validator !== null && !$validator->validate($model)) {
48
			return new NotValid([
49
				'errors' => $validator->getValidationFailures()
50
			]);
51
		}
52
53
		// save and dispatch post save hooks
54
		$model->save();
55
		$this->dispatch(SessionEvent::POST_CREATE, $model, $data);
56
		$this->dispatch(SessionEvent::POST_SAVE, $model, $data);
57
58
		return new Created(['model' => $model]);
59
	}
60
61
	/**
62
	 * Deletes a Session with the given id
63
	 * 
64
	 * @param mixed $id
65
	 * @return PayloadInterface
66
	 */
67
	public function delete($id) {
68
		// find
69
		$model = $this->get($id);
70
71
		if ($model === null) {
72
			return new NotFound(['message' => 'Session not found.']);
73
		}
74
75
		// delete
76
		$this->dispatch(SessionEvent::PRE_DELETE, $model);
77
		$model->delete();
78
79
		if ($model->isDeleted()) {
80
			$this->dispatch(SessionEvent::POST_DELETE, $model);
81
			return new Deleted(['model' => $model]);
82
		}
83
84
		return new NotDeleted(['message' => 'Could not delete Session']);
85
	}
86
87
	/**
88
	 * Returns a paginated result
89
	 * 
90
	 * @param Parameters $params
91
	 * @return PayloadInterface
92
	 */
93
	public function paginate(Parameters $params) {
94
		$sysPrefs = $this->getServiceContainer()->getPreferenceLoader()->getSystemPreferences();
95
		$defaultSize = $sysPrefs->getPaginationSize();
96
		$page = $params->getPage('number');
97
		$size = $params->getPage('size', $defaultSize);
98
99
		$query = SessionQuery::create();
100
101
		// sorting
102
		$sort = $params->getSort(Session::getSerializer()->getSortFields());
103
		foreach ($sort as $field => $order) {
104
			$method = 'orderBy' . NameUtils::toStudlyCase($field);
105
			$query->$method($order);
106
		}
107
108
		// filtering
109
		$filter = $params->getFilter();
110
		if (!empty($filter)) {
111
			$this->applyFilter($query, $filter);
112
		}
113
114
		// paginate
115
		$model = $query->paginate($page, $size);
116
117
		// run response
118
		return new Found(['model' => $model]);
119
	}
120
121
	/**
122
	 * Returns one Session with the given id
123
	 * 
124
	 * @param mixed $id
125
	 * @return PayloadInterface
126
	 */
127
	public function read($id) {
128
		// read
129
		$model = $this->get($id);
130
131
		// check existence
132
		if ($model === null) {
133
			return new NotFound(['message' => 'Session not found.']);
134
		}
135
136
		return new Found(['model' => $model]);
137
	}
138
139
	/**
140
	 * Sets the User id
141
	 * 
142
	 * @param mixed $id
143
	 * @param mixed $relatedId
144
	 * @return PayloadInterface
145
	 */
146
	public function setUserId($id, $relatedId) {
147
		// find
148
		$model = $this->get($id);
149
150
		if ($model === null) {
151
			return new NotFound(['message' => 'Session not found.']);
152
		}
153
154
		// update
155
		if ($this->doSetUserId($model, $relatedId)) {
156
			$this->dispatch(SessionEvent::PRE_USER_UPDATE, $model);
157
			$this->dispatch(SessionEvent::PRE_SAVE, $model);
158
			$model->save();
159
			$this->dispatch(SessionEvent::POST_USER_UPDATE, $model);
160
			$this->dispatch(SessionEvent::POST_SAVE, $model);
161
162
			return Updated(['model' => $model]);
163
		}
164
165
		return NotUpdated(['model' => $model]);
166
	}
167
168
	/**
169
	 * Updates a Session with the given idand the provided data
170
	 * 
171
	 * @param mixed $id
172
	 * @param mixed $data
173
	 * @return PayloadInterface
174
	 */
175
	public function update($id, $data) {
176
		// find
177
		$model = $this->get($id);
178
179
		if ($model === null) {
180
			return new NotFound(['message' => 'Session not found.']);
181
		}
182
183
		// hydrate
184
		$serializer = Session::getSerializer();
185
		$model = $serializer->hydrate($model, $data);
186
		$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...
187
188
		// dispatch pre save hooks
189
		$this->dispatch(SessionEvent::PRE_UPDATE, $model, $data);
190
		$this->dispatch(SessionEvent::PRE_SAVE, $model, $data);
191
192
		// validate
193
		$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...
194
		if ($validator !== null && !$validator->validate($model)) {
195
			return new NotValid([
196
				'errors' => $validator->getValidationFailures()
197
			]);
198
		}
199
200
		// save and dispath post save hooks
201
		$rows = $model->save();
202
		$this->dispatch(SessionEvent::POST_UPDATE, $model, $data);
203
		$this->dispatch(SessionEvent::POST_SAVE, $model, $data);
204
205
		$payload = ['model' => $model];
206
207
		if ($rows === 0) {
208
			return new NotUpdated($payload);
209
		}
210
211
		return new Updated($payload);
212
	}
213
214
	/**
215
	 * @param mixed $query
216
	 * @param mixed $filter
217
	 * @return void
218
	 */
219
	protected function applyFilter($query, $filter) {
220
		foreach ($filter as $column => $value) {
221
			$pos = strpos($column, '.');
222
			if ($pos !== false) {
223
				$rel = NameUtils::toStudlyCase(substr($column, 0, $pos));
224
				$col = substr($column, $pos + 1);
225
				$method = 'use' . $rel . 'Query';
226
				if (method_exists($query, $method)) {
227
					$sub = $query->$method();
228
					$this->applyFilter($sub, [$col => $value]);
229
					$sub->endUse();
230
				}
231
			} else {
232
				$method = 'filterBy' . NameUtils::toStudlyCase($column);
233
				if (method_exists($query, $method)) {
234
					$query->$method($value);
235
				}
236
			}
237
		}
238
	}
239
240
	/**
241
	 * @param string $type
242
	 * @param Session $model
243
	 * @param array $data
244
	 */
245
	protected function dispatch($type, Session $model, array $data = []) {
246
		$methods = [
247
			SessionEvent::PRE_CREATE => 'preCreate',
248
			SessionEvent::POST_CREATE => 'postCreate',
249
			SessionEvent::PRE_UPDATE => 'preUpdate',
250
			SessionEvent::POST_UPDATE => 'postUpdate',
251
			SessionEvent::PRE_DELETE => 'preDelete',
252
			SessionEvent::POST_DELETE => 'postDelete',
253
			SessionEvent::PRE_SAVE => 'preSave',
254
			SessionEvent::POST_SAVE => 'postSave'
255
		];
256
257
		if (isset($methods[$type])) {
258
			$method = $methods[$type];
259
			if (method_exists($this, $method)) {
260
				$this->$method($model, $data);
261
			}
262
		}
263
264
		$dispatcher = $this->getServiceContainer()->getDispatcher();
265
		$dispatcher->dispatch($type, new SessionEvent($model));
266
	}
267
268
	/**
269
	 * Internal mechanism to set the User id
270
	 * 
271
	 * @param Session $model
272
	 * @param mixed $relatedId
273
	 */
274
	protected function doSetUserId(Session $model, $relatedId) {
275
		if ($model->getUserId() !== $relatedId) {
276
			$model->setUserId($relatedId);
277
278
			return true;
279
		}
280
281
		return false;
282
	}
283
284
	/**
285
	 * Returns one Session with the given id from cache
286
	 * 
287
	 * @param mixed $id
288
	 * @return Session|null
289
	 */
290
	protected function get($id) {
291
		if ($this->pool === null) {
292
			$this->pool = new Map();
293
		} else if ($this->pool->has($id)) {
294
			return $this->pool->get($id);
295
		}
296
297
		$model = SessionQuery::create()->findOneById($id);
298
		$this->pool->set($id, $model);
299
300
		return $model;
301
	}
302
303
	/**
304
	 * Returns the service container
305
	 * 
306
	 * @return ServiceContainer
307
	 */
308
	abstract protected function getServiceContainer();
309
}
310