Completed
Pull Request — master (#119)
by Robbert
08:44
created

postgresql_compiler   D

Complexity

Total Complexity 82

Size/Duplication

Total Lines 352
Duplicated Lines 43.47 %

Coupling/Cohesion

Components 1
Dependencies 1

Test Coverage

Coverage 41.95%

Importance

Changes 0
Metric Value
dl 153
loc 352
rs 4.8717
c 0
b 0
f 0
ccs 125
cts 298
cp 0.4195
wmc 82
lcom 1
cbo 1

4 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
B test_for_lowercase() 0 13 5
D compile_tree() 148 248 63
F priv_sql_compile() 5 65 13

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like postgresql_compiler often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

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

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

1
<?php
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 4 and the first side effect is on line 2.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
2
include($this->code."stores/modules/sql_compiler.php");
3
4
class postgresql_compiler extends sql_compiler {
5
	protected $tbl_prefix;
6
	protected $in_orderby;
7
	protected $nls_join;
8
	protected $select_tables;
9
	protected $used_tables;
10
	protected $custom_id;
11
	protected $custom_ref;
12
	protected $used_custom_fields;
13
	protected $where_s_ext;
14
	protected $where_s;
15
	protected $limit_s;
16
	protected $orderby_s;
17
	protected $select_list;
18
19 48
	function __construct(&$store, $tbl_prefix="") {
20 48
		debug("postgresql_compiler($tbl_prefix)", "store");
21 48
		$this->tbl_prefix=$tbl_prefix;
22 48
		$this->store=$store;
23 48
	}
24
25 48
	function test_for_lowercase(&$node){
26 48
		$ret = false;
27 48
		switch ((string)$node["id"]) {
28 48
			case 'ident':
29
				if ( $node["table"] == "nodes" ) {
30
					if ( $node["field"] == "path" or $node["field"] == "parent" ) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as or instead of || is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
31
						$ret = true;
32
					}
33
				}
34
				break;
35
		}
36 48
		return $ret;
37
	}
38
39 48
	function compile_tree(&$node) {
40 48
		switch ((string)$node["id"]) {
41 48
			case 'property':
42 48
				$table=$this->tbl_prefix.$node["table"];
43 48
				$field=$node["field"];
44 48
				$record_id=$node["record_id"];
45 48
				if (!$record_id) {
46 48
					if (!$this->in_orderby) {
47 48
						$result=" $table.object = ".$this->tbl_prefix."objects.id and $table.$field ";
48 48
						$this->used_tables[$table]=$table;
49 48 View Code Duplication
					} else {
50
						if ($this->in_orderby && $node["nls"]) {
51
							/*
52
								we do a left join so that we will also find non
53
								matching objects
54
							*/
55
							$objects_table = $this->tbl_prefix."objects";
56
							$this->nls_join[$table] = "left join $table as order_$table on $objects_table.id=order_$table.object and order_$table.AR_nls='".$node["nls"]."' ";
57
58
							$result = " order_$table.$field ";
59
							$this->select_list["order_".$table.".".$field] = "order_$table.$field";
60
61
						} else {
62
							/*
63
								if we are parsing 'orderby' properties we have
64
								to join our tables for the whole query
65
							*/
66
							$this->select_tables[$table]=$table;
67
							$this->used_tables[$table]=$table;
68
							$result=" $table.$field ";
69
						}
70
					}
71 48
				} else {
72
					$this->used_tables["$table as $table$record_id"] = $table.$record_id;
73
					if (!$this->in_orderby) {
74
						$result=" $table$record_id.object = ".$this->tbl_prefix."objects.id and $table$record_id.$field ";
75
					} else {
76
						$this->select_tables["$table as $table$record_id"] = $table.$record_id;
77
						$result=" $table$record_id.$field ";
78
					}
79
				}
80 48
			break;
81 48 View Code Duplication
			case 'ident':
82
				$table=$this->tbl_prefix.$node["table"];
83
				$field=$node["field"];
84
				$this->used_tables[$table]=$table;
85
				$result=" $table.$field ";
86
			break;
87 48 View Code Duplication
			case 'custom':
88
				$table = $this->tbl_prefix."prop_custom";
89
				$field = $node["field"];
90
				$nls = $node["nls"];
91
				$record_id = $node["record_id"];
92
				/*
93
					when we are compiling orderby properties we always want
94
					to assign it to a new table alias
95
				*/
96
				if ($this->in_orderby) {
97
					$this->custom_id++;
98
				}
99
				$this->custom_ref++;
100
				if (!$record_id) {
101
					$this->used_tables[$table." as $table".$this->custom_id] = $table.$this->custom_id;
102
					$this->select_tables[$table." as $table".$this->custom_id] = 1;
103
104
					$this->used_custom_fields[$field] = true;
105
					$result = " $table".$this->custom_id.".AR_name = '$field' ";
106
					if ($nls) {
107
						$result = " $result and $table".$this->custom_id.".AR_nls = '$nls' ";
108
					}
109
110
					if (!$this->in_orderby) {
111
						$result = " $result and $table".$this->custom_id.".AR_value ";
112
					} else {
113
						$this->where_s_ext = $result;
114
						$result = " $table".$this->custom_id.".AR_value ";
115
					}
116
				} else {
117
					$this->used_tables["$table as $table$record_id"] = $table.$record_id;
118
			//		$this->select_tables[$table." as $table$record_id"] = 1;
0 ignored issues
show
Unused Code Comprehensibility introduced by
58% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
119
120
					$result = " $table$record_id.AR_name = '$field' ";
121
					if (!$this->in_orderby ) {
122
						if ($this->join_target_properties["prop_my"][":$record_id"]) {
123
							$result=" $result and $table$record_id.object = target.object and $table$record_id.AR_value ";
124
						} else {
125
							$result=" $table$record_id.object = ".$this->tbl_prefix."objects.id and $table$record_id.AR_value ";
126
						}
127
					} else {
128
						if ($this->join_target_properties[$node["table"]]) {
129
							$this->join_target_properties["$table as $table$record_id"] = $table.$record_id;
130
						}
131
						$this->select_tables["$table as $table$record_id"] = $table.$record_id;
132
						$result=" $table$record_id.AR_value ";
133
					}
134
				}
135
			break;
136 48
			case 'string':
137 48
				$result=" '".pg_escape_string($node["value"])."' ";
138 48
			break;
139 48
			case 'float':
140 48
			case 'int':
141
				$result=" ".$node["value"]." ";
142
			break;
143 48 View Code Duplication
			case 'and':
144 46
				$cr = $this->custom_ref;
145 46
				$left=$this->compile_tree($node["left"]);
146 46
				if ($this->custom_ref > $cr) {
147
					$this->custom_id++;
148
				}
149
150 46
				$right=$this->compile_tree($node["right"]);
151 46
				$cr = $this->custom_ref;
152 46
				if ($this->custom_ref > $cr) {
153
					$this->custom_id++;
154
				}
155 46
				$result=" $left and $right ";
156 46
			break;
157 48 View Code Duplication
			case 'or':
158
				$left=$this->compile_tree($node["left"]);
159
				$right=$this->compile_tree($node["right"]);
160
				$result=" $left or $right ";
161
			break;
162 48
			case 'cmp':
163 48
				$not = '';
164 48
				switch ($node["operator"]) {
165 48
					case '=':
166 48
					case '==':
167 48
						$operator="=";
168 48
					break;
169
					case '!=':
170
					case '<=':
171
					case '>=':
172
					case '<':
173
					case '>':
174
						$operator=$node["operator"];
175
					break;
176
					case '!~':
177
					case '!~~':
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
178
						$not="NOT ";
179
 					case '~=':
180
					case '=~':
181 View Code Duplication
					case '=~~':
182
						if (!strlen($node["operator"])==3) {
183
							$not.="I";
184
						}
185
						$operator=$not."LIKE";
186
					break;
187
					case '!/':
188
					case '!//':
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
189
						$not="!";
190
					case '=/':
191 View Code Duplication
					case '=//':
192
						$operator=$not."~";
193
						if (strlen($node["operator"])==3) {
194
							$operator.="*";
195
						}
196
						break;
197 48
				}
198 48
				if ($node["left"]["id"]!=="implements") {
199 48
					$left=$this->compile_tree($node["left"]);
200 48
					$right=$this->compile_tree($node["right"]);
201 48
					if($this->test_for_lowercase($node["left"])){
202
						// lowercase compile
203
						$result=" lower($left) $operator lower($right) ";
0 ignored issues
show
Bug introduced by
The variable $operator 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...
204
					} else {
205
						// normal compile
206
						/* lastchanged == unixtimestamp -> lastchanged == 200201.. */
207 48
						if ($node["left"]["field"]=="lastchanged") {
208
							$right = "to_timestamp($right)";
209
						}
210 48
						$result=" $left $operator $right ";
211
					}
212 48
				} else {
213 46
					$table=$this->tbl_prefix."types";
214 46
					$type=$this->compile_tree($node["right"]);
215
					switch ($operator) {
216 46 View Code Duplication
						case '!=':
217
							$result=" (".$this->tbl_prefix."objects.type not in (select type from ".$this->tbl_prefix."types where implements = $type )) ";
218
						break;
219 46
						default:
220 46
							$this->used_tables[$table]=$table;
221 46
							$result=" (".$this->tbl_prefix."types.implements $operator $type and ".$this->tbl_prefix."objects.vtype = ".$this->tbl_prefix."types.type ) ";
222 46
						break;
223 46
					}
224
				}
225 48
			break;
226 48 View Code Duplication
			case 'group':
227
				$left=$this->compile_tree($node["left"]);
228
				if ($left) {
229
					$result=" ( $left ) ";
230
				}
231
			break;
232
233 48 View Code Duplication
			case 'orderby':
234 12
				$result=$this->compile_tree($node["left"]);
235 12
				$this->orderby_s=$this->compile_tree($node["right"]);
236 12
			break;
237
238 48
			case 'orderbyfield':
239 12
				$this->in_orderby = true;
240 12
				$left=$this->compile_tree($node["left"]);
241 12
				if ( $node["right"]["field"] != "none" ) {
242
					$right=$this->compile_tree($node["right"]);
243
					if ($left) {
244
						$result=" $left ,  $right ".$node["type"]." ";
245 View Code Duplication
						if($node["left"]['id'] == 'property' && !$node["right"]['nls']){
246
							$lefttablefield = $this->tbl_prefix.$node["left"]['table'].".".$node["left"]['field'];
247
							$this->select_list[$lefttablefield] = $lefttablefield;
248
						}
249
					} else {
250
						$result=" $right ".$node["type"]." ";
251
					}
252 View Code Duplication
					if($node["right"]['id'] == 'property' && !$node["right"]['nls']){
253
						$righttablefield = $this->tbl_prefix.$node["right"]['table'].".".$node["right"]['field'];
254
						$this->select_list[$righttablefield] = $righttablefield;
255
					}
256
				} else {
257 12
					$result = "";
258 12
					if ($left) {
259
						$result = " $left ";
260 View Code Duplication
						if($node["left"]['id'] == 'property' && !$node["right"]['nls']){
261
							$lefttablefield = $this->tbl_prefix.$node["left"]['table'].".".$node["left"]['field'];
262
							$this->select_list[$lefttablefield] = $lefttablefield;
263
						}
264
					}
265 12
					$this->skipDefaultOrderBy = true;
266
				}
267 12
			break;
268
269 48 View Code Duplication
			case 'limit':
270 48
				$this->where_s=$this->compile_tree($node["left"]);
271 48
				$this->limit_s="";
272 48
				if ($node["limit"]) {
273 48
					$this->limit_s=" offset ".(int)$node["offset"]." limit ".$node["limit"]." ";
274 48
				} else
275 12
				if ($node["offset"]) {
276
					$this->limit_s=" limit ".(int)$node["offset"]." ";
277
				} else {
278 12
					if ($this->limit) {
279
						$offset = (int)$this->offset;
280
						$this->limit_s=" offset $offset limit ".(int)$this->limit." ";
281
					}
282
				}
283 48
			break;
284
		}
285 48
		return $result;
0 ignored issues
show
Bug introduced by
The variable $result 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...
286
	}
287
288
	// postgresql specific compiler function
289 48
	function priv_sql_compile($tree) {
290 48
		$this->custom_ref = 0;
291 48
		$this->custom_id = 0;
292 48
		$this->used_tables="";
293 48
		$this->compile_tree($tree);
294
295 48
		if ( $this->error ) {
296
			return null;
297
		}
298
299 48
		$nodes=$this->tbl_prefix."nodes";
300 48
		$objects=$this->tbl_prefix."objects";
301 48
		$this->used_tables[$nodes]=$nodes;
302 48
		$this->used_tables[$objects]=$objects;
303 48
		@reset($this->used_tables);
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...
304 48
		while (list($key, $val)=each($this->used_tables)) {
305 48
			if ($tables) {
306 48
				$tables.=", $key";
0 ignored issues
show
Bug introduced by
The variable $tables 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...
307 48
			} else {
308 48
				$tables="$key";
309
			}
310 48
			if ($this->select_tables[$key]) {
311
				$prop_dep.=" and $val.object=$objects.id ";
0 ignored issues
show
Bug introduced by
The variable $prop_dep 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...
312
			}
313 48
		}
314 48
		if (is_array($this->nls_join)) {
315
			$join = join($this->nls_join);
316
		}
317 48
		if(is_array($this->select_list)){
318
			$select = join(", ", $this->select_list);
319
		}
320
321 48
		$query ="where $nodes.object=$objects.id $prop_dep";
322 48
		$query.=" and $nodes.path like '".str_replace('_','\\_',pg_escape_string($this->path))."%' ";
323 48
		if ($this->where_s) {
324 48
			$query.=" and ( $this->where_s ) ";
325 48
		}
326 48
		if ($this->where_s_ext) {
327
			$query .= " and ($this->where_s_ext) ";
328
		}
329 48
		$order = '';
330 48
		if ($this->orderby_s) {
331 View Code Duplication
			if ($this->skipDefaultOrderBy) {
332
				$order .= "order by $this->orderby_s";
333
			} else {
334
				$order .= "order by $this->orderby_s, $nodes.parent ASC, $nodes.priority DESC, $nodes.path ASC ";
335
			}
336 48
		} else if (!$this->skipDefaultOrderBy) {
337 48
			$order .= "order by $nodes.parent ASC, $nodes.priority DESC, $nodes.path ASC ";
338 48
		}
339
340 48
		$order .= " $this->limit_s ";
341
342 48
		$select_query  = "select distinct($nodes.path), $nodes.parent, $nodes.priority, ";
343 48
		$select_query .= " $objects.id, $objects.type, $objects.object, date_part('epoch', $objects.lastchanged) as lastchanged, $objects.vtype ";
344
345 48
		if($select){
346
			$select_query .= ", " . $select;
0 ignored issues
show
Bug introduced by
The variable $select 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...
347
		}
348
349 48
		$select_query .= " from $tables $join $query $order";
0 ignored issues
show
Bug introduced by
The variable $join 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...
350 48
		$count_query = "select count(distinct($nodes.path)) as count from $tables ".$query;
351
352 48
		return Array("select_query" => $select_query, "count_query" => $count_query);
353
	}
354
355
  }
356