Completed
Push — master ( e24db7...5dd27b )
by Matt
02:58
created

AdditionalProperties::getDiff()   B

Complexity

Conditions 4
Paths 6

Size

Total Lines 23
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 14
CRAP Score 4

Importance

Changes 0
Metric Value
cc 4
eloc 13
nc 6
nop 2
dl 0
loc 23
ccs 14
cts 14
cp 1
crap 4
rs 8.7972
c 0
b 0
f 0
1
<?php
2
3
namespace League\JsonGuard\Constraints;
4
5
use League\JsonGuard;
6
use League\JsonGuard\SubSchemaValidatorFactory;
7
use League\JsonGuard\ValidationError;
8
9
class AdditionalProperties implements ParentSchemaAwareContainerInstanceConstraint
10
{
11
    const KEYWORD = 'additionalProperties';
12
13
    /**
14
     * {@inheritdoc}
15
     */
16 24
    public static function validate(
17
        $data,
18
        $schema,
19
        $parameter,
20
        SubSchemaValidatorFactory $validatorFactory,
21
        $pointer = null
22
    ) {
23 24
        if (!is_object($data)) {
24 8
            return null;
25
        }
26
27 24
        $diff = self::getDiff($data, $schema);
28
29 24
        if (count($diff) === 0) {
30 18
            return null;
31
        }
32
33 20
        if ($parameter === false) {
34 12
            $message = 'Additional properties found which are not allowed: {diff}';
35 12
            $context = ['diff' => implode(', ', $diff)];
36 12
            return new ValidationError($message, self::KEYWORD, $data, $pointer, $context);
37 12
        } elseif (is_object($parameter)) {
38
            // If additionalProperties is an object it's a schema,
39
            // so validate all additional properties against it.
40 12
            $additionalSchema = array_fill_keys($diff, $parameter);
41
42 12
            return Properties::validate($data, $additionalSchema, $validatorFactory, $pointer);
43
        }
44
45
        return null;
46
    }
47
48
    /**
49
     * Get the properties in $data which are not in $schema 'properties' or matching 'patternProperties'.
50
     *
51
     * @param object $data
52
     * @param object $schema
53
     *
54
     * @return array
55
     */
56 24
    protected static function getDiff($data, $schema)
57
    {
58 24
        if (property_exists($schema, 'properties')) {
59 18
            $definedProperties = array_keys(get_object_vars($schema->properties));
60 18
        } else {
61 10
            $definedProperties = [];
62
        }
63
64 24
        $actualProperties = array_keys(get_object_vars($data));
65 24
        $diff             = array_diff($actualProperties, $definedProperties);
66
67
        // The diff doesn't account for patternProperties, so lets filter those out too.
68 24
        if (property_exists($schema, 'patternProperties')) {
69 8
            foreach ($schema->patternProperties as $property => $schema) {
70 8
                $matches = JsonGuard\properties_matching_pattern($property, $diff);
71 8
                $diff    = array_diff($diff, $matches);
72 8
            }
73
74 8
            return $diff;
75
        }
76
77 20
        return $diff;
78
    }
79
}
80