Completed
Push — master ( bfd868...ee3a72 )
by Vincent
12:29 queued 10:26
created

AssertStructure::dataIsResourceObject()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 5
ccs 3
cts 3
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
namespace VGirol\JsonApiAssert\Asserts;
3
4
use PHPUnit\Framework\Assert as PHPUnit;
5
use VGirol\JsonApiAssert\Messages;
6
use PHPUnit\Framework\ExpectationFailedException;
7
8
trait AssertStructure
9
{
10
    /**
11
     * Asserts that a json document has valid structure.
12
     *
13
     * @param array $json
14
     *
15
     * @throws PHPUnit\Framework\ExpectationFailedException
16
     */
17 3
    public static function assertHasValidStructure($json)
18
    {
19 3
        static::assertHasValidTopLevelMembers($json);
20
21 3
        if (isset($json['data'])) {
22 2
            static::assertIsValidPrimaryData($json['data']);
23
        }
24
25 3
        if (isset($json['errors'])) {
26 1
            static::assertIsValidErrorsObject($json['errors']);
27
        }
28
29 3
        if (isset($json['meta'])) {
30 1
            static::assertIsValidMetaObject($json['meta']);
31
        }
32
33 3
        if (isset($json['jsonapi'])) {
34 1
            static::assertIsValidJsonapiObject($json['jsonapi']);
35
        }
36
37 3
        if (isset($json['links'])) {
38 2
            static::assertIsValidTopLevelLinksMember($json['links']);
39
        }
40
41 2
        if (isset($json['included'])) {
42 1
            static::assertIsValidIncludedCollection($json['included'], $json['data']);
43
        }
44 2
    }
45
46
    /**
47
     * Asserts that a json document has valid top-level structure.
48
     *
49
     * @param array $json
50
     *
51
     * @throws PHPUnit\Framework\ExpectationFailedException
52
     */
53 8
    public static function assertHasValidTopLevelMembers($json)
54
    {
55 8
        $expected = ['data', 'errors', 'meta'];
56 8
        static::assertContainsAtLeastOneMember(
57 8
            $expected,
58 8
            $json,
59 8
            \sprintf(Messages::TOP_LEVEL_MEMBERS, implode('", "', $expected))
60
        );
61
62 7
        PHPUnit::assertFalse(
63 7
            isset($json['data']) && isset($json['errors']),
64 7
            Messages::TOP_LEVEL_DATA_AND_ERROR
65
        );
66
67 6
        $allowed = ['data', 'errors', 'meta', 'jsonapi', 'links', 'included'];
68 6
        static::assertContainsOnlyAllowedMembers(
69 6
            $allowed,
70 6
            $json
71
        );
72
73 5
        PHPUnit::assertFALSE(
74 5
            !isset($json['data']) && isset($json['included']),
75 5
            Messages::TOP_LEVEL_DATA_AND_INCLUDED
76
        );
77 4
    }
78
79
    /**
80
     * Asserts that top-level links member of a json document is valid.
81
     *
82
     * @param array $links
83
     *
84
     * @throws PHPUnit\Framework\ExpectationFailedException
85
     */
86 2
    public static function assertIsValidTopLevelLinksMember($links)
87
    {
88 2
        $allowed = ['self', 'related', 'first', 'last', 'next', 'prev'];
89 2
        static::assertIsValidLinksObject($links, $allowed);
90 1
    }
91
92
    /**
93
     * Asserts that the primary data of a json document is valid.
94
     *
95
     * @param array] $data
96
     *
97
     * @throws PHPUnit\Framework\ExpectationFailedException
98
     */
99 8
    public static function assertIsValidPrimaryData($data)
100
    {
101
        try {
102 8
            PHPUnit::assertIsArray(
103 8
                $data,
104 8
                Messages::PRIMARY_DATA_NOT_ARRAY
105
            );
106 6
            if (empty($data)) {
107 6
                return;
108
            }
109 2
        } catch (ExpectationFailedException $e) {
110 2
            PHPUnit::assertNull(
111 2
                $data,
112 2
                Messages::PRIMARY_DATA_NOT_ARRAY
113
            );
114 1
            return;
115
        }
116
117 5
        if (static::isArrayOfObjects($data)) {
118
            // Resource collection (Resource Objects or Resource Identifier Objects)
119 3
            static::assertIsValidResourceCollection($data, true);
120
        } else {
121
            // Single Resource (Resource Object or Resource Identifier Object)
122 2
            static::assertIsValidSingleResource($data);
123
        }
124 4
    }
125
126
    /**
127
     * Asserts that a collection of resource object is valid.
128
     *
129
     * @param array     $list
130
     * @param boolean   $checkType  If true, asserts that all resources of the collection are of same type.
131
     *
132
     * @throws PHPUnit\Framework\ExpectationFailedException
133
     */
134 12
    public static function assertIsValidResourceCollection($list, $checkType)
135
    {
136 12
        static::assertIsArrayOfObjects($list);
137
138 11
        $isResourceObjectCollection = null;
139 11
        foreach ($list as $index => $resource) {
140 10
            if ($checkType) {
141
                // Assert that all resources of the collection are of same type.
142 7
                if ($index == 0) {
143 7
                    $isResourceObjectCollection = static::dataIsResourceObject($resource);
144
                } else {
145 6
                    PHPUnit::assertEquals(
146 6
                        $isResourceObjectCollection,
147 6
                        static::dataIsResourceObject($resource),
148 6
                        Messages::PRIMARY_DATA_SAME_TYPE
149
                    );
150
                }
151
            }
152
153
            // Check the resource
154 10
            static::assertIsValidSingleResource($resource);
155
        }
156 9
    }
157
158
    /**
159
     * Assert that a single resource object is valid.
160
     *
161
     * @param array $resource
162
     *
163
     * @throws PHPUnit\Framework\ExpectationFailedException
164
     */
165 16
    public static function assertIsValidSingleResource($resource)
166
    {
167 16
        static::assertIsNotArrayOfObjects($resource);
168
169 16
        if (static::dataIsResourceObject($resource)) {
170 8
            static::assertIsValidResourceObject($resource);
0 ignored issues
show
Bug introduced by
The method assertIsValidResourceObject() does not exist on VGirol\JsonApiAssert\Asserts\AssertStructure. Did you maybe mean assertIsValidResourceCollection()? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

170
            static::/** @scrutinizer ignore-call */ 
171
                    assertIsValidResourceObject($resource);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
171
        } else {
172 9
            static::assertIsValidResourceIdentifierObject($resource);
0 ignored issues
show
Bug introduced by
The method assertIsValidResourceIdentifierObject() does not exist on VGirol\JsonApiAssert\Asserts\AssertStructure. Did you maybe mean assertIsValidResourceCollection()? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

172
            static::/** @scrutinizer ignore-call */ 
173
                    assertIsValidResourceIdentifierObject($resource);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
173
        }
174 14
    }
175
176
    /**
177
     * Asserts that a collection of included resources is valid.
178
     *
179
     * @param array $included   The included top-level member of a json document.
180
     * @param array $data       The primary data of a json document.
181
     *
182
     * @throws PHPUnit\Framework\ExpectationFailedException
183
     */
184 6
    public static function assertIsValidIncludedCollection($included, $data)
185
    {
186 6
        static::assertIsArrayOfObjects($included);
187
188 4
        static::assertIsValidResourceCollection($included, false);
189
190 4
        $resIdentifiers = array_merge(
191 4
            static::getAllResourceIdentifierObjects($data),
192 4
            static::getAllResourceIdentifierObjects($included)
193
        );
194
195 4
        $present = [];
196 4
        foreach ($included as $inc) {
197 4
            PHPUnit::assertTrue(self::existsInArray($inc, $resIdentifiers));
198
199 4
            if (!isset($present[$inc['type']])) {
200 4
                $present[$inc['type']] = [];
201
            }
202 4
            PHPUnit::assertNotContains(
203 4
                $inc['id'],
204 4
                $present[$inc['type']],
205 4
                Messages::COMPOUND_DOCUMENT_ONLY_ONE_RESOURCE
206
            );
207 4
            array_push($present[$inc['type']], $inc['id']);
208
        }
209 2
    }
210
211 16
    private static function dataIsResourceObject($resource)
212
    {
213 16
        $expected = ['attributes', 'relationships', 'links'];
214
215 16
        return static::containsAtLeastOneMember($expected, $resource);
216
    }
217
218 4
    private static function getAllResourceIdentifierObjects($data)
219
    {
220 4
        $arr = [];
221 4
        if (empty($data)) {
222
            return $arr;
223
        }
224 4
        if (!static::isArrayOfObjects($data)) {
225 2
            $data = [$data];
226
        }
227 4
        foreach ($data as $obj) {
228 4
            if (!isset($obj['relationships'])) {
229 4
                continue;
230
            }
231 4
            foreach ($obj['relationships'] as $key => $relationship) {
232 4
                if (!isset($relationship['data'])) {
233
                    continue;
234
                }
235 4
                $arr = array_merge(
236 4
                    $arr,
237 4
                    static::isArrayOfObjects($relationship['data']) ? $relationship['data'] : [$relationship['data']]
238
                );
239
            }
240
        }
241
242 4
        return $arr;
243
    }
244
245 4
    private static function existsInArray($needle, $arr)
246
    {
247 4
        foreach ($arr as $resIdentifier) {
248 4
            if (($resIdentifier['type'] === $needle['type']) && ($resIdentifier['id'] === $needle['id'])) {
249 4
                return true;
250
            }
251
        }
252
253 1
        return false;
254
    }
255
}
256