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

Type::getBigintMode()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 4
ccs 0
cts 2
cp 0
crap 2
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 50
    public function __construct($bigintMode = self::BIGINT_MODE_STRING_INVALID)
31
    {
32 50
        $this->bigintMode = $bigintMode;
33 50
    }
34
35
    /**
36
     * {@inheritdoc}
37
     */
38 50
    public function validate($value, $type, Validator $validator)
39
    {
40 50
        Assert::type($type, ['array', 'string'], self::KEYWORD, $validator->getSchemaPath());
41
42 48
        if (is_array($type)) {
43 4
            return $this->anyType($value, $type, $validator);
44
        }
45
46
        switch ($type) {
47 48
            case 'object':
48 16
                return $this->validateType($value, 'is_object', $validator);
49 46
            case 'array':
50 8
                return $this->validateType($value, 'is_array', $validator);
51 44
            case 'boolean':
52 8
                return $this->validateType($value, 'is_bool', $validator);
53 42
            case 'null':
54 4
                return $this->validateType($value, 'is_null', $validator);
55 42
            case 'number':
56 10
                return $this->validateType(
57 5
                    $value,
58 10
                    'League\JsonGuard\is_json_number',
59
                    $validator
60 5
                );
61 38
            case 'integer':
62 32
                return $this->validateType(
63 16
                    $value,
64 32
                    'League\JsonGuard\is_json_integer',
65
                    $validator
66 16
                );
67 28
            case 'string':
68 28
                return $this->validateType(
69 14
                    $value,
70 28
                    function ($value) {
71 28
                        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 26
                            if (self::BIGINT_MODE_STRING_VALID === $this->bigintMode || !(ctype_digit($value) && bccomp($value, PHP_INT_MAX) === 1)) {
76 24
                                return true;
77
                            }
78 1
                        }
79
80 18
                        return false;
81 28
                    },
82
                    $validator
83 14
                );
84
        }
85
    }
86
87
    /**
88
     * @param int $bigintMode
89
     *
90
     * @throws \InvalidArgumentException
91
     */
92
    public function setBigintMode($bigintMode = self::BIGINT_MODE_STRING_INVALID)
93
    {
94
        if (!in_array($bigintMode, [self::BIGINT_MODE_STRING_VALID, self::BIGINT_MODE_STRING_INVALID])) {
95
            throw new \InvalidArgumentException('Please use one of the bigint mode constants.');
96
        }
97
98
        $this->bigintMode = $bigintMode;
99
    }
100
101
    /**
102
     * @return int
103
     */
104
    public function getBigintMode()
105
    {
106
        return $this->bigintMode;
107
    }
108
109
    /**
110
     * @param mixed                       $value
111
     * @param callable                    $callable
112
     * @param \League\JsonGuard\Validator $validator
113
     *
114
     * @return \League\JsonGuard\ValidationError|null
115
     *
116
     */
117 48
    private function validateType($value, callable $callable, Validator $validator)
118
    {
119 48
        if (call_user_func($callable, $value) === true) {
120 44
            return null;
121
        }
122
123 38
        return error('The data must be a(n) {parameter}.', $validator);
124
    }
125
126
    /**
127
     * @param mixed $value
128
     * @param array $choices
129
     *
130
     * @param Validator $validator
131
     *
132
     * @return ValidationError|null
133
     */
134 4
    private function anyType($value, array $choices, Validator $validator)
135
    {
136 4
        foreach ($choices as $type) {
137 4
            $error = $this->validate($value, $type, $validator);
138 4
            if (is_null($error)) {
139 4
                return null;
140
            }
141 2
        }
142
143 4
        return error('The data must be one of {parameter}.', $validator);
144
    }
145
}
146