Completed
Pull Request — master (#88)
by Matt
56:34 queued 23:44
created

Type   A

Complexity

Total Complexity 17

Size/Duplication

Total Lines 111
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 3

Test Coverage

Coverage 98.44%

Importance

Changes 0
Metric Value
dl 0
loc 111
ccs 63
cts 64
cp 0.9844
rs 10
c 0
b 0
f 0
wmc 17
lcom 0
cbo 3

3 Methods

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