Improve Permission denied handling in WordPress
authorBradley Taylor <hello@brad-taylor.co.uk>
Sun, 20 Feb 2022 16:21:55 +0000 (16:21 +0000)
committerBradley Taylor <hello@brad-taylor.co.uk>
Sun, 20 Feb 2022 16:44:14 +0000 (16:44 +0000)
CRM/Core/Error.php
CRM/Utils/System.php
CRM/Utils/System/Base.php
CRM/Utils/System/WordPress.php

index 763a2605d391bc7a979eb4c831467b8a4c37a29d..7687bb641a5e01b4690f4b988092ba5982de7313 100644 (file)
@@ -204,9 +204,11 @@ class CRM_Core_Error extends PEAR_ErrorStack {
     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::exitAfterFatal();
     }
     else {
       echo "Sorry. A non-recoverable error has occurred. The error trace below might help to resolve the issue<p>";
@@ -217,7 +219,7 @@ class CRM_Core_Error extends PEAR_ErrorStack {
       exit;
     }
     $runOnce = TRUE;
-    self::abend(CRM_Core_Error::FATAL_ERROR);
+    self::abend(CRM_Core_Error::FATAL_ERROR, $exit);
   }
 
   /**
@@ -442,9 +444,10 @@ class CRM_Core_Error extends PEAR_ErrorStack {
     }
 
     echo CRM_Utils_System::theme($content);
+    $exit = CRM_Utils_System::exitAfterFatal();
 
     // fin
-    self::abend(CRM_Core_Error::FATAL_ERROR);
+    self::abend(CRM_Core_Error::FATAL_ERROR, $exit);
   }
 
   /**
@@ -999,12 +1002,15 @@ class CRM_Core_Error extends PEAR_ErrorStack {
    * Terminate execution abnormally.
    *
    * @param string $code
+   * @param bool $exit
    */
-  protected static function abend($code) {
+  protected static function abend($code, $exit = TRUE) {
     // do a hard rollback of any pending transactions
     // if we've come here, its because of some unexpected PEAR errors
     CRM_Core_Transaction::forceRollbackIfEnabled();
-    CRM_Utils_System::civiExit($code);
+    if ($exit) {
+      CRM_Utils_System::civiExit($code);
+    }
   }
 
   /**
index addc25b46bff0749dd61b30c213bce2acf863d37..451454762817100944709c1bd682292a26590887 100644 (file)
@@ -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 {
 
index a4660834c5301d244f3fd8c6b962995492e86bf3..e52c33cbe1fd2369489afa9fd9dddf993f81c695 100644 (file)
@@ -1099,4 +1099,13 @@ abstract class CRM_Utils_System_Base {
     return [];
   }
 
+  /**
+   * Should the current execution exit after a fatal error?
+   * This is the appropriate functionality in most cases.
+   * @return bool
+   */
+  public function exitAfterFatal() {
+    return TRUE;
+  }
+
 }
index 241eeaca6c728a94896bc68b2e7748202b2d0e78..4f2bf719b5ed09ff6e6021f349222d23c6cf9158 100644 (file)
@@ -602,6 +602,8 @@ class CRM_Utils_System_WordPress extends CRM_Utils_System_Base {
    */
   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.'));
   }
 
@@ -1473,4 +1475,21 @@ class CRM_Utils_System_WordPress extends CRM_Utils_System_Base {
     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.
+   *
+   * @return bool
+   */
+  public function exitAfterFatal() {
+    $ret = TRUE;
+    if (!is_admin() && !wp_doing_ajax()) {
+      $ret = FALSE;
+    }
+
+    return apply_filters('civicrm_exit_after_fatal', $ret);
+  }
+
 }