Completed
Push — master ( c5a503...3ca135 )
by Derek
02:10
created

Query   A

Complexity

Total Complexity 8

Size/Duplication

Total Lines 108
Duplicated Lines 0 %

Coupling/Cohesion

Components 3
Dependencies 1

Test Coverage

Coverage 100%

Importance

Changes 3
Bugs 0 Features 0
Metric Value
wmc 8
lcom 3
cbo 1
dl 0
loc 108
ccs 35
cts 35
cp 1
rs 10
c 3
b 0
f 0

5 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 13 3
A isValid() 0 4 1
A toUriString() 0 10 2
A compileValidPattern() 0 10 1
A compileUnencodedCharacters() 0 9 1
1
<?php
2
namespace Subreality\Dilmun\Anshar\Http\UriParts;
3
4
/**
5
 * Class Query
6
 * @package Subreality\Dilmun\Anshar\Http\UriParts
7
 */
8
class Query extends AbstractUriPart
9
{
10
    protected $unencoded_characters = array("/", "?");
11
12
    /**
13
     * Query constructor. Accepts a string representing a URI query. Construction will throw an exception if the
14
     * query is not a string.
15
     *
16
     * Construction accepts strings that have been percent-encoded as well as string that have not been percent-encoded
17
     * and will encode invalid characters.
18
     *
19
     * Construction with a string that includes both encoded and decoded characters will be assumed to be an encoded
20
     * string, resulting in double-encoding.
21
     *
22
     * query       = *( pchar / "/" / "?" )
23
     * pchar       = unreserved / pct-encoded / sub-delims / ":" / "@"
24
     * unreserved  = ALPHA / DIGIT / "-" / "." / "_" / "~"
25
     * pct-encoded = "%" HEXDIG HEXDIG
26
     * sub-delims  = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="
27
     *
28
     * @see https://tools.ietf.org/html/rfc3986#appendix-A
29
     *
30
     * @throws \InvalidArgumentException
31
     *
32
     * @param string $query     A string representing a URI query
33
     */
34 89
    public function __construct($query)
35
    {
36 89
        $this->compileValidPattern();
37 89
        $this->compileUnencodedCharacters();
38
39 89
        if (!is_string($query)) {
40 6
            throw new \InvalidArgumentException("Query must be a string");
41 83
        } elseif (!self::isValid($query)) {
42 7
            $query = $this->encode($query);
43 7
        }
44
45 83
        $this->data = $query;
46 83
    }
47
48
    /**
49
     * Determines whether a given query adheres to the RFC3986 specification:
50
     *
51
     * query       = *( pchar / "/" / "?" )
52
     * pchar       = unreserved / pct-encoded / sub-delims / ":" / "@"
53
     * unreserved  = ALPHA / DIGIT / "-" / "." / "_" / "~"
54
     * pct-encoded = "%" HEXDIG HEXDIG
55
     * sub-delims  = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="
56
     *
57
     * @see https://tools.ietf.org/html/rfc3986#appendix-A
58
     * @see Query::$valid_pattern
59
     *
60
     * @param string $query     The query to check for validity
61
     * @return bool             Returns true if the provided query matches the RFC3986 specification
62
     *                          Returns false otherwise
63
     */
64 94
    public static function isValid($query)
65
    {
66 94
        return parent::isValid($query);
67
    }
68
69
    /**
70
     * Returns a string representation of the query formatted so that it can be compiled into a complete URI string
71
     * per the Uri object's string specification.
72
     *
73
     * If the query is empty, toUriString returns an empty string; if the query is not empty, toUriString returns the
74
     * query prefixed with a question mark.
75
     *
76
     * @see Uri::__toString
77
     *
78
     * @return string   A string representation of the query formatted for a complete URI string
79
     */
80 33
    public function toUriString()
81
    {
82 33
        $uri_query = $this->data;
83
84 33
        if (!empty($uri_query)) {
85 27
            $uri_query = "?" . $uri_query;
86 27
        }
87
88 33
        return $uri_query;
89
    }
90
91
    /**
92
     * Compiles a regexp pattern based on predefined patterns that define allowed characters for a query. Note that the
93
     * pipe indicates that a query can either contain all defined characters or contain percent encoded characters.
94
     */
95 89
    protected function compileValidPattern()
96
    {
97 89
        self::$valid_pattern = '/^([\/\?' .
98 89
            $this->unreserved_pattern .
99 89
            $this->sub_delims_pattern .
100 89
            $this->pchar_pattern .
101 89
            ']|' .
102 89
            $this->pct_encoded_pattern .
103 89
            ')*$/';
104 89
    }
105
106 89
    protected function compileUnencodedCharacters()
107
    {
108 89
        $this->unencoded_characters = array_merge(
109 89
            $this->unencoded_characters,
110 89
            $this->unreserved_characters,
111 89
            $this->pchar_characters,
112 89
            $this->sub_delims_characters
113 89
        );
114 89
    }
115
}
116