Utils::isValidRegex()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 6
c 0
b 0
f 0
ccs 3
cts 3
cp 1
rs 9.4285
cc 1
eloc 3
nc 1
nop 1
crap 1
1
<?php
2
3
/*
4
 * This file is part of the JVal package.
5
 *
6
 * For the full copyright and license information, please view the LICENSE
7
 * file that was distributed with this source code.
8
 */
9
10
namespace JVal;
11
12
use JVal\Exception\JsonDecodeException;
13
14
/**
15
 * Exposes common utility methods.
16
 */
17
class Utils
18
{
19
    private static $jsonErrors = [
20
        JSON_ERROR_NONE => 'No errors',
21
        JSON_ERROR_DEPTH => 'Maximum stack depth exceeded',
22
        JSON_ERROR_STATE_MISMATCH => 'Underflow or the modes mismatch',
23
        JSON_ERROR_CTRL_CHAR => 'Unexpected control character found',
24
        JSON_ERROR_SYNTAX => 'Syntax error, malformed JSON',
25
        JSON_ERROR_UTF8 => 'Malformed UTF-8 characters, possibly incorrectly encoded',
26
    ];
27
28
    /**
29
     * Returns whether two variables are equal. Always compares
30
     * values, not references, and walks each variable recursively
31
     * if needed.
32
     *
33
     * @param mixed $a
34
     * @param mixed $b
35
     *
36
     * @return bool
37
     */
38 50
    public static function areEqual($a, $b)
39
    {
40 50
        return self::doAreEqual($a, $b, []);
41
    }
42
43
    /**
44
     * Returns whether a regex is valid. Regex is supposed to be
45
     * non-anchored (see JSON Schema Validation 3.3).
46
     *
47
     * @param string $regex
48
     *
49
     * @return bool
50
     */
51 56
    public static function isValidRegex($regex)
52
    {
53 56
        $regex = str_replace('/', '\/', $regex);
54
55 56
        return @preg_match("/{$regex}/", '') !== false;
56
    }
57
58
    /**
59
     * Returns whether a string matches a regex. Regex is supposed to be
60
     * non-anchored (see JSON Schema Validation 3.3).
61
     *
62
     * @param string $string
63
     * @param string $regex
64
     *
65
     * @return bool
66
     */
67 44
    public static function matchesRegex($string, $regex)
68
    {
69 44
        $regex = str_replace('/', '\/', $regex);
70
71 44
        return preg_match("/{$regex}/", $string) > 0;
72
    }
73
74
    /**
75
     * Returns the JSON-decoded content of a file.
76
     *
77
     * @param $filePath
78
     *
79
     * @return mixed
80
     *
81
     * @throws \RuntimeException
82
     * @throws JsonDecodeException
83
     */
84 95
    public static function loadJsonFromFile($filePath)
85
    {
86 95
        if (!file_exists($filePath)) {
87 1
            throw new \RuntimeException("File '{$filePath}' doesn't exist");
88
        }
89
90 94
        $content = json_decode(file_get_contents($filePath));
91
92 94
        if (json_last_error() !== JSON_ERROR_NONE) {
93 1
            throw new JsonDecodeException(sprintf(
94 1
                'Cannot decode JSON from file "%s" (error: %s)',
95 1
                $filePath,
96 1
                static::lastJsonErrorMessage()
97 1
            ));
98
        }
99
100 93
        return $content;
101
    }
102
103
    /**
104
     * @codeCoverageIgnore (depends on PHP version)
105
     *
106
     * Returns the error message resulting from the last call to
107
     * json_encode or json_decode functions.
108
     *
109
     * @return string
110
     */
111
    public static function lastJsonErrorMessage()
112
    {
113
        if (defined('json_last_error_msg')) {
114
            return json_last_error_msg();
115
        }
116
117
        $lastError = json_last_error();
118
119
        if (isset(self::$jsonErrors[$lastError])) {
120
            return self::$jsonErrors[$lastError];
121
        }
122
123
        return 'Unknown error';
124
    }
125
126 50
    private static function doAreEqual($a, $b, array $stack)
127
    {
128
        // keep track of object references to avoid infinite recursion
129 50
        if (is_object($a)) {
130 23
            if (in_array($a, $stack)) {
131 1
                return true;
132
            }
133
134 23
            $stack[] = $a;
135 23
        }
136
137 50
        if (gettype($a) !== gettype($b)) {
138 18
            return false;
139
        }
140
141 46
        if (is_object($a)) {
142 15
            $a = (array) $a;
143 15
            $b = (array) $b;
144 15
            ksort($a);
145 15
            ksort($b);
146 15
        }
147
148 46
        if (is_array($a)) {
149 23
            return self::areArrayEqual($a, $b, $stack);
150
        }
151
152 39
        return $a === $b;
153
    }
154
155 23
    private static function areArrayEqual($a, $b, array $stack)
156
    {
157 23
        if (count($a) !== count($b)) {
158 2
            return false;
159
        }
160
161 22
        foreach ($a as $key => $value) {
162 18
            if (!array_key_exists($key, $b)) {
163 1
                return false;
164
            }
165
166 18
            if (!self::doAreEqual($value, $b[$key], $stack)) {
167 9
                return false;
168
            }
169 15
        }
170
171 13
        return true;
172
    }
173
}
174