Completed
Push — 7.0-syntax-fixes ( ccbc92 )
by
unknown
535:45 queued 529:05
created

sql_compiler::parse_orderby()   C

Complexity

Conditions 14
Paths 138

Size

Total Lines 68
Code Lines 54

Duplication

Lines 32
Ratio 47.06 %

Code Coverage

Tests 45
CRAP Score 20.9416

Importance

Changes 0
Metric Value
cc 14
eloc 54
nc 138
nop 1
dl 32
loc 68
ccs 45
cts 67
cp 0.6716
crap 20.9416
rs 5.2791
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
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 42
	protected function parse_const(&$YYBUFFER) {
21 42
		$YYCURSOR = 0;
22 42
		while (isset($this->_SCAN_WS[$YYBUFFER[$YYCURSOR]])) {
23 6
			$YYCURSOR++;
24 6
		}
25 42
		$value = '';
26 42
		$yych = $YYBUFFER[$YYCURSOR];
27
		switch (true) {
28 42
			case '"' === $yych:
29 42
			case "'" === $yych:
30 40
				$quote = $yych;
31 40
				$yych = $YYBUFFER[++$YYCURSOR];
32 40
				while ($yych !== "\0" && $yych !== $quote) {
33 40
					if ($yych === "\\") {
34 14
						$yych = $YYBUFFER[++$YYCURSOR];
35 2
						if ($yych !== $quote && $yych != "\\") {
36
							$value .= "\\";
37
						}
38 14
					}
39 40
					$value .= $yych;
40 40
					$yych = $YYBUFFER[++$YYCURSOR];
41 40
				}
42 40
				$YYBUFFER = substr($YYBUFFER, $YYCURSOR + 1);
43 40
				$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 40
				$node["type"] = ($quote === '"') ? "double" : "single";
45 40
				$node["value"] = stripslashes($value);
46 40
				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 1
					$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 47
	protected function parse_ident(&$YYBUFFER) {
75
		/* parse identifier regs 1,2 and 3
76
77
			reg[1]: tablename
78
			reg[2]: property name
79
			reg[3]: only used with 'my' properties
80
		*/
81 47
		$reg_id='^[[:space:]]*(([a-z_][a-z0-9_]*)(:[a-z]+)?([.][a-z_][a-z0-9_]*)?([.][a-z_][a-z0-9_]*)?)';
82 47
		$reg_id.='[[:space:]]*';
83
84 47
		$YYCURSOR = 0;
85 47
		while (isset($this->_SCAN_WS[$YYBUFFER[$YYCURSOR]])) {
86 2
			$YYCURSOR++;
87 2
		}
88 47
		$value = '';
89 47
		$yych = $YYBUFFER[$YYCURSOR];
90
91 47
		if ($this->_SCAN_AZ[$yych]) {
92 46
			$value .= $yych;
93 46
			$yych = $YYBUFFER[++$YYCURSOR];
94 46
			while (isset($this->_SCAN_AZ_09[$yych])) {
95 46
				$value .= $yych;
96 46
				$yych = $YYBUFFER[++$YYCURSOR];
97 46
			}
98 46
			$match_1 = $value; $value = '';
99 46
			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 46 View Code Duplication
			if ($yych === '.') {
108 43
				$yych = $YYBUFFER[++$YYCURSOR];
109 43
				if ($this->_SCAN_AZ[$yych]) {
110 43
					$value .= $yych;
111 43
					$yych = $YYBUFFER[++$YYCURSOR];
112 43
					while (isset($this->_SCAN_AZ_09[$yych])) {
113 43
						$value .= $yych;
114 43
						$yych = $YYBUFFER[++$YYCURSOR];
115 43
					}
116 43
				}
117 43
				$match_2 = $value; $value = '';
118 43
			}
119 46 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 46
		}
133
134
135 47
		if($match_1) {
136 46
			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 39
				$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 39
				$match_1 = "object";
140 39
			}
141 46
			$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 46
			$table=$match_1;
144 46
			$field=$match_2;
145 46
			if ($table=="object") {
146
				switch ($field) {
147 41
					case "implements":
148
						$node["id"]="implements";
149
					break;
150 41
					case "path":
151 41
					case "parent":
152 41
					case "priority":
153 1
						$node["table"]="nodes";
154 1
						$node["field"]=$field;
155 1
					break;
156 41
					default:
157 41
						$node["table"]="objects";
158 41
						$node["field"]=$field;
159 41
				}
160 41
			} else
161 41
			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 41
				$node["id"]="property";
171 41
				if ($match_3) {
172
					$node["nls"] = $field;
173
					$field = $match_3;
174
				}
175 41
				$node["table"]="prop_".$table;
176 41
				$node["field"]="AR_".$field;
177 41
				$node["record_id"] = $record_id;
178
			}
179 46
		}
180 47
		$YYBUFFER = substr($YYBUFFER, $YYCURSOR);
181 47
		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 45
	protected function parse_cmp_expr(&$YYBUFFER) {
185 45
		$result=$this->parse_ident($YYBUFFER);
186 45
		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 44
			$YYCURSOR = 0;
188 44
			while (isset($this->_SCAN_WS[$YYBUFFER[$YYCURSOR]])) {
189 7
				$YYCURSOR++;
190 7
			}
191 44
			$yych = $YYBUFFER[$YYCURSOR];
192 44
			$YYCURSOR_START = $YYCURSOR;
193 44
			$RULES = &$this->_SCAN_CMP;
194 44
			while (isset($RULES[$yych])) {
195 42
				$RULES = &$RULES[$yych];
196 42
				if (isset($RULES['FIN'])) {
197 42
					$YYMATCH = $YYCURSOR;
198 42
				}
199 42
				$yych = $YYBUFFER[++$YYCURSOR];
200 42
			}
201 44
			if (isset($YYMATCH)) {
202 42
					$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 42
					$node["operator"]=substr($YYBUFFER, $YYCURSOR_START, ($YYMATCH + 1) - $YYCURSOR_START);
204 42
					$node["left"]=$result;
205 42
					$YYBUFFER = substr($YYBUFFER, $YYCURSOR);
206 42
					$result=$this->parse_const($YYBUFFER);
207 42
					if ($result) {
208 42
						$node["right"]=$result;
209 42
					}
210 42
					$result=$node;
211 42
			} else {
212 2
				$this->error="unknow compare-operator near '$YYBUFFER'";
213
			}
214 44
		}
215 45
		return $result;
216
	}
