Add mongodb storage #4

Merged
merged 4 commits into from May 21, 2012
View
171 lib/Doctrine/KeyValueStore/Storage/MongoDbStorage.php
@@ -0,0 +1,171 @@
+<?php
+/*
@stof
Doctrine member
stof added a note May 11, 2012

The license header is missing

@Baachi
Baachi added a note May 11, 2012

Yes, I know.

Which licence is used, MIT or LGPL?

@stof
Doctrine member
stof added a note May 11, 2012

currently, it is still LGPL. but as Doctrine is switching, we need to know if beberlei wants to change before or after merging :)

@Baachi
Baachi added a note May 11, 2012

I agree.

I wait of @beberlei answer :)

@beberlei
Doctrine member

MIT

@Baachi
Baachi added a note May 11, 2012

Done :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* This software consists of voluntary contributions made by many individuals
+* and is licensed under the MIT license. For more information, see
+* <http://www.doctrine-project.org>.
+*/
+
+namespace Doctrine\KeyValueStore\Storage;
+
+use Doctrine\KeyValueStore\NotFoundException;
+
+/**
+ * MongoDb storage
+ *
+ * @author Markus Bachmann <markus.bachmann@bachi.biz>
+ */
+class MongoDbStorage implements Storage
+{
+ /**
+ * @var \Mongo
+ */
+ protected $mongo;
+
+ /**
+ * @var array
+ */
+ protected $dbOptions;
+
+ /**
+ * @var \MongoCollection
+ */
+ protected $collection;
+
+ /**
+ * Constructor
+ *
+ * @param \Mongo $mongo
+ * @param array $dbOptions
+ */
+ public function __construct(\Mongo $mongo, array $dbOptions = array())
+ {
+ $this->mongo = $mongo;
+ $this->dbOptions = array_merge(array(
+ 'database' => '',
+ 'collection' => '',
+ ), $dbOptions);
+ }
+
+ /**
+ * Initialize the mongodb collection
+ *
+ * @throws \RuntimeException
+ */
+ public function initialize()
+ {
+ if (null !== $this->collection) {
+ return;
+ }
+
+ if (empty($this->dbOptions['database'])) {
+ throw new \RuntimeException('The option "database" must be set');
+ }
+ if (empty($this->dbOptions['collection'])) {
+ throw new \RuntimeException('The option "collection" must be set');
+ }
+
+ $this->collection = $this->mongo->selectDB($this->dbOptions['database'])->selectCollection($this->dbOptions['collection']);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function supportsPartialUpdates()
+ {
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function supportsCompositePrimaryKeys()
+ {
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function requiresCompositePrimaryKeys()
+ {
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function insert($storageName, $key, array $data)
+ {
+ $this->initialize();
+
+ $value = array(
+ 'key' => $key,
+ 'value' => $data,
+ );
+
+ $this->collection->insert($value);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function update($storageName, $key, array $data)
+ {
+ $this->initialize();
+
+ $value = array(
+ 'key' => $key,
+ 'value' => $data,
+ );
+
+ $this->collection->update(array('key' => $key), $value);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function delete($storageName, $key)
+ {
+ $this->initialize();
+
+ $this->collection->remove(array('key' => $key));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function find($storageName, $key)
+ {
+ $this->initialize();
+
+ $value = $this->collection->findOne(array('key' => $key), array('value'));
+
+ if ($value) {
+ return $value['value'];
+ }
+
+ throw new NotFoundException();
+ }
+
+ /**
+ * Return a name of the underlying storage.
+ *
+ * @return string
+ */
+ public function getName()
+ {
+ return 'mongodb';
+ }
+}
View
140 tests/Doctrine/Tests/KeyValueStore/Storage/MongoDbStorageTest.php
@@ -0,0 +1,140 @@
+<?php
+
+namespace Doctrine\Tests\KeyValueStore\Storage;
+
+use Doctrine\KeyValueStore\Storage\MongoDbStorage;
+
+/**
+ * MongoDb storage testcase
+ *
+ * @author Markus Bachmann <markus.bachmann@bachi.biz>
+ */
+class MongoDbStorageTest extends \PHPUnit_Framework_TestCase
+{
+ protected function setUp()
+ {
+ $this->mongo = $this->getMock('\Mongo');
+
+ $this->mongodb = $this->getMockBuilder('\MongoDB')->disableOriginalConstructor()->getMock();
+
+ $this->mongo->expects($this->any())
+ ->method('selectDB')
+ ->will($this->returnValue($this->mongodb));
+
+ $this->collection = $this->getMockBuilder('MongoCollection')->disableOriginalConstructor()->getMock();
+
+ $this->mongodb->expects($this->once())
+ ->method('selectCollection')
+ ->will($this->returnValue($this->collection));
+
+ $this->storage = new MongoDbStorage($this->mongo, array(
+ 'collection' => 'test',
+ 'database' => 'test'
+ ));
+ }
+
+ public function testInsert()
+ {
+ $data = array(
+ 'author' => 'John Doe',
+ 'title' => 'example book',
+ );
+
+ $dbDataset = array();
+
+ $this->collection->expects($this->once())
+ ->method('insert')
+ ->will($this->returnCallback(function($data) use (&$dbDataset) {
+ $dbDataset[] = $data;
+ }));
+
+ $this->storage->insert('mongodb', '1', $data);
+ $this->assertCount(1, $dbDataset);
+
+ $this->assertEquals(array(array('key' => '1', 'value' => $data)), $dbDataset);
+ }
+
+ public function testUpdate()
+ {
+ $data = array(
+ 'author' => 'John Doe',
+ 'title' => 'example book',
+ );
+
+ $dbDataset = array();
+
+ $this->collection->expects($this->once())
+ ->method('update')
+ ->will($this->returnCallback(function($citeria, $data) use (&$dbDataset) {
+ $dbDataset = array($citeria, $data);
+ }));
+
+ $this->storage->update('mongodb', '1', $data);
+
+ $this->assertEquals(array('key' => '1'), $dbDataset[0]);
+ $this->assertEquals(array('key' => '1', 'value' => $data), $dbDataset[1]);
+ }
+
+ public function testDelete()
+ {
+ $dataset = array(
+ array(
+ 'key' => 'foobar',
+ 'value' => array(
+ 'author' => 'John Doe',
+ 'title' => 'example book',
+ ),
+ ),
+ );
+
+ $this->collection->expects($this->once())
+ ->method('remove')
+ ->will($this->returnCallback(function($citeria) use (&$dataset) {
+ foreach ($dataset as $key => $row) {
+ if ($row['key'] === $citeria['key']) {
+ unset($dataset[$key]);
+ }
+ }
+ }
+ ));
+
+ $this->storage->delete('test', 'foobar');
+
+ $this->assertCount(0, $dataset);
+ }
+
+ public function testFind()
+ {
+ $dataset = array(
+ array(
+ 'key' => 'foobar',
+ 'value' => array(
+ 'author' => 'John Doe',
+ 'title' => 'example book',
+ ),
+ ),
+ );
+
+ $this->collection->expects($this->once())
+ ->method('findOne')
+ ->will($this->returnCallback(function($citeria, $fields) use (&$dataset) {
+ foreach ($dataset as $key => $row) {
+ if ($row['key'] === $citeria['key']) {
+ return $row;
+ }
+ }
+ }
+ ));
+
+ $data = $this->storage->find('test', 'foobar');
+
+ $this->assertEquals($dataset[0]['value'], $data);
+ }
+
+ public function testGetName()
+ {
+ $this->storage->initialize();
+
+ $this->assertEquals('mongodb', $this->storage->getName());
+ }
+}