*/ class Mooses_Mongodb_Mongo { protected static $_connectionGroups = array(); protected static $_requirements = array(); protected static $_requirementCreators = array(); protected static $_validOperations = array('$set', '$unset', '$push', '$pushAll', '$pull', '$pullAll', '$addToSet', '$pop', '$inc'); protected static $_initialised = false; /** * Initialise Mooses_Mongodb_Mongo. In particular all the requirements. */ public static function init() { // If requirements are not empty then we have already initialised requirements if (static::$_initialised) return; // Custom validators static::storeRequirement('Validator:Array', new Mooses_Mongodb_Mongo_Validate_Array()); static::storeRequirement('Validator:MongoId', new Mooses_Mongodb_Mongo_Validate_Class('MongoId')); static::storeRequirement('Validator:MongoDate', new Mooses_Mongodb_Mongo_Validate_Class('MongoDate')); static::storeRequirement('Document', new Mooses_Mongodb_Mongo_Validate_Class('Mooses_Mongodb_Mongo_Document')); static::storeRequirement('DocumentSet', new Mooses_Mongodb_Mongo_Validate_Class('Mooses_Mongodb_Mongo_DocumentSet')); // Stubs static::storeRequirement('Required', new Mooses_Mongodb_Mongo_Validate_StubTrue()); static::storeRequirement('AsReference', new Mooses_Mongodb_Mongo_Validate_StubTrue()); static::storeRequirement('Ignore', new Mooses_Mongodb_Mongo_Validate_StubTrue()); // Requirement creator for validators static::storeRequirementCreator('/^Validator:([A-Za-z]+[\w\-:]*)$/', function($data, $options = null) { $instanceClass = $data[1]; if (!class_exists($instanceClass)) { $instanceClass = 'Zend_Validate_' . $instanceClass; if (!class_exists($instanceClass)) { return null; } } if (!is_null($options)) $validator = new $instanceClass($options); else $validator = new $instanceClass(); if (!($validator instanceof Zend_Validate_Interface)) return null; return $validator; }); // Requirement creator for filters static::storeRequirementCreator('/^Filter:([A-Za-z]+[\w\-:]*)$/', function($data, $options = null) { $instanceClass = $data[1]; if (!class_exists($instanceClass)) { $instanceClass = 'Zend_Filter_' . $instanceClass; if (!class_exists($instanceClass)) { return null; } } if (!is_null($options)) $validator = new $instanceClass($options); else $validator = new $instanceClass(); if (!($validator instanceof Zend_Filter_Interface)) return null; return $validator; }); // Creates requirements to match classes $classValidator = function($data) { if (!class_exists($data[1])) return null; return new Mooses_Mongodb_Mongo_Validate_Class($data[1]); }; static::storeRequirementCreator('/^Document:([A-Za-z]+[\w\-]*)$/', $classValidator); static::storeRequirementCreator('/^DocumentSet:([A-Za-z]+[\w\-]*)$/', $classValidator); static::$_initialised = true; } /** * Add connections Thinkopen Mongo * * @param array $options */ public static function addConnections($options) { if ($options instanceof Zend_Config) { $options = $options->toArray(); } $blurbs = array('host', 'master', 'masters', 'slaves', 'slave', 'hosts'); $intersection = array_intersect(array_keys($options), $blurbs); $connectionGroups = array(); if (!empty($intersection)) $connectionGroups['default'] = $options; else $connectionGroups = $options; foreach ($connectionGroups as $connectionGroupName => $connectionGroupOptions) { static::getConnectionGroup($connectionGroupName)->addConnections($connectionGroupOptions); } } /** * Get the requirement matching the name provided * * @param $name String Name of requirement * @return mixed * */ public static function retrieveRequirement($name, $options = null) { // Requirement is already initialised return it if (isset(static::$_requirements[$name])) { // If requirement does not have options, returned cached instance if (!$options) return static::$_requirements[$name]; $requirementClass = get_class(static::$_requirements[$name]); return new $requirementClass($options); } // Attempt to create requirement if (!$requirement = static::createRequirement($name, $options)) { require_once 'Thinkopen/MongodbMongo/Exception.php'; throw new Mooses_Mongodb_Mongo_Exception("No requirement exists for '{$name}'"); } // Requirement found. Store it for later use if (!is_null($options)) { static::storeRequirement($name, $requirement); } return $requirement; } /** * Add requirements to use in validation of document properties * * @param $name String Name of requirement * @param $requirement mixed * */ public static function storeRequirement($name, $requirement) { // Ensure $name is a string $name = (string) $name; static::$_requirements[$name] = $requirement; } /** * Add a creator of requirements * * @param String Regex to match this requirement producer * @param Closure Function to create requirement * */ public static function storeRequirementCreator($regex, Closure $function) { static::$_requirementCreators[$regex] = $function; } /** * Create a requirement * * @param $name String Name of requirement * @return mixed * */ public static function createRequirement($name, $options = null) { // Match requirement name against regex's $requirements = array_reverse(static::$_requirementCreators); foreach ($requirements as $regex => $function) { $matches = array(); preg_match($regex, $name, $matches); if (!empty($matches)) { return $function($matches, $options); } } return null; } /** * Remove all requirements */ public static function removeRequirements() { static::$_requirements = array(); } /** * Remove all requirement creators */ public static function removeRequirementCreators() { static::$_requirementCreators = array(); } /** * Deterimine if an operation is valid * * @param string $operation */ public static function isValidOperation($operation) { return in_array($operation, static::$_validOperations); } /** * Determine if a connection group exists * * @param string $name The name of the connection group */ public static function hasConnectionGroup($name) { return array_key_exists($name, static::$_connectionGroups); } /** * Set a connection group * * @param string $name * @param Mooses_Mongodb_Mongo_Connection_Group $connectionGroup */ public static function setConnectionGroup($name, Mooses_Mongodb_Mongo_Connection_Group $connectionGroup) { static::$_connectionGroups[$name] = $connectionGroup; } /** * Get a connection group. If it doesn't already exist, create it * * @param string $name The name of the connection group * @return Mooses_Mongodb_Mongo_Connection_Group */ public static function getConnectionGroup($name) { if (!static::hasConnectionGroup($name)) { static::setConnectionGroup($name, new Mooses_Mongodb_Mongo_Connection_Group()); } return static::$_connectionGroups[$name]; } /** * Get a list of all connection groups * * @return array */ public static function getConnectionGroups() { return static::$_connectionGroups; } /** * Remove all connection groups */ public static function removeConnectionGroups() { static::$_connectionGroups = array(); } /** * Add a connection to a master server * * @param Mooses_Mongodb_Mongo_Connection $connection * @param int $weight */ public static function addMaster(Mooses_Mongodb_Mongo_Connection $connection, $weight = 1, $connectionGroup = 'default') { static::getConnectionGroup($connectionGroup)->addMaster($connection, $weight); } /** * Add a connection to a slaver server * * @param $connection * @param $weight */ public static function addSlave(Mooses_Mongodb_Mongo_Connection $connection, $weight = 1, $connectionGroup = 'default') { static::getConnectionGroup($connectionGroup)->addSlave($connection, $weight); } /** * Get a write connection * * @param string $connectionGroupName The connection group name * @return Mooses_Mongodb_Mongo_Connection */ public static function getWriteConnection($connectionGroupName = 'default') { $connectionGroup = static::getConnectionGroup($connectionGroupName); if ($connectionGroupName == 'default' && count($connectionGroup->getMasters()) === 0) { // Add a connection to localhost if no connections currently exist for the default connection group $_iniConfig = Top::getConfig(); if(strlen($_iniConfig->mongodb->host) > 0){ $_connectionHost = $_iniConfig->mongodb->host; } else { $_connectionHost = "127.0.0.1"; } $connectionGroup->addMaster(new Mooses_Mongodb_Mongo_Connection($_connectionHost)); } if (!$connection = $connectionGroup->getWriteConnection($connectionGroupName)) { require_once 'Thinkopen/MongodbMongo/Exception.php'; throw new Mooses_Mongodb_Mongo_Exception("No write connection available for the '{$connectionGroupName}' connection group"); } return $connection; } /** * Get a read connection * * @param string $connectionGroupName The connection group name * @return Mooses_Mongodb_Mongo_Connection */ public static function getReadConnection($connectionGroupName = 'default') { $connectionGroup = static::getConnectionGroup($connectionGroupName); if ($connectionGroupName == 'default' && count($connectionGroup->getSlaves()) === 0 && count($connectionGroup->getMasters()) === 0) { // Add a connection to localhost if no connections currently exist for the default connection group $_iniConfig = Top::getConfig(); if(strlen($_iniConfig->mongodb->host) > 0){ $_connectionHost = $_iniConfig->mongodb->host; } else { $_connectionHost = "127.0.0.1"; } $connectionGroup->addMaster(new Mooses_Mongodb_Mongo_Connection($_connectionHost)); } if (!$connection = $connectionGroup->getReadConnection($connectionGroupName)) { require_once 'Thinkopen/MongodbMongo/Exception.php'; throw new Mooses_Mongodb_Mongo_Exception("No read connection available for the '{$connectionGroupName}' connection group"); } return $connection; } /** * Return Mooses_Mongodb_Mongo to pre-init status */ public static function makeClean() { static::removeConnectionGroups(); static::removeRequirements(); static::removeRequirementCreators(); static::$_initialised = false; } } Mooses_Mongodb_Mongo::init();