' . t('MongoDB implements a generic MongoDB interface.',
array(
'!project' => 'http://drupal.org/project/mongodb',
'!mongo' => 'http://www.mongodb.org/',
));
break;
}
}
/**
* Returns an MongoDB object.
*/
function mongodb($alias = 'default') {
static $mongo_objects;
$connections = variable_get('mongodb_connections', array());
$connections += array('default' => array('host' => 'localhost', 'db' => 'drupal'));
if (!isset($connections[$alias])) {
$alias = 'default';
}
$connection = $connections[$alias];
$host = $connection['host'];
$db = $connection['db'];
if (!isset($mongo_objects[$host][$db])) {
$mongo = new Mongo($host);
$mongo_objects[$host][$db] = $mongo->selectDB($db);
$mongo_objects[$host][$db]->connection = $mongo;
}
return $mongo_objects[$host][$db];
}
/**
* Returns a MongoCollection object.
*/
function mongodb_collection() {
$args = array_filter(func_get_args());
if (is_array($args[0])) {
list($collection_name, $prefixed) = $args[0];
$prefixed .= $collection_name;
}
else {
// Avoid something. collection names if NULLs are passed in.
$collection_name = implode('.', array_filter($args));
$prefixed = mongodb_collection_name($collection_name);
}
$collections = variable_get('mongodb_collections', array());
$alias = isset($collections[$collection_name]) ? $collections[$collection_name] : 'default';
// Prefix the collection name for simpletest. It will be in the same DB as the
// non-prefixed version so it's enough to prefix after choosing the mongodb
// object.
$mongodb_object = mongodb($alias);
$collection = $mongodb_object->selectCollection(mongodb_collection_name($collection_name));
$collection->connection = $mongodb_object->connection;
return variable_get('mongodb_debug', FALSE) ? new mongoDebugCollection($collection) : $collection;
}
class mongoDebugCollection {
function __construct($collection) {
$this->collection = $collection;
}
function find($query = array(), $fields = array()) {
debug('find');
debug($query);
debug($fields);
return mongoDebugCursor($this->collection->find($query, $fields));
}
function __call($name, $arguments) {
debug($name);
debug($arguments);
return call_user_func_array(array($this->collection, $name), $arguments);
}
}
class mongoDebugCursor {
function __construct($collection) {
$this->collection = $collection;
}
function __call($name, $arguments) {
debug($name);
debug($arguments);
return call_user_func_array(array($this->collection, $name), $arguments);
}
}
/**
* Returns the name to use for the collection, which works with prefixes and simpletest.
*/
function mongodb_collection_name($name) {
global $db_prefix;
static $simpletest_prefix;
// We call this function earlier than the database is initalized so we would
// read the parent collection without this.
if (!isset($simpletest_prefix)) {
if (isset($_SERVER['HTTP_USER_AGENT']) && preg_match("/^(simpletest\d+);/", $_SERVER['HTTP_USER_AGENT'], $matches)) {
$simpletest_prefix = $matches[1];
}
else {
$simpletest_prefix = '';
}
}
// However, once the test information is initialized, simpletest_prefix
// is no longer needed.
if (!empty($GLOBALS['drupal_test_info']['test_run_id'])) {
$simpletest_prefix = $GLOBALS['drupal_test_info']['test_run_id'];
}
return $simpletest_prefix . $name;
}
function mongodb_test_group_finished() {
$aliases = variable_get('mongodb_connections', array());
$aliases['default'] = TRUE;
foreach (array_keys($aliases) as $alias) {
$db = mongodb($alias);
foreach ($db->listCollections() as $collection) {
if (preg_match('/\.simpletest\d+/', $collection)) {
$db->dropCollection($collection);
}
}
}
}
/**
* Allow for the database connection we are using to be changed.
*
* @param $alias
* String the alias that we want to change the connection for.
* @param $connection_name
* String the name of the connection we will use.
*/
function mongodb_set_active_connection($alias, $connection_name = 'default') {
// No need to check if the connection is valid as mongodb() does this.
$GLOBALS['conf']['mongodb_collections'][$alias] = $connection_name;
}
/**
* Return the next id in a sequence.
*/
function mongodb_next_id($name, $existing_id = 0) {
// Atomitcaly get the next id in the sequence.
$mongo = mongodb();
$cmd = array(
'findandmodify' => mongodb_collection_name('sequence'),
'query' => array('_id' => $name),
'update' => array('$inc' => array('value' => 1)),
'new' => TRUE,
);
// It's very likely that this is not necessary as command returns an array
// not an exception. The increment will, however, will fix the problem of
// the sequence not existing. Still, better safe than sorry.
try {
$sequence = $mongo->command($cmd);
$value = isset($sequence['value']['value']) ? $sequence['value']['value'] : 0;
}
catch (Exception $e) {
}
if (0 < $existing_id - $value + 1) {
$cmd = array(
'findandmodify' => mongodb_collection_name('sequence'),
'query' => array('_id' => $name),
'update' => array('$inc' => array('value' => $existing_id - $value + 1)),
'upsert' => TRUE,
'new' => TRUE,
);
$sequence = $mongo->command($cmd);
$value = isset($sequence['value']['value']) ? $sequence['value']['value'] : 0;
}
return $value;
}