Completed
Pull Request — master (#3)
by
unknown
11:16
created

ExceptionPrinter::formatArgument()   C

Complexity

Conditions 8
Paths 7

Size

Total Lines 28
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 28
rs 5.3846
c 0
b 0
f 0
cc 8
eloc 14
nc 7
nop 1
1
<?php
2
3
namespace PolderKnowledge\LogModule\Formatter;
4
5
class ExceptionPrinter
6
{
7
    public static function linesFromException(\Throwable $exception, bool $nested = false): array
8
    {
9
        $lines = [];
10
        $lines[] = self::printFirstLineFromException($exception, $nested);
11
12
        foreach ($exception->getTrace() as $traceLine) {
13
            $lines[] = self::formatTraceLine($traceLine);
14
        }
15
16
        if ($exception->getPrevious()) {
17
            $previousLines = self::linesFromException($exception->getPrevious(), true);
18
19
            // recursion makes sure deeper nesting has longer prefixes
20
            foreach ($previousLines as $previousLine) {
21
                $lines[] = '  ' . $previousLine;
22
            }
23
        }
24
25
        return $lines;
26
    }
27
28
    public static function printFirstLineFromException(\Throwable $exception, bool $nested): string
29
    {
30
        return sprintf('[%s] %s: %s in %s:%s',
31
            // only the root exception has a timestamp
32
            $nested ? 'Previous Exception' : date('r'),
33
            get_class($exception),
34
            $exception->getMessage(),
35
            $exception->getFile(),
36
            $exception->getLine()
37
        );
38
    }
39
40
    /**
41
     * Transform an element of the array Exception::getTrace
42
     * to a string of a single line
43
     *
44
     * @param mixed[] $trace element of Exception::getTrace
45
     * @return string of a single line
46
     */
47
    public static function formatTraceLine(array $trace): string
48
    {
49
        $arguments = self::formatArguments($trace['args']);
0 ignored issues
show
Unused Code introduced by
$arguments is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
50
        $output = '';
51
52
        // only display file if we're not in the context of a class
53
        // to save space for the sake for readability of the stack trace
54
        if (isset($trace['file']) && !isset($trace['class'])) {
55
            $output .= $trace['file'];
56
57
            if (isset($trace['line'])) {
58
                $output .= '(' . $trace['line'] . ')';
59
            }
60
61
            $output .= ': ';
62
        }
63
64
        $output .= $trace['class'] ?? '';
65
        $output .= $trace['type'] ?? '';
66
        $output .= $trace['function'] ?? '';
67
68
        $arguments = self::formatArguments($trace['args'] ?? []);
69
        $output .= '(' . $arguments . ')';
70
71
        // print line number now if we skipped it
72
        if (isset($trace['class']) && isset($trace['line'])) {
73
            $output .= ':' . $trace['line'];
74
        }
75
76
        return $output;
77
    }
78
79
    /**
80
     * Convert function arguments of any type to a short readable string
81
     *
82
     * @param mixed[] $arguments
83
     * @return string a summary of the list of arguments
84
     */
85
    public static function formatArguments(array $arguments): string
86
    {
87
        return implode(', ', array_map([__CLASS__, 'formatArgument'], $arguments));
88
    }
89
90
    /**
91
     * Summarize a variable
92
     *
93
     * @param mixed $argument anything at all
94
     * @return string a summary of the argument
95
     */
96
    public static function formatArgument($argument): string
97
    {
98
        if (is_object($argument)) {
99
            return get_class($argument);
100
        }
101
102
        if (is_int($argument) || is_float($argument)) {
103
            return $argument;
104
        }
105
106
        if (is_string($argument)) {
107
            return self::truncateString($argument);
108
        }
109
110
        if ($argument === false) {
111
            return 'false';
112
        }
113
114
        if ($argument === true) {
115
            return 'true';
116
        }
117
118
        if (is_array($argument)) {
119
            return 'Array(' . count($argument) . ')';
120
        }
121
122
        return gettype($argument);
123
    }
124
125
    public static function truncateString(string $argument): string
126
    {
127
        if (strlen($argument) < 80) {
128
            $truncated = $argument;
129
        } else {
130
            $truncated = substr($argument, 0, 30) . '...' . substr($argument, -30, 30);
131
        }
132
133
        return "'$truncated'";
134
    }
135
}
136