protected function LogError($sMsg) { static $bDebug = null; if ($bDebug == null) { $bDebug = MetaModel::GetConfig()->GetModuleSetting('itop-backup', 'debug', false); } IssueLog::Error($sMsg); if ($bDebug) { echo 'Error: ' . $sMsg . "\n"; } }
/** * Create a new transaction id, store it in the session and return its id * @param void * @return int The identifier of the new transaction */ public static function GetNewTransactionId() { $bTransactionsEnabled = MetaModel::GetConfig()->Get('transactions_enabled'); if (!$bTransactionsEnabled) { return 'notransactions'; // Any value will do } $sClass = 'privUITransaction' . MetaModel::GetConfig()->Get('transaction_storage'); if (!class_exists($sClass, false)) { IssueLog::Error("Incorrect value '" . MetaModel::GetConfig()->Get('transaction_storage') . "' for 'transaction_storage', the class '{$sClass}' does not exists. Using privUITransactionSession instead for storing sessions."); $sClass = 'privUITransactionSession'; } return (string) $sClass::GetNewTransactionId(); }
/** * Add a 'context' OQL query, specifying extra objects to be marked as 'is_reached' * even though they are not part of the sources. * @param string $sOQL The OQL query defining the context objects */ public function AddContextQuery($key, $sOQL) { if ($sOQL === '') { return; } $oSearch = DBObjectSearch::FromOQL($sOQL); $aAliases = $oSearch->GetSelectedClasses(); if (count($aAliases) < 2) { IssueLog::Error("Invalid context query '{$sOQL}'. A context query must contain at least two columns."); throw new Exception("Invalid context query '{$sOQL}'. A context query must contain at least two columns. Columns: " . implode(', ', $aAliases) . '. '); } $aAliasNames = array_keys($aAliases); $sClassAlias = $oSearch->GetClassAlias(); $oCondition = new BinaryExpression(new FieldExpression('id', $aAliasNames[0]), '=', new VariableExpression('id')); $oSearch->AddConditionExpression($oCondition); $sClass = $oSearch->GetClass(); if (!array_key_exists($sClass, $this->aContextSearches)) { $this->aContextSearches[$sClass] = array(); } $this->aContextSearches[$sClass][] = array('key' => $key, 'search' => $oSearch); }
include_once 'directory.php'; $organizationID = $_GET['organizationID']; function escape_csv($value) { // replace \n with \r\n $value = preg_replace("/(?<!\r)\n/", "\r\n", $value); // escape quotes $value = str_replace('"', '""', $value); return '"' . $value . '"'; } function array_to_csv_row($array) { $escaped_array = array_map("escape_csv", $array); return implode(",", $escaped_array) . "\r\n"; } $issueLogObj = new IssueLog(); $issues = $issueLogObj->allExpandedAsArray($organizationID); $replace = array("/", "-"); $excelfile = "issues_export_" . str_replace($replace, "_", format_date(date('Y-m-d'))) . ".csv"; header("Pragma: public"); header("Content-type: text/csv"); header("Content-Disposition: attachment; filename=\"" . $excelfile . "\""); echo array_to_csv_row(array("Issues Export " . format_date(date('Y-m-d')))); $columnHeaders = array("Organization", "Issue Type", "Start Date", "End Date", "Issue Text"); echo array_to_csv_row($columnHeaders); foreach ($issues as $issue) { if ($resource['updateDate'] == "0000-00-00") { $updateDateFormatted = ""; } else { $updateDateFormatted = format_date($resource['updateDate']); }
protected function SendSynchronous(&$aIssues, $oLog = null) { $this->LoadConfig(); $sTransport = self::$m_oConfig->Get('email_transport'); switch ($sTransport) { case 'SMTP': $sHost = self::$m_oConfig->Get('email_transport_smtp.host'); $sPort = self::$m_oConfig->Get('email_transport_smtp.port'); $sEncryption = self::$m_oConfig->Get('email_transport_smtp.encryption'); $sUserName = self::$m_oConfig->Get('email_transport_smtp.username'); $sPassword = self::$m_oConfig->Get('email_transport_smtp.password'); $oTransport = Swift_SmtpTransport::newInstance($sHost, $sPort, $sEncryption); if (strlen($sUserName) > 0) { $oTransport->setUsername($sUserName); $oTransport->setPassword($sPassword); } break; case 'Null': $oTransport = Swift_NullTransport::newInstance(); break; case 'LogFile': $oTransport = Swift_LogFileTransport::newInstance(); $oTransport->setLogFile(APPROOT . 'log/mail.log'); break; case 'PHPMail': default: $oTransport = Swift_MailTransport::newInstance(); } $oMailer = Swift_Mailer::newInstance($oTransport); $aFailedRecipients = array(); $iSent = $oMailer->send($this->m_oMessage, $aFailedRecipients); if ($iSent === 0) { // Beware: it seems that $aFailedRecipients sometimes contains the recipients that actually received the message !!! IssueLog::Warning('Email sending failed: Some recipients were invalid, aFailedRecipients contains: ' . implode(', ', $aFailedRecipients)); $aIssues = array('Some recipients were invalid.'); return EMAIL_SEND_ERROR; } else { $aIssues = array(); return EMAIL_SEND_OK; } }
/** * Discard unexpected output data * This is a MUST when the Page output is DATA (download of a document, download CSV export, download ...) */ public function TrashUnexpectedOutput() { // This protection is redundant with a protection implemented in MetaModel::IncludeModule // which detects such issues while loading module files // Here, the purpose is to detect and discard characters produced by the code execution (echo) $sPreviousContent = ob_get_clean(); if (trim($sPreviousContent) != '') { if (Utils::GetConfig() && Utils::GetConfig()->Get('debug_report_spurious_chars')) { IssueLog::Error("Output already started before downloading file:\nContent was:'{$sPreviousContent}'\n"); } } }
protected function ForgotPwdGo() { $sAuthUser = utils::ReadParam('auth_user', '', true, 'raw_data'); try { UserRights::Login($sAuthUser); // Set the user's language (if possible!) $oUser = UserRights::GetUserObject(); if ($oUser == null) { throw new Exception(Dict::Format('UI:ResetPwd-Error-WrongLogin', $sAuthUser)); } if (!MetaModel::IsValidAttCode(get_class($oUser), 'reset_pwd_token')) { throw new Exception(Dict::S('UI:ResetPwd-Error-NotPossible')); } if (!$oUser->CanChangePassword()) { throw new Exception(Dict::S('UI:ResetPwd-Error-FixedPwd')); } $sTo = $oUser->GetResetPasswordEmail(); // throws Exceptions if not allowed if ($sTo == '') { throw new Exception(Dict::S('UI:ResetPwd-Error-NoEmail')); } // This token allows the user to change the password without knowing the previous one $sToken = substr(md5(APPROOT . uniqid()), 0, 16); $oUser->Set('reset_pwd_token', $sToken); CMDBObject::SetTrackInfo('Reset password'); $oUser->DBUpdate(); $oEmail = new Email(); $oEmail->SetRecipientTO($sTo); $sFrom = MetaModel::GetConfig()->Get('forgot_password_from'); if ($sFrom == '') { $sFrom = $sTo; } $oEmail->SetRecipientFrom($sFrom); $oEmail->SetSubject(Dict::S('UI:ResetPwd-EmailSubject')); $sResetUrl = utils::GetAbsoluteUrlAppRoot() . 'pages/UI.php?loginop=reset_pwd&auth_user='******'login')) . '&token=' . urlencode($sToken); $oEmail->SetBody(Dict::Format('UI:ResetPwd-EmailBody', $sResetUrl)); $iRes = $oEmail->Send($aIssues, true); switch ($iRes) { //case EMAIL_SEND_PENDING: case EMAIL_SEND_OK: break; case EMAIL_SEND_ERROR: default: IssueLog::Error('Failed to send the email with the NEW password for ' . $oUser->Get('friendlyname') . ': ' . implode(', ', $aIssues)); throw new Exception(Dict::S('UI:ResetPwd-Error-Send')); } $this->DisplayLoginHeader(); $this->add("<div id=\"login\">\n"); $this->add("<h1>" . Dict::S('UI:Login:ForgotPwdForm') . "</h1>\n"); $this->add("<p>" . Dict::S('UI:ResetPwd-EmailSent') . "</p>"); $this->add("<form method=\"post\">\n"); $this->add("<table>\n"); $this->add("<tr><td colspan=\"2\" class=\"center v-spacer\"><input type=\"button\" onClick=\"window.close();\" value=\"" . Dict::S('UI:Button:Done') . "\" /></td></tr>\n"); $this->add("</table>\n"); $this->add("</form>\n"); $this->add("</div\n"); } catch (Exception $e) { $this->DisplayForgotPwdForm(true, $e->getMessage()); } }
/** * @return boolean True if the task record can be deleted */ public function Process() { // By default: consider that the task is not completed $bRet = false; // Attempt to take the ownership $iStatus = $this->MarkAsRunning(); if ($iStatus == self::OK) { try { $sStatus = $this->DoProcess(); if ($this->Get('event_id') != 0) { $oEventLog = MetaModel::GetObject('Event', $this->Get('event_id')); $oEventLog->Set('message', $sStatus); $oEventLog->DBUpdate(); } $bRet = true; } catch (Exception $e) { $iRemaining = $this->Get('remaining_retries'); if ($iRemaining > 0) { $iRetryDelay = $this->GetRetryDelay(); IssueLog::Info('Failed to process async task #' . $this->GetKey() . ' - reason: ' . $e->getMessage() . ' - remaining retries: ' . $iRemaining . ' - next retry in ' . $iRetryDelay . 's'); $this->Set('remaining_retries', $iRemaining - 1); $this->Set('status', 'planned'); $this->Set('started', null); $this->Set('planned', time() + $iRetryDelay); $this->DBUpdate(); } else { IssueLog::Error('Failed to process async task #' . $this->GetKey() . ' - reason: ' . $e->getMessage()); } } } else { // Already done or being handled by another process... skip... $bRet = false; } return $bRet; }
protected function LogMessage($sMessage, $aData = array()) { if (MetaModel::IsLogEnabledIssue()) { if (MetaModel::IsValidClass('EventIssue')) { $oLog = new EventIssue(); $oLog->Set('message', $sMessage); $oLog->Set('userinfo', ''); $oLog->Set('issue', 'LDAP Authentication'); $oLog->Set('impact', 'User login rejected'); $oLog->Set('data', $aData); $oLog->DBInsertNoReload(); } IssueLog::Error($sMessage); } }
protected function LogError($sMsg) { IssueLog::Error($sMsg); }
protected static function IncludeModule($sModuleType, $sToInclude) { $sFirstChar = substr($sToInclude, 0, 1); $sSecondChar = substr($sToInclude, 1, 1); if ($sFirstChar != '/' && $sFirstChar != '\\' && $sSecondChar != ':') { // It is a relative path, prepend APPROOT if (substr($sToInclude, 0, 3) == '../') { // Preserve compatibility with config files written before 1.0.1 // Replace '../' by '<root>/' $sFile = APPROOT . '/' . substr($sToInclude, 3); } else { $sFile = APPROOT . '/' . $sToInclude; } } else { // Leave as is - should be an absolute path $sFile = $sToInclude; } if (!file_exists($sFile)) { $sConfigFile = self::$m_oConfig->GetLoadedFile(); if (strlen($sConfigFile) > 0) { throw new CoreException('Include: wrong file name in configuration file', array('config file' => $sConfigFile, 'section' => $sModuleType, 'filename' => $sFile)); } else { // The configuration is in memory only throw new CoreException('Include: wrong file name in configuration file (in memory)', array('section' => $sModuleType, 'filename' => $sFile)); } } // Note: We do not expect the modules to output characters while loading them. // Therefore, and because unexpected characters can corrupt the output, // they must be trashed here. // Additionnaly, pages aiming at delivering data in their output can call WebPage::TrashUnexpectedOutput() // to get rid of chars that could be generated during the execution of the code ob_start(); require_once $sFile; $sPreviousContent = ob_get_clean(); if (self::$m_oConfig->Get('debug_report_spurious_chars')) { if ($sPreviousContent != '') { IssueLog::Error("Spurious characters injected by {$sModuleType}/{$sToInclude}"); } } }
public static function Enable($sTargetFile) { self::$m_oFileLog = new FileLog($sTargetFile); }
/** * Read the output buffer and deal with its contents: * - trash unexpected output if the flag has been set * - report unexpected behaviors such as the output buffering being stopped * * Possible improvement: I've noticed that several output buffers are stacked, * if they are not empty, the output will be corrupted. The solution would * consist in unstacking all of them (and concatenate the contents). */ protected function ob_get_clean_safe() { $sOutput = ob_get_contents(); if ($sOutput === false) { $sMsg = "Design/integration issue: No output buffer. Some piece of code has called ob_get_clean() or ob_end_clean() without calling ob_start()"; if ($this->bTrashUnexpectedOutput) { IssueLog::Error($sMsg); $sOutput = ''; } else { $sOutput = $sMsg; } } else { ob_end_clean(); // on some versions of PHP doing so when the output buffering is stopped can cause a notice if ($this->bTrashUnexpectedOutput) { if (trim($sOutput) != '') { if (Utils::GetConfig() && Utils::GetConfig()->Get('debug_report_spurious_chars')) { IssueLog::Error("Trashing unexpected output:'{$s_captured_output}'\n"); } } $sOutput = ''; } } return $sOutput; }
/** * Get the description of the graph as text string in the XDot format * including the positions of the nodes and egdes (requires graphviz * to be installed on the machine and the path to dot/dot.exe to be * configured in the iTop configuration file) * Note: the function creates temporary files in APPROOT/data/tmp * @return string */ public function DumpAsXDot() { $sDotExecutable = MetaModel::GetConfig()->Get('graphviz_path'); if (file_exists($sDotExecutable)) { // create the file with Graphviz if (!is_dir(APPROOT . "data")) { @mkdir(APPROOT . "data"); } if (!is_dir(APPROOT . "data/tmp")) { @mkdir(APPROOT . "data/tmp"); } $sXdotFilePath = tempnam(APPROOT . "data/tmp", 'xdot-'); $sDotDescription = $this->GetDotDescription(true); // true => don't put (localized) labels in the file, since it makes it harder to parse $sDotFilePath = tempnam(APPROOT . "data/tmp", 'dot-'); $rFile = @fopen($sDotFilePath, "w"); @fwrite($rFile, $sDotDescription); @fclose($rFile); $aOutput = array(); $CommandLine = "\"{$sDotExecutable}\" -v -Tdot < {$sDotFilePath} -o{$sXdotFilePath} 2>&1"; exec($CommandLine, $aOutput, $iRetCode); if ($iRetCode != 0) { $sHtml = ''; $sHtml .= "<p><b>Error:</b></p>"; $sHtml .= "<p>The command: <pre>{$CommandLine}</pre> returned {$iRetCode}</p>"; $sHtml .= "<p>The output of the command is:<pre>\n" . implode("\n", $aOutput) . "</pre></p>"; IssueLog::Error($sHtml); } else { $sHtml = '<pre>' . file_get_contents($sXdotFilePath) . '</pre>'; @unlink($sXdotFilePath); } @unlink($sDotFilePath); } else { throw new Exception('graphviz not found (executable path: ' . $sDotExecutable . ')'); } return $sHtml; }
public static function SetProperty($sName, $sValue, $sComment = '', $sDescription = null) { try { $oSearch = DBObjectSearch::FromOQL('SELECT DBProperty WHERE name = :name'); $oSet = new DBObjectSet($oSearch, array(), array('name' => $sName)); if ($oSet->Count() == 0) { $oProp = new DBProperty(); $oProp->Set('name', $sName); $oProp->Set('description', $sDescription); $oProp->Set('value', $sValue); $oProp->Set('change_date', time()); $oProp->Set('change_comment', $sComment); $oProp->DBInsert(); } elseif ($oSet->Count() == 1) { $oProp = $oSet->fetch(); if (!is_null($sDescription)) { $oProp->Set('description', $sDescription); } $oProp->Set('value', $sValue); $oProp->Set('change_date', time()); $oProp->Set('change_comment', $sComment); $oProp->DBUpdate(); } else { // Houston... throw new CoreException('duplicate db property'); } } catch (MySQLException $e) { // This might be because the table could not be found, // let's check it and discard silently if this is really the case if (self::IsInstalled()) { throw $e; } IssueLog::Error('Attempting to write a DBProperty while the module has not been installed'); } }
/** * @param hash $aOrderBy Array of '[<classalias>.]attcode' => bAscending */ public function MakeSelectQuery($aOrderBy = array(), $aArgs = array(), $aAttToLoad = null, $aExtendedDataSpec = null, $iLimitCount = 0, $iLimitStart = 0, $bGetCount = false) { // Check the order by specification, and prefix with the class alias // and make sure that the ordering columns are going to be selected // $sClass = $this->GetClass(); $sClassAlias = $this->GetClassAlias(); $aOrderSpec = array(); foreach ($aOrderBy as $sFieldAlias => $bAscending) { if (!is_bool($bAscending)) { throw new CoreException("Wrong direction in ORDER BY spec, found '{$bAscending}' and expecting a boolean value"); } $iDotPos = strpos($sFieldAlias, '.'); if ($iDotPos === false) { $sAttClass = $sClass; $sAttClassAlias = $sClassAlias; $sAttCode = $sFieldAlias; } else { $sAttClassAlias = substr($sFieldAlias, 0, $iDotPos); $sAttClass = $this->GetClassName($sAttClassAlias); $sAttCode = substr($sFieldAlias, $iDotPos + 1); } if ($sAttCode != 'id') { MyHelpers::CheckValueInArray('field name in ORDER BY spec', $sAttCode, MetaModel::GetAttributesList($sAttClass)); $oAttDef = MetaModel::GetAttributeDef($sAttClass, $sAttCode); foreach ($oAttDef->GetOrderBySQLExpressions($sAttClassAlias) as $sSQLExpression) { $aOrderSpec[$sSQLExpression] = $bAscending; } } else { $aOrderSpec['`' . $sAttClassAlias . $sAttCode . '`'] = $bAscending; } // Make sure that the columns used for sorting are present in the loaded columns if (!is_null($aAttToLoad) && !isset($aAttToLoad[$sAttClassAlias][$sAttCode])) { $aAttToLoad[$sAttClassAlias][$sAttCode] = MetaModel::GetAttributeDef($sAttClass, $sAttCode); } } $oSQLQuery = $this->GetSQLQuery($aOrderBy, $aArgs, $aAttToLoad, $aExtendedDataSpec, $iLimitCount, $iLimitStart, $bGetCount); $aScalarArgs = array_merge(MetaModel::PrepareQueryArguments($aArgs), $this->GetInternalParams()); try { $bBeautifulSQL = self::$m_bTraceQueries || self::$m_bDebugQuery || self::$m_bIndentQueries; $sRes = $oSQLQuery->RenderSelect($aOrderSpec, $aScalarArgs, $iLimitCount, $iLimitStart, $bGetCount, $bBeautifulSQL); if ($sClassAlias == '_itop_') { IssueLog::Info('SQL Query (_itop_): ' . $sRes); } } catch (MissingQueryArgument $e) { // Add some information... $e->addInfo('OQL', $this->ToOQL()); throw $e; } $this->AddQueryTraceSelect($aOrderBy, $aArgs, $aAttToLoad, $aExtendedDataSpec, $iLimitCount, $iLimitStart, $bGetCount, $sRes); return $sRes; }
break; case 'xml': default: $oPage->SetContentType('text/xml'); $oObj = MetaModel::GetObject($sClass, $id, true); // Build the root XML part $oXmlDoc = new DOMDocument('1.0', 'UTF-8'); $oXmlRoot = $oXmlDoc->CreateElement('root'); $oXmlNode = $oXmlDoc->CreateElement('node'); $oXmlNode->SetAttribute('id', $oObj->GetKey()); $oXmlNode->SetAttribute('obj_class', get_class($oObj)); $oXmlNode->SetAttribute('obj_class_name', htmlspecialchars(MetaModel::GetName(get_class($oObj)))); $oXmlNode->SetAttribute('name', htmlspecialchars($oObj->GetRawName())); $oXmlNode->SetAttribute('icon', BuildIconPath($oObj->GetIcon(false))); // Hard coded for the moment AddNodeDetails($oXmlNode, $oObj); $oLinks = $oXmlDoc->CreateElement("links"); $oXmlRoot->SetAttribute('position', 'left'); $oXmlRoot->SetAttribute('title', MetaModel::GetRelationDescription($sRelation) . ' ' . htmlspecialchars($oObj->GetRawName())); IssueLog::Info(__FUNCTION__ . " Rel: {$sRelation}"); GetRelatedObjectsAsXml($oObj, $sRelation, $oLinks, $oXmlDoc, $oXmlNode, 0, $aExcludedClasses); $oXmlRoot->AppendChild($oXmlNode); $oXmlDoc->AppendChild($oXmlRoot); $oPage->add($oXmlDoc->SaveXML()); break; } } $oPage->output(); } catch (Exception $e) { echo "Error: " . $e->getMessage(); }
$externalLogin->password = $_POST['password']; $externalLogin->noteText = $_POST['noteText']; try { $externalLogin->save(); } catch (Exception $e) { echo $e->getMessage(); } break; case 'submitIssueLog': //if this is an existing issue $issueLogID = $_POST['issueLogID']; if ($issueLogID) { $issueLog = new IssueLog(new NamedArguments(array('primaryKey' => $issueLogID))); } else { //set up new external login $issueLog = new IssueLog(); } if ($_POST['issueStartDate']) { $issueLog->issueStartDate = date("Y-m-d", strtotime($_POST['issueStartDate'])); } else { $issueLog->issueStartDate = ''; } if ($_POST['issueEndDate']) { $issueLog->issueEndDate = date("Y-m-d", strtotime($_POST['issueEndDate'])); } else { $issueLog->issueEndDate = ''; } $issueLog->organizationID = $_POST['organizationID']; $issueLog->issueLogTypeID = $_POST['issueLogTypeID']; $issueLog->updateLoginID = $loginID; $issueLog->updateDate = date('Y-m-d H:i:s');
public function removeOrganization() { //delete organization roles $this->removeOrganizationRoles(); $instance = new Alias(); foreach ($this->getAliases() as $instance) { $instance->delete(); } $instance = new Contact(); foreach ($this->getContacts() as $instance) { $instance->removeContactRoles(); $instance->delete(); } $instance = new ExternalLogin(); foreach ($this->getExternalLogins() as $instance) { $instance->delete(); } $instance = new IssueLog(); foreach ($this->getIssueLog() as $instance) { $instance->delete(); } //delete parent and child relationships $this->removeOrganizationHierarchy(); $this->delete(); }
/** * Attempt to acquire the mutex * @returns bool True if the mutex is acquired, false if already locked elsewhere */ public function TryLock() { if ($this->bLocked) { return true; // Already acquired } if (self::$aAcquiredLocks[$this->sName] > 0) { self::$aAcquiredLocks[$this->sName]++; $this->bLocked = true; return true; } $res = $this->QueryToScalar("SELECT GET_LOCK('" . $this->sName . "', 0)"); if (is_null($res)) { throw new Exception("Failed to acquire the lock '" . $this->sName . "'"); } // $res === '1' means I hold the lock // $res === '0' means it timed out if ($res === '1') { $this->bLocked = true; self::$aAcquiredLocks[$this->sName]++; } if ($res !== '1' && $res !== '0') { $sMsg = 'GET_LOCK(' . $this->sName . ', 0) returned: ' . var_export($res, true) . '. Expected values are: 0, 1 or null'; IssueLog::Error($sMsg); throw new Exception($sMsg); } return $res !== '0'; }
$sFormat = utils::ReadParam('format', null, true); $sFileName = utils::ReadParam('filename', '', true, 'string'); $bInteractive = utils::ReadParam('interactive', false); $sMode = utils::ReadParam('mode', ''); if ($bInteractive) { InteractiveShell($sExpression, $sQueryId, $sFormat, $sFileName, $sMode); } else { $oExporter = CheckParameters($sExpression, $sQueryId, $sFormat); $sMimeType = $oExporter->GetMimeType(); if ($sMimeType == 'text/html') { $oP = new NiceWebPage('iTop export'); $oP->add_style("body { overflow: auto; }"); $oP->add_ready_script("\$('table.listResults').tablesorter({widgets: ['MyZebra']});"); } else { $oP = new ajax_page('iTop export'); $oP->SetContentType($oExporter->GetMimeType()); } DoExport($oP, $oExporter, false); $oP->output(); } } catch (BulkExportMissingParameterException $e) { $oP = new ajax_page('iTop Export'); $oP->add($e->getMessage()); Usage($oP); $oP->output(); } catch (Exception $e) { $oP = new WebPage('iTop Export'); $oP->add('Error: ' . $e->getMessage()); IssueLog::Error($e->getMessage() . "\n" . $e->getTraceAsString()); $oP->output(); }
/** * Get the context definitions from the parameters / configuration. The format of the "key" string is: * <module>/relation_context/<class>/<relation>/<direction> * The values will be retrieved for the given class and all its parents and merged together as a single array. * Entries with an invalid query are removed from the list. * @param string $sContextKey The key to fetch the queries in the configuration. Example: itop-tickets/relation_context/UserRequest/impacts/down * @param bool $bDevelopParams Whether or not to substitute the parameters inside the queries with the supplied "context params" * @param array $aContextParams Arguments for the queries (via ToArgs()) if $bDevelopParams == true * @return multitype:multitype:string */ public static function GetContextDefinitions($sContextKey, $bDevelopParams = true, $aContextParams = array()) { $aContextDefs = array(); $aLevels = explode('/', $sContextKey); if (count($aLevels) < 5) { IssueLog::Warning("GetContextDefinitions: invalid 'sContextKey' = '{$sContextKey}'. 5 levels of / are expected !"); } else { $sLeafClass = $aLevels[2]; if (!MetaModel::IsValidClass($sLeafClass)) { IssueLog::Warning("GetContextDefinitions: invalid 'sLeafClass' = '{$sLeafClass}'. A valid class name is expected in 3rd position inside '{$sContextKey}' !"); } else { $aRelationContext = MetaModel::GetConfig()->GetModuleSetting($aLevels[0], $aLevels[1], array()); foreach (MetaModel::EnumParentClasses($sLeafClass, ENUM_PARENT_CLASSES_ALL) as $sClass) { if (isset($aRelationContext[$sClass][$aLevels[3]][$aLevels[4]]['items'])) { $aContextDefs = array_merge($aContextDefs, $aRelationContext[$sClass][$aLevels[3]][$aLevels[4]]['items']); } } // Check if the queries are valid foreach ($aContextDefs as $sKey => $sDefs) { $sOQL = $aContextDefs[$sKey]['oql']; try { // Expand the parameters. If anything goes wrong, then the query is considered as invalid and removed from the list $oSearch = DBObjectSearch::FromOQL($sOQL); $aContextDefs[$sKey]['oql'] = $oSearch->ToOQL($bDevelopParams, $aContextParams); } catch (Exception $e) { IssueLog::Warning('Invalid OQL query: ' . $sOQL . ' in the parameter ' . $sContextKey); unset($aContextDefs[$sKey]); } } } } return $aContextDefs; }
$oAttachment->Set('item_class', $sObjClass); $oAttachment->SetDefaultOrgId(); $oAttachment->Set('contents', $oDoc); $iAttId = $oAttachment->DBInsert(); $aResult['msg'] = $oDoc->GetFileName(); $aResult['icon'] = utils::GetAbsoluteUrlAppRoot() . AttachmentPlugIn::GetFileIcon($oDoc->GetFileName()); $aResult['att_id'] = $iAttId; $aResult['preview'] = $oDoc->IsPreviewAvailable() ? 'true' : 'false'; } catch (FileUploadException $e) { $aResult['error'] = $e->GetMessage(); } } $oPage->add(json_encode($aResult)); break; case 'remove': $iAttachmentId = utils::ReadParam('att_id', ''); $oSearch = DBObjectSearch::FromOQL("SELECT Attachment WHERE id = :id"); $oSet = new DBObjectSet($oSearch, array(), array('id' => $iAttachmentId)); while ($oAttachment = $oSet->Fetch()) { $oAttachment->DBDelete(); } break; default: $oPage->p("Missing argument 'operation'"); } $oPage->output(); } catch (Exception $e) { // note: transform to cope with XSS attacks echo htmlentities($e->GetMessage(), ENT_QUOTES, 'utf-8'); IssueLog::Error($e->getMessage()); }
/** * Overridable to extend the behavior in case of error (logging) */ protected function HandleError($sErrorMessage, $iErrorCode) { if ($this->Get('last_attempt') == '') { // First attempt $this->Set('remaining_retries', $this->GetMaxRetries($iErrorCode)); } $this->Set('last_error', $sErrorMessage); $this->Set('last_error_code', $iErrorCode); // Note: can be ZERO !!! $this->Set('last_attempt', time()); $iRemaining = $this->Get('remaining_retries'); if ($iRemaining > 0) { $iRetryDelay = $this->GetRetryDelay($iErrorCode); IssueLog::Info('Failed to process async task #' . $this->GetKey() . ' - reason: ' . $sErrorMessage . ' - remaining retries: ' . $iRemaining . ' - next retry in ' . $iRetryDelay . 's'); $this->Set('remaining_retries', $iRemaining - 1); $this->Set('status', 'planned'); $this->Set('started', null); $this->Set('planned', time() + $iRetryDelay); } else { IssueLog::Error('Failed to process async task #' . $this->GetKey() . ' - reason: ' . $sErrorMessage); $this->Set('status', 'error'); $this->Set('started', null); $this->Set('planned', null); $this->OnDefinitiveFailure(); } $this->DBUpdate(); }