Completed
Push — master ( 7960db...3360d7 )
by Fwolf
13:54
created

Adodb::FindColTs()   B

Complexity

Conditions 9
Paths 7

Size

Total Lines 54
Code Lines 31

Duplication

Lines 10
Ratio 18.52 %

Importance

Changes 0
Metric Value
cc 9
eloc 31
nc 7
nop 1
dl 10
loc 54
rs 7.255
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
// Set include path in __construct
3
//require_once('adodb/adodb.inc.php');
4
require_once(dirname(__FILE__) . '/fwolflib.php');
5
require_once(dirname(__FILE__) . '/sql_generator.php');
6
require_once(dirname(__FILE__) . '/../func/ecl.php');
7
require_once(dirname(__FILE__) . '/../func/string.php');
8
9
10
/**
11
 * Extended ADODB class
12
 *
13
 * Include all ADODB had, and add a little others.
14
 *
15
 * Piror use this class' method and property, if the get/set/call target
16
 * is not exists, use original ADODB's, this can be done by php's mechematic
17
 * of overload __call __get __set.
18
 *
19
 * 这似乎是extend ADODB的一种比较好的方式,比官方网站文档上给的按不同数据库来继承子类的方式,
20
 * 我认为要更方便一些。缺点是没有对RecordSet对象进行处理。
21
 *
22
 * Adodb for Sybase bug:
23
 * Affected_Rows() in windows 2003 不可用,httpd 进程会出错中止
24
 *
25
 * 执行sql查询的系列更改中,限定系统/HTML/PHP使用$sSysCharset指定的编码,涉及函数列在__call()中,
26
 * 但一些通过数组等其它方式传递参数的ADODB方法仍然无法通过这种方式实现sql编码自动转换。
27
 *
28
 * 执行返回的数据还是需要转码的,不过返回数据的种类太多,放在应用中实现更简单一些,这里不自动执行,
29
 * 只提供一个EncodingConvert方法供用户调用。
30
 *
31
 * @deprecated  Use Fwlib\Bridge\Adodb
32
 * @package		fwolflib
33
 * @subpackage	class
34
 * @copyright	Copyright 2008-2012, Fwolf
35
 * @author		Fwolf <[email protected]>
36
 * @since		2008-04-08
37
 */
