X-Git-Url: https://vcs.fsf.org/?a=blobdiff_plain;f=CRM%2FCore%2FError.php;h=55e2cbeaf0567c6b5a69b5a551dc16c5b58ed08c;hb=0ef7efe286ef81f99aa7d8501d37630a560105d4;hp=4f8b855a2a224af8b9714f1057af0993bb158796;hpb=52df19870805bf5a2bae2388a1f6c5a0309c2d92;p=civicrm-core.git diff --git a/CRM/Core/Error.php b/CRM/Core/Error.php index 4f8b855a2a..55e2cbeaf0 100644 --- a/CRM/Core/Error.php +++ b/CRM/Core/Error.php @@ -106,7 +106,7 @@ class CRM_Core_Error extends PEAR_ErrorStack { $this->setDefaultCallback(array($this, 'handlePES')); } - function getMessages(&$error, $separator = '
') { + static public function getMessages(&$error, $separator = '
') { if (is_a($error, 'CRM_Core_Error')) { $errors = $error->getErrors(); $message = array(); @@ -228,7 +228,9 @@ class CRM_Core_Error extends PEAR_ErrorStack { $error['user_info'] = $pearError->getUserInfo(); $error['to_string'] = $pearError->toString(); - CRM_Core_Error::debug('Initialization Error', $error); + // ensure that debug does not check permissions since we are in bootstrap + // mode and need to print a decent message to help the user + CRM_Core_Error::debug('Initialization Error', $error, TRUE, TRUE, FALSE); // always log the backtrace to a file self::backtrace('backTrace', TRUE); @@ -309,6 +311,21 @@ class CRM_Core_Error extends PEAR_ErrorStack { } } + // If we are in an ajax callback, format output appropriately + if (CRM_Utils_Array::value('snippet', $_REQUEST) === CRM_Core_Smarty::PRINT_JSON) { + $out = array( + 'status' => 'fatal', + 'content' => '
' . ts('Sorry but we are not able to provide this at the moment.') . '
', + ); + if ($config->backtrace && CRM_Core_Permission::check('view debug output')) { + $out['backtrace'] = self::parseBacktrace(debug_backtrace()); + $message .= '

See console for backtrace

