Path::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
ccs 3
cts 3
cp 1
rs 10
cc 1
eloc 2
nc 1
nop 1
crap 1
1
<?php
2
namespace Subreality\Dilmun\Anshar\Http\UriParts;
3
4
use Subreality\Dilmun\Anshar\Utils\StringHelper;
5
6
/**
7
 * Class Path
8
 * @package Subreality\Dilmun\Anshar\Http\UriParts
9
 */
10
class Path extends AbstractUriPart
11
{
12
    protected static $unencoded_characters = array('/');
13
14
    protected static $compositions = array(
15
        "unreserved_characters",
16
        "sub_delims_characters",
17
        "pchar_characters",
18
    );
19
20
    protected static $part_pattern;
21
22
    /**
23
     * Host constructor. Accepts a string representing a URI host component. Construction will throw an exception if
24
     * the host is not a string.
25
     *
26
     * path-abempty  = *( "/" segment )
27
     * path-absolute = "/" [ segment-nz *( "/" segment ) ]
28
     * path-noscheme = segment-nz-nc *( "/" segment )
29
     * path-rootless = segment-nz *( "/" segment )
30
     * path-empty    = 0<pchar>
31
     *
32
     * segment       = *pchar
33
     * segment-nz    = 1*pchar
34
     * segment-nz-nc = 1*( unreserved / pct-encoded / sub-delims / "@" )
35
     * ; non-zero-length segment without any colon ":"
36
     *
37
     * pchar         = unreserved / pct-encoded / sub-delims / ":" / "@"
38
     *
39
     * @param string $path
40
     */
41 87
    public function __construct($path)
42
    {
43 87
        parent::__construct($path, "Path");
44 81
    }
45
46
    /**
47
     * Returns a string representation of the path formatted so that it can be compiled into a complete URI string
48
     * per the Uri object's string specification.
49
     *
50
     * If the path is empty, toUriString returns an empty string; if the path is not empty, toUriString returns the
51
     * path with one or more rules applied against an optional Authority to determine starting slashes:
52
     *
53
     * - If the path is rootless and an authority is present, the path MUST be prefixed by "/".
54
     * - If the path is starting with more than one "/" and no authority is present, the starting slashes MUST be
55
     *   reduced to one.
56
     *
57
     * @see Uri::__toString
58
     *
59
     * @param Authority|null $authority     [optional] An authority against which to derive starting slash rules
60
     *
61
     * @return string                       A string representation of the path formatted for a complete URI string
62
     */
63 25
    public function toUriString(Authority $authority = null)
64
    {
65 25
        $path_string = parent::toUriString();
66
67 25
        if (!empty($this->data)) {
68 22
            $path_string = $this->normalizePathWithAuthority($authority);
69 22
        }
70
71 25
        return $path_string;
72
    }
73
74
    /**
75
     * Validates whether a given path string conforms to the URI specification for a path provided an optional
76
     * authority. If a non-empty path is provide along with a non-empty authority, the path must begin with a slash.
77
     *
78
     * Note that validatePathAgainstAuthority only validates that a path conforms to the slash requirement and not the
79
     * validity of the path in general. For general path validation, use Path::isValid.
80
     *
81
     * @see Path::isValid
82
     * @see Uri::withPath
83
     *
84
     * @throws \InvalidArgumentException provided a non-string path.
85
     *
86
     * @param string $path_string           A path string
87
     * @param Authority|null $authority     [optional] An authority against which to check the path for validity
88
     *
89
     * @return bool
90
     */
91 30
    public static function validatePathAgainstAuthority($path_string, Authority $authority = null)
92
    {
93 30
        self::checkPathIsString($path_string);
94
95 18
        if (!empty((string) $path_string) && !empty((string) $authority)) {
96 9
            return self::startsWithSlash($path_string);
97
        }
98
99 9
        return true;
100
    }
101
102
    /**
103
     * Throws an InvalidArgumentException if the given path is not a string.
104
     *
105
     * @throws \InvalidArgumentException given a non-string path.
106
     *
107
     * @param string $path  The path to be checked
108
     *
109
     * @return void
110
     */
111 30
    private static function checkPathIsString($path)
112
    {
113 30
        if (!is_string($path)) {
114 12
            throw new \InvalidArgumentException("Path must be a string");
115
        }
116 18
    }
117
118
    /**
119
     * Checks whether a given path string starts with a slash.
120
     *
121
     * @throws \InvalidArgumentException given a non-string path.
122
     *
123
     * @param string $path  The path to be checked
124
     *
125
     * @return bool         Returns true if the path starts with a slash
126
     *                      Returns false if the path does not start with a slash
127
     */
128 25
    private static function startsWithSlash($path)
129 25
    {
130 9
        self::checkPathIsString($path);
131
132 9
        $path = new StringHelper($path);
133
134 9
        return $path->startsWith("/");
135
    }
136
137
    /**
138
     * Determines whether a given authority should begin with a slash provided an Authority.
139
     *
140
     * @see Path::toUriString
141
     *
142
     * @param Authority|null $authority     [optional] An authority against which to derive starting slash rules
143
     *
144
     * @return string                       The path string with appropriate starting slash rules applied
145
     */
146 22
    private function normalizePathWithAuthority(Authority $authority = null)
147
    {
148 22
        $path_string = $this->collapseStartingSlashes($this->data, $authority);
149
150 22
        $path_string = new StringHelper($path_string);
151
152 22
        if (!empty((string) $authority)) {
153 16
            if (!$path_string->startsWith("/")) {
154 2
                $path_string = "/" . $this->data;
155 2
            }
156 16
        }
157
158 22
        return (string) $path_string;
159
    }
160
161
    /**
162
     * Collapses starting slashes within a path if necessary given rules associated with an optional Authority.
163
     *
164
     * @see Path::toUriString
165
     *
166
     * @param string $path_string           The path string to process
167
     * @param Authority|null $authority     [optional] An authority against which to derive starting slash rules
168
     *
169
     * @return string                       The path string with appropriate starting slash rules applied
170
     */
171 22
    private function collapseStartingSlashes($path_string, Authority $authority = null)
172
    {
173 22
        $path_string = new StringHelper($path_string);
174
175 22
        if (empty((string) $authority)) {
176 6
            $path_string = $path_string->collapseStartingRepetition("/");
177 6
        }
178
179 22
        return (string) $path_string;
180
    }
181
}
182