38
class Adodb extends Fwolflib {
0 ignored issues
show
Deprecated Code introduced by
The class Fwolflib has been deprecated with message: Use classes in Fwlib namespace, see PSR-0/1/2

This class, trait or interface has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the type will be removed from the class and what other constant to use instead.

Loading history...
39
40
	/**
41
	 * Real ADODB connection object
42
	 * @var object
43
	 */
44
	protected $__conn = null;
45
46
	/**
47
	 * Db profile
48
	 * @var array
49
	 */
50
	public $aDbProfile = null;
51
52
	/**
53
	 * Table schema
54
	 *
55
	 * array(
56
	 * 	col ->	// ADOFieldObject Object, not Array !
57
	 * 		[name] => ts
58
	 * 		[max_length] => -1
59
	 * 		[type] => timestamp
60
	 * 		[scale] =>
61
	 * 		[not_null] => 1
62
	 * 		[primary_key] =>
63
	 * 		[auto_increment] =>
64
	 * 		[binary] =>
65
	 * 		[unsigned] =>
66
	 * 		[zerofill] =>
67
	 * 		[has_default] => 1
68
	 * 		[default_value] => CURRENT_TIMESTAMP
69
	 * 	)
70
	 * )
71
	 * @var array
72
	 */
73
	public $aMetaColumn = array();
74
75
	/**
76
	 * Table column name array, index is upper case of column name
77
	 *
78
	 * eg: array(
79
	 * 	'COLUMN' => 'column',
80
	 * )
81
	 * @var	array
82
	 */
83
	public $aMetaColumnName = array();
84
85
	/**
86
	 * Primary key columns of table
87
	 *
88
	 * array(
89
	 * 	tbl_name -> 'col_pk',
90
	 * 	tbl_name -> array(pk_col1, pk_col2),
91
	 * )
92
	 * @var	array
93
	 */
94
	public $aMetaPrimaryKey = array();
95
96
	/**
97
	 * Sql generator object
98
	 * @var object
99
	 */
100
	protected $oSg;
101
102
	/**
103
	 * Error msg
104
	 * @var	string
105
	 */
106
	public $sErrorMsg = '';
107
108
	/**
109
	 * System charset
110
	 *
111
	 * In common, this is your php script/operation system charset
112
	 * @var string
113
	 */
114
	public $sSysCharset = 'utf8';
115
116
117
	/**
118
	 * construct
119
	 *
120
	 * <code>
121
	 * $dbprofile = array(type, host, user, pass, name, lang);
122
	 * type is mysql/sybase_ase etc,
123
	 * name is dbname to select,
124
	 * lang is db server charset.
125
	 * </code>
126
	 * @var param	array	$dbprofile
127
	 * @var param	string	$path_adodb		Include path of original ADODB
128
	 */
129
	public function __construct ($dbprofile, $path_adodb = '') {
130
		parent::__construct();
131
132
		// Include original adodb lib
133
		if (empty($path_adodb))
134
			$path_adodb = 'adodb/adodb.inc.php';
135
		require_once($path_adodb);
136
137
		$this->aDbProfile = $dbprofile;
138
		$this->__conn = ADONewConnection($dbprofile['type']);
139
140
		// Sql generator object
141
		$this->oSg = new SqlGenerator($this);
0 ignored issues
show
Deprecated Code introduced by
The class SqlGenerator has been deprecated with message: Use Fwlib\Db\SqlGenerator

This class, trait or interface has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the type will be removed from the class and what other constant to use instead.

Loading history...
142
	} // end of class __construct
143
144
145
	/**
146
	 * Overload __call, redirect method call to adodb
147
	 *
148
	 * @var string	$name	Method name
149
	 * @var array	$arg	Method argument
150
	 * @global	int	$i_db_query_times
151
	 * @return mixed
152
	 */
153
	public function __call ($name, $arg) {
154
		// Before call, convert $sql encoding first
155
		if ($this->sSysCharset != $this->aDbProfile['lang']) {
156
			// Method list by ADODB doc order
157
			// $sql is the 1st param
158
			if (in_array($name, array('Execute',
159
									  'CacheExecute',
160
									  'SelectLimit',
161
									  'CacheSelectLimit',
162
									  'Prepare',
163
									  'PrepareSP',
164
									  'GetOne',
165
									  'GetRow',
166
									  'GetAll',
167
									  'GetCol',
168
									  'CacheGetOne',
169
									  'CacheGetRow',
170
									  'CacheGetAll',
171
									  'CacheGetCol',
172
									  'GetAssoc',
173
									  'CacheGetAssoc',
174
									  'ExecuteCursor',
175
									)))
176
				$arg[0] = mb_convert_encoding($arg[0], $this->aDbProfile['lang'], $this->sSysCharset);
177
178
			// $sql is the 2nd param
179
			if (in_array($name, array('CacheExecute',
180
									  'CacheSelectLimit',
181
									  'CacheGetOne',
182
									  'CacheGetRow',
183
									  'CacheGetAll',
184
									  'CacheGetCol',
185
									  'CacheGetAssoc',
186
									)))
187
				$arg[1] = mb_convert_encoding($arg[1], $this->aDbProfile['lang'], $this->sSysCharset);
188
		}
189
190
		// Count db query times
191
		// Use global var so multi Adodb object can be included in count.
192
		//	(Done in func now)
193
		// Use standalone func to can be easy extend by sub class.
194 View Code Duplication
		if (in_array($name, array(
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
195
			'Execute', 'SelectLimit', 'GetOne', 'GetRow', 'GetAll',
196
			'GetCol', 'GetAssoc', 'ExecuteCursor'
197
			)))
198
			$this->CountDbQueryTimes();
199
200
		return call_user_func_array(array($this->__conn, $name), $arg);
201
	} // end of func __call
202
203
204
	/**
205
	 * Overload __get, redirect method call to adodb
206
	 *
207
	 * @param string	$name
208
	 * @return mixed
209
	 */
210
	public function __get ($name) {
211
		return $this->__conn->$name;
212
	} // end of func __get
213
214
215
	/**
216
	 * Overload __set, redirect method call to adodb
217
	 *
218
	 * @param string	$name
219
	 * @param mixed		$val
220
	 */
221
	public function __set ($name, $val) {
222
		$this->__conn->$name = $val;
223
	} // end of func __set
224
225
226
	/**
227
}
228
	 * Connect, Add mysql 'set names utf8'
229
	 *
230
	 * <code>
231
	 * Obmit params(dbprofile was set in __construct):
232
	 * param $argHostname		Host to connect to
233
	 * param $argUsername		Userid to login
234
	 * param $argPassword		Associated password
235
	 * param $argDatabaseName	database
236
	 * </code>
237
	 * @param $forcenew			Force new connection
238
	 * @return boolean
239
	 */
240
	public function Connect ($forcenew = false) {
241
		// Mysqli doesn't allow port in host, grab it out and set
242 View Code Duplication
		if ('mysqli' == strtolower($this->__conn->databaseType)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
243
			$ar = array();
244
			$i = preg_match('/:(\d+)$/', $this->aDbProfile['host'], $ar);
245
			if (0 < $i) {
246
				$this->__conn->port = $ar[1];
247
				$this->aDbProfile['host'] = preg_replace('/:(\d+)$/', ''
248
					, $this->aDbProfile['host']);
249
			}
250
		}
251
252
253
		try {
254
			// Disable error display tempratory
255
			$s = ini_get("display_errors");
256
			ini_set("display_errors", "0");
257
258
			// Sybase will echo 'change to master' warning msg
259
			// :THINK: Will this problem solved if we drop default
260
			// database master from sa user ?
261
			if ($this->IsDbSybase()) {
262
				$rs = $this->__conn->Connect($this->aDbProfile['host'],
263
										 $this->aDbProfile['user'],
264
										 $this->aDbProfile['pass'],
265
										 $this->aDbProfile['name'],
266
										 $forcenew);
267
			}
268
			else {
269
				$rs = $this->__conn->Connect($this->aDbProfile['host'],
270
										 $this->aDbProfile['user'],
271
										 $this->aDbProfile['pass'],
272
										 $this->aDbProfile['name'],
273
										 $forcenew);
274
			}
275
276
			// Recover original error display setting
277
			ini_set("display_errors", $s);
278
279
			if (empty($rs)) {
280
				throw new Exception('Db connect fail, please check php errorlog.', -1);
281
			}
282
		} catch (Exception $e) {
283
			// Get error trace message
284
			$i_ob = ob_get_level();
285
			if (0 != $i_ob)
286
				$s_t = ob_get_clean();
287
288
			ob_start();
289
			adodb_backtrace($e->getTrace());
290
			$s_trace = ob_get_clean();
291
292
			if (0 != $i_ob) {
293
				// Maybe cause error if output handle of ob_start used before
294
				ob_start();
295
				echo $s_t;
0 ignored issues
show
Bug introduced by
The variable $s_t does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
296
			}
297
298
299
			// Log error
300
			$s_trace = "======== Adodb db connect error\n"
301
				. str_replace('&nbsp;', '>', strip_tags($s_trace))
302
				. $this->ErrorMsg() . "\n";
0 ignored issues
show
Documentation Bug introduced by
The method ErrorMsg does not exist on object<Adodb>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
303
			$this->sErrorMsg = $s_trace;
304
			error_log($s_trace);
305
306
/*
307
			// Print error
308
			$this->sErrorMsg = 'Error, code '
309
				. $e->getCode()
310
				. ', msg: ' . $e->getMessage();
311
312
			// Log error
313
			$s_trace = str_replace('&nbsp;', '>', strip_tags($s_trace));
314
			error_log('');
315
			error_log('======== Adodb db connect error');
316
			error_log("\n" . $s_trace);
317
			error_log($this->sErrorMsg);
318
			//error_log('');
319
*/
320
321
			//var_dump($e);
322
			//echo $e;
323
			if (0 != $i_ob) {
324
				ob_end_flush();
325
			}
326
			//exit();
327
			return false;
328
		}
329
330
		// 针对mysql 4.1以上,UTF8编码的数据库,需要在连接后指定编码
331
		// Can also use $this->aDbProfile['type']
332
		// mysql, mysqli
333
		if ($this->IsDbMysql()) {
334
			$this->__conn->Execute('set names "' . str_replace('utf-8', 'utf8', $this->aDbProfile['lang']) . '"');
335
		}
336
337
		//return $rs;
338
		return true;
339
	} // end of func Connect
340
341
342
	/**
343
	 * Count how many db query have executed
344
	 *
345
	 * This function can be extend by subclass if you want to count on multi db objects.
346
	 *
347
	 * Can't count in Adodb::property, because need display is done by Controler,
348
	 * which will call View, but Adodb is property of Module,
349
	 * so we can only use global vars to save this value.
350
	 * @global	int	$i_db_query_times
351
	 */
352
	protected function CountDbQueryTimes () {
353
		global $i_db_query_times;
354
		$i_db_query_times ++;
355
	} // end of func CountDbQueryTimes
356
357
358
	/**
359
	 * Delete rows by condition user given
360
	 *
361
	 * @param	string	$tbl
362
	 * @param	string	$cond	Condition, can be where, having etc, raw sql string, not null.
363
	 * @return	int		-1 error/0 not found/N > 0 number of rows
364
	 */
365 View Code Duplication
	public function DelRow ($tbl, $cond) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
366
		$cond = trim($cond);
367
		if (empty($cond))
368
			return -1;
369
		$this->PExecute($this->GenSql(array(
370
			'DELETE' => $tbl,
371
			)) . ' ' . $cond);
372
		if (0 != $this->ErrorNo())
0 ignored issues
show
Documentation Bug introduced by
The method ErrorNo does not exist on object<Adodb>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
373
			// Execute error
374
			return -1;
375
		else
376
			return $this->Affected_Rows();
0 ignored issues
show
Documentation Bug introduced by
The method Affected_Rows does not exist on object<Adodb>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
377
	} // end of func DelRow
