Mongo.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  1. <?php
  2. require_once 'Thinkopen/Mongodb/Mongo/Validate/Array.php';
  3. require_once 'Thinkopen/Mongodb/Mongo/Validate/Class.php';
  4. require_once 'Thinkopen/Mongodb/Mongo/Validate/StubTrue.php';
  5. require_once 'Thinkopen/Mongodb/Mongo/Connection/Group.php';
  6. /**
  7. * @category Thinkopen
  8. * @package Mooses_Mongodb_Mongo
  9. * @license New BSD License
  10. * @author Paolo Libertini <paolo.libertini@thinkopen.it>
  11. */
  12. class Mooses_Mongodb_Mongo {
  13. protected static $_connectionGroups = array();
  14. protected static $_requirements = array();
  15. protected static $_requirementCreators = array();
  16. protected static $_validOperations = array('$set', '$unset', '$push', '$pushAll', '$pull', '$pullAll', '$addToSet', '$pop', '$inc');
  17. protected static $_initialised = false;
  18. /**
  19. * Initialise Mooses_Mongodb_Mongo. In particular all the requirements.
  20. */
  21. public static function init() {
  22. // If requirements are not empty then we have already initialised requirements
  23. if (static::$_initialised)
  24. return;
  25. // Custom validators
  26. static::storeRequirement('Validator:Array', new Mooses_Mongodb_Mongo_Validate_Array());
  27. static::storeRequirement('Validator:MongoId', new Mooses_Mongodb_Mongo_Validate_Class('MongoId'));
  28. static::storeRequirement('Validator:MongoDate', new Mooses_Mongodb_Mongo_Validate_Class('MongoDate'));
  29. static::storeRequirement('Document', new Mooses_Mongodb_Mongo_Validate_Class('Mooses_Mongodb_Mongo_Document'));
  30. static::storeRequirement('DocumentSet', new Mooses_Mongodb_Mongo_Validate_Class('Mooses_Mongodb_Mongo_DocumentSet'));
  31. // Stubs
  32. static::storeRequirement('Required', new Mooses_Mongodb_Mongo_Validate_StubTrue());
  33. static::storeRequirement('AsReference', new Mooses_Mongodb_Mongo_Validate_StubTrue());
  34. static::storeRequirement('Ignore', new Mooses_Mongodb_Mongo_Validate_StubTrue());
  35. // Requirement creator for validators
  36. static::storeRequirementCreator('/^Validator:([A-Za-z]+[\w\-:]*)$/', function($data, $options = null) {
  37. $instanceClass = $data[1];
  38. if (!class_exists($instanceClass)) {
  39. $instanceClass = 'Zend_Validate_' . $instanceClass;
  40. if (!class_exists($instanceClass)) {
  41. return null;
  42. }
  43. }
  44. if (!is_null($options))
  45. $validator = new $instanceClass($options);
  46. else
  47. $validator = new $instanceClass();
  48. if (!($validator instanceof Zend_Validate_Interface))
  49. return null;
  50. return $validator;
  51. });
  52. // Requirement creator for filters
  53. static::storeRequirementCreator('/^Filter:([A-Za-z]+[\w\-:]*)$/', function($data, $options = null) {
  54. $instanceClass = $data[1];
  55. if (!class_exists($instanceClass)) {
  56. $instanceClass = 'Zend_Filter_' . $instanceClass;
  57. if (!class_exists($instanceClass)) {
  58. return null;
  59. }
  60. }
  61. if (!is_null($options))
  62. $validator = new $instanceClass($options);
  63. else
  64. $validator = new $instanceClass();
  65. if (!($validator instanceof Zend_Filter_Interface))
  66. return null;
  67. return $validator;
  68. });
  69. // Creates requirements to match classes
  70. $classValidator = function($data) {
  71. if (!class_exists($data[1]))
  72. return null;
  73. return new Mooses_Mongodb_Mongo_Validate_Class($data[1]);
  74. };
  75. static::storeRequirementCreator('/^Document:([A-Za-z]+[\w\-]*)$/', $classValidator);
  76. static::storeRequirementCreator('/^DocumentSet:([A-Za-z]+[\w\-]*)$/', $classValidator);
  77. static::$_initialised = true;
  78. }
  79. /**
  80. * Add connections Thinkopen Mongo
  81. *
  82. * @param array $options
  83. */
  84. public static function addConnections($options) {
  85. if ($options instanceof Zend_Config) {
  86. $options = $options->toArray();
  87. }
  88. $blurbs = array('host', 'master', 'masters', 'slaves', 'slave', 'hosts');
  89. $intersection = array_intersect(array_keys($options), $blurbs);
  90. $connectionGroups = array();
  91. if (!empty($intersection))
  92. $connectionGroups['default'] = $options;
  93. else
  94. $connectionGroups = $options;
  95. foreach ($connectionGroups as $connectionGroupName => $connectionGroupOptions) {
  96. static::getConnectionGroup($connectionGroupName)->addConnections($connectionGroupOptions);
  97. }
  98. }
  99. /**
  100. * Get the requirement matching the name provided
  101. *
  102. * @param $name String Name of requirement
  103. * @return mixed
  104. * */
  105. public static function retrieveRequirement($name, $options = null) {
  106. // Requirement is already initialised return it
  107. if (isset(static::$_requirements[$name])) {
  108. // If requirement does not have options, returned cached instance
  109. if (!$options)
  110. return static::$_requirements[$name];
  111. $requirementClass = get_class(static::$_requirements[$name]);
  112. return new $requirementClass($options);
  113. }
  114. // Attempt to create requirement
  115. if (!$requirement = static::createRequirement($name, $options)) {
  116. require_once 'Thinkopen/MongodbMongo/Exception.php';
  117. throw new Mooses_Mongodb_Mongo_Exception("No requirement exists for '{$name}'");
  118. }
  119. // Requirement found. Store it for later use
  120. if (!is_null($options)) {
  121. static::storeRequirement($name, $requirement);
  122. }
  123. return $requirement;
  124. }
  125. /**
  126. * Add requirements to use in validation of document properties
  127. *
  128. * @param $name String Name of requirement
  129. * @param $requirement mixed
  130. * */
  131. public static function storeRequirement($name, $requirement) {
  132. // Ensure $name is a string
  133. $name = (string) $name;
  134. static::$_requirements[$name] = $requirement;
  135. }
  136. /**
  137. * Add a creator of requirements
  138. *
  139. * @param String Regex to match this requirement producer
  140. * @param Closure Function to create requirement
  141. * */
  142. public static function storeRequirementCreator($regex, Closure $function) {
  143. static::$_requirementCreators[$regex] = $function;
  144. }
  145. /**
  146. * Create a requirement
  147. *
  148. * @param $name String Name of requirement
  149. * @return mixed
  150. * */
  151. public static function createRequirement($name, $options = null) {
  152. // Match requirement name against regex's
  153. $requirements = array_reverse(static::$_requirementCreators);
  154. foreach ($requirements as $regex => $function) {
  155. $matches = array();
  156. preg_match($regex, $name, $matches);
  157. if (!empty($matches)) {
  158. return $function($matches, $options);
  159. }
  160. }
  161. return null;
  162. }
  163. /**
  164. * Remove all requirements
  165. */
  166. public static function removeRequirements() {
  167. static::$_requirements = array();
  168. }
  169. /**
  170. * Remove all requirement creators
  171. */
  172. public static function removeRequirementCreators() {
  173. static::$_requirementCreators = array();
  174. }
  175. /**
  176. * Deterimine if an operation is valid
  177. *
  178. * @param string $operation
  179. */
  180. public static function isValidOperation($operation) {
  181. return in_array($operation, static::$_validOperations);
  182. }
  183. /**
  184. * Determine if a connection group exists
  185. *
  186. * @param string $name The name of the connection group
  187. */
  188. public static function hasConnectionGroup($name) {
  189. return array_key_exists($name, static::$_connectionGroups);
  190. }
  191. /**
  192. * Set a connection group
  193. *
  194. * @param string $name
  195. * @param Mooses_Mongodb_Mongo_Connection_Group $connectionGroup
  196. */
  197. public static function setConnectionGroup($name, Mooses_Mongodb_Mongo_Connection_Group $connectionGroup) {
  198. static::$_connectionGroups[$name] = $connectionGroup;
  199. }
  200. /**
  201. * Get a connection group. If it doesn't already exist, create it
  202. *
  203. * @param string $name The name of the connection group
  204. * @return Mooses_Mongodb_Mongo_Connection_Group
  205. */
  206. public static function getConnectionGroup($name) {
  207. if (!static::hasConnectionGroup($name)) {
  208. static::setConnectionGroup($name, new Mooses_Mongodb_Mongo_Connection_Group());
  209. }
  210. return static::$_connectionGroups[$name];
  211. }
  212. /**
  213. * Get a list of all connection groups
  214. *
  215. * @return array
  216. */
  217. public static function getConnectionGroups() {
  218. return static::$_connectionGroups;
  219. }
  220. /**
  221. * Remove all connection groups
  222. */
  223. public static function removeConnectionGroups() {
  224. static::$_connectionGroups = array();
  225. }
  226. /**
  227. * Add a connection to a master server
  228. *
  229. * @param Mooses_Mongodb_Mongo_Connection $connection
  230. * @param int $weight
  231. */
  232. public static function addMaster(Mooses_Mongodb_Mongo_Connection $connection, $weight = 1, $connectionGroup = 'default') {
  233. static::getConnectionGroup($connectionGroup)->addMaster($connection, $weight);
  234. }
  235. /**
  236. * Add a connection to a slaver server
  237. *
  238. * @param $connection
  239. * @param $weight
  240. */
  241. public static function addSlave(Mooses_Mongodb_Mongo_Connection $connection, $weight = 1, $connectionGroup = 'default') {
  242. static::getConnectionGroup($connectionGroup)->addSlave($connection, $weight);
  243. }
  244. /**
  245. * Get a write connection
  246. *
  247. * @param string $connectionGroupName The connection group name
  248. * @return Mooses_Mongodb_Mongo_Connection
  249. */
  250. public static function getWriteConnection($connectionGroupName = 'default') {
  251. $connectionGroup = static::getConnectionGroup($connectionGroupName);
  252. if ($connectionGroupName == 'default' && count($connectionGroup->getMasters()) === 0) {
  253. // Add a connection to localhost if no connections currently exist for the default connection group
  254. $_iniConfig = Top::getConfig();
  255. if(strlen($_iniConfig->mongodb->host) > 0){
  256. $_connectionHost = $_iniConfig->mongodb->host;
  257. } else {
  258. $_connectionHost = "127.0.0.1";
  259. }
  260. $connectionGroup->addMaster(new Mooses_Mongodb_Mongo_Connection($_connectionHost));
  261. }
  262. if (!$connection = $connectionGroup->getWriteConnection($connectionGroupName)) {
  263. require_once 'Thinkopen/MongodbMongo/Exception.php';
  264. throw new Mooses_Mongodb_Mongo_Exception("No write connection available for the '{$connectionGroupName}' connection group");
  265. }
  266. return $connection;
  267. }
  268. /**
  269. * Get a read connection
  270. *
  271. * @param string $connectionGroupName The connection group name
  272. * @return Mooses_Mongodb_Mongo_Connection
  273. */
  274. public static function getReadConnection($connectionGroupName = 'default') {
  275. $connectionGroup = static::getConnectionGroup($connectionGroupName);
  276. if ($connectionGroupName == 'default' && count($connectionGroup->getSlaves()) === 0 && count($connectionGroup->getMasters()) === 0) {
  277. // Add a connection to localhost if no connections currently exist for the default connection group
  278. $_iniConfig = Top::getConfig();
  279. if(strlen($_iniConfig->mongodb->host) > 0){
  280. $_connectionHost = $_iniConfig->mongodb->host;
  281. } else {
  282. $_connectionHost = "127.0.0.1";
  283. }
  284. $connectionGroup->addMaster(new Mooses_Mongodb_Mongo_Connection($_connectionHost));
  285. }
  286. if (!$connection = $connectionGroup->getReadConnection($connectionGroupName)) {
  287. require_once 'Thinkopen/MongodbMongo/Exception.php';
  288. throw new Mooses_Mongodb_Mongo_Exception("No read connection available for the '{$connectionGroupName}' connection group");
  289. }
  290. return $connection;
  291. }
  292. /**
  293. * Return Mooses_Mongodb_Mongo to pre-init status
  294. */
  295. public static function makeClean() {
  296. static::removeConnectionGroups();
  297. static::removeRequirements();
  298. static::removeRequirementCreators();
  299. static::$_initialised = false;
  300. }
  301. }
  302. Mooses_Mongodb_Mongo::init();