Completed
Push — master ( cee824...b1d97d )
by Robbert
06:12 queued 02:02
created

Query::parseQueryString()   B

Complexity

Conditions 6
Paths 2

Size

Total Lines 25
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 14
CRAP Score 6

Importance

Changes 5
Bugs 3 Features 1
Metric Value
c 5
b 3
f 1
dl 0
loc 25
ccs 14
cts 14
cp 1
rs 8.439
cc 6
eloc 15
nc 2
nop 1
crap 6
1
<?php
2
3
/*
4
 * This file is part of the Ariadne Component Library.
5
 *
6
 * (c) Muze <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace arc\url;
13
14
/**
15
 *  Query parses any valid url query part and generates array accessible values for it
16
 *  - you can use the same name multiple times -- ?name=value1&name=value2
17
 *    this will result in name becoming an array, similarly arrays will not be encoded with trailing [] behind the name
18
 *  - you can use names without values -- ?name&name2&name3
19
 *  - names may include any valid character -- ?valid+name
20
 *
21
 */
22
class Query extends \ArrayObject implements QueryInterface
23
{
24 14
    public function __construct($query = '')
25
    {
26 14
        parent::__construct( $this->parse( $query ), \ArrayObject::ARRAY_AS_PROPS );
27 14
    }
28
29 12
    public function __toString()
30
    {
31 12
        return str_replace( ['%7E', '%20'], ['~', '+'], // ~ and + are often unnecesarily encoded
32 12
            $this->compile( (array) $this )
33
        );
34
    }
35
36
    /**
37
     *	Import a query string or an array of key => value pairs into the UrlQuery.
38
     *
39
     *	Usage:
40
     *		$query->import( 'foo=bar&bar=1' );
41
     *		$query->import( array( 'foo' => 'bar', 'bar' => 1 ) );
42
     *
43
     *	@param string|array $values query string or array of values to import into this query
44
     */
45 14
    public function import($values)
46
    {
47 14
        $this->exchangeArray( $this->parse( $values ) + $this->getArrayCopy() );
48
49 14
        return $this;
50
    }
51
52
    /**
53
     * Removes all current query parameters.
54
     * @return $this
55
     */
56
    public function reset()
57
    {
58
        $this->exchangeArray( [] );
59
60
        return $this;
61
    }
62
63
    // === \arc\KeyValueStoreInterface ===
64
65
    /**
66
     *	@param string $name name of the query parameter
67
     *	@return mixed The named query parameter
68
     */
69
    public function getvar($name)
70
    {
71
        return $this->offsetGet($name);
72
    }
73
74
    /**
75
     *	@param string $name name for the query parameter
76
     *	@param mixed $value value of the query parameter
77
     */
78
    public function putvar($name, $value)
79
    {
80
        $this->offsetSet($name, $value);
81
    }
82
83 2
    protected function compile($values)
84
    {
85 2
        $result = array();
86 2
        foreach ($values as $name => $value) {
87 2
            $result[] = $this->encodeValue( $name, $value );
88
        }
89
90 2
        return implode( '&', $result );
91
    }
92
93 14
    protected function parse($values)
94
    {
95 14
        $result = array();
96 14
        if (is_array( $values ) || ( $values instanceof \Traversable )) {
97
            foreach ($values as $name => $value) {
98
                $result[$name] = $value;
99
            }
100 14
        } elseif (is_string( $values )) {
101 14
            $result = $this->parseQueryString( $values );
102
        }
103
104 14
        return $result;
105
    }
106
107 3
    protected function parseQueryString($queryString)
108
    {
109 3
        $result = array();
110 3
        if ($queryString) {
111 3
            $values = preg_split( '/[\&\;]/', $queryString );
112 3
            foreach ($values as $queryStringEntry) {
113 3
                list( $name, $value ) = $this->parseQueryStringEntry( $queryStringEntry );
114 3
                if (!isset($value)) {
115
                    // no '=' in query entry  => ?name&...
116 2
                    $result[] = $name;
117 2
                } elseif (!isset( $result[$name] )) {
118
                    // new entry => ?name=1&...
0 ignored issues
show
Unused Code Comprehensibility introduced by
47% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
119 2
                    $result[ $name ] = $value;
120 1
                } elseif (!is_array( $result[$name] )) {
121
                    // entry with same name exists already but is not an array yet => ?name=1&name=2&...
122 1
                    $result[ $name ] = array( $result[$name], $value );
123
                } else {
124
                    // entry with same name exists and is an array => ?name=1&name=2&name=3&...
125 3
                    $result[ $name ][] = $value;
126
                }
127
            }
128
        }
129
130 3
        return $result;
131
    }
132
133 3
    private function parseQueryStringEntry($queryStringEntry)
134
    {
135 3
        $result = explode( '=', $queryStringEntry, 2 ) + array( 1 => null ); // value may be null if no '=' is found in the query string
136 3
        foreach ($result as $key => $value) {
137 3
            if (isset($value)) {
138 3
                $value = urldecode( $value );
139
            }
140 3
            $result[$key] = $value;
141
        }
142
143 3
        return $result;
144
    }
145
146 2
    private function encodeValue($name, $value = null)
147
    {
148 2
        if (is_array( $value )) {
149 1
            $result = array();
150 1
            foreach ($value as $val) {
151 1
                $result[] = $this->encodeValue( $name, $val );
152
            }
153
154 1
            return implode( '&', $result );
155
        } else {
156 2
            return ( is_numeric( $name )
157 2
                ? RawUrlEncode( $value )
158 2
                : RawUrlEncode( $name ) . ( isset( $value ) ? '=' . RawUrlEncode( (string) $value ) : '' )
159
            );
160
        }
161
    }
162
}
163