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

Reference::__toString()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
ccs 2
cts 2
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 trim;
15
16
/**
17
 * `REFERENCES` keyword parser.
18
 */
19
final class Reference implements Component
20
{
21
    /**
22
     * All references options.
23
     *
24
     * @var array<string, int|array<int, int|string>>
25
     * @psalm-var array<string, (positive-int|array{positive-int, ('var'|'var='|'expr'|'expr=')})>
26
     */
27
    public static $referencesOptions = [
28
        'MATCH' => [
29
            1,
30
            'var',
31
        ],
32
        'ON DELETE' => [
33
            2,
34
            'var',
35
        ],
36
        'ON UPDATE' => [
37
            3,
38
            'var',
39
        ],
40
    ];
41
42
    /**
43
     * The referenced table.
44
     *
45
     * @var Expression
46
     */
47
    public $table;
48
49
    /**
50
     * The referenced columns.
51
     *
52
     * @var string[]
53
     */
54
    public $columns;
55
56
    /**
57
     * The options of the referencing.
58
     *
59
     * @var OptionsArray
60
     */
61
    public $options;
62
63
    /**
64
     * @param Expression   $table   the name of the table referenced
65
     * @param string[]     $columns the columns referenced
66
     * @param OptionsArray $options the options
67
     */
68 20
    public function __construct($table = null, array $columns = [], $options = null)
69
    {
70 20
        $this->table = $table;
71 20
        $this->columns = $columns;
72 20
        $this->options = $options;
73
    }
74
75
    /**
76
     * @param Parser               $parser  the parser that serves as context
77
     * @param TokensList           $list    the list of tokens that are being parsed
78
     * @param array<string, mixed> $options parameters for parsing
79
     *
80
     * @return Reference
81
     */
82 18
    public static function parse(Parser $parser, TokensList $list, array $options = [])
83
    {
84 18
        $ret = new static();
85
86
        /**
87
         * The state of the parser.
88
         *
89
         * Below are the states of the parser.
90
         *
91
         *      0 ----------------------[ table ]---------------------> 1
92
         *
93
         *      1 ---------------------[ columns ]--------------------> 2
94
         *
95
         *      2 ---------------------[ options ]--------------------> (END)
96
         *
97
         * @var int
98
         */
99 18
        $state = 0;
100
101 18
        for (; $list->idx < $list->count; ++$list->idx) {
102
            /**
103
             * Token parsed at this moment.
104
             */
105 18
            $token = $list->tokens[$list->idx];
106
107
            // End of statement.
108 18
            if ($token->type === Token::TYPE_DELIMITER) {
109 2
                break;
110
            }
111
112
            // Skipping whitespaces and comments.
113 18
            if (($token->type === Token::TYPE_WHITESPACE) || ($token->type === Token::TYPE_COMMENT)) {
114 16
                continue;
115
            }
116
117 18
            if ($state === 0) {
118 18
                $ret->table = Expression::parse(
119 18
                    $parser,
120 18
                    $list,
121 18
                    [
122 18
                        'parseField' => 'table',
123 18
                        'breakOnAlias' => true,
124 18
                    ]
125 18
                );
126 18
                $state = 1;
127 18
            } elseif ($state === 1) {
128 18
                $ret->columns = ArrayObj::parse($parser, $list)->values;
129 18
                $state = 2;
130 16
            } elseif ($state === 2) {
131 16
                $ret->options = OptionsArray::parse($parser, $list, static::$referencesOptions);
132 16
                ++$list->idx;
133 16
                break;
134
            }
135
        }
136
137 18
        --$list->idx;
138
139 18
        return $ret;
140
    }
141
142
    /**
143
     * @param Reference            $component the component to be built
144
     * @param array<string, mixed> $options   parameters for building
145
     */
146 6
    public static function build($component, array $options = []): string
147
    {
148 6
        return trim(
149 6
            $component->table
150 6
            . ' (' . implode(', ', Context::escape($component->columns)) . ') '
151 6
            . $component->options
152 6
        );
153
    }
154
155 4
    public function __toString(): string
156
    {
157 4
        return static::build($this);
158
    }
159
}
160