Passed
Pull Request — master (#222)
by Dmitriy
02:34
created

UrlValidator   A

Complexity

Total Complexity 9

Size/Duplication

Total Lines 39
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 3
Bugs 0 Features 0
Metric Value
eloc 16
c 3
b 0
f 0
dl 0
loc 39
ccs 17
cts 17
cp 1
rs 10
wmc 9

3 Methods

Rating   Name   Duplication   Size   Complexity  
A convertIdn() 0 10 2
A idnToAscii() 0 5 2
A validate() 0 18 5
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Validator\Rule\Url;
6
7
use Yiisoft\Validator\Result;
8
use Yiisoft\Validator\Rule\RuleValidatorInterface;
9
use Yiisoft\Validator\ValidationContext;
10
use Yiisoft\Validator\ValidatorInterface;
11
use function is_string;
12
use function strlen;
13
14
/**
15
 * Validates that the value is a valid HTTP or HTTPS URL.
16
 *
17
 * Note that this rule only checks if the URL scheme and host part are correct.
18
 * It does not check the remaining parts of a URL.
19
 */
20
final class UrlValidator implements RuleValidatorInterface
21
{
22 43
    public function validate(mixed $value, object $rule, ValidatorInterface $validator, ?ValidationContext $context = null): Result
23
    {
24 43
        $result = new Result();
25
26
        // make sure the length is limited to avoid DOS attacks
27 43
        if (is_string($value) && strlen($value) < 2000) {
28 41
            if ($rule->enableIDN) {
29 9
                $value = $this->convertIdn($value);
30
            }
31
32 41
            if (preg_match($rule->getPattern(), $value)) {
33 24
                return $result;
34
            }
35
        }
36
37 19
        $result->addError($rule->message);
38
39 19
        return $result;
40
    }
41
42 9
    private function idnToAscii(string $idn): string
43
    {
44 9
        $result = idn_to_ascii($idn, 0, INTL_IDNA_VARIANT_UTS46);
45
46 9
        return $result === false ? '' : $result;
47
    }
48
49 9
    private function convertIdn(string $value): string
50
    {
51 9
        if (!str_contains($value, '://')) {
52 5
            return $this->idnToAscii($value);
53
        }
54
55 4
        return preg_replace_callback(
56
            '/:\/\/([^\/]+)/',
57 4
            fn ($matches) => '://' . $this->idnToAscii($matches[1]),
58
            $value
59
        );
60
    }
61
}
62