Passed
Push — master ( da6711...ab6128 )
by Jean-Christophe
11:17
created

CRUDHelper::getMultiWhere()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 11
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
cc 3
eloc 9
nc 3
nop 2
dl 0
loc 11
ccs 0
cts 10
cp 0
crap 12
rs 9.9666
c 0
b 0
f 0
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 7
	public static function getIdentifierFunction($model) {
24 7
		$pks = OrmUtils::getKeyMembers ( $model );
25
		return function ($index, $instance) use ($pks) {
26 7
			$values = [ ];
27 7
			foreach ( $pks as $pk ) {
28 7
				$getter = 'get' . \ucfirst ( $pk );
29 7
				if (\method_exists ( $instance, $getter )) {
30 7
					$values [] = $instance->{$getter} ();
31
				}
32
			}
33 7
			return \implode ( '_', $values );
34 7
		};
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 3
	public static function update($instance, $values, $setValues = true, $updateMany = true, $eventCallback = null) {
62 3
		$className = \get_class ( $instance );
63 3
		$fieldsInRelationForUpdate = OrmUtils::getFieldsInRelationsForUpdate_ ( $className );
64 3
		$manyToOneRelations = $fieldsInRelationForUpdate ['manyToOne'];
65 3
		$manyToManyRelations = $fieldsInRelationForUpdate ['manyToMany'];
66 3
		$oneToManyRelations = $fieldsInRelationForUpdate ['oneToMany'];
67
68 3
		$members = \array_keys ( $values );
69 3
		OrmUtils::setFieldToMemberNames ( $members, $fieldsInRelationForUpdate ['relations'] );
70 3
		$update = false;
71
72 3
		$fieldTypes = OrmUtils::getFieldTypes ( $className );
73 3
		foreach ( $fieldTypes as $property => $type ) {
74 3
			if (DbTypes::isBoolean($type)) {
75
				if (isset ( $values [$property] )) {
76
					$values [$property] = 1;
77
				} else {
78
					$values [$property] = 0;
79
				}
80
			}
81
		}
82 3
		if ($setValues) {
83 3
			URequest::setValuesToObject ( $instance, $values );
84
		}
85 3
		if ($manyToOneRelations) {
86
			self::updateManyToOne ( $manyToOneRelations, $members, $className, $instance, $values );
87
		}
88 3
		if (isset ( $instance )) {
89 3
			if (isset ( $eventCallback )) {
90 3
				$eventCallback ( $instance, $instance->_new );
91
			}
92 3
			if ($instance->_new) {
93 1
				$update = DAO::insert ( $instance );
94
			} else {
95 2
				$update = DAO::update ( $instance );
96 2
				if (DbCache::$active) {
97
					// TODO update dbCache
98
				}
99
			}
100 3
			if ($updateMany && $update && $manyToManyRelations) {
101
				self::updateManyToMany ( $manyToManyRelations, $members, $className, $instance, $values );
102
			}
103 3
			if ($updateMany && $update && $oneToManyRelations) {
104 3
				self::updateOneToMany ( $oneToManyRelations, $members, $className, $instance, $values );
105
			}
106
		}
107 3
		return $update;
108
	}
109
110
	private static function getInputValues($values,$index){
111
		$r=[];
112
		foreach ($values as $k=>$oValues){
113
			if($k!=='_status') {
114
				$r[$k] = $oValues[$index];
115
			}
116
		}
117
		return $r;
118
	}
119
120
	private static function getOneToManyKeys($keys,$values,$index,$defaultId){
121
		$r=[];
122
		foreach ( $keys as $k){
123
			$nk=$values[$k][$index]??$defaultId;
124
			$r[$k]=$nk;
125
			if($nk==''){
126
				return false;
127
			}
128
		}
129
		return $r;
130
	}
131
132 3
	protected static function updateOneToMany($oneToManyRelations,$members,$className,$instance,$values){
133 3
		$id=OrmUtils::getFirstKeyValue($instance);
134 3
		$newValues=[];
135 3
		foreach ($oneToManyRelations as $name){
136 3
			$member=$name.'Ids';
137 3
			$len=\strlen($member);
138 3
			if(($values[$member]??'')==='updated'){
139
				foreach ($values as $k=>$v){
140
					if(\substr($k, 0, $len) === $member){
141
						$newK=\substr($k,$len+1);
142
						if($newK!=null) {
143
							$newValues[$newK] = $v;
144
						}
145
					}
146
				}
147
				$r=OrmUtils::getAnnotationInfoMember($className,'#oneToMany',$name);
148
				$fkClass=$r['className'];
149
				$keys=\array_keys(OrmUtils::getKeyFields($fkClass));
150
				foreach ($newValues['_status'] as $index=>$status){
151
					$kv=self::getOneToManyKeys($keys,$newValues,$index,$id);
152
					if($kv!==false) {
153
						switch ($status) {
154
							case 'deleted':
155
								DAO::deleteById($fkClass,$kv);
156
								break;
157
							case 'updated':
158
								$o = DAO::getById($fkClass, $kv);
159
								if ($o) {
160
									$oValues = self::getInputValues($newValues, $index);
161
									URequest::setValuesToObject($o, $oValues);
162
									DAO::update($o);
163
								}
164
								break;
165
							case 'added':
166
								$o=new $fkClass();
167
								$oValues = \array_merge($kv,self::getInputValues($newValues, $index));
168
								URequest::setValuesToObject($o, $oValues);
169
								DAO::insert($o);
170
								break;
171
						}
172
					}
173
				}
174
			}
175
		}
176 3
	}
177
178
	protected static function updateManyToOne($manyToOneRelations, $members, $className, $instance, $values) {
179
		foreach ( $manyToOneRelations as $member ) {
180
			if (\array_search ( $member, $members ) !== false) {
181
				$joinColumn = OrmUtils::getAnnotationInfoMember ( $className, '#joinColumn', $member );
182
				if ($joinColumn) {
183
					$fkClass = $joinColumn ['className'];
184
					$fkField = $joinColumn ['name'];
185
					if (isset ( $values [$fkField] )) {
186
						if ($values [$fkField] != null) {
187
							$fkObject = DAO::getById ( $fkClass, $values ["$fkField"] );
188
							Reflexion::setMemberValue ( $instance, $member, $fkObject );
189
						} elseif ($joinColumn ['nullable'] ?? false) {
190
							Reflexion::setMemberValue ( $instance, $member, null );
191
						}
192
					}
193
				}
194
			}
195
		}
196
	}
197
198
	protected static function updateManyToMany($manyToManyRelations, $members, $className, $instance, $values) {
199
		foreach ( $manyToManyRelations as $member ) {
200
			if (\array_search ( $member, $members ) !== false) {
201
				if (($annot = OrmUtils::getAnnotationInfoMember ( $className, '#manyToMany', $member )) !== false) {
202
					$newField = $member . 'Ids';
203
					$fkClass = $annot ['targetEntity'];
204
					$fkObjects = DAO::getAll ( $fkClass, self::getMultiWhere ( $values [$newField], $fkClass ) );
205
					if (Reflexion::setMemberValue ( $instance, $member, $fkObjects )) {
206
						DAO::insertOrUpdateManyToMany ( $instance, $member );
207
					}
208
				}
209
			}
210
		}
211
	}
212
213
	private static function getMultiWhere($ids, $class) {
214
		$pk = OrmUtils::getFirstKey ( $class );
215
		$ids = explode ( ',', $ids );
216
		$idCount = \count ( $ids );
217
		if ($idCount < 1)
218
			return '';
219
		$strs = [ ];
220
		for($i = 0; $i < $idCount; $i ++) {
221
			$strs [] = $pk . "='" . $ids [$i] . "'";
222
		}
223
		return \implode ( " OR ", $strs );
224
	}
225
226 3
	public static function getFkIntance($instance, $model, $member, $included = false) {
227 3
		$result = [ ];
228 3
		if (($annot = OrmUtils::getAnnotationInfoMember ( $model, '#oneToMany', $member )) !== false) {
229 3
			$objectFK = DAO::getOneToMany ( $instance, $member, $included );
230 3
			$fkClass = $annot ['className'];
231
		} elseif (($annot = OrmUtils::getAnnotationInfoMember ( $model, '#manyToMany', $member )) !== false) {
232
			$objectFK = DAO::getManyToMany ( $instance, $member );
233
			$fkClass = $annot ['targetEntity'];
234
		} else {
235
			$objectFK = Reflexion::getMemberValue ( $instance, $member );
236
			if ($objectFK!=null && ! is_object ( $objectFK )) {
237
				$objectFK = DAO::getManyToOne ( $instance, $member, $included );
238
			}
239
			if (isset ( $objectFK ))
240
				$fkClass = \get_class ( $objectFK );
241
		}
242 3
		if (isset ( $fkClass )) {
243 3
			$fkTable = OrmUtils::getTableName ( $fkClass );
244 3
			$result [$member] = compact ( 'objectFK', 'fkClass', 'fkTable' );
245
		}
246 3
		return $result;
247
	}
248
249 3
	public static function getFKIntances($instance, $model, $included = false) {
250 3
		$result = [ ];
251 3
		$relations = OrmUtils::getFieldsInRelations ( $model );
252 3
		foreach ( $relations as $member ) {
253 3
			$fkInstance = self::getFkIntance ( $instance, $model, $member, $included );
254 3
			if (\count ( $fkInstance ) > 0) {
255 3
				$result = \array_merge ( $result, $fkInstance );
256
			}
257
		}
258 3
		return $result;
259
	}
260
}
261
262