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

Type::validate()   C

Complexity

Conditions 13
Paths 9

Size

Total Lines 49
Code Lines 33

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 34
CRAP Score 13.0039

Importance

Changes 0
Metric Value
cc 13
eloc 33
nc 9
nop 3
dl 0
loc 49
ccs 34
cts 35
cp 0.9714
crap 13.0039
rs 5.1401
c 0
b 0
f 0

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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
76 26
                                || !(ctype_digit($value) && bccomp($value, PHP_INT_MAX) === 1)) {
77 24
                                return true;
78
                            }
79 1
                        }
80
81 18
                        return false;
82 28
                    },
83
                    $validator
84 14
                );
85
        }
86
    }
87
88
    /**
89
     * @param int $bigintMode
90
     *
91
     * @throws \InvalidArgumentException
92
     */
93
    public function setBigintMode($bigintMode = self::BIGINT_MODE_STRING_INVALID)
94
    {
95
        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
        $this->bigintMode = $bigintMode;
100
    }
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 48
    private function validateType($value, callable $callable, Validator $validator)
119
    {
120 48
        if (call_user_func($callable, $value) === true) {
121 44
            return null;
122
        }
123
124 38
        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