Passed
Push — master ( f5da16...2e3bf1 )
by Jean-Christophe
12:28
created

DAOUpdatesTrait::remove_()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 11
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
eloc 9
dl 0
loc 11
ccs 0
cts 9
cp 0
rs 9.9666
c 0
b 0
f 0
cc 3
nc 4
nop 4
crap 12
1
<?php
2
3
namespace Ubiquity\orm\traits;
4
5
use Ubiquity\db\SqlUtils;
6
use Ubiquity\events\DAOEvents;
7
use Ubiquity\events\EventsManager;
8
use Ubiquity\log\Logger;
9
use Ubiquity\orm\OrmUtils;
10
use Ubiquity\orm\parser\ManyToManyParser;
11
use Ubiquity\orm\parser\Reflexion;
12
use Ubiquity\controllers\Startup;
13
14
/**
15
 * Trait for DAO Updates (Create, Update, Delete)
16
 * Ubiquity\orm\traits$DAOUpdatesTrait
17
 * This class is part of Ubiquity
18
 *
19
 * @author jcheron <[email protected]>
20
 * @version 1.1.7
21
 * @property \Ubiquity\db\Database $db
22
 *
23
 */
24
trait DAOUpdatesTrait {
25
	
26
	/**
27
	 * Deletes the object $instance from the database
28
	 *
29
	 * @param object $instance instance à supprimer
30
	 */
31 13
	public static function remove($instance): ?int {
32 13
		self::deleteAllChildren($instance);
33 13
		$className = \get_class ( $instance );
34 13
		$tableName = OrmUtils::getTableName ( $className );
35 13
		$keyAndValues = OrmUtils::getKeyFieldsAndValues ( $instance );
36 13
		return self::removeByKey_ ( $className, $tableName, $keyAndValues );
37
	}
38
	
39
	/**
40
	 *
41
	 * @param string $className
42
	 * @param string $tableName
43
	 * @param array $keyAndValues
44
	 * @return int the number of rows that were modified or deleted by the SQL statement you issued
45
	 */
46 13
	private static function removeByKey_($className, $tableName, $keyAndValues): ?int {
47 13
		$db = self::getDb ( $className );
48 13
		$sql = 'DELETE FROM ' . $db->quote . $tableName . $db->quote . ' WHERE ' . SqlUtils::getWhere ( $keyAndValues );
49 13
		Logger::info ( 'DAOUpdates', $sql, 'delete' );
50 13
		$statement = $db->prepareStatement ( $sql );
51
		try {
52 13
			if ($statement->execute ( $keyAndValues )) {
53 12
				return $statement->rowCount ();
54
			}
55 1
		} catch ( \PDOException $e ) {
56 1
			Logger::warn ( 'DAOUpdates', $e->getMessage (), 'delete' );
57 1
			return null;
58
		}
59
		return 0;
60
	}
61
	
62
	/**
63
	 *
64
	 * @param \Ubiquity\db\Database $db
65
	 * @param string $className
66
	 * @param string $tableName
67
	 * @param string $where
68
	 * @param array $params
69
	 * @return boolean|int the number of rows that were modified or deleted by the SQL statement you issued
70
	 */
71
	private static function remove_($db, $tableName, $where, $params) {
72
		$sql = 'DELETE FROM ' . $tableName . ' ' . SqlUtils::checkWhere ( $where );
73
		Logger::info ( 'DAOUpdates', $sql, 'delete' );
74
		$statement = $db->prepareStatement ( $sql );
75
		try {
76
			if ($statement->execute ( $params )) {
77
				return $statement->rowCount ();
78
			}
79
		} catch ( \PDOException $e ) {
80
			Logger::warn ( 'DAOUpdates', $e->getMessage (), 'delete' );
81
			return false;
82
		}
83
	}
84
	
85
	/**
86
	 * Deletes all instances from $modelName matching the condition $where.
87
	 *
88
	 * @param string $modelName
89
	 * @param string $where
90
	 * @param array $params
91
	 * @return int|boolean
92
	 */
93
	public static function deleteAll($modelName, $where, $params = [ ]) {
94
		$db = self::getDb ( $modelName );
95
		$quote = $db->quote;
96
		$tableName = OrmUtils::getTableName ( $modelName );
97
		return self::remove_ ( $db, $quote . $tableName . $quote, $where, $params );
98
	}
99
	
100
	protected static function deleteManyToManyChildren(object $instance,string $memberName){
101
		$modelName=\get_class($instance);
102
		$db = self::getDb ( $modelName );
103
		$manyParser=new ManyToManyParser($db,$instance,$memberName);
104
		$manyParser->init();
105
		$pkv=OrmUtils::getFirstKeyValue($instance);
106
		$quote = $db->quote;
107
		$tableName = $manyParser->getJoinTable();
108
		$fkManyField=$manyParser->getMyFkField();
109
		return self::remove_ ( $db, $quote . $tableName . $quote, "$fkManyField= ?", [$pkv] );
110
	}
111
	
112
	protected static function deleteOneToManyChildren(object $instance,string $memberName){
113
		$getter='get'.\ucfirst($memberName);
114
		$instances=$instance->{$getter}();
115
		foreach ($instances as $o){
116
			self::remove($o);
117
		}
118
	}
119
	
120
	
121 13
	public static function deleteAllChildren(object $instance){
122 13
		$classname=\get_class($instance);
123 13
		$oneToManyMembers=OrmUtils::getRemoveCascadeFields($classname);
124 13
		$continue=true;
125 13
		$i=0;
126 13
		$count=\count($oneToManyMembers);
127 13
		while($continue!==false && $i<$count){
128
			$continue=self::deleteOneToManyChildren($instance, $oneToManyMembers[$i]);
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $continue is correct as self::deleteOneToManyChi... $oneToManyMembers[$i]) targeting Ubiquity\orm\traits\DAOU...leteOneToManyChildren() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
129
			$i++;
130
		}
131
		
132 13
		$manyToManyMembers=OrmUtils::getRemoveCascadeFields($classname,'#manyToMany');
133 13
		$continue=true;
134 13
		$j=0;
135 13
		$count=\count($manyToManyMembers);
136 13
		while($continue!==false && $j<$count){
137
			$continue=self::deleteManyToManyChildren($instance, $manyToManyMembers[$j]);
138
			$j++;
139
		}
140 13
		return $i+$j;
141
	}
