Passed
Push — master ( 95250a...74488a )
by Jean-Christophe
21:49
created

CRUDHelper::update()   B

Complexity

Conditions 10
Paths 62

Size

Total Lines 38
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 23
CRAP Score 10.0512

Importance

Changes 4
Bugs 0 Features 1
Metric Value
eloc 25
c 4
b 0
f 1
dl 0
loc 38
ccs 23
cts 25
cp 0.92
rs 7.6666
cc 10
nc 62
nop 5
crap 10.0512

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace Ubiquity\controllers\crud;
4
5
use Ubiquity\orm\OrmUtils;
6
use Ubiquity\utils\http\URequest;
7
use Ubiquity\orm\DAO;
8
use Ubiquity\orm\parser\Reflexion;
9
use Ubiquity\cache\database\DbCache;
10
use Ubiquity\db\SqlUtils;
11
use Ubiquity\db\utils\DbTypes;
12
13
/**
14
 * Ubiquity\controllers\crud$CRUDHelper
15
 * This class is part of Ubiquity
16
 *
17
 * @author jc
18
 * @version 1.0.4
19
 *
20
 */
21
class CRUDHelper {
22
23 8
	public static function getIdentifierFunction($model) {
24 8
		$pks = OrmUtils::getKeyMembers ( $model );
25
		return function ($index, $instance) use ($pks) {
26 8
			$values = [ ];
27 8
			foreach ( $pks as $pk ) {
28 8
				$getter = 'get' . \ucfirst ( $pk );
29 8
				if (\method_exists ( $instance, $getter )) {
30 8
					$values [] = $instance->{$getter} ();
31
				}
32
			}
33 8
			return \implode ( '_', $values );
34 8
		};
35
	}
36
37 1
	public static function search($model, $search, $fields, $initialCondition = '1=1') {
38 1
		$words = \preg_split ( "@(\s*?(\(|\)|\|\||\&\&)\s*?)@", $search );
39 1
		$params = [ ];
40 1
		$count = \count ( $fields );
41 1
		$db = DAO::getDb ( $model );
42 1
		$like = $db->getSpecificSQL ( 'tostring' ) . ' LIKE ';
43 1
		SqlUtils::$quote = $db->quote;
44 1
		if ($words !== false) {
45 1
			$words = array_filter ( $words, 'strlen' );
46 1
			$condition = "(" . SqlUtils::getSearchWhere ( $like, $fields, '?', '', '' ) . ")";
47 1
			foreach ( $words as $word ) {
48 1
				$word = \trim ( $word );
49 1
				$params = [ ...$params,...(\array_fill ( 0, $count, "%{$word}%" )) ];
50
			}
51
52 1
			$condition = \str_replace ( '||', ' OR ', $condition );
53 1
			$condition = \str_replace ( '&&', ' AND ', $condition );
54 1
			$condition = '(' . $condition . ') AND ' . $initialCondition . '';
55
		} else {
56
			$condition = $initialCondition;
57
		}
58 1
		return DAO::getAll ( $model, $condition, false, $params );
59
	}
60
61 4
	public static function update($instance, $values, $setValues = true, $updateMany = true, $eventCallback = null) {
62 4
		$className = \get_class ( $instance );
63 4
		$fieldsInRelationForUpdate = OrmUtils::getFieldsInRelationsForUpdate_ ( $className );
64 4
		$manyToOneRelations = $fieldsInRelationForUpdate ['manyToOne'];
65 4
		$manyToManyRelations = $fieldsInRelationForUpdate ['manyToMany'];
66 4
		$oneToManyRelations = $fieldsInRelationForUpdate ['oneToMany'];
67
68 4
		$members = \array_keys ( $values );
69 4
		OrmUtils::setFieldToMemberNames ( $members, $fieldsInRelationForUpdate ['relations'] );
70 4
		$update = false;
71
		
72 4
		self::setInputValues($className, $instance, $values, $setValues);
73
74 4
		if ($manyToOneRelations) {
75
			self::updateManyToOne ( $manyToOneRelations, $members, $className, $instance, $values );
76
		}
77 4
		if (isset ( $instance )) {
78 4
			if (isset ( $eventCallback )) {
79 3
				$eventCallback ( $instance, $instance->_new );
80
			}
81 4
			if ($instance->_new) {
82 2
				$update = DAO::insert ( $instance );
83
			} else {
84 3
				$update = DAO::update ( $instance );
85 3
				if (DbCache::$active) {
86
					// TODO update dbCache
87
				}
88
			}
89 4
			if($updateMany && $update){
90 4
				if ($manyToManyRelations) {
91
					self::updateManyToMany ( $manyToManyRelations, $members, $className, $instance, $values );
92
				}
93 4
				if ($oneToManyRelations) {
94 4
					self::updateOneToMany ( $oneToManyRelations, $members, $className, $instance, $values );
95
				}
96
			}
97
		}
98 4
		return $update;
99
	}
100
	
101 4
	protected static function setInputValues(string $className,$instance,&$values,$setValues){
102 4
		$fieldTypes = OrmUtils::getFieldTypes ( $className );
103 4
		foreach ( $fieldTypes as $property => $type ) {
104 4
			if (DbTypes::isBoolean($type)) {
105
				if (isset ( $values [$property] )) {
106
					$values [$property] = 1;
107
				} else {
108
					$values [$property] = 0;
109
				}
110
			}
111
		}
112 4
		if ($setValues) {
113 3
			URequest::setValuesToObject ( $instance, $values );
114
		}
115 4
	}
116
117
	private static function getInputValues($values,$index){
118
		$r=[];
119
		foreach ($values as $k=>$oValues){
120
			if($k!=='_status') {
121
				$r[$k] = $oValues[$index];
122
			}
123
		}
124
		return $r;
125
	}
126
127
	private static function getOneToManyKeys($keys,$values,$index,$defaultId){
128
		$r=[];
129
		foreach ( $keys as $k){
130
			$nk=$values[$k][$index]??$defaultId;
131
			$r[$k]=$nk;
132
			if($nk==''){
133
				return false;
134
			}
135
		}
136
		return $r;
137
	}
138
139 4
	protected static function updateOneToMany($oneToManyRelations,$members,$className,$instance,$values){
140 4
		$id=OrmUtils::getFirstKeyValue($instance);
141 4
		$newValues=[];
142 4
		foreach ($oneToManyRelations as $name){
143 4
			$member=$name.'Ids';
144 4
			$len=\strlen($member);
145 4
			if(($values[$member]??'')==='updated'){
146
				foreach ($values as $k=>$v){
147
					if(\substr($k, 0, $len) === $member){
148
						$newK=\substr($k,$len+1);
149
						if($newK!=null) {
150
							$newValues[$newK] = $v;
151
						}
152
					}
153
				}
154
				$r=OrmUtils::getAnnotationInfoMember($className,'#oneToMany',$name);
155
				$fkClass=$r['className'];
156
				$keys=\array_keys(OrmUtils::getKeyFields($fkClass));
157
				foreach ($newValues['_status'] as $index=>$status){
158
					$kv=self::getOneToManyKeys($keys,$newValues,$index,$id);
159
					if($kv!==false) {
160
						switch ($status) {
161
							case 'deleted':
162
								DAO::deleteById($fkClass,$kv);
163
								break;
164
							case 'updated':
165
								$o = DAO::getById($fkClass, $kv);
166
								if ($o) {
167
									$oValues = self::getInputValues($newValues, $index);
168
									self::setInputValues($fkClass, $o, $oValues, true);
169
									DAO::update($o);
170
								}
171
								break;
172
							case 'added':
173
								$o=new $fkClass();
174
								$oValues = \array_merge($kv,self::getInputValues($newValues, $index));
175
								self::setInputValues($fkClass, $o, $oValues, true);
176
								DAO::insert($o);
177
								break;
178
						}
179
					}
180
				}
181
			}
182
		}
183 4
	}
184
185
	protected static function updateManyToOne($manyToOneRelations, $members, $className, $instance, $values) {
186
		foreach ( $manyToOneRelations as $member ) {
187
			if (\array_search ( $member, $members ) !== false) {
188
				$joinColumn = OrmUtils::getAnnotationInfoMember ( $className, '#joinColumn', $member );
189
				if ($joinColumn) {
190
					$fkClass = $joinColumn ['className'];
191
					$fkField = $joinColumn ['name'];
192
					if (isset ( $values [$fkField] )) {
193
						if ($values [$fkField] != null) {
194
							$fkObject = DAO::getById ( $fkClass, $values ["$fkField"] );
195
							Reflexion::setMemberValue ( $instance, $member, $fkObject );
196
						} elseif ($joinColumn ['nullable'] ?? false) {
197
							Reflexion::setMemberValue ( $instance, $member, null );
198
						}
199
					}
200
				}
201
			}
202
		}
203
	}
204
205
	protected static function updateManyToMany($manyToManyRelations, $members, $className, $instance, $values) {
206
		foreach ( $manyToManyRelations as $member ) {
207
			if (\array_search ( $member, $members ) !== false) {
208
				if (($annot = OrmUtils::getAnnotationInfoMember ( $className, '#manyToMany', $member )) !== false) {
209
					$newField = $member . 'Ids';
210
					$fkClass = $annot ['targetEntity'];
211
					$fkObjects = DAO::getAll ( $fkClass, self::getMultiWhere ( $values [$newField], $fkClass ) );
212
					if (Reflexion::setMemberValue ( $instance, $member, $fkObjects )) {
213
						DAO::insertOrUpdateManyToMany ( $instance, $member );
214
					}
215
				}
216
			}
217
		}
218
	}
219
220
	private static function getMultiWhere($ids, $class) {
221
		$pk = OrmUtils::getFirstKey ( $class );
222
		$ids = explode ( ',', $ids );
223
		$idCount = \count ( $ids );
224
		if ($idCount < 1)
225
			return '';
226
		$strs = [ ];
227
		for($i = 0; $i < $idCount; $i ++) {
228
			$strs [] = $pk . "='" . $ids [$i] . "'";
229
		}
230
		return \implode ( " OR ", $strs );
231
	}
232
233 4
	public static function getFkIntance($instance, $model, $member, $included = false) {
234 4
		$result = [ ];
235 4
		if (($annot = OrmUtils::getAnnotationInfoMember ( $model, '#oneToMany', $member )) !== false) {
236 4
			$objectFK = DAO::getOneToMany ( $instance, $member, $included );
237 4
			$fkClass = $annot ['className'];
238 1
		} elseif (($annot = OrmUtils::getAnnotationInfoMember ( $model, '#manyToMany', $member )) !== false) {
239 1
			$objectFK = DAO::getManyToMany ( $instance, $member );
240 1
			$fkClass = $annot ['targetEntity'];
241
		} else {
242 1
			$objectFK = Reflexion::getMemberValue ( $instance, $member );
243 1
			if ($objectFK!=null && ! is_object ( $objectFK )) {
244
				$objectFK = DAO::getManyToOne ( $instance, $member, $included );
245
			}
246 1
			if (isset ( $objectFK ))
247 1
				$fkClass = \get_class ( $objectFK );
248
		}
249 4
		if (isset ( $fkClass )) {
250 4
			$fkTable = OrmUtils::getTableName ( $fkClass );
251 4
			$result [$member] = compact ( 'objectFK', 'fkClass', 'fkTable' );
252
		}
253 4
		return $result;
254
	}
255
256 4
	public static function getFKIntances($instance, $model, $included = false) {
257 4
		$result = [ ];
258 4
		$relations = OrmUtils::getFieldsInRelations ( $model );
259 4
		foreach ( $relations as $member ) {
260 4
			$fkInstance = self::getFkIntance ( $instance, $model, $member, $included );
261 4
			if (\count ( $fkInstance ) > 0) {
262 4
				$result = \array_merge ( $result, $fkInstance );
263
			}
264
		}
265 4
		return $result;
266
	}
267
}
268
269