Completed
Push — master ( da58d4...61a0f7 )
by Henry
06:34
created

includes/Db.php (1 issue)

Check for loose comparison of strings.

Best Practice Bug Major

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
namespace Redaxscript;
3
4
use ORM;
5
use PDO;
6
use PDOException;
7
use function array_column;
8
use function implode;
9
use function strstr;
10
11
/**
12
 * children class to handle the database
13
 *
14
 * @since 2.2.0
15
 *
16
 * @package Redaxscript
17
 * @category Db
18
 * @author Henry Ruhs
19
 *
20
 * @method $this _addJoinSource(string $operator, string $table, string|array $constraint, string $tableAlias)
21
 * @method $this _addOrderBy(string $column, string $value)
22
 * @method $this _addWhere(string $clause, string|array $value)
23
 */
24
25
class Db extends ORM
26
{
27
	/**
28
	 * instance of the config class
29
	 *
30
	 * @var Config
31
	 */
32
33
	protected static $_config;
34
35
	/**
36
	 * constructor of the class
37
	 *
38
	 * @since 2.6.0
39
	 *
40
	 * @param Config $config instance of the config class
41
	 */
42 4
43
	public static function construct(Config $config) : void
44 4
	{
45 4
		self::$_config = $config;
46
	}
47
48
	/**
49
	 * init the class
50
	 *
51
	 * @since 3.1.0
52
	 */
53 4
54
	public static function init() : void
55 4
	{
56 4
		$dbType = self::$_config->get('dbType');
57 4
		$dbHost = self::$_config->get('dbHost');
58 4
		$dbName = self::$_config->get('dbName');
59 4
		$dbUser = self::$_config->get('dbUser');
60 4
		$dbPassword = self::$_config->get('dbPassword');
61
		$dbSocket = strstr($dbHost, '.sock');
62
63
		/* handle various types */
64 4
65
		if ($dbType === 'mssql' || $dbType === 'mysql' || $dbType === 'pgsql')
66 3
		{
67
			if ($dbType === 'mssql')
68 1
			{
69
				self::configure('connection_string', 'sqlsrv:server=' . $dbHost . ';database=' . $dbName);
70 3
			}
71
			if ($dbType === 'mysql')
72 1
			{
73
				self::configure('connection_string', 'mysql:' . ($dbSocket ? 'unix_socket' : 'host') . '=' . $dbHost . ';dbname=' . $dbName . ';charset=utf8');
74 3
			}
75
			if ($dbType === 'pgsql')
76 1
			{
77
				self::configure('connection_string', 'pgsql:' . ($dbSocket ? 'unix_socket' : 'host') . '=' . $dbHost . ';dbname=' . $dbName . ';options=--client_encoding=utf8');
78
			}
79
80
			/* username and password */
81 3
82 3
			self::configure('username', $dbUser);
83
			if ($dbPassword)
0 ignored issues
show
Bug Best Practice introduced by
The expression $dbPassword of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
84 3
			{
85
				self::configure('password', $dbPassword);
86
			}
87
		}
88
89
		/* else handle sqlite */
90 4
91
		if ($dbType === 'sqlite')
92 1
		{
93
			self::configure('sqlite:' . $dbHost);
94
		}
95
96
		/* general */
97 4
98
		self::configure(
99 4
		[
100
			'caching' => true,
101
			'caching_auto_clear' => true,
102
			'return_result_sets' => true
103 4
		]);
104
	}
105
106
	/**
107
	 * get the database status
108
	 *
109
	 * @since 3.1.0
110
	 *
111
	 * @return int
112
	 */
113 1
114
	public static function getStatus() : int
115 1
	{
116
		$output = 0;
117
118
		/* has connection */
119
120
		try
121 1
		{
122 1
			$dbType = self::$_config->get('dbType') === 'mssql' ? 'sqlsrv' : self::$_config->get('dbType');
123 1
			$dbDriver = self::getDb()->getAttribute(PDO::ATTR_DRIVER_NAME);
124
			if ($dbType === $dbDriver)
125 1
			{
126
				$output = self::countTablePrefix() > 7 ? 2 : 1;
127
			}
128
		}
129
		catch (PDOException $exception)
130
		{
131
			$output = 0;
132 1
		}
133
		return $output;
134
	}
135
136
	/**
137
	 * set the auto increment
138
	 *
139
	 * @since 4.0.0
140
	 *
141
	 * @param string $table name of the table
142
	 * @param int $increment value of the auto increment
143
	 *
144
	 * @return bool
145
	 */
146
147
	public static function setAutoIncrement(string $table = null, int $increment = 0) : bool
148
	{
149
		$dbType = self::$_config->get('dbType');
150
		$dbPrefix = self::$_config->get('dbPrefix');
151
152
		/* mysql */
153
154
		if ($dbType === 'mysql')
155
		{
156
			return self::rawExecute('ALTER TABLE ' . $dbPrefix . $table . ' AUTO_INCREMENT = ' . $increment);
157
		}
158
		return false;
159
	}
160
161
	/**
162
	 * count table with prefix
163
	 *
164
	 * @since 3.1.0
165
	 *
166
	 * @return int
167
	 */
168 2
169
	public static function countTablePrefix() : int
170 2
	{
171 2
		$output = 0;
172 2
		$dbType = self::$_config->get('dbType');
173 2
		$dbName = self::$_config->get('dbName');
174
		$dbPrefix = self::$_config->get('dbPrefix');
175
176
		/* mssql and mysql */
177 2
178
		if ($dbType === 'mssql' || $dbType === 'mysql')
179
		{
180
			$output = self::forTable('information_schema.tables')
181
				->where($dbType === 'mssql' ? 'table_catalog' : 'table_schema', $dbName)
182
				->whereLike('table_name', $dbPrefix . '%')
183
				->count();
184
		}
185
186
		/* pgsql */
187 2
188
		if ($dbType === 'pgsql')
189
		{
190
			$output = self::forTable('pg_catalog.pg_tables')
191
				->whereLike('tablename', $dbPrefix . '%')
192
				->whereNotLike('tablename', 'pg_%')
193
				->whereNotLike('tablename', 'sql_%')
194
				->count();
195
		}
196
197
		/* sqlite */
198 2
199
		if ($dbType === 'sqlite')
200 2
		{
201 2
			$output = self::forTable('sqlite_master')
202 2
				->whereLike('tbl_name', $dbPrefix . '%')
203 2
				->whereNotLike('tbl_name', 'sql_%')
204
				->count();
205 2
		}
206
		return $output;
207
	}
208
209
	/**
210
	 * for table with prefix
211
	 *
212
	 * @since 2.2.0
213
	 *
214
	 * @param string $table name of the table
215
	 * @param string $connection which connection to use
216
	 *
217
	 * @return self
218
	 */
219 14
220
	public static function forTablePrefix(string $table = null, string $connection = self::DEFAULT_CONNECTION) : self
221 14
	{
222
		return new self(self::$_config->get('dbPrefix') . $table, [], $connection);
223
	}
224
225
	/**
226
	 * left join with prefix
227
	 *
228
	 * @since 2.2.0
229
	 *
230
	 * @param string $table name of the table
231
	 * @param string|array $constraint constraint as needed
232
	 * @param string $tableAlias alias of the table
233
	 *
234
	 * @return self
235
	 */
236 1
237
	public function leftJoinPrefix(string $table = null, string $constraint = null, string $tableAlias = null) : self
238 1
	{
239
		return $this->_addJoinSource('LEFT', self::$_config->get('dbPrefix') . $table, $constraint, $tableAlias);
240
	}
241
242
	/**
243
	 * where like with many
244
	 *
245
	 * @since 3.0.0
246
	 *
247
	 * @param array $columnArray array of column names
248
	 * @param array $likeArray array of the like
249
	 *
250
	 * @return self
251
	 */
252 1
253
	public function whereLikeMany(array $columnArray = [], array $likeArray = []) : self
254 1
	{
255
		return $this->_addWhere('(' . implode($columnArray, ' LIKE ? OR ') . ' LIKE ?)', $likeArray);
256
	}
257
258
	/**
259
	 * where language is
260
	 *
261
	 * @since 3.0.0
262
	 *
263
	 * @param string $language value of the language
264
	 *
265
	 * @return self
266
	 */
267 3
268
	public function whereLanguageIs(string $language = null) : self
269 3
	{
270
		return $this->_addWhere('(language = ? OR language IS NULL)', $language);
271
	}
272
273
	/**
274
	 * find the flat array
275
	 *
276
	 * @since 4.0.0
277
	 *
278
	 * @param string $column name of the column
279
	 *
280
	 * @return array
281
	 */
282 1
283
	public function findFlatArray(string $column = 'id') : array
284 1
	{
285 1
		return array_column($this->findArray(), $column);
286
	}
287
288
	/**
289
	 * order by global setting
290
	 *
291
	 * @since 3.3.0
292
	 *
293
	 * @param string $column name of the column
294
	 *
295
	 * @return self
296
	 */
297
298 1
	public function orderBySetting(string $column = null) : self
299
	{
300 1
		$order = $this->getSetting('order');
301 1
		return $this->_addOrderBy($column, $order);
302 1
	}
303
304
	/**
305
	 * limit by global setting
306
	 *
307
	 * @since 3.3.0
308
	 *
309
	 * @param int $step step of the offset
310
	 *
311
	 * @return self
312
	 */
313
314
	public function limitBySetting(int $step = null) : self
315 2
	{
316
		$limit = $this->getSetting('limit');
317 2
		$this->_limit = $step > 0 ? $step * $limit . ',' . $limit : $limit;
318
		return $this;
319
	}
320
321 2
	/**
322
	 * get the value from settings
323 2
	 *
324
	 * @since 4.0.0
325 2
	 *
326
	 * @param string $key key of the item
327 2
	 *
328
	 * @return string|null
329
	 */
330
331
	public function getSetting(string $key = null) : ?string
332
	{
333
		$settings = self::forTablePrefix('settings')->findMany();
334
335
		/* process settings */
336
337
		if ($key)
338
		{
339
			foreach ($settings as $setting)
340
			{
341
				if ($setting->name === $key)
342
				{
343
					return $setting->value;
344
				}
345
			}
346
		}
347
		return null;
348
	}
349
}
350