Completed
Push — master ( bd5ff6...90c2c7 )
by Bernhard
07:04
created

ExceptionTrace::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
ccs 3
cts 3
cp 1
rs 10
cc 1
eloc 2
nc 1
nop 1
crap 1
1
<?php
2
3
/*
4
 * This file is part of the webmozart/console package.
5
 *
6
 * (c) Bernhard Schussek <[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 Webmozart\Console\UI\Component;
13
14
use Exception;
15
use Webmozart\Console\Api\IO\IO;
16
use Webmozart\Console\UI\Component;
17
18
/**
19
 * Renders the trace of an exception.
20
 *
21
 * @since  1.0
22
 *
23
 * @author Bernhard Schussek <[email protected]>
24
 */
25
class ExceptionTrace implements Component
26
{
27
    /**
28
     * @var Exception
29
     */
30
    private $exception;
31
32
    /**
33
     * Creates a renderer for the given exception.
34
     *
35
     * @param Exception $exception The exception to render.
36
     */
37 6
    public function __construct(Exception $exception)
38
    {
39 6
        $this->exception = $exception;
40 6
    }
41
42
    /**
43
     * Renders the exception trace.
44
     *
45
     * @param IO  $io          The I/O.
46
     * @param int $indentation The number of spaces to indent.
47
     */
48 6
    public function render(IO $io, $indentation = 0)
49
    {
50 6
        if (!$io->isVerbose()) {
51 4
            $io->errorLine('fatal: '.$this->exception->getMessage());
52
53 4
            return;
54
        }
55
56 2
        $exception = $this->exception;
57
58 2
        $this->renderException($io, $exception);
59
60 2
        if ($io->isVeryVerbose()) {
61 1
            while ($exception = $exception->getPrevious()) {
62 1
                $io->errorLine('Caused by:');
63
64 1
                $this->renderException($io, $exception);
65
            }
66
        }
67 2
    }
68
69 2
    private function renderException(IO $io, Exception $exception)
70
    {
71 2
        $this->printBox($io, $exception);
72 2
        $this->printTrace($io, $exception);
73 2
    }
74
75 2
    private function printBox(IO $io, Exception $exception)
76
    {
77 2
        $screenWidth = $io->getTerminalDimensions()->getWidth() - 1;
78 2
        $boxWidth = 0;
79
80 2
        $boxLines = array_merge(
81 2
            array(sprintf('[%s]', get_class($exception))),
82
            // TODO replace by implementation that is aware of format codes
83 2
            explode("\n", wordwrap($exception->getMessage(), $screenWidth - 4))
84
        );
85
86 2
        foreach ($boxLines as $line) {
87 2
            $boxWidth = max($boxWidth, strlen($line));
88
        }
89
90
        // TODO handle $boxWidth > $screenWidth
91 2
        $emptyLine = sprintf('<error>%s</error>', str_repeat(' ', $boxWidth + 4));
92
93 2
        $io->errorLine('');
94 2
        $io->errorLine('');
95 2
        $io->errorLine($emptyLine);
96
97 2
        foreach ($boxLines as $boxLine) {
98 2
            $padding = str_repeat(' ', max(0, $boxWidth - strlen($boxLine)));
99 2
            $io->errorLine(sprintf('<error>  %s%s  </error>', $boxLine, $padding));
100
        }
101
102 2
        $io->errorLine($emptyLine);
103 2
        $io->errorLine('');
104 2
        $io->errorLine('');
105 2
    }
106
107 2
    private function printTrace(IO $io, Exception $exception)
108
    {
109 2
        $traces = $exception->getTrace();
110 2
        $cwd = getcwd().DIRECTORY_SEPARATOR;
111 2
        $cwdLength = strlen($cwd);
112
113
        $lastTrace = array(
114 2
            'function' => '',
115
            'args' => array(),
116
        );
117
118 2
        if (null !== $exception->getFile()) {
119 2
            $lastTrace['file'] = $exception->getFile();
120
        }
121
122 2
        if (null !== $exception->getLine()) {
123 2
            $lastTrace['line'] = $exception->getLine();
124
        }
125
126 2
        array_unshift($traces, $lastTrace);
127
128 2
        $io->errorLine('<b>Exception trace:</b>');
129
130 2
        foreach ($traces as $trace) {
131 2
            $namespace = '';
132 2
            $class = '';
133 2
            $location = 'n/a';
134
135 2
            if (isset($trace['class'])) {
136 2
                if (false !== $pos = strrpos($trace['class'], '\\')) {
137 2
                    $namespace = substr($trace['class'], 0, $pos + 1);
138 2
                    $class = substr($trace['class'], $pos + 1);
139
                } else {
140 2
                    $class = $trace['class'];
141
                }
142
            }
143
144 2
            if (isset($trace['file'])) {
145 2
                if (0 === strpos($trace['file'], $cwd)) {
146 2
                    $location = substr($trace['file'], $cwdLength);
147
                } else {
148
                    $location = $trace['file'];
149
                }
150
            }
151
152
            // class, operator, function
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
153 2
            $signature = $class.(isset($trace['type']) ? $trace['type'] : '').$trace['function'];
154 2
            $location .= ':'.(isset($trace['line']) ? $trace['line'] : 'n/a');
155
156 2
            $io->errorLineRaw(sprintf('  %s%s()', $namespace, $io->format('<u>'.$signature.'</u>')));
157 2
            $io->errorLineRaw(sprintf('    %s', $io->format('<c1>'.$location.'</c1>')));
158
        }
159
160 2
        $io->errorLine('');
161 2
        $io->errorLine('');
162 2
    }
163
}
164