'; + } + CRM_Core_Session::setStatus($message, ts('Sorry an Error Occured'), 'error'); + CRM_Core_Transaction::forceRollbackIfEnabled(); + CRM_Core_Page_AJAX::returnJsonResponse($out); + } + if ($config->backtrace) { self::backtrace(); } @@ -319,7 +336,13 @@ class CRM_Core_Error extends PEAR_ErrorStack { CRM_Core_Error::debug_var('Fatal Error Details', $vars); CRM_Core_Error::backtrace('backTrace', TRUE); $content = $template->fetch($config->fatalErrorTemplate); - if ($config->userFramework == 'Joomla' && class_exists('JError')) { + // JErrorPage exists only in 3.x and not 2.x + // CRM-13714 + if ($config->userFramework == 'Joomla' && class_exists('JErrorPage')) { + $error = new Exception($content); + JErrorPage::render($error); + } + else if ($config->userFramework == 'Joomla' && class_exists('JError')) { JError::raiseError('CiviCRM-001', $content); } else { @@ -410,12 +433,15 @@ class CRM_Core_Error extends PEAR_ErrorStack { * @param mixed reference to variables that we need a trace of * @param bool should we log or return the output * @param bool whether to generate a HTML-escaped output + * @param bool should we check permissions before displaying output + * useful when we die during initialization and permissioning + * subsystem is not initialized - CRM-13765 * * @return string the generated output * @access public * @static */ - static function debug($name, $variable = NULL, $log = TRUE, $html = TRUE) { + static function debug($name, $variable = NULL, $log = TRUE, $html = TRUE, $checkPermission = TRUE) { $error = self::singleton(); if ($variable === NULL) { @@ -438,7 +464,10 @@ class CRM_Core_Error extends PEAR_ErrorStack { } $out = "{$prefix}$out\n"; } - if ($log && CRM_Core_Permission::check('view debug output')) { + if ( + $log && + (!$checkPermission || CRM_Core_Permission::check('view debug output')) + ) { echo $out; } @@ -590,15 +619,32 @@ class CRM_Core_Error extends PEAR_ErrorStack { * @param boolean $showArgs TRUE if we should try to display content of function arguments (which could be sensitive); FALSE to display only the type of each function argument * @param int $maxArgLen maximum number of characters to show from each argument string * @return string printable plain-text - * @see debug_backtrace - * @see Exception::getTrace() */ static function formatBacktrace($backTrace, $showArgs = TRUE, $maxArgLen = 80) { $message = ''; - foreach ($backTrace as $idx => $trace) { + foreach (self::parseBacktrace($backTrace, $showArgs, $maxArgLen) as $idx => $trace) { + $message .= sprintf("#%s %s\n", $idx, $trace); + } + $message .= sprintf("#%s {main}\n", 1+$idx); + return $message; + } + + /** + * Render a backtrace array as an array + * + * @param array $backTrace array of stack frames + * @param boolean $showArgs TRUE if we should try to display content of function arguments (which could be sensitive); FALSE to display only the type of each function argument + * @param int $maxArgLen maximum number of characters to show from each argument string + * @return array + * @see debug_backtrace + * @see Exception::getTrace() + */ + static function parseBacktrace($backTrace, $showArgs = TRUE, $maxArgLen = 80) { + $ret = array(); + foreach ($backTrace as $trace) { $args = array(); $fnName = CRM_Utils_Array::value('function', $trace); - $className = array_key_exists('class', $trace) ? ($trace['class'] . $trace['type']) : ''; + $className = isset($trace['class']) ? ($trace['class'] . $trace['type']) : ''; // do now show args for a few password related functions $skipArgs = ($className == 'DB::' && $fnName == 'connect') ? TRUE : FALSE; @@ -637,9 +683,8 @@ class CRM_Core_Error extends PEAR_ErrorStack { } } - $message .= sprintf( - "#%s %s(%s): %s%s(%s)\n", - $idx, + $ret[] = sprintf( + "%s(%s): %s%s(%s)", CRM_Utils_Array::value('file', $trace, '[internal function]'), CRM_Utils_Array::value('line', $trace, ''), $className, @@ -647,8 +692,7 @@ class CRM_Core_Error extends PEAR_ErrorStack { implode(", ", $args) ); } - $message .= sprintf("#%s {main}\n", 1+$idx); - return $message; + return $ret; } /** @@ -728,6 +772,9 @@ class CRM_Core_Error extends PEAR_ErrorStack { $redirect = $session->readUserContext(); } $session->setStatus($status, $title); + if (CRM_Utils_Array::value('snippet', $_REQUEST) === CRM_Core_Smarty::PRINT_JSON) { + CRM_Core_Page_AJAX::returnJsonResponse(array('status' => 'error')); + } CRM_Utils_System::redirect($redirect); } @@ -743,25 +790,21 @@ class CRM_Core_Error extends PEAR_ErrorStack { $error->_errorsByLevel = array(); } - public static function ignoreException($callback = NULL) { - if (!$callback) { - $callback = array('CRM_Core_Error', 'nullHandler'); - } - - $GLOBALS['_PEAR_default_error_mode'] = PEAR_ERROR_CALLBACK; - $GLOBALS['_PEAR_default_error_options'] = $callback; - } - + /** + * PEAR error-handler which converts errors to exceptions + * + * @param $pearError + * @throws PEAR_Exception + */ public static function exceptionHandler($pearError) { CRM_Core_Error::backtrace('backTrace', TRUE); throw new PEAR_Exception($pearError->getMessage(), $pearError); } /** - * Error handler to quietly catch otherwise fatal smtp transport errors. + * PEAR error-handler to quietly catch otherwise fatal errors. Intended for use with smtp transport. * * @param object $obj The PEAR_ERROR object - * * @return object $obj * @access public * @static @@ -772,21 +815,6 @@ class CRM_Core_Error extends PEAR_ErrorStack { return $obj; } - /** - * (Re)set the default callback method - * - * @return void - * @access public - * @static - */ - public static function setCallback($callback = NULL) { - if (!$callback) { - $callback = array('CRM_Core_Error', 'handle'); - } - $GLOBALS['_PEAR_default_error_mode'] = PEAR_ERROR_CALLBACK; - $GLOBALS['_PEAR_default_error_options'] = $callback; - } - /* * @deprecated * This function is no longer used by v3 api. @@ -828,7 +856,7 @@ class CRM_Core_Error extends PEAR_ErrorStack { } public static function isAPIError($error, $type = CRM_Core_Error::FATAL_ERROR) { - if (is_array($error) && CRM_Utils_Array::value('is_error', $error)) { + if (is_array($error) && !empty($error['is_error'])) { $code = $error['error_message']['code']; if ($code == $type) { return TRUE;