Completed
Push — master ( f8d4b2...9b5d9d )
by Márk
10s
created

PhpbrakeHandler::handle()   C

Complexity

Conditions 7
Paths 64

Size

Total Lines 44
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 44
rs 6.7272
c 0
b 0
f 0
cc 7
eloc 24
nc 64
nop 2
1
<?php
2
3
namespace Nofw\Emperror\Handler;
4
5
use Airbrake\Notifier;
6
use Nofw\Emperror\Version;
7
use Nofw\Error\Context;
8
9
/**
10
 * PHP Brake (Airbrake) implementation.
11
 *
12
 * @author Márk Sági-Kazár <[email protected]>
13
 */
14
final class PhpbrakeHandler implements \Nofw\Error\ErrorHandler
15
{
16
    /**
17
     * Notifier details.
18
     */
19
    private const NOTIFIER = [
20
        'name' => 'emperror',
21
        'version' => Version::VERSION,
22
        'url' => 'https://github.com/nofw/emperror',
23
    ];
24
25
    /**
26
     * @var Notifier
27
     */
28
    private $notifier;
29
30
    public function __construct(Notifier $notifier)
31
    {
32
        $this->notifier = $notifier;
33
    }
34
35
    public function handle(\Throwable $t, array $context = []): void
36
    {
37
        $error = [
38
            'type' => get_class($t),
39
            'message' => $t->getMessage(),
40
            'backtrace' => $this->backtrace($t),
41
        ];
42
43
        $pcontext = $context[Context::APP] ?? [];
44
        $pcontext['notifier'] = self::NOTIFIER;
45
46
        if (isset($pcontext['root_dir'])) {
47
            $pcontext['rootDirectory'] = $pcontext['root_dir'];
48
49
            unset($pcontext['root_dir']);
50
        }
51
52
        if (isset($context[Context::USER])) {
53
            $pcontext['user'] = $context[Context::USER];
54
        }
55
56
        $notice = [
57
            'errors' => [$error],
58
            'context' => $pcontext,
59
        ];
60
61
        if (isset($context[Context::ENVIRONMENT])) {
62
            $notice['environment'] = $context[Context::ENVIRONMENT];
63
        }
64
65
        if (isset($context[Context::SESSION])) {
66
            $notice['session'] = $context[Context::SESSION];
67
        }
68
69
        if (isset($context[Context::PARAMETERS])) {
70
            $notice['params'] = $context[Context::PARAMETERS];
71
        }
72
73
        if (isset($context[Context::REQUEST])) {
74
            $notice['params'] = array_merge($context[Context::REQUEST], $notice['params'] ?? []);
75
        }
76
77
        $this->notifier->sendNotice($notice);
78
    }
79
80
    /**
81
     * Creates an Airbrake compatible backtrace representation.
82
     */
83
    private function backtrace(\Throwable $t): array
84
    {
85
        $backtrace = [];
86
87
        $backtrace[] = [
88
            'file' => $t->getFile(),
89
            'line' => $t->getLine(),
90
            'function' => '',
91
        ];
92
93
        $trace = $t->getTrace();
94
95
        foreach ($trace as $frame) {
96
            $func = $frame['function'];
97
98
            if (isset($frame['class']) && isset($frame['type'])) {
99
                $func = $frame['class'].$frame['type'].$func;
100
            }
101
102
            if (count($backtrace) > 0) {
103
                $backtrace[count($backtrace) - 1]['function'] = $func;
104
            }
105
106
            $backtrace[] = [
107
                'file' => isset($frame['file']) ? $frame['file'] : '',
108
                'line' => isset($frame['line']) ? $frame['line'] : 0,
109
                'function' => '',
110
            ];
111
        }
112
113
        return $backtrace;
114
    }
115
}
116