Adodb::GetMetaColumn()   B
last analyzed

Complexity

Conditions 6
Paths 4

Size

Total Lines 21

Duplication

Lines 5
Ratio 23.81 %

Importance

Changes 0
Metric Value
cc 6
nc 4
nop 2
dl 5
loc 21
rs 8.9617
c 0
b 0
f 0
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
					'tableName' => 'c.name',
467
					),
468
				'FROM'	=> array(
469
					'a' => 'syscolumns',
470
					'b' => 'systypes',
471
					'c' => 'sysobjects',
472
					),
473
				'WHERE' => array(
474
					"a.id = c.id",
475
					'a.type = b.type',
476
					'a.usertype = b.usertype',
477
                    'b.type = 37',
478
                    'b.usertype = 80',
479
					),
480
				));
481 View Code Duplication
			while (!empty($rs) && !$rs->EOF) {
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...
482
				if ($tbl == $rs->fields['tableName']) {
483
                    return $rs->fields['name'];
484
				}
485
				$rs->MoveNext();
486
			}
487
488
			return '';
489
			//select a.name,a.length,a.usertype,b.name AS type from syscolumns a ,systypes b
490
			//where id = object_id('ztb_yh') and a.type=b.type and a.usertype = b.usertype
491
492
		}
493 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...
494
			// Check 'type'
495
			foreach ($ar_col as $k => $v)
496
				if (isset($v->type) && 'timestamp' == $v->type)
497
					return $k;
498
		}
499
		else {
500
			die("FindColTs not implemented!\n");
501
		}
502
	} // end of func FindColTs
503
504
505
	/**
506
	 * Generate SQL statement
507
	 *
508
	 * User should avoid use SELECT/UPDATE/INSERT/DELETE simultaneously.
509
	 *
510
	 * Generate order by SQL statement format order.
511
	 *
512
	 * UPDATE/INSERT/DELETE is followed by [TBL_NAME],
513
	 * so need not use FROM.
514
	 * @param array	$ar_sql	Array(select=>..., from=>...)
515
	 * @return string
516
	 * @see	SqlGenerator
517
	 */
518
	public function GenSql ($ar_sql) {
519
		// Changed to use SqlGenerator
520
		if (!empty($ar_sql)) {
521
			return $this->oSg->GetSql($ar_sql);
522
		}
523
		else
524
			return '';
525
	} // end of func GenSql
526
527
528
	/**
529
	 * Generate SQL statement for Prepare
530
	 *
531
	 * value -> ? or :name, and quote chars removed
532
	 * @param	array	$ar_sql	Same as GenSql()
533
	 * @return	string
534
	 * @see	GenSql()
535
	 * @see	SqlGenerator
536
	 */
537
	public function GenSqlPrepare ($ar_sql) {
538
		if (!empty($ar_sql))
539
			return $this->oSg->GetSqlPrepare($ar_sql);
540
		else
541
			return '';
542
	} // end of func GenSqlPrepare
543
544
545
	/**
546
	 * Get data from single table using PK
547
	 *
548
	 * $m_pk, $col, $col_pk support string split by ',' or array, like:
549
	 * 1. 'val'
550
	 * 2. 'val1, val2'
551
	 * 3. array('val1', 'val2')
552
	 *
553
	 * '*' can be used for $col, means all cols in table, this way can't use
554
	 * cache, not recommend.
555
	 *
556
	 * Notice: $col must indexed by number start from 0.
557
	 *
558
	 * Also, this function can be used to retrieve data from a table with
559
	 * single unique index, by assigning $col_pk to non-PK column.
560
	 *
561
	 * @param	string	$s_tbl
562
	 * @param	mixed	$m_pk			PK value
563
	 * @param	mixed	$col			Cols need to retrieve.
564
	 * @param	mixed	$col_pk			PK column name, NULL to auto get.
565
	 * @return	mixed					Single/array, NULL if error occur.
566
	 */
