PageRenderTime 92ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 0ms

/application/libraries/Mdb.php

https://github.com/escusado/Sinapsis
PHP | 333 lines | 219 code | 42 blank | 72 comment | 35 complexity | 186e4b70b0a4a5f4114524c6f52562b2 MD5 | raw file
  1. <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
  2. // ::LIBRARY/Mdb:: Provides a CI friendly wrapper for MongoDB
  3. class Mdb {
  4. // ::ATTRIBUTE/mongo_friendly/string/public:: Stores the friendly name for the selected database
  5. public $mongo_friendly = '';
  6. // ::ATTRIBUTE/CI/object/protected:: Pointer to the CI superobject
  7. protected $CI;
  8. // ::ATTRIBUTE/mongo_conn/string/protected:: MongoDB connection string, see config for more details
  9. protected $mongo_conn = 'mongodb://localhost:27017';
  10. // ::ATTRIBUTE/mongo_db/string/protected:: MongoDB database name, see config for more details
  11. protected $mongo_db = 'test';
  12. // ::ATTRIBUTE/mongo_persist/string/protected:: MongoDB persistence string, see config for more details
  13. protected $mongo_persist = 'cimongodb';
  14. // ::ATTRIBUTE/mongo_last_error/string/protected:: Last error in human readable form
  15. protected $mongo_last_error = '';
  16. // ::ATTRIBUTE/mongo_error/bool/protected:: Last operation resulted in an error?
  17. protected $mongo_error = false;
  18. // ::METHOD/__construct($params = array())/public:: Constructor, sets up the MongoDB connection
  19. public function __construct($params = array()) {
  20. // set the super object to a local variable for use throughout the class
  21. $this->CI =& get_instance();
  22. // set all mongoDB preferences
  23. foreach (array('mongo_conn', 'mongo_db', 'mongo_friendly', 'mongo_persist') as $key) { $this->{$key} = (isset($params[$key])) ? $params[$key] : $this->CI->config->item($key); }
  24. // friendly name
  25. $this->mongo_friendly = (!isset($this->mongo_friendly) or strlen(trim($this->mongo_friendly)) < 1) ? $this->mongo_db : trim($this->mongo_friendly);
  26. // create mongoDB connection
  27. try {
  28. // connect to server
  29. $m = new Mongo($this->mongo_conn, array("persist" => $this->mongo_persist));
  30. // select database
  31. $this->{$this->mongo_friendly} = $m->{$this->mongo_db};
  32. } catch (MongoConnectionException $e) {
  33. show_error('Unable to connect to MongoDB server.');
  34. } catch (MongoException $e) {
  35. show_error('MongoDB Error: ' . $e->getMessage());
  36. }
  37. log_message('debug', "Mdb Class Initialized");
  38. }
  39. // ::METHOD/get(&$collection, $criteria = array(), $sort = array(), $keys = array(), $limit, $return_cursor = false)/public:: Get a list of records matching $criteria from $collection, sort by $sort and limit to $limit.
  40. // Optionally return only the $keys listed
  41. // Optionally return the entire cursor instead of a data array. The $keys option will not work when you want the cursor returned.
  42. // Returns an array (even if empty) or a cursor. Use $this->check_error() to check for errors. The returned data array is indexed by the record '_id' as a string.
  43. public function get(&$collection, $criteria = array(), $sort = array(), $keys = array(), $limit = 0, $return_cursor = false) {
  44. // init
  45. $this->mongo_error = false;
  46. $this->mongo_last_error = '';
  47. $results = array();
  48. // if collection exists, criteria are valid interact with the DB
  49. if ($this->check_collection($collection)) {
  50. if ($this->check_criteria($criteria)) {
  51. try {
  52. // first create the cursor
  53. if (count($keys) > 0) { $cursor = $collection->find($criteria, $keys); }
  54. else { $cursor = $collection->find($criteria); }
  55. // apply sorting if array is in proper form
  56. if (is_array($sort) and count($sort)) {
  57. //print_r($sort);
  58. $cursor->sort($sort);
  59. // foreach($cursor as $record){
  60. // print_r( $record );
  61. // }
  62. }
  63. // apply limit if the limit is valid
  64. if (ctype_digit((string)$limit) and $limit > 0) { $cursor->limit($limit); }
  65. // execute a count (this will cause the cursor to execute)
  66. $stat = $cursor->count();
  67. // if we only have to return the cursor, do that now, otherwise return the actual data
  68. if ($return_cursor) {
  69. return $cursor;
  70. } else {
  71. // build return object
  72. if ($stat) {
  73. foreach ($cursor as $obj) { $results[$obj["_id"]->__toString()] = $obj; }
  74. }
  75. }
  76. unset($cursor);
  77. } catch (MongoException $e) {
  78. $this->mongo_error = true;
  79. $this->mongo_last_error = $e->getMessage();
  80. }
  81. }
  82. }
  83. return $results;
  84. }
  85. // ::METHOD/getfirst(&$collection, $criteria = array(), $sort = array())/public:: Get only one record (the first) matching $criteria from $collection, shorthand for $this->get($collection, $criteria, $sort, array(), 1)
  86. // Returns the record or false if none was found
  87. public function getfirst(&$collection, $criteria = array(), $sort = array()) {
  88. $tmp = $this->get($collection, $criteria, $sort, array(), 1);
  89. if (count($tmp)) { return reset($tmp); }
  90. else { return false; }
  91. }
  92. // ::METHOD/getbyid(&$collection, $_id)/public:: Get the record identified by the $_id provided.
  93. // Returns the record or false if none was found
  94. public function getbyid(&$collection, $_id) {
  95. // init
  96. $this->mongo_error = false;
  97. $this->mongo_last_error = '';
  98. $result = false;
  99. // validate id
  100. $_id = $this->valid_id($_id);
  101. if ($_id !== false) {
  102. if ($this->check_collection($collection)) {
  103. try {
  104. $result = $collection->findOne(array('_id' => $_id));
  105. if (!is_array($result)) { $result = false; }
  106. } catch (MongoException $e) {
  107. $this->mongo_error = true;
  108. $this->mongo_last_error = $e->getMessage();
  109. }
  110. }
  111. }
  112. return $result;
  113. }
  114. // ::METHOD/update(&$collection, $criteria = array(), $data = array(), $upsert = false)/public:: Update records matching $criteria from $collection with $data
  115. // Optionally you can elect to insert the data if no records match
  116. public function update(&$collection, $criteria = array(), $data, $upsert = false) {
  117. // init
  118. $this->mongo_error = false;
  119. $this->mongo_last_error = '';
  120. $result = false;
  121. // if collection exists, criteria are valid, data isn't empty interact with the DB
  122. if ($this->check_collection($collection)) {
  123. if ($this->check_criteria($criteria)) {
  124. if ($this->check_data($data)) {
  125. try {
  126. // dont update the _id column, just in case your query updates more records then anticipated.
  127. unset($data['_id']);
  128. $result = $collection->update($criteria, array('$set' => $data), array('upsert' => $upsert, 'multiple' => true));
  129. } catch (MongoException $e) {
  130. $this->mongo_error = true;
  131. $this->mongo_last_error = $e->getMessage();
  132. $result = false;
  133. }
  134. }
  135. }
  136. }
  137. return $result;
  138. }
  139. // ::METHOD/updatebyid(&$collection, $_id, $data = array())/public:: Update record matching $_id from $collection with $data, see $this->update for more info
  140. public function updatebyid(&$collection, $_id, $data) {
  141. // init
  142. $this->mongo_error = false;
  143. $this->mongo_last_error = '';
  144. $result = false;
  145. // validate id
  146. $_id = $this->valid_id($_id);
  147. if ($_id !== false) { $result = $this->update($collection, array('_id' => $_id), $data); }
  148. return $result;
  149. }
  150. // ::METHOD/insert(&$collection, $data = array())/public:: Insert record into $collection with $data
  151. public function insert(&$collection, $data) {
  152. // init
  153. $this->mongo_error = false;
  154. $this->mongo_last_error = '';
  155. $result = false;
  156. // if collection exists, data isn't empty interact with the DB
  157. if ($this->check_collection($collection)) {
  158. if ($this->check_data($data)) {
  159. try {
  160. $result = $collection->insert($data);
  161. if ($result !== false) { $result = $data['_id']->__toString(); }
  162. } catch (MongoException $e) {
  163. $this->mongo_error = true;
  164. $this->mongo_last_error = $e->getMessage();
  165. $result = false;
  166. }
  167. }
  168. }
  169. return $result;
  170. }
  171. // ::METHOD/delete(&$collection, $criteria = array())/public:: Delete from $collection records matching $criteria
  172. public function delete(&$collection, $criteria = array()) {
  173. // init
  174. $this->mongo_error = false;
  175. $this->mongo_last_error = '';
  176. $result = false;
  177. // if collection exists, criteria are valid interact with the DB
  178. if ($this->check_collection($collection)) {
  179. if ($this->check_criteria($criteria)) {
  180. try {
  181. $result = $collection->remove($criteria);
  182. } catch (MongoException $e) {
  183. $this->mongo_error = true;
  184. $this->mongo_last_error = $e->getMessage();
  185. $result = false;
  186. }
  187. }
  188. }
  189. return $result;
  190. }
  191. // ::METHOD/deletebyid(&$collection, $_id)/public:: Delete from $collection record matching $_id
  192. public function deletebyid(&$collection, $_id) {
  193. // init
  194. $this->mongo_error = false;
  195. $this->mongo_last_error = '';
  196. $result = false;
  197. // validate id
  198. $_id = $this->valid_id($_id);
  199. if ($_id !== false) { $result = $this->delete($collection, array('_id' => $_id)); }
  200. return $result;
  201. }
  202. // ::METHOD/delkey(&$collection, $criteria = array(), $keys = array())/public:: Remove from records matching $criteria of $collection the $keys listed
  203. public function delkey(&$collection, $criteria = array(), $keys) {
  204. // init
  205. $this->mongo_error = false;
  206. $this->mongo_last_error = '';
  207. $result = false;
  208. // if collection exists, criteria are valid, data isn't empty interact with the DB
  209. if ($this->check_collection($collection)) {
  210. if ($this->check_criteria($criteria)) {
  211. if ($this->check_data($keys)) {
  212. try {
  213. // dont update the _id column, just in case your query updates more records then anticipated.
  214. unset($keys['_id']);
  215. $tmp = array();
  216. foreach ($keys as $k) { $tmp[$k] = 1; }
  217. $result = $collection->update($criteria, array('$unset' => $tmp), array('multiple' => true));
  218. } catch (MongoException $e) {
  219. $this->mongo_error = true;
  220. $this->mongo_last_error = $e->getMessage();
  221. $result = false;
  222. }
  223. }
  224. }
  225. }
  226. return $result;
  227. }
  228. // ::METHOD/updatebyid(&$collection, $_id, $keys = array())/public:: Update record matching $_id from $collection with $data, see $this->update for more info
  229. public function delkeybyid(&$collection, $_id, $keys) {
  230. // init
  231. $this->mongo_error = false;
  232. $this->mongo_last_error = '';
  233. $result = false;
  234. // validate id
  235. $_id = $this->valid_id($_id);
  236. if ($_id !== false) { $result = $this->delkey($collection, array('_id' => $_id), $keys); }
  237. return $result;
  238. }
  239. // ::METHOD/check_error()/public:: return the status of the last query
  240. public function check_error() {
  241. return $this->mongo_error;
  242. }
  243. // ::METHOD/error_message()/public:: return the error message from the last query (if any)
  244. public function error_message() {
  245. return $this->mongo_last_error;
  246. }
  247. // ::METHOD/valid_id(&$data)/public:: cleans and checks the $_id and returns a MongoId object or false
  248. public function valid_id($_id) {
  249. // cleanup the id and make sure it is a legitimate id, first convert to string, (if it's not a string but a MongoID this shuld get you the string part)
  250. $_id = trim("$_id");
  251. if (ctype_xdigit($_id) and strlen($_id) == 24) {
  252. $_id = new MongoId($_id);
  253. return $_id;
  254. } else {
  255. $this->mongo_error = true;
  256. $this->mongo_last_error = 'The _id value is not an allowed Id';
  257. return false;
  258. }
  259. }
  260. // ::METHOD/check_collection(&$collection)/protected:: pre-query validation checks on collection
  261. protected function check_collection(&$collection) {
  262. // we are not checking if a collection actually exists, since if it doesn't it will be created on the fly
  263. // we're merely checking that &$collection reflects an object that exists, of course the object could still be the wrong one...
  264. if (!isset($collection)) {
  265. $this->mongo_error = true;
  266. $this->mongo_last_error = 'The collection referenced does not appear to exist';
  267. return false;
  268. }
  269. return true;
  270. }
  271. // ::METHOD/check_criteria(&$criteria)/protected:: pre-query validation checks on criteria
  272. protected function check_criteria(&$criteria) {
  273. // has to be an array, even if it's a blank one
  274. if (!is_array($criteria)) {
  275. $this->mongo_error = true;
  276. $this->mongo_last_error = 'The criteria need to be an array, even if blank';
  277. return false;
  278. }
  279. return true;
  280. }
  281. // ::METHOD/check_data(&$data)/protected:: pre-query validation checks on data
  282. protected function check_data(&$data) {
  283. // has to be an array, and has to be non-empty
  284. if (!is_array($data) or count($data) < 1) {
  285. $this->mongo_error = true;
  286. $this->mongo_last_error = 'The data array needs to be an array and cannot be empty';
  287. return false;
  288. }
  289. return true;
  290. }
  291. }