Test Failed
Push — master ( 28ea53...a47f4f )
by Jean-Christophe
23:07 queued 18s
created

DAO::orderBy()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 1
c 0
b 0
f 0
dl 0
loc 2
ccs 1
cts 1
cp 1
rs 10
cc 1
nc 1
nop 7
crap 1
1
<?php
2
3
namespace Ubiquity\orm;
4
5
use Ubiquity\db\Database;
6
use Ubiquity\log\Logger;
7
use Ubiquity\db\SqlUtils;
8
use Ubiquity\orm\traits\DAOUpdatesTrait;
9
use Ubiquity\orm\traits\DAORelationsTrait;
10
use Ubiquity\orm\parser\ConditionParser;
11
use Ubiquity\orm\traits\DAOUQueries;
12
use Ubiquity\orm\traits\DAOCoreTrait;
13
use Ubiquity\orm\traits\DAORelationsPrepareTrait;
14
use Ubiquity\exceptions\DAOException;
15
use Ubiquity\orm\traits\DAORelationsAssignmentsTrait;
16
use Ubiquity\orm\traits\DAOTransactionsTrait;
17
use Ubiquity\controllers\Startup;
18
use Ubiquity\cache\CacheManager;
19
use Ubiquity\orm\traits\DAOPooling;
20
use Ubiquity\orm\traits\DAOBulkUpdatesTrait;
21
use Ubiquity\orm\traits\DAOPreparedTrait;
22
use Ubiquity\cache\dao\AbstractDAOCache;
23
24
/**
25
 * Gateway class between database and object model.
26
 * This class is part of Ubiquity
27
 *
28
 * @author jcheron <[email protected]>
29
 * @version 1.2.7
30
 *
31
 */
