Port::portIsInValidRange()   A
last analyzed

Complexity

Conditions 3
Paths 2

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 3

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 8
ccs 4
cts 4
cp 1
rs 9.4285
cc 3
eloc 5
nc 2
nop 1
crap 3
1
<?php
2
namespace Subreality\Dilmun\Anshar\Http\UriParts;
3
4
use Subreality\Dilmun\Anshar\Http\SchemePortsTrait;
5
use Subreality\Dilmun\Anshar\Utils\ArrayHelper;
6
7
/**
8
 * Class Port
9
 * @package Subreality\Dilmun\Anshar\Http\UriParts
10
 */
11
class Port implements UriPartInterface
12
{
13
    use SchemePortsTrait;
14
15
    protected $port = null;
16
17
    protected static $part_pattern  = '[0-9]{0,4}';
18
    protected static $valid_pattern = '/^[0-9]{0,4}$/';
19
20
    /**
21
     * Port constructor. Accepts an integer or null value representing a URI port component. Construction will throw an
22
     * exception if port is not an integer or is not null or if the given integer is outside of the allowed TCP/UDP
23
     * range of 1 to 65535.
24
     *
25
     * port = *DIGIT
26
     *
27
     * @see https://tools.ietf.org/html/rfc3986#appendix-A
28
     *
29
     * @throws \InvalidArgumentException if the given port is not an integer or null or if the given integer is out of
30
     * range
31
     *
32
     * @param int|null $port    A string representing a URI port
33
     */
34 117
    public function __construct($port)
35
    {
36 117
        if (!is_int($port) && !is_null($port)) {
37 11
            throw new \InvalidArgumentException("Port must be an integer or null");
38 106
        } elseif (!self::isValid($port)) {
39 5
            throw new \InvalidArgumentException("Port must be between 1 and 65535 inclusive");
40
        }
41
42 101
        $this->port = $port;
43 101
    }
44
45
    /**
46
     * Returns a string representation of the port.
47
     *
48
     * @return string   The string representation of the port
49
     */
50 5
    public function __toString()
51
    {
52 5
        return (string) $this->port;
53
    }
54
55
    /**
56
     * Returns the raw port data
57
     *
58
     * @return int|null
59
     */
60 2
    public function getPort()
61
    {
62 2
        return $this->port;
63
    }
64
65
    /**
66
     * Returns a string representing a valid pattern for a URI port
67
     *
68
     * @return string
69
     */
70 17
    public static function getValidPattern()
71
    {
72 17
        return self::$part_pattern;
73
    }
74
75
    /**
76
     * Validates a given port. A port is valid if it is either null or an integer between 1 and 65535 inclusive.
77
     *
78
     * @param mixed $port   The port to be validated
79
     * @return bool         Returns true if the given port is valid
80
     *                      Returns false otherwise
81
     */
82 111
    public static function isValid($port)
83
    {
84 111
        $port_valid = false;
85
86 111
        if (is_int($port)) {
87 58
            $port_valid = self::portIsInValidRange($port);
88 111
        } elseif (is_null($port)) {
89 53
            $port_valid = true;
90 53
        }
91
92 111
        return $port_valid;
93
    }
94
95
    /**
96
     * Returns a string representation of the port formatted so that it can be compiled into a complete URI string
97
     * per the Uri object's string specification.
98
     *
99
     * If the port is empty, toUriString returns an empty string; if the port is not empty, toUriString returns the
100
     * port prefixed with a colon.
101
     *
102
     * toUriString will also check the port against an optionally-provided scheme; if the port is standard for the given
103
     * scheme, toUriString returns an empty string.
104
     *
105
     * @see Uri::__toString
106
     *
107
     * @param Scheme|null $scheme   [optional] A scheme against which to check if the port is the standard
108
     *
109
     * @return string               A string representation of the port formatted for a complete URI string
110
     */
111 87
    public function toUriString(Scheme $scheme = null)
112
    {
113 87
        $normalized_port = $this->normalizePortAgainstScheme($scheme);
114
115 87
        $uri_string = (string) $normalized_port;
116
117 87
        if (!is_null($normalized_port)) {
118 48
            $uri_string = ":" . $uri_string;
119 48
        }
120
121 87
        return $uri_string;
122
    }
123
124
    /**
125
     * Normalizes the port against a given scheme so that the scheme is reported as null if the port is standard for the
126
     * scheme.
127
     *
128
     * For example, given a http scheme and a port of 80, the normalized port will be reported as null; given a https
129
     * scheme and a port of 80, the normalized port will be reported as 80.
130
     *
131
     * @see Port::toUriString()
132
     * @see SchemePortsTrait
133
     *
134
     * @param Scheme|null $scheme
135
     * @return int|null
136
     */
137 94
    public function normalizePortAgainstScheme(Scheme $scheme = null)
138
    {
139 94
        $scheme_port_array = new ArrayHelper($this->scheme_ports);
140 94
        $scheme_string     = (string) $scheme;
141
142 94
        $standard_port = $scheme_port_array->valueLookup($scheme_string);
143
144 94
        if ($this->port == $standard_port) {
145 41
            $normalized_port = null;
146 41
        } else {
147 54
            $normalized_port = $this->port;
148
        }
149
150 94
        return $normalized_port;
151
    }
152
153
    /**
154
     * Validates whether a given port falls within the range of valid ports for TCP/UDP (1 to 65535)
155
     *
156
     * @param int $port The port to be validated
157
     *
158
     * @return bool     Returns true if the port falls within the valid range
159
     *                  Returns false otherwise
160
     */
161 58
    private static function portIsInValidRange($port)
162
    {
163 58
        if ($port > 0 && $port < 65536) {
164 51
            return true;
165
        } else {
166 7
            return false;
167
        }
168
    }
169
}
170