Completed
Push — master ( e44420...645bfc )
by Derek
02:15
created

AbstractUriPart::getValidPattern()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 7
ccs 4
cts 4
cp 1
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 4
nc 1
nop 0
crap 1
1
<?php
2
namespace Subreality\Dilmun\Anshar\Http\UriParts;
3
4
use Subreality\Dilmun\Anshar\Utils\StringHelper;
5
6
/**
7
 * Class AbstractUriPart
8
 * @package Subreality\Dilmun\Anshar\Http\UriParts
9
 */
10
abstract class AbstractUriPart implements UriPartInterface
11
{
12
    protected static $unreserved_pattern  = '\w\-\.~';
13
    protected static $pct_encoded_pattern = '%[A-Fa-f0-9]{2}';
14
    protected static $sub_delims_pattern  = '\!\$&\'\(\)\*\+,;\=';
15
    protected static $pchar_pattern       = '\:@';
16
17
    protected static $unreserved_characters = array("_", "-", ".", "~");
18
    protected static $pchar_characters      = array(":", "@");
19
20
    protected static $sub_delims_characters = array(
21
        "!",
22
        "$",
23
        "&",
24
        "'",
25
        "(",
26
        ")",
27
        "*",
28
        "+",
29
        ",",
30
        ";",
31
        "=",
32
    );
33
34
    protected $data = "";
35
36
    /**
37
     * Provides a common composition of allowed characters for validation and encoding.
38
     *
39
     * @see AbstractUriPart::compileUnencodedCharacters()
40
     * @see AbstractUriPart::compileValidPattern()
41
     *
42
     * @var array
43
     */
44
    protected static $compositions = array(
45
        "unreserved_characters",
46
        "pchar_characters",
47
        "sub_delims_characters",
48
    );
49
50
    protected static $unencoded_characters = array();
51
52
    protected static $valid_pattern;
53
54
    /**
55
     * Constructor for URI parts.
56
     *
57
     * Note that, if overriding the abstract class's constructor, care should be taken to compile unencoded characters
58
     * prior to compiling the part's valid pattern, as the default behavior of the abstract class is to base the part's
59
     * validation pattern on compiled unencoded characters.
60
     *
61
     * @see AbstractUriPart::compileUnencodedCharacters()
62
     * @see AbstractUriPart::compileValidPattern()
63
     *
64
     * @param string $part_data The data used to construct a URI part
65
     * @param string $part_name The name of the URI part for exception reporting
66
     * @param string $part_type [optional] The expected type of the URI part
67
     */
68 173
    public function __construct($part_data, $part_name, $part_type = "string")
69
    {
70 173
        if (gettype($part_data) != $part_type) {
71 30
            throw new \InvalidArgumentException("{$part_name} must be a {$part_type}");
72 149
        } elseif (!static::isValid($part_data)) {
73 24
            $part_data = $this->encode($part_data);
74 24
        }
75
76 149
        $this->data = $part_data;
77 149
    }
78
79
    /**
80
     * Returns a string representation of the URI component
81
     *
82
     * @return string   A string representation of the URI component
83
     */
84 130
    public function __toString()
85
    {
86 130
        return (string) $this->data;
87
    }
88
89 5
    public static function getValidPattern()
90
    {
91 5
        static::compileValidPattern();
92 5
        echo static::$valid_pattern . "\n";
93
94 5
        return static::$valid_pattern;
95
    }
96
97
    /**
98
     * Determines whether a given string adheres to the RFC3986 specification for the extending URI part.
99
     *
100
     * Requires extending classes to define self::$valid_pattern.
101
     *
102
     * @see https://tools.ietf.org/html/rfc3986#appendix-A
103
     *
104
     * @param mixed $data   The data to check for validity
105
     *
106
     * @return bool         Returns true if the provided query matches the RFC3986 specification
107
     *                      Returns false otherwise
108
     */
109 203
    public static function isValid($data)
110
    {
111 203
        static::compileValidPattern();
112
113 203
        return (bool) preg_match(static::$valid_pattern, $data);
114
    }
115
116
    /**
117
     * @return string
118
     */
119 45
    public function toUriString()
120
    {
121 45
        return (string) $this;
122
    }
123
124
    /**
125
     * Percent-encodes invalid characters within a given string. Percent-encoding ignores valid as defined by the
126
     * component per RFC3986.
127
     *
128
     * @see https://tools.ietf.org/html/rfc3986#appendix-A
129
     *
130
     * @param string $string     The query string to be percent-encoded
131
     *
132
     * @return string            The query string with invalid characters percent-encoded
133
     */
134 24
    protected function encode($string)
135
    {
136 24
        $encoded_query = $string;
137
138 24
        if (!empty(static::$unencoded_characters)) {
139 24
            $string_helper = new StringHelper($string);
140
141 24
            $encoded_query = $string_helper->affectChunks("rawurlencode", ...static::$unencoded_characters);
142 24
        }
143
144 24
        return $encoded_query;
145
    }
146
147
    /**
148
     * Creates a validation pattern based upon a URI part's unencoded characters, allowing for empty strings (^$),
149
     * word characters (\w), and percent encoding by default.
150
     *
151
     * @see AbstractUriPart::compileUnencodedCharacters()
152
     *
153
     * @return void
154
     */
155 195
    protected static function compileValidPattern()
156
    {
157 195
        static::compileUnencodedCharacters();
158
159 195
        $valid_character_string = implode(static::$unencoded_characters);
160
161 195
        $part_pattern = preg_quote($valid_character_string, "/");
162
163 195
        static::$valid_pattern = '/^$|' .     //allows part to be empty
164 195
            '^([\w' .                       //start decoded group
165 195
            $part_pattern .
166 195
            ']|' .                          //predefined patterns or percent-encoding
167 195
            self::$pct_encoded_pattern .
168 195
            ')*$/';
169 195
    }
170
171
    /**
172
     * Compiles unencoded characters provided a URI part's composition, as defined by its compositions property.
173
     * Note that unencoded characters form the basis for the URI part's validation pattern.
174
     *
175
     * @see AbstractUriPart::compileValidPattern()
176
     *
177
     * @return void
178
     */
179 195
    protected static function compileUnencodedCharacters()
180
    {
181 195
        foreach (static::$compositions as $composition) {
182 195
            $composition_characters = self::${$composition};
183
184 195
            $delta = array_diff($composition_characters, static::$unencoded_characters);
185
186 195
            if (!empty($delta)) {
187
                static::$unencoded_characters = array_merge(static::$unencoded_characters, self::${$composition});
188
            }
189 195
        }
190 195
    }
191
}
192