Passed
Push — master ( 5c2907...37dc07 )
by Sergei
24:35 queued 21:56
created

UrlHandler::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 0

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 0
c 1
b 0
f 0
dl 0
loc 2
ccs 1
cts 1
cp 1
rs 10
cc 1
nc 1
nop 1
crap 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Validator\Rule;
6
7
use Yiisoft\Validator\Exception\UnexpectedRuleException;
8
use Yiisoft\Validator\Result;
9
use Yiisoft\Validator\RuleHandlerInterface;
10
use Yiisoft\Validator\ValidationContext;
11
12
use function is_string;
13
use function strlen;
14
15
/**
16
 * Validates that the value is a valid HTTP or HTTPS URL.
17
 *
18
 * Note that this rule only checks if the URL scheme and host part are correct.
19
 * It does not check the remaining parts of a URL.
20
 */
21
final class UrlHandler implements RuleHandlerInterface
22
{
23 39
    public function validate(mixed $value, object $rule, ValidationContext $context): Result
24
    {
25 39
        if (!$rule instanceof Url) {
26 1
            throw new UnexpectedRuleException(Url::class, $rule);
27
        }
28
29 38
        $result = new Result();
30
31
        // make sure the length is limited to avoid DOS attacks
32 38
        if (is_string($value) && strlen($value) < 2000) {
33 37
            if ($rule->isEnableIDN()) {
34 5
                $value = $this->convertIdn($value);
35
            }
36
37 37
            if (preg_match($rule->getPattern(), $value)) {
38 22
                return $result;
39
            }
40
        }
41
42 16
        $result->addError(
43 16
            $rule->getMessage(),
44
            [
45 16
                'attribute' => $context->getAttribute(),
46
                'value' => $value,
47
            ],
48
        );
49
50 16
        return $result;
51
    }
52
53 5
    private function idnToAscii(string $idn): string
54
    {
55 5
        $result = idn_to_ascii($idn, 0, INTL_IDNA_VARIANT_UTS46);
56
57 5
        return $result === false ? '' : $result;
58
    }
59
60 5
    private function convertIdn(string $value): string
61
    {
62 5
        if (!str_contains($value, '://')) {
63 3
            return $this->idnToAscii($value);
64
        }
65
66 2
        return preg_replace_callback(
67
            '/:\/\/([^\/]+)/',
68 2
            fn ($matches) => '://' . $this->idnToAscii($matches[1]),
69
            $value
70
        );
71
    }
72
}
73