Skip to content

Commit

Permalink
[mms] Added a NoSQL (MongoDB) driver for the storage backend.
Browse files Browse the repository at this point in the history
  • Loading branch information
slusarz committed Feb 25, 2015
1 parent d16edf0 commit 8d5592f
Show file tree
Hide file tree
Showing 7 changed files with 259 additions and 5 deletions.
5 changes: 5 additions & 0 deletions ingo/config/conf.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@
<configheader>Rules Storage</configheader>
<configswitch name="driver" desc="What storage driver should we use?">sql
<case name="prefs" desc="Preference System"/>
<case name="nosql" desc="NoSQL">
<configsection name="params">
<confignosql swicthname="driverconfig"/>
</configsection>
</case>
<case name="sql" desc="SQL">
<configsection name="params">
<configsql switchname="driverconfig"/>
Expand Down
1 change: 1 addition & 0 deletions ingo/docs/CHANGES
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
v3.3.0-git
----------

[mms] Added a NoSQL (MongoDB) driver for the storage backend.
[mms] Rule code has been separated from the storage backend drivers.
[jan] Use Horde\ManageSieve instead of Net_Sieve.
[mms] Rearrange the default order of filter rules.
Expand Down
10 changes: 10 additions & 0 deletions ingo/docs/UPGRADING
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,16 @@ Administration => Configuration and update anything that's highlighted as
outdated.


Upgrading Ingo From 3.x To 4.0
==============================

Configuration Options (conf.php)
--------------------------------

Added a NoSQL (MongoDB) driver for the storage backend.



Upgrading Ingo From 3.1.x To 3.2
================================

Expand Down
15 changes: 15 additions & 0 deletions ingo/lib/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -383,4 +383,19 @@ protected function _listRulesets()
return $this->_rulesets;
}

/* NoSQL methods. */

/**
*/
public function nosqlDrivers()
{
global $injector;

$storage = $injector->getInstance('Ingo_Factory_Storage')->create();

return ($storage instanceof Ingo_Storage_Mongo)
? array($storage)
: array();
}

}
20 changes: 17 additions & 3 deletions ingo/lib/Factory/Storage.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,10 @@ class Ingo_Factory_Storage extends Horde_Core_Factory_Base
*/
public function create($driver = null, $params = null)
{
global $conf, $injector;

if (is_null($driver)) {
$driver = $GLOBALS['conf']['storage']['driver'];
$driver = $conf['storage']['driver'];
}
$driver = ucfirst(basename($driver));

Expand All @@ -53,8 +55,17 @@ public function create($driver = null, $params = null)
}

switch ($driver) {
case 'Nosql':
$nosql = $injector->getInstance('Horde_Core_Factory_Nosql')
->create('ingo', 'storage');
if ($nosql instanceof Horde_Mongo_Client) {
$params['mongo_db'] = $nosql;
$driver = 'Mongo';
}
break;

case 'Sql':
$params['db'] = $GLOBALS['injector']->getInstance('Horde_Db_Adapter');
$params['db'] = $injector->getInstance('Horde_Db_Adapter');
$params['table_forwards'] = 'ingo_forwards';
$params['table_lists'] = 'ingo_lists';
$params['table_rules'] = 'ingo_rules';
Expand All @@ -67,7 +78,10 @@ public function create($driver = null, $params = null)
if (class_exists($class)) {
$this->_instances[$driver] = new $class($params);
} else {
throw new Ingo_Exception(sprintf(_("Unable to load the storage driver \"%s\"."), $class));
throw new Ingo_Exception(sprintf(
_("Unable to load the storage driver \"%s\"."),
$class
));
}
}

Expand Down
205 changes: 205 additions & 0 deletions ingo/lib/Storage/Mongo.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
<?php
/**
* Copyright 2015 Horde LLC (http://www.horde.org/)
*
* See the enclosed file LICENSE for license information (ASL). If you
* did not receive this file, see http://www.horde.org/licenses/apache.
*
* @category Horde
* @copyright 2015 Horde LLC
* @license http://www.horde.org/licenses/apache ASL
* @package Ingo
*/