142
	
143
	/**
144
	 * Mass update for $modelName matching the condition $where, with an associative array of $values.
145
	 *
146
	 * @param string $modelName
147
	 * @param array $values
148
	 * @param string $condition
149
	 * @param array $params
150
	 */
151
	public static function updateAll(string $modelName,array $values,string $condition,array $params){
152
		$db = self::getDb ( $modelName );
153
		$quote = $db->quote;
154
		$tableName = OrmUtils::getTableName ( $modelName );
155
		
156
		$allParams = \array_merge ( $values, $params );
157
		
158
		$sql = "UPDATE {$quote}{$tableName}{$quote} SET " . SqlUtils::getUpdateFieldsKeyAndParams ( $values ) . SqlUtils::checkWhereParams($condition,$params);
159
		if (Logger::isActive ()) {
160
			Logger::info ( "DAOUpdates", $sql, "updateAll" );
161
			Logger::info ( "DAOUpdates", \json_encode ( $allParams ), "All params" );
162
		}
163
		$statement = $db->getUpdateStatement ( $sql );
164
		try {
165
			return  $statement->execute ( $allParams );
166
		}catch ( \Exception $e ) {
167
			Logger::warn ( "DAOUpdates", $e->getMessage (), "updateAll" );
168
		}
169
		return false;
170
	}
171
	
172
	/**
173
	 * Deletes all instances from $modelName corresponding to $ids
174
	 *
175
	 * @param string $modelName
176
	 * @param array|int $ids
177
	 * @return int|boolean
178
	 */
