Преглед изворни кода

Deprecate DateTimeImmutable (#1928)

Fixes #1926
Ruud Kamphuis пре 1 година
родитељ
комит
a258e4fe90

+ 4 - 0
CHANGELOG.md

@@ -1,3 +1,7 @@
+### Unreleased
+
+  * Deprecated Monolog\DateTimeImmutable in favor of Monolog\JsonSerializableDateTimeImmutable
+
 ### 3.8.0 (2024-11-12)
 
   * Added `$fileOpenMode` param to `StreamHandler` to define a custom fopen mode to open the log file (#1913)

+ 6 - 0
UPGRADE.md

@@ -1,3 +1,9 @@
+### 4.0.0
+
+Overall / notable changes:
+
+- Monolog\DateTimeImmutable has been removed in favor of Monolog\JsonSerializableDateTimeImmutable.
+
 ### 3.0.0
 
 Overall / notable changes:

+ 1 - 1
doc/message-structure.md

@@ -11,7 +11,7 @@ message    | string                    | The log message. When the `PsrLogMessag
 level      | Monolog\Level case        | Severity of the log message. See log levels described in [01-usage.md](01-usage.md#log-levels).
 context    | array                     | Arbitrary data passed with the construction of the message. For example the username of the current user or their IP address.
 channel    | string                    | The channel this message was logged to. This is the name that was passed when the logger was created with `new Logger('channel')`.
-datetime   | Monolog\DateTimeImmutable | Date and time when the message was logged. Class extends `\DateTimeImmutable`.
+datetime   | Monolog\JsonSerializableDateTimeImmutable | Date and time when the message was logged. Class extends `\DateTimeImmutable`.
 extra      | array                     | A placeholder array where processors can put additional data. Always available, but empty if there are no processors registered.
 
 At first glance `context` and `extra` look very similar, and they are in the sense that they both carry arbitrary data that is related to the log message somehow.

+ 6 - 31
src/Monolog/DateTimeImmutable.php

@@ -11,38 +11,13 @@
 
 namespace Monolog;
 
-use DateTimeZone;
+class_alias(JsonSerializableDateTimeImmutable::class, 'Monolog\DateTimeImmutable');
 
-/**
- * Overrides default json encoding of date time objects
- *
- * @author Menno Holtkamp
- * @author Jordi Boggiano <j.boggiano@seld.be>
- */
-class DateTimeImmutable extends \DateTimeImmutable implements \JsonSerializable
-{
-    private bool $useMicroseconds;
-
-    public function __construct(bool $useMicroseconds, ?DateTimeZone $timezone = null)
-    {
-        $this->useMicroseconds = $useMicroseconds;
-
-        // if you like to use a custom time to pass to Logger::addRecord directly,
-        // call modify() or setTimestamp() on this instance to change the date after creating it
-        parent::__construct('now', $timezone);
-    }
-
-    public function jsonSerialize(): string
-    {
-        if ($this->useMicroseconds) {
-            return $this->format('Y-m-d\TH:i:s.uP');
-        }
-
-        return $this->format('Y-m-d\TH:i:sP');
-    }
-
-    public function __toString(): string
+if (false) {
+    /**
+     * @deprecated Use \Monolog\JsonSerializableDateTimeImmutable instead.
+     */
+    class DateTimeImmutable extends JsonSerializableDateTimeImmutable
     {
-        return $this->jsonSerialize();
     }
 }

+ 3 - 3
src/Monolog/Formatter/NormalizerFormatter.php

@@ -11,7 +11,7 @@
 
 namespace Monolog\Formatter;
 
-use Monolog\DateTimeImmutable;
+use Monolog\JsonSerializableDateTimeImmutable;
 use Monolog\Utils;
 use Throwable;
 use Monolog\LogRecord;
@@ -322,9 +322,9 @@ class NormalizerFormatter implements FormatterInterface
 
     protected function formatDate(\DateTimeInterface $date): string
     {
-        // in case the date format isn't custom then we defer to the custom DateTimeImmutable
+        // in case the date format isn't custom then we defer to the custom JsonSerializableDateTimeImmutable
         // formatting logic, which will pick the right format based on whether useMicroseconds is on
-        if ($this->dateFormat === self::SIMPLE_DATE && $date instanceof DateTimeImmutable) {
+        if ($this->dateFormat === self::SIMPLE_DATE && $date instanceof JsonSerializableDateTimeImmutable) {
             return (string) $date;
         }
 

+ 2 - 2
src/Monolog/Handler/ChromePHPHandler.php

@@ -16,7 +16,7 @@ use Monolog\Formatter\FormatterInterface;
 use Monolog\Level;
 use Monolog\Utils;
 use Monolog\LogRecord;
-use Monolog\DateTimeImmutable;
+use Monolog\JsonSerializableDateTimeImmutable;
 
 /**
  * Handler sending logs to the ChromePHP extension (http://www.chromephp.com/)
@@ -150,7 +150,7 @@ class ChromePHPHandler extends AbstractProcessingHandler
                 message: 'Incomplete logs, chrome header size limit reached',
                 level: Level::Warning,
                 channel: 'monolog',
-                datetime: new DateTimeImmutable(true),
+                datetime: new JsonSerializableDateTimeImmutable(true),
             );
             self::$json['rows'][\count(self::$json['rows']) - 1] = $this->getFormatter()->format($record);
             $json = Utils::jsonEncode(self::$json, Utils::DEFAULT_JSON_FLAGS & ~JSON_UNESCAPED_UNICODE, true);

+ 48 - 0
src/Monolog/JsonSerializableDateTimeImmutable.php

@@ -0,0 +1,48 @@
+<?php declare(strict_types=1);
+
+/*
+ * This file is part of the Monolog package.
+ *
+ * (c) Jordi Boggiano <j.boggiano@seld.be>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Monolog;
+
+use DateTimeZone;
+
+/**
+ * Overrides default json encoding of date time objects
+ *
+ * @author Menno Holtkamp
+ * @author Jordi Boggiano <j.boggiano@seld.be>
+ */
+class JsonSerializableDateTimeImmutable extends \DateTimeImmutable implements \JsonSerializable
+{
+    private bool $useMicroseconds;
+
+    public function __construct(bool $useMicroseconds, ?DateTimeZone $timezone = null)
+    {
+        $this->useMicroseconds = $useMicroseconds;
+
+        // if you like to use a custom time to pass to Logger::addRecord directly,
+        // call modify() or setTimestamp() on this instance to change the date after creating it
+        parent::__construct('now', $timezone);
+    }
+
+    public function jsonSerialize(): string
+    {
+        if ($this->useMicroseconds) {
+            return $this->format('Y-m-d\TH:i:s.uP');
+        }
+
+        return $this->format('Y-m-d\TH:i:sP');
+    }
+
+    public function __toString(): string
+    {
+        return $this->jsonSerialize();
+    }
+}

+ 5 - 4
src/Monolog/Logger.php

@@ -323,12 +323,13 @@ class Logger implements LoggerInterface, ResettableInterface
      * @param  int                    $level    The logging level (a Monolog or RFC 5424 level)
      * @param  string                 $message  The log message
      * @param  mixed[]                $context  The log context
-     * @param  DateTimeImmutable|null $datetime Optional log date to log into the past or future
+     * @param  JsonSerializableDateTimeImmutable|null $datetime Optional log date to log into the past or future
+     *
      * @return bool                   Whether the record has been processed
      *
      * @phpstan-param value-of<Level::VALUES>|Level $level
      */
-    public function addRecord(int|Level $level, string $message, array $context = [], DateTimeImmutable|null $datetime = null): bool
+    public function addRecord(int|Level $level, string $message, array $context = [], JsonSerializableDateTimeImmutable|null $datetime = null): bool
     {
         if (\is_int($level) && isset(self::RFC_5424_LEVELS[$level])) {
             $level = self::RFC_5424_LEVELS[$level];
@@ -356,7 +357,7 @@ class Logger implements LoggerInterface, ResettableInterface
             $recordInitialized = \count($this->processors) === 0;
 
             $record = new LogRecord(
-                datetime: $datetime ?? new DateTimeImmutable($this->microsecondTimestamps, $this->timezone),
+                datetime: $datetime ?? new JsonSerializableDateTimeImmutable($this->microsecondTimestamps, $this->timezone),
                 channel: $this->name,
                 level: self::toMonologLevel($level),
                 message: $message,
@@ -518,7 +519,7 @@ class Logger implements LoggerInterface, ResettableInterface
     public function isHandling(int|string|Level $level): bool
     {
         $record = new LogRecord(
-            datetime: new DateTimeImmutable($this->microsecondTimestamps, $this->timezone),
+            datetime: new JsonSerializableDateTimeImmutable($this->microsecondTimestamps, $this->timezone),
             channel: $this->name,
             message: '',
             level: self::toMonologLevel($level),

+ 1 - 1
src/Monolog/Processor/PsrLogMessageProcessor.php

@@ -60,7 +60,7 @@ class PsrLogMessageProcessor implements ProcessorInterface
             if (null === $val || \is_scalar($val) || (\is_object($val) && method_exists($val, "__toString"))) {
                 $replacements[$placeholder] = $val;
             } elseif ($val instanceof \DateTimeInterface) {
-                if (null === $this->dateFormat && $val instanceof \Monolog\DateTimeImmutable) {
+                if (null === $this->dateFormat && $val instanceof \Monolog\JsonSerializableDateTimeImmutable) {
                     // handle monolog dates using __toString if no specific dateFormat was asked for
                     // so that it follows the useMicroseconds flag
                     $replacements[$placeholder] = (string) $val;

+ 2 - 2
src/Monolog/Test/TestCase.php

@@ -14,7 +14,7 @@ namespace Monolog\Test;
 use Monolog\Level;
 use Monolog\Logger;
 use Monolog\LogRecord;
-use Monolog\DateTimeImmutable;
+use Monolog\JsonSerializableDateTimeImmutable;
 use Monolog\Formatter\FormatterInterface;
 use Psr\Log\LogLevel;
 use ReflectionProperty;
@@ -34,7 +34,7 @@ class TestCase extends \PHPUnit\Framework\TestCase
      *
      * @phpstan-param value-of<Level::VALUES>|value-of<Level::NAMES>|Level|LogLevel::* $level
      */
-    protected function getRecord(int|string|Level $level = Level::Warning, string|\Stringable $message = 'test', array $context = [], string $channel = 'test', \DateTimeImmutable $datetime = new DateTimeImmutable(true), array $extra = []): LogRecord
+    protected function getRecord(int|string|Level $level = Level::Warning, string|\Stringable $message = 'test', array $context = [], string $channel = 'test', \DateTimeImmutable $datetime = new JsonSerializableDateTimeImmutable(true), array $extra = []): LogRecord
     {
         return new LogRecord(
             message: (string) $message,

+ 2 - 2
tests/Monolog/Formatter/ScalarFormatterTest.php

@@ -11,7 +11,7 @@
 
 namespace Monolog\Formatter;
 
-use Monolog\DateTimeImmutable;
+use Monolog\JsonSerializableDateTimeImmutable;
 use Monolog\Test\TestCase;
 
 class ScalarFormatterTest extends TestCase
@@ -57,7 +57,7 @@ class ScalarFormatterTest extends TestCase
             'baz' => false,
             'bam' => [1, 2, 3],
             'bat' => ['foo' => 'bar'],
-            'bap' => $dt = new DateTimeImmutable(true),
+            'bap' => $dt = new JsonSerializableDateTimeImmutable(true),
             'ban' => $exception,
         ]));
 

+ 3 - 3
tests/Monolog/LoggerTest.php

@@ -556,7 +556,7 @@ class LoggerTest extends TestCase
 
     /**
      * @covers Logger::setTimezone
-     * @covers DateTimeImmutable::__construct
+     * @covers JsonSerializableDateTimeImmutable::__construct
      */
     public function testTimezoneIsRespectedInUTC()
     {
@@ -578,7 +578,7 @@ class LoggerTest extends TestCase
 
     /**
      * @covers Logger::setTimezone
-     * @covers DateTimeImmutable::__construct
+     * @covers JsonSerializableDateTimeImmutable::__construct
      */
     public function testTimezoneIsRespectedInOtherTimezone()
     {
@@ -807,7 +807,7 @@ class LoggerTest extends TestCase
             $logger->pushHandler($loggingHandler);
             $logger->pushHandler($testHandler);
 
-            $datetime = (new DateTimeImmutable($microseconds))->modify('2022-03-04 05:06:07');
+            $datetime = (new JsonSerializableDateTimeImmutable($microseconds))->modify('2022-03-04 05:06:07');
             $logger->addRecord(Level::Debug, 'test', [], $datetime);
 
             list($record) = $testHandler->getRecords();