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

Json::validateValue()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 4
c 1
b 0
f 0
nc 2
nop 2
dl 0
loc 9
ccs 5
cts 5
cp 1
crap 2
rs 10
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