179
	public static function delete($modelName, $ids) {
180
		$tableName = OrmUtils::getTableName ( $modelName );
181
		$db = self::getDb ( $modelName );
182
		$pk = OrmUtils::getFirstKey ( $modelName );
183
		if (! \is_array ( $ids )) {
184
			$ids = [ $ids ];
185
		}
186
		$quote = $db->quote;
187
		$count = \count ( $ids );
188
		$r = $quote . $pk . $quote . "= ?";
189
		return self::remove_ ( $db, $quote . $tableName . $quote, \str_repeat ( "$r OR", $count - 1 ) . $r, $ids );
190
	}
191
	
192
	public static function deleteById($modelName,$id){
193
		$tableName = OrmUtils::getTableName ( $modelName );
194
		if(!\is_array($id)){
195
			$id=[OrmUtils::getFirstKey($modelName)=>$id];
196
		}
197
		return self::removeByKey_($modelName,$tableName,$id);
198
	}
199
	
200
	/**
201
	 * Inserts a new instance $instance into the database
202
	 *
203
	 * @param object $instance the instance to insert
204
	 * @param boolean $insertMany if true, save instances related to $instance by a ManyToMany association
205
	 */
206 20
	public static function insert($instance, $insertMany = false) {
207 20
		EventsManager::trigger ( 'dao.before.insert', $instance );
208 20
		$className = \get_class ( $instance );
209 20
		$db = self::getDb ( $className );
210 20
		$quote = $db->quote;
211 20
		$tableName = OrmUtils::getTableName ( $className );
212 20
		$keyAndValues = Reflexion::getPropertiesAndValues ( $instance );
213 20
		$keyAndValues = \array_merge ( $keyAndValues, OrmUtils::getManyToOneMembersAndValues ( $instance ) );
214 20
		$pk = OrmUtils::getFirstKey ( $className );
215 20
		$pkVal = $keyAndValues [$pk] ?? null;
216 20
		if (($pkVal) == null) {
217 20
			unset ( $keyAndValues [$pk] );
218
		}
219 20
		$sql = "INSERT INTO {$quote}{$tableName}{$quote} (" . SqlUtils::getInsertFields ( $keyAndValues ) . ') VALUES(' . SqlUtils::getInsertFieldsValues ( $keyAndValues ) . ')';
220 20
		if (Logger::isActive ()) {
221 20
			Logger::info ( 'DAOUpdates', $sql, 'insert' );
222 20
			Logger::info ( 'DAOUpdates', \json_encode ( $keyAndValues ), 'Key and values' );
223
		}
224
		
225 20
		$statement = $db->getUpdateStatement ( $sql );
226
		try {
227 20
			$result = $statement->execute ( $keyAndValues );
228 20
			if ($result) {
229 20
				if ($pkVal == null) {
230 20
					$lastId = $db->lastInserId ( "{$tableName}_{$pk}_seq" );
231 20
					if ($lastId != 0) {
232 20
						$propKey = OrmUtils::getFirstPropKey ( $className );
233 20
						$propKey->setValue ( $instance, $lastId );
234 20
						$pkVal = $lastId;
235
					}
236
				}
237 20
				$instance->_rest = $keyAndValues;
238 20
				$instance->_rest [$pk] = $pkVal;
239
				
240 20
				if ($insertMany) {
241 1
					self::insertOrUpdateAllManyToMany ( $instance );
242
				}
243
			}
244 20
			EventsManager::trigger ( DAOEvents::AFTER_INSERT, $instance, $result );
245 20
			return $result;
246 1
		} catch ( \Exception $e ) {
247 1
			Logger::warn ( 'DAOUpdates', $e->getMessage (), 'insert' );
248 1
			if (Startup::$config ['debug']) {
249 1
				throw $e;
250
			}
251
		}
252
		return false;
253
	}
254
	
255
	/**
256
	 * Updates manyToMany members
257
	 *
258
	 * @param object $instance
259
	 */
