Scrutinizer GitHub App not installed

We could not synchronize checks via GitHub's checks API since Scrutinizer's GitHub App is not installed for this repository.

Install GitHub App

Completed
Pull Request — master (#678)
by Henrique
02:51
created

Message::normalize()   B

Complexity

Conditions 6
Paths 6

Size

Total Lines 24
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 24
c 0
b 0
f 0
rs 8.5125
cc 6
eloc 12
nc 6
nop 2
1
<?php
2
3
/*
4
 * This file is part of Respect/Validation.
5
 *
6
 * (c) Alexandre Gomes Gaigalas <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the "LICENSE.md"
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Respect\Validation;
13
14
use DateTimeInterface;
15
use Exception;
16
use Respect\Validation\Annotations\Template;
17
use Traversable;
18
19
final class Message
20
{
21
    /**
22
     * @var int
23
     */
24
    const MAX_DEPTH = 3;
25
26
    /**
27
     * @var int
28
     */
29
    const MAX_CHILDREN = 5;
30
31
    /**
32
     * @var string
33
     */
34
    private $template;
35
36
    /**
37
     * @var mixed
38
     */
39
    private $input;
40
41
    /**
42
     * @var array
43
     */
44
    private $properties;
45
46
    /**
47
     * @var bool
48
     */
49
    private $isIgnorable;
50
51
    /**
52
     * Initializes the object.
53
     *
54
     * @param string $template
55
     * @param mixed  $input
56
     * @param array  $properties
57
     * @param bool   $isIgnorable
58
     */
59
    public function __construct(string $template, $input, array $properties = [], bool $isIgnorable = false)
60
    {
61
        $this->template = $template;
62
        $this->input = $input;
63
        $this->properties = $properties;
64
        $this->isIgnorable = $isIgnorable;
65
    }
66
67
    /**
68
     * @return bool
69
     */
70
    public function isIgnorable(): bool
71
    {
72
        return $this->isIgnorable;
73
    }
74
75
    public function __toString(): string
76
    {
77
        $properties = $this->properties + ['placeholder' => $this->normalize($this->input)];
78
79
        return preg_replace_callback(
80
            '/{{(\w+)}}/',
81
            function ($matches) use ($properties) {
82
                $value = $matches[0];
83
                if (array_key_exists($matches[1], $properties)) {
84
                    $value = $properties[$matches[1]];
85
                }
86
87
                if ($matches[1] === 'placeholder' && is_string($value)) {
88
                    return $value;
89
                }
90
91
                return $this->normalize($value);
92
            },
93
            $this->template
94
        );
95
    }
96
97
    private function quoteCode(string $string, $currentDepth): string
98
    {
99
        if ($currentDepth === 0) {
100
            $string = sprintf('`%s`', $string);
101
        }
102
103
        return $string;
104
    }
105
106
    private function normalize($raw, int $currentDepth = 0): string
107
    {
108
        if (is_object($raw)) {
109
            return $this->normalizeObject($raw, $currentDepth);
110
        }
111
112
        if (is_array($raw)) {
113
            return $this->normalizeArray($raw, $currentDepth);
114
        }
115
116
        if (is_float($raw)) {
117
            return $this->normalizeFloat($raw, $currentDepth);
118
        }
119
120
        if (is_resource($raw)) {
121
            return $this->normalizeResource($raw, $currentDepth);
122
        }
123
124
        if (is_bool($raw)) {
125
            return $this->normalizeBool($raw, $currentDepth);
126
        }
127
128
        return json_encode($raw, (JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
129
    }
130
131
    private function normalizeObject($object, int $currentDepth): string
132
    {
133
        $nextDepth = $currentDepth + 1;
134
135
        if ($object instanceof Traversable) {
136
            $array = iterator_to_array($object);
137
            $normalized = sprintf('[traversable] (%s: %s)', get_class($object), $this->normalize($array, $nextDepth));
138
139
            return $this->quoteCode($normalized, $currentDepth);
140
        }
141
142
        if ($object instanceof DateTimeInterface) {
143
            return sprintf('"%s"', $object->format('c'));
144
        }
145
146
        if ($object instanceof Exception) {
147
            $normalized = $this->normalizeException($object, $nextDepth);
148
149
            return $this->quoteCode($normalized, $currentDepth);
150
        }
151
152
        if (method_exists($object, '__toString')) {
153
            return $this->normalize($object->__toString(), $nextDepth);
154
        }
155
156
        $normalized = sprintf(
157
            '[object] (%s: %s)',
158
            get_class($object),
159
            $this->normalize(get_object_vars($object), $currentDepth)
160
        );
161
162
        return $this->quoteCode($normalized, $currentDepth);
163
    }
164
165
    private function normalizeException(Exception $exception, int $currentDepth): string
166
    {
167
        $properties = [
168
            'message' => $exception->getMessage(),
169
            'code' => $exception->getCode(),
170
            'file' => str_replace(getcwd().'/', '', $exception->getFile()).':'.$exception->getLine(),
171
        ];
172
173
        return sprintf('[exception] (%s: %s)', get_class($exception), $this->normalize($properties, $currentDepth));
174
    }
175
176
    private function normalizeArray(array $array, int $currentDepth): string
177
    {
178
        if ($currentDepth >= self::MAX_DEPTH) {
179
            return '...';
180
        }
181
182
        if (empty($array)) {
183
            return '{ }';
184
        }
185
186
        $string = '';
187
        $total = count($array);
188
        $current = 0;
189
        $nextDepth = $currentDepth + 1;
190
        foreach ($array as $key => $value) {
191
            if ($current++ >= self::MAX_CHILDREN) {
192
                $string .= ' ... ';
193
                break;
194
            }
195
196
            if (!is_int($key)) {
197
                $string .= sprintf('%s: ', $this->normalize($key, $nextDepth));
198
            }
199
200
            $string .= $this->normalize($value, $nextDepth);
201
202
            if ($current !== $total) {
203
                $string .= ', ';
204
            }
205
        }
206
207
        return sprintf('{ %s }', $string);
208
    }
209
210
    private function normalizeFloat(float $float, int $currentDepth): string
211
    {
212
        if (is_infinite($float)) {
213
            return $this->quoteCode(($float > 0 ? '' : '-').'INF', $currentDepth);
214
        }
215
216
        if (is_nan($float)) {
217
            return $this->quoteCode('NaN', $currentDepth);
218
        }
219
220
        return var_export($float, true);
221
    }
222
223
    private function normalizeResource($raw, int $currentDepth): string
224
    {
225
        return $this->quoteCode(sprintf('[resource] (%s)', get_resource_type($raw)), $currentDepth);
226
    }
227
228
    private function normalizeBool(bool $raw, int $currentDepth): string
229
    {
230
        return $this->quoteCode(var_export($raw, true), $currentDepth);
231
    }
232
}
233