Passed
Push — master ( c4282d...8835f1 )
by Jean-Christophe
10:25
created

DAO::connect()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2.5

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 6
c 2
b 0
f 0
dl 0
loc 7
ccs 3
cts 6
cp 0.5
rs 10
cc 2
nc 2
nop 10
crap 2.5

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
namespace Ubiquity\orm;
4
5
use Ubiquity\db\Database;
6
use Ubiquity\log\Logger;
7
use Ubiquity\orm\parser\ManyToManyParser;
8
use Ubiquity\db\SqlUtils;
9
use Ubiquity\orm\traits\DAOUpdatesTrait;
10
use Ubiquity\orm\traits\DAORelationsTrait;
11
use Ubiquity\orm\parser\ConditionParser;
12
use Ubiquity\orm\traits\DAOUQueries;
13
use Ubiquity\orm\traits\DAOCoreTrait;
14
use Ubiquity\orm\traits\DAORelationsPrepareTrait;
15
use Ubiquity\exceptions\DAOException;
16
use Ubiquity\orm\traits\DAORelationsAssignmentsTrait;
17
use Ubiquity\orm\parser\Reflexion;
18
use Ubiquity\orm\traits\DAOTransactionsTrait;
19
use Ubiquity\controllers\Startup;
20
use Ubiquity\cache\CacheManager;
21
use Ubiquity\orm\traits\DAOPooling;
22
23
/**
24
 * Gateway class between database and object model.
25
 * This class is part of Ubiquity
26
 *
27
 * @author jcheron <[email protected]>
28
 * @version 1.2.1
29
 *
30
 */
