Completed
Push — master ( 5bc96a...96acaf )
by
unknown
14s queued 12s
created

Json::ensureValueIsString()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 4
c 1
b 0
f 0
nc 3
nop 1
dl 0
loc 8
rs 10
1
<?php
2
3
namespace TraderInteractive\Filter;
4
5
use TraderInteractive\Exceptions\FilterException;
6
7
/**
8
 * A collection of filters for JSON
9
 */
10
final class Json
11
{
12
    /**
13
     * @var bool
14
     */
15
    const DEFAULT_SHOULD_ALLOW_NULL = false;
16
17
    /**
18
     * @var int
19
     */
20
    const DEFAULT_RECURSION_DEPTH = 512;
21
22
    /**
23
     * @var string
24
     */
25
    const ERROR_CANNOT_BE_NULL = "Value cannot be null";
26
27
    /**
28
     * @var string
29
     */
30
    const ERROR_NOT_A_STRING = "Value '%s' is not a string";
31
32
    /**
33
     * @var string
34
     */
35
    const ERROR_INVALID_JSON = "JSON failed validation with message '%s'";
36
37
    /**
38
     * Parses a JSON string and returns the result.
39
     *
40
     * @param mixed $value           The value to filter.
41
     * @param bool  $shouldAllowNull Allows null values to pass through the filter when set to true.
42
     * @param int   $depth           The maximum recursion depth.
43
     *
44
     * @return array|bool|int|float|double|null
45
     *
46
     * @throws FilterException Thrown if the value is invalid.
47
     */
48
    public static function parse(
49
        $value,
50
        bool $shouldAllowNull = self::DEFAULT_SHOULD_ALLOW_NULL,
51
        int $depth = self::DEFAULT_RECURSION_DEPTH
52
    ) {
53
        return self::decode($value, $shouldAllowNull, true, $depth);
54
    }
55
56
    /**
57
     * Checks that the JSON is valid and returns the original value.
58
     *
59
     * @param mixed $value           The value to filter.
60
     * @param bool  $shouldAllowNull Allows null values to pass through the filter when set to true.
61
     * @param int   $depth           The maximum recursion depth.
62
     *
63
     * @return string|null
64
     *
65
     * @throws FilterException Thrown if the value is invalid.
66
     */
67
    public static function validate(
68
        $value,
69
        bool $shouldAllowNull = self::DEFAULT_SHOULD_ALLOW_NULL,
70
        int $depth = self::DEFAULT_RECURSION_DEPTH
71
    ) {
72
        self::decode($value, $shouldAllowNull, false, $depth);
73
        return $value;
74
    }
75
76
    /**
77
     * Parses a JSON string and returns the result.
78
     *
79
     * @param mixed $value               The value to filter.
80
     * @param bool  $shouldAllowNull     Allows null values to pass through the filter when set to true.
81
     * @param bool  $shouldDecodeToArray Decodes the JSON string to an associative array when set to true.
82
     * @param int   $depth               The maximum recursion depth.
83
     *
84
     * @return string|array|bool|int|float|double|null
85
     *
86
     * @throws FilterException Thrown if the value is invalid.
87
     */
88
    private static function decode($value, bool $shouldAllowNull, bool $shouldDecodeToArray, int $depth)
89
    {
90
        if ($shouldAllowNull && $value === null) {
91
            return $value;
92
        }
93
94
        self::ensureValueIsString($value);
95
96
        $value = json_decode($value, $shouldDecodeToArray, $depth);
97
        $lastErrorCode = json_last_error();
98
        if ($lastErrorCode !== JSON_ERROR_NONE) {
99
            $message = sprintf(self::ERROR_INVALID_JSON, json_last_error_msg());
100
            throw new FilterException($message, $lastErrorCode);
101
        }
102
103
        return $value;
104
    }
105
106
    /**
107
     * Ensures that the value is a string.
108
     *
109
     * @param mixed $value The value to filter.
110
     *
111
     * @throws FilterException Thrown if the value is not a string.
112
     */
113
    private static function ensureValueIsString($value)
114
    {
115
        if ($value === null) {
116
            throw new FilterException(self::ERROR_CANNOT_BE_NULL);
117
        }
118
119
        if (!is_string($value)) {
120
            throw new FilterException(sprintf(self::ERROR_NOT_A_STRING, var_export($value, true)));
121
        }
122
    }
123
}
124