378
379
380
	/**
381
	 * Convert recordset(simple array) or other string
382
	 * from db encoding to system encoding
383
	 *
384
	 * Use recursive mechanism, beware of loop hole.
385
	 * @param mixed	&$s	Source to convert
386
	 * @return mixed
387
	 */
388 View Code Duplication
	public function EncodingConvert (&$s) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
389
		if (is_array($s) && !empty($s)) {
390
			foreach ($s as &$val)
391
				$this->EncodingConvert($val);
392
			unset($val);
393
		}
394
395
		if (is_string($s)) {
396
			if ($this->sSysCharset != $this->aDbProfile['lang'])
397
				$s = mb_convert_encoding($s, $this->sSysCharset, $this->aDbProfile['lang']);
398
		}
399
		return $s;
400
	} // end of func EncodingConvert
401
402
403
	/**
404
	 * Convert data encoding
405
	 * from system(usually utf-8) to db
406
	 *
407
	 * Use recursive mechanism, beware of loop hole.
408
	 * @param mixed	&$s	Source to convert
409
	 * @return mixed
410
	 */
411 View Code Duplication
	public function EncodingConvertReverse (&$s) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
412
		if (is_array($s) && !empty($s)) {
413
			foreach ($s as &$val)
414
				$this->EncodingConvertReverse($val);
415
			unset($val);
416
		}
417
418
		if (is_string($s)) {
419
			if ($this->sSysCharset != $this->aDbProfile['lang'])
420
				$s = mb_convert_encoding($s, $this->aDbProfile['lang'], $this->sSysCharset);
421
		}
422
		return $s;
423
	} // end of func EncodingConvertReverse
424
425
426
	/**
427
	 * Generate SQL then exec it
428
	 *
429
	 * @param	array	$ar_sql		Same as GenSql()
430
	 * @return	object
431
	 * @see	GenSql()
432
	 */
433
	public function ExecuteGenSql ($ar_sql) {
434
		return $this->Execute($this->GenSql($ar_sql));
0 ignored issues
show
Bug introduced by
The method Execute() does not exist on Adodb. Did you maybe mean ExecuteGenSql()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
435
	} // end of func ExecuteGenSql
436
437
438
	/**
439
	 * Find name of timestamp column of a table
440
	 *
441
	 * @param	$tbl	Table name
442
	 * @return	string
443
	 */
444
	public function FindColTs ($tbl) {
445
		$ar_col = $this->GetMetaColumn($tbl);
446
		if (empty($ar_col))
447
			return '';
448
449
		if ($this->IsDbSybase()) {
450
			// Sybase's timestamp column must be lower cased
451
			// Can name as others, but name as 'timestamp' will auto got )timestamp) type.
452
			/*
453
			if (isset($ar_col['timestamp']))
454
				return 'timestamp';
455
			else
456
				return '';
457
			*/
458
			// New way:
459
			// http://bbs.chinaunix.net/archiver/tid-930729.html
460
			$rs = $this->ExecuteGenSql(array(
461
				'SELECT' => array(
462
					'name'		=> 'a.name',
463
					'length' 	=> 'a.length',
464
					'usertype'	=> 'a.usertype',
465
					'type'		=> 'b.name',
466
					),
467
				'FROM'	=> array(
468
					'a' => 'syscolumns',
469
					'b' => 'systypes',
470
					'c' => 'sysobjects',
471
					),
472
				'WHERE' => array(
473
					"c.name = '$tbl'",
474
					"a.id = c.id",
475
					'a.type = b.type',
476
					'a.usertype = b.usertype',
477
					'b.name = "timestamp"',		// Without this line, can retrieve sybase's col info
478
					),
479
				));
480 View Code Duplication
			if (!empty($rs) && 0 < $rs->RowCount())
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
481
				return $rs->fields['name'];
482
			else
483
				return '';
484
			//select a.name,a.length,a.usertype,b.name AS type from syscolumns a ,systypes b
485
			//where id = object_id('ztb_yh') and a.type=b.type and a.usertype = b.usertype
486
487
		}
488 View Code Duplication
		elseif ($this->IsDbMysql()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
489
			// Check 'type'
490
			foreach ($ar_col as $k => $v)
491
				if (isset($v->type) && 'timestamp' == $v->type)
492
					return $k;
493
		}
494
		else {
495
			die("FindColTs not implemented!\n");
496
		}
497
	} // end of func FindColTs
