Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WordPress - Display site-theme/decorations on error screens #22805

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 48 additions & 4 deletions CRM/Core/Error.php
Original file line number Diff line number Diff line change
Expand Up @@ -204,9 +204,11 @@ public static function handle($pearError) {
CRM_Core_Error::debug_var('Fatal Error Details', $error, TRUE, TRUE, '', PEAR_LOG_ERR);
CRM_Core_Error::backtrace('backTrace', TRUE);

$exit = TRUE;
if ($config->initialized) {
$content = $template->fetch('CRM/common/fatal.tpl');
echo CRM_Utils_System::theme($content);
$exit = CRM_Utils_System::shouldExitAfterFatal();
}
else {
echo "Sorry. A non-recoverable error has occurred. The error trace below might help to resolve the issue<p>";
Expand All @@ -217,7 +219,13 @@ public static function handle($pearError) {
exit;
}
$runOnce = TRUE;
self::abend(CRM_Core_Error::FATAL_ERROR);

if ($exit) {
self::abend(CRM_Core_Error::FATAL_ERROR);
}
else {
self::inpageExceptionDisplay(CRM_Core_Error::FATAL_ERROR);
}
}

/**
Expand Down Expand Up @@ -442,9 +450,14 @@ function_exists($config->fatalErrorHandler)
}

echo CRM_Utils_System::theme($content);
$exit = CRM_Utils_System::shouldExitAfterFatal();

// fin
self::abend(CRM_Core_Error::FATAL_ERROR);
if ($exit) {
self::abend(CRM_Core_Error::FATAL_ERROR);
}
else {
self::inpageExceptionDisplay(CRM_Core_Error::FATAL_ERROR);
}
}

/**
Expand Down Expand Up @@ -998,7 +1011,7 @@ public static function movedSiteError($file) {
/**
* Terminate execution abnormally.
*
* @param string $code
* @param int $code
*/
protected static function abend($code) {
// do a hard rollback of any pending transactions
Expand All @@ -1007,6 +1020,37 @@ protected static function abend($code) {
CRM_Utils_System::civiExit($code);
}

/**
* Show in-page exception
* For situations where where calling abend will block the ability for a branded error screen
*
* Although the host page will run past this point, CiviCRM should not,
* therefore we trigger the civi.exit events
*
* @param string $code
*/
protected static function inpageExceptionDisplay($code) {
// do a hard rollback of any pending transactions
// if we've come here, its because of some unexpected PEAR errors
CRM_Core_Transaction::forceRollbackIfEnabled();

if ($code > 0 && !headers_sent()) {
http_response_code(500);
}

// move things to CiviCRM cache as needed
CRM_Core_Session::storeSessionObjects();

if (Civi\Core\Container::isContainerBooted()) {
Civi::dispatcher()->dispatch('civi.core.exit');
}

$userSystem = CRM_Core_Config::singleton()->userSystem;
if (is_callable([$userSystem, 'onCiviExit'])) {
$userSystem->onCiviExit();
}
}

/**
* @param array $error
* @param int $type
Expand Down
1 change: 1 addition & 0 deletions CRM/Utils/System.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
* @method static array synchronizeUsers() Create CRM contacts for all existing CMS users.
* @method static void appendCoreResources(\Civi\Core\Event\GenericHookEvent $e) Callback for hook_civicrm_coreResourceList.
* @method static void alterAssetUrl(\Civi\Core\Event\GenericHookEvent $e) Callback for hook_civicrm_getAssetUrl.
* @method static exitAfterFatal() Should the current execution exit after a fatal error?
*/
class CRM_Utils_System {

Expand Down
11 changes: 11 additions & 0 deletions CRM/Utils/System/Base.php
Original file line number Diff line number Diff line change
Expand Up @@ -1099,4 +1099,15 @@ public function getUfGroupTypes() {
return [];
}

/**
* Should the current execution exit after a fatal error?
* This is the appropriate functionality in most cases.
*
* @internal
* @return bool
*/
public function shouldExitAfterFatal() {
return TRUE;
}

}
20 changes: 20 additions & 0 deletions CRM/Utils/System/WordPress.php
Original file line number Diff line number Diff line change
Expand Up @@ -602,6 +602,8 @@ public function loadUser($user) {
*/
public function permissionDenied() {
status_header(403);
global $civicrm_wp_title;
$civicrm_wp_title = ts('You do not have permission to access this page.');
throw new CRM_Core_Exception(ts('You do not have permission to access this page.'));
}

Expand Down Expand Up @@ -1473,4 +1475,22 @@ public function showPasswordFieldWhenAdminCreatesUser() {
return !$this->isUserRegistrationPermitted();
}

/**
* Should the current execution exit after a fatal error?
*
* In WordPress, it is not usually possible to trigger theming outside of the WordPress theme process,
* meaning that in order to render an error inside the theme we cannot exit on error.
*
* @internal
* @return bool
*/
public function shouldExitAfterFatal() {
$ret = TRUE;
if (!is_admin() && !wp_doing_ajax()) {
$ret = FALSE;
}

return apply_filters('civicrm_exit_after_fatal', $ret);
}

}