GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

DBCubrid::_createTable()   F
last analyzed

Complexity

Conditions 27
Paths 1754

Size

Total Lines 122

Duplication

Lines 16
Ratio 13.11 %

Importance

Changes 0
Metric Value
cc 27
nc 1754
nop 1
dl 16
loc 122
rs 0
c 0
b 0
f 0

How to fix   Long Method    Complexity   

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
/* Copyright (C) XEHub <https://www.xehub.io> */
3
4
/**
5
 * - DB child class
6
 * - Cubrid DBMS to use the class
7
 * - Works with CUBRID up to 8.4.1
8
 *
9
 * @author XEHub ([email protected])
10
 * @package /classes/db
11
 * @version 0.1
12
 */
13
class DBCubrid extends DB
14
{
15
16
	/**
17
	 * prefix of XE tables(One more XE can be installed on a single DB)
18
	 * @var string
19
	 */
20
	var $prefix = 'xe_';
21
22
	/**
23
	 * max size of constant in CUBRID(if string is larger than this, '...'+'...' should be used)
24
	 * @var int
25
	 */
26
	var $cutlen = 12000;
27
	var $comment_syntax = '/* %s */';
28
29
	/**
30
	 * column type used in CUBRID
31
	 *
32
	 * column_type should be replaced for each DBMS's type
33
	 * becasue it uses commonly defined type in the schema/query xml
34
	 * @var array
35
	 */
36
	var $column_type = array(
37
		'bignumber' => 'numeric(20)',
38
		'number' => 'integer',
39
		'varchar' => 'character varying',
40
		'char' => 'character',
41
		'tinytext' => 'character varying(256)',
42
		'text' => 'character varying(1073741823)',
43
		'bigtext' => 'character varying(1073741823)',
44
		'date' => 'character varying(14)',
45
		'float' => 'float',
46
	);
47
48
	/**
49
	 * constructor
50
	 * @return void
0 ignored issues
show
Comprehensibility Best Practice introduced by
Adding a @return annotation to constructors is generally not recommended as a constructor does not have a meaningful return value.

Adding a @return annotation to a constructor is not recommended, since a constructor does not have a meaningful return value.

Please refer to the PHP core documentation on constructors.

Loading history...
51
	 */
52
	function __construct($auto_connect = TRUE)
53
	{
54
		$this->_setDBInfo();
55
		if($auto_connect) $this->_connect();
56
	}
57
58
	/**
59
	 * Create an instance of this class
60
	 * @return DBCubrid return DBCubrid object instance
61
	 */
62
	function create()
63
	{
64
		return new DBCubrid;
65
	}
66
67
	/**
68
	 * DB Connect
69
	 * this method is private
70
	 * @param array $connection connection's value is db_hostname, db_port, db_database, db_userid, db_password
71
	 * @return resource
72
	 */
73
	function __connect($connection)
74
	{
75
		// attempts to connect
76
		$result = @cubrid_connect($connection["db_hostname"], $connection["db_port"], $connection["db_database"], $connection["db_userid"], $connection["db_password"]);
77
78
		// check connections
79
		if(!$result)
80
		{
81
			$this->setError(-1, 'database connect fail');
82
			return;
83
		}
84
85
		if(!defined('__CUBRID_VERSION__'))
86
		{
87
			$cubrid_version = cubrid_get_server_info($result);
88
			$cubrid_version_elem = explode('.', $cubrid_version);
89
			$cubrid_version = $cubrid_version_elem[0] . '.' . $cubrid_version_elem[1] . '.' . $cubrid_version_elem[2];
90
			define('__CUBRID_VERSION__', $cubrid_version);
91
		}
92
93
		if(__CUBRID_VERSION__ >= '8.4.0')
94
			cubrid_set_autocommit($result, CUBRID_AUTOCOMMIT_TRUE);
95
96
		return $result;
97
	}
98
99
	/**
100
	 * DB disconnection
101
	 * this method is private
102
	 * @param resource $connection
103
	 * @return void
104
	 */
105
	function _close($connection)
106
	{
107
		@cubrid_commit($connection);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
108
		@cubrid_disconnect($connection);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
109
		$this->transaction_started = FALSE;
110
	}
111
112
	/**
113
	 * Handles quatation of the string variables from the query
114
	 * @param string $string
115
	 * @return string
116
	 */
117 View Code Duplication
	function addQuotes($string)
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...
118
	{
119
		if(version_compare(PHP_VERSION, "5.4.0", "<") &&
120
				get_magic_quotes_gpc())
121
		{
122
			$string = stripslashes(str_replace("\\", "\\\\", $string));
123
		}
124
125
		if(!is_numeric($string))
126
		{
127
			/*
128
			  if ($this->isConnected()) {
129
			  $string = cubrid_real_escape_string($string);
130
			  }
131
			  else {
132
			  $string = str_replace("'","\'",$string);
133
			  }
134
			 */
135
136
			$string = str_replace("'", "''", $string);
137
		}
138
139
		return $string;
140
	}
141
142
	/**
143
	 * DB transaction start
144
	 * this method is private
145
	 * @return boolean
146
	 */
147
	function _begin($transactionLevel = 0)
148
	{
149
		if(__CUBRID_VERSION__ >= '8.4.0')
150
		{
151
			$connection = $this->_getConnection('master');
152
153
			if(!$transactionLevel)
154
			{
155
				cubrid_set_autocommit($connection, CUBRID_AUTOCOMMIT_FALSE);
156
			}
157
			else
158
			{
159
				$this->_query("SAVEPOINT SP" . $transactionLevel, $connection);
160
			}
161
		}
162
		return TRUE;
163
	}
164
165
	/**
166
	 * DB transaction rollback
167
	 * this method is private
168
	 * @return boolean
169
	 */
170
	function _rollback($transactionLevel = 0)
171
	{
172
		$connection = $this->_getConnection('master');
173
174
		$point = $transactionLevel - 1;
175
176
		if($point)
177
		{
178
			$this->_query("ROLLBACK TO SP" . $point, $connection);
179
		}
180
		else
181
		{
182
			@cubrid_rollback($connection);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
183
		}
184
185
		return TRUE;
186
	}
187
188
	/**
189
	 * DB transaction commit
190
	 * this method is private
191
	 * @return boolean
192
	 */
193
	function _commit()
194
	{
195
		$connection = $this->_getConnection('master');
196
		@cubrid_commit($connection);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
197
		return TRUE;
198
	}
199
200
	/**
201
	 * Execute the query
202
	 * this method is private
203
	 * @param string $query
204
	 * @param resource $connection
205
	 * @return resource
206
	 */
207
	function __query($query, $connection)
208
	{
209
		if($this->use_prepared_statements == 'Y')
210
		{
211
			$req = @cubrid_prepare($connection, $query);
212
			if(!$req)
213
			{
214
				$this->_setError();
215
				return false;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return false; (false) is incompatible with the return type documented by DBCubrid::__query of type resource.

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...
216
			}
217
218
			$position = 0;
219
			if($this->param)
220
			{
221
				foreach($this->param as $param)
0 ignored issues
show
Bug introduced by
The property param does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
222
				{
223
					$value = $param->getUnescapedValue();
224
					$type = $param->getType();
225
226
					if($param->isColumnName())
227
					{
228
						continue;
229
					}
230
231
					switch($type)
232
					{
233
						case 'number' :
234
							$bind_type = 'numeric';
235
							break;
236
						case 'varchar' :
237
							$bind_type = 'string';
238
							break;
239
						default:
240
							$bind_type = 'string';
241
					}
242
243
					if(is_array($value))
244
					{
245
						foreach($value as $v)
246
						{
247
							$bound = @cubrid_bind($req, ++$position, $v, $bind_type);
248
							if(!$bound)
249
							{
250
								$this->_setError();
251
								return false;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return false; (false) is incompatible with the return type documented by DBCubrid::__query of type resource.

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...
252
							}
253
						}
254
					}
255
					else
256
					{
257
						$bound = @cubrid_bind($req, ++$position, $value, $bind_type);
258
						if(!$bound)
259
						{
260
							$this->_setError();
261
							return false;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return false; (false) is incompatible with the return type documented by DBCubrid::__query of type resource.

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...
262
						}
263
					}
264
				}
265
			}
266
267
			$result = @cubrid_execute($req);
268
			if(!$result)
269
			{
270
				$this->_setError();
271
				return false;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return false; (false) is incompatible with the return type documented by DBCubrid::__query of type resource.

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...
272
			}
273
			return $req;
274
		}
275
		// Execute the query
276
		$result = @cubrid_execute($connection, $query);
277
		// error check
278
		if(!$result)
279
		{
280
			$this->_setError();
281
			return false;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return false; (false) is incompatible with the return type documented by DBCubrid::__query of type resource.

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...
282
		}
283
		// Return the result
284
		return $result;
285
	}
286
287
	/**
288
	 * Retrieve CUBRID error and set to object
289
	 *
290
	 * @author Corina Udrescu ([email protected])
291
	 */
292
	function _setError()
293
	{
294
		$code = cubrid_error_code();
295
		$msg = cubrid_error_msg();
296
297
		$this->setError($code, $msg);
298
	}
299
300
	/**
301
	 * Fetch the result
302
	 * @param resource $result
303
	 * @param int|NULL $arrayIndexEndValue
304
	 * @return array
305
	 */
306
	function _fetch($result, $arrayIndexEndValue = NULL)
307
	{
308
		$output = array();
309
		if(!$this->isConnected() || $this->isError() || !$result)
310
		{
311
			return array();
312
		}
313
314
		if($this->use_prepared_statements == 'Y')
315
		{
316
317
		}
318
319
		// TODO Improve this piece of code
320
		// This code trims values from char type columns
321
		$col_types = cubrid_column_types($result);
322
		$col_names = cubrid_column_names($result);
323
		$max = count($col_types);
324
325
		for($count = 0; $count < $max; $count++)
326
		{
327
			if(preg_match("/^char/", $col_types[$count]) > 0)
328
			{
329
				$char_type_fields[] = $col_names[$count];
0 ignored issues
show
Coding Style Comprehensibility introduced by
$char_type_fields was never initialized. Although not strictly required by PHP, it is generally a good practice to add $char_type_fields = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
330
			}
331
		}
332
333
		while($tmp = cubrid_fetch($result, CUBRID_OBJECT))
334
		{
335
			if(is_array($char_type_fields))
336
			{
337
				foreach($char_type_fields as $val)
0 ignored issues
show
Bug introduced by
The variable $char_type_fields 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...
338
				{
339
					$tmp->{$val} = rtrim($tmp->{$val});
340
				}
341
			}
342
343
			if($arrayIndexEndValue)
0 ignored issues
show
Bug Best Practice introduced by
The expression $arrayIndexEndValue of type integer|null is loosely compared to true; this is ambiguous if the integer can be zero. You might want to explicitly use !== null instead.

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

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
344
			{
345
				$output[$arrayIndexEndValue--] = $tmp;
346
			}
347
			else
348
			{
349
				$output[] = $tmp;
350
			}
351
		}
352
353
		unset($char_type_fields);
354
355
		if($result)
356
		{
357
			cubrid_close_request($result);
358
		}
359
360
		if(count($output) == 1)
361
		{
362
			// If call is made for pagination, always return array
363
			if(isset($arrayIndexEndValue))
364
			{
365
				return $output;
366
			}
367
			// Else return object instead of array
368
			else
369
			{
370
				return $output[0];
371
			}
372
		}
373
		return $output;
374
	}
375
376
	/**
377
	 * Return the sequence value incremented by 1
378
	 * Auto_increment column only used in the CUBRID sequence table
379
	 * @return int
380
	 */
381
	function getNextSequence()
382
	{
383
		$this->_makeSequence();
384
385
		$query = sprintf("select \"%ssequence\".\"nextval\" as \"seq\" from db_root", $this->prefix);
386
		$result = $this->_query($query);
387
		$output = $this->_fetch($result);
0 ignored issues
show
Bug introduced by
It seems like $result defined by $this->_query($query) on line 386 can also be of type null; however, DBCubrid::_fetch() does only seem to accept resource, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
388
389
		return $output->seq;
390
	}
391
392
	/**
393
	 * if the table already exists, set the status to GLOBALS
394
	 * @return void
395
	 */
396
	function _makeSequence()
397
	{
398
		if($_GLOBALS['XE_EXISTS_SEQUENCE'])
0 ignored issues
show
Bug introduced by
The variable $_GLOBALS seems only to be defined at a later point. Did you maybe move this code here without moving the variable definition?

This error can happen if you refactor code and forget to move the variable initialization.

Let’s take a look at a simple example:

function someFunction() {
    $x = 5;
    echo $x;
}

The above code is perfectly fine. Now imagine that we re-order the statements:

function someFunction() {
    echo $x;
    $x = 5;
}

In that case, $x would be read before it is initialized. This was a very basic example, however the principle is the same for the found issue.

Loading history...
399
			return;
400
401
		// check cubrid serial
402
		$query = sprintf('select count(*) as "count" from "db_serial" where name=\'%ssequence\'', $this->prefix);
403
		$result = $this->_query($query);
404
		$output = $this->_fetch($result);
0 ignored issues
show
Bug introduced by
It seems like $result defined by $this->_query($query) on line 403 can also be of type null; however, DBCubrid::_fetch() does only seem to accept resource, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
405
406
		// if do not create serial
407
		if($output->count == 0)
408
		{
409
			$query = sprintf('select max("a"."srl") as "srl" from ' .
410
					'( select max("document_srl") as "srl" from ' .
411
					'"%sdocuments" UNION ' .
412
					'select max("comment_srl") as "srl" from ' .
413
					'"%scomments" UNION ' .
414
					'select max("member_srl") as "srl" from ' .
415
					'"%smember"' .
416
					') as "a"', $this->prefix, $this->prefix, $this->prefix);
417
418
			$result = $this->_query($query);
419
			$output = $this->_fetch($result);
0 ignored issues
show
Bug introduced by
It seems like $result defined by $this->_query($query) on line 418 can also be of type null; however, DBCubrid::_fetch() does only seem to accept resource, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
420
			$srl = $output->srl;
421
			if($srl < 1)
422
			{
423
				$start = 1;
424
			}
425
			else
426
			{
427
				$start = $srl + 1000000;
428
			}
429
430
			// create sequence
431
			$query = sprintf('create serial "%ssequence" start with %s increment by 1 minvalue 1 maxvalue 10000000000000000000000000000000000000 nocycle;', $this->prefix, $start);
432
			$this->_query($query);
433
		}
434
435
		$_GLOBALS['XE_EXISTS_SEQUENCE'] = TRUE;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$_GLOBALS was never initialized. Although not strictly required by PHP, it is generally a good practice to add $_GLOBALS = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
436
	}
437
438
	/**
439
	 * Check a table exists status
440
	 * @param string $target_name
441
	 * @return boolean
442
	 */
443
	function isTableExists($target_name)
444
	{
445
		if($target_name == 'sequence')
446
		{
447
			$query = sprintf("select \"name\" from \"db_serial\" where \"name\" = '%s%s'", $this->prefix, $target_name);
448
		}
449
		else
450
		{
451
			$query = sprintf("select \"class_name\" from \"db_class\" where \"class_name\" = '%s%s'", $this->prefix, $target_name);
452
		}
453
454
		$result = $this->_query($query);
455
		if(cubrid_num_rows($result) > 0)
456
		{
457
			$output = TRUE;
458
		}
459
		else
460
		{
461
			$output = FALSE;
462
		}
463
464
		if($result)
465
		{
466
			cubrid_close_request($result);
467
		}
468
469
		return $output;
470
	}
471
472
	/**
473
	 * Add a column to the table
474
	 * @param string $table_name table name
475
	 * @param string $column_name column name
476
	 * @param string $type column type, default value is 'number'
477
	 * @param int $size column size
478
	 * @param string|int $default default value
479
	 * @param boolean $notnull not null status, default value is false
480
	 * @return void
481
	 */
482
	function addColumn($table_name, $column_name, $type = 'number', $size = '', $default = null, $notnull = FALSE)
483
	{
484
		$type = strtoupper($this->column_type[$type]);
485
		if($type == 'INTEGER')
486
		{
487
			$size = '';
488
		}
489
490
		$query = sprintf("alter class \"%s%s\" add \"%s\" ", $this->prefix, $table_name, $column_name);
491
492
		if($type == 'char' || $type == 'varchar')
493
		{
494
			if($size)
495
			{
496
				$size = $size * 3;
497
			}
498
		}
499
500
		if($size)
501
		{
502
			$query .= sprintf("%s(%s) ", $type, $size);
503
		}
504
		else
505
		{
506
			$query .= sprintf("%s ", $type);
507
		}
508
509
		if(isset($default))
510
		{
511
			if($type == 'INTEGER' || $type == 'BIGINT' || $type == 'INT')
512
			{
513
				$query .= sprintf("default %d ", $default);
514
			}
515
			else
516
			{
517
				$query .= sprintf("default '%s' ", $default);
518
			}
519
		}
520
521
		if($notnull)
522
		{
523
			$query .= "not null ";
524
		}
525
526
		return $this->_query($query);
527
	}
528
529
	/**
530
	 * Drop a column from the table
531
	 * @param string $table_name table name
532
	 * @param string $column_name column name
533
	 * @return void
534
	 */
535
	function dropColumn($table_name, $column_name)
536
	{
537
		$query = sprintf("alter class \"%s%s\" drop \"%s\" ", $this->prefix, $table_name, $column_name);
538
539
		$this->_query($query);
540
	}
541
542
	/**
543
	 * Check column exist status of the table
544
	 * @param string $table_name table name
545
	 * @param string $column_name column name
546
	 * @return boolean
547
	 */
548
	function isColumnExists($table_name, $column_name)
549
	{
550
		$query = sprintf("select \"attr_name\" from \"db_attribute\" where " . "\"attr_name\" ='%s' and \"class_name\" = '%s%s'", $column_name, $this->prefix, $table_name);
551
		$result = $this->_query($query);
552
553
		if(cubrid_num_rows($result) > 0)
554
		{
555
			$output = TRUE;
556
		}
557
		else
558
		{
559
			$output = FALSE;
560
		}
561
562
		if($result)
563
		{
564
			cubrid_close_request($result);
565
		}
566
567
		return $output;
568
	}
569
570
	/**
571
	 * Add an index to the table
572
	 * $target_columns = array(col1, col2)
573
	 * $is_unique? unique : none
574
	 * @param string $table_name table name
575
	 * @param string $index_name index name
576
	 * @param string|array $target_columns target column or columns
577
	 * @param boolean $is_unique
578
	 * @return void
579
	 */
580
	function addIndex($table_name, $index_name, $target_columns, $is_unique = FALSE)
581
	{
582
		if(!is_array($target_columns))
583
		{
584
			$target_columns = array($target_columns);
585
		}
586
587
		$query = sprintf("create %s index \"%s\" on \"%s%s\" (%s);", $is_unique ? 'unique' : '', $index_name, $this->prefix, $table_name, '"' . implode('","', $target_columns) . '"');
588
589
		$this->_query($query);
590
	}
591
592
	/**
593
	 * Drop an index from the table
594
	 * @param string $table_name table name
595
	 * @param string $index_name index name
596
	 * @param boolean $is_unique
597
	 * @return void
598
	 */
599
	function dropIndex($table_name, $index_name, $is_unique = FALSE)
600
	{
601
		$query = sprintf("drop %s index \"%s\" on \"%s%s\"", $is_unique ? 'unique' : '', $index_name, $this->prefix, $table_name);
602
603
		$this->_query($query);
604
	}
605
606
	/**
607
	 * Check index status of the table
608
	 * @param string $table_name table name
609
	 * @param string $index_name index name
610
	 * @return boolean
611
	 */
612 View Code Duplication
	function isIndexExists($table_name, $index_name)
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...
613
	{
614
		$query = sprintf("select \"index_name\" from \"db_index\" where " . "\"class_name\" = '%s%s' and (\"index_name\" = '%s' or \"index_name\" = '%s') ", $this->prefix, $table_name, $this->prefix . $index_name, $index_name);
615
		$result = $this->_query($query);
616
617
		if($this->isError())
618
		{
619
			return FALSE;
620
		}
621
622
		$output = $this->_fetch($result);
0 ignored issues
show
Bug introduced by
It seems like $result defined by $this->_query($query) on line 615 can also be of type null; however, DBCubrid::_fetch() does only seem to accept resource, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
623
624
		if(!$output)
0 ignored issues
show
Bug Best Practice introduced by
The expression $output of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
625
		{
626
			return FALSE;
627
		}
628
		return TRUE;
629
	}
630
631
	/**
632
	 * Delete duplicated index of the table
633
	 * @return boolean
634
	 */
635
	function deleteDuplicateIndexes()
636
	{
637
		$query = sprintf("
638
				select \"class_name\"
639
				, case
640
				when substr(\"index_name\", 0, %d) = '%s'
641
				then substr(\"index_name\", %d)
642
				else \"index_name\" end as unprefixed_index_name
643
				, \"is_unique\"
644
				from \"db_index\"
645
				where \"class_name\" like %s
646
				group by \"class_name\"
647
				, case
648
				when substr(\"index_name\", 0, %d) = '%s'
649
				then substr(\"index_name\", %d)
650
				else \"index_name\"
651
				end
652
				having count(*) > 1
653
				", strlen($this->prefix)
654
				, $this->prefix
655
				, strlen($this->prefix) + 1
656
				, "'" . $this->prefix . '%' . "'"
657
				, strlen($this->prefix)
658
				, $this->prefix
659
				, strlen($this->prefix) + 1
660
		);
661
		$result = $this->_query($query);
662
663
		if($this->isError())
664
		{
665
			return FALSE;
666
		}
667
668
		$output = $this->_fetch($result);
0 ignored issues
show
Bug introduced by
It seems like $result defined by $this->_query($query) on line 661 can also be of type null; however, DBCubrid::_fetch() does only seem to accept resource, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
669
		if(!$output)
0 ignored issues
show
Bug Best Practice introduced by
The expression $output of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
670
		{
671
			return FALSE;
672
		}
673
674
		if(!is_array($output))
675
		{
676
			$indexes_to_be_deleted = array($output);
677
		}
678
		else
679
		{
680
			$indexes_to_be_deleted = $output;
681
		}
682
683
		foreach($indexes_to_be_deleted as $index)
684
		{
685
			$this->dropIndex(substr($index->class_name, strlen($this->prefix))
686
					, $this->prefix . $index->unprefixed_index_name
687
					, $index->is_unique == 'YES' ? TRUE : FALSE);
688
		}
689
690
		return TRUE;
691
	}
692
693
	/**
694
	 * Creates a table by using xml contents
695
	 * @param string $xml_doc xml schema contents
696
	 * @return void|object
697
	 */
698
	function createTableByXml($xml_doc)
699
	{
700
		return $this->_createTable($xml_doc);
701
	}
702
703
	/**
704
	 * Creates a table by using xml file path
705
	 * @param string $file_name xml schema file path
706
	 * @return void|object
707
	 */
708
	function createTableByXmlFile($file_name)
709
	{
710
		if(!file_exists($file_name))
711
		{
712
			return;
713
		}
714
		// read xml file
715
		$buff = FileHandler::readFile($file_name);
716
		return $this->_createTable($buff);
717
	}
718
719
	/**
720
	 * Create table by using the schema xml
721
	 *
722
	 * type : number, varchar, tinytext, text, bigtext, char, date, \n
723
	 * opt : notnull, default, size\n
724
	 * index : primary key, index, unique\n
725
	 * @param string $xml_doc xml schema contents
726
	 * @return void|object
727
	 */
728
	function _createTable($xml_doc)
729
	{
730
		// xml parsing
731
		$oXml = new XmlParser();
732
		$xml_obj = $oXml->parse($xml_doc);
733
		// Create a table schema
734
		$table_name = $xml_obj->table->attrs->name;
735
736
		// if the table already exists exit function
737
		if($this->isTableExists($table_name))
738
		{
739
			return;
740
		}
741
742
		// If the table name is sequence, it creates a serial
743
		if($table_name == 'sequence')
744
		{
745
			$query = sprintf('create serial "%s" start with 1 increment by 1' .
746
					' minvalue 1 ' .
747
					'maxvalue 10000000000000000000000000000000000000' . ' nocycle;', $this->prefix . $table_name);
748
749
			return $this->_query($query);
750
		}
751
752
753
		$table_name = $this->prefix . $table_name;
754
755
		$query = sprintf('create class "%s";', $table_name);
756
		$this->_query($query);
757
758
		if(!is_array($xml_obj->table->column))
759
		{
760
			$columns[] = $xml_obj->table->column;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$columns was never initialized. Although not strictly required by PHP, it is generally a good practice to add $columns = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
761
		}
762
		else
763
		{
764
			$columns = $xml_obj->table->column;
765
		}
766
767
		$query = sprintf("alter class \"%s\" add attribute ", $table_name);
768
769
		$primary_list = array();
770
		$unique_list = array();
771
		$index_list = array();
772
773
		foreach($columns as $column)
774
		{
775
			$name = $column->attrs->name;
776
			$type = $column->attrs->type;
777
			$size = $column->attrs->size;
778
			$notnull = $column->attrs->notnull;
779
			$primary_key = $column->attrs->primary_key;
780
			$index = $column->attrs->index;
781
			$unique = $column->attrs->unique;
782
			$default = $column->attrs->default;
783
784
			switch($this->column_type[$type])
785
			{
786
				case 'integer' :
787
					$size = NULL;
788
					break;
789
				case 'text' :
790
					$size = NULL;
791
					break;
792
			}
793
794
			if(isset($default) && ($type == 'varchar' || $type == 'char' ||
795
					$type == 'text' || $type == 'tinytext' || $type == 'bigtext'))
796
			{
797
				$default = sprintf("'%s'", $default);
798
			}
799
800
			if($type == 'varchar' || $type == 'char')
801
			{
802
				if($size)
803
					$size = $size * 3;
804
			}
805
806
807
			$column_schema[] = sprintf('"%s" %s%s %s %s', $name, $this->column_type[$type], $size ? '(' . $size . ')' : '', isset($default) ? "default " . $default : '', $notnull ? 'not null' : '');
0 ignored issues
show
Coding Style Comprehensibility introduced by
$column_schema was never initialized. Although not strictly required by PHP, it is generally a good practice to add $column_schema = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
808
809
			if($primary_key)
810
			{
811
				$primary_list[] = $name;
812
			}
813
			else if($unique)
814
			{
815
				$unique_list[$unique][] = $name;
816
			}
817
			else if($index)
818
			{
819
				$index_list[$index][] = $name;
820
			}
821
		}
822
823
		$query .= implode(',', $column_schema) . ';';
0 ignored issues
show
Bug introduced by
The variable $column_schema 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...
824
		$this->_query($query);
825
826
		if(count($primary_list))
827
		{
828
			$query = sprintf("alter class \"%s\" add attribute constraint " . "\"pkey_%s\" PRIMARY KEY(%s);", $table_name, $table_name, '"' . implode('","', $primary_list) . '"');
829
			$this->_query($query);
830
		}
831
832 View Code Duplication
		if(count($unique_list))
833
		{
834
			foreach($unique_list as $key => $val)
835
			{
836
				$query = sprintf("create unique index \"%s\" on \"%s\" " . "(%s);", $key, $table_name, '"' . implode('","', $val) . '"');
837
				$this->_query($query);
838
			}
839
		}
840
841 View Code Duplication
		if(count($index_list))
842
		{
843
			foreach($index_list as $key => $val)
844
			{
845
				$query = sprintf("create index \"%s\" on \"%s\" (%s);", $key, $table_name, '"' . implode('","', $val) . '"');
846
				$this->_query($query);
847
			}
848
		}
849
	}
850
851
	/**
852
	 * Handles insertAct
853
	 * @param BaseObject $queryObject
854
	 * @param boolean $with_values
855
	 * @return resource
856
	 */
857 View Code Duplication
	function _executeInsertAct($queryObject, $with_values = TRUE)
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...
858
	{
859
		if($this->use_prepared_statements == 'Y')
860
		{
861
			$this->param = $queryObject->getArguments();
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class BaseObject as the method getArguments() does only exist in the following sub-classes of BaseObject: Query, Subquery. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
862
			$with_values = FALSE;
863
		}
864
		$query = $this->getInsertSql($queryObject, $with_values);
865
		if(is_a($query, 'BaseObject'))
866
		{
867
			unset($this->param);
868
			return;
869
		}
870
871
		$query .= (__DEBUG_QUERY__ & 1 && $this->query_id) ? sprintf(' ' . $this->comment_syntax, $this->query_id) : '';
0 ignored issues
show
Bug introduced by
The property query_id does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
872
873
		$result = $this->_query($query);
874
		if($result && !$this->transaction_started)
875
		{
876
			$this->_commit();
877
		}
878
		unset($this->param);
879
		return $result;
880
	}
881
882
	/**
883
	 * Handles updateAct
884
	 * @param BaseObject $queryObject
885
	 * @param boolean $with_values
886
	 * @return resource
887
	 */
888 View Code Duplication
	function _executeUpdateAct($queryObject, $with_values = TRUE)
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...
889
	{
890
		if($this->use_prepared_statements == 'Y')
891
		{
892
			$this->param = $queryObject->getArguments();
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class BaseObject as the method getArguments() does only exist in the following sub-classes of BaseObject: Query, Subquery. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
893
			$with_values = FALSE;
894
		}
895
		$query = $this->getUpdateSql($queryObject, $with_values);
896
		if(is_a($query, 'BaseObject'))
897
		{
898
			unset($this->param);
899
			return;
900
		}
901
902
		$query .= (__DEBUG_QUERY__ & 1 && $this->query_id) ? sprintf(' ' . $this->comment_syntax, $this->query_id) : '';
903
904
		$result = $this->_query($query);
905
906
		if($result && !$this->transaction_started)
907
		{
908
			$this->_commit();
909
		}
910
		unset($this->param);
911
		return $result;
912
	}
913
914
	/**
915
	 * Handles deleteAct
916
	 * @param BaseObject $queryObject
917
	 * @param boolean $with_values
918
	 * @return resource
919
	 */
920 View Code Duplication
	function _executeDeleteAct($queryObject, $with_values = TRUE)
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...
921
	{
922
		if($this->use_prepared_statements == 'Y')
923
		{
924
			$this->param = $queryObject->getArguments();
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class BaseObject as the method getArguments() does only exist in the following sub-classes of BaseObject: Query, Subquery. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
925
			$with_values = FALSE;
926
		}
927
		$query = $this->getDeleteSql($queryObject, $with_values);
928
		if(is_a($query, 'BaseObject'))
929
		{
930
			unset($this->param);
931
			return;
932
		}
933
934
		$query .= (__DEBUG_QUERY__ & 1 && $this->query_id) ? sprintf(' ' . $this->comment_syntax, $this->query_id) : '';
935
936
		$result = $this->_query($query);
937
938
		if($result && !$this->transaction_started)
939
		{
940
			$this->_commit();
941
		}
942
943
		unset($this->param);
944
		return $result;
945
	}
946
947
	/**
948
	 * Handle selectAct
949
	 * To get a specific page list easily in select statement,
950
	 * a method, navigation, is used
951
	 * @param BaseObject $queryObject
952
	 * @param resource $connection
953
	 * @param boolean $with_values
954
	 * @return BaseObject
955
	 */
956
	function _executeSelectAct($queryObject, $connection = NULL, $with_values = TRUE)
957
	{
958
		if($this->use_prepared_statements == 'Y')
959
		{
960
			$this->param = $queryObject->getArguments();
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class BaseObject as the method getArguments() does only exist in the following sub-classes of BaseObject: Query, Subquery. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
961
			$with_values = FALSE;
962
		}
963
		$limit = $queryObject->getLimit();
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class BaseObject as the method getLimit() does only exist in the following sub-classes of BaseObject: Query, Subquery. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
964
		if($limit && $limit->isPageHandler())
965
		{
966
			return $this->queryPageLimit($queryObject, $connection, $with_values);
0 ignored issues
show
Bug introduced by
It seems like $connection defined by parameter $connection on line 956 can also be of type null; however, DBCubrid::queryPageLimit() does only seem to accept resource, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
967
		}
968
		else
969
		{
970
			$query = $this->getSelectSql($queryObject, $with_values);
971
			if(is_a($query, 'BaseObject'))
972
			{
973
				unset($this->param);
974
				return;
975
			}
976
977
			$query .= (__DEBUG_QUERY__ & 1 && $this->query_id) ? sprintf(' ' . $this->comment_syntax, $this->query_id) : '';
978
			$result = $this->_query($query, $connection);
979
980
			if($this->isError())
981
			{
982
				unset($this->param);
983
				return $this->queryError($queryObject);
984
			}
985
986
			$data = $this->_fetch($result);
0 ignored issues
show
Bug introduced by
It seems like $result defined by $this->_query($query, $connection) on line 978 can also be of type null; however, DBCubrid::_fetch() does only seem to accept resource, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
987
			$buff = new BaseObject();
988
			$buff->data = $data;
0 ignored issues
show
Bug introduced by
The property data does not seem to exist in BaseObject.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
989
990
			unset($this->param);
991
			return $buff;
992
		}
993
	}
994
995
	/**
996
	 * If have a error, return error object
997
	 * @param BaseObject $queryObject
998
	 * @return BaseObject
999
	 */
1000 View Code Duplication
	function queryError($queryObject)
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...
1001
	{
1002
		$limit = $queryObject->getLimit();
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class BaseObject as the method getLimit() does only exist in the following sub-classes of BaseObject: Query, Subquery. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
1003
		if($limit && $limit->isPageHandler())
1004
		{
1005
			$buff = new BaseObject ();
1006
			$buff->total_count = 0;
0 ignored issues
show
Bug introduced by
The property total_count does not seem to exist in BaseObject.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
1007
			$buff->total_page = 0;
0 ignored issues
show
Bug introduced by
The property total_page does not seem to exist in BaseObject.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
1008
			$buff->page = 1;
0 ignored issues
show
Bug introduced by
The property page does not seem to exist in BaseObject.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
1009
			$buff->data = array();
0 ignored issues
show
Bug introduced by
The property data does not seem to exist in BaseObject.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
1010
			$buff->page_navigation = new PageHandler(/* $total_count */0, /* $total_page */1, /* $page */1, /* $page_count */10); //default page handler values
0 ignored issues
show
Bug introduced by
The property page_navigation does not seem to exist in BaseObject.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
1011
			return $buff;
1012
		}else
1013
			return;
1014
	}
1015
1016
	/**
1017
	 * If select query execute, return page info
1018
	 * @param BaseObject $queryObject
1019
	 * @param resource $connection
1020
	 * @param boolean $with_values
1021
	 * @return BaseObject BaseObject with page info containing
1022
	 */
1023
	function queryPageLimit($queryObject, $connection, $with_values)
1024
	{
1025
		$limit = $queryObject->getLimit();
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class BaseObject as the method getLimit() does only exist in the following sub-classes of BaseObject: Query, Subquery. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
1026
		// Total count
1027
		$temp_where = $queryObject->getWhereString($with_values, FALSE);
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class BaseObject as the method getWhereString() does only exist in the following sub-classes of BaseObject: Query, Subquery. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
1028
		$count_query = sprintf('select count(*) as "count" %s %s', 'FROM ' . $queryObject->getFromString($with_values), ($temp_where === '' ? '' : ' WHERE ' . $temp_where));
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class BaseObject as the method getFromString() does only exist in the following sub-classes of BaseObject: Query, Subquery. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
1029
1030
		// Check for distinct query and if found update count query structure
1031
		$temp_select = $queryObject->getSelectString($with_values);
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class BaseObject as the method getSelectString() does only exist in the following sub-classes of BaseObject: Query, Subquery. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
1032
		$uses_distinct = stripos($temp_select, "distinct") !== FALSE;
1033
		$uses_groupby = $queryObject->getGroupByString() != '';
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class BaseObject as the method getGroupByString() does only exist in the following sub-classes of BaseObject: Query, Subquery. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
1034 View Code Duplication
		if($uses_distinct || $uses_groupby)
1035
		{
1036
			$count_query = sprintf('select %s %s %s %s'
1037
					, $temp_select
1038
					, 'FROM ' . $queryObject->getFromString($with_values)
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class BaseObject as the method getFromString() does only exist in the following sub-classes of BaseObject: Query, Subquery. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
1039
					, ($temp_where === '' ? '' : ' WHERE ' . $temp_where)
1040
					, ($uses_groupby ? ' GROUP BY ' . $queryObject->getGroupByString() : '')
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class BaseObject as the method getGroupByString() does only exist in the following sub-classes of BaseObject: Query, Subquery. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
1041
			);
1042
1043
			// If query uses grouping or distinct, count from original select
1044
			$count_query = sprintf('select count(*) as "count" from (%s) xet', $count_query);
1045
		}
1046
1047
		$count_query .= (__DEBUG_QUERY__ & 1 && $queryObject->queryID) ? sprintf(' ' . $this->comment_syntax, $queryObject->queryID) : '';
0 ignored issues
show
Bug introduced by
The property queryID does not seem to exist in BaseObject.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
1048
		$result = $this->_query($count_query, $connection);
1049
		$count_output = $this->_fetch($result);
0 ignored issues
show
Bug introduced by
It seems like $result defined by $this->_query($count_query, $connection) on line 1048 can also be of type null; however, DBCubrid::_fetch() does only seem to accept resource, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
1050
		$total_count = (int) (isset($count_output->count) ? $count_output->count : NULL);
1051
1052
		$list_count = $limit->list_count->getValue();
1053
		if(!$list_count)
1054
		{
1055
			$list_count = 20;
1056
		}
1057
		$page_count = $limit->page_count->getValue();
1058
		if(!$page_count)
1059
		{
1060
			$page_count = 10;
1061
		}
1062
		$page = $limit->page->getValue();
1063
		if(!$page || $page < 1)
1064
		{
1065
			$page = 1;
1066
		}
1067
1068
		// total pages
1069 View Code Duplication
		if($total_count)
1070
		{
1071
			$total_page = (int) (($total_count - 1) / $list_count) + 1;
1072
		}
1073
		else
1074
		{
1075
			$total_page = 1;
1076
		}
1077
1078
		// check the page variables
1079 View Code Duplication
		if($page > $total_page)
1080
		{
1081
			// If requested page is bigger than total number of pages, return empty list
1082
1083
			$buff = new BaseObject();
1084
			$buff->total_count = $total_count;
0 ignored issues
show
Bug introduced by
The property total_count does not seem to exist in BaseObject.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
1085
			$buff->total_page = $total_page;
0 ignored issues
show
Bug introduced by
The property total_page does not seem to exist in BaseObject.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
1086
			$buff->page = $page;
0 ignored issues
show
Bug introduced by
The property page does not seem to exist in BaseObject.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
1087
			$buff->data = array();
0 ignored issues
show
Bug introduced by
The property data does not seem to exist in BaseObject.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
1088
			$buff->page_navigation = new PageHandler($total_count, $total_page, $page, $page_count);
0 ignored issues
show
Bug introduced by
The property page_navigation does not seem to exist in BaseObject.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
1089
			unset($this->param);
1090
			return $buff;
1091
		}
1092
		$start_count = ($page - 1) * $list_count;
1093
1094
		$query = $this->getSelectPageSql($queryObject, $with_values, $start_count, $list_count);
1095
		$query .= (__DEBUG_QUERY__ & 1 && $queryObject->query_id) ? sprintf(' ' . $this->comment_syntax, $this->query_id) : '';
0 ignored issues
show
Bug introduced by
The property query_id does not seem to exist in BaseObject.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
1096
		$result = $this->_query($query, $connection);
1097
		if($this->isError())
1098
		{
1099
			unset($this->param);
1100
			return $this->queryError($queryObject);
1101
		}
1102
1103
		$virtual_no = $total_count - ($page - 1) * $list_count;
1104
		$data = $this->_fetch($result, $virtual_no);
0 ignored issues
show
Bug introduced by
It seems like $result defined by $this->_query($query, $connection) on line 1096 can also be of type null; however, DBCubrid::_fetch() does only seem to accept resource, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
1105
1106
		$buff = new BaseObject();
1107
		$buff->total_count = $total_count;
1108
		$buff->total_page = $total_page;
1109
		$buff->page = $page;
1110
		$buff->data = $data;
1111
		$buff->page_navigation = new PageHandler($total_count, $total_page, $page, $page_count);
1112
		unset($this->param);
1113
		return $buff;
1114
	}
1115
1116
	/**
1117
	 * Return the DBParser
1118
	 * @param boolean $force
1119
	 * @return DBParser
1120
	 */
1121
	function getParser($force = FALSE)
1122
	{
1123
		return new DBParser('"', '"', $this->prefix);
1124
	}
1125
1126
	/**
1127
	 * If select query execute, return paging sql
1128
	 * @param object $query
1129
	 * @param boolean $with_values
1130
	 * @param int $start_count
1131
	 * @param int $list_count
1132
	 * @return string select paging sql
1133
	 */
1134 View Code Duplication
	function getSelectPageSql($query, $with_values = TRUE, $start_count = 0, $list_count = 0)
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...
1135
	{
1136
1137
		$select = $query->getSelectString($with_values);
1138
		if($select == '')
1139
		{
1140
			return new BaseObject(-1, "Invalid query");
1141
		}
1142
		$select = 'SELECT ' . $select;
1143
1144
		$from = $query->getFromString($with_values);
1145
		if($from == '')
1146
		{
1147
			return new BaseObject(-1, "Invalid query");
1148
		}
1149
		$from = ' FROM ' . $from;
1150
1151
		$where = $query->getWhereString($with_values);
1152
		if($where != '')
1153
		{
1154
			$where = ' WHERE ' . $where;
1155
		}
1156
1157
		$groupBy = $query->getGroupByString();
1158
		if($groupBy != '')
1159
		{
1160
			$groupBy = ' GROUP BY ' . $groupBy;
1161
		}
1162
1163
		$orderBy = $query->getOrderByString();
1164
		if($orderBy != '')
1165
		{
1166
			$orderBy = ' ORDER BY ' . $orderBy;
1167
		}
1168
1169
		$limit = $query->getLimitString();
1170
		if($limit != '')
1171
		{
1172
			$limit = sprintf(' LIMIT %d, %d', $start_count, $list_count);
1173
		}
1174
1175
		return $select . ' ' . $from . ' ' . $where . ' ' . $groupBy . ' ' . $orderBy . ' ' . $limit;
1176
	}
1177
1178
}
1179
1180
DBCubrid::$isSupported = function_exists('cubrid_connect');
0 ignored issues
show
Bug introduced by
The property isSupported cannot be accessed from this context as it is declared private in class DB.

This check looks for access to properties that are not accessible from the current context.

If you need to make a property accessible to another context you can either raise its visibility level or provide an accessible getter in the defining class.

Loading history...
1181
1182
/* End of file DBCubrid.class.php */
1183
/* Location: ./classes/db/DBCubrid.class.php */
1184