Completed
Push — master ( 60ba61...279e03 )
by Auke
87:58 queued 69:03
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 42.28%
Metric Value
wmc 82
lcom 1
cbo 1
dl 153
loc 352
ccs 126
cts 298
cp 0.4228
rs 4.8717

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 144
	function __construct(&$store, $tbl_prefix="") {
20 144
		debug("postgresql_compiler($tbl_prefix)", "store");
21 144
		$this->tbl_prefix=$tbl_prefix;
22 144
		$this->store=$store;
23 144
	}
24
25 144
	function test_for_lowercase(&$node){
26 144
		$ret = false;
27 144
		switch ((string)$node["id"]) {
28 144
			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 144
		return $ret;
37
	}
38
39 144
	function compile_tree(&$node) {
40 144
		switch ((string)$node["id"]) {
41 144
			case 'property':
42 144
				$table=$this->tbl_prefix.$node["table"];
43 144
				$field=$node["field"];
44 144
				$record_id=$node["record_id"];
45 144
				if (!$record_id) {
46 144
					if (!$this->in_orderby) {
47 144
						$result=" $table.object = ".$this->tbl_prefix."objects.id and $table.$field ";
48 144
						$this->used_tables[$table]=$table;
49 96 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 48
							$result=" $table.$field ";
69
						}
70
					}
71 96
				} 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 144
			break;
81 144 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 144 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 144
			case 'string':
137 144
				$result=" '".pg_escape_string($node["value"])."' ";
138 144
			break;
139 144
			case 'float':
140 144
			case 'int':
141
				$result=" ".$node["value"]." ";
142
			break;
143 144 View Code Duplication
			case 'and':
144 138
				$cr = $this->custom_ref;
145 138
				$left=$this->compile_tree($node["left"]);
146 138
				if ($this->custom_ref > $cr) {
147
					$this->custom_id++;
148
				}
149
150 138
				$right=$this->compile_tree($node["right"]);
151 138
				$cr = $this->custom_ref;
152 138
				if ($this->custom_ref > $cr) {
153
					$this->custom_id++;
154
				}
155 138
				$result=" $left and $right ";
156 138
			break;
157 144 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 144
			case 'cmp':
163 144
				$not = '';
164 144
				switch ($node["operator"]) {
165 144
					case '=':
166 96
					case '==':
167 144
						$operator="=";
168 144
					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 96
				}
198 144
				if ($node["left"]["id"]!=="implements") {
199 144
					$left=$this->compile_tree($node["left"]);
200 144
					$right=$this->compile_tree($node["right"]);
201 144
					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 144
						if ($node["left"]["field"]=="lastchanged") {
208
							$right = "to_timestamp($right)";
209
						}
210 144
						$result=" $left $operator $right ";
211
					}
212 96
				} else {
213 138
					$table=$this->tbl_prefix."types";
214 138
					$type=$this->compile_tree($node["right"]);
215
					switch ($operator) {
216 138 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 92
						default:
220 138
							$this->used_tables[$table]=$table;
221 138
							$result=" (".$this->tbl_prefix."types.implements $operator $type and ".$this->tbl_prefix."objects.vtype = ".$this->tbl_prefix."types.type ) ";
222 138
						break;
223 92
					}
224
				}
225 144
			break;
226 144 View Code Duplication
			case 'group':
227
				$left=$this->compile_tree($node["left"]);
228
				if ($left) {
229
					$result=" ( $left ) ";
230
				}
231
			break;
232
233 144 View Code Duplication
			case 'orderby':
234 36
				$result=$this->compile_tree($node["left"]);
235 36
				$this->orderby_s=$this->compile_tree($node["right"]);
236 36
			break;
237
238 144
			case 'orderbyfield':
239 36
				$this->in_orderby = true;
240 36
				$left=$this->compile_tree($node["left"]);
241 36
				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 36
					$result = "";
258 36
					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 36
					$this->skipDefaultOrderBy = true;
266
				}
267 36
			break;
268
269 144 View Code Duplication
			case 'limit':
270 144
				$this->where_s=$this->compile_tree($node["left"]);
271 144
				$this->limit_s="";
272 144
				if ($node["limit"]) {
273 144
					$this->limit_s=" offset ".(int)$node["offset"]." limit ".$node["limit"]." ";
274 96
				} else
275 36
				if ($node["offset"]) {
276
					$this->limit_s=" limit ".(int)$node["offset"]." ";
277
				} else {
278 36
					if ($this->limit) {
279
						$offset = (int)$this->offset;
280
						$this->limit_s=" offset $offset limit ".(int)$this->limit." ";
281
					}
282
				}
283 144
			break;
284
		}
285 144
		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 144
	function priv_sql_compile($tree) {
290 144
		$this->custom_ref = 0;
291 144
		$this->custom_id = 0;
292 144
		$this->used_tables="";
293 144
		$this->compile_tree($tree);
294
295 144
		if ( $this->error ) {
296
			return null;
297
		}
298
299 144
		$nodes=$this->tbl_prefix."nodes";
300 144
		$objects=$this->tbl_prefix."objects";
301 144
		$this->used_tables[$nodes]=$nodes;
302 144
		$this->used_tables[$objects]=$objects;
303 144
		@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 144
		while (list($key, $val)=each($this->used_tables)) {
305 144
			if ($tables) {
306 144
				$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 96
			} else {
308 144
				$tables="$key";
309
			}
310 144
			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 96
		}
314 144
		if (is_array($this->nls_join)) {
315
			$join = join($this->nls_join);
316
		}
317 144
		if(is_array($this->select_list)){
318
			$select = join(", ", $this->select_list);
319
		}
320
321 144
		$query ="where $nodes.object=$objects.id $prop_dep";
322 144
		$query.=" and $nodes.path like '".str_replace('_','\\_',pg_escape_string($this->path))."%' ";
323 144
		if ($this->where_s) {
324 144
			$query.=" and ( $this->where_s ) ";
325 96
		}
326 144
		if ($this->where_s_ext) {
327
			$query .= " and ($this->where_s_ext) ";
328
		}
329 144
		$order = '';
330 144
		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 144
		} else if (!$this->skipDefaultOrderBy) {
337 144
			$order .= "order by $nodes.parent ASC, $nodes.priority DESC, $nodes.path ASC ";
338 96
		}
339
340 144
		$order .= " $this->limit_s ";
341
342 144
		$select_query  = "select distinct($nodes.path), $nodes.parent, $nodes.priority, ";
343 144
		$select_query .= " $objects.id, $objects.type, $objects.object, date_part('epoch', $objects.lastchanged) as lastchanged, $objects.vtype ";
344
345 144
		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 144
		$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 144
		$count_query = "select count(distinct($nodes.path)) as count from $tables ".$query;
351
352 144
		return Array("select_query" => $select_query, "count_query" => $count_query);
353
	}
354
355
  }
356