Passed
Push — master ( 6c3f09...c54108 )
by William
03:43
created

ParameterDefinition::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 3
dl 0
loc 5
ccs 4
cts 4
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace PhpMyAdmin\SqlParser\Components;
6
7
use PhpMyAdmin\SqlParser\Component;
8
use PhpMyAdmin\SqlParser\Context;
9
use PhpMyAdmin\SqlParser\Parser;
10
use PhpMyAdmin\SqlParser\Token;
11
use PhpMyAdmin\SqlParser\TokensList;
12
13
use function implode;
14
use function is_array;
15
use function trim;
16
17
/**
18
 * The definition of a parameter of a function or procedure.
19
 */
20
final class ParameterDefinition implements Component
21
{
22
    /**
23
     * The name of the new column.
24
     *
25
     * @var string
26
     */
27
    public $name;
28
29
    /**
30
     * Parameter's direction (IN, OUT or INOUT).
31
     *
32
     * @var string
33
     */
34
    public $inOut;
35
36
    /**
37
     * The data type of thew new column.
38
     *
39
     * @var DataType
40
     */
41
    public $type;
42
43
    /**
44
     * @param string   $name  parameter's name
45
     * @param string   $inOut parameter's directional type (IN / OUT or None)
46
     * @param DataType $type  parameter's type
47
     */
48 48
    public function __construct($name = null, $inOut = null, $type = null)
49
    {
50 48
        $this->name = $name;
51 48
        $this->inOut = $inOut;
52 48
        $this->type = $type;
53
    }
54
55
    /**
56
     * @param Parser               $parser  the parser that serves as context
57
     * @param TokensList           $list    the list of tokens that are being parsed
58
     * @param array<string, mixed> $options parameters for parsing
59
     *
60
     * @return ParameterDefinition[]
61
     */
62 48
    public static function parse(Parser $parser, TokensList $list, array $options = [])
63
    {
64 48
        $ret = [];
65
66 48
        $expr = new static();
67
68
        /**
69
         * The state of the parser.
70
         *
71
         * Below are the states of the parser.
72
         *
73
         *      0 -----------------------[ ( ]------------------------> 1
74
         *
75
         *      1 ----------------[ IN / OUT / INOUT ]----------------> 1
76
         *      1 ----------------------[ name ]----------------------> 2
77
         *
78
         *      2 -------------------[ data type ]--------------------> 3
79
         *
80
         *      3 ------------------------[ , ]-----------------------> 1
81
         *      3 ------------------------[ ) ]-----------------------> (END)
82
         *
83
         * @var int
84
         */
85 48
        $state = 0;
86
87 48
        for (; $list->idx < $list->count; ++$list->idx) {
88
            /**
89
             * Token parsed at this moment.
90
             */
91 48
            $token = $list->tokens[$list->idx];
92
93
            // End of statement.
94 48
            if ($token->type === Token::TYPE_DELIMITER) {
95 4
                break;
96
            }
97
98
            // Skipping whitespaces and comments.
99 48
            if (($token->type === Token::TYPE_WHITESPACE) || ($token->type === Token::TYPE_COMMENT)) {
100 40
                continue;
101
            }
102
103 48
            if ($state === 0) {
104 48
                if (($token->type === Token::TYPE_OPERATOR) && ($token->value === '(')) {
105 46
                    $state = 1;
106
                }
107
108 48
                continue;
109 46
            } elseif ($state === 1) {
110 46
                if (($token->value === 'IN') || ($token->value === 'OUT') || ($token->value === 'INOUT')) {
111 18
                    $expr->inOut = $token->value;
112 18
                    ++$list->idx;
113 46
                } elseif ($token->value === ')') {
114 6
                    ++$list->idx;
115 6
                    break;
116
                } else {
117 40
                    $expr->name = $token->value;
118 40
                    $state = 2;
119
                }
120 40
            } elseif ($state === 2) {
121 40
                $expr->type = DataType::parse($parser, $list);
122 40
                $state = 3;
123 40
            } elseif ($state === 3) {
124 40
                $ret[] = $expr;
125 40
                $expr = new static();
126 40
                if ($token->value === ',') {
127 6
                    $state = 1;
128 38
                } elseif ($token->value === ')') {
129 38
                    ++$list->idx;
130 38
                    break;
131
                }
132
            }
133
        }
134
135
        // Last iteration was not saved.
136 48
        if (isset($expr->name) && ($expr->name !== '')) {
137 2
            $ret[] = $expr;
138
        }
139
140 48
        --$list->idx;
141
142 48
        return $ret;
143
    }
144
145
    /**
146
     * @param ParameterDefinition[] $component the component to be built
147
     * @param array<string, mixed>  $options   parameters for building
148
     */
149 6
    public static function build($component, array $options = []): string
150
    {
151 6
        if (is_array($component)) {
0 ignored issues
show
introduced by
The condition is_array($component) is always true.
Loading history...
152 6
            return '(' . implode(', ', $component) . ')';
153
        }
154
155 6
        $tmp = '';
156 6
        if (! empty($component->inOut)) {
157 4
            $tmp .= $component->inOut . ' ';
158
        }
159
160 6
        return trim(
161 6
            $tmp . Context::escape($component->name) . ' ' . $component->type
162 6
        );
163
    }
164
165 6
    public function __toString(): string
166
    {
167 6
        return static::build($this);
0 ignored issues
show
Bug introduced by
$this of type PhpMyAdmin\SqlParser\Com...nts\ParameterDefinition is incompatible with the type PhpMyAdmin\SqlParser\Com...s\ParameterDefinition[] expected by parameter $component of PhpMyAdmin\SqlParser\Com...eterDefinition::build(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

167
        return static::build(/** @scrutinizer ignore-type */ $this);
Loading history...
168
    }
169
}
170