Completed
Pull Request — master (#42)
by Théo
02:05
created

Json::lint()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
c 0
b 0
f 0
rs 9.4285
cc 2
eloc 3
nc 2
nop 1
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the box project.
7
 *
8
 * (c) Kevin Herrera <[email protected]>
9
 *     Théo Fidry <[email protected]>
10
 *
11
 * This source file is subject to the MIT license that is bundled
12
 * with this source code in the file LICENSE.
13
 */
14
15
namespace KevinGH\Box\Json;
16
17
use InvalidArgumentException;
18
use JsonSchema\Validator;
19
use Seld\JsonLint\JsonParser;
20
use Seld\JsonLint\ParsingException;
21
use stdClass;
22
23
final class Json
24
{
25
    private $linter;
26
    private $validator;
27
28
    public function __construct()
29
    {
30
        $this->linter = new JsonParser();
31
        $this->validator = new Validator();
32
    }
33
34
    public function decode(string $json): stdClass
35
    {
36
        $data = json_decode($json);
37
38
        if (JSON_ERROR_NONE !== ($error = json_last_error())) {
39
            if (JSON_ERROR_UTF8 === $error) {
40
                throw JsonValidationException::createDecodeException($error);
41
            }
42
43
            $this->lint($json);
44
45
            if (($result = $this->linter->lint($json)) instanceof ParsingException) {
0 ignored issues
show
introduced by
The condition $result = $this->linter-...onLint\ParsingException can never be false since $result = $this->linter->lint($json) is always a sub-type of Seld\JsonLint\ParsingException.
Loading history...
46
                throw $result;
47
            }
48
        }
49
50
        return $data;
51
    }
52
53
    public function decodeFile(string $file): stdClass
54
    {
55
        if (false === is_file($file)) {
56
            throw new InvalidArgumentException(
57
                sprintf(
58
                    'The file "%s" does not exist.',
59
                    $file
60
                )
61
            );
62
        }
63
64
        if (false === ($json = @file_get_contents($file))) {
0 ignored issues
show
introduced by
The condition false === $json = @file_get_contents($file) can never be true.
Loading history...
65
            throw new InvalidArgumentException(
66
                sprintf(
67
                    'Could not read the file "%s": %s',
68
                    $file,
69
                    error_get_last()['message']
70
                )
71
            );
72
        }
73
74
        return $this->decode($json);
75
    }
76
77
    public function lint(string $json): void
78
    {
79
        $result = $this->linter->lint($json);
80
81
        if ($result instanceof ParsingException) {
0 ignored issues
show
introduced by
The condition $result instanceof Seld\JsonLint\ParsingException can never be false since $result is always a sub-type of Seld\JsonLint\ParsingException.
Loading history...
82
            throw $result;
83
        }
84
    }
85
86
    /**
87
     * Validates the decoded JSON data.
88
     *
89
     * @param string   $file   The JSON file
90
     * @param stdClass $json   The decoded JSON data
91
     * @param stdClass $schema The JSON schema
92
     *
93
     * @throws JsonValidationException If the JSON data failed validation
94
     */
95
    public function validate(string $file, stdClass $json, stdClass $schema): void
96
    {
97
        $validator = new Validator();
98
        $validator->check($json, $schema);
99
100
        if (!$validator->isValid()) {
101
            $errors = [];
102
103
            foreach ((array) $validator->getErrors() as $error) {
104
                $errors[] = ($error['property'] ? $error['property'].' : ' : '').$error['message'];
105
            }
106
107
            $message = [] !== $errors
108
                ? "\"$file\" does not match the expected JSON schema:\n  - ".implode("\n  - ", $errors)
109
                : "\"$file\" does not match the expected JSON schema."
110
            ;
111
112
            throw new JsonValidationException($message, $file, $errors);
113
        }
114
    }
115
}
116