From 34866662776cfd4db3e50e363a15341e793f3f81 Mon Sep 17 00:00:00 2001 From: Coleman Watts Date: Wed, 1 Jan 2014 14:10:18 -0800 Subject: [PATCH] CRM-10693 - Handle core errors while in ajax context --- CRM/Core/Error.php | 51 ++++++++++++++++++++++++++++++++++++++-------- js/Common.js | 2 +- 2 files changed, 43 insertions(+), 10 deletions(-) diff --git a/CRM/Core/Error.php b/CRM/Core/Error.php index ed6be358d1..be85234b39 100644 --- a/CRM/Core/Error.php +++ b/CRM/Core/Error.php @@ -311,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(); } @@ -604,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; @@ -651,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, @@ -661,8 +692,7 @@ class CRM_Core_Error extends PEAR_ErrorStack { implode(", ", $args) ); } - $message .= sprintf("#%s {main}\n", 1+$idx); - return $message; + return $ret; } /** @@ -742,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); } diff --git a/js/Common.js b/js/Common.js index f9ba78ac9b..274371ccda 100644 --- a/js/Common.js +++ b/js/Common.js @@ -989,7 +989,7 @@ CRM.validate = CRM.validate || { url: data.url.replace(/reset=1[&]?/, ''), dataType: 'json', success: function(response) { - if (response.status === 'success') { + if (response.status !== 'form_error') { $el.crmSnippet('option', 'block') && $el.unblock(); $el.trigger('crmFormSuccess', response); // Reset form for e.g. "save and new" -- 2.25.1