Subversion-Projekte lars-tiefland.laravel_shop

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
148 lars 1
<?php declare(strict_types=1);
2
 
3
/*
4
 * This file is part of the Monolog package.
5
 *
6
 * (c) Jordi Boggiano <j.boggiano@seld.be>
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 Monolog\Formatter;
13
 
14
use Throwable;
15
 
16
/**
17
 * Encodes whatever record data is passed to it as json
18
 *
19
 * This can be useful to log to databases or remote APIs
20
 *
21
 * @author Jordi Boggiano <j.boggiano@seld.be>
22
 *
23
 * @phpstan-import-type Record from \Monolog\Logger
24
 */
25
class JsonFormatter extends NormalizerFormatter
26
{
27
    public const BATCH_MODE_JSON = 1;
28
    public const BATCH_MODE_NEWLINES = 2;
29
 
30
    /** @var self::BATCH_MODE_* */
31
    protected $batchMode;
32
    /** @var bool */
33
    protected $appendNewline;
34
    /** @var bool */
35
    protected $ignoreEmptyContextAndExtra;
36
    /** @var bool */
37
    protected $includeStacktraces = false;
38
 
39
    /**
40
     * @param self::BATCH_MODE_* $batchMode
41
     */
42
    public function __construct(int $batchMode = self::BATCH_MODE_JSON, bool $appendNewline = true, bool $ignoreEmptyContextAndExtra = false, bool $includeStacktraces = false)
43
    {
44
        $this->batchMode = $batchMode;
45
        $this->appendNewline = $appendNewline;
46
        $this->ignoreEmptyContextAndExtra = $ignoreEmptyContextAndExtra;
47
        $this->includeStacktraces = $includeStacktraces;
48
 
49
        parent::__construct();
50
    }
51
 
52
    /**
53
     * The batch mode option configures the formatting style for
54
     * multiple records. By default, multiple records will be
55
     * formatted as a JSON-encoded array. However, for
56
     * compatibility with some API endpoints, alternative styles
57
     * are available.
58
     */
59
    public function getBatchMode(): int
60
    {
61
        return $this->batchMode;
62
    }
63
 
64
    /**
65
     * True if newlines are appended to every formatted record
66
     */
67
    public function isAppendingNewlines(): bool
68
    {
69
        return $this->appendNewline;
70
    }
71
 
72
    /**
73
     * {@inheritDoc}
74
     */
75
    public function format(array $record): string
76
    {
77
        $normalized = $this->normalize($record);
78
 
79
        if (isset($normalized['context']) && $normalized['context'] === []) {
80
            if ($this->ignoreEmptyContextAndExtra) {
81
                unset($normalized['context']);
82
            } else {
83
                $normalized['context'] = new \stdClass;
84
            }
85
        }
86
        if (isset($normalized['extra']) && $normalized['extra'] === []) {
87
            if ($this->ignoreEmptyContextAndExtra) {
88
                unset($normalized['extra']);
89
            } else {
90
                $normalized['extra'] = new \stdClass;
91
            }
92
        }
93
 
94
        return $this->toJson($normalized, true) . ($this->appendNewline ? "\n" : '');
95
    }
96
 
97
    /**
98
     * {@inheritDoc}
99
     */
100
    public function formatBatch(array $records): string
101
    {
102
        switch ($this->batchMode) {
103
            case static::BATCH_MODE_NEWLINES:
104
                return $this->formatBatchNewlines($records);
105
 
106
            case static::BATCH_MODE_JSON:
107
            default:
108
                return $this->formatBatchJson($records);
109
        }
110
    }
111
 
112
    /**
113
     * @return self
114
     */
115
    public function includeStacktraces(bool $include = true): self
116
    {
117
        $this->includeStacktraces = $include;
118
 
119
        return $this;
120
    }
121
 
122
    /**
123
     * Return a JSON-encoded array of records.
124
     *
125
     * @phpstan-param Record[] $records
126
     */
127
    protected function formatBatchJson(array $records): string
128
    {
129
        return $this->toJson($this->normalize($records), true);
130
    }
131
 
132
    /**
133
     * Use new lines to separate records instead of a
134
     * JSON-encoded array.
135
     *
136
     * @phpstan-param Record[] $records
137
     */
138
    protected function formatBatchNewlines(array $records): string
139
    {
140
        $instance = $this;
141
 
142
        $oldNewline = $this->appendNewline;
143
        $this->appendNewline = false;
144
        array_walk($records, function (&$value, $key) use ($instance) {
145
            $value = $instance->format($value);
146
        });
147
        $this->appendNewline = $oldNewline;
148
 
149
        return implode("\n", $records);
150
    }
151
 
152
    /**
153
     * Normalizes given $data.
154
     *
155
     * @param mixed $data
156
     *
157
     * @return mixed
158
     */
159
    protected function normalize($data, int $depth = 0)
160
    {
161
        if ($depth > $this->maxNormalizeDepth) {
162
            return 'Over '.$this->maxNormalizeDepth.' levels deep, aborting normalization';
163
        }
164
 
165
        if (is_array($data)) {
166
            $normalized = [];
167
 
168
            $count = 1;
169
            foreach ($data as $key => $value) {
170
                if ($count++ > $this->maxNormalizeItemCount) {
171
                    $normalized['...'] = 'Over '.$this->maxNormalizeItemCount.' items ('.count($data).' total), aborting normalization';
172
                    break;
173
                }
174
 
175
                $normalized[$key] = $this->normalize($value, $depth + 1);
176
            }
177
 
178
            return $normalized;
179
        }
180
 
181
        if (is_object($data)) {
182
            if ($data instanceof \DateTimeInterface) {
183
                return $this->formatDate($data);
184
            }
185
 
186
            if ($data instanceof Throwable) {
187
                return $this->normalizeException($data, $depth);
188
            }
189
 
190
            // if the object has specific json serializability we want to make sure we skip the __toString treatment below
191
            if ($data instanceof \JsonSerializable) {
192
                return $data;
193
            }
194
 
195
            if (method_exists($data, '__toString')) {
196
                return $data->__toString();
197
            }
198
 
199
            return $data;
200
        }
201
 
202
        if (is_resource($data)) {
203
            return parent::normalize($data);
204
        }
205
 
206
        return $data;
207
    }
208
 
209
    /**
210
     * Normalizes given exception with or without its own stack trace based on
211
     * `includeStacktraces` property.
212
     *
213
     * {@inheritDoc}
214
     */
215
    protected function normalizeException(Throwable $e, int $depth = 0): array
216
    {
217
        $data = parent::normalizeException($e, $depth);
218
        if (!$this->includeStacktraces) {
219
            unset($data['trace']);
220
        }
221
 
222
        return $data;
223
    }
224
}