/**
* Ingo_Storage API implementation to save Ingo data via a MongoDB database.
*
* @author Michael Slusarz <slusarz@horde.org>
* @category Horde
* @copyright 2015 Horde LLC
* @license http://www.horde.org/licenses/apache ASL
* @package Ingo
*/
class Ingo_Storage_Mongo
extends Ingo_Storage
implements Horde_Mongo_Collection_Index
{
/* Field names. */
const MONGO_ID = '_id';
const DATA = 'data';
const ORDER = 'order';
const WHO = 'who';

/**
* Indices list.
*
* @var array
*/
protected $_indices = array(
'index_who' => array(
self::WHO => 1
)
);

/**
* @param array $params Parameters:
* - collection: (string) The name of the storage collection.
* - mongo_db: (Horde_Mongo_Client) [REQUIRED] The DB instance.
*/
public function __construct(array $params = array())
{
if (!isset($params['mongo_db'])) {
throw new InvalidArgumentException('Missing mongo_db parameter.');
}

parent::__construct(array_merge(array(
'collection' => 'ingo_storage'
), $params));

$this->_params['db'] = $this->_params['mongo_db']
->selectCollection(null, $this->_params['collection']);
}

/**
*/
protected function _loadFromBackend()
{
try {
$res = $this->_params['db']->aggregate(array(
/* Match the query. */
array(
'$match' => array(
self::WHO => Ingo::getUser()
)
),

/* Sort the rows. */
array(
'$sort' => array(self::ORDER => 1)
)
));

if (isset($res['result'])) {
foreach ($res['result'] as $val) {
if ($ob = @unserialize($val[self::DATA])) {
$ob->uid = strval($val[self::MONGO_ID]);
$this->_rules[] = $ob;
}
}
}
} catch (MongoException $e) {}
}

/**
*/
protected function _removeUserData($user)
{
try {
$this->_params['db']->remove(array(
self::WHO => Ingo::getUser()
));
} catch (MongoException $e) {}
}

/**
*/
protected function _storeBackend($action, $rule)
{
$user = Ingo::getUser();

switch ($action) {
case self::STORE_ADD:
try {
$res = $this->_params['db']->aggregate(array(
array(
'$match' => array(
self::WHO => $user
)
),
array(
'$group' => array(
self::MONGO_ID => '',
'max' => array('$max' => '$' . self::ORDER)
)
)
));

if (isset($res['result'])) {
$res = current($res['result']);
$max = ++$res['max'];
} else {
$max = 0;
}

$this->_params['db']->insert(array(
self::DATA => serialize($rule),
self::ORDER => $max,
self::WHO => $user
));
} catch (MongoException $e) {
throw new Ingo_Exception($e);
}
break;

case self::STORE_DELETE:
try {
$this->_params['db']->remove(array(
self::MONGO_ID => new MongoId($rule->uid),
self::WHO => $user
));
} catch (MongoException $e) {}
break;

case self::STORE_SORT:
try {
foreach ($this->_rules as $key => $val) {
$this->_params['db']->update(array(
self::MONGO_ID => new MongoId($val->uid),
self::WHO => $user
), array(
'$set' => array(
self::ORDER => $key
)
));
}
} catch (MongoException $e) {}
break;

case self::STORE_UPDATE:
try {
$this->_params['db']->update(array(
self::MONGO_ID => new MongoId($rule->uid),
self::WHO => $user
), array(
'$set' => array(
self::DATA => serialize($rule)
)
));
} catch (MongoException $e) {}
break;
}
}

/* Horde_Mongo_Collection_Index methods. */

/**
*/
public function checkMongoIndices()
{
return $this->_params['mongo_db']->checkIndices(
$this->_params['db'],
$this->_indices
);
}

/**
*/
public function createMongoIndices()
{
$this->_params['mongo_db']->createIndices(
$this->_params['db'],
$this->_indices
);
}

}
8 changes: 6 additions & 2 deletions ingo/package.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<email>chuck@horde.org</email>
<active>no</active>
</lead>
<date>2015-02-24</date>
<date>2015-02-25</date>
<version>
<release>3.3.0</release>
<api>3.2.0</api>
Expand All @@ -33,6 +33,7 @@
</stability>
<license uri="http://www.horde.org/licenses/apache">ASL</license>
<notes>
* [mms] Added a NoSQL (MongoDB) driver for the storage backend.
* [mms] Rule code has been separated from the storage backend drivers.
* [jan] Use Horde\ManageSieve instead of Net_Sieve.
* [mms] Rearrange the default order of filter rules.
Expand Down Expand Up @@ -215,6 +216,7 @@
</dir> <!-- /lib/Storage/FilterIterator -->
<file name="FilterIterator.php" role="horde" />
<file name="Memory.php" role="horde" />
<file name="Mongo.php" role="horde" />
<file name="Prefs.php" role="horde" />
<file name="Sql.php" role="horde" />
</dir> <!-- /lib/Storage -->
Expand Down Expand Up @@ -796,6 +798,7 @@
<install as="ingo/lib/Script/Sieve/Test/True.php" name="lib/Script/Sieve/Test/True.php" />
<install as="ingo/lib/Storage/FilterIterator.php" name="lib/Storage/FilterIterator.php" />
<install as="ingo/lib/Storage/Memory.php" name="lib/Storage/Memory.php" />
<install as="ingo/lib/Storage/Mongo.php" name="lib/Storage/Mongo.php" />
<install as="ingo/lib/Storage/Prefs.php" name="lib/Storage/Prefs.php" />
<install as="ingo/lib/Storage/Sql.php" name="lib/Storage/Sql.php" />
<install as="ingo/lib/Storage/FilterIterator/Match.php" name="lib/Storage/FilterIterator/Match.php" />
Expand Down Expand Up @@ -1572,7 +1575,7 @@
</notes>
</release>
<release>
<date>2015-02-24</date>
<date>2015-02-25</date>
<version>
<release>3.3.0</release>
<api>3.2.0</api>
Expand All @@ -1583,6 +1586,7 @@
</stability>
<license uri="http://www.horde.org/licenses/apache">ASL</license>
<notes>
* [mms] Added a NoSQL (MongoDB) driver for the storage backend.
* [mms] Rule code has been separated from the storage backend drivers.
* [jan] Use Horde\ManageSieve instead of Net_Sieve.
* [mms] Rearrange the default order of filter rules.
Expand Down

0 comments on commit 8d5592f

Please sign in to comment.