Completed
Pull Request — master (#88)
by Deven
61:40
created

CaseExpression::build()   C

Complexity

Conditions 7
Paths 8

Size

Total Lines 32
Code Lines 21

Duplication

Lines 16
Ratio 50 %

Importance

Changes 0
Metric Value
cc 7
eloc 21
nc 8
nop 2
dl 16
loc 32
rs 6.7272
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * Parses a reference to a CASE expression
5
 *
6
 * @package    SqlParser
7
 * @subpackage Components
8
 */
9
namespace SqlParser\Components;
10
11
use SqlParser\Context;
12
use SqlParser\Component;
13
use SqlParser\Parser;
14
use SqlParser\Token;
15
use SqlParser\TokensList;
16
17
18
19
20
/**
21
 * Parses a reference to a CASE expression
22
 *
23
 * @category   Components
24
 * @package    SqlParser
25
 * @subpackage Components
26
 * @author     Deven Bansod <[email protected]>
27
 * @license    http://opensource.org/licenses/GPL-2.0 GNU Public License
28
 */
29
class CaseExpression extends Component
30
{
31
32
    /**
33
     * The value to be compared
34
     *
35
     * @var Expression
36
     */
37
    public $value;
38
39
    /**
40
     * The conditions in WHEN clauses
41
     *
42
     * @var array
43
     */
44
    public $conditions;
45
46
    /**
47
     * The results matching with the WHEN clauses
48
     *
49
     * @var array
50
     */
51
    public $results;
52
53
    /**
54
     * The values to be compared against
55
     *
56
     * @var array
57
     */
58
    public $compare_values;
59
60
    /**
61
     * The result in ELSE section of expr
62
     *
63
     * @var array
64
     */
65
    public $else_result;
66
67
    /**
68
     * Constructor.
69
     *
70
     */
71
    public function __construct()
72
    {
73
    }
74
75
    /**
76
     *
77
     * @param Parser     $parser  The parser that serves as context.
78
     * @param TokensList $list    The list of tokens that are being parsed.
79
     *
80
     * @return Expression
0 ignored issues
show
Documentation introduced by
Should the return type not be CaseExpression?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
81
     */
82
    public static function parse(Parser $parser, TokensList $list)
83
    {
84
        $ret = new CaseExpression();
85
86
        /**
87
         * Counts brackets.
88
         *
89
         * @var int $brackets
90
         */
91
        $brackets = 0;
0 ignored issues
show
Unused Code introduced by
$brackets 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...
92
93
        /**
94
         * Keeps track of the last two previous tokens.
95
         *
96
         * @var Token[] $prev
97
         */
98
        $prev = array(null, null);
0 ignored issues
show
Unused Code introduced by
$prev 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...
99
100
        /**
101
         * State of parser
102
         *
103
         * @var int $parser
104
         */
105
        $state = 0;
106
107
        /**
108
         * Syntax type (type 0 or type 1)
109
         *
110
         * @var int $type
111
         */
112
        $type = 0;
113
114
        ++$list->idx; // Skip 'CASE'
115
116
        for (; $list->idx < $list->count; ++$list->idx) {
117
118
            /**
119
             * Token parsed at this moment.
120
             *
121
             * @var Token $token
122
             */
123
            $token = $list->tokens[$list->idx];
124
125
            // End of statement.
126
            if ($token->type === Token::TYPE_DELIMITER) {
127
                break;
128
            }
129
130
            // Skipping whitespaces and comments.
131
            if (($token->type === Token::TYPE_WHITESPACE)
132
                || ($token->type === Token::TYPE_COMMENT)
133
            ) {
134
                continue;
135
            }
136
137
            if ($state === 0) {
138
                if ($token->type === Token::TYPE_KEYWORD
139
                    && $token->value === 'WHEN'
140
                ) {
141
                    ++$list->idx; // Skip 'WHEN'
142
                    $new_condition = Condition::parse($parser, $list);
0 ignored issues
show
Documentation introduced by
$parser is of type integer, but the function expects a object<SqlParser\Parser>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
143
                    $type = 1;
144
                    $state = 1;
145
                    $ret->conditions[] = $new_condition;
146
                } elseif ($token->type === Token::TYPE_KEYWORD
147
                    && $token->value === 'ELSE'
148
                ) {
149
                    ++$list->idx; // Skip 'ELSE'
150
                    $ret->else_result = Expression::parse($parser, $list);
0 ignored issues
show
Documentation introduced by
$parser is of type integer, but the function expects a object<SqlParser\Parser>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
Documentation Bug introduced by
It seems like \SqlParser\Components\Ex...::parse($parser, $list) of type object<SqlParser\Components\Expression> or null is incompatible with the declared type array of property $else_result.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
151
                    $state = 0; // last clause of CASE expression
152
                } elseif ($token->type === Token::TYPE_KEYWORD
153
                    && ($token->value === 'END'
154
                    || $token->value === 'end')
155
                ) {
156
                    $state = 3; // end of CASE expression
157
                    ++$list->idx;
158
                    break;
159
                } elseif ($token->type === Token::TYPE_KEYWORD) {
160
                    $parser->error(__('Unexpected keyword'), $token);
0 ignored issues
show
Bug introduced by
The method error cannot be called on $parser (of type integer).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
161
                    break;
162
                } else {
163
                    $ret->value = Expression::parse($parser, $list);
0 ignored issues
show
Documentation introduced by
$parser is of type integer, but the function expects a object<SqlParser\Parser>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
164
                    $type = 0;
165
                    $state = 1;
166
                }
167
            } elseif ($state === 1) {
168
                if ($type === 0) {
169
                    if ($token->type === Token::TYPE_KEYWORD
170
                        && $token->value === 'WHEN'
171
                    ) {
172
                        ++$list->idx; // Skip 'WHEN'
173
                        $new_value = Expression::parse($parser, $list);
0 ignored issues
show
Documentation introduced by
$parser is of type integer, but the function expects a object<SqlParser\Parser>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
174
                        $state = 2;
175
                        $ret->compare_values[] = $new_value;
176
                    } elseif ($token->type === Token::TYPE_KEYWORD
177
                        && $token->value === 'ELSE'
178
                    ) {
179
                        ++$list->idx; // Skip 'ELSE'
180
                        $ret->else_result = Expression::parse($parser, $list);
0 ignored issues
show
Documentation introduced by
$parser is of type integer, but the function expects a object<SqlParser\Parser>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
181
                        $state = 0; // last clause of CASE expression
182
                    } elseif ($token->type === Token::TYPE_KEYWORD
183
                        && ($token->value === 'END'
184
                        || $token->value === 'end')
185
                    ) {
186
                        $state = 3; // end of CASE expression
187
                        ++$list->idx;
188
                        break;
189
                    } elseif ($token->type === Token::TYPE_KEYWORD) {
190
                        $parser->error(__('Unexpected keyword'), $token);
0 ignored issues
show
Bug introduced by
The method error cannot be called on $parser (of type integer).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
191
                        break;
192
                    } else {
193
                        $parser->error(__('Unexpected token'), $token);
0 ignored issues
show
Bug introduced by
The method error cannot be called on $parser (of type integer).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
194
                        break;
195
                    }
196 View Code Duplication
                } else {
197
                    if ($token->type === Token::TYPE_KEYWORD
198
                        && $token->value === 'THEN'
199
                    ) {
200
                        ++$list->idx; // Skip 'THEN'
201
                        $new_result = Expression::parse($parser, $list);
0 ignored issues
show
Documentation introduced by
$parser is of type integer, but the function expects a object<SqlParser\Parser>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
202
                        $state = 0;
203
                        $ret->results[] = $new_result;
204
                    } elseif ($token->type === Token::TYPE_KEYWORD) {
205
                        $parser->error(__('Unexpected keyword'), $token);
0 ignored issues
show
Bug introduced by
The method error cannot be called on $parser (of type integer).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
206
                        break;
207
                    } else {
208
                        $parser->error(__('Unexpected token'), $token);
0 ignored issues
show
Bug introduced by
The method error cannot be called on $parser (of type integer).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
209
                        break;
210
                    }
211
                }
212
            } elseif ($state === 2) {
213
                if ($type === 0) {
214 View Code Duplication
                    if ($token->type === Token::TYPE_KEYWORD
215
                        && $token->value === 'THEN'
216
                    ) {
217
                        ++$list->idx; // Skip 'THEN'
218
                        $new_result = Expression::parse($parser, $list);
0 ignored issues
show
Documentation introduced by
$parser is of type integer, but the function expects a object<SqlParser\Parser>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
219
                        $ret->results[] = $new_result;
220
                        $state = 1;
221
                    } elseif ($token->type === Token::TYPE_KEYWORD) {
222
                        $parser->error(__('Unexpected keyword'), $token);
0 ignored issues
show
Bug introduced by
The method error cannot be called on $parser (of type integer).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
223
                        break;
224
                    } else {
225
                        $parser->error(__('Unexpected token'), $token);
0 ignored issues
show
Bug introduced by
The method error cannot be called on $parser (of type integer).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
226
                        break;
227
                    }
228
                } else {
229
                    $parser->error(__('Unexpected token'), $token);
0 ignored issues
show
Bug introduced by
The method error cannot be called on $parser (of type integer).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
230
                    break;
231
                }
232
            }
233
        }
234
235
        if ($state !== 3) {
236
            $parser->error(
0 ignored issues
show
Bug introduced by
The method error cannot be called on $parser (of type integer).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
237
                __('Unexpected end of CASE expression'),
238
                $list->list[$list->idx - 1]
0 ignored issues
show
Bug introduced by
The property list does not seem to exist in SqlParser\TokensList.

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

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

Loading history...
239
            );
240
        }
241
242
        --$list->idx;
243
        return $ret;
244
    }
245
246
    /**
247
     * @param Expression $component The component to be built.
248
     * @param array      $options   Parameters for building.
249
     *
250
     * @return string
251
     */
252
    public static function build($component, array $options = array())
253
    {
254
        $ret = 'CASE ';
255
        if (isset($component->value)) {
256
            // Syntax type 0
257
            $ret .= $component->value . ' ';
0 ignored issues
show
Bug introduced by
The property value does not seem to exist in SqlParser\Components\Expression.

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

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

Loading history...
258 View Code Duplication
            for (
259
                $i = 0;
260
                $i < count($component->compare_values) && $i < count($component->results);
0 ignored issues
show
Bug introduced by
The property compare_values does not seem to exist in SqlParser\Components\Expression.

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

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

Loading history...
Bug introduced by
The property results does not seem to exist in SqlParser\Components\Expression.

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

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

Loading history...
261
                $i++
262
            ) {
263
                $ret .= 'WHEN ' . $component->compare_values[$i] . ' ';
264
                $ret .= 'THEN ' . $component->results[$i] . ' ';
265
            }
266
        } else {
267
            // Syntax type 1
268 View Code Duplication
            for (
269
                $i = 0;
270
                $i < count($component->conditions) && $i < count($component->results);
0 ignored issues
show
Bug introduced by
The property conditions does not seem to exist in SqlParser\Components\Expression.

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

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

Loading history...
271
                $i++
272
            ) {
273
                $ret .= 'WHEN ' . Condition::build($component->conditions[$i]) . ' ';
274
                $ret .= 'THEN ' . $component->results[$i] . ' ';
275
            }
276
        }
277
        if (isset($component->else_result)) {
278
            $ret .= 'ELSE ' . $component->else_result . ' ';
0 ignored issues
show
Bug introduced by
The property else_result does not seem to exist in SqlParser\Components\Expression.

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

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

Loading history...
279
        }
280
        $ret .= 'END';
281
282
        return $ret;
283
    }
284
}
285