Test Failed
Pull Request — master (#291)
by William
12:25
created

ReplaceStatement::parse()   C

Complexity

Conditions 14
Paths 5

Size

Total Lines 93

Duplication

Lines 30
Ratio 32.26 %

Code Coverage

Tests 43
CRAP Score 14.0171

Importance

Changes 0
Metric Value
dl 30
loc 93
ccs 43
cts 45
cp 0.9556
rs 5.166
c 0
b 0
f 0
cc 14
nc 5
nop 2
crap 14.0171

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
/**
4
 * `REPLACE` statement.
5
 */
6
7
namespace PhpMyAdmin\SqlParser\Statements;
8
9
use PhpMyAdmin\SqlParser\Components\Array2d;
10
use PhpMyAdmin\SqlParser\Components\IntoKeyword;
11
use PhpMyAdmin\SqlParser\Components\OptionsArray;
12
use PhpMyAdmin\SqlParser\Components\SetOperation;
13
use PhpMyAdmin\SqlParser\Parser;
14
use PhpMyAdmin\SqlParser\Statement;
15
use PhpMyAdmin\SqlParser\Token;
16
use PhpMyAdmin\SqlParser\TokensList;
17
18
/**
19
 * `REPLACE` statement.
20
 *
21
 * REPLACE [LOW_PRIORITY | DELAYED]
22
 *     [INTO] tbl_name [(col_name,...)]
23
 *     {VALUES | VALUE} ({expr | DEFAULT},...),(...),...
24
 *
25
 * or
26
 *
27
 * REPLACE [LOW_PRIORITY | DELAYED]
28
 *     [INTO] tbl_name
29
 *     SET col_name={expr | DEFAULT}, ...
30
 *
31
 * or
32
 *
33
 * REPLACE [LOW_PRIORITY | DELAYED]
34
 *   [INTO] tbl_name
35
 *   [PARTITION (partition_name,...)]
36
 *   [(col_name,...)]
37
 *   SELECT ...
38
 *
39
 * @category   Statements
40
 *
41
 * @license    https://www.gnu.org/licenses/gpl-2.0.txt GPL-2.0+
42
 */
43
class ReplaceStatement extends Statement
44
{
45
    /**
46
     * Options for `REPLACE` statements and their slot ID.
47
     *
48
     * @var array
49
     */
50
    public static $OPTIONS = array(
51
        'LOW_PRIORITY' => 1,
52
        'DELAYED' => 1
53
    );
54
55
    /**
56
     * Tables used as target for this statement.
57
     *
58
     * @var IntoKeyword
59
     */
60
    public $into;
61
62
    /**
63
     * Values to be replaced.
64
     *
65
     * @var Array2d
66
     */
67
    public $values;
68
69
    /**
70
     * If SET clause is present
71
     * holds the SetOperation.
72
     *
73
     * @var SetOperation[]
74
     */
75
    public $set;
76
77
    /**
78
     * If SELECT clause is present
79
     * holds the SelectStatement.
80
     *
81
     * @var SelectStatement
82
     */
83
    public $select;
84
85
    /**
86
     * @return string
87
     */
88 4
    public function build()
89
    {
90 4
        $ret = 'REPLACE ' . $this->options;
91 4
        $ret = trim($ret) . ' INTO ' . $this->into;
92
93 4 View Code Duplication
        if (! is_null($this->values) && count($this->values) > 0) {
94 1
            $ret .= ' VALUES ' . Array2d::build($this->values);
0 ignored issues
show
Documentation introduced by
$this->values is of type object<PhpMyAdmin\SqlParser\Components\Array2d>, but the function expects a array<integer,object<Php...r\Components\ArrayObj>>.

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...
95 3
        } elseif (! is_null($this->set) && count($this->set) > 0) {
96 1
            $ret .= ' SET ' . SetOperation::build($this->set);
97 2
        } elseif (! is_null($this->select) && strlen($this->select) > 0) {
98 2
            $ret .= ' ' . $this->select->build();
99
        }
100
101 4
        return $ret;
102
    }
103
104
    /**
105
     * @param Parser     $parser the instance that requests parsing
106
     * @param TokensList $list   the list of tokens to be parsed
107
     */
108 13
    public function parse(Parser $parser, TokensList $list)
109
    {
110 13
        ++$list->idx; // Skipping `REPLACE`.
111
112
        // parse any options if provided
113 13
        $this->options = OptionsArray::parse(
114 13
            $parser,
115 13
            $list,
116 13
            static::$OPTIONS
117
        );
118
119 13
        ++$list->idx;
120
121
        /**
122
         * The state of the parser.
123
         *
124
         * Below are the states of the parser.
125
         *
126
         *      0 ---------------------------------[ INTO ]----------------------------------> 1
127
         *
128
         *      1 -------------------------[ VALUES/VALUE/SET/SELECT ]-----------------------> 2
129
         *
130
         * @var int
131
         */
132 13
        $state = 0;
133
134 13
        for (; $list->idx < $list->count; ++$list->idx) {
135
            /**
136
             * Token parsed at this moment.
137
             *
138
             * @var Token
139
             */
140 13
            $token = $list->tokens[$list->idx];
141
142
            // End of statement.
143 13
            if ($token->type === Token::TYPE_DELIMITER) {
144 10
                break;
145
            }
146
147
            // Skipping whitespaces and comments.
148 13
            if (($token->type === Token::TYPE_WHITESPACE) || ($token->type === Token::TYPE_COMMENT)) {
149 9
                continue;
150
            }
151
152 13
            if ($state === 0) {
153 13
                if ($token->type === Token::TYPE_KEYWORD
154 13
                    && $token->keyword !== 'INTO'
155
                ) {
156
                    $parser->error('Unexpected keyword.', $token);
157
                    break;
158
                }
159 13
                ++$list->idx;
160 13
                $this->into = IntoKeyword::parse(
161 13
                    $parser,
162 13
                    $list,
163 13
                    array('fromReplace' => true)
164
                );
165
166 13
                $state = 1;
167 13 View Code Duplication
            } elseif ($state === 1) {
168 13
                if ($token->type === Token::TYPE_KEYWORD) {
169 11
                    if ($token->keyword === 'VALUE'
170 11
                        || $token->keyword === 'VALUES'
171
                    ) {
172 4
                        ++$list->idx; // skip VALUES
173
174 4
                        $this->values = Array2d::parse($parser, $list);
0 ignored issues
show
Documentation Bug introduced by
It seems like \PhpMyAdmin\SqlParser\Co...::parse($parser, $list) of type array<integer,object<Php...r\Components\ArrayObj>> is incompatible with the declared type object<PhpMyAdmin\SqlParser\Components\Array2d> of property $values.

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...
175 7
                    } elseif ($token->keyword === 'SET') {
176 3
                        ++$list->idx; // skip SET
177
178 3
                        $this->set = SetOperation::parse($parser, $list);
179 4
                    } elseif ($token->keyword === 'SELECT') {
180 3
                        $this->select = new SelectStatement($parser, $list);
181
                    } else {
182 1
                        $parser->error(
183 1
                            'Unexpected keyword.',
184
                            $token
185
                        );
186 1
                        break;
187
                    }
188 10
                    $state = 2;
189
                } else {
190 2
                    $parser->error(
191 2
                        'Unexpected token.',
192
                        $token
193
                    );
194 2
                    break;
195
                }
196
            }
197
        }
198
199 13
        --$list->idx;
200 13
    }
201
}
202