Completed
Push — master ( 5927eb...1e13db )
by
unknown
04:04
created

Type   A

Complexity

Total Complexity 20

Size/Duplication

Total Lines 104
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 1

Test Coverage

Coverage 98.15%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
dl 0
loc 104
ccs 53
cts 54
cp 0.9815
rs 10
c 1
b 0
f 0
wmc 20
lcom 0
cbo 1

3 Methods

Rating   Name   Duplication   Size   Complexity  
C validate() 0 53 15
A validateType() 0 10 2
A anyType() 0 17 3
1
<?php
2
3
namespace League\JsonGuard\Constraints;
4
5
use League\JsonGuard;
6
use League\JsonGuard\ErrorCode;
7
use League\JsonGuard\ValidationError;
8
9
class Type implements PropertyConstraint
10
{
11
    /**
12
     * {@inheritdoc}
13
     */
14 34
    public static function validate($value, $type, $pointer = null)
15
    {
16 34
        if (is_array($type)) {
17 4
            return self::anyType($value, $type, $pointer);
18
        }
19
20
        switch ($type) {
21 34
            case 'object':
22 10
                return self::validateType($value, $type, 'is_object', ErrorCode::INVALID_OBJECT, $pointer);
23 34
            case 'array':
24 8
                return self::validateType($value, $type, 'is_array', ErrorCode::INVALID_ARRAY, $pointer);
25 32
            case 'boolean':
26 8
                return self::validateType($value, $type, 'is_bool', ErrorCode::INVALID_BOOLEAN, $pointer);
27 30
            case 'null':
28 4
                return self::validateType($value, $type, 'is_null', ErrorCode::INVALID_NULL, $pointer);
29 30
            case 'number':
30 6
                return self::validateType($value, $type, 'is_numeric', ErrorCode::INVALID_NUMERIC, $pointer);
31 30
            case 'integer':
32 30
                return self::validateType(
33 30
                    $value,
34 30
                    $type,
35
                    function ($value) {
36
                        // when json decoding numbers larger than PHP_INT_MAX,
37
                        // it's possible to receive a valid int as a string.
38 30
                        return is_int($value) || is_string($value) && ctype_digit($value);
39 30
                    },
40 30
                    ErrorCode::INVALID_INTEGER,
41
                    $pointer
42 30
                );
43 20
            case 'string':
44 20
                return self::validateType(
45 20
                    $value,
46 20
                    $type,
47 20
                    function ($value) {
48 20
                        if (is_string($value)) {
49
                            // Make sure the string isn't actually a number that was too large
50
                            // to be cast to an int on this platform.  This is only possible
51
                            // if the bcmath extension is loaded, and will only happen if
52
                            // you decode JSON with the JSON_BIGINT_AS_STRING option.
53 18
                            if (function_exists('bccomp')) {
54 18
                                if (!(ctype_digit($value) && bccomp($value, PHP_INT_MAX, 0) === 1)) {
55 16
                                    return true;
56
                                }
57 2
                            }
58 2
                        }
59
60 18
                        return false;
61 20
                    },
62 20
                    ErrorCode::INVALID_STRING,
63
                    $pointer
64 20
                );
65
        }
66
    }
67
68
    /**
69
     * @param mixed    $value
70
     * @param string   $type
71
     * @param callable $callable
72
     * @param int      $errorCode
73
     * @param string   $pointer
74
     *
75
     * @return \League\JsonGuard\ValidationError|null
76
     */
77 34
    private static function validateType($value, $type, callable $callable, $errorCode, $pointer)
78
    {
79 34
        if (call_user_func($callable, $value) === true) {
80 32
            return null;
81
        }
82
83 34
        $message = sprintf('Value "%s" is not %s.', JsonGuard\asString($value), $type);
84
85 34
        return new ValidationError($message, $errorCode, $value, $pointer);
86
    }
87
88
    /**
89
     * @param mixed  $value
90
     * @param array  $choices
91
     * @param string $pointer
92
     *
93
     * @return \League\JsonGuard\ValidationError|null
94
     */
95 4
    private static function anyType($value, array $choices, $pointer)
96
    {
97 4
        foreach ($choices as $type) {
98 4
            $error = static::validate($value, $type, $pointer);
99 4
            if (is_null($error)) {
100 4
                return null;
101
            }
102 4
        }
103
104 4
        $message = sprintf(
105 4
            'Value "%s" is not one of: %s',
106 4
            JsonGuard\asString($value),
107 4
            implode(', ', array_map('League\JsonGuard\asString', $choices))
108 4
        );
109
110 4
        return new ValidationError($message, ErrorCode::INVALID_TYPE, $value, $pointer, ['types' => $choices]);
111
    }
112
}
113