498
499
500
	/**
501
	 * Generate SQL statement
502
	 *
503
	 * User should avoid use SELECT/UPDATE/INSERT/DELETE simultaneously.
504
	 *
505
	 * Generate order by SQL statement format order.
506
	 *
507
	 * UPDATE/INSERT/DELETE is followed by [TBL_NAME],
508
	 * so need not use FROM.
509
	 * @param array	$ar_sql	Array(select=>..., from=>...)
510
	 * @return string
511
	 * @see	SqlGenerator
512
	 */
513
	public function GenSql ($ar_sql) {
514
		// Changed to use SqlGenerator
515
		if (!empty($ar_sql)) {
516
			return $this->oSg->GetSql($ar_sql);
517
		}
518
		else
519
			return '';
520
	} // end of func GenSql
521
522
523
	/**
524
	 * Generate SQL statement for Prepare
525
	 *
526
	 * value -> ? or :name, and quote chars removed
527
	 * @param	array	$ar_sql	Same as GenSql()
528
	 * @return	string
529
	 * @see	GenSql()
530
	 * @see	SqlGenerator
531
	 */
532
	public function GenSqlPrepare ($ar_sql) {
533
		if (!empty($ar_sql))
534
			return $this->oSg->GetSqlPrepare($ar_sql);
535
		else
536
			return '';
537
	} // end of func GenSqlPrepare
538
539
540
	/**
541
	 * Get data from single table using PK
542
	 *
543
	 * $m_pk, $col, $col_pk support string split by ',' or array, like:
544
	 * 1. 'val'
545
	 * 2. 'val1, val2'
546
	 * 3. array('val1', 'val2')
547
	 *
548
	 * '*' can be used for $col, means all cols in table, this way can't use
549
	 * cache, not recommend.
550
	 *
551
	 * Notice: $col must indexed by number start from 0.
552
	 *
553
	 * Also, this function can be used to retrieve data from a table with
554
	 * single unique index, by assigning $col_pk to non-PK column.
555
	 *
556
	 * @param	string	$s_tbl
557
	 * @param	mixed	$m_pk			PK value
558
	 * @param	mixed	$col			Cols need to retrieve.
559
	 * @param	mixed	$col_pk			PK column name, NULL to auto get.
560
	 * @return	mixed					Single/array, NULL if error occur.
561
	 */
562
	public function GetDataByPk ($s_tbl, $m_pk, $col = NULL, $col_pk = NULL) {
563
		// Treat PK col
564
		if (empty($col_pk)) {
565
			$col_pk = $this->GetMetaPrimaryKey($s_tbl);
566
		}
567
568
		// PK and col name all convert to array
569 View Code Duplication
		if (!is_array($m_pk)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
570
			if (is_string($m_pk))
571
				$m_pk = StrToArray($m_pk, ',');
0 ignored issues
show
Deprecated Code introduced by
The function StrToArray() has been deprecated with message: Use Fwlib\Util\StringUtil::toArray()

This function has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed from the class and what other function to use instead.

Loading history...
572
			else
573
				$m_pk = array($m_pk);
574
		}
575 View Code Duplication
		if (!is_array($col_pk)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
576
			if (is_string($col_pk))
577
				$col_pk = StrToArray($col_pk, ',');
0 ignored issues
show
Deprecated Code introduced by
The function StrToArray() has been deprecated with message: Use Fwlib\Util\StringUtil::toArray()

This function has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed from the class and what other function to use instead.

Loading history...
578
			else
579
				$col_pk = array($col_pk);
580
		}
581
582
		// $col_pk need to be array same count with $m_pk
583
		if (count($m_pk) != count($col_pk)) {
584
			$this->Log('PK value and column not match.', 4);
585
			return NULL;
586
		}
587
588
		// Treat col
589
		if (empty($col))
590
			$col = '*';
591
		if ('*' == $col)
592
			// Drop uppercased index
593
			$col = array_values($this->GetMetaColumnName($s_tbl));
594 View Code Duplication
		if (!is_array($col)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
595
			if (is_string($col))
596
				// String split by ',', style 'col AS col_alias' allowed
597
				$col = StrToArray($col, ',');
0 ignored issues
show
Deprecated Code introduced by
The function StrToArray() has been deprecated with message: Use Fwlib\Util\StringUtil::toArray()

This function has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed from the class and what other function to use instead.

Loading history...
598
			else
599
				$col = array($col);
600
		}
601
602
		// $m_pk, $col, $col_pk all converted to array
603
604
		// Retrieve from db
605
		$ar_sql = array(
606
			'SELECT'	=> $col,
607
			'FROM'		=> $s_tbl,
608
			'LIMIT'		=> 1,
609
		);
610
		while (!empty($m_pk)) {
611
			$s_col_pk = array_shift($col_pk);
612
			$ar_sql['WHERE'][] = $s_col_pk . ' = '
613
				. $this->QuoteValue($s_tbl, $s_col_pk, array_shift($m_pk));
614
			unset($s_col_pk);
615
		}
616
		$rs = $this->ExecuteGenSql($ar_sql);
617
		$ar_rs = array();
618
		if (!empty($rs) && !$rs->EOF) {
619
			$ar_rs = $rs->GetRowAssoc(false);
620
		}
621
622
		// Return value
623
		if (empty($ar_rs))
624
			return NULL;
625
		else {
626
			if (1 == count($ar_rs))
627
				return array_pop($ar_rs);
628
			else
629
				return $ar_rs;
630
		}
631
	} // end of func GetDataByPk
