Completed
Push — master ( 98b500...211af5 )
by Derek
03:45
created

AbstractUriPart::compileUnencodedCharacters()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 6
ccs 5
cts 5
cp 1
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 3
nc 2
nop 0
crap 2
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 $unreserved_pattern  = '\w\-\.~';
13
    protected $pct_encoded_pattern = '%[A-Fa-f0-9]{2}';
14
    protected $sub_delims_pattern  = '\!\$&\'\(\)\*\+,;\=';
15
    protected $pchar_pattern       = '\:@';
16
17
    protected $unreserved_characters = array("_", "-", ".", "~");
18
    protected $pchar_characters      = array(":", "@");
19
20
    protected $sub_delims_characters = array(
21
        "!",
22
        "$",
23
        "&",
24
        "'",
25
        "(",
26
        ")",
27
        "*",
28
        "+",
29
        ",",
30
        ";",
31
        "=",
32
    );
33
34
    protected $data = "";
35
36
    protected $compositions = array(
37
        "unreserved_characters",
38
        "pchar_characters",
39
        "sub_delims_characters",
40
    );
41
42
    protected $unencoded_characters = array();
43
44
    protected $part_pattern = "";
45
46
    protected static $valid_pattern;
47
48
    /**
49
     * Abstract constructor for URI parts.
50
     *
51
     * @param string $part_data The data used to construct a URI part
52
     * @param string $part_name The name of the URI part for exception reporting
53
     * @param string $part_type [optional] The expected type of the URI part
54
     */
55 112
    public function __construct($part_data, $part_name, $part_type = "string")
56
    {
57 112
        $this->compileUnencodedCharacters();
58 112
        $this->compileValidPattern();
59
60 112
        if (gettype($part_data) != $part_type) {
61 18
            throw new \InvalidArgumentException("{$part_name} must be a {$part_type}");
62 94
        } elseif (!self::isValid($part_data)) {
63 19
            $part_data = $this->encode($part_data);
64 19
        }
65
66 94
        $this->data = $part_data;
67 94
    }
68
69
    /**
70
     * Returns a string representation of the URI component
71
     *
72
     * @return string   A string representation of the URI component
73
     */
74 76
    public function __toString()
75
    {
76 76
        return (string) $this->data;
77
    }
78
79
    /**
80
     * Determines whether a given string adheres to the RFC3986 specification for the extending URI part.
81
     *
82
     * Requires extending classes to define self::$valid_pattern.
83
     *
84
     * @see https://tools.ietf.org/html/rfc3986#appendix-A
85
     *
86
     * @param string $string    The query to check for validity
87
     *
88
     * @return bool             Returns true if the provided query matches the RFC3986 specification
89
     *                          Returns false otherwise
90
     */
91 129
    public static function isValid($string)
92
    {
93 129
        return (bool) preg_match(self::$valid_pattern, $string);
94
    }
95
96
    /**
97
     * @return string
98
     */
99 37
    public function toUriString()
100
    {
101 37
        return (string) $this;
102
    }
103
104
    /**
105
     * Percent-encodes invalid characters within a given string. Percent-encoding ignores valid as defined by the
106
     * component per RFC3986.
107
     *
108
     * @see https://tools.ietf.org/html/rfc3986#appendix-A
109
     *
110
     * @param string $string     The query string to be percent-encoded
111
     *
112
     * @return string            The query string with invalid characters percent-encoded
113
     */
114 19
    protected function encode($string)
115
    {
116 19
        $encoded_query = $string;
117
118 19
        if (!empty($this->unencoded_characters)) {
119 19
            $string_helper = new StringHelper($string);
120
121 19
            $encoded_query = $string_helper->affectChunks("rawurlencode", ...$this->unencoded_characters);
122 19
        }
123
124 19
        return $encoded_query;
125
    }
126
127
    /**
128
     * Provides the most common validation pattern for URI parts.
129
     *
130
     * @return void
131
     */
132 112
    protected function compileValidPattern()
133
    {
134 112
        $valid_character_string = implode($this->unencoded_characters);
135
136 112
        $this->part_pattern = preg_quote($valid_character_string, "/");
137
138 112
        self::$valid_pattern = '/^$|' .     //allows part to be empty
139 112
            '^([\w' .                       //start decoded group
140 112
            $this->part_pattern .
141 112
            ']|' .                          //predefined patterns or percent-encoding
142 112
            $this->pct_encoded_pattern .
143 112
            ')*$/';
144 112
    }
145
146
    /**
147
     * @return void
148
     */
149 112
    protected function compileUnencodedCharacters()
150
    {
151 112
        foreach ($this->compositions as $composition) {
152 112
            $this->unencoded_characters = array_merge($this->unencoded_characters, $this->{$composition});
153 112
        }
154 112
    }
155
}
156