Completed
Push — master ( 1bc4b8...c77c49 )
by ignace nyamagana
02:36
created

Query::__debugInfo()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
cc 1
eloc 2
nc 1
nop 0
crap 1
1
<?php
2
/**
3
 * League.Uri (http://uri.thephpleague.com)
4
 *
5
 * @package   League.uri
6
 * @author    Ignace Nyamagana Butera <[email protected]>
7
 * @copyright 2013-2015 Ignace Nyamagana Butera
8
 * @license   https://github.com/thephpleague/uri/blob/master/LICENSE (MIT License)
9
 * @version   4.2.0
10
 * @link      https://github.com/thephpleague/uri/
11
 */
12
namespace League\Uri\Components;
13
14
use InvalidArgumentException;
15
use League\Uri\Interfaces\Query as QueryInterface;
16
use League\Uri\QueryParser;
17
use League\Uri\Types\ImmutableCollectionTrait;
18
use League\Uri\Types\ImmutableComponentTrait;
19
20
/**
21
 * Value object representing a URI query component.
22
 *
23
 * @package League.uri
24
 * @author  Ignace Nyamagana Butera <[email protected]>
25
 * @since   1.0.0
26
 */
27
class Query implements QueryInterface
28
{
29
    use ImmutableComponentTrait;
30
31
    use ImmutableCollectionTrait;
32
33
    /**
34
     * Key/pair separator character
35
     *
36
     * @var string
37
     */
38
    protected static $separator = '&';
39
40
    /**
41
     * Preserve the delimiter
42
     *
43
     * @var bool
44
     */
45
    protected $preserveDelimiter = false;
46
47
    /**
48
     * DEPRECATION WARNING! This method will be removed in the next major point release
49
     *
50
     * @deprecated deprecated since version 4.2
51
     *
52
     * return a new instance from an array or a traversable object
53
     *
54
     * @param \Traversable|array $data
55
     *
56
     * @return static
57
     */
58
    public static function createFromArray($data)
59
    {
60
        return self::createFromPairs($data);
61
    }
62
63
    /**
64
     * return a new Query instance from an Array or a traversable object
65
     *
66
     * @param \Traversable|array $data
67
     *
68
     * @return static
69 108
     */
70
    public static function createFromPairs($data)
71 108
    {
72 102
        $data = static::validateIterator($data);
73 27
        if (empty($data)) {
74
            return new static();
75
        }
76 81
77
        $query = (new QueryParser())->build($data, static::$separator);
78 81
79
        return new static($query);
80
    }
81
82
    /**
83
     * a new instance
84
     *
85
     * @param string $data
86 967
     */
87
    public function __construct($data = null)
88 967
    {
89 967
        $this->data = $this->validate($data);
90 967
        $this->preserveDelimiter = null !== $data;
91
    }
92
93
    /**
94
     * sanitize the submitted data
95
     *
96
     * @param string $str
97
     *
98
     * @return array
99 967
     */
100
    protected function validate($str)
101 967
    {
102 474
        if (null === $str) {
103
            return [];
104
        }
105 754
106 754
        $str = $this->filterEncodedQuery($this->validateString($str));
107
108
        return (new QueryParser())->parse($str, static::$separator, PHP_QUERY_RFC3986);
109
    }
110
111
    /**
112 2
     * Filter the encoded query string
113
     *
114 2
     * @param string $str the encoded query
115
     *
116
     * @throws InvalidArgumentException If the encoded query is invalid
117
     *
118
     * @return string
119
     */
120 12
    protected function filterEncodedQuery($str)
121
    {
122 12
        if (false === strpos($str, '#')) {
123 12
            return $str;
124
        }
125 12
126
        throw new InvalidArgumentException(sprintf(
127
            'The encoded query `%s` contains invalid characters',
128
            $str
129
        ));
130
    }
131
132
    /**
133 880
     * @inheritdoc
134
     */
135 880
    public function __debugInfo()
136 501
    {
137
        return ['query' => $this->getContent()];
138
    }
139 664
140
    /**
141
     * @inheritdoc
142
     */
143
    public static function __set_state(array $properties)
144
    {
145
        $component = static::createFromPairs($properties['data']);
146
        $component->preserveDelimiter = $properties['preserveDelimiter'];
147
148 874
        return $component;
149
    }
150 874
151
    /**
152
     * Returns the component literal value.
153
     *
154
     * @return null|string
155
     */
156
    public function getContent()
157
    {
158
        if (!$this->preserveDelimiter) {
159 824
            return null;
160
        }
161 824
162 824
        return (new QueryParser())->build($this->data, static::$separator, PHP_QUERY_RFC3986);
163 590
    }
164
165
    /**
166 483
     * Returns the instance string representation; If the
167
     * instance is not defined an empty string is returned
168
     *
169
     * @return string
170
     */
171
    public function __toString()
172
    {
173
        return (string) $this->getContent();
174
    }
175
176
    /**
177
     * Returns the instance string representation
178
     * with its optional URI delimiters
179
     *
180
     * @return string
181
     */
182
    public function getUriComponent()
183
    {
184
        $query = $this->__toString();
185
        if ($this->preserveDelimiter) {
186
            return QueryInterface::DELIMITER.$query;
187
        }
188 54
189
        return $query;
190 54
    }
191
192
    /**
193
     * DEPRECATION WARNING! This method will be removed in the next major point release
194
     *
195
     * @deprecated deprecated since version 4.2
196
     *
197
     * Returns an array representation of the query
198
     *
199
     * @return array
200
     */
201
    public function toArray()
202
    {
203
        return $this->getPairs();
204 9
    }
205
206 9
    /**
207 9
     * Returns an array representation of the query
208 9
     *
209 3
     * @return array
210
     */
211
    public function getPairs()
212 6
    {
213
        return $this->data;
214
    }
215
216
    /**
217
     * Retrieves a single query parameter.
218
     *
219
     * Retrieves a single query parameter. If the parameter has not been set,
220
     * returns the default value provided.
221
     *
222
     * @param string $offset  the parameter name
223
     * @param mixed  $default Default value to return if the parameter does not exist.
224
     *
225 240
     * @return mixed
226
     */
227 240
    public function getValue($offset, $default = null)
228 207
    {
229
        $offset = $this->validateString($offset);
230
        $offset = $this->decodeComponent($offset);
231 33
        if (isset($this->data[$offset])) {
232
            return $this->data[$offset];
233
        }
234
235
        return $default;
236
    }
237
238
    /**
239
     * Returns an instance with the specified string
240
     *
241
     * This method MUST retain the state of the current instance, and return
242
     * an instance that contains the modified data
243
     *
244
     * @param string $value
245
     *
246
     * @return static
247
     */
248
    public function withContent($value = null)
249
    {
250
        if ($value === $this->getContent()) {
251
            return $this;
252
        }
253
254
        return new static($value);
255
    }
256
257
    /**
258
     * DEPRECATION WARNING! This method will be removed in the next major point release
259
     *
260
     * @deprecated deprecated since version 4.2
261
     *
262
     * @see withContent
263
     *
264
     * Returns an instance with the specified string
265 24
     *
266
     * This method MUST retain the state of the current instance, and return
267 24
     * an instance that contains the modified data
268 24
     *
269 3
     * @param string $value
270
     *
271
     * @return static
272 21
     */
273
    public function modify($value)
274
    {
275
        return $this->withContent($value);
276
    }
277
278
    /**
279
     * Returns an instance merge with the specified query
280
     *
281
     * This method MUST retain the state of the current instance, and return
282
     * an instance that contains the modified query
283
     *
284
     * @param QueryInterface|string $query the data to be merged
285
     *
286
     * @return static
287
     */
288
    public function merge($query)
289 57
    {
290
        $pairs = !$query instanceof QueryInterface ? $this->validate($query) : $query->getPairs();
291 57
        if ($this->data === $pairs) {
292 57
            return $this;
293 57
        }
294 57
295 45
        return static::createFromPairs(array_merge($this->data, $pairs));
296
    }
297
298 12
    /**
299
     * Sort the query string by offset, maintaining offset to data correlations.
300
     *
301
     * This method MUST retain the state of the current instance, and return
302
     * an instance that contains the modified query
303
     *
304 3
     * @param callable|int $sort a PHP sort flag constant or a comparaison function
305
     *                           which must return an integer less than, equal to,
306 3
     *                           or greater than zero if the first argument is
307 3
     *                           considered to be respectively less than, equal to,
308
     *                           or greater than the second.
309 3
     *
310
     * @return static
311
     */
312
    public function ksort($sort = SORT_REGULAR)
313
    {
314
        $func = is_callable($sort) ? 'uksort' : 'ksort';
315 6
        $data = $this->data;
316
        $func($data, $sort);
317 6
        if ($data === $this->data) {
318 3
            return $this;
319
        }
320
321 3
        return static::createFromPairs($data);
322
    }
323
324
    /**
325
     * @inheritdoc
326
     */
327 9
    public function hasKey($offset)
328
    {
329 9
        $offset = $this->validateString($offset);
330 9
        $offset = $this->decodeComponent($offset);
331 9
332 6
        return array_key_exists($offset, $this->data);
333
    }
334 9
335
    /**
336
     * @inheritdoc
337
     */
338
    public function keys()
339
    {
340
        if (0 === func_num_args()) {
341
            return array_keys($this->data);
342
        }
343
344
        return array_keys($this->data, $this->decodeComponent(func_get_arg(0)), true);
345
    }
346 42
347
    /**
348 42
     * @inheritdoc
349 15
     */
350
    public function without(array $offsets)
351
    {
352 27
        $data = $this->data;
353
        foreach ($offsets as $offset) {
354
            unset($data[$this->decodeComponent($offset)]);
355
        }
356
357
        return $this->newCollectionInstance($data);
358
    }
359
360
361
362
    /**
363
     * Return a new instance when needed
364
     *
365
     * @param array $data
366
     *
367
     * @return static
368
     */
369
    protected function newCollectionInstance(array $data)
370
    {
371
        if ($data === $this->data) {
372
            return $this;
373
        }
374
375
        return static::createFromPairs($data);
376
    }
377
}
378