632
633
634
	/**
635
	 * Get table schema
636
	 *
637
	 * @param	string	$table
638
	 * @param	boolean	$forcenew	Force to retrieve instead of read from cache
639
	 * @return	array
640
	 * @see $aMetaColumn
641
	 */
642
	public function GetMetaColumn ($table, $forcenew = false) {
643
		if (!isset($this->aMetaColumn[$table]) || (true == $forcenew)) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
644
			$this->aMetaColumn[$table] = $this->MetaColumns($table);
0 ignored issues
show
Documentation Bug introduced by
The method MetaColumns does not exist on object<Adodb>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
645
646
			// Convert columns to native case
647
			$col_name = $this->GetMetaColumnName($table);
648
			// $col_name = array(COLUMN => column), $c is UPPER CASED
649
			foreach ($this->aMetaColumn[$table] as $c => $ar) {
650
				$this->aMetaColumn[$table][$col_name[$c]] = $ar;
651
				unset($this->aMetaColumn[$table][$c]);
652
			}
653
			// Fix: sybase db display timestamp column as varbinary
654 View Code Duplication
			if ($this->IsDbSybase()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
655
				$s = $this->FindColTs($table);
656
				if (!empty($s))
657
					$this->aMetaColumn[$table][$s]->type = 'timestamp';
658
			}
659
			//print_r($this->aMetaColumn);
660
		}
661
		return $this->aMetaColumn[$table];
662
	} // end of func GetMetaColumn
663
664
665
	/**
666
	 * Get table column name
667
	 *
668
	 * @param	string	$table
669
	 * @param	boolean	$forcenew	Force to retrieve instead of read from cache
670
	 * @return	array
671
	 * @see $aMetaColumnName
672
	 */
673
	public function GetMetaColumnName ($table, $forcenew = false) {
674 View Code Duplication
		if (!isset($this->aMetaColumnName[$table]) || (true == $forcenew)) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
675
			$this->aMetaColumnName[$table] = $this->MetaColumnNames($table);
0 ignored issues
show
Documentation Bug introduced by
The method MetaColumnNames does not exist on object<Adodb>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
676
		}
677
		return $this->aMetaColumnName[$table];
678
	} // end of func GetMetaColumnName
679
680
681
	/**
682
	 * Get primary key column of a table
683
	 *
684
	 * @param	string	$table
685
	 * @param	boolean	$forcenew	Force to retrieve instead of read from cache
686
	 * @return	mixed	Single string value or array when primary key contain multi columns.
687
	 * @see $aMetaPrimaryKey
688
	 */
689
	public function GetMetaPrimaryKey ($table, $forcenew = false) {
690
		if (!isset($this->aMetaPrimaryKey[$table]) || (true == $forcenew)) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
691
			// Find using Adodb first
692
			$ar = $this->MetaPrimaryKeys($table);
0 ignored issues
show
Documentation Bug introduced by
The method MetaPrimaryKeys does not exist on object<Adodb>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
693
			if (false == $ar || empty($ar)) {
694
				// Adodb not support, find by hand
695
				// Sybase
696
				// 	keys1、keys2、keys3的描述不清,应该是:
697
				//	select name ,keycnt
698
				//		,index_col(YourTableName,indid,1)   --主键中的第一列
699
				//		,index_col(YourTableName,indid,2)   --主键中的第二列,如果有的话
700
				//	from   sysindexes
701
				//	where   status   &   2048=2048
702
				//		and   id=object_id(YourTableName)
703
				// 主键涉及的列的数量在keycnt中。如果主键索引不是簇集索引(由status中的0x10位决定)的话,则为keycnt-1。
704
				// http://topic.csdn.net/t/20030117/17/1369396.html
705
				// 根据这种方法,目前好像只能用于主键包含三个以下字段的情况?
706
				// 已测试过主键包含两个字段的情况下能取出来
707
				/*
708
				 select name, keycnt, index_col('sgqyjbqk', indid, 1)
709
				, index_col('sgqyjbqk', indid, 2)
710
				, index_col('sgqyjbqk', indid, 3)
711
				from sysindexes
712
				where status & 2048 = 2048
713
					and id = object_id('sgqyjbqk')
714
				 */
715 View Code Duplication
				if ($this->IsDbSybase()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
716
					$rs = $this->PExecuteGenSql(array(
717
						'select' => array(
718
							'name' => 'a.name',
719
							'keycnt' => 'a.keycnt',
720
							'k1' => "index_col('$table', indid, 1)",
721
							'k2' => "index_col('$table', indid, 2)",
722
							'k3' => "index_col('$table', indid, 3)",
723
							),
724
						'from'	=> array(
725
							'a' => 'sysindexes',
726
							'b' => 'sysobjects',
727
						),
728
						'where' => array(
729
							'a.status & 2048 = 2048 ',
730
							"b.name = '$table'",
731
							"a.id = b.id"
732
							)
733
						));
734
					if (true == $rs && 0 < $rs->RowCount()) {
735
						// Got
736
						$ar = array($rs->fields['k1']);
737
						if (!empty($rs->fields['k2']))
738
							$ar[] = $rs->fields['k2'];
739
						if (!empty($rs->fields['k3']))
740
							$ar[] = $rs->fields['k3'];
741
					}
742
					else {
743
						// Table have no primary key
744
						$ar = '';
745
					}
746
				}
747
			}
748
749
			// Convert columns to native case
750
			if (!empty($ar)) {
751
				$col_name = $this->GetMetaColumnName($table);
752
				// $col_name = array(COLUMN => column), $c is UPPER CASED
753
				foreach ($ar as $idx => &$col) {
754
					if ($col != $col_name[strtoupper($col)]) {
755
						unset($ar[$idx]);
756
						$ar[] = $col_name[strtoupper($col)];
757
					}
758
				}
759
				unset($col);
760
			}
761
762
			if (is_array($ar) && 1 == count($ar))
763
				// Only 1 primary key column
764
				$ar = $ar[0];
765
766
			// Set to cache
767
			if (!empty($ar))
768
				$this->aMetaPrimaryKey[$table] = $ar;
769
		}
