/** * Stops PHP execution : die() if some critical error appeared * This method is taken from the great ameos_formidable extension. * * @param string $msg: the error message * @return void */ public static function mayday($msg, $extKey = '') { tx_rnbase::load('tx_rnbase_util_Logger'); tx_rnbase::load('tx_rnbase_util_Debug'); tx_rnbase_util_Logger::fatal($msg, $extKey ? $extKey : 'rn_base'); $aTrace = debug_backtrace(); $aLocation = array_shift($aTrace); $aTrace1 = array_shift($aTrace); $aTrace2 = array_shift($aTrace); $aTrace3 = array_shift($aTrace); $aTrace4 = array_shift($aTrace); $aDebug = array(); $aDebug[] = '<h2 id="backtracetitle">Call stack</h2>'; $aDebug[] = '<div class="backtrace">'; $aDebug[] = '<span class="notice"><b>Call 0: </b>' . str_replace(PATH_site, '/', $aLocation['file']) . ':' . $aLocation['line'] . ' | <b>' . $aTrace1['class'] . $aTrace1['type'] . $aTrace1['function'] . '</b></span><br/>With parameters: ' . (!empty($aTrace1['args']) ? self::viewMixed($aTrace1['args']) : ' no parameters'); $aDebug[] = '<hr/>'; $aDebug[] = '<span class="notice"><b>Call -1: </b>' . str_replace(PATH_site, '/', $aTrace1['file']) . ':' . $aTrace1['line'] . ' | <b>' . $aTrace2['class'] . $aTrace2['type'] . $aTrace2['function'] . '</b></span><br />With parameters: ' . (!empty($aTrace2['args']) ? self::viewMixed($aTrace2['args']) : ' no parameters'); $aDebug[] = '<hr/>'; $aDebug[] = '<span class="notice"><b>Call -2: </b>' . str_replace(PATH_site, '/', $aTrace2['file']) . ':' . $aTrace2['line'] . ' | <b>' . $aTrace3['class'] . $aTrace3['type'] . $aTrace3['function'] . '</b></span><br />With parameters: ' . (!empty($aTrace3['args']) ? self::viewMixed($aTrace3['args']) : ' no parameters'); $aDebug[] = '<hr/>'; $aDebug[] = '<span class="notice"><b>Call -3: </b>' . str_replace(PATH_site, '/', $aTrace3['file']) . ':' . $aTrace3['line'] . ' | <b>' . $aTrace4['class'] . $aTrace4['type'] . $aTrace4['function'] . '</b></span><br />With parameters: ' . (!empty($aTrace4['args']) ? self::viewMixed($aTrace4['args']) : ' no parameters'); $aDebug[] = '<hr/>'; if ($debugTrail = tx_rnbase_util_Debug::getDebugTrail()) { $aDebug[] = '<span class="notice">' . $debugTrail . '</span>'; $aDebug[] = '<hr/>'; } $aDebug[] = '</div>'; if (intval(tx_rnbase_configurations::getExtensionCfgValue('rn_base', 'forceException4Mayday'))) { throw tx_rnbase::makeInstance('tx_rnbase_util_Exception', $msg, 0, array('Info' => $aDebug)); } $aDebug[] = '<br/>'; $sContent = '<h1 id="title">Mayday</h1>'; $sContent .= '<div id="errormessage">' . $msg . '</div>'; $sContent .= '<hr />'; $verbose = intval(tx_rnbase_configurations::getExtensionCfgValue('rn_base', 'verboseMayday')); if ($verbose) { $sContent .= implode('', $aDebug); } $sPage = <<<MAYDAYPAGE <!DOCTYPE html \tPUBLIC '-//W3C//DTD XHTML 1.1//EN' \t'http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd'> <html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en'> \t<head> \t\t<title>{$extKey}::Mayday</title> \t\t<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> \t\t<meta name="robots" content="noindex, nofollow" /> \t\t<style type="text/css"> \t\t\t#title { \t\t\t\tcolor: red; \t\t\t\tfont-family: Verdana; \t\t\t} \t\t\t#errormessage { \t\t\t\tborder: 2px solid red; \t\t\t\tpadding: 10px; \t\t\t\tcolor: white; \t\t\t\tbackground-color: red; \t\t\t\tfont-family: Verdana; \t\t\t\tfont-size: 12px; \t\t\t} \t\t\t.notice { \t\t\t\tfont-family: Verdana; \t\t\t\tfont-size: 9px; \t\t\t\tfont-style: italic; \t\t\t} \t\t\t#backtracetitle { \t\t\t} \t\t\t.backtrace { \t\t\t\tbackground-color: #FFFFCC; \t\t\t} \t\t\tHR { \t\t\t\tborder: 1px solid silver; \t\t\t} \t\t</style> \t</head> \t<body> \t\t{$sContent} \t</body> </html> MAYDAYPAGE; $dieOnMayday = intval(tx_rnbase_configurations::getExtensionCfgValue('rn_base', 'dieOnMayday')); if ($dieOnMayday) { die($sPage); } else { echo $sPage; } }
/** * Function executed from the Scheduler. * * @return boolean Returns true on successful execution, false on error */ public function execute() { /* beispiel für das logging array. $devLog = array('message' => '', 'extKey' => 'mklib', 'dataVar' => FALSE); $devLog = array( tx_rnbase_util_Logger::LOGLEVEL_DEBUG => $devLog, tx_rnbase_util_Logger::LOGLEVEL_INFO => $devLog, tx_rnbase_util_Logger::LOGLEVEL_NOTICE => $devLog, tx_rnbase_util_Logger::LOGLEVEL_WARN => $devLog, tx_rnbase_util_Logger::LOGLEVEL_FATAL => $devLog ); */ $devLog = array(); $options = $this->getOptions(); $startTimeInMilliseconds = t3lib_div::milliseconds(); $memoryUsageAtStart = memory_get_usage(); tx_rnbase_util_Logger::info('[' . get_class($this) . ']: Scheduler starts', $this->getExtKey()); try { $message = $this->executeTask($options, $devLog); $this->setLastRunTime(); // devlog if (t3lib_extMgm::isLoaded('devlog')) { if (empty($devLog) || isset($devLog[tx_rnbase_util_Logger::LOGLEVEL_INFO]) && empty($devLog[tx_rnbase_util_Logger::LOGLEVEL_INFO]['message'])) { $devLog[tx_rnbase_util_Logger::LOGLEVEL_INFO]['message'] = $message; } foreach ($devLog as $logLevel => $logData) { if (empty($logData['message'])) { continue; } t3lib_div::devLog('[' . get_class($this) . ']: ' . $logData['message'], isset($logData['extKey']) ? $logData['extKey'] : $this->getExtKey(), $logLevel, isset($logData['dataVar']) ? $logData['dataVar'] : FALSE); } } } catch (Exception $exception) { $dataVar = array('errorcode' => $exception->getCode(), 'errormsg' => $exception->getMessage(), 'trace' => $exception->getTraceAsString(), 'options' => $options, 'devlog' => $devLog); if ($exception instanceof tx_rnbase_util_Exception) { $dataVar['exception_data'] = $exception->getAdditional(FALSE); } if (tx_rnbase_util_Logger::isFatalEnabled()) { tx_rnbase_util_Logger::fatal('Task [' . get_class($this) . '] failed.' . ' Error(' . $exception->getCode() . '):' . $exception->getMessage(), $this->getExtKey(), $dataVar); } // Exception Mail an die Entwicker senden $mail = tx_rnbase_configurations::getExtensionCfgValue('rn_base', 'sendEmailOnException'); if (!empty($mail)) { $this->sendErrorMail($mail, tx_rnbase::makeInstance('tx_rnbase_util_Exception', get_class($exception) . ': ' . $exception->getMessage(), $exception->getCode(), $dataVar, $exception)); } // Wir geben die Exception weiter, // damit der Scheduler eine entsprechende Meldung ausgeben kann. throw $exception; } $memoryUsageAtEnd = memory_get_usage(); tx_rnbase_util_Logger::info('[' . get_class($this) . ']: Scheduler ends successful ', $this->getExtKey(), array('Execution Time' => t3lib_div::milliseconds() - $startTimeInMilliseconds . ' ms', 'Memory Start' => $memoryUsageAtStart . ' Bytes', 'Memory End' => $memoryUsageAtEnd . ' Bytes', 'Memory Consumed' => $memoryUsageAtEnd - $memoryUsageAtStart . ' Bytes')); return true; }
/** * Function executed from the Scheduler. * Sends an email * * @return boolean */ public function execute() { $success = TRUE; $taskId = $this->taskUid; tx_rnbase::load('tx_rnbase_util_Misc'); try { $lastRun = $this->getLastRunTime($taskId); /* @var $srv tx_mklog_srv_WatchDog */ $srv = tx_rnbase_util_Misc::getService('mklog', 'WatchDog'); $filters = array(); $options = array(); $options['minimalSeverity'] = $this->getMinimalSeverity(); $options['forceSummaryMail'] = $this->getForceSummaryMail(); $options['includeDataVar'] = $this->getIncludeDataVar(); //damit jede Nachricht nur einmal kommt, auch wenn sie mehrmals vorhanden ist if ($this->getGroupEntries()) { $options['groupby'] = Tx_Mklog_Utility_Devlog::getMessageFieldName() . ',extkey'; // wir wollen aber wissen wie oft jede Nachricht vorhanden ist $options['count'] = TRUE; } $srv->triggerMails($this->getEmailReceiver(), $lastRun, $filters, $options); $this->updateLastRunTime($taskId); } catch (Exception $e) { tx_rnbase_util_Logger::fatal('WatchDog failed!', 'mklog', array('Exception' => $e->getMessage())); $success = FALSE; } return $success; }
/** * Interne Verarbeitung der Exception * @param Exception $e * @param tx_rnbase_Configurations $configurations */ private function handleException($actionName, Exception $e, $configurations) { $exceptionHandlerClass = tx_rnbase_configurations::getExtensionCfgValue('rn_base', 'exceptionHandler'); $defaultExceptionHandlerClass = 'tx_rnbase_exception_Handler'; if (!$exceptionHandlerClass) { $exceptionHandlerClass = $defaultExceptionHandlerClass; } $exceptionHandler = tx_rnbase::makeInstance($exceptionHandlerClass); if (!$exceptionHandler instanceof tx_rnbase_exception_IHandler) { $exceptionHandler = tx_rnbase::makeInstance($defaultExceptionHandlerClass); tx_rnbase::load('tx_rnbase_util_Logger'); tx_rnbase_util_Logger::fatal("the configured error handler ({$exceptionHandlerClass}) does not implement the tx_rnbase_exception_IHandler interface", 'rn_base'); } return $exceptionHandler->handleException($actionName, $e, $configurations); }
/** * chechs, if the exception was allready thrown in the stack. * returns TRUE, if the exception was allready thrown. * * die recursion können wir an dieser stelle nicht über den backtrace prüfen. * bei ungecachten ausgaben wird bei typo3 mit int_script gearbeidet, * wodurch der stack auch bei mehrfacher rekursion immer gleich ist, * also die methode nur ein mal auftaucht. * * @param string $actionName * @param Exception $e * @param tx_rnbase_configurations $configurations * @return boolean */ private function checkExceptionRecursion($action, Exception $e, tx_rnbase_configurations $configurations, $type = 'error') { static $calls = 0, $trace = array(); // konfiguration für die maximale anzahl an durchläufen holen. $maxCalls = $configurations->getInt('recursionCheck.maxCalls'); $maxCalls = $maxCalls ? $maxCalls : 50; $maxThrows = $configurations->getInt('recursionCheck.maxThrows'); $maxThrows = $maxThrows ? $maxThrows : 1; // bei mehr als 50 exception calls, müssen wir davon ausgehen, // das ein kritischer fehler vorliegt if (++$calls > $maxCalls) { tx_rnbase_util_Logger::fatal('Too much recursion in "' . get_class($this) . '"' . ' That should not have happened.' . ' It looks as if there is a problem with a faulty configuration.', 'rn_base'); return TRUE; } // else // ansonsten setzen wir eine art stack aus action, errorcode und config zusammen. $code = $e->getCode(); // das typoscript wir bei jedem plugin aufruf neu generiert // und unterscheidet sich demnach. // wenn es zu einer rekursion kommt, ist das ts allerdings immer gleich! // (abgesehen von unaufgelösten referenzen) $configKey = md5(serialize($configurations->getConfigArray())); if (empty($trace[$type])) { $trace[$type] = array(); } if (empty($trace[$type][$action])) { $trace[$type][$action] = array(); } if (empty($trace[$type][$action][$code])) { $trace[$type][$action][$code] = array(); } if (empty($trace[$type][$action][$code][$configKey])) { $trace[$type][$action][$code][$configKey] = 0; } $trace[$type][$action][$code][$configKey]++; if (isset($trace[$type][$action][$code][$configKey]) && $trace[$type][$action][$code][$configKey] > $maxThrows) { return TRUE; } return FALSE; }
/** * @param Exception $exception * @param array $args * @return void */ protected function logException(Exception $exception, array $args = array()) { $soapClient = $this->getSoapClient(); if ($soapClient instanceof SoapClient) { tx_rnbase_util_Logger::fatal('Access to Soap Interface failed: ' . $exception->getMessage(), 'mklib', array('Fehler', 'functions' => $soapClient->__getFunctions(), 'response' => $soapClient->__getLastResponse(), 'request' => $soapClient->__getLastRequest(), 'args' => $args)); } else { tx_rnbase_util_Logger::fatal('Soap Client was not instanciated!', 'mklib'); } }