/** * Exception handler * @param Exception $exception The exception raised */ function exceptionHandler($exception) { try { $exceptionMessage = NULL; // If a transaction is in progress, rollback it if (DatabaseFactory::isTransactionInProgress()) { DatabaseFactory::rollback(); } // logs exception before doing anything else, for logs to be filled even if an exception will occur during the exception treatment $logInstance = LogTool::getInstance(); // debug exception in web context if ($exception instanceof GenericWarningException) { // logs warning $logInstance->logException($exception, LogTool::WARNING_LEVEL); } else { // logs error $logInstance->logException($exception); } $exceptionClass = get_class($exception); if ($exception instanceof GenericException) { // Displays message if (TranslationTool::isTranslationAllowed()) { $exceptionMessage = $exception->getUserLocalizedMessage(); } else { $exceptionMessage = $exception->getMessage(); } } else { // If error is not managed, displays generic message $exceptionMessage = 'GENERIC_EXCEPTION'; } if (SystemTool::isAjaxContext()) { echo json_encode(array('error' => $exceptionMessage), true); } else { echo $exceptionMessage; } } catch (Exception $e) { echo $e->getMessage(); try { LogTool::getInstance()->logException($e); echo $exceptionClass . ' raised : ' . $exceptionMessage; echo '+ ' . get_class($e) . ' while handling exception : ' . $e->getMessage(); exit(LogTool::KO_RETURN_CODE); } catch (Exception $e2) { try { LogTool::getInstance()->logException($e2); echo $exceptionClass . ' raised (unable to display exception details)'; exit(LogTool::KO_RETURN_CODE); } catch (Exception $e3) { echo 'unable to display exception details'; exit; } } } }
/** * Converts a time string to a timestamp * @param string $string The time string * @param string $format The string format * @return int The timestamp */ public static function stringToTimestamp($string, $format = DateTool::FORMAT_MYSQL_DATETIME) { if (!is_string($string)) { throw new Exception('Unable to convert time string to timestamp : "' . $string . '" is not a string'); } $var = DateTime::createFromFormat($format, $string); if ($var instanceof DateTime) { return $var->getTimestamp(); } LogTool::getInstance()->logWarning("DateTime::createFromFormat returned errors."); LogTool::getInstance()->logDebug("debug " . serialize(DateTime::getLastErrors())); return false; }
/** * Updates current element */ public function update() { $updatedPropertyList = $this->getUpdatedPropertyList(); // Checks if element has to be updated if (count($updatedPropertyList) > 0) { // Updates element ElementFactory::updateElement($this); // resets original attributes, has element is now updted, there is no more property to update $this->originalPropertyList = array(); } else { LogTool::getInstance()->logDebug('Trying to update ' . $this->getElementClass() . ' but no change detected'); } }
/** * Generic request execution method * @param string $request The request string * @return resource The request results or an exception if any error occures */ protected function &request($request) { $timer = TimerTool::getInstance(); $timer->tick('Executing request (' . $this->dbName . ') : ' . $request, 'ms', 0, FALSE); $timer->incrementCount(); // Request execution $result = mysql_unbuffered_query($request, $this->dbLink); if (!$result) { $mysqlErrNo = mysql_errno($this->dbLink); $mysqlErrMsg = mysql_error($this->dbLink); // Mysql connection lost : reconnect and retry query if (!$this->isConnected()) { $logInstance = LogTool::getInstance(); $logInstance->logWarning('Connection lost (Error #' . $mysqlErrNo . ' : ' . $mysqlErrMsg . ') during request execution, will reconnect and retry it : ' . $request); $this->connect(); $logInstance->logWarning('Retrying request (' . $this->dbName . ') : ' . $request); $result = mysql_unbuffered_query($request, $this->dbLink); if (!$result) { throw DatabaseException::getSpecificException('Error while executing query (retry): "' . $request . '" (Error #' . $mysqlErrNo . ' : ' . $mysqlErrMsg . ')', $mysqlErrNo); } } else { throw DatabaseException::getSpecificException('Error while executing following query : "' . $request . '" (Error #' . $mysqlErrNo . ' : ' . $mysqlErrMsg . ')', $mysqlErrNo); } } $timer->tick('Finished executing request', 'ms', 0, TRUE); return $result; }
public function tick($logDebugText = '', $unit = 'ms', $roundPrecision = 0, $isMySQLTime = FALSE, $color = LogTool::COLOR_BLUE) { $logInstance = LogTool::getInstance(); if ($unit == 's') { $getTimeFunction = 'getTimeSeconds'; } else { $getTimeFunction = 'getTimeMicroseconds'; } // Write debug message $logInstance->logDebug((isset($this->countValue) ? '[Increment = ' . $this->countValue . ']' : '') . 'Timer: ' . round($this->{$getTimeFunction}(), $roundPrecision) . ' ' . $unit . ($this->lastTickTime ? ' (' . round($this->{$getTimeFunction}(TRUE), $roundPrecision) . ' ' . $unit . ' since last tick)' : '') . ' : ' . $logDebugText, $color); // Adds to cumulative timers if ($isMySQLTime) { $this->mysqlCumulativeTime += $this->getTimeMicroseconds(TRUE); LogTool::getInstance()->logTrace($color); } else { $this->phpCumulativeTime += $this->getTimeMicroseconds(TRUE); } // Remember current microTime $this->lastTickTime = TimerTool::getMicrotimeFloat(); }
/** * Imports data, creating a table and inserting rows * @param string $tablename The destination table's name * @param array $head The column headers * @param array $data The data to import * @param string $mismatchtable Optional table's name to store type mismatch alerts * @return boolean TRUE on success or FALSE on failure */ public function importRequest($tablename = null, $head = null, $data = null, $mismatchtable = null) { if ($tablename === null || $head === null || $data === null) { // mandatory params return false; } try { $logInstance = LogTool::getInstance(); $coltype = array(); // tells int, float or varchar for each column $nadata = array(); // stores type mismatch alerts in a second table $nb_lines_to_check = 5; $sql = 'CREATE TABLE IF NOT EXISTS ' . $tablename . ' ('; if ($mismatchtable) { $sql2 = 'CREATE TABLE IF NOT EXISTS ' . $mismatchtable . ' ('; } $nb_col_to_check = array_key_exists(0, $head) ? count($head) - 1 : count($head); // if columns begin at #1, there's no id and we won't create one ; // if they begin at #0, it probably means there's an id, so let's handle it if (array_key_exists(0, $head)) { // " && $head[0] == 'id' " unnecessary $coltype[$head[0]] = 'int(11)'; $sql .= '`' . $head[0] . '` ' . $coltype[$head[0]] . ', '; } for ($i = 1; $i <= $nb_col_to_check; $i++) { $colindex = StringTool::cleanVarName($head[$i]); if ($colindex == SGBD_SDF_MOLSTRUCCOL) { $coltype[$colindex] = 'text'; } else { $nb_flt = 0; $nb_int = 0; $nb_str = 0; // try the first $nb_lines_to_check lines of data for ($j = 0; $j < $nb_lines_to_check; $j++) { //$logInstance->logDebug("j : ".$j." - colindex : ".$colindex); if (array_key_exists($j, $data)) { // "false" if less than 5 lines in data $temp = $data[$j][$colindex]; if (StringTool::isFloat($temp)) { $nb_flt++; } elseif (StringTool::isInt($temp)) { $nb_int++; } else { $nb_str++; } } } if ($nb_flt > 0 && $nb_flt + $nb_int >= $nb_lines_to_check - 1) { // we tolerate 1 line with wrong type $coltype[$colindex] = 'float'; } elseif ($nb_int >= $nb_lines_to_check - 1) { $coltype[$colindex] = 'int(11)'; } else { $coltype[$colindex] = 'text'; } // varchar too short sometimes if ($mismatchtable) { $sql2 .= '`' . $head[$i] . '` varchar(50), '; } // store mismatches directly in this table (not just 0/1/null) } $sql .= '`' . $head[$i] . '` ' . $coltype[$colindex] . ', '; } // the line below gets rid of the comma $sql = substr($sql, 0, strlen($sql) - 2); $sql .= ') ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;'; $ok = $this->createRequest($sql); if (!$ok) { return false; } // ensure it's empty $sql = 'TRUNCATE TABLE ' . $tablename . ';'; $ok = $this->deleteRequest($sql); if ($mismatchtable) { $sql2 = substr($sql2, 0, strlen($sql2) - 2); $sql2 .= ') ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;'; $ok = $this->createRequest($sql2); $sql2 = 'TRUNCATE TABLE ' . $mismatchtable . ';'; $ok = $this->deleteRequest($sql2); } // now insert data $logInstance->setSilentMode(); $entry = array(); if ($mismatchtable) { $entry2 = array(); } foreach ($data as $key => $row) { $sql = 'INSERT INTO ' . $tablename . ' VALUES (\''; foreach ($row as $field => $value) { if ($coltype[$field] == 'float' && !StringTool::isFloat($value) && !StringTool::isInt($value) || $coltype[$field] == 'int(11)' && !StringTool::isInt($value) && !StringTool::isFloat($value)) { if ($mismatchtable) { $entry2[] = $value == "" ? "NULL" : "1:" . $value; // store mismatches directly in this table, with "1:" prefix } $value = "NULL"; } elseif ($value !== "" && !is_null($value)) { if ($mismatchtable && $field != SGBD_SDF_MOLSTRUCCOL) { $entry2[] = 0; } } else { $value = "NULL"; if ($mismatchtable) { $entry2[] = "NULL"; } } $entry[] = $value; } $sql .= implode("','", $entry); $sql .= '\');'; $sql = str_replace('\'NULL\'', 'NULL', $sql); $entry = array(); $ok = $this->insertRequest($sql); if ($mismatchtable) { $sql2 = 'INSERT INTO ' . $mismatchtable . ' VALUES (\''; $sql2 .= implode("','", $entry2); $sql2 .= '\');'; $sql2 = str_replace('\'NULL\'', 'NULL', $sql2); $ok = $this->insertRequest($sql2); $entry2 = array(); } } $logInstance->unsetSilentMode(); return true; } catch (ParameterException $e) { return false; } }
/** * Gets all entities by type from cache * @param string $elementClass The element type searched * @param string $conditions The conditions string to apply * @param string $orderBy The order string to apply * @return array The found entities or an exception if the entities hasn't been cached */ public static function &getElementList($elementClass, $conditions = null, $orderBy = null) { // Entities not cached yet if (!self::isCachedElementList($elementClass, $conditions, $orderBy)) { throw new CacheFactoryException('No element list found in cache for ' . $elementClass . ' (conditions:"' . $conditions . '", order:"' . $orderBy . '")'); } // Element cached LogTool::getInstance()->logDebug('Getting List from cache'); $cachedElementIdList = self::$cachedElementListArray[$elementClass][self::getListIndex($conditions, $orderBy)]; $cachedElementList = array(); foreach ($cachedElementIdList as $cachedElementId) { $cachedElementList[$cachedElementId] = self::getElement($elementClass, $cachedElementId, false); } return $cachedElementList; }
/** * Translates the string in correct language * @param string $string The string to translate * @param array $paramList The param list to be replaced in the string * @param int $quantity The quantity to pluralize the string * @param string $category The translation's category * @return string The translated string */ public function translate($string, $paramList = NULL, $quantity = NULL, $category = NULL) { // Checks if string has to be pluralized if ($quantity !== NULL && $quantity !== 1) { $string .= '_PLURAL'; } // Set silent mode to avoid every translation log LogTool::getInstance()->setSilentMode(); return $string; // Gets string from database try { if ($category !== NULL) { $category = ' AND translation_category = \'' . $category . '\''; } else { $category = ''; } $translation = ElementFactory::getElement('Translation', NULL, 'translation_language = \'' . $this->getLocale() . '\' AND translation_text = \'' . $string . '\'' . $category); LogTool::getInstance()->unsetSilentMode(); if ($paramList === NULL) { return $translation->value; } // String has params "%1" to be replaced if (!is_array($paramList)) { $paramList = array($paramList); } // Sets pattern to be replaced $patternList = array(); for ($paramNumber = 1; $paramNumber <= count($paramList); ++$paramNumber) { $patternList[] = '/%' . $paramNumber . '(?![0-9])/'; } return preg_replace($patternList, $paramList, $translation->value); } catch (ElementNoResultException $e) { // String is not localized try { $warningTracking = new WarningTracking(); $warningTracking->addTracking("Missing " . $this->getLocale() . " translation on " . $string); // TODO : Get template. DatabaseFactory::commit(); } catch (Exception $e) { } LogTool::getInstance()->unsetSilentMode(); return 'TO_BE_LOCALIZED(' . $string . ')'; } }
/** * Cancels current transactions */ public static function rollback() { LogTool::getInstance()->logNotice('Rolling back database modifications...'); DatabaseConnectionModel::rollbackTransaction(); }
/** * Deletes an element list in database * @param string $elementClass The element class to delete * @param string $conditions The delete request conditions * @return int The affected rows number */ public static function deleteElementList($elementClass, $conditions) { $logInstance = LogTool::getInstance(); $logInstance->logDebug('Deletes ' . $elementClass . ' element list'); // Deletes element in database return DatabaseFactory::deleteElementList($elementClass, $conditions); }
$isBestTime = true; } $playerStructure->update(); } //Checks if structures are unlocked if ($isSuccess) { $relatedStructureList = OsteoFactory::getElementList('StructureRequiredStructure', 'required_structure_id=' . $quizz['structureId']); foreach ($relatedStructureList as $relatedStructure) { $structure = OsteoFactory::getElement('Structure', $relatedStructure->structure_id); $requiredStructureList = OsteoFactory::getElementList('StructureRequiredStructure', 'structure_id=' . $structure->id . ' AND required_structure_id !=' . $quizz['structureId']); $isUnlocked = true; foreach ($requiredStructureList as $requiredStructure) { try { OsteoFactory::getElement('PlayerHasStructure', null, 'player_id=' . $player->id . ' AND structure_id=' . $requiredStructure->required_structure_id); } catch (ElementNoResultException $e) { LogTool::getInstance()->logWarning('no unlock'); $isUnlocked = false; break; } } if ($isUnlocked) { try { $newPlayerStructure = new PlayerHasStructure(); $newPlayerStructure->player_id = $player->id; $newPlayerStructure->structure_id = $relatedStructure->structure_id; $newPlayerStructure->add(); } catch (DatabaseDuplicateEntryException $e) { // Already in database } } }