260 1
	public static function insertOrUpdateAllManyToMany($instance) {
261 1
		$members = OrmUtils::getAnnotationInfo ( get_class ( $instance ), '#manyToMany' );
262 1
		if ($members !== false) {
263
			$members = \array_keys ( $members );
264
			foreach ( $members as $member ) {
265
				self::insertOrUpdateManyToMany ( $instance, $member );
266
			}
267
		}
268 1
	}
269
	
270
	/**
271
	 * Updates the $member member of $instance annotated by a ManyToMany
272
	 *
273
	 * @param Object $instance
274
	 * @param String $member
275
	 */
276
	public static function insertOrUpdateManyToMany($instance, $member) {
277
		$db = self::getDb ( \get_class ( $instance ) );
278
		$parser = new ManyToManyParser ( $db, $instance, $member );
279
		if ($parser->init ()) {
280
			$quote = $db->quote;
281
			$myField = $parser->getMyFkField ();
282
			$field = $parser->getFkField ();
283
			$sql = "INSERT INTO {$quote}" . $parser->getJoinTable () . "{$quote}({$quote}" . $myField . "{$quote},{$quote}" . $field . "{$quote}) VALUES (:" . $myField . ",:" . $field . ");";
284
			$memberAccessor = 'get' . \ucfirst ( $member );
285
			$memberValues = $instance->$memberAccessor ();
286
			$myKey = $parser->getMyPk ();
287
			$myAccessorId = 'get' . \ucfirst ( $myKey );
288
			$accessorId = 'get' . \ucfirst ( $parser->getPk () );
289
			$id = $instance->$myAccessorId ();
290
			if (! \is_null ( $memberValues )) {
291
				$db->execute ( "DELETE FROM {$quote}" . $parser->getJoinTable () . "{$quote} WHERE {$quote}{$myField}{$quote}='{$id}'" );
292
				$statement = $db->prepareStatement ( $sql );
293
				foreach ( $memberValues as $targetInstance ) {
294
					$foreignId = $targetInstance->$accessorId ();
295
					$foreignInstances = self::getAll ( $parser->getTargetEntity (), $quote . $parser->getPk () . $quote . "='{$foreignId}'" );
296
					if (! OrmUtils::exists ( $targetInstance, $parser->getPk (), $foreignInstances )) {
297
						self::insert ( $targetInstance, false );
298
						$foreignId = $targetInstance->$accessorId ();
299
						Logger::info ( 'DAOUpdates', "Insertion d'une instance de " . get_class ( $instance ), 'InsertMany' );
300
					}
301
					$db->bindValueFromStatement ( $statement, $myField, $id );
302
					$db->bindValueFromStatement ( $statement, $field, $foreignId );
303
					$statement->execute ();
304
					Logger::info ( 'DAOUpdates', "Insertion des valeurs dans la table association '" . $parser->getJoinTable () . "'", 'InsertMany' );
305
				}
306
			}
307
		}
308
	}
309
	
310
	/**
311
	 * Updates an existing $instance in the database.
312
	 * Be careful not to modify the primary key
313
	 *
314
	 * @param object $instance instance to modify
315
	 * @param boolean $updateMany Adds or updates ManyToMany members
316
	 */