567
	public function GetDataByPk ($s_tbl, $m_pk, $col = NULL, $col_pk = NULL) {
568
		// Treat PK col
569
		if (empty($col_pk)) {
570
			$col_pk = $this->GetMetaPrimaryKey($s_tbl);
571
		}
572
573
		// PK and col name all convert to array
574 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...
575
			if (is_string($m_pk))
576
				$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...
577
			else
578
				$m_pk = array($m_pk);
579
		}
580 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...
581
			if (is_string($col_pk))
582
				$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...
583
			else
584
				$col_pk = array($col_pk);
585
		}
586
587
		// $col_pk need to be array same count with $m_pk
588
		if (count($m_pk) != count($col_pk)) {
589
			$this->Log('PK value and column not match.', 4);
590
			return NULL;
591
		}
592
593
		// Treat col
594
		if (empty($col))
595
			$col = '*';
596
		if ('*' == $col)
597
			// Drop uppercased index
598
			$col = array_values($this->GetMetaColumnName($s_tbl));
599 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...
600
			if (is_string($col))
601
				// String split by ',', style 'col AS col_alias' allowed
602
				$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...
603
			else
604
				$col = array($col);
605
		}
606
607
		// $m_pk, $col, $col_pk all converted to array
608
609
		// Retrieve from db
610
		$ar_sql = array(
611
			'SELECT'	=> $col,
612
			'FROM'		=> $s_tbl,
613
			'LIMIT'		=> 1,
614
		);
615
		while (!empty($m_pk)) {
616
			$s_col_pk = array_shift($col_pk);
617
			$ar_sql['WHERE'][] = $s_col_pk . ' = '
618
				. $this->QuoteValue($s_tbl, $s_col_pk, array_shift($m_pk));
619
			unset($s_col_pk);
620
		}
621
		$rs = $this->ExecuteGenSql($ar_sql);
622
		$ar_rs = array();
623
		if (!empty($rs) && !$rs->EOF) {
624
			$ar_rs = $rs->GetRowAssoc(false);
625
		}
626
627
		// Return value
628
		if (empty($ar_rs))
629
			return NULL;
630
		else {
631
			if (1 == count($ar_rs))
632
				return array_pop($ar_rs);
633
			else
634
				return $ar_rs;
635
		}
636
	} // end of func GetDataByPk
637
638
639
	/**
640
	 * Get table schema
641
	 *
642
	 * @param	string	$table
643
	 * @param	boolean	$forcenew	Force to retrieve instead of read from cache
644
	 * @return	array
645
	 * @see $aMetaColumn
646
	 */
647
	public function GetMetaColumn ($table, $forcenew = false) {
648
		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...
649
			$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...
650
651
			// Convert columns to native case
652
			$col_name = $this->GetMetaColumnName($table);
653
			// $col_name = array(COLUMN => column), $c is UPPER CASED
654
			foreach ($this->aMetaColumn[$table] as $c => $ar) {
655
				$this->aMetaColumn[$table][$col_name[$c]] = $ar;
656
				unset($this->aMetaColumn[$table][$c]);
657
			}
658
			// Fix: sybase db display timestamp column as varbinary
659 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...
660
				$s = $this->FindColTs($table);
661
				if (!empty($s))
662
					$this->aMetaColumn[$table][$s]->type = 'timestamp';
663
			}
664
			//print_r($this->aMetaColumn);
665
		}
666
		return $this->aMetaColumn[$table];
667
	} // end of func GetMetaColumn
668
669
670
	/**
671
	 * Get table column name
672
	 *
673
	 * @param	string	$table
674
	 * @param	boolean	$forcenew	Force to retrieve instead of read from cache
675
	 * @return	array
676
	 * @see $aMetaColumnName
677
	 */
678
	public function GetMetaColumnName ($table, $forcenew = false) {
679 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...
680
			$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...
681
		}
682
		return $this->aMetaColumnName[$table];
683
	} // end of func GetMetaColumnName
