Passed
Push — master ( ae6dff...0062d3 )
by Jean-Christophe
09:44
created

RestControllerUtilitiesTrait::AddOperation()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 1
c 1
b 0
f 0
dl 0
loc 2
ccs 2
cts 2
cp 1
rs 10
cc 1
nc 1
nop 3
crap 1
1
<?php
2
3
namespace Ubiquity\controllers\rest;
4
5
use Ubiquity\orm\DAO;
6
use Ubiquity\utils\base\UString;
7
use Ubiquity\utils\http\URequest;
8
use Ubiquity\contents\validation\ValidatorsManager;
9
use Ubiquity\contents\validation\validators\ConstraintViolation;
10
use Ubiquity\orm\OrmUtils;
11
use Ubiquity\orm\parser\Reflexion;
12
13
/**
14
 * Rest controller internal utilities.
15
 * Ubiquity\controllers\rest$RestControllerUtilitiesTrait
16
 * This class is part of Ubiquity
17
 *
18
 * @author jcheron <[email protected]>
19
 * @version 1.0.5
20
 * @property ResponseFormatter $responseFormatter
21
 * @property RestServer $server
22
 * @property string $model
23
 *
24
 */
25
trait RestControllerUtilitiesTrait {
26
	protected $errors;
27
28
	abstract public function _setResponseCode($value);
29
30 1
	protected function getDatas() {
31 1
		return URequest::getDatas ();
32
	}
33
34
	/**
35
	 *
36
	 * @param string $param
37
	 * @param string|boolean $default
38
	 * @return string|boolean
39
	 */
40 9
	protected function getRequestParam($param, $default) {
41 9
		if (isset ( $_GET [$param] )) {
42 3
			return $_GET [$param];
43
		}
44 8
		return $default;
45
	}
46
47 1
	protected function operate_($instance, $callback, $status, $exceptionMessage, $keyValues) {
48 1
		if (isset ( $instance )) {
49 1
			$result = $callback ( $instance );
50 1
			if ($result == true) {
51 1
				$formatter = $this->_getResponseFormatter ();
52 1
				echo $formatter->format ( [ "status" => $status,"data" => $formatter->cleanRestObject ( $instance ) ] );
53
			} elseif ($result === null) {
54
				$this->displayErrors ();
55
			} else {
56 1
				throw new \Exception ( $exceptionMessage );
57
			}
58
		} else {
59 1
			$this->_setResponseCode ( 404 );
60 1
			echo $this->_getResponseFormatter ()->format ( [ "message" => "No result found","keyValues" => $keyValues ] );
61
		}
62 1
	}
63
64 2
	protected function generatePagination(&$filter, $pageNumber, $pageSize) {
65 2
		$count = DAO::count ( $this->model, $filter );
66 2
		$pagesCount = \ceil ( $count / $pageSize );
67 2
		$pages = [ 'self' => $pageNumber,'first' => 1,'last' => $pagesCount,'pageSize' => $pageSize ];
68 2
		if ($pageNumber - 1 > 0) {
69 1
			$pages ['prev'] = $pageNumber - 1;
70
		}
71 2
		if ($pageNumber + 1 <= $pagesCount) {
72 1
			$pages ['next'] = $pageNumber + 1;
73
		}
74 2
		$offset = ($pageNumber - 1) * $pageSize;
75 2
		$filter .= ' limit ' . $offset . ',' . $pageSize;
76 2
		return $pages;
77
	}
78
79 1
	protected function updateOperation($instance, $datas, $updateMany = false) {
80 1
		return DAO::update ( $instance, $updateMany );
81
	}
82
83 1
	protected function AddOperation($instance, $datas, $insertMany = false) {
84 1
		return DAO::insert ( $instance, $insertMany );
85
	}
86
87
	/**
88
	 *
89
	 * @return \Ubiquity\controllers\rest\ResponseFormatter
90
	 */
91 16
	protected function _getResponseFormatter() {
92 16
		if (! isset ( $this->responseFormatter )) {
93 16
			$this->responseFormatter = $this->getResponseFormatter ();
94
		}
95 16
		return $this->responseFormatter;
96
	}
97
98
	/**
99
	 * To override, returns the active formatter for the response
100
	 *
101
	 * @return \Ubiquity\controllers\rest\ResponseFormatter
102
	 */
103 12
	protected function getResponseFormatter(): ResponseFormatter {
104 12
		return new ResponseFormatter ();
105
	}
106
107 16
	protected function _getRestServer() {
108 16
		if (! isset ( $this->server )) {
109 16
			$this->server = $this->getRestServer ();
110
		}
111 16
		return $this->server;
112
	}
113
114
	/**
115
	 * To override, returns the active RestServer
116
	 *
117
	 * @return \Ubiquity\controllers\rest\RestServer
118
	 */
119 12
	protected function getRestServer(): RestServer {
120 12
		return new RestServer ( $this->config );
121
	}
122
123
	/**
124
	 * Updates $instance with $values
125
	 * To eventually be redefined in derived classes
126
	 *
127
	 * @param object $instance the instance to update
128
	 * @param array $values
129
	 */
130 1
	protected function _setValuesToObject($instance, $values = [ ]) {
131 1
		if (URequest::isJSON ()) {
132
			if (\is_string ( $values )) {
133
				$values = \json_decode ( $values, true );
134
			}
135
		}
136 1
		$className = \get_class ( $instance );
137 1
		$fieldsInRelationForUpdate = OrmUtils::getFieldsInRelationsForUpdate_ ( $className );
138 1
		$manyToOneRelations = $fieldsInRelationForUpdate ["manyToOne"];
139
140 1
		$members = \array_keys ( $values );
141 1
		OrmUtils::setFieldToMemberNames ( $members, $fieldsInRelationForUpdate ["relations"] );
142 1
		URequest::setValuesToObject ( $instance, $values );
143 1
		if ($manyToOneRelations) {
144
			$this->updateManyToOne ( $manyToOneRelations, $members, $className, $instance, $values );
145
		}
146 1
	}
147
148
	protected function updateManyToOne($manyToOneRelations, $members, $className, $instance, $values) {
149
		foreach ( $manyToOneRelations as $member ) {
150
			if (\array_search ( $member, $members ) !== false) {
151
				$joinColumn = OrmUtils::getAnnotationInfoMember ( $className, "#joinColumn", $member );
152
				if ($joinColumn) {
153
					$fkClass = $joinColumn ["className"];
154
					$fkField = $joinColumn ["name"];
155
					if (isset ( $values [$fkField] )) {
156
						$fkObject = DAO::getById ( $fkClass, $values ["$fkField"] );
157
						Reflexion::setMemberValue ( $instance, $member, $fkObject );
158
					}
159
				}
160
			}
161
		}
162
	}
163
164
	/**
165
	 *
166
	 * @param string|boolean $include
167
	 * @return array|boolean
168
	 */
169 10
	protected function getInclude($include) {
170 10
		if (! UString::isBooleanStr ( $include )) {
171 1
			return \explode ( ',', $include );
172
		}
173 10
		return UString::isBooleanTrue ( $include );
174
	}
175
176
	protected function addError($code, $title, $detail = null, $source = null, $status = null) {
177
		$this->errors [] = new RestError ( $code, $title, $detail, $source, $status );
178
	}
179
180
	protected function hasErrors() {
181
		return \is_array ( $this->errors ) && \sizeof ( $this->errors ) > 0;
182
	}
183
184
	protected function displayErrors() {
185
		if ($this->hasErrors ()) {
186
			$status = 200;
187
			$errors = [ ];
188
			foreach ( $this->errors as $error ) {
189
				$errors [] = $error->asArray ();
190
				if ($error->getStatus () > $status) {
191
					$status = $error->getStatus ();
192
				}
193
			}
194
			echo $this->_getResponseFormatter ()->format ( [ 'errors' => $errors ] );
195
			$this->_setResponseCode ( $status );
196
			return true;
197
		}
198
		return false;
199
	}
200
201
	/**
202
	 *
203
	 * @param string $ids The primary key values (comma separated if pk is multiple)
204
	 * @param callable $getDatas
205
	 * @param string $member The member to load
206
	 * @param boolean|string $include if true, loads associate members with associations, if string, example : client.*,commands
207
	 * @param boolean $useCache
208
	 * @param boolean $multiple
209
	 * @throws \Exception
210
	 */
211 3
	protected function getAssociatedMemberValues_($ids, $getDatas, $member, $include = false, $useCache = false, $multiple = true) {
212 3
		$include = $this->getInclude ( $include );
213 3
		$useCache = UString::isBooleanTrue ( $useCache );
214 3
		$datas = $getDatas ( [ $this->model,$ids ], $member, $include, $useCache );
215 3
		if ($multiple) {
216 2
			echo $this->_getResponseFormatter ()->get ( $datas );
217
		} else {
218 1
			echo $this->_getResponseFormatter ()->getOne ( $datas );
219
		}
220 3
	}
221
222 1
	public function _validateInstance($instance, $members, $excludedValidators = [ ]) {
223 1
		if ($this->useValidation) {
224 1
			$isValid = true;
225 1
			$violations = ValidatorsManager::validate ( $instance, '', $excludedValidators );
226 1
			foreach ( $violations as $violation ) {
227
				if (\array_search ( $violation->getMember (), $members ) !== false) {
228
					$this->addViolation ( $violation );
229
					$isValid = false;
230
				}
231
			}
232 1
			return $isValid;
233
		}
234
		return true;
235
	}
236
237
	protected function addViolation(ConstraintViolation $violation) {
238
		$this->addError ( 406, 'Validation error', $violation->getMessage (), $violation->getMember (), $violation->getValidatorType () );
239
	}
240
241
	protected function getPrimaryKeysFromDatas($datas, $model) {
242
		$pks = OrmUtils::getKeyFields ( $model );
243
		$result = [ ];
244
		foreach ( $pks as $pk ) {
245
			if (isset ( $datas [$pk] )) {
246
				$result [] = $datas [$pk];
247
			} else {
248
				$this->addError ( 404, 'Primary key required', 'The primary key ' . $pk . ' is required!', $pk );
249
			}
250
		}
251
		return $result;
252
	}
253
254 7
	protected function getCondition($condition) {
255 7
		$condition = urldecode ( $condition );
256 7
		if (\strpos ( $condition, 'like' ) !== false) {
257 3
			$condition = \str_replace ( '*', '%', $condition );
258
		}
259 7
		return $condition;
260
	}
261
}
262
263