32
class DAO {
33
	use DAOCoreTrait,DAOUpdatesTrait,DAORelationsTrait,DAORelationsPrepareTrait,DAORelationsAssignmentsTrait,
34
	DAOUQueries,DAOTransactionsTrait,DAOPooling,DAOBulkUpdatesTrait,DAOPreparedTrait;
35
36
	/**
37
	 *
38
	 * @var Database
39
	 */
40
	public static $db;
41
	public static $useTransformers = false;
42
	public static $transformerOp = 'transform';
43
	private static $conditionParsers = [ ];
44
	protected static $modelsDatabase = [ ];
45
46
	/**
47
	 *
48
	 * @var AbstractDAOCache
49
	 */
50
	protected static $cache;
51
52 155
	public static function getDb($model) {
53 155
		return self::getDatabase ( self::$modelsDatabase [$model] ?? 'default');
54
	}
55
56
	/**
57
	 * Returns an array of $className objects from the database
58
	 *
59
	 * @param string $className class name of the model to load
60
	 * @param string $condition Part following the WHERE of an SQL statement
61
	 * @param boolean|array $included if true, loads associate members with associations, if array, example : ['client.*','commands']
62
	 * @param array|null $parameters
63
	 * @param boolean $useCache use the active cache if true
64
	 * @return array
65
	 */
66 57
	public static function getAll($className, $condition = '', $included = true, $parameters = null, $useCache = NULL) {
67 57
		$db = self::getDb ( $className );
68 57
		return static::_getAll ( $db, $className, new ConditionParser ( $condition, null, $parameters ), $included, $useCache );
69
	}
70
71
	/**
72
	 * Returns an array of $className objects loaded by id from the database
73
	 *
74
	 * @param string $className class name of the model to load
75
	 * @param array $keyValues
76
	 * @param boolean|array $included if true, loads associate members with associations, if array, example : ['client.*','commands']
77
	 * @param string $condition additional condition
78
	 * @param boolean $useCache use the active cache if true
79
	 * @return array
80
	 */
81 1
	public static function getAllByIds($className, $keyValues = [ ], $included = true, $condition = '', $useCache = NULL): array {
82 1
		$db = self::getDb ( $className );
83 1
		$key = OrmUtils::getFirstKey ( $className );
84 1
		$countK = \count ( $keyValues );
85 1
		if ($countK > 0) {
86 1
			$nCondition = $key . ' IN (' . \str_repeat ( '?,', $countK - 1 ) . '?)';
87 1
			if ($condition != null) {
88
				$nCondition .= ' AND ' . $condition;
89
			}
90 1
			return static::_getAll ( $db, $className, new ConditionParser ( $nCondition, null, $keyValues ), $included, $useCache );
91
		}
92
		return [];
93
		
94
	}
95
96 6
	public static function paginate($className, $page = 1, $rowsPerPage = 20, $condition = null, $included = true) {
97 6
		return self::getAll ( $className, ($condition ?? '1=1') . ' LIMIT ' . $rowsPerPage . ' OFFSET ' . (($page - 1) * $rowsPerPage), $included );
98
	}
99
100 5
    /**
101 5
     * Returns an array of $className objects from the database ordered by $field
102 5
     *
103 5
     * @param string $className class name of the model to load
104 5
     * @param string $field field to order by
105 5
     * @param string $order order of the sort (ASC or DESC)
106 5
     * @param string $condition Part following the WHERE of an SQL statement
107 5
     * @param boolean $included if true, loads associate members with associations
108 5
     * @param null $parameters parameters to bind
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $parameters is correct as it would always require null to be passed?
Loading history...
109
     * @param null $useCache use the active cache if true
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $useCache is correct as it would always require null to be passed?
Loading history...
110
     * @return array
111
     */
112 5
    public static function orderBy(string $className, string $field, string $order = 'ASC', string $condition = '', bool $included = true, $parameters = null, $useCache = NULL): array {
113
        return self::getAll ( $className, ($condition ?? '1=1') . ' ORDER BY ' . $field . ' ' . $order, $included, $parameters, $useCache );
114
    }
115
116
	public static function getRownum($className, $ids) {
117
		$tableName = OrmUtils::getTableName ( $className );
118
		$db = self::getDb ( $className );
119
		$quote = $db->quote;
120
		self::parseKey ( $ids, $className, $quote );
121
		$condition = SqlUtils::getCondition ( $ids, $className );
122
		$keyFields = OrmUtils::getKeyFields ( $className );
123 31
		if (\is_array ( $keyFields )) {
124 31
			$keys = \implode ( ',', $keyFields );
125 31
		} else {
126 10
			$keys = '1';
127
		}
128 31
		return $db->getRowNum ( $tableName, $keys, $condition );
129 31
	}
130 31
131
	/**
132
	 * Returns the number of objects of $className from the database respecting the condition possibly passed as parameter
133
	 *
134
	 * @param string $className complete classname of the model to load
135
	 * @param string $condition Part following the WHERE of an SQL statement
136
	 * @param array|null $parameters The query parameters
137
	 * @return int|false count of objects
138
	 */
139
	public static function count($className, $condition = '', $parameters = null) {
140
		$tableName = OrmUtils::getTableName ( $className );
141 2
		if ($condition != '') {
142 2
			$condition = SqlUtils::checkWhere($condition);
143 2
		}
144 2
		$db = self::getDb ( $className );
145
		$quote = $db->quote;
146 2
		return $db->prepareAndFetchColumn ( 'SELECT COUNT(*) FROM ' . $quote . $tableName . $quote . $condition, $parameters );
147 2
	}
148 2
149
	/**
150
	 * Tests the existence of objects of $className from the database respecting the condition possibly passed as parameter
151
	 *
152
	 * @param string $className complete classname of the model to load
153
	 * @param string $condition Part following the WHERE of an SQL statement
154
	 * @param array|null $parameters The query parameters
155
	 * @return boolean
156
	 */
157
	public static function exists($className, $condition = '', $parameters = null): bool {
158
		$tableName = OrmUtils::getTableName ( $className );
159
		if ($condition != '') {
160
			$condition = SqlUtils::checkWhere($condition);
161 30
		}
162 30
		$db = self::getDb ( $className );
163 30
		$quote = $db->quote;
164 30
		return (1 == $db->prepareAndFetchColumn ( "SELECT EXISTS(SELECT 1 FROM {$quote}{$tableName}{$quote}{$condition})", $parameters ));
165 27
	}
166 5
167 5
    /**
168 5
     * Returns an instance of $className from the database, from $keyvalues values of the primary key or with a condition
169
     *
170
     * @param String $className complete classname of the model to load
171
     * @param array|string $condition condition or primary key values
172 30
     * @param boolean|array $included if true, charges associate members with association
173
     * @param array|null $parameters the request parameters
174
     * @param boolean|null $useCache use cache if true
175
     * @return object the instance loaded or null if not found
176
     * @throws DAOException
177
     */
178
	public static function getOne($className, $condition, $included = true, $parameters = null, $useCache = NULL) {
179
		$db = self::getDb ( $className );
180
		$conditionParser = new ConditionParser ();
181
		if (! isset ( $parameters )) {
182
			$conditionParser->addKeyValues ( $condition, $className );
183
		} elseif (! is_array ( $condition )) {
184 44
			$conditionParser->setCondition ( $condition );
185 44
			$conditionParser->setParams ( $parameters );
186
		} else {
187
			throw new DAOException ( "The \$condition parameter should not be an array if \$parameters is not null" );
188 44
		}
189 44
		return static::_getOne ( $db, $className, $conditionParser, $included, $useCache );
190 16
	}
191 16
192 16
	/**
193
	 * Returns an instance of $className from the database, from $keyvalues values of the primary key
194 31
	 *
195
	 * @param String $className complete classname of the model to load
196 44
	 * @param array|string $keyValues primary key values or condition
197
	 * @param boolean|array $included if true, charges associate members with association
198
	 * @param boolean|null $useCache use cache if true
199
	 * @return object the instance loaded or null if not found
200
	 */
201
	public static function getById($className, $keyValues, $included = true, $useCache = NULL) {
202
		return static::_getOne ( self::getDatabase ( self::$modelsDatabase [$className] ?? 'default'), $className, self::getConditionParser ( $className, $keyValues ), $included, $useCache );
203
	}
204
205
	protected static function getConditionParser($className, $keyValues): ConditionParser {
206
		if (! isset ( self::$conditionParsers [$className] )) {
207
			$conditionParser = new ConditionParser ();
208
			$conditionParser->addKeyValues ( $keyValues, $className );
209
			self::$conditionParsers [$className] = $conditionParser;
210
		} else {
211
			self::$conditionParsers [$className]->setKeyValues ( $keyValues );
212
		}
213 157
		return self::$conditionParsers [$className];
214 157
	}
215
216 157
    /**
217
     * Establishes the connection to the database using the past parameters
218
     *
219
     * @param string $offset
220
     * @param string $wrapper
221
     * @param string $dbType
222
     * @param string $dbName
223
     * @param string $serverName
224
     * @param string $port
225
     * @param string $user
226
     * @param string $password
227
     * @param array $options
228 31
     * @param boolean $cache
229 31
     * @throws DAOException|\Ubiquity\exceptions\CacheException
230 31
     */
231 31
	public static function connect($offset, $wrapper, $dbType, $dbName, $serverName = '127.0.0.1', $port = '3306', $user = 'root', $password = '', $options = [ ], $cache = false) {
232
		self::$db [$offset] = new Database ( $wrapper, $dbType, $dbName, $serverName, $port, $user, $password, $options, $cache, self::$pool );
233
		try {
234
			self::$db [$offset]->connect ();
235 225
		} catch ( \Exception $e ) {
236 225
			Logger::error ( "DAO", $e->getMessage () );
237
			throw new DAOException ( $e->getMessage (), $e->getCode (), $e->getPrevious () );
238
		}
239
	}
240
241
	/**
242
	 * Establishes the connection to the database using the $config array
243
	 *
244 8
	 * @param array $config the config array (Startup::getConfig())
245 8
	 */
246 8
	public static function startDatabase(&$config, $offset = null) {
247
		$db = $offset ? ($config ['database'] [$offset] ?? ($config ['database'] ?? [ ])) : ($config ['database'] ['default'] ?? $config ['database']);
248
		if ($db ['dbName'] !== '') {
249
			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);
250
		}
251
	}