317 3
	public static function update($instance, $updateMany = false) {
318 3
		EventsManager::trigger ( 'dao.before.update', $instance );
319 3
		$className = \get_class ( $instance );
320 3
		$db = self::getDb ( $className );
321 3
		$quote = $db->quote;
322 3
		$tableName = OrmUtils::getTableName ( $className );
323 3
		$ColumnskeyAndValues = \array_merge ( Reflexion::getPropertiesAndValues ( $instance ), OrmUtils::getManyToOneMembersAndValues ( $instance ) );
324 3
		$keyFieldsAndValues = OrmUtils::getKeyFieldsAndValues ( $instance );
325 3
		$sql = "UPDATE {$quote}{$tableName}{$quote} SET " . SqlUtils::getUpdateFieldsKeyAndParams ( $ColumnskeyAndValues ) . ' WHERE ' . SqlUtils::getWhere ( $keyFieldsAndValues );
326 3
		if (Logger::isActive ()) {
327 3
			Logger::info ( "DAOUpdates", $sql, "update" );
328 3
			Logger::info ( "DAOUpdates", \json_encode ( $ColumnskeyAndValues ), "Key and values" );
329
		}
330 3
		$statement = $db->getUpdateStatement ( $sql );
331
		try {
332 3
			$result = $statement->execute ( $ColumnskeyAndValues );
333 3
			if ($updateMany && $result) {
334 1
				self::insertOrUpdateAllManyToMany ( $instance );
335
			}
336 3
			EventsManager::trigger ( DAOEvents::AFTER_UPDATE, $instance, $result );
337 3
			$instance->_rest = \array_merge ( $instance->_rest, $ColumnskeyAndValues );
338 3
			return $result;
339
		} catch ( \Exception $e ) {
340
			Logger::warn ( "DAOUpdates", $e->getMessage (), "update" );
341
		}
342
		return false;
343
	}
344
	
345
	/**
346
	 * Updates an array of $instances in the database.
347
	 * Be careful not to modify the primary key
348
	 *
349
	 * @param array $instances instances to modify
350
	 * @param boolean $updateMany Adds or updates ManyToMany members
351
	 * @return boolean
352
	 */
353
	public static function updateGroup($instances, $updateMany = false) {
354
		if (\count ( $instances ) > 0) {
355
			$instance = \current ( $instances );
356
			$className = \get_class ( $instance );
357
			$db = self::getDb ( $className );
358
			$quote = $db->quote;
359
			$tableName = OrmUtils::getTableName ( $className );
360
			$ColumnskeyAndValues = \array_merge ( Reflexion::getPropertiesAndValues ( $instance ), OrmUtils::getManyToOneMembersAndValues ( $instance ) );
361
			$keyFieldsAndValues = OrmUtils::getKeyFieldsAndValues ( $instance );
362
			$sql = "UPDATE {$quote}{$tableName}{$quote} SET " . SqlUtils::getUpdateFieldsKeyAndParams ( $ColumnskeyAndValues ) . ' WHERE ' . SqlUtils::getWhere ( $keyFieldsAndValues );
363
			
364
			$statement = $db->getUpdateStatement ( $sql );
365
			try {
366
				$db->beginTransaction ();
367
				foreach ( $instances as $instance ) {
368
					EventsManager::trigger ( 'dao.before.update', $instance );
369
					$ColumnskeyAndValues = \array_merge ( Reflexion::getPropertiesAndValues ( $instance ), OrmUtils::getManyToOneMembersAndValues ( $instance ) );
370
					$result = $statement->execute ( $ColumnskeyAndValues );
371
					if ($updateMany && $result) {
372
						self::insertOrUpdateAllManyToMany ( $instance );
373
					}
374
					EventsManager::trigger ( DAOEvents::AFTER_UPDATE, $instance, $result );
375
					$instance->_rest = \array_merge ( $instance->_rest, $ColumnskeyAndValues );
376
					if (Logger::isActive ()) {
377
						Logger::info ( "DAOUpdates", $sql, "update" );
378
						Logger::info ( "DAOUpdates", json_encode ( $ColumnskeyAndValues ), "Key and values" );
379
					}
380
				}
381
				$db->commit ();
382
				return true;
383
			} catch ( \Exception $e ) {
384
				Logger::warn ( "DAOUpdates", $e->getMessage (), "update" );
385
				$db->rollBack ();
386
			}
387
		}
388
		return false;
389
	}
390
	
391
	/**
392
	 *
393
	 * @param object $instance
394
	 * @param boolean $updateMany
395
	 * @return boolean|int
396
	 */
397
	public static function save($instance, $updateMany = false) {
398
		if (isset ( $instance->_rest )) {
399
			return self::update ( $instance, $updateMany );
400
		}
401
		return self::insert ( $instance, $updateMany );
402
	}
403
}
404