Completed
Pull Request — master (#85)
by Robbert
87:16 queued 75:50
created

sql_compiler::parse_join_target_properties()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 15
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20
Metric Value
dl 0
loc 15
ccs 0
cts 11
cp 0
rs 9.2
cc 4
eloc 11
nc 3
nop 1
crap 20
1
<?php
2
3
abstract class sql_compiler {
4
	protected $skipDefaultOrderBy;
5
	protected $store;
6
	public  $error;
7
	protected $join_target_properties;
8
	protected $offset;
9
	protected $limit;
10
	protected $cache;
11
	protected $path;
12
	protected $_SCAN_WS        = array(" " => true, "\t" => true, "\n" => true ,"\r" => true);
13
	protected $_SCAN_AZ        = array("a" => true, "A" => true, "b" => true, "B" => true, "c" => true, "C" => true, "d" => true, "D" => true, "e" => true, "E" => true, "f" => true, "F" => true, "g" => true, "G" => true, "h" => true, "H" => true, "i" => true, "I" => true, "j" => true, "J" => true, "k" => true, "K" => true, "l" => true, "L" => true, "m" => true, "M" => true, "n" => true, "N" => true, "o" => true, "O" => true, "p" => true, "P" => true, "q" => true, "Q" => true, "r" => true, "R" => true, "s" => true, "S" => true, "t" => true, "T" => true, "u" => true, "U" => true, "v" => true, "V" => true, "w" => true, "W" => true, "x" => true, "X" => true, "y" => true, "Y" => true, "z" => true, "Z" => true);
14
	protected $_SCAN_AZ_09     = array("a" => true, "A" => true, "b" => true, "B" => true, "c" => true, "C" => true, "d" => true, "D" => true, "e" => true, "E" => true, "f" => true, "F" => true, "g" => true, "G" => true, "h" => true, "H" => true, "i" => true, "I" => true, "j" => true, "J" => true, "k" => true, "K" => true, "l" => true, "L" => true, "m" => true, "M" => true, "n" => true, "N" => true, "o" => true, "O" => true, "p" => true, "P" => true, "q" => true, "Q" => true, "r" => true, "R" => true, "s" => true, "S" => true, "t" => true, "T" => true, "u" => true, "U" => true, "v" => true, "V" => true, "w" => true, "W" => true, "x" => true, "X" => true, "y" => true, "Y" => true, "z" => true, "Z" => true, "_" => true, "0" => true, "1" => true, "2" => true, "3" => true, "4" => true, "5" => true, "6" => true, "7" => true, "8" => true, "9" => true);
15
	protected $_SCAN_NUM       = array("0" => true, "1" => true, "2" => true, "3" => true, "4" => true, "5" => true, "6" => true, "7" => true, "8" => true, "9" => true);
16
	protected $_SCAN_NUM_START = array("0" => true, "1" => true, "2" => true, "3" => true, "4" => true, "5" => true, "6" => true, "7" => true, "8" => true, "9" => true, "-" => true);
17
	protected $_SCAN_CMP       = array("~" => array("=" => array("FIN" => true)), "=" => array("=" => array("FIN" => true), "FIN" => true, "~" => array("FIN" => true, "~" => array("FIN" => true)), "*" => array("FIN" => true, "*" => array("FIN" => true)), "/" => array("FIN" => true)), "!" => array("=" => array("FIN" => true), "~" => array("FIN" => true, "~" => array("FIN" => true)), "*" => array("FIN" => true, "*" => array("FIN" => true)), "/" => array("FIN" => true, "/" => array("FIN" => true))), "<" => array("=" => array("FIN" => true), "FIN" => true), ">" => array("=" => array("FIN" => true), "FIN" => true), "/" => array("=" => array("=" => array("FIN" => true))));
18
19
20 194
	protected function parse_const(&$YYBUFFER) {
21 194
		$YYCURSOR = 0;
22 194
		while (isset($this->_SCAN_WS[$YYBUFFER[$YYCURSOR]])) {
23 194
			$YYCURSOR++;
24 194
		}
25 194
		$value = '';
26 194
		$yych = $YYBUFFER[$YYCURSOR];
27
		switch (true) {
28 194
			case '"' === $yych:
29 194
			case "'" === $yych:
30 192
				$quote = $yych;
31 192
				$yych = $YYBUFFER[++$YYCURSOR];
32 192
				while ($yych !== "\0" && $yych !== $quote) {
33 192
					if ($yych === "\\") {
34 4
						$yych = $YYBUFFER[++$YYCURSOR];
35 4
						if ($yych !== $quote && $yych != "\\") {
36
							$value .= "\\";
37
						}
38 4
					}
39 192
					$value .= $yych;
40 192
					$yych = $YYBUFFER[++$YYCURSOR];
41 192
				}
42 192
				$YYBUFFER = substr($YYBUFFER, $YYCURSOR + 1);
43 192
				$node["id"] = "string";
0 ignored issues
show
Coding Style Comprehensibility introduced by
$node was never initialized. Although not strictly required by PHP, it is generally a good practice to add $node = 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...
44 192
				$node["type"] = ($quote === '"') ? "double" : "single";
45 192
				$node["value"] = stripslashes($value);
46 192
				return $node;
47
			break;
48 2
			case $this->_SCAN_NUM_START[$yych]:
49 2
				$value = $yych;
50 2
				$yych = $YYBUFFER[++$YYCURSOR];
51 2
				while (isset($this->_SCAN_NUM[$yych])) {
52
					$value .= $yych;
53
					$yych = $YYBUFFER[++$YYCURSOR];
54
				}
55 2
				if ($yych === '.') {
56
					$value .= $yych;
57
					$yych = $YYBUFFER[++$YYCURSOR];
58
					while (isset($this->_SCAN_NUM[$yych])) {
59
						$value .= $yych;
60
						$yych = $YYBUFFER[++$YYCURSOR];
61
					}
62
					$node["id"]="float";
0 ignored issues
show
Coding Style Comprehensibility introduced by
$node was never initialized. Although not strictly required by PHP, it is generally a good practice to add $node = 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...
63
					$node["value"]=(float)$value;
64
				} else {
65 2
					$node["id"]="int";
0 ignored issues
show
Coding Style Comprehensibility introduced by
$node was never initialized. Although not strictly required by PHP, it is generally a good practice to add $node = 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...
66 2
					$node["value"]=(int)$value;;
67
				}
68 2
				$YYBUFFER = substr($YYBUFFER, $YYCURSOR);
69 2
				return $node;
70
			break;
71
		}
72
	}
73
74 204
	protected function parse_ident(&$YYBUFFER) {
75
		/* parse identifier regs 1,2 and 3
0 ignored issues
show
Unused Code Comprehensibility introduced by
37% 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...
76
77
			reg[1]: tablename
78
			reg[2]: property name
79
			reg[3]: only used with 'my' properties
80
		*/
81 204
		$reg_id='^[[:space:]]*(([a-z_][a-z0-9_]*)(:[a-z]+)?([.][a-z_][a-z0-9_]*)?([.][a-z_][a-z0-9_]*)?)';
82 204
		$reg_id.='[[:space:]]*';
83
84 204
		$YYCURSOR = 0;
85 204
		while (isset($this->_SCAN_WS[$YYBUFFER[$YYCURSOR]])) {
86 188
			$YYCURSOR++;
87 188
		}
88 204
		$value = '';
89 204
		$yych = $YYBUFFER[$YYCURSOR];
90
91 204
		if ($this->_SCAN_AZ[$yych]) {
92 202
			$value .= $yych;
93 202
			$yych = $YYBUFFER[++$YYCURSOR];
94 202
			while (isset($this->_SCAN_AZ_09[$yych])) {
95 202
				$value .= $yych;
96 202
				$yych = $YYBUFFER[++$YYCURSOR];
97 202
			}
98 202
			$match_1 = $value; $value = '';
99 202
			if ($yych === ':') {
100
				$yych = $YYBUFFER[++$YYCURSOR];
101
				while (isset($this->_SCAN_AZ[$yych])) {
102
					$value .= $yych;
103
					$yych = $YYBUFFER[++$YYCURSOR];
104
				}
105
				$record_id = $value; $value = '';
106
			}
107 202 View Code Duplication
			if ($yych === '.') {
108 196
				$yych = $YYBUFFER[++$YYCURSOR];
109 196
				if ($this->_SCAN_AZ[$yych]) {
110 196
					$value .= $yych;
111 196
					$yych = $YYBUFFER[++$YYCURSOR];
112 196
					while (isset($this->_SCAN_AZ_09[$yych])) {
113 196
						$value .= $yych;
114 196
						$yych = $YYBUFFER[++$YYCURSOR];
115 196
					}
116 196
				}
117 196
				$match_2 = $value; $value = '';
118 196
			}
119 202 View Code Duplication
			if ($yych === '.') {
120
				$yych = $YYBUFFER[++$YYCURSOR];
121
				if ($this->_SCAN_AZ[$yych]) {
122
					$value .= $yych;
123
					$yych = $YYBUFFER[++$YYCURSOR];
124
					while (isset($this->_SCAN_AZ_09[$yych])) {
125
						$value .= $yych;
126
						$yych = $YYBUFFER[++$YYCURSOR];
127
					}
128
				}
129
				$match_3 = $value; $value = '';
0 ignored issues
show
Unused Code introduced by
$value is not used, you could remove the assignment.

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

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

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

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

Loading history...
130
			}
131
132 202
		}
133
134
135 204
		if($match_1) {
136 202
			if (!$match_2) {
0 ignored issues
show
Bug introduced by
The variable $match_2 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...
137
				/* default table is 'object' */
138 54
				$match_2 = $match_1;
0 ignored issues
show
Bug introduced by
The variable $match_1 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...
139 54
				$match_1 = "object";
140 54
			}
141 202
			$node["id"]="ident";
0 ignored issues
show
Coding Style Comprehensibility introduced by
$node was never initialized. Although not strictly required by PHP, it is generally a good practice to add $node = 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...
142
143 202
			$table=$match_1;
144 202
			$field=$match_2;
145 202
			if ($table=="object") {
146
				switch ($field) {
147 192
					case "implements":
148 184
						$node["id"]="implements";
149 184
					break;
150 56
					case "path":
151 56
					case "parent":
152 56
					case "priority":
153 2
						$node["table"]="nodes";
154 2
						$node["field"]=$field;
155 2
					break;
156 56
					default:
157 56
						$node["table"]="objects";
158 56
						$node["field"]=$field;
159 56
				}
160 192
			} else
161 194
			if ($table === "my") {
162
				$node["id"] = "custom";
163
				if ($match_3) {
164
					$node["nls"] = $field;
165
					$field = $match_3;
0 ignored issues
show
Bug introduced by
The variable $match_3 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...
166
				}
167
				$node["field"] = $field;
168
				$node["record_id"] = $record_id;
0 ignored issues
show
Bug introduced by
The variable $record_id 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...
169
			} else {
170 194
				$node["id"]="property";
171 194
				if ($match_3) {
172
					$node["nls"] = $field;
173
					$field = $match_3;
174
				}
175 194
				$node["table"]="prop_".$table;
176 194
				$node["field"]="AR_".$field;
177 194
				$node["record_id"] = $record_id;
178
			}
179 202
		}
180 204
		$YYBUFFER = substr($YYBUFFER, $YYCURSOR);
181 204
		return $node;
0 ignored issues
show
Bug introduced by
The variable $node 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...
182
	}
183
184 200
	protected function parse_cmp_expr(&$YYBUFFER) {
185 200
		$result=$this->parse_ident($YYBUFFER);
186 200
		if ($result) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $result of type array<string,string> 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...
187 198
			$YYCURSOR = 0;
188 198
			while (isset($this->_SCAN_WS[$YYBUFFER[$YYCURSOR]])) {
189 196
				$YYCURSOR++;
190 196
			}
191 198
			$yych = $YYBUFFER[$YYCURSOR];
192 198
			$YYCURSOR_START = $YYCURSOR;
193 198
			$RULES = &$this->_SCAN_CMP;
194 198
			while (isset($RULES[$yych])) {
195 194
				$RULES = &$RULES[$yych];
196 194
				if (isset($RULES['FIN'])) {
197 194
					$YYMATCH = $YYCURSOR;
198 194
				}
199 194
				$yych = $YYBUFFER[++$YYCURSOR];
200 194
			}
201 198
			if (isset($YYMATCH)) {
202 194
					$node["id"]="cmp";
0 ignored issues
show
Coding Style Comprehensibility introduced by
$node was never initialized. Although not strictly required by PHP, it is generally a good practice to add $node = 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...
203 194
					$node["operator"]=substr($YYBUFFER, $YYCURSOR_START, ($YYMATCH + 1) - $YYCURSOR_START);
204 194
					$node["left"]=$result;
205 194
					$YYBUFFER = substr($YYBUFFER, $YYCURSOR);
206 194
					$result=$this->parse_const($YYBUFFER);
207 194
					if ($result) {
208 194
						$node["right"]=$result;
209 194
					}
210 194
					$result=$node;
211 194
			} else {
212 4
				$this->error="unknow compare-operator near '$YYBUFFER'";
213
			}
214 198
		}
215 200
		return $result;
216
	}
217
218 200
	protected function parse_group_expr(&$YYBUFFER) {
219 200
		$YYCURSOR = 0;
220 200
		while (isset($this->_SCAN_WS[$YYBUFFER[$YYCURSOR]])) {
221 188
			$YYCURSOR++;
222 188
		}
223 200
		$yych = $YYBUFFER[$YYCURSOR++];
224 200
		if ($yych === '(') {
225
			$YYBUFFER = substr($YYBUFFER, $YYCURSOR);
226
			$result = $this->parse_or_expr($YYBUFFER);
227
			$YYCURSOR = 0;
228
			while (isset($this->_SCAN_WS[$YYBUFFER[$YYCURSOR]])) {
229
				$YYCURSOR++;
230
			}
231
			$yych = $YYBUFFER[$YYCURSOR++];
232
			if ($yych === ')') {
233
				$YYBUFFER = substr($YYBUFFER, $YYCURSOR);
234
				$node["id"]="group";
0 ignored issues
show
Coding Style Comprehensibility introduced by
$node was never initialized. Although not strictly required by PHP, it is generally a good practice to add $node = 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...
235
				$node["left"]=$result;
236
				$result=$node;
237
			} else {
238
				unset($result);
239
				$this->error = "missing closing group sign near '$YYBUFFER'";
240
			}
241
		} else {
242 200
			$result = $this->parse_cmp_expr($YYBUFFER);
243
		}
244 200
		return $result;
245
	}
246
247 200 View Code Duplication
	protected function parse_and_expr(&$YYBUFFER) {
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...
248 200
		$result=$this->parse_group_expr($YYBUFFER);
249 200
		while (is_array($result)) {
250 198
			$YYCURSOR = 0;
251 198
			while (isset($this->_SCAN_WS[$YYBUFFER[$YYCURSOR]])) {
252 186
				$YYCURSOR++;
253 186
			}
254 198
			$ident = strtolower(substr($YYBUFFER, $YYCURSOR, 3));
255 198
			if ($ident === 'and' && !isset($this->_SCAN_AZ_09[$YYBUFFER[$YYCURSOR + 3]]) ) {
256 184
				$YYBUFFER = substr($YYBUFFER, $YYCURSOR + 3);
257 184
				$right = $this->parse_group_expr($YYBUFFER);
258 184
				if (is_array($right)) {
259
					$result = array(
260 184
						'id' => $ident,
261 184
						'left' => $result,
262
						'right' => $right
263 184
					);
264 184
				} else {
265
					unset($result);
266
				}
267 184
			} else {
268 198
				break;
269
			}
270 184
		}
271 200
		return $result;
272
	}
273
274 200 View Code Duplication
	protected function parse_or_expr(&$YYBUFFER) {
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...
275 200
		$result=$this->parse_and_expr($YYBUFFER);
276 200
		while (is_array($result)) {
277 198
			$YYCURSOR = 0;
278 198
			while (isset($this->_SCAN_WS[$YYBUFFER[$YYCURSOR]])) {
279 50
				$YYCURSOR++;
280 50
			}
281 198
			$ident = strtolower(substr($YYBUFFER, $YYCURSOR, 2));
282 198
			if ($ident === 'or' && !isset($this->_SCAN_AZ_09[$YYBUFFER[$YYCURSOR + 2]]) ) {
283
				$YYBUFFER = substr($YYBUFFER, $YYCURSOR + 2);
284
				$right = $this->parse_and_expr($YYBUFFER);
285
				if (is_array($right)) {
286
					$result = array(
287
						'id' => $ident,
288
						'left' => $result,
289
						'right' => $right
290
					);
291
				} else {
292
					unset($result);
293
				}
294
			} else {
295 198
				break;
296
			}
297
		}
298 200
		return $result;
299
	}
300
301 196
	protected function parse_orderby(&$YYBUFFER) {
302 52
		$field = $this->parse_ident($YYBUFFER);
303
304 52
		$YYCURSOR = 0;
305 124
		while (isset($this->_SCAN_WS[$YYBUFFER[$YYCURSOR]])) {
306 2
			$YYCURSOR++;
307 2
		}
308 52
		$value = '';
309 52
		$yych  = $YYBUFFER[$YYCURSOR];
310 52 View Code Duplication
		if ($this->_SCAN_AZ[$yych]) {
311 2
			$value .= $yych;
312 2
			$yych = $YYBUFFER[++$YYCURSOR];
313 2
			while (isset($this->_SCAN_AZ[$yych])) {
314 2
				$value .= $yych;
315 2
				$yych = $YYBUFFER[++$YYCURSOR];
316 2
			}
317 2
			$sort_type = strtoupper($value);
318 2
			if (!($sort_type == 'ASC' || $sort_type == 'DESC')) { // If sort type is anything else than ASC or DESC, it is not part of the order by.
319 2
				$sort_type = 'ASC';
320 2
				$YYCURSOR = $YYCURSOR - strlen($value);
321 98
				$value = '';
0 ignored issues
show
Unused Code introduced by
$value is not used, you could remove the assignment.

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

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

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

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

Loading history...
322 2
			}
323 2
		} else {
324 50
			$sort_type = 'ASC';
325
		}
326 52
		while (is_array($field)) {
327
			$result = array(
328 124
				'id' => 'orderbyfield',
329 52
				'type' => $sort_type,
330 52
				'right' => $field,
331
				'left' => $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...
332 52
			);
333 52
			while (isset($this->_SCAN_WS[$YYBUFFER[$YYCURSOR]])) {
334
				$YYCURSOR++;
335
			}
336 52
			$yych  = $YYBUFFER[$YYCURSOR];
337 52
			if ($yych !== ',') {
338 52
				$YYBUFFER = substr($YYBUFFER, $YYCURSOR);
339 52
				unset($field);
340 52
			} else {
341 2
				$YYBUFFER = substr($YYBUFFER, $YYCURSOR + 1);
342 2
				$field = $this->parse_ident($YYBUFFER);
343 2
				$YYCURSOR = 0;
344 2
				while (isset($this->_SCAN_WS[$YYBUFFER[$YYCURSOR]])) {
345 96
					$YYCURSOR++;
346
				}
347 2
				$value = '';
348 2
				$yych  = $YYBUFFER[$YYCURSOR];
349 98 View Code Duplication
				if ($this->_SCAN_AZ[$yych]) {
350
					$value .= $yych;
351
					$yych = $YYBUFFER[++$YYCURSOR];
352
					while (isset($this->_SCAN_AZ[$yych])) {
353
						$value .= $yych;
354
						$yych = $YYBUFFER[++$YYCURSOR];
355
					}
356
					$sort_type = strtoupper($value);
357
					if (!($sort_type == 'ASC' || $sort_type == 'DESC')) { // If sort type is anything else than ASC or DESC, it is not part of the order by.
358
						$sort_type = 'ASC';
359
						$YYCURSOR = $YYCURSOR - strlen($value);
360
						$value = '';
0 ignored issues
show
Unused Code introduced by
$value is not used, you could remove the assignment.

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

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

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

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

Loading history...
361
					}
362
				} else {
363 2
					$sort_type = 'ASC';
364
				}
365
			}
366 52
		}
367 52
		return $result;
368
	}
369
370
371
	protected function parse_join_target_properties(&$query) {
372
		do {
373
			if (!preg_match('/^([a-z_][a-z0-9_]*)(:[a-z]+)?/i', $query, $regs)) {
374
				$this->error = "expected property name at '$query'";
375
				return false;
376
			}
377
			$this->join_target_properties["prop_".$regs[1]][$regs[2]] = true;
378
			$query = substr($query, strlen($regs[0]));
379
380
			if (!preg_match('/^[[:space:]]*,[[:space:]]*/', $query, $regs)) {
381
				return true;
382
			}
383
			$query = substr($query, strlen($regs[0]));
384
		} while(1);
385
	}
386
387 204
	protected function parse_query(&$query) {
388
389 204
		if (!preg_match('|^[[:space:]]*order[[:space:]]*by[[:space:]]+|i', $query, $regs)) {
390 200
			$result=$this->parse_or_expr($query);
391 200
		} else {
392 4
			$no_selection = true;
393
		}
394
395
/*
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...
396
		$YYCURSOR = 0;
397
		while ($this->_SCAN_WS[$YYBUFFER[$YYCURSOR]]) {
398
			$YYCURSOR++;
399
		}
400
401
		$yych  = $YYBUFFER[$YYCURSOR];
402
		if ($this->_SCAN_AZ[$yych]) {
403
			$value = $yych;
404
			$yych  = $YYBUFFER[++$YYCURSOR];
405
			while ($this->_SCAN_AZ[$yych]) {
406
				$value .= $yych;
407
				$yych = $YYBUFFER[++$YYCURSOR];
408
			}
409
			$value = strtolower($value);
410
			if ($value === 'order') {
411
				while ($this->_SCAN_WS[$YYBUFFER[$YYCURSOR]]) {
412
					$YYCURSOR++;
413
				}
414
				$yych  = $YYBUFFER[$YYCURSOR];
415
				if ($this->_SCAN_AZ[$yych]) {
416
					$value = $yych;
417
					$yych  = $YYBUFFER[++$YYCURSOR];
418
					while ($this->_SCAN_AZ[$yych]) {
419
						$value .= $yych;
420
						$yych = $YYBUFFER[++$YYCURSOR];
421
					}
422
					$value = strtolower($value);
423
					if ($value === 'by') {
424
						$YYBUFFER = substr($YYBUFFER, $YYCURSOR;
425
						$result = $this->parse_or_expr($YYBUFFER);
426
						$YYCURSOR = 0;
427
						$value = '';
428
					} else {
429
						$this->error = "syntax error near: $YYBUFFER";
430
						return false;
431
					}
432
				}
433
			}
434
		}
435
436
*/
437
438 204
		if (preg_match('|^[[:space:]]*join[[:space:]]*target[[:space:]]*on[[:space:]]*|i', $query, $regs)) {
439
			$this->join_target_properties = array();
440
			$query = substr($query, strlen($regs[0]));
441
			$this->parse_join_target_properties($query);
442
		}
443
444 204
		$matching = preg_match('|^[[:space:]]*order[[:space:]]*by[[:space:]]+|i', $query, $regs);
445 204
		if ( $matching || $no_selection ) {
0 ignored issues
show
Bug introduced by
The variable $no_selection 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...
446 52
			$query=substr($query, strlen($regs[0]));
447 52
			$node["id"]="orderby";
0 ignored issues
show
Coding Style Comprehensibility introduced by
$node was never initialized. Although not strictly required by PHP, it is generally a good practice to add $node = 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...
448 52
			$node["right"]=$this->parse_orderby($query);
449 52
			$node["left"]=$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...
450 52
			$result=$node;
451 52
		}
452 204
		if (preg_match('|^[[:space:]]*limit[[:space:]]+([0-9]+)[[:space:]]*([,][[:space:]]*([0-9]+))?|i', $query, $regs)) {
453 2
			$query=substr($query, strlen($regs[0]));
454 2
			$limit_s["id"]="limit";
0 ignored issues
show
Coding Style Comprehensibility introduced by
$limit_s was never initialized. Although not strictly required by PHP, it is generally a good practice to add $limit_s = 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...
455 2
			$limit_s["offset"]=$regs[1];
456 2
			$limit_s["limit"]=$regs[3];
457 2
		} else {
458 202
			$limit_s["id"]="limit";
0 ignored issues
show
Coding Style Comprehensibility introduced by
$limit_s was never initialized. Although not strictly required by PHP, it is generally a good practice to add $limit_s = 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...
459 202
			$limit_s["offset"]=($this->offset) ? $this->offset : 0;
460 202
			$limit_s["limit"]=($this->limit) ? $this->limit : 0;
461
		}
462 204
		$limit_s["left"]=$result;
463 204
		$result=$limit_s;
464
465 204
		return $result;
466
	}
467
468
	// virtual (&private) method. To be implemented in the sql specific compiler
469
	protected abstract function priv_sql_compile($node) ;
0 ignored issues
show
Coding Style introduced by
The abstract declaration must precede the visibility declaration
Loading history...
470
471 204
	public function compile($path, $query, $limit=100, $offset=0, $layers = array()) {
472 204
		debug("sql_compiler::compile ($path, $query, $limit, $offset)", "store");
473 204
		$this->error="";
474 204
		$this->path = $path;
475
476 204
		$this->limit=$limit;
477 204
		$this->offset=$offset;
478 204
		$this->layers=$layers;
0 ignored issues
show
Bug introduced by
The property layers 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...
479
480 204
		$tree=$this->parse_query($query);
481
482 204
		if ( $this->error ) {
483 4
			return null;
484 200
		} else if ( trim($query) ) {
485
			// no error detected, but there is still a part of the query left
486
			$this->error="unkown operator near '$query'";
487
			return null;
488 200
		} else if ( $tree ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $tree 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...
489 200
			$compiled_query=$this->priv_sql_compile($tree);
490 200
			return $compiled_query;
491
		} else {
492
			return null;
493
		}
494
495
	}
496
497
498
  }
499