252
253
	public static function getDbOffset(&$config, $offset = null) {
254
		return $offset ? ($config ['database'] [$offset] ?? ($config ['database'] ?? [ ])) : ($config ['database'] ['default'] ?? $config ['database']);
255
	}
256
257
	/**
258
	 * Returns true if the connection to the database is established
259
	 *
260
	 * @return boolean
261 104
	 */
262 104
	public static function isConnected($offset = 'default'): bool {
263 104
		$db = self::$db [$offset] ?? false;
264 103
		return ($db instanceof Database) && $db->isConnected ();
265
	}
266
267
	/**
268
	 * Sets the transformer operation
269
	 *
270
	 * @param string $op
271
	 */
272
	public static function setTransformerOp(string $op) {
273
		self::$transformerOp = $op;
274 10
	}
275 10
276
	/**
277
	 * Closes the active pdo connection to the database
278
	 */
279
	public static function closeDb($offset = 'default') {
280
		$db = self::$db [$offset] ?? false;
281
		if ($db !== false) {
282
			$db->close ();
283
		}
284
	}
285
286
	/**
287
	 * Defines the database connection to use for $model class
288
	 *
289
	 * @param string $model a model class
290
	 * @param string $database a database connection defined in config.php
291
	 */
292
	public static function setModelDatabase($model, $database = 'default') {
293 161
		self::$modelsDatabase [$model] = $database;
294 161
	}
