Просмотр исходного кода

Replace deprecated code in MongoDB classes and allow 2.0+ (#1998)

* Remove unused code path in MongoDBFormatter

Monolog already required mongodb/mongodb 1.8+ (and a related ext-mongodb version) so this code path was never used.

* Use Collection::getCollection() from mongodb/mongodb 1.21

The original selectCollection method is deprecated. Since Monolog itself requires PHP 8.1, it should be sane to rely on 1.21+, which shares the same requirement.

* Update class refs for MongoDB extension and library

* Conditionally use Collection getter by version

* Relax PHPLIB version requirement

* Use RequiresPhpExtension attribute to require ext-mongodb

* Import UTCDateTime class and revise var names
Jeremy Mikola 2 месяцев назад
Родитель
Сommit
2dc620c22c

+ 1 - 1
composer.json

@@ -24,7 +24,7 @@
         "graylog2/gelf-php": "^1.4.2 || ^2@dev",
         "guzzlehttp/guzzle": "^7.4",
         "guzzlehttp/psr7": "^2.2",
-        "mongodb/mongodb": "^1.8",
+        "mongodb/mongodb": "^1.8 || ^2.0",
         "php-amqplib/php-amqplib": "~2.4 || ^3",
         "phpspec/prophecy": "^1.15",
         "phpstan/phpstan": "^1.10",

+ 0 - 32
src/Monolog/Formatter/MongoDBFormatter.php

@@ -26,8 +26,6 @@ class MongoDBFormatter implements FormatterInterface
     private $exceptionTraceAsString;
     /** @var int */
     private $maxNestingLevel;
-    /** @var bool */
-    private $isLegacyMongoExt;
 
     /**
      * @param int  $maxNestingLevel        0 means infinite nesting, the $record itself is level 1, $record['context'] is 2
@@ -37,8 +35,6 @@ class MongoDBFormatter implements FormatterInterface
     {
         $this->maxNestingLevel = max($maxNestingLevel, 0);
         $this->exceptionTraceAsString = $exceptionTraceAsString;
-
-        $this->isLegacyMongoExt = extension_loaded('mongodb') && version_compare((string) phpversion('mongodb'), '1.1.9', '<=');
     }
 
     /**
@@ -128,35 +124,7 @@ class MongoDBFormatter implements FormatterInterface
     }
 
     protected function formatDate(\DateTimeInterface $value, int $nestingLevel): UTCDateTime
-    {
-        if ($this->isLegacyMongoExt) {
-            return $this->legacyGetMongoDbDateTime($value);
-        }
-
-        return $this->getMongoDbDateTime($value);
-    }
-
-    private function getMongoDbDateTime(\DateTimeInterface $value): UTCDateTime
     {
         return new UTCDateTime((int) floor(((float) $value->format('U.u')) * 1000));
     }
-
-    /**
-     * This is needed to support MongoDB Driver v1.19 and below
-     *
-     * See https://github.com/mongodb/mongo-php-driver/issues/426
-     *
-     * It can probably be removed in 2.1 or later once MongoDB's 1.2 is released and widely adopted
-     */
-    private function legacyGetMongoDbDateTime(\DateTimeInterface $value): UTCDateTime
-    {
-        $milliseconds = floor(((float) $value->format('U.u')) * 1000);
-
-        $milliseconds = (PHP_INT_SIZE == 8) //64-bit OS?
-            ? (int) $milliseconds
-            : (string) $milliseconds;
-
-        // @phpstan-ignore-next-line
-        return new UTCDateTime($milliseconds);
-    }
 }

+ 7 - 6
src/Monolog/Handler/MongoDBHandler.php

@@ -11,12 +11,13 @@
 
 namespace Monolog\Handler;
 
+use MongoDB\Client;
+use MongoDB\Collection;
 use MongoDB\Driver\BulkWrite;
 use MongoDB\Driver\Manager;
-use MongoDB\Client;
-use Monolog\Logger;
 use Monolog\Formatter\FormatterInterface;
 use Monolog\Formatter\MongoDBFormatter;
