Passed
Push — master ( 2b6758...acf834 )
by Aleksei
06:59
created

Json   A

Complexity

Total Complexity 5

Size/Duplication

Total Lines 45
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 25
dl 0
loc 45
ccs 12
cts 12
cp 1
rs 10
c 1
b 0
f 0
wmc 5

3 Methods

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