Passed
Push — master ( 893d1e...31005e )
by Kirill
03:35
created

AddressChecker::url()   B

Complexity

Conditions 8
Paths 12

Size

Total Lines 24
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 12
c 1
b 0
f 0
dl 0
loc 24
rs 8.4444
cc 8
nc 12
nop 3
1
<?php
2
3
/**
4
 * Spiral Framework.
5
 *
6
 * @license   MIT
7
 * @author    Anton Titov (Wolfy-J)
8
 */
9
10
declare(strict_types=1);
11
12
namespace Spiral\Validation\Checker;
13
14
use Spiral\Core\Container\SingletonInterface;
15
use Spiral\Validation\AbstractChecker;
16
17
/**
18
 * @inherit-messages
19
 */
20
final class AddressChecker extends AbstractChecker implements SingletonInterface
21
{
22
    /**
23
     * {@inheritdoc}
24
     */
25
    public const MESSAGES = [
26
        'email' => '[[Must be a valid email address.]]',
27
        'url'   => '[[Must be a valid URL address.]]',
28
    ];
29
30
    /**
31
     * Check if email is valid.
32
     *
33
     * @link http://www.ietf.org/rfc/rfc2822.txt
34
     * @param string $address
35
     * @return bool
36
     */
37
    public function email($address): bool
38
    {
39
        return (bool)filter_var($address, FILTER_VALIDATE_EMAIL);
40
    }
41
42
    /**
43
     * Check if URL is valid.
44
     *
45
     * @link http://www.faqs.org/rfcs/rfc2396.html
46
     * @param string      $url
47
     * @param null|array  $schemas
48
     * @param null|string $defaultSchema
49
     * @return bool
50
     */
51
    public function url(string $url, ?array $schemas = null, ?string $defaultSchema = null): bool
52
    {
53
        //Add default schema if not presented
54
        if (!empty($defaultSchema) && !$this->hasSchema($url)) {
55
            $defaultSchema = $this->trimSchema($defaultSchema);
56
            if (!empty($defaultSchema)) {
57
                $url = "$defaultSchema://{$this->trimURL($url)}";
58
            }
59
        }
60
61
        if (empty($schemas)) {
62
            return (bool)filter_var($url, FILTER_VALIDATE_URL);
63
        }
64
65
        foreach ($schemas as $schema) {
66
            $schema = $this->trimSchema($schema);
67
            if (empty($schema) || !$this->containsSchema($url, $schema)) {
68
                continue;
69
            }
70
71
            return (bool)filter_var($url, FILTER_VALIDATE_URL);
72
        }
73
74
        return false;
75
    }
76
77
    /**
78
     * @link http://www.ietf.org/rfc/rfc3986.txt
79
     * @link https://en.wikipedia.org/wiki/Uniform_Resource_Identifier
80
     * @param string $uri
81
     * @return bool
82
     */
83
    public function uri(string $uri): bool
84
    {
85
        // todo: improve the regexp pattern
86
87
        $pattern = "/^(([^:\/\?#]+):)?(\/\/([^\/\?#]*))?([^\?#]*)(\?([^#]*))?(#(.*))?$/";
88
89
        return (bool)preg_match($pattern, $uri);
90
    }
91
92
    /**
93
     * @param string $url
94
     * @return bool
95
     */
96
    private function hasSchema(string $url): bool
97
    {
98
        return mb_stripos($url, '://') !== false;
99
    }
100
101
    /**
102
     * @param string $schema
103
     * @return string
104
     */
105
    private function trimSchema(string $schema): string
106
    {
107
        return preg_replace('/^([a-z]+):\/\/$/i', '$1', $schema);
108
    }
109
110
    /**
111
     * @param string $url
112
     * @param string $schema
113
     *
114
     * @return bool
115
     */
116
    private function containsSchema(string $url, string $schema): bool
117
    {
118
        return mb_stripos($url, "$schema://") === 0;
119
    }
120
121
    /**
122
     * @param string $url
123
     * @return string
124
     */
125
    private function trimURL(string $url): string
126
    {
127
        return preg_replace('/^\/\/(.*)$/', '$1', $url);
128
    }
129
}
130