Passed
Push — master ( 224397...5f8db2 )
by Waaaaaaaaaa
04:30
created

Payload::setContext()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 3
ccs 0
cts 2
cp 0
crap 2
rs 10
1
<?php declare(strict_types=1);
2
3
namespace Logfile;
4
5
use Throwable;
6
7
class Payload
8
{
9
    protected $message;
10
11
    protected $config;
12
13
    protected $id;
14
15
    protected $exceptions = [];
16
17
    public function __construct(string $message, Config $config)
18
    {
19
        $this->message = $message;
20
        $this->config = $config;
21
        $this->id = $this->uuid4();
22
    }
23
24
    public static function createFromException(Throwable $exception, Config $config): self
25
    {
26
        $payload = new Payload($exception->getMessage(), $config);
27
        $payload->pushException($exception);
28
        return $payload;
29
    }
30
31
    public function getMessage(): string
32
    {
33
        return $this->message;
34
    }
35
36
    public function newId(string $id): string
37
    {
38
        $old = $this->id;
39
        $this->id = $id;
40
        return $old;
41
    }
42
43
    public function getId(): string
44
    {
45
        return $this->id;
46
    }
47
48
    public function pushException(Throwable $exception): void
49
    {
50
        $trace = new Stacktrace($exception);
51
        $trace->setPath($this->config->getPath());
52
53
        $this->exceptions[] = [
54
            'exception' => \get_class($exception),
55
            'message' => $exception->getMessage(),
56
            'trace' => $trace->getFrames(),
57
        ];
58
59
        if ($previousException = $exception->getPrevious()) {
60
            $this->pushException($previousException);
61
        }
62
    }
63
64
    public function getExceptions(): array
65
    {
66
        return $this->exceptions;
67
    }
68
69
    /**
70
     * Get payload data
71
     *
72
     * @return array
73
     */
74
    public function getData(): array
75
    {
76
        return [
77
            'id' => $this->getId(),
78
            'message' => $this->getMessage(),
79
            'tags' => $this->config->getTags(),
80
            'exceptions' => $this->getExceptions(),
81
        ];
82
    }
83
84
    /**
85
     * Get payload json encoded
86
     *
87
     * @return string
88
     */
89
    public function getEncodedData(): string
90
    {
91
        $data = $this->getData();
92
        $encoded = json_encode($data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
93
94
        if (JSON_ERROR_UTF8 === json_last_error()) {
95
            if (is_string($data)) {
0 ignored issues
show
introduced by
The condition is_string($data) is always false.
Loading history...
96
                $this->detectAndCleanUtf8($data);
97
            } elseif (is_array($data)) {
0 ignored issues
show
introduced by
The condition is_array($data) is always true.
Loading history...
98
                array_walk_recursive($data, array($this, 'detectAndCleanUtf8'));
99
            }
100
            $encoded = json_encode($data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
101
        }
102
103
        if (JSON_ERROR_NONE !== json_last_error()) {
104
            $error = json_last_error_msg();
105
            throw new \LogicException(sprintf('Failed to encode json data: %s.', $error));
106
        }
107
108
        return $encoded;
109
    }
110
111
    /**
112
     * Detect invalid UTF-8 string characters and convert to valid UTF-8.
113
     * @see https://github.com/Seldaek/monolog/blob/master/src/Monolog/Formatter/NormalizerFormatter.php
114
     */
115
    public function detectAndCleanUtf8(&$data)
116
    {
117
        if (is_string($data) && !preg_match('//u', $data)) {
118
            $data = preg_replace_callback(
119
                '/[\x80-\xFF]+/',
120
                function ($m) {
121
                    return utf8_encode($m[0]);
122
                },
123
                $data
124
            );
125
            $data = str_replace(
126
                array('¤', '¦', '¨', '´', '¸', '¼', '½', '¾'),
127
                array('€', 'Š', 'š', 'Ž', 'ž', 'Œ', 'œ', 'Ÿ'),
128
                $data
129
            );
130
        }
131
    }
132
133
    /**
134
     * Get uuid v4
135
     *
136
     * @see http://www.php.net/manual/en/function.uniqid.php#94959
137
     * @return string
138
     */
139
    protected function uuid4(): string
140
    {
141
        mt_srand();
142
        return sprintf(
143
            '%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
144
            // 32 bits for "time_low"
145
            mt_rand(0, 0xffff),
146
            mt_rand(0, 0xffff),
147
            // 16 bits for "time_mid"
148
            mt_rand(0, 0xffff),
149
            // 16 bits for "time_hi_and_version",
150
            // four most significant bits holds version number 4
151
            mt_rand(0, 0x0fff) | 0x4000,
152
            // 16 bits, 8 bits for "clk_seq_hi_res",
153
            // 8 bits for "clk_seq_low",
154
            // two most significant bits holds zero and one for variant DCE1.1
155
            mt_rand(0, 0x3fff) | 0x8000,
156
            // 48 bits for "node"
157
            mt_rand(0, 0xffff),
158
            mt_rand(0, 0xffff),
159
            mt_rand(0, 0xffff)
160
        );
161
    }
162
}
163