Failed Conditions
Push — master ( 5e6761...398dce )
by Adrien
04:14 queued 01:57
created

DbWriter::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 3
c 1
b 0
f 0
nc 1
nop 3
dl 0
loc 5
cc 1
rs 10
ccs 0
cts 5
cp 0
crap 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Ecodev\Felix\Log;
6
7
use Ecodev\Felix\Model\CurrentUser;
8
use Ecodev\Felix\Repository\LogRepository;
9
use Laminas\Log\Writer\AbstractWriter;
10
11
class DbWriter extends AbstractWriter
12
{
13
    /**
14
     * @var LogRepository
15
     */
16
    private $logRepository;
17
18
    /**
19
     * @var string
20
     */
21
    private $baseUrl;
22
23
    public function __construct(LogRepository $logRepository, string $baseUrl, $options = null)
24
    {
25
        parent::__construct($options);
26
        $this->logRepository = $logRepository;
27
        $this->baseUrl = $baseUrl;
28
    }
29
30
    /**
31
     * Write a message to the log
32
     *
33
     * @param array $event log data event
34
     */
35
    protected function doWrite(array $event): void
36
    {
37
        $completedEvent = $this->completeEvent($event);
38
        $this->logRepository->log($completedEvent);
39
    }
40
41
    private function completeEvent(array $event): array
42
    {
43
        $envData = $this->getEnvData();
44
        $event = array_merge($event, $envData);
45
46
        // If we are logging PHP errors, then we include all known information in message
47
        if ($event['extra']['errno'] ?? false) {
48
            $event['message'] .= "\nStacktrace:\n" . $this->getStacktrace();
49
        }
50
51
        $event['creation_date'] = $event['timestamp'];
52
        unset($event['timestamp'], $event['priorityName']);
53
54
        return $event;
55
    }
56
57
    /**
58
     * Retrieve dynamic information from environment to be logged.
59
     *
60
     * @return array
61
     */
62
    private function getEnvData(): array
63
    {
64
        $user = CurrentUser::get();
65
66
        if (PHP_SAPI === 'cli') {
67
            global $argv;
68
            $request = $argv;
69
            $ip = 'script';
70
            $url = implode(' ', $argv);
71
            $referer = '';
72
        } else {
73
            $request = $_REQUEST;
74
            $ip = $_SERVER['REMOTE_ADDR'] ?? '';
75
            $url = $this->baseUrl . $_SERVER['REQUEST_URI'];
76
            $referer = $_SERVER['HTTP_REFERER'] ?? '';
77
        }
78
79
        $envData = [
80
            'creator_id' => $user ? $user->getId() : null,
81
            'url' => $url,
82
            'referer' => $referer,
83
            'request' => json_encode($request, JSON_PRETTY_PRINT),
84
            'ip' => $ip,
85
        ];
86
87
        return $envData;
88
    }
89
90
    /**
91
     * Returns the backtrace excluding the most recent calls to this function so we only get the interesting parts
92
     *
93
     * @return string
94
     */
95
    private function getStacktrace(): string
96
    {
97
        ob_start();
98
        @debug_print_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
2 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for debug_print_backtrace(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

98
        /** @scrutinizer ignore-unhandled */ @debug_print_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
Bug introduced by
Are you sure the usage of debug_print_backtrace(Ec..._BACKTRACE_IGNORE_ARGS) is correct as it seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
99
        $trace = ob_get_contents();
100
        ob_end_clean();
101
102
        if ($trace === false) {
103
            return 'Could not get stacktrace';
104
        }
105
106
        // Remove first items from backtrace as it's this function and previous logging functions which is not interesting
107
        $shortenTrace = preg_replace('/^#[0-4]\s+[^\n]*\n/m', '', $trace);
108
109
        if ($shortenTrace === null) {
110
            return $trace;
111
        }
112
113
        // Renumber backtrace items.
114
        $renumberedTrace = preg_replace_callback('/^#(\d+)/m', function ($matches) {
115
            return '#' . ($matches[1] - 5);
116
        }, $shortenTrace);
117
118
        if ($renumberedTrace === null) {
119
            return $shortenTrace;
120
        }
121
122
        return $renumberedTrace;
123
    }
124
}
125