Completed
Pull Request — master (#58)
by ignace nyamagana
03:11
created

Query::modify()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 12
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 4

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 12
ccs 6
cts 6
cp 1
rs 9.2
cc 4
eloc 6
nc 3
nop 1
crap 4
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 string
44
     */
45
    protected $preserveDelimiter = false;
46
47
    /**
48
     * a new instance
49
     *
50
     * @param string $data
51
     */
52 767
    public function __construct($data = null)
53
    {
54 767
        if (null !== $data) {
55 611
            $this->preserveDelimiter = true;
0 ignored issues
show
Documentation Bug introduced by
The property $preserveDelimiter was declared of type string, but true is of type boolean. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
56 611
            $this->data = $this->validate($data);
57 406
        }
58 767
    }
59
60
    /**
61
     * sanitize the submitted data
62
     *
63
     * @param string $str
64
     *
65
     * @throws InvalidArgumentException If reserved characters are used
66
     *
67
     * @return array
68
     */
69 611
    protected function validate($str)
70
    {
71 611
        $str = $this->validateString($str);
72 611
        if (strpos($str, '#') !== false) {
73 3
            throw new InvalidArgumentException('the query string must not contain a URI fragment');
74
        }
75
76 611
        return (new QueryParser())->parse($str, static::$separator, false);
77
    }
78
79
    /**
80
     * return a new Query instance from an Array or a traversable object
81
     *
82
     * @param \Traversable|array $data
83
     *
84
     * @return static
85
     */
86 102
    public static function createFromArray($data)
87
    {
88 102
        $data = static::validateIterator($data);
89 96
        if (empty($data)) {
90 27
            return new static(null);
91
        }
92
93 78
        $query = (new QueryParser())->build($data, static::$separator, PHP_QUERY_RFC3986);
94
95 78
        return new static($query);
96
    }
97
98
    /**
99
     * @inheritdoc
100
     */
101 1
    public function __debugInfo()
102
    {
103 1
        return ['query' => $this->__toString()];
104
    }
105
106
    /**
107
     * @inheritdoc
108
     */
109 12
    public static function __set_state(array $properties)
110
    {
111 12
        $component = static::createFromArray($properties['data']);
112 12
        $component->preserveDelimiter = $properties['preserveDelimiter'];
113
114 12
        return $component;
115
    }
116
117
    /**
118
     * Returns the instance string representation; If the
119
     * instance is not defined an empty string is returned
120
     *
121
     * @return string
122
     */
123 674
    public function __toString()
124
    {
125 674
        return (new QueryParser())->build($this->data, static::$separator, PHP_QUERY_RFC3986);
126
    }
127
128
    /**
129
     * Returns the instance string representation
130
     * with its optional URI delimiters
131
     *
132
     * @return string
133
     */
134 625
    public function getUriComponent()
135
    {
136 625
        $query = $this->__toString();
137 625
        if ($this->preserveDelimiter) {
138 454
            return QueryInterface::DELIMITER.$query;
139
        }
140
141 330
        return $query;
142
    }
143
144
    /**
145
     * Returns an instance with the specified string
146
     *
147
     * This method MUST retain the state of the current instance, and return
148
     * an instance that contains the modified data
149
     *
150
     * @param string $value
151
     *
152
     * @return static
153
     */
154 162
    public function modify($value)
155
    {
156 162
        if (null === $value && [] === $this->data) {
157 117
            return $this;
158
        }
159
160 45
        if ($value == $this->__toString()) {
161 18
            return $this;
162
        }
163
164 27
        return new static($value);
165
    }
166
167
    /**
168
     * Retrieves a single query parameter.
169
     *
170
     * Retrieves a single query parameter. If the parameter has not been set,
171
     * returns the default value provided.
172
     *
173
     * @param string $offset  the parameter name
174
     * @param mixed  $default Default value to return if the parameter does not exist.
175
     *
176
     * @return mixed
177
     */
178 9
    public function getValue($offset, $default = null)
179
    {
180 9
        $offset = rawurldecode($offset);
181 9
        if (isset($this->data[$offset])) {
182 3
            return $this->data[$offset];
183
        }
184
185 6
        return $default;
186
    }
187
188
    /**
189
     * Returns an instance merge with the specified query
190
     *
191
     * This method MUST retain the state of the current instance, and return
192
     * an instance that contains the modified query
193
     *
194
     * @param Query|string $query the data to be merged query can be
195
     *                            - another Interfaces\Query object
196
     *                            - a string or a Stringable object
197
     *
198
     * @return static
199
     */
200 24
    public function merge($query)
201
    {
202 24
        if (!$query instanceof QueryInterface) {
203 6
            $query = static::createFromArray($this->validate($query));
204 4
        }
205
206 24
        if ($this->sameValueAs($query)) {
207 3
            return $this;
208
        }
209
210 21
        return static::createFromArray(array_merge($this->toArray(), $query->toArray()));
211
    }
212
213
    /**
214
     * Sort the query string by offset, maintaining offset to data correlations.
215
     *
216
     * This method MUST retain the state of the current instance, and return
217
     * an instance that contains the modified query
218
     *
219
     * @param callable|int $sort a PHP sort flag constant or a comparaison function
220
     *                           which must return an integer less than, equal to,
221
     *                           or greater than zero if the first argument is
222
     *                           considered to be respectively less than, equal to,
223
     *                           or greater than the second.
224
     *
225
     * @return static
226
     */
227 45
    public function ksort($sort = SORT_REGULAR)
228
    {
229 45
        $func = is_callable($sort) ? 'uksort' : 'ksort';
230 45
        $data = $this->data;
231 45
        $func($data, $sort);
232 45
        if ($data === $this->data) {
233 33
            return $this;
234
        }
235
236 12
        return static::createFromArray($data);
237
    }
238
239
    /**
240
     * Return a new instance when needed
241
     *
242
     * @param array $data
243
     *
244
     * @return static
245
     */
246 42
    protected function newCollectionInstance(array $data)
247
    {
248 42
        if ($data == $this->data) {
249 15
            return $this;
250
        }
251
252 27
        return static::createFromArray($data);
253
    }
254
}
255