Failed Conditions
Push — master ( 9f23c0...1448ca )
by Adrien
07:45
created

DbWriter::completeEvent()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 14
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
cc 2
eloc 7
nc 2
nop 1
dl 0
loc 14
ccs 0
cts 10
cp 0
crap 6
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Application\Log;
6
7
use Application\Model\User;
8
use Application\Repository\LogRepository;
9
use Zend\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 = User::getCurrent();
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);
1 ignored issue
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(Ap..._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
        // Remove first items from backtrace as it's this function and previous logging functions which is not interesting
103
        $trace = preg_replace('/^#[0-4]\s+[^\n]*\n/m', '', $trace);
104
105
        // Renumber backtrace items.
106
        $trace = preg_replace_callback('/^#(\d+)/m', function ($matches) {
107
            return '#' . ($matches[1] - 5);
108
        }, $trace);
109
110
        return $trace;
111
    }
112
}
113