31
class DAO {
32
	use DAOCoreTrait,DAOUpdatesTrait,DAORelationsTrait,DAORelationsPrepareTrait,DAORelationsAssignmentsTrait,
33
	DAOUQueries,DAOTransactionsTrait,DAOPooling;
34
35
	/**
36
	 *
37
	 * @var Database
38
	 */
39
	public static $db;
40
	public static $useTransformers = false;
41
	public static $transformerOp = 'transform';
42
	private static $conditionParsers = [ ];
43
	protected static $modelsDatabase = [ ];
44
45 66
	protected static function getDb($model) {
46 66
		return self::getDatabase ( self::$modelsDatabase [$model] ?? 'default');
47
	}
48
49
	/**
50
	 * Loads member associated with $instance by a ManyToOne relationship
51
	 *
52
	 * @param object|array $instance The instance object or an array with [classname,id]
53
	 * @param string $member The member to load
54
	 * @param boolean|array $included if true, loads associate members with associations, if array, example : ["client.*","commands"]
55
	 * @param boolean|null $useCache
56
	 */
57 4
	public static function getManyToOne($instance, $member, $included = false, $useCache = NULL) {
58 4
		$classname = self::getClass_ ( $instance );
59 4
		if (is_array ( $instance )) {
60 1
			$instance = self::getById ( $classname, $instance [1], false, $useCache );
61
		}
62 4
		$fieldAnnot = OrmUtils::getMemberJoinColumns ( $classname, $member );
63 4
		if ($fieldAnnot !== null) {
64 4
			$annotationArray = $fieldAnnot [1];
65 4
			$member = $annotationArray ["member"];
66 4
			$value = Reflexion::getMemberValue ( $instance, $member );
67 4
			$key = OrmUtils::getFirstKey ( $annotationArray ["className"] );
68 4
			$kv = array ($key => $value );
69 4
			$obj = self::getById ( $annotationArray ["className"], $kv, $included, $useCache );
70 4
			if ($obj !== null) {
71 4
				Logger::info ( "DAO", "Loading the member " . $member . " for the object " . $classname, "getManyToOne" );
72 4
				$accesseur = "set" . ucfirst ( $member );
73 4
				if (is_object ( $instance ) && method_exists ( $instance, $accesseur )) {
74 4
					$instance->$accesseur ( $obj );
75 4
					$instance->_rest [$member] = $obj->_rest;
76
				}
77 4
				return $obj;
78
			}
79
		}
80
	}
81
82
	/**
83
	 * Assign / load the child records in the $member member of $instance.
84
	 *
85
	 * @param object|array $instance The instance object or an array with [classname,id]
86
	 * @param string $member Member on which a oneToMany annotation must be present
87
	 * @param boolean|array $included if true, loads associate members with associations, if array, example : ["client.*","commands"]
88
	 * @param boolean $useCache
89
	 * @param array $annot used internally
90
	 */
91 7
	public static function getOneToMany($instance, $member, $included = true, $useCache = NULL, $annot = null) {
92 7
		$ret = array ();
93 7
		$class = self::getClass_ ( $instance );
94 7
		if (! isset ( $annot )) {
95 7
			$annot = OrmUtils::getAnnotationInfoMember ( $class, "#oneToMany", $member );
96
		}
97 7
		if ($annot !== false) {
98 7
			$fkAnnot = OrmUtils::getAnnotationInfoMember ( $annot ["className"], "#joinColumn", $annot ["mappedBy"] );
99 7
			if ($fkAnnot !== false) {
100 7
				$fkv = self::getFirstKeyValue_ ( $instance );
101 7
				$db = self::getDb ( $annot ["className"] );
102 7
				$ret = self::_getAll ( $db, $annot ["className"], ConditionParser::simple ( $db->quote . $fkAnnot ["name"] . $db->quote . "= ?", $fkv ), $included, $useCache );
103 7
				if (is_object ( $instance ) && $modifier = self::getAccessor ( $member, $instance, 'getOneToMany' )) {
104 6
					self::setToMember ( $member, $instance, $ret, $modifier );
105
				}
106
			}
107
		}
108 7
		return $ret;
109
	}
110
111
	/**
112
	 * Assigns / loads the child records in the $member member of $instance.
113
	 * If $array is null, the records are loaded from the database
114
	 *
115
	 * @param object|array $instance The instance object or an array with [classname,id]
116
	 * @param string $member Member on which a ManyToMany annotation must be present
117
	 * @param boolean|array $included if true, loads associate members with associations, if array, example : ["client.*","commands"]
118
	 * @param array $array optional parameter containing the list of possible child records
119
	 * @param boolean $useCache
120
	 */
121 4
	public static function getManyToMany($instance, $member, $included = false, $array = null, $useCache = NULL) {
122 4
		$ret = [ ];
123 4
		$class = self::getClass_ ( $instance );
124 4
		$parser = new ManyToManyParser ( $class, $member );
125 4
		if ($parser->init ()) {
126 4
			if (is_null ( $array )) {
127 4
				$pk = self::getFirstKeyValue_ ( $instance );
128 4
				$quote = SqlUtils::$quote;
129 4
				$condition = " INNER JOIN " . $quote . $parser->getJoinTable () . $quote . " on " . $quote . $parser->getJoinTable () . $quote . "." . $quote . $parser->getFkField () . $quote . "=" . $quote . $parser->getTargetEntityTable () . $quote . "." . $quote . $parser->getPk () . $quote . " WHERE " . $quote . $parser->getJoinTable () . $quote . "." . $quote . $parser->getMyFkField () . $quote . "= ?";
130 4
				$targetEntityClass = $parser->getTargetEntityClass ();
131 4
				$ret = self::_getAll ( self::getDb ( $targetEntityClass ), $targetEntityClass, ConditionParser::simple ( $condition, $pk ), $included, $useCache );
132
			} else {
133
				$ret = self::getManyToManyFromArray ( $instance, $array, $class, $parser );
134
			}
135 4
			if (is_object ( $instance ) && $modifier = self::getAccessor ( $member, $instance, 'getManyToMany' )) {
136 3
				self::setToMember ( $member, $instance, $ret, $modifier );
137
			}
138
		}
139 4
		return $ret;
140
	}
141
142
	/**
143
	 *
144
	 * @param object $instance
145
	 * @param array $array
146
	 * @param boolean $useCache
147
	 */
148
	public static function affectsManyToManys($instance, $array = NULL, $useCache = NULL) {
149
		$metaDatas = OrmUtils::getModelMetadata ( \get_class ( $instance ) );
150
		$manyToManyFields = $metaDatas ["#manyToMany"];
151
		if (\sizeof ( $manyToManyFields ) > 0) {
152
			foreach ( $manyToManyFields as $member ) {
153
				self::getManyToMany ( $instance, $member, false, $array, $useCache );
154
			}
155
		}
156
	}
157
158
	/**
159
	 * Returns an array of $className objects from the database
160
	 *
161
	 * @param string $className class name of the model to load
162
	 * @param string $condition Part following the WHERE of an SQL statement
163
	 * @param boolean|array $included if true, loads associate members with associations, if array, example : ["client.*","commands"]
164
	 * @param array|null $parameters
165
	 * @param boolean $useCache use the active cache if true
166
	 * @return array
167
	 */
168 23
	public static function getAll($className, $condition = '', $included = true, $parameters = null, $useCache = NULL) {
169 23
		return self::_getAll ( self::getDb ( $className ), $className, new ConditionParser ( $condition, null, $parameters ), $included, $useCache );
170
	}
171
172 3
	public static function paginate($className, $page = 1, $rowsPerPage = 20, $condition = null, $included = true) {
173 3
		if (! isset ( $condition )) {
174 1
			$condition = "1=1";
175
		}
176 3
		return self::getAll ( $className, $condition . " LIMIT " . $rowsPerPage . " OFFSET " . (($page - 1) * $rowsPerPage), $included );
177
	}
178
179 3
	public static function getRownum($className, $ids) {
180 3
		$tableName = OrmUtils::getTableName ( $className );
181 3
		$db = self::getDb ( $className );
182 3
		$quote = $db->quote;
183 3
		self::parseKey ( $ids, $className, $quote );
184 3
		$condition = SqlUtils::getCondition ( $ids, $className );
185 3
		$keyFields = OrmUtils::getKeyFields ( $className );
186 3
		if (is_array ( $keyFields )) {
187 3
			$keys = implode ( ",", $keyFields );
188
		} else {
189
			$keys = "1";
190
		}
191
192 3
		return $db->queryColumn ( "SELECT num FROM (SELECT *, @rownum:=@rownum + 1 AS num FROM {$quote}{$tableName}{$quote}, (SELECT @rownum:=0) r ORDER BY {$keys}) d WHERE " . $condition );
193
	}
194
195
	/**
196
	 * Returns the number of objects of $className from the database respecting the condition possibly passed as parameter
197
	 *
198
	 * @param string $className complete classname of the model to load
199
	 * @param string $condition Part following the WHERE of an SQL statement
200
	 * @param array|null $parameters The query parameters
201
	 * @return int|false count of objects
202
	 */
203 21
	public static function count($className, $condition = '', $parameters = null) {
204 21
		$tableName = OrmUtils::getTableName ( $className );
205 21
		if ($condition != '') {
206 9
			$condition = " WHERE " . $condition;
207
		}
208 21
		$db = self::getDb ( $className );
209 21
		$quote = $db->quote;
210 21
		return $db->prepareAndFetchColumn ( "SELECT COUNT(*) FROM " . $quote . $tableName . $quote . $condition, $parameters );
211
	}
212
213
	/**
214
	 * Returns an instance of $className from the database, from $keyvalues values of the primary key or with a condition
215
	 *
216
	 * @param String $className complete classname of the model to load
217
	 * @param Array|string $condition condition or primary key values
218
	 * @param boolean|array $included if true, charges associate members with association
219
	 * @param array|null $parameters the request parameters
220
	 * @param boolean|null $useCache use cache if true
221
	 * @return object the instance loaded or null if not found
222
	 */
223 16
	public static function getOne($className, $condition, $included = true, $parameters = null, $useCache = NULL) {
224 16
		$conditionParser = new ConditionParser ();
225 16
		if (! isset ( $parameters )) {
226 16
			$conditionParser->addKeyValues ( $condition, $className );
227
		} elseif (! is_array ( $condition )) {
228
			$conditionParser->setCondition ( $condition );
229
			$conditionParser->setParams ( $parameters );
230
		} else {
231
			throw new DAOException ( "The \$keyValues parameter should not be an array if \$parameters is not null" );
232
		}
233 16
		return self::_getOne ( self::getDb ( $className ), $className, $conditionParser, $included, $useCache );
234
	}
235
236
	/**
237
	 * Returns an instance of $className from the database, from $keyvalues values of the primary key
238
	 *
239
	 * @param String $className complete classname of the model to load
240
	 * @param Array|string $keyValues primary key values or condition
241
	 * @param boolean|array $included if true, charges associate members with association
242
	 * @param array|null $parameters the request parameters
243
	 * @param boolean|null $useCache use cache if true
244
	 * @return object the instance loaded or null if not found
245
	 */
246 20
	public static function getById($className, $keyValues, $included = true, $useCache = NULL) {
247 20
		return self::_getOne ( self::getDb ( $className ), $className, self::getConditionParser ( $className, $keyValues ), $included, $useCache );
248
	}
249
250 20
	protected static function getConditionParser($className, $keyValues) {
251 20
		if (! isset ( self::$conditionParsers [$className] )) {
252 13
			$conditionParser = new ConditionParser ();
253 13
			$conditionParser->addKeyValues ( $keyValues, $className );
254 13
			self::$conditionParsers [$className] = $conditionParser;
255
		} else {
256 9
			self::$conditionParsers [$className]->setKeyValues ( $keyValues );
257
		}
258 20
		return self::$conditionParsers [$className];
259
	}
260
261
	/**
262
	 * Establishes the connection to the database using the past parameters
263
	 *
264
	 * @param string $offset
265
	 * @param string $wrapper
266
	 * @param string $dbType
267
	 * @param string $dbName
268
	 * @param string $serverName
269
	 * @param string $port
270
	 * @param string $user
271
	 * @param string $password
272
	 * @param array $options
273
	 * @param boolean $cache
274
	 */
275 64
	public static function connect($offset, $wrapper, $dbType, $dbName, $serverName = '127.0.0.1', $port = '3306', $user = 'root', $password = '', $options = [], $cache = false) {
276 64
		self::$db [$offset] = new Database ( $wrapper, $dbType, $dbName, $serverName, $port, $user, $password, $options, $cache, self::$pool );
277
		try {
278 64
			self::$db [$offset]->connect ();
279
		} catch ( \Exception $e ) {
280
			Logger::error ( "DAO", $e->getMessage () );
281
			throw new DAOException ( $e->getMessage (), $e->getCode (), $e->getPrevious () );
282
		}
283 64
	}
284
285
	/**
286
	 * Establishes the connection to the database using the $config array
287
	 *
288
	 * @param array $config the config array (Startup::getConfig())
289
	 */
290 20
	public static function startDatabase(&$config, $offset = null) {
291 20
		$db = $offset ? ($config ['database'] [$offset] ?? ($config ['database'] ?? [ ])) : ($config ['database'] ['default'] ?? $config ['database']);
292 20
		if ($db ['dbName'] !== '') {
293 20
			self::connect ( $offset ?? 'default', $db ['wrapper'] ?? \Ubiquity\db\providers\pdo\PDOWrapper::class, $db ['type'], $db ['dbName'], $db ['serverName'] ?? '127.0.0.1', $db ['port'] ?? 3306, $db ['user'] ?? 'root', $db ['password'] ?? '', $db ['options'] ?? [ ], $db ['cache'] ?? false);
294
		}
295 20
	}
296
297 110
	public static function getDbOffset(&$config, $offset = null) {
298 110
		return $offset ? ($config ['database'] [$offset] ?? ($config ['database'] ?? [ ])) : ($config ['database'] ['default'] ?? $config ['database']);
299
	}
300
301
	/**
302
	 * Returns true if the connection to the database is established
303
	 *
304
	 * @return boolean
305
	 */
306 5
	public static function isConnected($offset = 'default') {
307 5
		$db = self::$db [$offset] ?? false;
308 5
		return $db && ($db instanceof Database) && $db->isConnected ();
309
	}
310
311
	/**
312
	 * Sets the transformer operation
313
	 *
314
	 * @param string $op
315
	 */
316
	public static function setTransformerOp($op) {
317
		self::$transformerOp = $op;
318
	}
319
320
	/**
321
	 * Closes the active pdo connection to the database
322
	 */
323 23
	public static function closeDb($offset = 'default') {
324 23
		$db = self::$db [$offset] ?? false;
325 23
		if ($db !== false) {
326 23
			$db->close ();
327
		}
328 23
	}
329
330
	/**
331
	 * Defines the database connection to use for $model class
332
	 *
333
	 * @param string $model a model class
334
	 * @param string $database a database connection defined in config.php
335
	 */
336
	public static function setModelDatabase($model, $database = 'default') {
337
		self::$modelsDatabase [$model] = $database;
338
	}
339
340
	/**
341
	 * Defines the database connections to use for models classes
342
	 *
343
	 * @param array $modelsDatabase
344
	 */
345
	public static function setModelsDatabases($modelsDatabase) {
346
		self::$modelsDatabase = $modelsDatabase;
347
	}
348
349
	/**
350
	 * Returns the database instance defined at $offset key in config
351
	 *
352
	 * @param string $offset
353
	 * @return \Ubiquity\db\Database
354
	 */
355 66
	public static function getDatabase($offset = 'default') {
356 66
		if (! isset ( self::$db [$offset] )) {
357 19
			self::startDatabase ( Startup::$config, $offset );
358
		}
359 66
		SqlUtils::$quote = self::$db [$offset]->quote;
360 66
		return self::$db [$offset];
361
	}
362
363 4
	public static function getDatabases() {
364 4
		$config = Startup::getConfig ();
365 4
		if (isset ( $config ['database'] )) {
366 4
			if (isset ( $config ['database'] ['dbName'] )) {
367 4
				return [ 'default' ];
368
			} else {
369
				return \array_keys ( $config ['database'] );
370
			}
371
		}
372
		return [ ];
373
	}
374
375
	public static function updateDatabaseParams(array &$config, array $parameters, $offset = 'default') {
376
		if ($offset === 'default') {
377
			if (isset ( $config ['database'] [$offset] )) {
378
				foreach ( $parameters as $k => $param ) {
379
					$config ['database'] [$offset] [$k] = $param;
380
				}
381
			} else {
382
				foreach ( $parameters as $k => $param ) {
383
					$config ['database'] [$k] = $param;
384
				}
385
			}
386
		} else {
387
			if (isset ( $config ['database'] [$offset] )) {
388
				foreach ( $parameters as $k => $param ) {
389
					$config ['database'] [$offset] [$k] = $param;
390
				}
391
			}
392
		}
393
	}
394
395 38
	public static function start() {
396 38
		self::$modelsDatabase = CacheManager::getModelsDatabases ();
397 38
	}
398
}
399