Completed
Pull Request — master (#108)
by Matt
19:10
created

Type   A

Complexity

Total Complexity 17

Size/Duplication

Total Lines 93
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 2

Importance

Changes 0
Metric Value
dl 0
loc 93
rs 10
c 0
b 0
f 0
wmc 17
lcom 0
cbo 2

3 Methods

Rating   Name   Duplication   Size   Complexity  
C validate() 0 48 12
A validateType() 0 8 2
A anyType() 0 11 3
1
<?php
2
3
namespace League\JsonGuard\Constraints\DraftFour;
4
5
use League\JsonGuard\Assert;
6
use League\JsonGuard\Constraint;
7
use League\JsonGuard\ValidationError;
8
use League\JsonGuard\Validator;
9
use function League\JsonGuard\error;
10
11
class Type implements Constraint
12
{
13
    const KEYWORD = 'type';
14
15
    /**
16
     * {@inheritdoc}
17
     */
18
    public function validate($value, $type, Validator $validator)
19
    {
20
        Assert::type($type, ['array', 'string'], self::KEYWORD, $validator->getSchemaPath());
21
22
        if (is_array($type)) {
23
            return $this->anyType($value, $type, $validator);
24
        }
25
26
        switch ($type) {
27
            case 'object':
28
                return $this->validateType($value, 'is_object', $validator);
29
            case 'array':
30
                return $this->validateType($value, 'is_array', $validator);
31
            case 'boolean':
32
                return $this->validateType($value, 'is_bool', $validator);
33
            case 'null':
34
                return $this->validateType($value, 'is_null', $validator);
35
            case 'number':
36
                return $this->validateType(
37
                    $value,
38
                    'League\JsonGuard\is_json_number',
39
                    $validator
40
                );
41
            case 'integer':
42
                return $this->validateType(
43
                    $value,
44
                    'League\JsonGuard\is_json_integer',
45
                    $validator
46
                );
47
            case 'string':
48
                return $this->validateType(
49
                    $value,
50
                    function ($value) {
51
                        if (is_string($value)) {
52
                            // Make sure the string isn't actually a number that was too large
53
                            // to be cast to an int on this platform.  This will only happen if
54
                            // you decode JSON with the JSON_BIGINT_AS_STRING option.
55
                            if (!(ctype_digit($value) && bccomp($value, PHP_INT_MAX) === 1)) {
56
                                return true;
57
                            }
58
                        }
59
60
                        return false;
61
                    },
62
                    $validator
63
                );
64
        }
65
    }
66
67
    /**
68
     * @param mixed                       $value
69
     * @param callable                    $callable
70
     * @param \League\JsonGuard\Validator $validator
71
     *
72
     * @return \League\JsonGuard\ValidationError|null
73
     *
74
     */
75
    private function validateType($value, callable $callable, Validator $validator)
76
    {
77
        if (call_user_func($callable, $value) === true) {
78
            return null;
79
        }
80
81
        return error('The data must be a(n) {parameter}.', $validator);
82
    }
83
84
    /**
85
     * @param mixed $value
86
     * @param array $choices
87
     *
88
     * @param Validator $validator
89
     *
90
     * @return ValidationError|null
91
     */
92
    private function anyType($value, array $choices, Validator $validator)
93
    {
94
        foreach ($choices as $type) {
95
            $error = $this->validate($value, $type, $validator);
96
            if (is_null($error)) {
97
                return null;
98
            }
99
        }
100
101
        return error('The data must be one of {parameter}.', $validator);
102
    }
103
}
104