Passed
Push — master ( 17df0f...8aa659 )
by Jean-Christophe
07:40
created

RestControllerUtilitiesTrait   B

Complexity

Total Complexity 50

Size/Duplication

Total Lines 242
Duplicated Lines 0 %

Test Coverage

Coverage 66.67%

Importance

Changes 0
Metric Value
wmc 50
eloc 106
dl 0
loc 242
ccs 86
cts 129
cp 0.6667
rs 8.4
c 0
b 0
f 0

22 Methods

Rating   Name   Duplication   Size   Complexity  
A getResponseFormatter() 0 2 1
A addViolation() 0 2 1
A getAssociatedMemberValues_() 0 8 2
A connectDb() 0 4 2
A getDatas() 0 2 1
A AddOperation() 0 2 1
A hasErrors() 0 2 2
A getRequestParam() 0 5 2
A displayErrors() 0 15 4
A updateManyToOne() 0 10 5
A operate_() 0 14 4
A getInclude() 0 5 2
A _getRestServer() 0 5 2
A _validateInstance() 0 13 4
A getPrimaryKeysFromDatas() 0 11 3
A addError() 0 2 1
A updateOperation() 0 2 1
A getRestServer() 0 2 1
A _setValuesToObject() 0 15 4
A _getResponseFormatter() 0 5 2
A getCondition() 0 6 2
A generatePagination() 0 13 3

How to fix   Complexity   

Complex Class

