Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
55 / 55
100.00% covered (success)
100.00%
3 / 3
CRAP
100.00% covered (success)
100.00%
1 / 1
IpAddress
100.00% covered (success)
100.00%
55 / 55
100.00% covered (success)
100.00%
3 / 3
13
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 validate
100.00% covered (success)
100.00%
52 / 52
100.00% covered (success)
100.00%
1 / 1
11
 getInverseError
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3namespace Verja\Validator;
4
5use Verja\Error;
6use Verja\Validator;
7
8class IpAddress extends Validator
9{
10    const VERSION_ANY = 'any';
11    const VERSION_4 = 'v4';
12    const VERSION_6 = 'v6';
13
14    const RANGE_ANY = 'any';
15    const RANGE_PUBLIC = 'public';
16    const RANGE_UNRESERVED = 'unreserved';
17    const RANGE_PRIVATE = 'private';
18
19    /** @var string */
20    protected $version;
21
22    /** @var string */
23    protected $range;
24
25    /**
26     * IpAddress constructor.
27     *
28     * @param string $version 'any' (default), 'v4' or 'v6'
29     * @param string $range 'any' (default), 'public', 'public,unreserved' or 'private'
30     */
31    public function __construct(string $version = self::VERSION_ANY, string $range = self::RANGE_ANY)
32    {
33        $this->version = $version;
34        $this->range = $range;
35    }
36
37    /**
38     * Validate $value
39     *
40     * @param mixed $value
41     * @param array $context
42     * @return bool
43     */
44    public function validate($value, array $context = []): bool
45    {
46        $flags = 0;
47
48        $ipName = 'ip address';
49        if ($this->version === self::VERSION_6) {
50            $flags = $flags | FILTER_FLAG_IPV6;
51            $ipName = 'ip-v6 address';
52        } elseif ($this->version === self::VERSION_4) {
53            $flags = $flags | FILTER_FLAG_IPV4;
54            $ipName = 'ip-v4 address';
55        }
56
57        $parameters = [
58            'version' => $this->version,
59            'range' => $this->range,
60        ];
61
62        if (!filter_var($value, FILTER_VALIDATE_IP, $flags)) {
63            // not a valid ip address
64            $this->error = new Error(
65                'NO_IP_ADDRESS',
66                $value,
67                sprintf('value should be an %s', $ipName),
68                $parameters
69            );
70            return false;
71        }
72
73        if ($this->range !== self::RANGE_ANY) {
74            if (strpos($this->range, self::RANGE_PUBLIC) !== false) {
75                $flags = $flags | FILTER_FLAG_NO_PRIV_RANGE;
76                if (!filter_var($value, FILTER_VALIDATE_IP, $flags)) {
77                    // not a public ip address
78                    $this->error = new Error(
79                        'NO_PUBLIC_IP_ADDRESS',
80                        $value,
81                        sprintf('value should be a public %s', $ipName),
82                        $parameters
83                    );
84                    return false;
85                } elseif (strpos($this->range, self::RANGE_UNRESERVED) !== false) {
86                    $flags = $flags | FILTER_FLAG_NO_RES_RANGE;
87                    if (!filter_var($value, FILTER_VALIDATE_IP, $flags)) {
88                        // reserved ip address
89                        $this->error = new Error(
90                            'IS_RESERVED_IP_ADDRESS',
91                            $value,
92                            sprintf('value should not be a reserved %s', $ipName),
93                            $parameters
94                        );
95                        return false;
96                    }
97                }
98            }
99
100            if ($this->range === self::RANGE_PRIVATE) {
101                $flags = $flags | FILTER_FLAG_NO_PRIV_RANGE;
102                if (filter_var($value, FILTER_VALIDATE_IP, $flags)) {
103                    // public ip address
104                    $this->error = new Error(
105                        'IS_PUBLIC_IP_ADDRESS',
106                        $value,
107                        sprintf('value should not be a public %s', $ipName),
108                        $parameters
109                    );
110                    return false;
111                }
112            }
113        }
114
115        return true;
116    }
117
118    public function getInverseError($value)
119    {
120        return new Error('IS_IP_ADDRESS', $value, 'value should not be an ip address');
121    }
122}