Passed
Branch develop (8c22de)
by
unknown
43:25
created

DoliDB   B

Complexity

Total Complexity 43

Size/Duplication

Total Lines 352
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 121
c 2
b 0
f 0
dl 0
loc 352
rs 8.96
wmc 43

17 Methods

Rating   Name   Duplication   Size   Complexity  
A ifsql() 0 4 1
A lasterror() 0 3 1
A getVersionArray() 0 3 1
B order() 0 35 8
A begin() 0 14 3
A lastquery() 0 3 1
A lastqueryerror() 0 3 1
A plimit() 0 13 4
A idate() 0 4 1
A getRow() 0 15 3
A rollback() 0 11 3
A sanitize() 0 6 2
A lasterrno() 0 3 1
A jdate() 0 10 3
A prefix() 0 3 2
A getRows() 0 14 4
A commit() 0 15 4

How to fix   Complexity   

Complex Class

Complex classes like DoliDB often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use DoliDB, and based on these observations, apply Extract Interface, too.

1
<?php
2
/*
3
 * Copyright (C) 2013-2015 Raphaël Doursenaud <[email protected]>
4
 * Copyright (C) 2014-2015 Laurent Destailleur <[email protected]>
5
 *
6
 * This program is free software; you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation; either version 3 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18
 */
19
20
/**
21
 * \file 		htdocs/core/db/DoliDB.class.php
22
 * \brief 		Class file to manage Dolibarr database access
23
 */
24
25
require_once DOL_DOCUMENT_ROOT.'/core/db/Database.interface.php';
26
27
/**
28
 * Class to manage Dolibarr database access
29
 */
