AbstractMongo.php 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. <?php
  2. /**
  3. * Questa classe fa da interfaccia verso MongoDb
  4. *
  5. * @author Paolo Libertini <paolo.libertini@thinkopen.it>
  6. * @method getCollection()
  7. * @method addFieldToFilter($_attributeName, $_value)
  8. * @method addFieldToSelect($_attributeName)
  9. */
  10. class Mooses_AbstractMongo extends Mooses_Mongodb_Mongo_Document {
  11. const ASC = "ASC";
  12. protected static $_db;
  13. protected static $_collection;
  14. protected static $_instance;
  15. protected $calledClass;
  16. protected $_classMethods = array();
  17. protected static $_order = array();
  18. protected $_queryConditions = array();
  19. protected $_fields = array();
  20. protected $_sorterArray = array();
  21. protected $_sorterAttribute = "";
  22. protected $_sorterDate = false;
  23. protected $_sorterOrder = self::ASC;
  24. protected $_forceNoCachePaginatedCollection = false;
  25. public $loadKey = array();
  26. protected $_dataUpdate = array();
  27. public function __construct($_data = []) {
  28. $this->_setCollectionAndDatabase();
  29. parent::__construct($_data, array());
  30. $this->calledClass = get_called_class();
  31. self::$_instance = $this;
  32. return $this;
  33. }
  34. private function _setCollectionAndDatabase(){
  35. $_mongoInformations = $this->_retrieveTableName();
  36. self::$_db = $_mongoInformations['db'];
  37. static::$_db = $_mongoInformations['db'];
  38. self::$_collection = $_mongoInformations['collection'];
  39. static::$_collection = $_mongoInformations['collection'];
  40. $this->_classMethods = get_class_methods($this);
  41. }
  42. public static function getInstance() {
  43. if (self::$_instance === NULL || self::$_instance->calledClass !== get_called_class()) {
  44. $_className = get_called_class();
  45. self::$_instance = new $_className();
  46. }
  47. return self::$_instance;
  48. }
  49. protected static function ___retrieveTableName(){
  50. $_return = array();
  51. $annotations = new ReflectionClass(get_called_class());
  52. $_tableSuffix = NULL;
  53. $_tablePrefix = "re_";
  54. $_databaseAnnotated = self::_parseDocComment($annotations->getDocComment(), "@Db");
  55. $_collectionAnnotated = self::_parseDocComment($annotations->getDocComment(), "@Collection");
  56. $_return['collection'] = (stristr($_collectionAnnotated, $_tableSuffix)) ? $_collectionAnnotated : $_tablePrefix . $_collectionAnnotated . $_tableSuffix;
  57. $_return['db'] = $_databaseAnnotated;
  58. return $_return;
  59. }
  60. protected function _retrieveTableName() {
  61. return self::___retrieveTableName();
  62. }
  63. private static function _parseDocComment($str, $tag = ''){
  64. if (empty($tag)) {
  65. return $str;
  66. }
  67. $matches = array();
  68. preg_match("/" . $tag . ":(.*)(\\r\\n|\\r|\\n)/U", $str, $matches);
  69. if (isset($matches[1])) {
  70. return trim($matches[1]);
  71. }
  72. return '';
  73. }
  74. protected function _convertMongoCursor($_mongoCursor, $_forceArray = false, $_order = false){
  75. $_calledClass = $_mongoCursor->getDocumentClass();
  76. if($_mongoCursor->count() == 0){
  77. return (($_forceArray) ? array() : false);
  78. } elseif($_mongoCursor->count() == 1){
  79. $_object = new $_calledClass($_mongoCursor->next());
  80. $_object->loadKey = $this->loadKey;
  81. $_object = (($_forceArray) ? array($_object) : $_object);
  82. return $_object;
  83. } else {
  84. $_arrayResults = array();
  85. while($_result = $_mongoCursor->next()){
  86. $_object = new $_calledClass($_result);
  87. $_object->loadKey = $this->_loadKey;
  88. array_push($_arrayResults, $_object);
  89. }
  90. if($_order !== false && is_array($_order)){
  91. $this->_sorterAttribute = $_order[0];
  92. $this->_sorterOrder = $_order[1];
  93. $this->_sorterDate = (($_order[2] === true) ? true : false);
  94. $_orderer = function($a, $b){
  95. if($this->_sorterDate === false) {
  96. if (strcasecmp((string)$a->getData($this->_sorterAttribute), (string)$b->getData($this->_sorterAttribute)) > 0) {
  97. return (($this->_sorterOrder == self::ASC) ? 1 : -1);
  98. } else {
  99. return (($this->_sorterOrder == self::ASC) ? -1 : 1);
  100. }
  101. } else {
  102. if(is_a($a, "Default_Model_Mapper_Utenti")) {
  103. $_datiA = $a->getAllData();
  104. } else {
  105. $_datiA = $a->getData();
  106. }
  107. if(is_array($_datiA[$this->_sorterAttribute]) && isset($_datiA[$this->_sorterAttribute]['date'])) {
  108. $_dataA = DateTime::createFromFormat("Y-m-d H:i:s", substr($_datiA[$this->_sorterAttribute]['date'], 0, 19));
  109. } else {
  110. $_dataA = DateTime::createFromFormat("Y-m-d H:i:s", substr($_datiA[$this->_sorterAttribute], 0, 19));
  111. }
  112. if(is_a($b, "Default_Model_Mapper_Utenti")) {
  113. $_datiB = $b->getAllData();
  114. } else {
  115. $_datiB = $b->getData();
  116. }
  117. if(is_array($_datiB[$this->_sorterAttribute]) && isset($_datiB[$this->_sorterAttribute]['date'])) {
  118. $_dataB = DateTime::createFromFormat("Y-m-d H:i:s", substr($_datiB[$this->_sorterAttribute]['date'], 0, 19));
  119. } else {
  120. $_dataB = DateTime::createFromFormat("Y-m-d H:i:s", substr($_datiB[$this->_sorterAttribute], 0, 19));
  121. }
  122. if($_dataA > $_dataB){
  123. return (($this->_sorterOrder == self::ASC) ? 1 : -1);
  124. } else {
  125. return (($this->_sorterOrder == self::ASC) ? -1 : 1);
  126. }
  127. }
  128. };
  129. usort($_arrayResults, $_orderer);
  130. }
  131. return $_arrayResults;
  132. }
  133. }
  134. public static function __callStatic($name, $arguments)
  135. {
  136. if(get_called_class() != get_class(self::$_instance)){
  137. $_mongoInformations = self::_retrieveTableName();
  138. self::$_db = $_mongoInformations['db'];
  139. static::$_db = $_mongoInformations['db'];
  140. self::$_collection = $_mongoInformations['collection'];
  141. static::$_collection = $_mongoInformations['collection'];
  142. }
  143. }
  144. public function __call($methodName, $params = null) {
  145. if(get_called_class() != get_class(self::$_instance)){
  146. $this->_setCollectionAndDatabase();
  147. }
  148. $_methodsAllowed = array("setData", "setProperty", "getData", "getProperty");
  149. $methodPrefix = substr($methodName, 0, 3);
  150. $key = strtolower(substr($methodName, 3));
  151. $_isUppercase = ctype_upper(substr($methodName, 3, 1));
  152. if (in_array("___".$methodName, $_methodsAllowed) || in_array("___".$methodName, $this->_classMethods)) {
  153. return call_user_func_array(array($this, "___".$methodName), $params);
  154. } elseif ($methodPrefix == 'set' && count($params) == 1 && $_isUppercase) {
  155. $value = htmlspecialchars($params[0],ENT_QUOTES,"UTF-8");
  156. return parent::setProperty($key, $value);
  157. } elseif ($methodPrefix == 'get') {
  158. return htmlspecialchars(parent::getProperty($key),ENT_QUOTES);
  159. } elseif (!in_array($methodName, array_flip(get_class_methods($this)))) {
  160. throw new Exception("Method \"" . $methodName . "\" doesn't exist in " . get_called_class(), 500);
  161. }
  162. }
  163. public static function addMongoRegexp(&$_value){
  164. if(!is_array($_value) && stristr($_value, "/") != FALSE){
  165. $_value = new MongoRegex($_value);
  166. }
  167. }
  168. protected function ___getCollection(){
  169. $this->_queryConditions = array();
  170. return $this;
  171. }
  172. protected function ___addFieldToFilter($_attributeName, $_value){
  173. if(!is_array($_value) && stristr($_value, "/") != FALSE){
  174. $_value = new MongoRegex($_value);
  175. }
  176. if(is_array($_value)){
  177. array_walk_recursive($_value, array(get_called_class(), "addMongoRegexp"));
  178. $_condition = array();
  179. foreach ($_value as $_operators => $_realValue) {
  180. $_condition[$_operators] = $_realValue;
  181. }
  182. } else {
  183. $_condition = $_value;
  184. }
  185. if(isset($this->_queryConditions[$_attributeName])){
  186. $_alreadyExistingConditions = $this->_queryConditions[$_attributeName];
  187. $_condition = array_merge($_alreadyExistingConditions, $_condition);
  188. }
  189. $this->_queryConditions[$_attributeName] = $_condition;
  190. return $this;
  191. }
  192. protected function ___setFieldToSelect($_fields = array()){
  193. $_truesFiller = function(&$_value){$_value = true;};
  194. $_keysFields = array_flip($_fields);
  195. array_walk_recursive($_keysFields, $_truesFiller);
  196. $this->_fields = $_keysFields;
  197. return $this;
  198. }
  199. protected function ___getCollectionData($_forceArray = true){
  200. $_result = $this->fetchAll($this->_queryConditions, $this->_fields);
  201. if (count($this->_sorterArray) == 0) {
  202. return $this->_convertMongoCursor($_result, $_forceArray);
  203. } else {
  204. return $this->_convertMongoCursor($_result, $_forceArray, $this->_sorterArray);
  205. }
  206. }
  207. protected function ___getPaginatedCollectionData($_page = 1, $_itemsPerPage = 15){
  208. // $_cacher = Mooses_Cacher::getInstance(strtolower("p_".str_replace("Default_Model_Mapper", "", get_called_class())), 3600);
  209. // $_idCache = preg_replace("/[^a-zA-Z0-9_]+/", "", "query_" . json_encode($this->_queryConditions));
  210. // if($this->_forceNoCachePaginatedCollection === true || !$_arrayResults = $_cacher->load($_idCache)) {
  211. $_result = $this->fetchAll($this->_queryConditions, $this->_fields);
  212. if (count($this->_sorterArray) == 0) {
  213. $_arrayResults = $this->_convertMongoCursor($_result, true);
  214. } else {
  215. $_arrayResults = $this->_convertMongoCursor($_result, true, $this->_sorterArray);
  216. }
  217. // $_cacher->save($_arrayResults, $_idCache);
  218. // }
  219. if(count($_arrayResults) > 0) {
  220. $_paginatorAdapter = new Zend_Paginator_Adapter_Array($_arrayResults);
  221. $_paginator = new Zend_Paginator($_paginatorAdapter);
  222. $_paginator->setItemCountPerPage($_itemsPerPage)->setCurrentPageNumber($_page);
  223. return $_paginator;
  224. } else {
  225. return false;
  226. }
  227. }
  228. protected function ___setCollectionOrder($_sorterArray){
  229. $this->_sorterArray = $_sorterArray;
  230. return $this;
  231. }
  232. protected function ___useCache($_useCache = true){
  233. $this->_forceNoCachePaginatedCollection = !$_useCache;
  234. return $this;
  235. }
  236. protected function ___getData($_key = NULL, $_default = NULL, $_forceDateExtendedFormat = false){
  237. if(is_null($_key)) {
  238. return parent::getAllData();
  239. } else {
  240. if(parent::hasProperty($_key)) {
  241. $_value = parent::getProperty($_key);
  242. if (is_object($_value)) {
  243. if(isset($_value->date)) {
  244. $_valueDatetime = DateTime::createFromFormat("Y-m-d H:i:s", $_value->date);
  245. if(is_object($_valueDatetime) && $_forceDateExtendedFormat){
  246. $_value = $_valueDatetime->format("d/m/Y H:i:s");
  247. } elseif(is_object($_valueDatetime)) {
  248. $_value = $_valueDatetime->format("d/m/Y");
  249. } else {
  250. $_value = $_value->date;
  251. }
  252. } else {
  253. $_value = $_value->getAllData();
  254. }
  255. }
  256. return $_value;
  257. } else {
  258. return (($_default != NULL) ? $_default : NULL);
  259. }
  260. }
  261. }
  262. protected function ___setData($_key, $_value = NULL, $_forceCleanData = false){
  263. if(is_array($_key)){
  264. foreach($_key as $_chiave => $_value){
  265. parent::setProperty($_chiave, $_value);
  266. $this->_dataUpdate[$_chiave] = $_value;
  267. }
  268. } else {
  269. if($_key == "birthdate" || is_a($_value, "DateTime")){
  270. $_oldValue = $_value;
  271. $_value = new stdClass();
  272. $_value->date = $_oldValue->format("Y-m-d H:i:s");
  273. $_value->timezone_type = 3;
  274. $_value->timezone = "Europe/Rome";
  275. }
  276. parent::setProperty($_key, $_value, $_forceCleanData);
  277. }
  278. $this->_dataUpdate[$_key] = $_value;
  279. return $this;
  280. }
  281. protected function ___load($_value, $_attributeName = NULL){
  282. if(is_null($_attributeName)){
  283. return parent::find($_value);
  284. } else {
  285. return parent::fetchOne(array($_attributeName => $_value));
  286. }
  287. }
  288. protected function ___loadByAttribute($_attributeName = "", $_value = "", $_forceArray = false){
  289. if(stristr($_value, "/") !== FALSE){
  290. $_value = new MongoRegex($_value);
  291. }
  292. $this->loadKey = array($_attributeName => $_value);
  293. $_results = parent::fetchAll($this->loadKey);
  294. return $this->_convertMongoCursor($_results, $_forceArray);
  295. }
  296. public function ___save($entierDocument = false, $safe = true){
  297. return parent::save($entierDocument, $safe);
  298. }
  299. public function deleteData($_safe = true, $onlyOne = true){
  300. $mongoCollection = $this->_getMongoCollection(true);
  301. $this->preDelete();
  302. if (!$this->isRootDocument()) {
  303. $result = $mongoCollection->update($this->loadKey, array('$unset' => array($this->getPathToDocument() => 1)), array('safe' => $_safe));
  304. }
  305. else {
  306. $result = $mongoCollection->remove($this->loadKey, array('justOne' => $onlyOne, 'safe' => $_safe));
  307. }
  308. return $result;
  309. }
  310. public function updateData(){
  311. $_return = $this->update($this->loadKey, array('$set' => $this->_dataUpdate));
  312. return $_return;
  313. }
  314. public function setUpdateCriteria($_array){
  315. $this->loadKey = $_array;
  316. return $this;
  317. }
  318. public function flatten($array, $prefix = '') {
  319. $result = array();
  320. foreach($array as $key=>$value) {
  321. if(is_array($value)) {
  322. $result = $result + $this->flatten($value, strtolower($prefix . $key . '_'));
  323. }
  324. else {
  325. $result[strtolower($prefix . $key)] = $value;
  326. }
  327. }
  328. return $result;
  329. }
  330. }