Passed
Push — master ( 2e610f...e9d334 )
by Paweł
02:08
created

MatchesJsonSchema::generateSchema()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 3
c 0
b 0
f 0
nc 1
nop 1
dl 0
loc 6
rs 10
1
<?php
2
/**
3
 * Copyright (c) 2020.
4
 * @author Paweł Antosiak <[email protected]>
5
 */
6
7
declare(strict_types=1);
8
9
namespace Gorynych\Testing\Constraint;
10
11
use JsonSchema\Validator;
12
use PHPUnit\Framework\Constraint\Constraint;
13
14
final class MatchesJsonSchema extends Constraint
15
{
16
    private object $schema;
17
    private ?int $checkMode;
18
19
    public function __construct(object $schema, ?int $checkMode = null)
20
    {
21
        $this->schema = $schema;
22
        $this->checkMode = $checkMode;
23
    }
24
25
    /**
26
     * {@inheritdoc}
27
     */
28
    public function toString(): string
29
    {
30
        return 'matches provided JSON Schema';
31
    }
32
33
    /**
34
     * {@inheritdoc}
35
     */
36
    protected function matches($other): bool
37
    {
38
        $other = $this->normalizeJson($other);
39
40
        $validator = new Validator();
41
        $validator->validate($other, $this->schema, $this->checkMode);
42
43
        return $validator->isValid();
44
    }
45
46
    /**
47
     * {@inheritdoc}
48
     */
49
    protected function additionalFailureDescription($other): string
50
    {
51
        $other = $this->normalizeJson($other);
52
53
        $validator = new Validator();
54
        $validator->validate($other, $this->schema, $this->checkMode);
55
56
        $errors = array_map(
57
            static function (array $error): string {
58
                return ($error['property'] ? $error['property'] . ': ' : '') . $error['message'];
59
            },
60
            $validator->getErrors()
61
        );
62
63
        return implode("\n", $errors);
64
    }
65
66
    /**
67
     * Normalizes a JSON document
68
     *
69
     * Specifically, we should ensure that:
70
     * 1. a JSON object is represented as a PHP object, not as an associative array
71
     *
72
     * @param mixed $document
73
     * @return object|mixed[]
74
     * @throws \InvalidArgumentException
75
     * @throws \UnexpectedValueException
76
     */
77
    private function normalizeJson($document)
78
    {
79
        if (true === is_scalar($document) || true === is_object($document)) {
80
            return $document;
81
        }
82
83
        if (false === is_array($document)) {
84
            throw new \InvalidArgumentException('Document must be scalar, array or object.');
85
        }
86
87
        $document = json_encode($document);
88
89
        if (false === is_string($document)) {
0 ignored issues
show
introduced by
The condition false === is_string($document) is always false.
Loading history...
90
            throw new \UnexpectedValueException('JSON encode failed.');
91
        }
92
93
        $document = json_decode($document);
94
95
        if (false === is_array($document) && false === is_object($document)) {
96
            throw new \UnexpectedValueException('JSON decode failed.');
97
        }
98
99
        return $document;
100
    }
101
}
102