Test Failed
Push — main ( c8394f...8477f1 )
by Rafael
66:21
created

ExceptionCaster::castFrameStub()   F

Complexity

Conditions 30
Paths > 20000

Size

Total Lines 71
Code Lines 48

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 30
eloc 48
nc 23833
nop 4
dl 0
loc 71
rs 0
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/*
4
 * This file is part of the Symfony package.
5
 *
6
 * (c) Fabien Potencier <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Symfony\Component\VarDumper\Caster;
13
14
use Symfony\Component\VarDumper\Exception\ThrowingCasterException;
15
use Symfony\Component\VarDumper\Cloner\Stub;
16
17
/**
18
 * Casts common Exception classes to array representation.
19
 *
20
 * @author Nicolas Grekas <[email protected]>
21
 */
22
class ExceptionCaster
23
{
24
    public static $srcContext = 1;
25
    public static $traceArgs = true;
26
    public static $errorTypes = array(
27
        E_DEPRECATED => 'E_DEPRECATED',
28
        E_USER_DEPRECATED => 'E_USER_DEPRECATED',
29
        E_RECOVERABLE_ERROR => 'E_RECOVERABLE_ERROR',
30
        E_ERROR => 'E_ERROR',
31
        E_WARNING => 'E_WARNING',
32
        E_PARSE => 'E_PARSE',
33
        E_NOTICE => 'E_NOTICE',
34
        E_CORE_ERROR => 'E_CORE_ERROR',
35
        E_CORE_WARNING => 'E_CORE_WARNING',
36
        E_COMPILE_ERROR => 'E_COMPILE_ERROR',
37
        E_COMPILE_WARNING => 'E_COMPILE_WARNING',
38
        E_USER_ERROR => 'E_USER_ERROR',
39
        E_USER_WARNING => 'E_USER_WARNING',
40
        E_USER_NOTICE => 'E_USER_NOTICE',
41
        E_STRICT => 'E_STRICT',
42
    );
43
44
    private static $framesCache = array();
45
46
    public static function castError(\Error $e, array $a, Stub $stub, $isNested, $filter = 0)
47
    {
48
        return self::filterExceptionArray($stub->class, $a, "\0Error\0", $filter);
49
    }
50
51
    public static function castException(\Exception $e, array $a, Stub $stub, $isNested, $filter = 0)
52
    {
53
        return self::filterExceptionArray($stub->class, $a, "\0Exception\0", $filter);
54
    }
55
56
    public static function castErrorException(\ErrorException $e, array $a, Stub $stub, $isNested)
57
    {
58
        if (isset($a[$s = Caster::PREFIX_PROTECTED . 'severity'], self::$errorTypes[$a[$s]])) {
59
            $a[$s] = new ConstStub(self::$errorTypes[$a[$s]], $a[$s]);
60
        }
61
62
        return $a;
63
    }
64
65
    public static function castThrowingCasterException(ThrowingCasterException $e, array $a, Stub $stub, $isNested)
66
    {
67
        $prefix = Caster::PREFIX_PROTECTED;
68
        $xPrefix = "\0Exception\0";
69
70
        if (isset($a[$xPrefix . 'previous'], $a[$xPrefix . 'trace']) && $a[$xPrefix . 'previous'] instanceof \Exception) {
71
            $b = (array) $a[$xPrefix . 'previous'];
72
            self::traceUnshift($b[$xPrefix . 'trace'], get_class($a[$xPrefix . 'previous']), $b[$prefix . 'file'], $b[$prefix . 'line']);
73
            $a[$xPrefix . 'trace'] = new TraceStub($b[$xPrefix . 'trace'], false, 0, -1 - count($a[$xPrefix . 'trace']->value));
74
        }
75
76
        unset($a[$xPrefix . 'previous'], $a[$prefix . 'code'], $a[$prefix . 'file'], $a[$prefix . 'line']);
77
78
        return $a;
79
    }
80
81
    public static function castTraceStub(TraceStub $trace, array $a, Stub $stub, $isNested)
82
    {
83
        if (!$isNested) {
84
            return $a;
85
        }
86
        $stub->class = '';
87
        $stub->handle = 0;
88
        $frames = $trace->value;
89
        $prefix = Caster::PREFIX_VIRTUAL;
90
91
        $a = array();
92
        $j = count($frames);
93
        if (0 > $i = $trace->sliceOffset) {
94
            $i = max(0, $j + $i);
95
        }
96
        if (!isset($trace->value[$i])) {
97
            return array();
98
        }
99
        $lastCall = isset($frames[$i]['function']) ? (isset($frames[$i]['class']) ? $frames[0]['class'] . $frames[$i]['type'] : '') . $frames[$i]['function'] . '()' : '';
100
        $frames[] = array('function' => '');
101
102
        for ($j += $trace->numberingOffset - $i++; isset($frames[$i]); ++$i, --$j) {
103
            $f = $frames[$i];
104
            $call = isset($f['function']) ? (isset($f['class']) ? $f['class'] . $f['type'] : '') . $f['function'] . '()' : '???';
105
106
            $label = substr_replace($prefix, "title=Stack level $j.", 2, 0) . $lastCall;
107
            $frame = new FrameStub(
108
                array(
109
                    'object' => isset($f['object']) ? $f['object'] : null,
110
                    'class' => isset($f['class']) ? $f['class'] : null,
111
                    'type' => isset($f['type']) ? $f['type'] : null,
112
                    'function' => isset($f['function']) ? $f['function'] : null,
113
                ) + $frames[$i - 1],
114
                false,
115
                true
116
            );
117
            $f = self::castFrameStub($frame, array(), $frame, true);
118
            if (isset($f[$prefix . 'src'])) {
119
                foreach ($f[$prefix . 'src']->value as $label => $frame) {
120
                    $label = substr_replace($label, "title=Stack level $j.&", 2, 0);
121
                }
122
                $f = $frames[$i - 1];
123
                if ($trace->keepArgs && !empty($f['args']) && $frame instanceof EnumStub) {
124
                    $frame->value['arguments'] = new ArgsStub($f['args'], isset($f['function']) ? $f['function'] : null, isset($f['class']) ? $f['class'] : null);
125
                }
126
            }
127
            $a[$label] = $frame;
128
129
            $lastCall = $call;
130
        }
131
        if (null !== $trace->sliceLength) {
132
            $a = array_slice($a, 0, $trace->sliceLength, true);
133
        }
134
135
        return $a;
136
    }
137
138
    public static function castFrameStub(FrameStub $frame, array $a, Stub $stub, $isNested)
139
    {
140
        if (!$isNested) {
141
            return $a;
142
        }
143
        $f = $frame->value;
144
        $prefix = Caster::PREFIX_VIRTUAL;
145
146
        if (isset($f['file'], $f['line'])) {
147
            $cacheKey = $f;
148
            unset($cacheKey['object'], $cacheKey['args']);
149
            $cacheKey[] = self::$srcContext;
150
            $cacheKey = implode('-', $cacheKey);
151
152
            if (isset(self::$framesCache[$cacheKey])) {
153
                $a[$prefix . 'src'] = self::$framesCache[$cacheKey];
154
            } else {
155
                if (preg_match('/\((\d+)\)(?:\([\da-f]{32}\))? : (?:eval\(\)\'d code|runtime-created function)$/', $f['file'], $match)) {
156
                    $f['file'] = substr($f['file'], 0, -strlen($match[0]));
157
                    $f['line'] = (int) $match[1];
158
                }
159
                $caller = isset($f['function']) ? sprintf('in %s() on line %d', (isset($f['class']) ? $f['class'] . $f['type'] : '') . $f['function'], $f['line']) : null;
160
                $src = $f['line'];
161
                $srcKey = $f['file'];
162
                $ellipsis = explode(DIRECTORY_SEPARATOR, $srcKey);
163
                $ellipsis = 3 < count($ellipsis) ? 2 + strlen(implode(array_slice($ellipsis, -2))) : 0;
164
165
                if (file_exists($f['file']) && 0 <= self::$srcContext) {
166
                    if (!empty($f['class']) && (is_subclass_of($f['class'], 'Twig\Template') || is_subclass_of($f['class'], 'Twig_Template')) && method_exists($f['class'], 'getDebugInfo')) {
167
                        $template = isset($f['object']) ? $f['object'] : unserialize(sprintf('O:%d:"%s":0:{}', strlen($f['class']), $f['class']));
168
169
                        $ellipsis = 0;
170
                        $templateSrc = method_exists($template, 'getSourceContext') ? $template->getSourceContext()->getCode() : (method_exists($template, 'getSource') ? $template->getSource() : '');
171
                        $templateInfo = $template->getDebugInfo();
172
                        if (isset($templateInfo[$f['line']])) {
173
                            if (!method_exists($template, 'getSourceContext') || !file_exists($templatePath = $template->getSourceContext()->getPath())) {
174
                                $templatePath = null;
175
                            }
176
                            if ($templateSrc) {
177
                                $src = self::extractSource($templateSrc, $templateInfo[$f['line']], self::$srcContext, $caller, 'twig', $templatePath);
178
                                $srcKey = ($templatePath ?: $template->getTemplateName()) . ':' . $templateInfo[$f['line']];
179
                            }
180
                        }
181
                    }
182
                    if ($srcKey == $f['file']) {
183
                        $src = self::extractSource(file_get_contents($f['file']), $f['line'], self::$srcContext, $caller, 'php', $f['file']);
184
                        $srcKey .= ':' . $f['line'];
185
                        if ($ellipsis) {
186
                            $ellipsis += 1 + strlen($f['line']);
187
                        }
188
                    }
189
                }
190
                $srcAttr = $ellipsis ? 'ellipsis=' . $ellipsis : '';
191
                self::$framesCache[$cacheKey] = $a[$prefix . 'src'] = new EnumStub(array("\0~$srcAttr\0$srcKey" => $src));
192
            }
193
        }
194
195
        unset($a[$prefix . 'args'], $a[$prefix . 'line'], $a[$prefix . 'file']);
196
        if ($frame->inTraceStub) {
197
            unset($a[$prefix . 'class'], $a[$prefix . 'type'], $a[$prefix . 'function']);
198
        }
199
        foreach ($a as $k => $v) {
200
            if (!$v) {
201
                unset($a[$k]);
202
            }
203
        }
204
        if ($frame->keepArgs && !empty($f['args'])) {
205
            $a[$prefix . 'arguments'] = new ArgsStub($f['args'], $f['function'], $f['class']);
206
        }
207
208
        return $a;
209
    }
210
211
    private static function filterExceptionArray($xClass, array $a, $xPrefix, $filter)
212
    {
213
        if (isset($a[$xPrefix . 'trace'])) {
214
            $trace = $a[$xPrefix . 'trace'];
215
            unset($a[$xPrefix . 'trace']); // Ensures the trace is always last
216
        } else {
217
            $trace = array();
218
        }
219
220
        if (!($filter & Caster::EXCLUDE_VERBOSE)) {
221
            if (isset($a[Caster::PREFIX_PROTECTED . 'file'], $a[Caster::PREFIX_PROTECTED . 'line'])) {
222
                self::traceUnshift($trace, $xClass, $a[Caster::PREFIX_PROTECTED . 'file'], $a[Caster::PREFIX_PROTECTED . 'line']);
223
            }
224
            $a[$xPrefix . 'trace'] = new TraceStub($trace, self::$traceArgs);
225
        }
226
        if (empty($a[$xPrefix . 'previous'])) {
227
            unset($a[$xPrefix . 'previous']);
228
        }
229
        unset($a[$xPrefix . 'string'], $a[Caster::PREFIX_DYNAMIC . 'xdebug_message'], $a[Caster::PREFIX_DYNAMIC . '__destructorException']);
230
231
        if (isset($a[Caster::PREFIX_PROTECTED . 'file'], $a[Caster::PREFIX_PROTECTED . 'line'])) {
232
            $a[Caster::PREFIX_PROTECTED . 'file'] = new LinkStub($a[Caster::PREFIX_PROTECTED . 'file'], $a[Caster::PREFIX_PROTECTED . 'line']);
233
        }
234
235
        return $a;
236
    }
237
238
    private static function traceUnshift(&$trace, $class, $file, $line)
239
    {
240
        if (isset($trace[0]['file'], $trace[0]['line']) && $trace[0]['file'] === $file && $trace[0]['line'] === $line) {
241
            return;
242
        }
243
        array_unshift($trace, array(
244
            'function' => $class ? 'new ' . $class : null,
245
            'file' => $file,
246
            'line' => $line,
247
        ));
248
    }
249
250
    private static function extractSource($srcLines, $line, $srcContext, $title, $lang, $file = null)
251
    {
252
        $srcLines = explode("\n", $srcLines);
253
        $src = array();
254
255
        for ($i = $line - 1 - $srcContext; $i <= $line - 1 + $srcContext; ++$i) {
256
            $src[] = (isset($srcLines[$i]) ? $srcLines[$i] : '') . "\n";
257
        }
258
259
        $srcLines = array();
260
        $ltrim = 0;
261
        do {
262
            $pad = null;
263
            for ($i = $srcContext << 1; $i >= 0; --$i) {
264
                if (isset($src[$i][$ltrim]) && "\r" !== ($c = $src[$i][$ltrim]) && "\n" !== $c) {
265
                    if (null === $pad) {
266
                        $pad = $c;
267
                    }
268
                    if ((' ' !== $c && "\t" !== $c) || $pad !== $c) {
269
                        break;
270
                    }
271
                }
272
            }
273
            ++$ltrim;
274
        } while (0 > $i && null !== $pad);
275
276
        --$ltrim;
277
278
        foreach ($src as $i => $c) {
279
            if ($ltrim) {
280
                $c = isset($c[$ltrim]) && "\r" !== $c[$ltrim] ? substr($c, $ltrim) : ltrim($c, " \t");
281
            }
282
            $c = substr($c, 0, -1);
283
            if ($i !== $srcContext) {
284
                $c = new ConstStub('default', $c);
285
            } else {
286
                $c = new ConstStub($c, $title);
287
                if (null !== $file) {
288
                    $c->attr['file'] = $file;
289
                    $c->attr['line'] = $line;
290
                }
291
            }
292
            $c->attr['lang'] = $lang;
293
            $srcLines[sprintf("\0~%d\0", $i + $line - $srcContext)] = $c;
294
        }
295
296
        return new EnumStub($srcLines);
297
    }
298
}
299