684
685
686
	/**
687
	 * Get primary key column of a table
688
	 *
689
	 * @param	string	$table
690
	 * @param	boolean	$forcenew	Force to retrieve instead of read from cache
691
	 * @return	mixed	Single string value or array when primary key contain multi columns.
692
	 * @see $aMetaPrimaryKey
693
	 */
694
	public function GetMetaPrimaryKey ($table, $forcenew = false) {
695
		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...
696
			// Find using Adodb first
697
			$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...
698
			if (false == $ar || empty($ar)) {
699
				// Adodb not support, find by hand
700
				// Sybase
701
				// 	keys1、keys2、keys3的描述不清,应该是:
702
				//	select name ,keycnt
703
				//		,index_col(YourTableName,indid,1)   --主键中的第一列
704
				//		,index_col(YourTableName,indid,2)   --主键中的第二列,如果有的话
705
				//	from   sysindexes
706
				//	where   status   &   2048=2048
707
				//		and   id=object_id(YourTableName)
708
				// 主键涉及的列的数量在keycnt中。如果主键索引不是簇集索引(由status中的0x10位决定)的话,则为keycnt-1。
709
				// http://topic.csdn.net/t/20030117/17/1369396.html
710
				// 根据这种方法,目前好像只能用于主键包含三个以下字段的情况?
711
				// 已测试过主键包含两个字段的情况下能取出来
712
				/*
713
				 select name, keycnt, index_col('sgqyjbqk', indid, 1)
714
				, index_col('sgqyjbqk', indid, 2)
715
				, index_col('sgqyjbqk', indid, 3)
716
				from sysindexes
717
				where status & 2048 = 2048
718
					and id = object_id('sgqyjbqk')
719
				 */
720 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...
721
					$rs = $this->PExecuteGenSql(array(
722
						'select' => array(
723
							'name' => 'a.name',
724
							'keycnt' => 'a.keycnt',
725
							'k1' => "index_col('$table', indid, 1)",
726
							'k2' => "index_col('$table', indid, 2)",
727
							'k3' => "index_col('$table', indid, 3)",
728
							),
729
						'from'	=> array(
730
							'a' => 'sysindexes',
731
							'b' => 'sysobjects',
732
						),
733
						'where' => array(
734
							'a.status & 2048 = 2048 ',
735
							"b.name = '$table'",
736
							"a.id = b.id"
737
							)
738
						));
739
					if (true == $rs && 0 < $rs->RowCount()) {
740
						// Got
741
						$ar = array($rs->fields['k1']);
742
						if (!empty($rs->fields['k2']))
743
							$ar[] = $rs->fields['k2'];
744
						if (!empty($rs->fields['k3']))
745
							$ar[] = $rs->fields['k3'];
746
					}
747
					else {
748
						// Table have no primary key
749
						$ar = '';
750
					}
751
				}
752
			}
753
754
			// Convert columns to native case
755
			if (!empty($ar)) {
756
				$col_name = $this->GetMetaColumnName($table);
757
				// $col_name = array(COLUMN => column), $c is UPPER CASED
758
				foreach ($ar as $idx => &$col) {
759
					if ($col != $col_name[strtoupper($col)]) {
760
						unset($ar[$idx]);
761
						$ar[] = $col_name[strtoupper($col)];
762
					}
763
				}
764
				unset($col);
765
			}
766
767
			if (is_array($ar) && 1 == count($ar))
768
				// Only 1 primary key column
769
				$ar = $ar[0];
770
771
			// Set to cache
772
			if (!empty($ar))
773
				$this->aMetaPrimaryKey[$table] = $ar;
774
		}
775
		if (isset($this->aMetaPrimaryKey[$table]))
776
			return $this->aMetaPrimaryKey[$table];
777
		else
778
			return '';
779
	} // end of func GetMetaPrimaryKey
780
781
782
	/**
783
	 * Get rows count by condition user given
784
	 *
785
	 * @param	string	$tbl
786
	 * @param	string	$cond	Condition, can be where, having etc, raw sql string.
787
	 * @return	int		-1: error/N >= 0: number of rows
788
	 */
