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
06:13 queued 02:59
created

Creator   A

Complexity

Total Complexity 32

Size/Duplication

Total Lines 205
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 1

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
wmc 32
lcom 1
cbo 1
dl 0
loc 205
ccs 0
cts 134
cp 0
rs 9.6
c 0
b 0
f 0

9 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
B create() 0 24 3
A getTemplate() 0 13 3
A quoteCode() 0 8 2
B normalize() 0 24 6
B normalizeObject() 0 33 5
A normalizeException() 0 10 1
C normalizeArray() 0 33 7
A normalizeFloat() 0 12 4
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\Message;
13
14
use DateTimeInterface;
15
use Exception;
16
use Traversable;
17
18
/**
19
 * Message creator.
20
 *
21
 * @author Henrique Moody <[email protected]>
22
 *
23
 * @since 2.0.0
24
 */
25
final class Creator
26
{
27
    /**
28
     * @var Translator
29
     */
30
    private $translator;
31
32
    /**
33
     * @var int
34
     */
35
    private $maxDepth;
36
37
    /**
38
     * @var int
39
     */
40
    private $maxChildren;
41
42
    /**
43
     * Initializes the message creator.
44
     *
45
     * @param Translator $translator  Message translator to translate the templates
46
     * @param int        $maxDepth    Maximum depth level to show when normalizing data
47
     * @param int        $maxChildren Maximum children level to show when normalizing data
48
     */
49
    public function __construct(Translator $translator, int $maxDepth, int $maxChildren)
50
    {
51
        $this->translator = $translator;
52
        $this->maxDepth = $maxDepth;
53
        $this->maxChildren = $maxChildren;
54
    }
55
56
    /**
57
     * Creates a message based on a result and some templates.
58
     *
59
     * @param mixed $input
60
     * @param array $properties
61
     * @param array $templates
62
     *
63
     * @return string
64
     */
65
    public function create($input, array $properties, array $templates): string
66
    {
67
        $properties += ['placeholder' => $this->normalize($input)];
68
69
        $template = $this->getTemplate($properties, $templates);
70
        $templateTranslated = $this->translator->translate($template);
71
72
        return preg_replace_callback(
73
            '/{{(\w+)}}/',
74
            function ($matches) use ($properties) {
75
                $value = $matches[0];
76
                if (array_key_exists($matches[1], $properties)) {
77
                    $value = $properties[$matches[1]];
78
                }
79
80
                if ($matches[1] === 'placeholder') {
81
                    return $value;
82
                }
83
84
                return $this->normalize($value);
85
            },
86
            $templateTranslated
87
        );
88
    }
89
90
    private function getTemplate(array $properties, array $templates): string
91
    {
92
        if (array_key_exists('template', $properties)) {
93
            return $properties['template'];
94
        }
95
96
        $templateKey = $properties['templateId'] ?? 0;
97
        if (array_key_exists($templateKey, $templates)) {
98
            return $templates[$templateKey];
99
        }
100
101
        return current($templates);
102
    }
103
104
    private function quoteCode(string $string, $currentDepth): string
105
    {
106
        if ($currentDepth === 0) {
107
            $string = sprintf('`%s`', $string);
108
        }
109
110
        return $string;
111
    }
112
113
    private function normalize($raw, $currentDepth = 0): string
114
    {
115
        if (is_object($raw)) {
116
            return $this->normalizeObject($raw, $currentDepth);
117
        }
118
119
        if (is_array($raw)) {
120
            return $this->normalizeArray($raw, $currentDepth);
121
        }
122
123
        if (is_resource($raw)) {
124
            return $this->quoteCode(sprintf('[resource] (%s)', get_resource_type($raw)), $currentDepth);
125
        }
126
127
        if (is_float($raw)) {
128
            return $this->normalizeFloat($raw);
129
        }
130
131
        if (is_bool($raw)) {
132
            return $this->quoteCode(var_export($raw, true), $currentDepth);
133
        }
134
135
        return json_encode($raw, (JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
136
    }
137
138
    private function normalizeObject($raw, int $currentDepth): string
139
    {
140
        $nextDepth = $currentDepth + 1;
141
142
        if ($raw instanceof Traversable) {
143
            $array = iterator_to_array($raw);
144
            $normalized = sprintf('[traversable] (%s: %s)', get_class($raw), $this->normalize($array, $nextDepth));
145
146
            return $this->quoteCode($normalized, $currentDepth);
147
        }
148
149
        if ($raw instanceof DateTimeInterface) {
150
            return sprintf('"%s"', $raw->format('c'));
151
        }
152
153
        if ($raw instanceof Exception) {
154
            $normalized = $this->normalizeException($raw, $nextDepth);
155
156
            return $this->quoteCode($normalized, $currentDepth);
157
        }
158
159
        if (method_exists($raw, '__toString')) {
160
            return $this->normalize($raw->__toString(), $nextDepth);
161
        }
162
163
        $normalized = sprintf(
164
            '[object] (%s: %s)',
165
            get_class($raw),
166
            $this->normalize(get_object_vars($raw), $currentDepth)
167
        );
168
169
        return $this->quoteCode($normalized, $currentDepth);
170
    }
171
172
    private function normalizeException(Exception $exception, int $currentDepth): string
173
    {
174
        $properties = [
175
            'message' => $exception->getMessage(),
176
            'code' => $exception->getCode(),
177
            'file' => str_replace(getcwd().'/', '', $exception->getFile()).':'.$exception->getLine(),
178
        ];
179
180
        return sprintf('[exception] (%s: %s)', get_class($exception), $this->normalize($properties, $currentDepth));
181
    }
182
183
    private function normalizeArray(array $raw, int $currentDepth): string
184
    {
185
        if ($currentDepth >= $this->maxDepth) {
186
            return '...';
187
        }
188
189
        if (empty($raw)) {
190
            return '{ }';
191
        }
192
193
        $string = '';
194
        $total = count($raw);
195
        $current = 0;
196
        $nextDepth = $currentDepth + 1;
197
        foreach ($raw as $key => $value) {
198
            if ($current++ >= $this->maxChildren) {
199
                $string .= ' ... ';
200
                break;
201
            }
202
203
            if (!is_int($key)) {
204
                $string .= sprintf('%s: ', $this->normalize($key, $nextDepth));
205
            }
206
207
            $string .= $this->normalize($value, $nextDepth);
208
209
            if ($current !== $total) {
210
                $string .= ', ';
211
            }
212
        }
213
214
        return sprintf('{ %s }', $string);
215
    }
216
217
    private function normalizeFloat(float $raw): string
218
    {
219
        if (is_infinite($raw)) {
220
            return ($raw > 0 ? '' : '-').'INF';
221
        }
222
223
        if (is_nan($raw)) {
224
            return 'NaN';
225
        }
226
227
        return var_export($raw, true);
228
    }
229
}
230