Completed
Pull Request — master (#45)
by
unknown
15:06 queued 11:50
created

AdditionalProperties   A

Complexity

Total Complexity 9

Size/Duplication

Total Lines 69
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 2

Test Coverage

Coverage 96.3%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 69
ccs 26
cts 27
cp 0.963
rs 10
wmc 9
lcom 0
cbo 2

2 Methods

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