* @method getCollection() * @method sendAsArray() * @method getCollectionData() * @method loadByAttribute() * @method load() * @method addFieldToFilter($_attributeName, $_value) * @method addFieldToSelect($_attributeName) */ class Mooses_AbstractMongo extends Mooses_Mongodb_Mongo_Document { const ASC = "ASC"; protected static $_db; protected static $_collection; protected static $_instance; protected $calledClass; protected $_classMethods = array(); protected static $_order = array(); protected $_queryConditions = array(); protected $_fields = array(); protected $_sorterArray = array(); protected $_sorterAttribute = ""; protected $_sorterDate = false; protected $_sorterOrder = self::ASC; protected $_forceNoCachePaginatedCollection = false; public $loadKey = array(); protected $_dataUpdate = array(); protected $_sendAsArray = false; protected $_pageLimit = false; protected $_page = false; public function __construct($_data = []) { $this->_setCollectionAndDatabase(); parent::__construct($_data, array()); $this->calledClass = get_called_class(); self::$_instance = $this; return $this; } private function _setCollectionAndDatabase(){ $_mongoInformations = $this->_retrieveTableName(); self::$_db = $_mongoInformations['db']; static::$_db = $_mongoInformations['db']; self::$_collection = $_mongoInformations['collection']; static::$_collection = $_mongoInformations['collection']; $this->_classMethods = get_class_methods($this); } public static function getInstance() { if (self::$_instance === NULL || self::$_instance->calledClass !== get_called_class()) { $_className = get_called_class(); self::$_instance = new $_className(); } return self::$_instance; } protected static function ___retrieveTableName(){ $_return = array(); $annotations = new ReflectionClass(get_called_class()); $_tableSuffix = NULL; $_tablePrefix = "re_"; $_databaseAnnotated = self::_parseDocComment($annotations->getDocComment(), "@Db"); $_collectionAnnotated = self::_parseDocComment($annotations->getDocComment(), "@Collection"); $_return['collection'] = (stristr($_collectionAnnotated, $_tableSuffix)) ? $_collectionAnnotated : $_tablePrefix . $_collectionAnnotated . $_tableSuffix; $_return['db'] = $_databaseAnnotated; return $_return; } protected function _retrieveTableName() { return self::___retrieveTableName(); } private static function _parseDocComment($str, $tag = ''){ if (empty($tag)) { return $str; } $matches = array(); preg_match("/" . $tag . ":(.*)(\\r\\n|\\r|\\n)/U", $str, $matches); if (isset($matches[1])) { return trim($matches[1]); } return ''; } protected function ___sendAsArray(){ $this->_sendAsArray = true; return $this; } protected function _convertMongoCursor($_mongoCursor, $_forceArray = false, $_order = false){ $_calledClass = $_mongoCursor->getDocumentClass(); if($_mongoCursor->count() == 0){ return (($_forceArray) ? array() : false); } elseif($_mongoCursor->count() == 1){ $_object = new $_calledClass($_mongoCursor->next()); $_object->loadKey = $this->loadKey; $_object = (($_forceArray) ? array($_object) : $_object); return $_object; } else { $_arrayResults = array(); while($_result = $_mongoCursor->next()){ $_object = new $_calledClass($_result); $_object->loadKey = $this->_loadKey; array_push($_arrayResults, (($this->_sendAsArray && $_order === false) ? $_object->getData() : $_object)); } if($_order !== false && is_array($_order)){ $this->_sorterAttribute = $_order[0]; $this->_sorterOrder = $_order[1]; $this->_sorterDate = (($_order[2] === true) ? true : false); $_orderer = function($a, $b){ if($this->_sorterDate === false) { if (strcasecmp((string)$a->getData($this->_sorterAttribute), (string)$b->getData($this->_sorterAttribute)) > 0) { return (($this->_sorterOrder == self::ASC) ? 1 : -1); } else { return (($this->_sorterOrder == self::ASC) ? -1 : 1); } } else { if(is_a($a, "Default_Model_Mapper_Utenti")) { $_datiA = $a->getAllData(); } else { $_datiA = $a->getData(); } if(is_array($_datiA[$this->_sorterAttribute]) && isset($_datiA[$this->_sorterAttribute]['date'])) { $_dataA = DateTime::createFromFormat("Y-m-d H:i:s", substr($_datiA[$this->_sorterAttribute]['date'], 0, 19)); } else { $_dataA = DateTime::createFromFormat("Y-m-d H:i:s", substr($_datiA[$this->_sorterAttribute], 0, 19)); } if(is_a($b, "Default_Model_Mapper_Utenti")) { $_datiB = $b->getAllData(); } else { $_datiB = $b->getData(); } if(is_array($_datiB[$this->_sorterAttribute]) && isset($_datiB[$this->_sorterAttribute]['date'])) { $_dataB = DateTime::createFromFormat("Y-m-d H:i:s", substr($_datiB[$this->_sorterAttribute]['date'], 0, 19)); } else { $_dataB = DateTime::createFromFormat("Y-m-d H:i:s", substr($_datiB[$this->_sorterAttribute], 0, 19)); } if($_dataA > $_dataB){ return (($this->_sorterOrder == self::ASC) ? 1 : -1); } else { return (($this->_sorterOrder == self::ASC) ? -1 : 1); } } }; usort($_arrayResults, $_orderer); } return $_arrayResults; } } protected function ___setPageSize($_limit){ $this->_pageLimit = $_limit; return $this; } protected function ___setPage($_page){ $this->_page = $_page; return $this; } public static function __callStatic($name, $arguments) { if(get_called_class() != get_class(self::$_instance)){ $_mongoInformations = self::_retrieveTableName(); self::$_db = $_mongoInformations['db']; static::$_db = $_mongoInformations['db']; self::$_collection = $_mongoInformations['collection']; static::$_collection = $_mongoInformations['collection']; } } public function __call($methodName, $params = null) { if(get_called_class() != get_class(self::$_instance)){ $this->_setCollectionAndDatabase(); } $_methodsAllowed = array("setData", "setProperty", "getData", "getProperty"); $methodPrefix = substr($methodName, 0, 3); $key = strtolower(substr($methodName, 3)); $_isUppercase = ctype_upper(substr($methodName, 3, 1)); if (in_array("___".$methodName, $_methodsAllowed) || in_array("___".$methodName, $this->_classMethods)) { return call_user_func_array(array($this, "___".$methodName), $params); } elseif ($methodPrefix == 'set' && count($params) == 1 && $_isUppercase) { $value = ((is_string($params[0])) ? htmlspecialchars($params[0],ENT_QUOTES,"UTF-8") : $params[0]); return parent::setProperty($key, $value); } elseif ($methodPrefix == 'get') { return htmlspecialchars(parent::getProperty($key),ENT_QUOTES); } elseif (!in_array($methodName, array_flip(get_class_methods($this)))) { throw new Exception("Method \"" . $methodName . "\" doesn't exist in " . get_called_class(), 500); } } public static function addMongoRegexp(&$_value){ if(!is_array($_value) && stristr($_value, "/") != FALSE){ $_value = new MongoRegex($_value); } } protected function ___getCollection(){ $this->_queryConditions = array(); return $this; } protected function ___addFieldToFilter($_attributeName, $_value){ if(!is_array($_value) && stristr($_value, "/") != FALSE){ $_value = new MongoRegex($_value); } if(is_array($_value)){ array_walk_recursive($_value, array(get_called_class(), "addMongoRegexp")); $_condition = array(); foreach ($_value as $_operators => $_realValue) { $_condition[$_operators] = $_realValue; } } else { $_condition = $_value; } if(isset($this->_queryConditions[$_attributeName])){ $_alreadyExistingConditions = $this->_queryConditions[$_attributeName]; $_condition = array_merge($_alreadyExistingConditions, $_condition); } $this->_queryConditions[$_attributeName] = $_condition; return $this; } protected function ___setFieldToSelect($_fields = array()){ $_truesFiller = function(&$_value){$_value = true;}; $_keysFields = array_flip($_fields); array_walk_recursive($_keysFields, $_truesFiller); $this->_fields = $_keysFields; return $this; } /** * @param $_pageLimit * @param $_pageSize * @return Mooses_Mongodb_Mongo_Iterator_Cursor * @throws MongoCursorException * @throws Mooses_Mongodb_Mongo_Exception */ protected static function fetchAllWithLimits($query, array $fields, $_pageLimit, $_pageSize){ $inheritance = static::getCollectionInheritance(); if (count($inheritance) > 1) { $query['_type'] = $inheritance[0]; } // If we are selecting specific fields make sure _type is always there if (!empty($fields) && !isset($fields['_type'])) { $fields['_type'] = 1; } $_skipParameter = $_pageSize * $_pageLimit; $cursor = static::getMongoCollection(false)->find($query, $fields)->limit($_pageLimit)->skip($_skipParameter); $config = array(); $config['connectionGroup'] = static::getConnectionGroupName(); $config['db'] = static::getDbName(); $config['collection'] = static::getCollectionName(); $config['documentClass'] = static::getDocumentClass(); $config['documentSetClass'] = static::getDocumentSetClass(); return new Mooses_Mongodb_Mongo_Iterator_Cursor($cursor, $config); } /** * @param $_pageLimit * @param $_pageSize * @return int * @throws Mooses_Mongodb_Mongo_Exception */ protected static function countResults($query){ $inheritance = static::getCollectionInheritance(); if (count($inheritance) > 1) { $query['_type'] = $inheritance[0]; } // If we are selecting specific fields make sure _type is always there if (!empty($fields) && !isset($fields['_type'])) { $fields['_type'] = 1; } return static::getMongoCollection(false)->count($query); } protected function ___countCollection(){ return self::countResults($this->_queryConditions); } protected function ___getCollectionData($_forceArray = true){ if($this->_pageLimit !== false && $this->_page !== false) { $_result = self::fetchAllWithLimits($this->_queryConditions, $this->_fields, $this->_pageLimit, $this->_page); } else { $_result = $this->fetchAll($this->_queryConditions, $this->_fields); } if (count($this->_sorterArray) == 0) { return $this->_convertMongoCursor($_result, $_forceArray); } else { return $this->_convertMongoCursor($_result, $_forceArray, $this->_sorterArray); } } protected function ___getPaginatedCollectionData($_page = 1, $_itemsPerPage = 15){ // $_cacher = Mooses_Cacher::getInstance(strtolower("p_".str_replace("Default_Model_Mapper", "", get_called_class())), 3600); // $_idCache = preg_replace("/[^a-zA-Z0-9_]+/", "", "query_" . json_encode($this->_queryConditions)); // if($this->_forceNoCachePaginatedCollection === true || !$_arrayResults = $_cacher->load($_idCache)) { $_result = $this->fetchAll($this->_queryConditions, $this->_fields); if (count($this->_sorterArray) == 0) { $_arrayResults = $this->_convertMongoCursor($_result, true); } else { $_arrayResults = $this->_convertMongoCursor($_result, true, $this->_sorterArray); } // $_cacher->save($_arrayResults, $_idCache); // } if(count($_arrayResults) > 0) { $_paginatorAdapter = new Zend_Paginator_Adapter_Array($_arrayResults); $_paginator = new Zend_Paginator($_paginatorAdapter); $_paginator->setItemCountPerPage($_itemsPerPage)->setCurrentPageNumber($_page); return $_paginator; } else { return false; } } protected function ___setCollectionOrder($_sorterArray){ $this->_sorterArray = $_sorterArray; return $this; } protected function ___useCache($_useCache = true){ $this->_forceNoCachePaginatedCollection = !$_useCache; return $this; } protected function ___getData($_key = NULL, $_default = NULL, $_forceDateExtendedFormat = false){ if(is_null($_key)) { return parent::getAllData(); } else { if(parent::hasProperty($_key)) { $_value = parent::getProperty($_key); if (is_object($_value)) { if(isset($_value->date)) { $_valueDatetime = DateTime::createFromFormat("Y-m-d H:i:s", $_value->date); if(is_object($_valueDatetime) && $_forceDateExtendedFormat){ $_value = $_valueDatetime->format("d/m/Y H:i:s"); } elseif(is_object($_valueDatetime)) { $_value = $_valueDatetime->format("d/m/Y"); } else { $_value = $_value->date; } } else { $_value = $_value->getAllData(); } } return $_value; } else { return (($_default != NULL) ? $_default : NULL); } } } protected function ___setData($_key, $_value = NULL, $_forceCleanData = false){ if(is_array($_key)){ foreach($_key as $_chiave => $_value){ parent::setProperty($_chiave, $_value); $this->_dataUpdate[$_chiave] = $_value; } } else { if($_key == "birthdate" || is_a($_value, "DateTime")){ $_oldValue = $_value; $_value = new stdClass(); $_value->date = $_oldValue->format("Y-m-d H:i:s"); $_value->timezone_type = 3; $_value->timezone = "Europe/Rome"; } parent::setProperty($_key, $_value, $_forceCleanData); } $this->_dataUpdate[$_key] = $_value; return $this; } protected function ___load($_value, $_attributeName = NULL){ if(is_null($_attributeName)){ $this->loadKey = ['_id' => new MongoId($_value)]; return parent::find($_value); } else { $this->loadKey = array($_attributeName => $_value); return parent::fetchOne(array($_attributeName => $_value)); } } protected function ___loadByAttribute($_attributeName = "", $_value = "", $_forceArray = false){ if(stristr($_value, "/") !== FALSE){ $_value = new MongoRegex($_value); } $this->loadKey = array($_attributeName => $_value); $_results = parent::fetchAll($this->loadKey); return $this->_convertMongoCursor($_results, $_forceArray); } public function ___save($entierDocument = false, $safe = true){ return parent::save($entierDocument, $safe); } public function deleteData($_safe = true, $onlyOne = true){ $mongoCollection = $this->_getMongoCollection(true); $this->preDelete(); if (!$this->isRootDocument()) { $result = $mongoCollection->update($this->loadKey, array('$unset' => array($this->getPathToDocument() => 1)), array('safe' => $_safe)); } else { $result = $mongoCollection->remove($this->loadKey, array('justOne' => $onlyOne, 'safe' => $_safe)); } return $result; } public function updateData($_criteria = false){ $_criteria = $_criteria ?: $this->loadKey; $_return = $this->update($_criteria, array('$set' => $this->_dataUpdate)); return $_return; } public function setUpdateCriteria($_array){ $this->loadKey = $_array; return $this; } public function flatten($array, $prefix = '') { $result = array(); foreach($array as $key=>$value) { if(is_array($value)) { $result = $result + $this->flatten($value, strtolower($prefix . $key . '_')); } else { $result[strtolower($prefix . $key)] = $value; } } return $result; } }