Test Failed
Pull Request — master (#200)
by
unknown
06:18 queued 02:53
created

Check   A

Complexity

Total Complexity 38

Size/Duplication

Total Lines 231
Duplicated Lines 21.65 %

Coupling/Cohesion

Components 1
Dependencies 4

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
wmc 38
lcom 1
cbo 4
dl 50
loc 231
ccs 0
cts 99
cp 0
rs 9.36
c 0
b 0
f 0

3 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 3 1
A build() 0 22 5
F parse() 50 147 32

How to fix   Duplicated Code   

Duplicated Code

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

Common duplication problems, and corresponding solutions are:

1
<?php
2
3
/**
4
 * Parses the definition of a Check component.
5
 */
6
7
namespace PhpMyAdmin\SqlParser\Components;
8
9
use PhpMyAdmin\SqlParser\Component;
10
use PhpMyAdmin\SqlParser\Context;
11
use PhpMyAdmin\SqlParser\Parser;
12
use PhpMyAdmin\SqlParser\Token;
13
use PhpMyAdmin\SqlParser\TokensList;
14
15
/**
16
 * Parses the definition of a Check component.
17
 *
18
 * Used for parsing `CREATE TABLE` statement.
19
 *
20
 * @category   Components
21
 *
22
 * @license    https://www.gnu.org/licenses/gpl-2.0.txt GPL-2.0+
23
 */
24
class Check extends Component
25
{
26
27
    /**
28
     * Columns.
29
     *
30
     * @var array
31
     */
32
    public $columns;
33
34
    /**
35
     * The operators in this component.
36
     *
37
     * @var OptionsArray
38
     */
39
    public $operators;
40
41
    /**
42
     * The operands in this component.
43
     *
44
     * @var operands
45
     */
46
    public $operands;
47
48
    /**
49
     * The logical operators in this component.
50
     *
51
     * @var logicalOperatorsArray
52
     */
53
    public $logicalOperators;
54
55
    /**
56
     * Possible operators in the component.
57
     *
58
     * @var OperatorsArray
59
     */
60
    public static $operatorsArray = array("=", ">", "<", "<=", ">=", "!=", "LIKE", "NOT", "BETWEEN", "IS", "NULL", "REGEXP", "REGEXP");
0 ignored issues
show
Coding Style Comprehensibility introduced by
The string literal = does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
Coding Style Comprehensibility introduced by
The string literal > does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
Coding Style Comprehensibility introduced by
The string literal < does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
Coding Style Comprehensibility introduced by
The string literal <= does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
Coding Style Comprehensibility introduced by
The string literal >= does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
Coding Style Comprehensibility introduced by
The string literal != does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
Coding Style Comprehensibility introduced by
The string literal LIKE does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
Coding Style Comprehensibility introduced by
The string literal NOT does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
Coding Style Comprehensibility introduced by
The string literal BETWEEN does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
Coding Style Comprehensibility introduced by
The string literal IS does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
Coding Style Comprehensibility introduced by
The string literal NULL does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
Coding Style Comprehensibility introduced by
The string literal REGEXP does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 135 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
61
62
    /**
63
     * Constructor.
64
     *
65
     * @param string       $name    the name of the component
0 ignored issues
show
Documentation introduced by
Should the type for parameter $name not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
66
     */
67
    public function __construct($name = null) {
68
        $this->name = $name;
0 ignored issues
show
Bug introduced by
The property name 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...
69
    }
70
71
    /**
72
     * @param Parser     $parser  the parser that serves as context
73
     * @param TokensList $list    the list of tokens that are being parsed
74
     * @param array      $options parameters for parsing
75
     *
76
     * @return component
0 ignored issues
show
Documentation introduced by
Should the return type not be Check?

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...
77
     */
78
    public static function parse(Parser $parser, TokensList $list, array $options = array())
79
    {
80
        $ret = new self();
81
82
        /**
83
         * Last parsed column.
84
         *
85
         * @var array
86
         */
87
        $lastColumn = array();
0 ignored issues
show
Unused Code introduced by
$lastColumn 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...
88
89
        /**
90
         * Bracket stack
91
         *
92
         * @var bracketStack
93
         */
94
        $bracketStack = array();
95
96
        /**
97
         * The state of the parser.
98
         *
99
         * Below are the states of the parser.
100
         *
101
         *      0 ----------------------[ column name ]-----------------------> 1
102
         *
103
         *      1 ----------------------[ operator ]-----------------------> 2
104
         *      2 ---------------------[ operand ]---------------------> 3
105
         *      2 ---------------------[ operand ]---------------------> 4
106
         *
107
         *      3 ---------------------[ logical operator ]---------------------> 0
108
         *
109
         * @var int
110
         */
111
        $state = 0;
112
113
        for (; $list->idx < $list->count; ++$list->idx) {
114
            /**
115
             * Token parsed at this moment.
116
             *
117
             * @var Token
118
             */
119
            $token = $list->tokens[$list->idx];
120
121
            // End of statement.
122
            if ($token->type === Token::TYPE_DELIMITER) {
123
                break;
124
            }
125
126
            // Skipping whitespaces and comments.
127
            if (($token->type === Token::TYPE_WHITESPACE) || ($token->type === Token::TYPE_COMMENT)) {
128
                continue;
129
            }
130
131
            if ($state === 0) {
132 View Code Duplication
                if (($token->type === Token::TYPE_KEYWORD) && $token->keyword === 'CHECK') {
133
                    $state = 0;
134
                } elseif(($token->type === Token::TYPE_OPERATOR) && ($token->value === '(')) {
135
                    $state = 1;
136
                    array_push($bracketStack, '(');
137
                } else {
138
                    $parser->error(
139
                        'Invalid token',
140
                        $token
141
                    );
142
                    return $ret;
143
                }
144
            } else if($state === 1) {
145 View Code Duplication
                if(($token->type === Token::TYPE_OPERATOR) && ($token->value === '(')) {
146
                    array_push($bracketStack, '(');
147
                    $state = 1;
148
                } elseif($token->type === Token::TYPE_OPERATOR) {
149
                    $parser->error(
150
                        'A Column name was expected!',
151
                        $token
152
                    );
153
                    return $ret;
154
                } else {
155
                    $ret->columns[] = $token->value;
156
                    $state = 2;
157
                }
158
            } elseif ($state === 2) {
159
                if(($token->type === Token::TYPE_OPERATOR) || in_array($token->value, self::$operatorsArray)) {
160
                    if(($token->value === ')')) {
161 View Code Duplication
                        if(count($bracketStack) > 1) {
162
                            array_pop($bracketStack);
163
                            $state = 2;
164
                        } else $state = 5;
165
                    } elseif(in_array($token->value, self::$operatorsArray)) {
166
                        $ret->operators[] = $token->value;
167
                        $state = 3;
168
                    } else {
169
                        $parser->error(
170
                            'Unrecognized operator!',
171
                            $token
172
                        );
173
                        return $ret;
174
                    }
175
                } else {
176
                    $parser->error(
177
                        'An operator was expected!',
178
                        $token
179
                    );
180
                    return $ret;
181
                }
182 View Code Duplication
            } elseif ($state === 3) {
183
                if(($token->type === Token::TYPE_OPERATOR) && ($token->value === '(')) {
184
                    $state = 3;
185
                    array_push($bracketStack, '(');
186
                } elseif($token->type === Token::TYPE_OPERATOR) {
187
                    $parser->error(
188
                        'An operand was expected!',
189
                        $token
190
                    );
191
                    return $ret;
192
                } else {
193
                    $ret->operands[] = $token->value;
194
                    $state = 4;
195
                }
196
            } elseif ($state === 4) {
197
                if (($token->value === 'AND') || ($token->value === 'OR')) {
198
                    $ret->logicalOperators[] = $token->value;
199
                    $state = 1;
200
                } elseif (($token->type === Token::TYPE_OPERATOR) && ($token->value === ')')) {
201 View Code Duplication
                    if(count($bracketStack) === 1) {
202
                        $state = 5;
203
                    } else {
204
                        array_pop($bracketStack);
205
                        $state = 4;
206
                    }
207
                } elseif($token->type === Token::TYPE_OPERATOR) {
208
                    $parser->error(
209
                        'Unrecognized token!',
210
                        $token
211
                    );
212
                    return $ret;
213
                } else {
214
                    $state = 5;
215
                }
216
            } elseif ($state === 5) {
217
                break;
218
            }
219
        }
220
221
        --$list->idx;
222
223
        return $ret;
224
    }
225
226
    /**
227
     * @param Check   $component the component to be built
228
     * @param array $options   parameters for building
229
     *
230
     * @return string
231
     */
232
    public static function build($component, array $options = array())
233
    {
234
        $columns = $component->columns;
235
        $logical_op = $component->logicalOperators;
236
        $operators = $component->operators;
237
        $operands = $component->operands;
238
        $definition = 'CHECK (';
239
        for($i=0; $i<count($columns); ++$i) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
240
            $columns[$i] = trim($columns[$i]);
241
            if($i>0) {
242
                $definition .= ' ' . $logical_op[$i-1] . ' ';
243
            }
244
            $definition .= Context::escape($columns[$i]);
245
            if($operators[$i] === 'IS NULL' || $operators[$i] === 'IS NOT NULL') {
246
                $definition .= ' ' . $operators[$i];
247
            } else {
248
                $definition .= ' ' . $operators[$i] . ' \'' . $operands[$i] . '\'';
249
            }
250
        }
251
        $definition .= ')';
252
        return trim($definition);
253
    }
254
}
255