295 23
296
	/**
297 161
	 * Defines the database connections to use for models classes
298 161
	 *
299
	 * @param array $modelsDatabase
300
	 */
301 6
	public static function setModelsDatabases($modelsDatabase) {
302 6
		self::$modelsDatabase = $modelsDatabase;
303 6
	}
304 6
305
	/**
306
	 * Returns the database instance defined at $offset key in config
307 6
	 *
308
	 * @param string $offset
309
	 * @return \Ubiquity\db\Database
310
	 */
311
	public static function getDatabase($offset = 'default') {
312
		if (! isset ( self::$db [$offset] )) {
313 1
			self::startDatabase ( Startup::$config, $offset );
314 1
		}
315 1
		SqlUtils::$quote = self::$db [$offset]->quote??'';
316
		return self::$db [$offset]??null;
317
	}
318
319
	public static function getDatabases(): array {
320 1
		$config = Startup::getConfig ();
321 1
		if (isset ( $config ['database'] )) {
322
			if (isset ( $config ['database'] ['dbName'] )) {
323
				return [ 'default' ];
324
			} else {
325
				return \array_keys ( $config ['database'] );
326
			}
327
		}
328
		return [ ];
329
	}
330
331
	public static function updateDatabaseParams(array &$config, array $parameters, $offset = 'default') {
332
		if ($offset === 'default') {
333 77
			if (isset ( $config ['database'] [$offset] )) {
334 77
				foreach ( $parameters as $k => $param ) {
335
					$config ['database'] [$offset] [$k] = $param;
336
				}
337
			} else {
338
				foreach ( $parameters as $k => $param ) {
339
					$config ['database'] [$k] = $param;
340
				}
341
			}
342 2
		} else {
343 2
			if (isset ( $config ['database'] [$offset] )) {
344 2
				foreach ( $parameters as $k => $param ) {
345 2
					$config ['database'] [$offset] [$k] = $param;
346
				}
347 2
			}
348 2
		}
349 2
	}
350 2
351 2
	public static function start() {
352
		self::$modelsDatabase = CacheManager::getModelsDatabases ();
353
	}
354 2
355 2
	public static function getDbCacheInstance($model) {
356
		$db = static::$db [self::$modelsDatabase [$model] ?? 'default'];
357
		return $db->getCacheInstance ();
358
	}
359
360
	public static function warmupCache($className, $condition = '', $included = false, $parameters = [ ]) {
361
		$objects = self::getAll ( $className, $condition, $included, $parameters );
362 66
		foreach ( $objects as $o ) {
363 66
			self::$cache->store ( $className, OrmUtils::getKeyValues ( $o ), $o );
364
		}
365
		self::$cache->optimize ();
366
		$offset = self::$modelsDatabase [$className] ?? 'default';
367
		$db = self::$db [$offset];
368
		$db->close ();
369
		unset ( self::$db [$offset] );
370
	}
371
372
	public static function setCache(AbstractDAOCache $cache) {
373
		self::$cache = $cache;
374
	}
375
376
	/**
377
	 *
378
	 * @return \Ubiquity\cache\dao\AbstractDAOCache
379
	 */
380
	public static function getCache() {
381
		return static::$cache;
382
	}
383
384
	/**
385
	 * @return array
386
	 */
387
	public static function getModelsDatabase(): array {
388
		return self::$modelsDatabase;
389
	}
390
}
391