Completed
Push — master ( 40347a...a5d136 )
by ignace nyamagana
04:24
created

Query::modify()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

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