770
		if (isset($this->aMetaPrimaryKey[$table]))
771
			return $this->aMetaPrimaryKey[$table];
772
		else
773
			return '';
774
	} // end of func GetMetaPrimaryKey
775
776
777
	/**
778
	 * Get rows count by condition user given
779
	 *
780
	 * @param	string	$tbl
781
	 * @param	string	$cond	Condition, can be where, having etc, raw sql string.
782
	 * @return	int		-1: error/N >= 0: number of rows
783
	 */
784 View Code Duplication
	public function GetRowCount ($tbl, $cond = '') {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
785
		$rs = $this->PExecute($this->GenSql(array(
786
			'SELECT' => array('c' => 'count(1)'),
787
			'FROM'	=> $tbl,
788
			)) . ' ' . $cond);
789
		if (false == $rs || 0 != $this->ErrorNo()
0 ignored issues
show
Documentation Bug introduced by
The method ErrorNo does not exist on object<Adodb>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
790
				|| 0 == $rs->RowCount())
791
			// Execute error
792
			return -1;
793
		else
794
			return $rs->fields['c'];
795
	} // end of func GetRowCount
796
797
798
	/**
799
	 * Get delimiter between SQL for various db
800
	 *
801
	 * @return	string
802
	 */
803
	public function GetSqlDelimiter () {
804
		if ($this->IsDbMysql())
805
			return ";\n";
806
		elseif ($this->IsDbSybase())
807
			return "\n";
808
		else {
809
			$this->Log('GetSqlDelimiter() for this kind of db not implement.'
810
				, 5);
811
			return "\n";
812
		}
813
	} // end of func GetSqlDelimiter
814
815
816
	/**
817
	 * Get SQL: begin transaction
818
	 *
819
	 * @return	string
820
	 */
821
	public function GetSqlTransBegin () {
822
		if ($this->IsDbMysql())
823
			return 'START TRANSACTION' . $this->GetSqlDelimiter();
824
		else
825
			return 'BEGIN TRANSACTION' . $this->GetSqlDelimiter();
826
	} // end of func GetSqlTransBegin
827
828
829
	/**
830
	 * Get SQL: commit transaction
831
	 *
832
	 * @return	string
833
	 */
834
	public function GetSqlTransCommit () {
835
		return 'COMMIT' . $this->GetSqlDelimiter();
836
	} // end of func GetSqlTransCommit
837
838
839
	/**
840
	 * Get SQL: rollback transaction
841
	 *
842
	 * @return	string
843
	 */
844
	public function GetSqlTransRollback () {
845
		return 'ROLLBACK' . $this->GetSqlDelimiter();
846
	} // end of func GetSqlTransRollback
847
848
849
	/**
850
	 * If current db is a mysql db.
851
	 *
852
	 * @return	boolean
853
	 */
854
	public function IsDbMysql () {
855
		return ('mysql' == substr($this->__conn->databaseType, 0, 5));
856
	} // end of func IsDbMysql
857
858
859
	/**
860
	 * If current db is a sybase db.
861
	 *
862
	 * @return	boolean
863
	 */
864
	public function IsDbSybase () {
865
        return ('sybase' == substr($this->aDbProfile['type'], 0, 6)) ||
866
            ('pdo_sybase' == substr($this->aDbProfile['type'], 0, 10));
867
	}
868
869
870
	/**
871
	 * Is timestamp column's value is unique
872
	 *
873
	 * @return	boolean
874
	 */
875
	public function IsTsUnique () {
876
		if ('sybase' == $this->IsDbSybase())
877
			return true;
878
		else
879
			// Mysql
880
			return false;
881
	} // end of func IsTsUnique
882
883
884
	/**
885
	 * Prepare and execute sql
886
	 *
887
	 * @param	string	$sql
888
	 * @param	array	$inputarr	Optional parameters in sql
889
	 * @return	object
890
	 */
891
	public function PExecute ($sql, $inputarr = false) {
892
		$stmt = $this->Prepare($sql);
0 ignored issues
show
Bug introduced by
The method Prepare() does not exist on Adodb. Did you maybe mean GenSqlPrepare()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
893
		$this->BeginTrans();
0 ignored issues
show
Documentation Bug introduced by
The method BeginTrans does not exist on object<Adodb>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
894
		$rs = $this->Execute($stmt, $inputarr);
0 ignored issues
show
Bug introduced by
The method Execute() does not exist on Adodb. Did you maybe mean ExecuteGenSql()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
895 View Code Duplication
		if (0 != $this->ErrorNo()) {
0 ignored issues
show
Documentation Bug introduced by
The method ErrorNo does not exist on object<Adodb>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
896
			// Log to error log file
897
			error_log('ErrorNo: ' . $this->ErrorNo()
0 ignored issues
show
Documentation Bug introduced by
The method ErrorNo does not exist on object<Adodb>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
898
				. "\nErrorMsg: " . $this->ErrorMsg()
0 ignored issues
show
Documentation Bug introduced by
The method ErrorMsg does not exist on object<Adodb>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
899
				);
900
			$this->RollbackTrans();
0 ignored issues
show
Documentation Bug introduced by
The method RollbackTrans does not exist on object<Adodb>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
901
			return -1;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return -1; (integer) is incompatible with the return type documented by Adodb::PExecute of type object.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
902
		}
903
		$this->CommitTrans();
0 ignored issues
show
Documentation Bug introduced by
The method CommitTrans does not exist on object<Adodb>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
904
		return $rs;
905
	} // end of PExecute