Complex classes like RestControllerUtilitiesTrait often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use RestControllerUtilitiesTrait, and based on these observations, apply Extract Interface, too.

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.4
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 1
			} 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 19
	protected function _getResponseFormatter() {
92 19
		if (! isset ( $this->responseFormatter )) {
93 19
			$this->responseFormatter = $this->getResponseFormatter ();
94
		}
95 19
		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 15
	protected function getResponseFormatter(): ResponseFormatter {
104 15
		return new ResponseFormatter ();
105
	}
106
107 19
	protected function _getRestServer() {
108 19
		if (! isset ( $this->server )) {
109 19
			$this->server = $this->getRestServer ();
110
		}
111 19
		return $this->server;
112
	}
113
114
	/**
115
	 * To override, returns the active RestServer
116
	 *
117
	 * @return \Ubiquity\controllers\rest\RestServer
118
	 */
119 15
	protected function getRestServer(): RestServer {
120 15
		return new RestServer ( $this->config );
121
	}
122
123 12
	protected function connectDb($config) {
124 12
		$db = $config ["database"];
125 12
		if ($db ["dbName"] !== "") {
126 12
			DAO::connect ( $db ["type"], $db ["dbName"], $db ["serverName"] ?? '127.0.0.1', $db ["port"] ?? 3306, $db ["user"] ?? 'root', $db ["password"] ?? '', $db ["options"] ?? [ ], $db ["cache"] ?? false);
127
		}
128 12
	}
129
130
	/**
131
	 * Updates $instance with $values
132
	 * To eventually be redefined in derived classes
133
	 *
134
	 * @param object $instance the instance to update
135
	 * @param array|null $values
136
	 */
137 1
	protected function _setValuesToObject($instance, $values = null) {
138 1
		if (URequest::isJSON ()) {
139 1
			if(is_string($values)){
140
				$values = \json_decode ( $values, true );
141
			}
142
		}
143 1
		$className = \get_class ( $instance );
144 1
		$fieldsInRelationForUpdate = OrmUtils::getFieldsInRelationsForUpdate_ ( $className );
145 1
		$manyToOneRelations = $fieldsInRelationForUpdate ["manyToOne"];
146
		
147 1
		$members = array_keys ( $values );
0 ignored issues
show
Bug introduced by
It seems like $values can also be of type null; however, parameter $input of array_keys() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

147
		$members = array_keys ( /** @scrutinizer ignore-type */ $values );
Loading history...
148 1
		OrmUtils::setFieldToMemberNames ( $members, $fieldsInRelationForUpdate ["relations"] );
149 1
		URequest::setValuesToObject ( $instance, $values );
150 1
		if ($manyToOneRelations) {
151
			$this->updateManyToOne ( $manyToOneRelations, $members, $className, $instance, $values );
152
		}
153 1
	}
154
	
155
	protected function updateManyToOne($manyToOneRelations,$members,$className,$instance,$values){
156
		foreach ( $manyToOneRelations as $member ) {
157
			if (array_search($member, $members)!==false) {
158
				$joinColumn=OrmUtils::getAnnotationInfoMember($className, "#joinColumn", $member);
159
				if ($joinColumn) {
160
					$fkClass=$joinColumn["className"];
161
					$fkField=$joinColumn["name"];
162
					if (isset($values[$fkField])) {
163
						$fkObject=DAO::getOne($fkClass, $values["$fkField"]);
164
						Reflexion::setMemberValue($instance, $member, $fkObject);
165
					}
166
				}
167
			}
168
		}
169
	}
170
171
	/**
172
	 *
173
	 * @param string|boolean $include
174
	 * @return array|boolean
175
	 */
176 10
	protected function getInclude($include) {
177 10
		if (! UString::isBooleanStr ( $include )) {
178 1
			return explode ( ",", $include );
179
		}
180 10
		return UString::isBooleanTrue ( $include );
181
	}
182
183
	protected function addError($code, $title, $detail = null, $source = null, $status = null) {
184
		$this->errors [] = new RestError ( $code, $title, $detail, $source, $status );
185
	}
186
187 1
	protected function hasErrors() {
188 1
		return is_array ( $this->errors ) && sizeof ( $this->errors ) > 0;
189
	}
190
191
	protected function displayErrors() {
192
		if ($this->hasErrors ()) {
193
			$status = 200;
194
			$errors = [ ];
195
			foreach ( $this->errors as $error ) {
196
				$errors [] = $error->asArray ();
197
				if ($error->getStatus () > $status) {
198
					$status = $error->getStatus ();
199
				}
200
			}
201
			echo $this->_getResponseFormatter ()->format ( [ 'errors' => $errors ] );
202
			$this->_setResponseCode ( $status );
203
			return true;
204
		}
205
		return false;
206
	}
207
208
	/**
209
	 *
210
	 * @param string $ids The primary key values (comma separated if pk is multiple)
211
	 * @param callable $getDatas
212
	 * @param string $member The member to load
213
	 * @param boolean|string $include if true, loads associate members with associations, if string, example : client.*,commands
214
	 * @param boolean $useCache
215
	 * @param boolean $multiple
216
	 * @throws \Exception
217
	 */
218 3
	protected function getAssociatedMemberValues_($ids, $getDatas, $member, $include = false, $useCache = false, $multiple = true) {
219 3
		$include = $this->getInclude ( $include );
220 3
		$useCache = UString::isBooleanTrue ( $useCache );
221 3
		$datas = $getDatas ( [ $this->model,$ids ], $member, $include, $useCache );
222 3
		if ($multiple) {
223 2
			echo $this->_getResponseFormatter ()->get ( $datas );
224
		} else {
225 1
			echo $this->_getResponseFormatter ()->getOne ( $datas );
226
		}
227 3
	}
228
229 1
	public function _validateInstance($instance, $members) {
230 1
		if ($this->useValidation) {
231 1
			$isValid = true;
232 1
			$violations = ValidatorsManager::validate ( $instance );
233 1
			foreach ( $violations as $violation ) {
234 1
				if (array_search ( $violation->getMember (), $members ) !== false) {
235
					$this->addViolation ( $violation );
236
					$isValid = false;
237
				}
238
			}
239 1
			return $isValid;
240
		}
241
		return true;
242
	}
243
244
	protected function addViolation(ConstraintViolation $violation) {
245
		$this->addError ( 406, 'Validation error', $violation->getMessage (), $violation->getMember (), $violation->getValidatorType () );
246
	}
247
248
	protected function getPrimaryKeysFromDatas($datas, $model) {
249
		$pks = OrmUtils::getKeyFields ( $model );
250
		$result = [ ];
251
		foreach ( $pks as $pk ) {
252
			if (isset ( $datas [$pk] )) {
253
				$result [] = $datas [$pk];
254
			} else {
255
				$this->addError ( 404, 'Primary key required', 'The primary key ' . $pk . ' is required!', $pk );
256
			}
257
		}
258
		return $result;
259
	}
260
	
261 7
	protected function getCondition($condition){
262 7
		$condition=urldecode($condition);
263 7
		if(strpos($condition, 'like')!==false){
264 3
			$condition=str_replace('*', '%', $condition);
265
		}
266 7
		return $condition;
267
	}
268
}
269
270