217
218 45
	protected function parse_group_expr(&$YYBUFFER) {
219 45
		$YYCURSOR = 0;
220 45
		while (isset($this->_SCAN_WS[$YYBUFFER[$YYCURSOR]])) {
221 2
			$YYCURSOR++;
222 2
		}
223 45
		$yych = $YYBUFFER[$YYCURSOR++];
224 45
		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 45
			$result = $this->parse_cmp_expr($YYBUFFER);
243
		}
244 45
		return $result;
245
	}
246
247 45 View Code Duplication
	protected function parse_and_expr(&$YYBUFFER) {
248 45
		$result=$this->parse_group_expr($YYBUFFER);
249 45
		while (is_array($result)) {
250 44
			$YYCURSOR = 0;
251 44
			while (isset($this->_SCAN_WS[$YYBUFFER[$YYCURSOR]])) {
252 37
				$YYCURSOR++;
253 37
			}
254 44
			$ident = strtolower(substr($YYBUFFER, $YYCURSOR, 3));
255 44
			if ($ident === 'and' && !isset($this->_SCAN_AZ_09[$YYBUFFER[$YYCURSOR + 3]]) ) {
256
				$YYBUFFER = substr($YYBUFFER, $YYCURSOR + 3);
257
				$right = $this->parse_group_expr($YYBUFFER);
258
				if (is_array($right)) {
259
					$result = array(
260
						'id' => $ident,
261
						'left' => $result,
262
						'right' => $right
263
					);
264
				} else {
265
					unset($result);
266
				}
267
			} else {
268 44
				break;
269
			}
270
		}
271 45
		return $result;
272
	}
273
274 45 View Code Duplication
	protected function parse_or_expr(&$YYBUFFER) {
275 45
		$result=$this->parse_and_expr($YYBUFFER);
276 45
		while (is_array($result)) {
277 44
			$YYCURSOR = 0;
278 44
			while (isset($this->_SCAN_WS[$YYBUFFER[$YYCURSOR]])) {
279 37
				$YYCURSOR++;
280 37
			}
281 44
			$ident = strtolower(substr($YYBUFFER, $YYCURSOR, 2));
282 44
			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 44
				break;
296
			}
297
		}
298 45
		return $result;
299
	}
