Completed
Push — master ( 504e73...4ffb3e )
by Derek
02:22
created

Path::validatePathAgainstAuthority()   B

Complexity

Conditions 5
Paths 4

Size

Total Lines 16
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 5

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 16
ccs 9
cts 9
cp 1
rs 8.8571
cc 5
eloc 8
nc 4
nop 2
crap 5
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 106
    public function __construct($path)
42
    {
43 106
        parent::__construct($path, "Path");
44 100
    }
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 9
    public function toUriString(Authority $authority = null)
64
    {
65 9
        $path_string = parent::toUriString();
66
67 9
        if (!empty($this->data)) {
68 7
            $path_string = $this->normalizePathWithAuthority($authority);
69 7
        }
70
71 9
        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
        if (!is_string($path_string)) {
94 12
            throw new \InvalidArgumentException("Path must be a string");
95
        }
96
97 18
        if (!empty((string) $path_string) && !empty((string) $authority)) {
98 9
            $path_string = new StringHelper($path_string);
99
100 9
            if (!$path_string->startsWith("/")) {
101 2
                return false;
102
            }
103 7
        }
104
105 16
        return true;
106
    }
107
108
    /**
109
     * Determines whether a given authority should begin with a slash provided an Authority.
110
     *
111
     * @see Path::toUriString
112
     *
113
     * @param Authority|null $authority     [optional] An authority against which to derive starting slash rules
114
     *
115
     * @return string                       The path string with appropriate starting slash rules applied
116
     */
117 9
    private function normalizePathWithAuthority(Authority $authority = null)
118
    {
119 7
        $path_string = $this->collapseStartingSlashes($this->data, $authority);
120
121 7
        $path_string = new StringHelper($path_string);
122
123 7
        if (!empty((string) $authority)) {
124 3
            if (!$path_string->startsWith("/")) {
125 1
                $path_string = "/" . $this->data;
126 1
            }
127 3
        }
128
129 9
        return (string) $path_string;
130
    }
131
132
    /**
133
     * Collapses starting slashes within a path if necessary given rules associated with an optional Authority.
134
     *
135
     * @see Path::toUriString
136
     *
137
     * @param string $path_string       The path string to proceess
138
     * @param Authority|null $authority     [optional] An authority against which to derive starting slash rules
139
     *
140
     * @return string                       The path string with appropriate starting slash rules applied
141
     */
142 7
    private function collapseStartingSlashes($path_string, Authority $authority = null)
143
    {
144 7
        $path_string = new StringHelper($path_string);
145
146 7
        if (empty((string) $authority)) {
147 4
            $path_string = $path_string->collapseStartingRepetition("/");
148 4
        }
149
150 7
        return (string) $path_string;
151
    }
152
}
153