+use Monolog\Logger;
 
 /**
  * Logs to a MongoDB database.
@@ -33,12 +34,12 @@ use Monolog\Formatter\MongoDBFormatter;
  */
 class MongoDBHandler extends AbstractProcessingHandler
 {
-    /** @var \MongoDB\Collection */
+    /** @var Collection */
     private $collection;
     /** @var Client|Manager */
     private $manager;
-    /** @var string */
-    private $namespace;
+    /** @var string|null */
+    private $namespace = null;
 
     /**
      * Constructor.
@@ -54,7 +55,7 @@ class MongoDBHandler extends AbstractProcessingHandler
         }
 
         if ($mongodb instanceof Client) {
-            $this->collection = $mongodb->selectCollection($database, $collection);
+            $this->collection = method_exists($mongodb, 'getCollection') ? $mongodb->getCollection($database, $collection) : $mongodb->selectCollection($database, $collection);
         } else {
             $this->manager = $mongodb;
             $this->namespace = $database . '.' . $collection;

+ 3 - 3
tests/Monolog/Formatter/MongoDBFormatterTest.php

@@ -23,7 +23,7 @@ class MongoDBFormatterTest extends \PHPUnit\Framework\TestCase
 {
     public function setUp(): void
     {
-        if (!class_exists('MongoDB\BSON\UTCDateTime')) {
+        if (!extension_loaded('mongodb')) {
             $this->markTestSkipped('ext-mongodb not installed');
         }
     }
@@ -78,7 +78,7 @@ class MongoDBFormatterTest extends \PHPUnit\Framework\TestCase
         $this->assertEquals(Logger::WARNING, $formattedRecord['level']);
         $this->assertEquals(Logger::getLevelName(Logger::WARNING), $formattedRecord['level_name']);
         $this->assertEquals('test', $formattedRecord['channel']);
-        $this->assertInstanceOf('MongoDB\BSON\UTCDateTime', $formattedRecord['datetime']);
+        $this->assertInstanceOf(UTCDateTime::class, $formattedRecord['datetime']);
         $this->assertEquals('1453410690123', $formattedRecord['datetime']->__toString());
         $this->assertEquals([], $formattedRecord['extra']);
     }
@@ -109,7 +109,7 @@ class MongoDBFormatterTest extends \PHPUnit\Framework\TestCase
         $formattedRecord = $formatter->format($record);
 
         $this->assertCount(5, $formattedRecord['context']);
-        $this->assertInstanceOf('MongoDB\BSON\UTCDateTime', $formattedRecord['context']['stuff']);
+        $this->assertInstanceOf(UTCDateTime::class, $formattedRecord['context']['stuff']);
         $this->assertEquals('-29731710213', $formattedRecord['context']['stuff']->__toString());
         $this->assertEquals(
             [

+ 17 - 11
tests/Monolog/Handler/MongoDBHandlerTest.php

@@ -11,11 +11,21 @@
 
 namespace Monolog\Handler;
 
+use MongoDB\BSON\UTCDateTime;
+use MongoDB\Client;
+use MongoDB\Collection;
 use MongoDB\Driver\Manager;
 use Monolog\Test\TestCase;
 
 class MongoDBHandlerTest extends TestCase
 {
+    public function setUp(): void
+    {
+        if (!extension_loaded('mongodb')) {
+            $this->markTestSkipped('ext-mongodb not installed');
+        }
+    }
+
     public function testConstructorShouldThrowExceptionForInvalidMongo()
     {
         $this->expectException(\InvalidArgumentException::class);
@@ -25,41 +35,37 @@ class MongoDBHandlerTest extends TestCase
 
     public function testHandleWithLibraryClient()
     {
-        if (!(class_exists('MongoDB\Client'))) {
+        if (!class_exists(Client::class)) {
             $this->markTestSkipped('mongodb/mongodb not installed');
         }
 
-        $mongodb = $this->getMockBuilder('MongoDB\Client')
+        $client = $this->getMockBuilder(Client::class)
             ->disableOriginalConstructor()
             ->getMock();
 
-        $collection = $this->getMockBuilder('MongoDB\Collection')
+        $collection = $this->getMockBuilder(Collection::class)
             ->disableOriginalConstructor()
             ->getMock();
 
-        $mongodb->expects($this->once())
-            ->method('selectCollection')
+        $client->expects($this->once())
+            ->method('getCollection')
             ->with('db', 'collection')
             ->will($this->returnValue($collection));
 
         $record = $this->getRecord();
         $expected = $record;
-        $expected['datetime'] = new \MongoDB\BSON\UTCDateTime((int) floor(((float) $record['datetime']->format('U.u')) * 1000));
+        $expected['datetime'] = new UTCDateTime((int) floor(((float) $record['datetime']->format('U.u')) * 1000));
 
         $collection->expects($this->once())
             ->method('insertOne')
             ->with($expected);
 
-        $handler = new MongoDBHandler($mongodb, 'db', 'collection');
+        $handler = new MongoDBHandler($client, 'db', 'collection');
         $handler->handle($record);
     }
 
     public function testHandleWithDriverManager()
     {
-        if (!(class_exists('MongoDB\Driver\Manager'))) {
-            $this->markTestSkipped('ext-mongodb not installed');
-        }
-
         /* This can become a unit test once ManagerInterface can be mocked.
          * See: https://jira.mongodb.org/browse/PHPC-378
          */