Skip to content

Commit

Permalink
Add mongodb storage
Browse files Browse the repository at this point in the history
  • Loading branch information
Baachi committed May 11, 2012
1 parent 4fe8657 commit b88ed9e
Show file tree
Hide file tree
Showing 2 changed files with 320 additions and 0 deletions.
180 changes: 180 additions & 0 deletions lib/Doctrine/KeyValueStore/Storage/MongoDbStorage.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
<?php

namespace Doctrine\KeyValueStore\Storage;

/**
* 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']);
}

/**
* Determine if the storage supports updating only a subset of properties,
* or if all properties have to be set, even if only a subset of properties
* changed.
*
* @return bool
*/
public function supportsPartialUpdates()
{
return false;
}

/**
* Does this storage support composite primary keys?
*
* @return bool
*/
public function supportsCompositePrimaryKeys()
{
return false;
}

/**
* Does this storage require composite primary keys?
*
* @return bool
*/
public function requiresCompositePrimaryKeys()
{
return false;
}

/**
* Insert data into the storage key specified.
*
* @param string $storageName
* @param array|string $key
* @param array $data
* @return void
*/
public function insert($storageName, $key, array $data)
{
$this->initialize();

$value = array(
'key' => $key,
'value' => $data,
);

$this->collection->insert($value);
}

/**
* Update data into the given key.
*
* @param string $storageName
* @param array|string $key
* @param array $data
* @return void
*/
public function update($storageName, $key, array $data)
{
$this->initialize();

$value = array(
'key' => $key,
'value' => $data,
);

$this->collection->update(array('key' => $key), $value);
}

/**
* Delete data at key
*
* @param string $storageName
* @param array|string $key
* @return void
*/
public function delete($storageName, $key)
{
$this->initialize();

$this->collection->remove(array('key' => $key));
}

/**
* Find data at key
*
* Important note: The returned array does contain the identifier (again)!
*
* @param string $storageName
* @param array|string $key
* @return array
*/
public function find($storageName, $key)
{
$this->initialize();

$value = $this->collection->findOne(array('key' => $key), array('value'));

if ($value) {
return $value['value'];
}

return array();
}

/**
* Return a name of the underlying storage.
*
* @return string
*/
public function getName()
{
return 'mongodb';
}
}
140 changes: 140 additions & 0 deletions tests/Doctrine/Tests/KeyValueStore/Storage/MongoDbStorageTest.php
Original file line number Diff line number Diff line change
@@ -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());
}
}

0 comments on commit b88ed9e

Please sign in to comment.