Completed
Push — master ( 65f66e...428edc )
by Michal
04:14
created

AlterOperation::parse()   D

Complexity

Conditions 22
Paths 12

Size

Total Lines 119
Code Lines 54

Duplication

Lines 22
Ratio 18.49 %

Code Coverage

Tests 61
CRAP Score 22.002

Importance

Changes 0
Metric Value
cc 22
eloc 54
nc 12
nop 3
dl 22
loc 119
ccs 61
cts 62
cp 0.9839
crap 22.002
rs 4.6625
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
/**
4
 * Parses an alter operation.
5
 */
6
7
namespace PhpMyAdmin\SqlParser\Components;
8
9
use PhpMyAdmin\SqlParser\Component;
10
use PhpMyAdmin\SqlParser\Parser;
11
use PhpMyAdmin\SqlParser\Token;
12
use PhpMyAdmin\SqlParser\TokensList;
13
14
/**
15
 * Parses an alter operation.
16
 *
17
 * @category   Components
18
 *
19
 * @license    https://www.gnu.org/licenses/gpl-2.0.txt GPL-2.0+
20
 */
21
class AlterOperation extends Component
22
{
23
    /**
24
     * All database options.
25
     *
26
     * @var array
27
     */
28
    public static $DB_OPTIONS = array(
29
        'CHARACTER SET' => array(1, 'var'),
30
        'CHARSET' => array(1, 'var'),
31
        'DEFAULT CHARACTER SET' => array(1, 'var'),
32
        'DEFAULT CHARSET' => array(1, 'var'),
33
        'UPGRADE' => array(1, 'var'),
34
        'COLLATE' => array(2, 'var'),
35
        'DEFAULT COLLATE' => array(2, 'var'),
36
    );
37
38
    /**
39
     * All table options.
40
     *
41
     * @var array
42
     */
43
    public static $TABLE_OPTIONS = array(
44
        'ENGINE' => array(1, 'var='),
45
        'AUTO_INCREMENT' => array(1, 'var='),
46
        'AVG_ROW_LENGTH' => array(1, 'var'),
47
        'MAX_ROWS' => array(1, 'var'),
48
        'ROW_FORMAT' => array(1, 'var'),
49
        'COMMENT' => array(1, 'var'),
50
        'ADD' => 1,
51
        'ALTER' => 1,
52
        'ANALYZE' => 1,
53
        'CHANGE' => 1,
54
        'CHECK' => 1,
55
        'COALESCE' => 1,
56
        'CONVERT' => 1,
57
        'DISABLE' => 1,
58
        'DISCARD' => 1,
59
        'DROP' => 1,
60
        'ENABLE' => 1,
61
        'IMPORT' => 1,
62
        'MODIFY' => 1,
63
        'OPTIMIZE' => 1,
64
        'ORDER' => 1,
65
        'PARTITION' => 1,
66
        'REBUILD' => 1,
67
        'REMOVE' => 1,
68
        'RENAME' => 1,
69
        'REORGANIZE' => 1,
70
        'REPAIR' => 1,
71
        'UPGRADE' => 1,
72
73
        'COLUMN' => 2,
74
        'CONSTRAINT' => 2,
75
        'DEFAULT' => 2,
76
        'TO' => 2,
77
        'BY' => 2,
78
        'FOREIGN' => 2,
79
        'FULLTEXT' => 2,
80
        'KEY' => 2,
81
        'KEYS' => 2,
82
        'PARTITIONING' => 2,
83
        'PRIMARY KEY' => 2,
84
        'SPATIAL' => 2,
85
        'TABLESPACE' => 2,
86
        'INDEX' => 2,
87
    );
88
89
    /**
90
     * All view options.
91
     *
92
     * @var array
93
     */
94
    public static $VIEW_OPTIONS = array(
95
        'AS' => 1,
96
    );
97
98
    /**
99
     * Options of this operation.
100
     *
101
     * @var OptionsArray
102
     */
103
    public $options;
104
105
    /**
106
     * The altered field.
107
     *
108
     * @var Expression
109
     */
110
    public $field;
111
112
    /**
113
     * Unparsed tokens.
114
     *
115
     * @var Token[]|string
116
     */
117
    public $unknown = array();
118
119
    /**
120
     * @param Parser     $parser  the parser that serves as context
121
     * @param TokensList $list    the list of tokens that are being parsed
122
     * @param array      $options parameters for parsing
123
     *
124
     * @return AlterOperation
125
     */
126 9
    public static function parse(Parser $parser, TokensList $list, array $options = array())
127
    {
128 9
        $ret = new self();
129
130
        /**
131
         * Counts brackets.
132
         *
133
         * @var int
134
         */
135 9
        $brackets = 0;
136
137
        /**
138
         * The state of the parser.
139
         *
140
         * Below are the states of the parser.
141
         *
142
         *      0 ---------------------[ options ]---------------------> 1
143
         *
144
         *      1 ----------------------[ field ]----------------------> 2
145
         *
146
         *      2 -------------------------[ , ]-----------------------> 0
147
         *
148
         * @var int
149
         */
150 9
        $state = 0;
151
152 9
        for (; $list->idx < $list->count; ++$list->idx) {
153
            /**
154
             * Token parsed at this moment.
155
             *
156
             * @var Token
157
             */
158 9
            $token = $list->tokens[$list->idx];
159
160
            // End of statement.
161 9
            if ($token->type === Token::TYPE_DELIMITER) {
162 6
                break;
163
            }
164
165
            // Skipping comments.
166 9
            if ($token->type === Token::TYPE_COMMENT) {
167 1
                continue;
168
            }
169
170
            // Skipping whitespaces.
171 9
            if ($token->type === Token::TYPE_WHITESPACE) {
172 3
                if ($state === 2) {
173
                    // When parsing the unknown part, the whitespaces are
174
                    // included to not break anything.
175 3
                    $ret->unknown[] = $token;
176 3
                }
177 3
                continue;
178
            }
179
180 9
            if ($state === 0) {
181 9
                $ret->options = OptionsArray::parse($parser, $list, $options);
182
183 9
                if ($ret->options->has('AS')) {
184 1 View Code Duplication
                    for (; $list->idx < $list->count; ++$list->idx) {
185 1
                        if ($list->tokens[$list->idx]->type === Token::TYPE_DELIMITER) {
186 1
                            break;
187
                        }
188 1
                        $ret->unknown[] = $list->tokens[$list->idx];
189 1
                    }
190 1
                    break;
191
                }
192
193 8
                $state = 1;
194 8 View Code Duplication
            } elseif ($state === 1) {
195 6
                $ret->field = Expression::parse(
196 6
                    $parser,
197 6
                    $list,
198
                    array(
199 6
                        'breakOnAlias' => true,
200 6
                        'parseField' => 'column',
201
                    )
202 6
                );
203 6
                if ($ret->field === null) {
204
                    // No field was read. We go back one token so the next
205
                    // iteration will parse the same token, but in state 2.
206 3
                    --$list->idx;
207 3
                }
208 6
                $state = 2;
209 6
            } elseif ($state === 2) {
210 5
                if ($token->type === Token::TYPE_OPERATOR) {
211 4
                    if ($token->value === '(') {
212 4
                        ++$brackets;
213 4
                    } elseif ($token->value === ')') {
214 4
                        --$brackets;
215 4
                    } elseif (($token->value === ',') && ($brackets === 0)) {
216 3
                        break;
217
                    }
218 5
                } elseif (!empty(Parser::$STATEMENT_PARSERS[$token->value])) {
219
                    // We have reached the end of ALTER operation and suddenly found
220
                    // a start to new statement, but have not find a delimiter between them
221
222 2
                    if (!($token->value == 'SET' && $list->tokens[$list->idx - 1]->value == 'CHARACTER')) {
223 2
                        $parser->error(
224 2
                            __('A new statement was found, but no delimiter between it and the previous one.'),
225
                            $token
226 2
                        );
227 2
                        break;
228
                    }
229
                }
230 5
                $ret->unknown[] = $token;
231 5
            }
232 8
        }
233
234 9
        if ($ret->options->isEmpty()) {
235 1
            $parser->error(
236 1
                __('Unrecognized alter operation.'),
237 1
                $list->tokens[$list->idx]
238 1
            );
239 1
        }
240
241 9
        --$list->idx;
242
243 9
        return $ret;
244
    }
245
246
    /**
247
     * @param AlterOperation $component the component to be built
248
     * @param array          $options   parameters for building
249
     *
250
     * @return string
251
     */
252 1
    public static function build($component, array $options = array())
253
    {
254 1
        $ret = $component->options . ' ';
255 1
        if ((isset($component->field)) && ($component->field !== '')) {
256 1
            $ret .= $component->field . ' ';
257 1
        }
258 1
        $ret .= TokensList::build($component->unknown);
259
260 1
        return $ret;
261
    }
262
}
263