789 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...
790
		$rs = $this->PExecute($this->GenSql(array(
791
			'SELECT' => array('c' => 'count(1)'),
792
			'FROM'	=> $tbl,
793
			)) . ' ' . $cond);
794
		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...
795
				|| 0 == $rs->RowCount())
796
			// Execute error
797
			return -1;
798
		else
799
			return $rs->fields['c'];
800
	} // end of func GetRowCount
801
802
803
	/**
804
	 * Get delimiter between SQL for various db
805
	 *
806
	 * @return	string
807
	 */
808
	public function GetSqlDelimiter () {
809
		if ($this->IsDbMysql())
810
			return ";\n";
811
		elseif ($this->IsDbSybase())
812
			return "\n";
813
		else {
814
			$this->Log('GetSqlDelimiter() for this kind of db not implement.'
815
				, 5);
816
			return "\n";
817
		}
818
	} // end of func GetSqlDelimiter
819
820
821
	/**
822
	 * Get SQL: begin transaction
823
	 *
824
	 * @return	string
825
	 */
826
	public function GetSqlTransBegin () {
827
		if ($this->IsDbMysql())
828
			return 'START TRANSACTION' . $this->GetSqlDelimiter();
829
		else
830
			return 'BEGIN TRANSACTION' . $this->GetSqlDelimiter();
831
	} // end of func GetSqlTransBegin
832
833
834
	/**
835
	 * Get SQL: commit transaction
836
	 *
837
	 * @return	string
838
	 */
839
	public function GetSqlTransCommit () {
840
		return 'COMMIT' . $this->GetSqlDelimiter();
841
	} // end of func GetSqlTransCommit
842
843
844
	/**
845
	 * Get SQL: rollback transaction
846
	 *
847
	 * @return	string
848
	 */
849
	public function GetSqlTransRollback () {
850
		return 'ROLLBACK' . $this->GetSqlDelimiter();
851
	} // end of func GetSqlTransRollback
852
853
854
	/**
855
	 * If current db is a mysql db.
856
	 *
857
	 * @return	boolean
858
	 */
859
	public function IsDbMysql () {
860
		return ('mysql' == substr($this->__conn->databaseType, 0, 5));
861
	} // end of func IsDbMysql
862
863
864
	/**
865
	 * If current db is a sybase db.
866
	 *
867
	 * @return	boolean
868
	 */
869
	public function IsDbSybase () {
870
        return ('sybase' == substr($this->aDbProfile['type'], 0, 6)) ||
871
            ('pdo_sybase' == substr($this->aDbProfile['type'], 0, 10));
872
	}
873
874
875
	/**
876
	 * Is timestamp column's value is unique
877
	 *
878
	 * @return	boolean
879
	 */
880
	public function IsTsUnique () {
881
		if ('sybase' == $this->IsDbSybase())
882
			return true;
883
		else
884
			// Mysql
885
			return false;
886
	} // end of func IsTsUnique
887
888
889
	/**
890
	 * Prepare and execute sql
891
	 *
892
	 * @param	string	$sql
893
	 * @param	array	$inputarr	Optional parameters in sql
894
	 * @return	object
895
	 */
896
	public function PExecute ($sql, $inputarr = false) {
897
		$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...
898
		$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...
899
		$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...
900 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...
901
			// Log to error log file
902
			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...
903
				. "\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...
904
				);
905
			$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...
906
			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...
907
		}
908
		$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...
909
		return $rs;
910
	} // end of PExecute
911
912
913
	/**
914
	 * Generate, prepare and exec SQL
915
	 *
916
	 * @param	array	$ar_sql		Same as GenSql()
917
	 * @param	array	$inputarr	Optional parameters in sql
918
	 * @return	object
919
	 * @see	GenSql()
920
	 */
921
	public function PExecuteGenSql ($ar_sql, $inputarr = false) {
922
		return $this->PExecute($this->GenSqlPrepare($ar_sql), $inputarr);
923
	} // end of func PExecuteGenSql
