Issues (332)

Bundle/Test/Constraint/MatchesJsonSchema.php (1 issue)

1
<?php
2
3
/*
4
 * This file is part of the API Platform project.
5
 *
6
 * (c) Kévin Dunglas <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
namespace ApiPlatform\Core\Bridge\Symfony\Bundle\Test\Constraint;
15
16
use JsonSchema\Validator;
17
use PHPUnit\Framework\Constraint\Constraint;
18
19
/**
20
 * Asserts that a JSON document matches a given JSON Schema.
21
 *
22
 * @author Kévin Dunglas <[email protected]>
23
 *
24
 * @experimental
25
 */
26
final class MatchesJsonSchema extends Constraint
27
{
28
    /**
29
     * @var object|array
30
     */
31
    private $schema;
32
    private $checkMode;
33
34
    /**
35
     * @param object|array|string $schema
36
     */
37
    public function __construct($schema, ?int $checkMode = null)
38
    {
39
        $this->schema = \is_string($schema) ? json_decode($schema) : $schema;
40
        $this->checkMode = $checkMode;
41
    }
42
43
    /**
44
     * {@inheritdoc}
45
     */
46
    public function toString(): string
47
    {
48
        return 'matches the provided JSON Schema';
49
    }
50
51
    /**
52
     * {@inheritdoc}
53
     */
54
    protected function matches($other): bool
55
    {
56
        if (!class_exists(Validator::class)) {
57
            throw new \LogicException('The "justinrainbow/json-schema" library must be installed to use "assertMatchesJsonSchema()". Try running "composer require --dev justinrainbow/json-schema".');
58
        }
59
60
        $other = $this->normalizeJson($other);
61
62
        $validator = new Validator();
63
        $validator->validate($other, $this->schema, $this->checkMode);
64
65
        return $validator->isValid();
66
    }
67
68
    /**
69
     * {@inheritdoc}
70
     */
71
    protected function additionalFailureDescription($other): string
72
    {
73
        $other = $this->normalizeJson($other);
74
75
        $validator = new Validator();
76
        $validator->validate($other, $this->schema, $this->checkMode);
77
78
        $errors = [];
79
        foreach ($validator->getErrors() as $error) {
80
            $property = $error['property'] ? $error['property'].': ' : '';
81
            $errors[] = $property.$error['message'];
82
        }
83
84
        return implode("\n", $errors);
85
    }
86
87
    /**
88
     * Normalizes a JSON document.
89
     *
90
     * Specifically, we should ensure that:
91
     * 1. a JSON object is represented as a PHP object, not as an associative array.
92
     */
93
    private function normalizeJson($document)
94
    {
95
        if (is_scalar($document) || \is_object($document)) {
96
            return $document;
97
        }
98
99
        if (!\is_array($document)) {
100
            throw new \InvalidArgumentException('Document must be scalar, array or object.');
101
        }
102
103
        $document = json_encode($document);
104
        if (!\is_string($document)) {
0 ignored issues
show
The condition is_string($document) is always true.
Loading history...
105
            throw new \UnexpectedValueException('JSON encode failed.');
106
        }
107
        $document = json_decode($document);
108
        if (!\is_array($document) && !\is_object($document)) {
109
            throw new \UnexpectedValueException('JSON decode failed.');
110
        }
111
112
        return $document;
113
    }
114
}
115