From bc73a2481c2e8974c684e642572643f5de2dff2d Mon Sep 17 00:00:00 2001
From: Paul Klimov <klimov.paul@gmail.com>
Date: Sat, 8 Mar 2014 15:19:46 +0200
Subject: [PATCH] MongoDB log fixed to handle Mongo objects correctly

---
 extensions/mongodb/Collection.php                | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 tests/unit/extensions/mongodb/CollectionTest.php | 24 ++++++++++++++++++++++++
 2 files changed, 83 insertions(+), 1 deletion(-)

diff --git a/extensions/mongodb/Collection.php b/extensions/mongodb/Collection.php
index feea31e..3a5a910 100644
--- a/extensions/mongodb/Collection.php
+++ b/extensions/mongodb/Collection.php
@@ -107,12 +107,70 @@ class Collection extends Object
 	{
 		$parts = [];
 		foreach ($arguments as $argument) {
-			$parts[] = is_scalar($argument) ? $argument : Json::encode($argument);
+			$parts[] = is_scalar($argument) ? $argument : $this->encodeLogData($argument);
 		}
 		return $this->getFullName() . '.' . $command . '(' . implode(', ', $parts) . ')';
 	}
 
 	/**
+	 * Encodes complex log data into JSON format string.
+	 * @param mixed $data raw data.
+	 * @return string encoded data string.
+	 */
+	protected function encodeLogData($data)
+	{
+		return json_encode($this->processLogData($data));
+	}
+
+	/**
+	 * Pre-processes the log data before sending it to `json_encode()`.
+	 * @param mixed $data raw data.
+	 * @return mixed the processed data.
+	 */
+	protected function processLogData($data)
+	{
+		if (is_object($data)) {
+			if ($data instanceof \MongoId ||
+				$data instanceof \MongoRegex ||
+				$data instanceof \MongoDate ||
+				$data instanceof \MongoInt32 ||
+				$data instanceof \MongoInt64 ||
+				$data instanceof \MongoTimestamp
+			) {
+				$data = get_class($data) . '(' . $data->__toString() . ')';
+			} elseif ($data instanceof \MongoCode) {
+				$data = 'MongoCode( ' . $data->__toString() . ' )';
+			} elseif ($data instanceof \MongoBinData) {
+				$data = 'MongoBinData(...)';
+			} elseif ($data instanceof \MongoDBRef) {
+				$data = 'MongoDBRef(...)';
+			} elseif ($data instanceof \MongoMinKey || $data instanceof \MongoMaxKey) {
+				$data = get_class($data);
+			} else {
+				$result = [];
+				foreach ($data as $name => $value) {
+					$result[$name] = $value;
+				}
+				$data = $result;
+			}
+
+			if ($data === []) {
+				return new \stdClass();
+			}
+		}
+
+		if (is_array($data)) {
+			foreach ($data as $key => $value) {
+				if (is_array($value) || is_object($value)) {
+					$data[$key] = $this->processLogData($value);
+				}
+			}
+		}
+
+		return $data;
+	}
+
+	/**
 	 * Drops this collection.
 	 * @throws Exception on failure.
 	 * @return boolean whether the operation successful.
diff --git a/tests/unit/extensions/mongodb/CollectionTest.php b/tests/unit/extensions/mongodb/CollectionTest.php
index d685d2e..cfafd7c 100644
--- a/tests/unit/extensions/mongodb/CollectionTest.php
+++ b/tests/unit/extensions/mongodb/CollectionTest.php
@@ -420,6 +420,10 @@ class CollectionTest extends MongoDbTestCase
 		$this->assertCount(2, $result);
 	}
 
+	/**
+	 * @depends testInsert
+	 * @depends testFind
+	 */
 	public function testFindByNotObjectId()
 	{
 		$collection = $this->getConnection()->getCollection('customer');
@@ -439,4 +443,24 @@ class CollectionTest extends MongoDbTestCase
 		$this->assertTrue($cursor instanceof \MongoCursor);
 		$this->assertEquals(0, $cursor->count());
 	}
+
+	/**
+	 * @depends testInsert
+	 *
+	 * @see https://github.com/yiisoft/yii2/issues/2548
+	 */
+	public function testInsertMongoBin()
+	{
+		$collection = $this->getConnection()->getCollection('customer');
+
+		$fileName = realpath(__DIR__ . '/../../../../extensions/gii/assets/logo.png');
+		$data = [
+			'name' => 'customer 1',
+			'address' => 'customer 1 address',
+			'binData' => new \MongoBinData(file_get_contents($fileName), 2),
+		];
+		$id = $collection->insert($data);
+		$this->assertTrue($id instanceof \MongoId);
+		$this->assertNotEmpty($id->__toString());
+	}
 }
\ No newline at end of file
--
libgit2 0.27.1