924
925
926
	/**
927
	 * Smarty quote string in sql, by check columns type
928
	 *
929
	 * @param	string	$table
930
	 * @param	string	$column
931
	 * @param	mixed	$val
932
	 * @return	string
933
	 */
934 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...
935
		$this->GetMetaColumn($table);
936
		if (!isset($this->aMetaColumn[$table][$column]->type)) {
937
			error_log("Column to quote not exists($table.$column).\n");
938
			// Return quoted value for safety
939
			$val = stripslashes($val);
940
			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...
941
		}
942
943
		//print_r($this->aMetaColumn[$table][$column]);
944
		$type = $this->aMetaColumn[$table][$column]->type;
945
		//var_dump($type);
946
		if (in_array($type, array(
947
				'bigint',
948
				'bit',
949
				'decimal',
950
				'double',
951
				'float',
952
				'int',
953
				'intn', // Sybase - tinyint
954
				'mediumint',
955
				'numeric',
956
				'numericn',	// Sybase - numeric
957
				'real',
958
				'smallint',
959
				'tinyint',
960
			)))
961
			// Need not quote, output directly
962
			return $val;
963
		// Sybase timestamp
964
		//elseif ($this->IsDbSybase() && 'varbinary' == $type && 'timestamp' == $column)
965
		elseif ($this->IsDbSybase() && 'timestamp' == $type)
966
			return '0x' . $val;
967
		else {
968
			// Need quote, use db's quote method
969
			$val = stripslashes($val);
970
			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...
971
		}
972
	} // end of func GenSqlQuote
973
974
975
	/**
976
	 * If a table exists in db ?
977
	 *
978
	 * @param	string	$tbl
979
	 * @return	boolean
980
	 */
981 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...
982
		if ($this->IsDbSybase()) {
983
			$sql = "select count(1) as c from sysobjects where name = '$tbl' and type = 'U'";
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->fields['c']);
986
		}
987
		elseif ($this->IsDbMysql()) {
988
			$sql = "SHOW TABLES LIKE '$tbl'";
989
			$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...
990
			return (0 != $rs->RowCount());
991
		}
992
		else {
993
			// :NOTICE: Un-tested method
994
			$sql = "select 1 from $tbl";
995
			$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...
996
			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...
997
		}
998
	} // end of func TblExists
999
1000
1001
	/**
1002
	 * Smart write data row(s) to table
1003
	 *
1004
	 * Will auto check row existence, and decide to use INSERT or UPDATE,
1005
	 * so PRIMARY KEY column must include in $data array.
1006
	 * Also, table must have primary key defined.
1007
	 * @param	string	$tbl	Table which rows to write to
1008
	 * @param	array	$data	Row(s) data, only one row(1-dim array, index is column name)
1009
	 * 							or some rows(2-dim array, index layer 1 MUST be number and
1010
	 * 							will not write to db).
1011
	 * @param	string	$mode	A auto detect/U update/I insert, ignore case.
1012
	 * 							If you assign some rows, it's better not to set this to 0,
1013
	 * 							because it will only detect by the FIRST row data.
1014
	 * @return	int		Number of inserted or updated rows, -1 means some error,
1015
	 * 					0 and upper are normal result.
1016
	 */
1017
	public function Write ($tbl, $data, $mode = 'A') {
1018
		// Find primary key column first
1019
		$pk = $this->GetMetaPrimaryKey($tbl);
1020
1021
		// Convert single row data to multi row mode
1022
		if (!isset($data[0]))
1023
			$data = array(0 => $data);
1024
		// Convert primary key to array if it's single string now
1025
		if (!is_array($pk))
1026
			$pk = array(0 => $pk);
1027
1028
		// Columns in $data
1029
		$ar_cols = array_keys($data[0]);
1030
		// Check if primary key is assigned in $data
1031
		$b_data_ok = true;
1032
		foreach ($pk as $key)
1033
			if (!in_array($key, $ar_cols))
1034
				$b_data_ok = false;
1035
		// If no primary key column in $data, return -1
1036
		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...
1037
			return -1;
1038
1039
		$mode = strtoupper($mode);
1040
		// Consider mode if user not assigned
1041 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...
1042
			$s_where = ' WHERE ';
1043
			foreach ($pk as $key)
1044
				$s_where .= " $key = " . $this->QuoteValue($tbl, $key, $data[0][$key])
1045
					. ' AND ';
1046
			$s_where = substr($s_where, 0, strlen($s_where) - 5);
1047
			if (0 < $this->GetRowCount($tbl, $s_where))
1048
				$mode = 'U';
1049
			else
1050
				$mode = 'I';
1051
		}
