Passed
Push — master ( ee792a...6ee6fa )
by Michal
03:51
created

src/Components/ArrayObj.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
/**
4
 * Parses an array.
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 array.
16
 *
17
 * @category   Components
18
 *
19
 * @license    https://www.gnu.org/licenses/gpl-2.0.txt GPL-2.0+
20
 */
21
class ArrayObj extends Component
22
{
23
    /**
24
     * The array that contains the unprocessed value of each token.
25
     *
26
     * @var array
27
     */
28
    public $raw = array();
29
30
    /**
31
     * The array that contains the processed value of each token.
32
     *
33
     * @var array
34
     */
35
    public $values = array();
36
37
    /**
38
     * Constructor.
39
     *
40
     * @param array $raw    the unprocessed values
41
     * @param array $values the processed values
42
     */
43 73
    public function __construct(array $raw = array(), array $values = array())
44
    {
45 73
        $this->raw = $raw;
46 73
        $this->values = $values;
47 73
    }
48
49
    /**
50
     * @param Parser     $parser  the parser that serves as context
51
     * @param TokensList $list    the list of tokens that are being parsed
52
     * @param array      $options parameters for parsing
53
     *
54
     * @return ArrayObj|Component[]
0 ignored issues
show
Should the return type not be ArrayObj|array?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
55
     */
56 71
    public static function parse(Parser $parser, TokensList $list, array $options = array())
57
    {
58 71
        $ret = empty($options['type']) ? new self() : array();
59
60
        /**
61
         * The last raw expression.
62
         *
63
         * @var string
64
         */
65 71
        $lastRaw = '';
66
67
        /**
68
         * The last value.
69
         *
70
         * @var string
71
         */
72 71
        $lastValue = '';
73
74
        /**
75
         * Counts brackets.
76
         *
77
         * @var int
78
         */
79 71
        $brackets = 0;
80
81
        /**
82
         * Last separator (bracket or comma).
83
         *
84
         * @var bool
85
         */
86 71
        $isCommaLast = false;
87
88 71
        for (; $list->idx < $list->count; ++$list->idx) {
89
            /**
90
             * Token parsed at this moment.
91
             *
92
             * @var Token
93
             */
94 71
            $token = $list->tokens[$list->idx];
95
96
            // End of statement.
97 71
            if ($token->type === Token::TYPE_DELIMITER) {
98 3
                break;
99
            }
100
101
            // Skipping whitespaces and comments.
102 71
            if (($token->type === Token::TYPE_WHITESPACE)
103 71
                || ($token->type === Token::TYPE_COMMENT)
104
            ) {
105 33
                $lastRaw .= $token->token;
106 33
                $lastValue = trim($lastValue) . ' ';
107 33
                continue;
108
            }
109
110 71
            if (($brackets === 0)
111 71
                && (($token->type !== Token::TYPE_OPERATOR)
112 70
                || ($token->value !== '('))
113
            ) {
114 1
                $parser->error('An opening bracket was expected.', $token);
115 1
                break;
116
            }
117
118 70
            if ($token->type === Token::TYPE_OPERATOR) {
119 70
                if ($token->value === '(') {
120 70
                    if (++$brackets === 1) { // 1 is the base level.
121 70
                        continue;
122
                    }
123 70
                } elseif ($token->value === ')') {
124 67
                    if (--$brackets === 0) { // Array ended.
125 67
                        break;
126
                    }
127 38
                } elseif ($token->value === ',') {
128 38
                    if ($brackets === 1) {
129 38
                        $isCommaLast = true;
130 38 View Code Duplication
                        if (empty($options['type'])) {
131 35
                            $ret->raw[] = trim($lastRaw);
132 35
                            $ret->values[] = trim($lastValue);
133 35
                            $lastRaw = $lastValue = '';
134
                        }
135
                    }
136 38
                    continue;
137
                }
138
            }
139
140 68
            if (empty($options['type'])) {
141 66
                $lastRaw .= $token->token;
142 66
                $lastValue .= $token->value;
143
            } else {
144 3
                $ret[] = $options['type']::parse(
145 3
                    $parser,
146 3
                    $list,
147 3
                    empty($options['typeOptions']) ? array() : $options['typeOptions']
148
                );
149
            }
150
        }
151
152
        // Handling last element.
153
        //
154
        // This is treated differently to treat the following cases:
155
        //
156
        //           => array()
157
        //      (,)  => array('', '')
158
        //      ()   => array()
159
        //      (a,) => array('a', '')
160
        //      (a)  => array('a')
161
        //
162 71
        $lastRaw = trim($lastRaw);
163 71 View Code Duplication
        if ((empty($options['type']))
164 69
            && ((strlen($lastRaw) > 0) || ($isCommaLast))
165
        ) {
166 66
            $ret->raw[] = $lastRaw;
167 66
            $ret->values[] = trim($lastValue);
168
        }
169
170 71
        return $ret;
171
    }
172
173
    /**
174
     * @param ArrayObj|ArrayObj[] $component the component to be built
175
     * @param array               $options   parameters for building
176
     *
177
     * @return string
178
     */
179 9
    public static function build($component, array $options = array())
180
    {
181 9
        if (is_array($component)) {
182 3
            return implode(', ', $component);
183 9
        } elseif (!empty($component->raw)) {
184 8
            return '(' . implode(', ', $component->raw) . ')';
185
        }
186
187 1
        return '(' . implode(', ', $component->values) . ')';
188
    }
189
}
190