30
abstract class DoliDB implements Database
31
{
32
	/** @var bool|resource|SQLite3 Database handler */
33
	public $db;
34
	/** @var string Database type */
35
	public $type;
36
	/** @var string Charset used to force charset when creating database */
37
	public $forcecharset = 'utf8';
38
	/** @var string Collate used to force collate when creating database */
39
	public $forcecollate = 'utf8_unicode_ci';
40
	/** @var resource Resultset of last query */
41
	private $_results;
42
	/** @var bool true if connected, else false */
43
	public $connected;
44
	/** @var bool true if database selected, else false */
45
	public $database_selected;
46
	/** @var string Selected database name */
47
	public $database_name;
48
	/** @var string Database username */
49
	public $database_user;
50
	/** @var string Database host */
51
	public $database_host;
52
	/** @var int Database port */
53
	public $database_port;
54
	/** @var int >=1 if a transaction is opened, 0 otherwise */
55
	public $transaction_opened;
56
	/** @var string Last successful query */
57
	public $lastquery;
58
	/** @var string Last failed query */
59
	public $lastqueryerror;
60
	/** @var string Last error message */
61
	public $lasterror;
62
	/** @var string Last error number. For example: 'DB_ERROR_RECORD_ALREADY_EXISTS', '12345', ... */
63
	public $lasterrno;
64
65
	/** @var string If we need to set a prefix specific to the database so it can be reused (when defined instead of MAIN_DB_PREFIX) to forge requests */
66
	public $prefix_db;
67
68
	/** @var bool Status */
69
	public $ok;
70
	/** @var string */
71
	public $error;
72
73
74
75
	/**
76
	 *	Return the DB prefix
77
	 *
78
	 *	@return string		The DB prefix
79
	 */
80
	public function prefix()
81
	{
82
		return (empty($this->prefix_db) ? MAIN_DB_PREFIX : $this->prefix_db);
83
	}
84
85
	/**
86
	 *	Format a SQL IF
87
	 *
88
	 *	@param	string	$test           Test string (example: 'cd.statut=0', 'field IS NULL')
89
	 *	@param	string	$resok          resultat si test egal
90
	 *	@param	string	$resko          resultat si test non egal
91
	 *	@return	string          		SQL string
92
	 */
93
	public function ifsql($test, $resok, $resko)
94
	{
95
		//return 'IF('.$test.','.$resok.','.$resko.')';		// Not sql standard
96
		return '(CASE WHEN '.$test.' THEN '.$resok.' ELSE '.$resko.' END)';
97
	}
98
99
	/**
100
	 *   Convert (by PHP) a GM Timestamp date into a string date with PHP server TZ to insert into a date field.
101
	 *   Function to use to build INSERT, UPDATE or WHERE predica
102
	 *
103
	 *   @param	    int		$param      Date TMS to convert
104
	 *	 @param		mixed	$gm			'gmt'=Input informations are GMT values, 'tzserver'=Local to server TZ
105
	 *   @return	string      		Date in a string YYYY-MM-DD HH:MM:SS
106
	 */
107
	public function idate($param, $gm = 'tzserver')
108
	{
109
		// TODO $param should be gmt, so we should add $gm to 'gmt' instead of default 'tzserver'
110
		return dol_print_date($param, "%Y-%m-%d %H:%M:%S", $gm);
111
	}
112
113
	/**
114
	 *	Return last error code
115
	 *
116
	 *	@return	    string	lasterrno
117
	 */
118
	public function lasterrno()
119
	{
120
		return $this->lasterrno;
121
	}
122
123
	/**
124
	 * Sanitize a string for SQL forging
125
	 *
126
	 * @param   string 	$stringtosanitize 	String to escape
127
	 * @param   int		$allowsimplequote 	1=Allow simple quotes in string. When string is used as a list of SQL string ('aa', 'bb', ...)
128
	 * @return  string                      String escaped
129
	 */
130
	public function sanitize($stringtosanitize, $allowsimplequote = 0)
131
	{
132
		if ($allowsimplequote) {
133
			return preg_replace('/[^a-z0-9_\-\.,\']/i', '', $stringtosanitize);
134
		} else {
135
			return preg_replace('/[^a-z0-9_\-\.,]/i', '', $stringtosanitize);
136
		}
137
	}
138
139
	/**
140
	 * Start transaction
141
	 *
142
	 * @return	    int         1 if transaction successfuly opened or already opened, 0 if error
143
	 */
144
	public function begin()
145
	{
146
		if (!$this->transaction_opened) {
147
			$ret = $this->query("BEGIN");
148
			if ($ret) {
149
				$this->transaction_opened++;
150
				dol_syslog("BEGIN Transaction", LOG_DEBUG);
151
				dol_syslog('', 0, 1);
152
			}
153
			return $ret;
154
		} else {
155
			$this->transaction_opened++;
156
			dol_syslog('', 0, 1);
157
			return 1;
158
		}
159
	}
160
161
	/**
162
	 * Validate a database transaction
163
	 *
164
	 * @param	string	$log		Add more log to default log line
165
	 * @return	int         		1 if validation is OK or transaction level no started, 0 if ERROR
166
	 */
167
	public function commit($log = '')
168
	{
169
		dol_syslog('', 0, -1);
170
		if ($this->transaction_opened <= 1) {
171
			$ret = $this->query("COMMIT");
172
			if ($ret) {
173
				$this->transaction_opened = 0;
174
				dol_syslog("COMMIT Transaction".($log ? ' '.$log : ''), LOG_DEBUG);
175
				return 1;
176
			} else {
177
				return 0;
178
			}
179
		} else {
180
			$this->transaction_opened--;
181
			return 1;
182
		}
183
	}
184
185
	/**
186
	 *	Cancel a transaction and go back to initial data values
187
	 *
188
	 * 	@param	string			$log		Add more log to default log line
189
	 * 	@return	resource|int         		1 if cancelation is ok or transaction not open, 0 if error
190
	 */
191
	public function rollback($log = '')
192
	{
193
		dol_syslog('', 0, -1);
194
		if ($this->transaction_opened <= 1) {
195
			$ret = $this->query("ROLLBACK");
196
			$this->transaction_opened = 0;
197
			dol_syslog("ROLLBACK Transaction".($log ? ' '.$log : ''), LOG_DEBUG);
198
			return $ret;
199
		} else {
200
			$this->transaction_opened--;
201
			return 1;
202
		}
203
	}
204
205
	/**
206
	 *	Define limits and offset of request
207
	 *
208
	 *	@param	int		$limit      Maximum number of lines returned (-1=conf->liste_limit, 0=no limit)
209
	 *	@param	int		$offset     Numero of line from where starting fetch
210
	 *	@return	string      		String with SQL syntax to add a limit and offset
211
	 */
212
	public function plimit($limit = 0, $offset = 0)
213
	{
214
		global $conf;
215
		if (empty($limit)) {
216
			return "";
217
		}
218
		if ($limit < 0) {
219
			$limit = $conf->liste_limit;
220
		}
221
		if ($offset > 0) {
222
			return " LIMIT ".((int) $offset).",".((int) $limit)." ";
223
		} else {
224
			return " LIMIT ".((int) $limit)." ";
225
		}
226
	}
227
228
	/**
229
	 *	Return version of database server into an array
230
	 *
231
	 *	@return	        array  		Version array
232
	 */
233
	public function getVersionArray()
234
	{
235
		return preg_split("/[\.,-]/", $this->getVersion());
236
	}
237
238
	/**
239
	 *	Return last request executed with query()
240
	 *
241
	 *	@return	string					Last query
242
	 */
243
	public function lastquery()
244
	{
245
		return $this->lastquery;
246
	}
247
248
	/**
249
	 * Define sort criteria of request
250
	 *
251
	 * @param	string		$sortfield		List of sort fields, separated by comma. Example: 't1.fielda,t2.fieldb'
252
	 * @param	string		$sortorder		Sort order, separated by comma. Example: 'ASC,DESC'. Note: If the quantity fo sortorder values is lower than sortfield, we used the last value for missing values.
253
	 * @return	string						String to provide syntax of a sort sql string
254
	 */
255
	public function order($sortfield = null, $sortorder = null)
256
	{
257
		if (!empty($sortfield)) {
258
			$oldsortorder = '';
259
			$return = '';
260
			$fields = explode(',', $sortfield);
261
			$orders = explode(',', $sortorder);
262
			$i = 0;
263
			foreach ($fields as $val) {
264
				if (!$return) {
265
					$return .= ' ORDER BY ';
266
				} else {
267
					$return .= ', ';
268
				}
269
270
				$return .= preg_replace('/[^0-9a-z_\.]/i', '', $val); // Add field
271
272
				$tmpsortorder = (empty($orders[$i]) ? '' : trim($orders[$i]));
273
274
				// Only ASC and DESC values are valid SQL
275
				if (strtoupper($tmpsortorder) === 'ASC') {
276
					$oldsortorder = 'ASC';
277
					$return .= ' ASC';
278
				} elseif (strtoupper($tmpsortorder) === 'DESC') {
279
					$oldsortorder = 'DESC';
280
					$return .= ' DESC';
281
				} else {
282
					$return .= ' '.($oldsortorder ? $oldsortorder : 'ASC');
283
				}
284
285
				$i++;
286
			}
287
			return $return;
288
		} else {
289
			return '';
290
		}
291
	}
292
293
	/**
294
	 *	Return last error label
295
	 *
296
	 *	@return	    string		Last error
297
	 */
298
	public function lasterror()
299
	{
300
		return $this->lasterror;
301
	}
302
303
	/**
304
	 *	Convert (by PHP) a PHP server TZ string date into a Timestamps date (GMT if gm=true)
305
	 * 	19700101020000 -> 3600 with TZ+1 and gmt=0
306
	 * 	19700101020000 -> 7200 whaterver is TZ if gmt=1
307
	 *
308
	 * 	@param	string				$string		Date in a string (YYYYMMDDHHMMSS, YYYYMMDD, YYYY-MM-DD HH:MM:SS)
309
	 *	@param	mixed				$gm			'gmt'=Input informations are GMT values, 'tzserver'=Local to server TZ
310
	 *	@return	int|string						Date TMS or ''
311
	 */
312
	public function jdate($string, $gm = 'tzserver')
313
	{
314
		// TODO $string should be converted into a GMT timestamp, so param gm should be set to true by default instead of false
315
		if ($string == 0 || $string == "0000-00-00 00:00:00") {
316
			return '';
317
		}
318
		$string = preg_replace('/([^0-9])/i', '', $string);
319
		$tmp = $string.'000000';
320
		$date = dol_mktime((int) substr($tmp, 8, 2), (int) substr($tmp, 10, 2), (int) substr($tmp, 12, 2), (int) substr($tmp, 4, 2), (int) substr($tmp, 6, 2), (int) substr($tmp, 0, 4), $gm);
321
		return $date;
322
	}
323
324
	/**
325
	 *	Return last query in error
326
	 *
327
	 *	@return	    string	lastqueryerror
328
	 */
329
	public function lastqueryerror()
330
	{
331
		return $this->lastqueryerror;
332
	}
333
334
	/**
335
	 * Return first result from query as object
336
	 * Note : This method executes a given SQL query and retrieves the first row of results as an object. It should only be used with SELECT queries
337
	 * Dont add LIMIT to your query, it will be added by this method
338
	 *
339
	 * @param 	string 				$sql 	The sql query string
340
	 * @return 	bool|int|object    			False on failure, 0 on empty, object on success
341
	 */
342
	public function getRow($sql)
343
	{
344
		$sql .= ' LIMIT 1';
345
346
		$res = $this->query($sql);
347
		if ($res) {
348
			$obj = $this->fetch_object($res);
349
			if ($obj) {
350
				return $obj;
351
			} else {
352
				return 0;
353
			}
354
		}
355
356
		return false;
357
	}
358
359
	/**
360
	 * Return all results from query as an array of objects
361
	 * Note : This method executes a given SQL query and retrieves all row of results as an array of objects. It should only be used with SELECT queries
362
	 * be carefull with this method use it only with some limit of results to avoid performences loss.
363
	 *
364
	 * @param 	string 		$sql 		The sql query string
365
	 * @return 	bool|array				Result
366
	 * @deprecated
367
	 */
368
	public function getRows($sql)
369
	{
370
		$res = $this->query($sql);
371
		if ($res) {
372
			$results = array();
373
			if ($this->num_rows($res) > 0) {
374
				while ($obj = $this->fetch_object($res)) {
375
					$results[] = $obj;
376
				}
377
			}
378
			return $results;
379
		}
380
381
		return false;
382
	}
383
}
384