1052
1053
		// Do batch update or insert, prepare stmt first
1054
		$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...
1055 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...
1056
			$ar_conf = array(
1057
				'UPDATE' => $tbl,
1058
				'LIMIT' => 1,
1059
				);
1060
			foreach ($pk as $key) {
1061
				// Primary key need remove from 'SET' clause
1062
				// Actual value will assign later, do quote then.
1063
				// :NOTICE: Remember to put pk data to end of row data when assign,
1064
				//	because where clause is after set clause.
1065
				$ar_conf['WHERE'][] = "$key = "
1066
					. $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...
1067
				unset($ar_cols[array_search($key, $ar_cols)]);
1068
			}
1069
			// Convert array $ar_cols with to prepare param
1070
			$ar_set = array();
1071
			foreach ($ar_cols as $key)
1072
				$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...
1073
			// Fin, assign 'SET' clause
1074
			$ar_conf['SET'] = $ar_set;
1075
		}
1076
		elseif ('I' == $mode) {
1077
			$ar_set = array();
1078
			foreach ($ar_cols as $key) {
1079
				$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...
1080
			}
1081
			$ar_conf = array(
1082
				'INSERT' => $tbl,
1083
				'VALUES' => $ar_set,
1084
				);
1085
		}
1086
		$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...
1087
1088
		/* Treat moved to  SqlGenerator
1089
		//$sql = $this->GenSql($ar_conf);
1090
		// Remove duplicate ' in sql add by SqlGenerator,
1091
		// Execute after Prepare will auto recoginize variant type and quote,
1092
		// but notice, it's VAR TYPE and NOT DB COLUMN TYPE.
1093
		// replaceQuote: The string used to escape quotes. Eg. double single-quotes for
1094
		// Microsoft SQL, and backslash-quote for MySQL. Used by qstr.
1095
		if ("''" == $this->replaceQuote)
1096
			$s_quote = "'";
1097
		else
1098
			$s_quote = $this->replaceQuote;
1099
		$sql = preg_replace(
1100
			"/ {$s_quote}([\?\:\w\-_]+){$s_quote}([, ])/i",
1101
			" $1$2", $sql);
1102
		*/
1103
1104
		if (!empty($sql)) {
1105
			// Do prepare
1106
			$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...
1107
			// Execute
1108 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...
1109
				foreach ($data as &$row) {
1110
					// Change pk's value position when update mode
1111
					foreach ($pk as $key) {
1112
						$v = $row[$key];
1113
						unset($row[$key]);
1114
						$row[$key] = $v;
1115
					}
1116
				}
1117
				unset($row);
1118
			}
1119
			// Now, finanly, actual write data
1120
			// Auto convert encoding ?
1121
			// Use of prepare we must convert $data manually, because $data is not sql.
1122
			$this->EncodingConvert($data);
1123
			try {
1124
				$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...
1125
			}
1126
			catch (Exception $e) {
1127
				// Show error message ?
1128
				$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...
1129
				return -1;
1130
			}
1131
			// Any error ?
1132 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...
1133
				// Log to error log file
1134
				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...
1135
					. "\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...
1136
					);
1137
				$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...
1138
				return -1;
1139
			}
1140
			else {
1141
				$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...
1142
				return count($data);
1143
			}
1144
		}
1145
		else
1146
			return -1;
1147
	} // end of func Write
1148
1149
1150
} // end of class Adodb
1151
?>
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...
1152