2017-05-22 21:20:20 +00:00
|
|
|
<?php
|
|
|
|
namespace devilbox;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @requires devilbox::Logger
|
|
|
|
*/
|
|
|
|
class Mongo extends BaseClass implements BaseInterface
|
|
|
|
{
|
|
|
|
/*********************************************************************************
|
|
|
|
*
|
|
|
|
* Private Variables
|
|
|
|
*
|
|
|
|
*********************************************************************************/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* MongoDB manager instance
|
|
|
|
* @var object|null
|
|
|
|
*/
|
|
|
|
private $_mongo = null;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*********************************************************************************
|
|
|
|
*
|
|
|
|
* Constructor Overwrite
|
|
|
|
*
|
|
|
|
*********************************************************************************/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Use singleton getInstance() instead.
|
|
|
|
*
|
|
|
|
* @param string $user Username
|
|
|
|
* @param string $pass Password
|
|
|
|
* @param string $host Host
|
|
|
|
*/
|
|
|
|
public function __construct($hostname, $data = array())
|
|
|
|
{
|
|
|
|
parent::__construct($hostname, $data);
|
|
|
|
|
|
|
|
|
|
|
|
// Faster check if mongo is not loaded
|
|
|
|
if (!$this->isAvailable()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
$mongo = new \MongoDB\Driver\Manager('mongodb://'.$hostname);
|
|
|
|
|
|
|
|
// MongoDB uses lazy loading of server list
|
|
|
|
// so just execute an arbitrary command in order
|
|
|
|
// to make it populate the server list
|
|
|
|
$command = new \MongoDB\Driver\Command(array('ping' => 1));
|
|
|
|
|
|
|
|
try {
|
|
|
|
$mongo->executeCommand('admin', $command);
|
|
|
|
} catch (\MongoDB\Driver\Exception\ConnectionTimeoutException $e) {
|
|
|
|
$this->_connect_error = $e;
|
|
|
|
$this->_connect_errno = 1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// retrieve server list
|
|
|
|
$servers = $mongo->getServers();
|
|
|
|
|
|
|
|
if (!isset($servers[0])) {
|
|
|
|
$this->_connect_error = 'Failed to connect to MongoDB host on '.$hostname.' (No host info available)';
|
|
|
|
$this->_connect_errno = 2;
|
|
|
|
return;
|
|
|
|
} else if ($servers[0]->getHost() != $hostname) {
|
|
|
|
$this->_connect_error = 'Failed to connect to MongoDB host on '.$hostname.' (servername does not match: '.$servers[0]->getHost().')';
|
|
|
|
$this->_connect_errno = 3;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
$this->_mongo = $mongo;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*********************************************************************************
|
|
|
|
*
|
|
|
|
* Select functions
|
|
|
|
*
|
|
|
|
*********************************************************************************/
|
|
|
|
|
|
|
|
|
2017-05-23 07:01:50 +00:00
|
|
|
/**
|
|
|
|
* Execute MongoDB command and return iteratable
|
|
|
|
* @param array $command Command
|
|
|
|
* @return iteratable
|
|
|
|
*/
|
2017-05-22 21:20:20 +00:00
|
|
|
private function command($command)
|
|
|
|
{
|
|
|
|
if ($this->_mongo) {
|
|
|
|
try {
|
2018-12-15 16:03:45 +00:00
|
|
|
$cmd = new \MongoDB\Driver\Command($command);
|
2017-05-22 21:20:20 +00:00
|
|
|
$cursor = $this->_mongo->executeCommand('admin', $cmd);
|
|
|
|
return $cursor->toArray();
|
|
|
|
} catch(\MongoDB\Driver\Exception $e) {
|
|
|
|
loadClass('Logger')->error($e->getMessage().'. Could not execute MongoDB command: '.print_r($command, true));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return array();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get all MongoDB Databases.
|
|
|
|
* @return mixed[] Array of databases
|
|
|
|
*/
|
|
|
|
public function getDatabases()
|
|
|
|
{
|
|
|
|
$databases = array();
|
|
|
|
$tmp = $this->command(array('listDatabases' => true));
|
|
|
|
if (isset($tmp[0])) {
|
2018-05-12 14:01:31 +00:00
|
|
|
if (is_array($tmp[0])) {
|
|
|
|
foreach ($tmp[0]['databases'] as $db) {
|
|
|
|
$databases[] = array(
|
|
|
|
'name' => $db->name,
|
|
|
|
'size' => $db->sizeOnDisk,
|
|
|
|
'empty' => $db->empty
|
|
|
|
);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
foreach ($tmp[0]->databases as $db) {
|
|
|
|
$databases[] = array(
|
|
|
|
'name' => $db->name,
|
|
|
|
'size' => $db->sizeOnDisk,
|
|
|
|
'empty' => $db->empty
|
|
|
|
);
|
|
|
|
}
|
2017-05-22 21:20:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return $databases;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public function getInfo()
|
|
|
|
{
|
|
|
|
$info = array();
|
|
|
|
$tmp = $this->command(array('serverStatus' => true));
|
|
|
|
|
|
|
|
if (isset($tmp[0])) {
|
|
|
|
$info = $tmp[0];
|
|
|
|
}
|
|
|
|
return $info;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*********************************************************************************
|
|
|
|
*
|
|
|
|
* Interface required functions
|
|
|
|
*
|
|
|
|
*********************************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
private $_can_connect = array();
|
|
|
|
private $_can_connect_err = array();
|
|
|
|
|
|
|
|
private $_name = null;
|
|
|
|
private $_version = null;
|
|
|
|
|
|
|
|
public function canConnect(&$err, $hostname, $data = array())
|
|
|
|
{
|
|
|
|
$err = false;
|
|
|
|
|
|
|
|
// Return if already cached
|
|
|
|
if (isset($this->_can_connect[$hostname])) {
|
|
|
|
// Assume error for unset error message
|
|
|
|
$err = isset($this->_can_connect_err[$hostname]) ? $this->_can_connect_err[$hostname] : true;
|
|
|
|
return $this->_can_connect[$hostname];
|
|
|
|
}
|
|
|
|
|
|
|
|
$manager = new \MongoDB\Driver\Manager('mongodb://'.$hostname);
|
|
|
|
|
|
|
|
// MongoDB uses lazy loading of server list
|
|
|
|
// so just execute an arbitrary command in order
|
|
|
|
// to make it populate the server list
|
|
|
|
$command = new \MongoDB\Driver\Command(array('ping' => 1));
|
|
|
|
$manager->executeCommand('admin', $command);
|
|
|
|
|
|
|
|
// retrieve server list
|
|
|
|
$servers = $manager->getServers();
|
|
|
|
|
|
|
|
if (!isset($servers[0])) {
|
|
|
|
$err = 'Failed to connect to MongoDB host on '.$hostname.' (No host info available)';
|
|
|
|
$this->_can_connect[$hostname] = false;
|
|
|
|
} else if ($servers[0]->getHost() != $hostname) {
|
|
|
|
$err = 'Failed to connect to MongoDB host on '.$hostname.' (servername does not match: '.$servers[0]->getHost().')';
|
|
|
|
$this->_can_connect[$hostname] = false;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
$this->_can_connect[$hostname] = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->_can_connect_err[$hostname] = $err;
|
|
|
|
return $this->_can_connect[$hostname];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public function getName($default = 'MongoDB')
|
|
|
|
{
|
|
|
|
return $default;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getVersion()
|
|
|
|
{
|
|
|
|
// Return if already cached
|
|
|
|
if ($this->_version !== null) {
|
|
|
|
return $this->_version;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Return empty if not available
|
|
|
|
if (!$this->isAvailable()) {
|
|
|
|
$this->_version = '';
|
|
|
|
return $this->_version;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($this->_mongo) {
|
|
|
|
$info = $this->getInfo();
|
|
|
|
if (!isset($info->version)) {
|
|
|
|
loadClass('Logger')->error('Could not get MongoDB version');
|
|
|
|
$this->_version = '';
|
|
|
|
} else {
|
|
|
|
$this->_version = $info->version;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return $this->_version;
|
|
|
|
}
|
|
|
|
}
|