300
301 42
	protected function parse_orderby(&$YYBUFFER) {
302 38
		$field = $this->parse_ident($YYBUFFER);
303
304 38
		$YYCURSOR = 0;
305 40
		while (isset($this->_SCAN_WS[$YYBUFFER[$YYCURSOR]])) {
306 1
			$YYCURSOR++;
307 1
		}
308 38
		$value = '';
309 38
		$yych  = $YYBUFFER[$YYCURSOR];
310 38 View Code Duplication
		if ($this->_SCAN_AZ[$yych]) {
311 1
			$value .= $yych;
312 1
			$yych = $YYBUFFER[++$YYCURSOR];
313 1
			while (isset($this->_SCAN_AZ[$yych])) {
314 1
				$value .= $yych;
315 1
				$yych = $YYBUFFER[++$YYCURSOR];
316 1
			}
317 1
			$sort_type = strtoupper($value);
318 1
			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 1
				$sort_type = 'ASC';
320 1
				$YYCURSOR = $YYCURSOR - strlen($value);
321 15
				$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 1
			}
323 1
		} else {
324 37
			$sort_type = 'ASC';
325
		}
326 38
		while (is_array($field)) {
327
			$result = array(
328 40
				'id' => 'orderbyfield',
329 38
				'type' => $sort_type,
330 38
				'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 38
			);
333 38
			while (isset($this->_SCAN_WS[$YYBUFFER[$YYCURSOR]])) {
334
				$YYCURSOR++;
335
			}
336 38
			$yych  = $YYBUFFER[$YYCURSOR];
337 38
			if ($yych !== ',') {
338 38
				$YYBUFFER = substr($YYBUFFER, $YYCURSOR);
339 38
				unset($field);
340 38
			} else {
341 1
				$YYBUFFER = substr($YYBUFFER, $YYCURSOR + 1);
342 1
				$field = $this->parse_ident($YYBUFFER);
343 1
				$YYCURSOR = 0;
344 1
				while (isset($this->_SCAN_WS[$YYBUFFER[$YYCURSOR]])) {
345 14
					$YYCURSOR++;
346
				}
347 1
				$value = '';
348 1
				$yych  = $YYBUFFER[$YYCURSOR];
349 15 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 1
					$sort_type = 'ASC';
364
				}
365
			}
366 38
		}
367 38
		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 47
	protected function parse_query(&$query) {
388
389 47
		if (!preg_match('|^[[:space:]]*order[[:space:]]*by[[:space:]]+|i', $query, $regs)) {
390 45
			$result=$this->parse_or_expr($query);
391 45
		} else {
392 2
			$no_selection = true;
393
		}
394
395
/*
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 47
		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 47
		$matching = preg_match('|^[[:space:]]*order[[:space:]]*by[[:space:]]+|i', $query, $regs);
445 47
		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 38
			$query=substr($query, strlen($regs[0]));
447 38
			$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 38
			$node["right"]=$this->parse_orderby($query);
449 38
			$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 38
			$result=$node;
451 38
		}
452 47
		if (preg_match('|^[[:space:]]*limit[[:space:]]+([0-9]+)[[:space:]]*([,][[:space:]]*([0-9]+))?|i', $query, $regs)) {
453 1
			$query=substr($query, strlen($regs[0]));
454 1
			$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 1
			$limit_s["offset"]=$regs[1];
456 1
			$limit_s["limit"]=$regs[3];
457 1
		} else {
458 46
			$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 46
			$limit_s["offset"]=($this->offset) ? $this->offset : 0;
460 46
			$limit_s["limit"]=($this->limit) ? $this->limit : 0;
461
		}
462 47
		$limit_s["left"]=$result;
463 47
		$result=$limit_s;
464
465 47
		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 47
	public function compile($path, $query, $limit=100, $offset=0, $layers = array()) {
472 47
		debug("sql_compiler::compile ($path, $query, $limit, $offset)", "store");
473 47
		$this->error="";
474 47
		$this->path = $path;
475
476 47
		$this->limit=$limit;
477 47
		$this->offset=$offset;
478 47
		$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 47
		$tree=$this->parse_query($query);
481
482 47
		if ( $this->error ) {
483 2
			return null;
484 45
		} 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 45
		} 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 45
			$compiled_query=$this->priv_sql_compile($tree);
490 45
			return $compiled_query;
491
		} else {
492
			return null;
493
		}
494
495
	}
496
497
498
  }
499