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

Key::parse()   D

Complexity

Conditions 20
Paths 3

Size

Total Lines 85
Code Lines 40

Duplication

Lines 7
Ratio 8.24 %

Code Coverage

Tests 43
CRAP Score 20

Importance

Changes 0
Metric Value
cc 20
eloc 40
nc 3
nop 3
dl 7
loc 85
ccs 43
cts 43
cp 1
crap 20
rs 4.7819
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 the definition of a key.
5
 */
6
7
namespace PhpMyAdmin\SqlParser\Components;
8
9
use PhpMyAdmin\SqlParser\Context;
10
use PhpMyAdmin\SqlParser\Component;
11
use PhpMyAdmin\SqlParser\Parser;
12
use PhpMyAdmin\SqlParser\Token;
13
use PhpMyAdmin\SqlParser\TokensList;
14
15
/**
16
 * Parses the definition of a key.
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 Key extends Component
25
{
26
    /**
27
     * All key options.
28
     *
29
     * @var array
30
     */
31
    public static $KEY_OPTIONS = array(
32
        'KEY_BLOCK_SIZE' => array(1, 'var'),
33
        'USING' => array(2, 'var'),
34
        'WITH PARSER' => array(3, 'var'),
35
        'COMMENT' => array(4, 'var='),
36
    );
37
38
    /**
39
     * The name of this key.
40
     *
41
     * @var string
42
     */
43
    public $name;
44
45
    /**
46
     * Columns.
47
     *
48
     * @var array
49
     */
50
    public $columns;
51
52
    /**
53
     * The type of this key.
54
     *
55
     * @var string
56
     */
57
    public $type;
58
59
    /**
60
     * The options of this key.
61
     *
62
     * @var OptionsArray
63
     */
64
    public $options;
65
66
    /**
67
     * Constructor.
68
     *
69
     * @param string       $name    the name of the key
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...
70
     * @param array        $columns the columns covered by this key
71
     * @param string       $type    the type of this key
0 ignored issues
show
Documentation introduced by
Should the type for parameter $type 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...
72
     * @param OptionsArray $options the options of this key
0 ignored issues
show
Documentation introduced by
Should the type for parameter $options not be OptionsArray|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...
73
     */
74 13
    public function __construct(
75
        $name = null,
76
        array $columns = array(),
77
        $type = null,
78
        $options = null
79
    ) {
80 13
        $this->name = $name;
81 13
        $this->columns = $columns;
82 13
        $this->type = $type;
83 13
        $this->options = $options;
84 13
    }
85
86
    /**
87
     * @param Parser     $parser  the parser that serves as context
88
     * @param TokensList $list    the list of tokens that are being parsed
89
     * @param array      $options parameters for parsing
90
     *
91
     * @return Key
92
     */
93 13
    public static function parse(Parser $parser, TokensList $list, array $options = array())
94
    {
95 13
        $ret = new self();
96
97
        /**
98
         * Last parsed column.
99
         *
100
         * @var array
101
         */
102 13
        $lastColumn = array();
103
104
        /**
105
         * The state of the parser.
106
         *
107
         * Below are the states of the parser.
108
         *
109
         *      0 ----------------------[ type ]-----------------------> 1
110
         *
111
         *      1 ----------------------[ name ]-----------------------> 1
112
         *      1 ---------------------[ columns ]---------------------> 2
113
         *
114
         *      2 ---------------------[ options ]---------------------> 3
115
         *
116
         * @var int
117
         */
118 13
        $state = 0;
119
120 13
        for (; $list->idx < $list->count; ++$list->idx) {
121
            /**
122
             * Token parsed at this moment.
123
             *
124
             * @var Token
125
             */
126 13
            $token = $list->tokens[$list->idx];
127
128
            // End of statement.
129 13
            if ($token->type === Token::TYPE_DELIMITER) {
130 2
                break;
131
            }
132
133
            // Skipping whitespaces and comments.
134 12
            if (($token->type === Token::TYPE_WHITESPACE) || ($token->type === Token::TYPE_COMMENT)) {
135 12
                continue;
136
            }
137
138 12
            if ($state === 0) {
139 12
                $ret->type = $token->value;
140 12
                $state = 1;
141 12 View Code Duplication
            } elseif ($state === 1) {
142 12
                if (($token->type === Token::TYPE_OPERATOR) && ($token->value === '(')) {
143 12
                    $state = 2;
144 12
                } else {
145 9
                    $ret->name = $token->value;
146
                }
147 12
            } elseif ($state === 2) {
148 12
                if ($token->type === Token::TYPE_OPERATOR) {
149 12
                    if ($token->value === '(') {
150 2
                        $state = 3;
151 12
                    } elseif (($token->value === ',') || ($token->value === ')')) {
152 12
                        $state = ($token->value === ',') ? 2 : 4;
153 12
                        if (!empty($lastColumn)) {
154 12
                            $ret->columns[] = $lastColumn;
155 12
                            $lastColumn = array();
156 12
                        }
157 12
                    }
158 12
                } else {
159 12
                    $lastColumn['name'] = $token->value;
160
                }
161 12
            } elseif ($state === 3) {
162 2
                if (($token->type === Token::TYPE_OPERATOR) && ($token->value === ')')) {
163 2
                    $state = 2;
164 2
                } else {
165 2
                    $lastColumn['length'] = $token->value;
166
                }
167 11
            } elseif ($state === 4) {
168 11
                $ret->options = OptionsArray::parse($parser, $list, static::$KEY_OPTIONS);
169 11
                ++$list->idx;
170 11
                break;
171
            }
172 12
        }
173
174 13
        --$list->idx;
175
176 13
        return $ret;
177
    }
178
179
    /**
180
     * @param Key   $component the component to be built
181
     * @param array $options   parameters for building
182
     *
183
     * @return string
184
     */
185 3
    public static function build($component, array $options = array())
186
    {
187 3
        $ret = $component->type . ' ';
188 3
        if (!empty($component->name)) {
189 2
            $ret .= Context::escape($component->name) . ' ';
190 2
        }
191
192 3
        $columns = array();
193 3
        foreach ($component->columns as $column) {
194 3
            $tmp = Context::escape($column['name']);
195 3
            if (isset($column['length'])) {
196 1
                $tmp .= '(' . $column['length'] . ')';
197 1
            }
198 3
            $columns[] = $tmp;
199 3
        }
200
201 3
        $ret .= '(' . implode(',', $columns) . ') ' . $component->options;
202
203 3
        return trim($ret);
204
    }
205
}
206