906
907
908
	/**
909
	 * Generate, prepare and exec SQL
910
	 *
911
	 * @param	array	$ar_sql		Same as GenSql()
912
	 * @param	array	$inputarr	Optional parameters in sql
913
	 * @return	object
914
	 * @see	GenSql()
915
	 */
916
	public function PExecuteGenSql ($ar_sql, $inputarr = false) {
917
		return $this->PExecute($this->GenSqlPrepare($ar_sql), $inputarr);
918
	} // end of func PExecuteGenSql
919
920
921
	/**
922
	 * Smarty quote string in sql, by check columns type
923
	 *
924
	 * @param	string	$table
925
	 * @param	string	$column
926
	 * @param	mixed	$val
927
	 * @return	string
928
	 */
929 View Code Duplication
	public function QuoteValue ($table, $column, $val) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
930
		$this->GetMetaColumn($table);
931
		if (!isset($this->aMetaColumn[$table][$column]->type)) {
932
			error_log("Column to quote not exists($table.$column).\n");
933
			// Return quoted value for safety
934
			$val = stripslashes($val);
935
			return $this->qstr($val, false);
0 ignored issues
show
Documentation Bug introduced by
The method qstr does not exist on object<Adodb>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
936
		}
937
938
		//print_r($this->aMetaColumn[$table][$column]);
939
		$type = $this->aMetaColumn[$table][$column]->type;
940
		//var_dump($type);
941
		if (in_array($type, array(
942
				'bigint',
943
				'bit',
944
				'decimal',
945
				'double',
946
				'float',
947
				'int',
948
				'intn', // Sybase - tinyint
949
				'mediumint',
950
				'numeric',
951
				'numericn',	// Sybase - numeric
952
				'real',
953
				'smallint',
954
				'tinyint',
955
			)))
956
			// Need not quote, output directly
957
			return $val;
958
		// Sybase timestamp
959
		//elseif ($this->IsDbSybase() && 'varbinary' == $type && 'timestamp' == $column)
960
		elseif ($this->IsDbSybase() && 'timestamp' == $type)
961
			return '0x' . $val;
962
		else {
963
			// Need quote, use db's quote method
964
			$val = stripslashes($val);
965
			return $this->qstr($val, false);
0 ignored issues
show
Documentation Bug introduced by
The method qstr does not exist on object<Adodb>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
966
		}
967
	} // end of func GenSqlQuote
968
969
970
	/**
971
	 * If a table exists in db ?
972
	 *
973
	 * @param	string	$tbl
974
	 * @return	boolean
975
	 */
976 View Code Duplication
	public function TblExists ($tbl) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
977
		if ($this->IsDbSybase()) {
978
			$sql = "select count(1) as c from sysobjects where name = '$tbl' and type = 'U'";
979
			$rs = $this->Execute($sql);
0 ignored issues
show
Bug introduced by
The method Execute() does not exist on Adodb. Did you maybe mean ExecuteGenSql()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
980
			return (0 != $rs->fields['c']);
981
		}
982
		elseif ($this->IsDbMysql()) {
983
			$sql = "SHOW TABLES LIKE '$tbl'";
984
			$rs = $this->Execute($sql);
0 ignored issues
show
Bug introduced by
The method Execute() does not exist on Adodb. Did you maybe mean ExecuteGenSql()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
985
			return (0 != $rs->RowCount());
986
		}
987
		else {
988
			// :NOTICE: Un-tested method
989
			$sql = "select 1 from $tbl";
990
			$rs = $this->Execute($sql);
0 ignored issues
show
Unused Code introduced by
$rs is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
Bug introduced by
The method Execute() does not exist on Adodb. Did you maybe mean ExecuteGenSql()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
991
			return (0 == $this->ErrorNo());
0 ignored issues
show
Documentation Bug introduced by
The method ErrorNo does not exist on object<Adodb>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
992
		}
993
	} // end of func TblExists
994
995
996
	/**
997
	 * Smart write data row(s) to table
998
	 *
999
	 * Will auto check row existence, and decide to use INSERT or UPDATE,
1000
	 * so PRIMARY KEY column must include in $data array.
1001
	 * Also, table must have primary key defined.
1002
	 * @param	string	$tbl	Table which rows to write to
1003
	 * @param	array	$data	Row(s) data, only one row(1-dim array, index is column name)
1004
	 * 							or some rows(2-dim array, index layer 1 MUST be number and
1005
	 * 							will not write to db).
1006
	 * @param	string	$mode	A auto detect/U update/I insert, ignore case.
1007
	 * 							If you assign some rows, it's better not to set this to 0,
1008
	 * 							because it will only detect by the FIRST row data.
1009
	 * @return	int		Number of inserted or updated rows, -1 means some error,
1010
	 * 					0 and upper are normal result.
1011
	 */
1012
	public function Write ($tbl, $data, $mode = 'A') {
1013
		// Find primary key column first
1014
		$pk = $this->GetMetaPrimaryKey($tbl);
1015
1016
		// Convert single row data to multi row mode
1017
		if (!isset($data[0]))
1018
			$data = array(0 => $data);
1019
		// Convert primary key to array if it's single string now
1020
		if (!is_array($pk))
1021
			$pk = array(0 => $pk);
1022
1023
		// Columns in $data
1024
		$ar_cols = array_keys($data[0]);
1025
		// Check if primary key is assigned in $data
1026
		$b_data_ok = true;
1027
		foreach ($pk as $key)
1028
			if (!in_array($key, $ar_cols))
1029
				$b_data_ok = false;
1030
		// If no primary key column in $data, return -1
1031
		if (false == $b_data_ok)
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
1032
			return -1;
1033
1034
		$mode = strtoupper($mode);
1035
		// Consider mode if user not assigned
1036 View Code Duplication
		if ('A' == $mode) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1037
			$s_where = ' WHERE ';
1038
			foreach ($pk as $key)
1039
				$s_where .= " $key = " . $this->QuoteValue($tbl, $key, $data[0][$key])
1040
					. ' AND ';
1041
			$s_where = substr($s_where, 0, strlen($s_where) - 5);
1042
			if (0 < $this->GetRowCount($tbl, $s_where))
1043
				$mode = 'U';
1044
			else
1045
				$mode = 'I';
1046
		}
