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

JsonHandler   A

Complexity

Total Complexity 5

Size/Duplication

Total Lines 37
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 5
eloc 21
dl 0
loc 37
ccs 10
cts 10
cp 1
rs 10
c 0
b 0
f 0

2 Methods

Rating   Name   Duplication   Size   Complexity  
A isValidJson() 0 20 2
A validate() 0 13 3
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Validator\Rule;
6
7
use Yiisoft\Validator\Result;
8
use Yiisoft\Validator\ValidationContext;
9
use Yiisoft\Validator\ValidatorInterface;
10
use function is_string;
11
use Yiisoft\Validator\Exception\UnexpectedRuleException;
12
13
/**
14
 * Validates that the value is a valid json.
15
 */
16
final class JsonHandler implements RuleHandlerInterface
17
{
18 10
    public function validate(mixed $value, object $rule, ?ValidationContext $context = null): Result
19
    {
20 10
        if (!$rule instanceof Json) {
21 1
            throw new UnexpectedRuleException(Json::class, $rule);
22
        }
23
24 9
        $result = new Result();
25
26 9
        if (!$this->isValidJson($value)) {
27 6
            $result->addError($rule->message);
28
        }
29
30 9
        return $result;
31
    }
32
33 9
    private function isValidJson($value): bool
34
    {
35
        // Regular expression is built based on JSON grammar specified at
36
        // https://tools.ietf.org/html/rfc8259
37 9
        $regex = <<<'REGEX'
38
        /
39
        (?(DEFINE)
40
            (?<json>(?>\s*(?&object)\s*|\s*(?&array)\s*))
41
            (?<object>(?>\{\s*(?>(?&member)(?>\s*,\s*(?&member))*)?\s*\}))
42
            (?<member>(?>(?&string)\s*:\s*(?&value)))
43
            (?<array>(?>\[\s*(?>(?&value)(?>\s*,\s*(?&value))*)?\s*\]))
44
            (?<value>(?>)false|null|true|(?&object)|(?&array)|(?&number)|(?&string))
45
            (?<number>(?>-?(?>0|[1-9]\d*)(?>\.\d+)?(?>[eE][-+]?\d+)?))
46
            (?<string>(?>"(?>\\(?>["\\\/bfnrt]|u[a-fA-F0-9]{4})|[^"\\\0-\x1F\x7F]+)*"))
47
        )
48
        \A(?&json)\z
49
        /x
50
        REGEX;
51
52 9
        return is_string($value) && preg_match($regex, $value) === 1;
53
    }
54
}
55