Completed
Pull Request — master (#116)
by
unknown
02:26
created

Type::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
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 4
ccs 3
cts 3
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace League\JsonGuard\Constraint\DraftFour;
4
5
use League\JsonGuard\Assert;
6
use League\JsonGuard\ConstraintInterface;
7
use League\JsonGuard\ValidationError;
8
use League\JsonGuard\Validator;
9
use function League\JsonGuard\error;
10
11
final class Type implements ConstraintInterface
12
{
13
    const KEYWORD = 'type';
14
15
    /**
16
     * Whether examples like 98249283749234923498293171823948729348710298301928331
17
     * and "98249283749234923498293171823948729348710298301928331" are valid strings.
18
     */
19
    const BIGINT_MODE_STRING_VALID = 1;
20
    const BIGINT_MODE_STRING_INVALID = 2;
21
22
    /**
23
     * @var int
24
     */
25
    private $bigintMode = 0;
26
27
    /**
28
     * @param int $bigintMode
29
     */
30 54
    public function __construct($bigintMode = self::BIGINT_MODE_STRING_INVALID)
31
    {
32 54
        $this->setBigintMode($bigintMode);
33 54
    }
34
35
    /**
36
     * {@inheritdoc}
37
     */
38 54
    public function validate($value, $type, Validator $validator)
39
    {
40 54
        Assert::type($type, ['array', 'string'], self::KEYWORD, $validator->getSchemaPath());
41
42 52
        if (is_array($type)) {
43 4
            return $this->anyType($value, $type, $validator);
44
        }
45
46
        switch ($type) {
47 52
            case 'object':
48 16
                return $this->validateType($value, 'is_object', $validator);
49 50
            case 'array':
50 8
                return $this->validateType($value, 'is_array', $validator);
51 48
            case 'boolean':
52 8
                return $this->validateType($value, 'is_bool', $validator);
53 46
            case 'null':
54 4
                return $this->validateType($value, 'is_null', $validator);
55 46
            case 'number':
56 10
                return $this->validateType(
57 5
                    $value,
58 10
                    'League\JsonGuard\is_json_number',
59
                    $validator
60 5
                );
61 42
            case 'integer':
62 32
                return $this->validateType(
63 16
                    $value,
64 32
                    'League\JsonGuard\is_json_integer',
65
                    $validator
66 16
                );
67 32
            case 'string':
68 32
                return $this->validateType(
69 16
                    $value,
70 32
                    function ($value) {
71 32
                        if (is_string($value)) {
72
                            // Make sure the string isn't actually a number that was too large
73
                            // to be cast to an int on this platform.  This will only happen if
74
                            // you decode JSON with the JSON_BIGINT_AS_STRING option.
75 30
                            if (self::BIGINT_MODE_STRING_VALID === $this->bigintMode
76 30
                                || !(ctype_digit($value) && bccomp($value, PHP_INT_MAX) === 1)) {
77 26
                                return true;
78
                            }
79 2
                        }
80
81 20
                        return false;
82 32
                    },
83
                    $validator
84 16
                );
85
        }
86
    }
87
88
    /**
89
     * @param int|null $bigintMode
90
     *
91
     * @throws \InvalidArgumentException
92
     */
93 54
    public function setBigintMode($bigintMode = self::BIGINT_MODE_STRING_INVALID)
94
    {
95 54
        if (!in_array($bigintMode, [self::BIGINT_MODE_STRING_VALID, self::BIGINT_MODE_STRING_INVALID])) {
96
            throw new \InvalidArgumentException('Please use one of the bigint mode constants.');
97
        }
98
99 54
        $this->bigintMode = $bigintMode;
100 54
    }
101
102
    /**
103
     * @return int
104
     */
105
    public function getBigintMode()
106
    {
107
        return $this->bigintMode;
108
    }
109
110
    /**
111
     * @param mixed                       $value
112
     * @param callable                    $callable
113
     * @param \League\JsonGuard\Validator $validator
114
     *
115
     * @return \League\JsonGuard\ValidationError|null
116
     *
117
     */
118 52
    private function validateType($value, callable $callable, Validator $validator)
119
    {
120 52
        if (call_user_func($callable, $value) === true) {
121 46
            return null;
122
        }
123
124 40
        return error('The data must be a(n) {parameter}.', $validator);
125
    }
126
127
    /**
128
     * @param mixed $value
129
     * @param array $choices
130
     *
131
     * @param Validator $validator
132
     *
133
     * @return ValidationError|null
134
     */
135 4
    private function anyType($value, array $choices, Validator $validator)
136
    {
137 4
        foreach ($choices as $type) {
138 4
            $error = $this->validate($value, $type, $validator);
139 4
            if (is_null($error)) {
140 4
                return null;
141
            }
142 2
        }
143
144 4
        return error('The data must be one of {parameter}.', $validator);
145
    }
146
}
147