1047
1048
		// Do batch update or insert, prepare stmt first
1049
		$sql = '';
0 ignored issues
show
Unused Code introduced by
$sql is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1050
		if ('U' == $mode) {
1051
			$ar_conf = array(
1052
				'UPDATE' => $tbl,
1053
				'LIMIT' => 1,
1054
				);
1055
			foreach ($pk as $key) {
1056
				// Primary key need remove from 'SET' clause
1057
				// Actual value will assign later, do quote then.
1058
				// :NOTICE: Remember to put pk data to end of row data when assign,
1059
				//	because where clause is after set clause.
1060
				$ar_conf['WHERE'][] = "$key = "
1061
					. $this->Param($key);
0 ignored issues
show
Documentation Bug introduced by
The method Param does not exist on object<Adodb>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
1062
				unset($ar_cols[array_search($key, $ar_cols)]);
1063
			}
1064
			// Convert array $ar_cols with to prepare param
1065
			$ar_set = array();
1066
			foreach ($ar_cols as $key)
1067
				$ar_set[$key] = $this->Param($key);
0 ignored issues
show
Documentation Bug introduced by
The method Param does not exist on object<Adodb>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
1068
			// Fin, assign 'SET' clause
1069
			$ar_conf['SET'] = $ar_set;
1070
		}
1071
		elseif ('I' == $mode) {
1072
			$ar_set = array();
1073
			foreach ($ar_cols as $key) {
1074
				$ar_set[$key] = $this->Param($key);
0 ignored issues
show
Documentation Bug introduced by
The method Param does not exist on object<Adodb>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
1075
			}
1076
			$ar_conf = array(
1077
				'INSERT' => $tbl,
1078
				'VALUES' => $ar_set,
1079
				);
1080
		}
1081
		$sql = $this->GenSqlPrepare($ar_conf);
0 ignored issues
show
Bug introduced by
The variable $ar_conf does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
1082
1083
		/* Treat moved to  SqlGenerator
1084
		//$sql = $this->GenSql($ar_conf);
1085
		// Remove duplicate ' in sql add by SqlGenerator,
1086
		// Execute after Prepare will auto recoginize variant type and quote,
1087
		// but notice, it's VAR TYPE and NOT DB COLUMN TYPE.
1088
		// replaceQuote: The string used to escape quotes. Eg. double single-quotes for
1089
		// Microsoft SQL, and backslash-quote for MySQL. Used by qstr.
1090
		if ("''" == $this->replaceQuote)
1091
			$s_quote = "'";
1092
		else
1093
			$s_quote = $this->replaceQuote;
1094
		$sql = preg_replace(
1095
			"/ {$s_quote}([\?\:\w\-_]+){$s_quote}([, ])/i",
1096
			" $1$2", $sql);
1097
		*/
1098
1099
		if (!empty($sql)) {
1100
			// Do prepare
1101
			$stmt = $this->Prepare($sql);
0 ignored issues
show
Bug introduced by
The method Prepare() does not exist on Adodb. Did you maybe mean GenSqlPrepare()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
1102
			// Execute
1103 View Code Duplication
			if ('U' == $mode) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1104
				foreach ($data as &$row) {
1105
					// Change pk's value position when update mode
1106
					foreach ($pk as $key) {
1107
						$v = $row[$key];
1108
						unset($row[$key]);
1109
						$row[$key] = $v;
1110
					}
1111
				}
1112
				unset($row);
1113
			}
1114
			// Now, finanly, actual write data
1115
			// Auto convert encoding ?
1116
			// Use of prepare we must convert $data manually, because $data is not sql.
1117
			$this->EncodingConvert($data);
1118
			try {
1119
				$this->Execute($stmt, $data);
0 ignored issues
show
Bug introduced by
The method Execute() does not exist on Adodb. Did you maybe mean ExecuteGenSql()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
1120
			}
1121
			catch (Exception $e) {
1122
				// Show error message ?
1123
				$this->RollbackTrans();
0 ignored issues
show
Documentation Bug introduced by
The method RollbackTrans does not exist on object<Adodb>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
1124
				return -1;
1125
			}
1126
			// Any error ?
1127 View Code Duplication
			if (0 != $this->ErrorNo()) {
0 ignored issues
show
Documentation Bug introduced by
The method ErrorNo does not exist on object<Adodb>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1128
				// Log to error log file
1129
				error_log('ErrorNo: ' . $this->ErrorNo()
0 ignored issues
show
Documentation Bug introduced by
The method ErrorNo does not exist on object<Adodb>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
1130
					. "\nErrorMsg: " . $this->ErrorMsg()
0 ignored issues
show
Documentation Bug introduced by
The method ErrorMsg does not exist on object<Adodb>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
1131
					);
1132
				$this->RollbackTrans();
0 ignored issues
show
Documentation Bug introduced by
The method RollbackTrans does not exist on object<Adodb>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
1133
				return -1;
1134
			}
1135
			else {
1136
				$this->CommitTrans();
0 ignored issues
show
Documentation Bug introduced by
The method CommitTrans does not exist on object<Adodb>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
1137
				return count($data);
1138
			}
1139
		}
1140
		else
1141
			return -1;
1142
	} // end of func Write
1143
1144
1145
} // end of class Adodb
1146
?>
0 ignored issues
show
Best Practice introduced by
It is not recommended to use PHP's closing tag ?> in files other than templates.

Using a closing tag in PHP files that only contain PHP code is not recommended as you might accidentally add whitespace after the closing tag which would then be output by PHP. This can cause severe problems, for example headers cannot be sent anymore.

A simple precaution is to leave off the closing tag as it is not required, and it also has no negative effects whatsoever.

Loading history...
1147