Skip to content
Snippets Groups Projects
civicrm.users.php 18.3 KiB
Newer Older
  • Learn to ignore specific revisions
  • Kevin Cristiano's avatar
    Kevin Cristiano committed
    <?php
    /*
     +--------------------------------------------------------------------+
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
     | Copyright CiviCRM LLC. All rights reserved.                        |
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
     |                                                                    |
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
     | This work is published under the GNU AGPLv3 license with some      |
     | permitted exceptions and without any warranty. For full license    |
     | and copyright information, see https://civicrm.org/licensing       |
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
     +--------------------------------------------------------------------+
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
     */
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    /**
     *
     * @package CRM
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
     * @copyright CiviCRM LLC https://civicrm.org/licensing
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
     *
     */
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    // This file must not accessed directly.
    if (!defined('ABSPATH')) {
      exit;
    }
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    /**
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
     * Define CiviCRM_For_WordPress_Users Class.
     *
     * @since 4.6
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
     */
    class CiviCRM_For_WordPress_Users {
    
      /**
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       * @var object
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       * Plugin object reference.
       * @since 4.6
       * @access public
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       */
      public $civi;
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
      /**
       * @var string
       * Custom role name.
       * @since 5.52
       * @access private
       */
      private $custom_role_name = 'civicrm_admin';
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
      /**
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       * Instance constructor.
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       *
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       * @since 4.6
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       */
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
      public function __construct() {
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        // Store reference to CiviCRM plugin object.
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        $this->civi = civi_wp();
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        // Always listen for activation action.
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        add_action('civicrm_activate', [$this, 'activate']);
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
      }
    
      /**
       * Plugin activation tasks.
       *
       * @since 5.6
       */
      public function activate() {
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        /*
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
         * Assign minimum capabilities to all WordPress roles and create
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
         * 'anonymous_user' role.
         */
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        $this->set_wp_user_capabilities();
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
      }
    
      /**
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       * Register hooks.
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       *
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       * @since 4.6
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       */
      public function register_hooks() {
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        // Add CiviCRM access capabilities to WordPress roles.
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        $this->set_access_capabilities();
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        // Do not hook into user updates if CiviCRM not installed yet.
        if (!CIVICRM_INSTALLED) {
          return;
        }
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        // Synchronise users on insert and update.
        add_action('user_register', [$this, 'update_user']);
        add_action('profile_update', [$this, 'update_user']);
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        // Delete ufMatch record when a WordPress user is deleted.
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        add_action('deleted_user', [$this, 'delete_user_ufmatch']);
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       * Check permissions.
       *
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       * This method only denies permission when the CiviCRM path that is requested
       * begins with "civicrm/admin". Its intention seems to be to exclude admin
       * requests from display on the front-end.
       *
       * Used internally by:
       *
       * - CiviCRM_For_WordPress_Basepage::basepage_handler()
       * - CiviCRM_For_WordPress_Shortcodes::render_single()
       * - civicrm_check_permission()
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       *
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       * @since 4.6
       *
       * @param array $args The page arguments array.
       * @return bool True if authenticated, false otherwise.
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       */
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
      public function check_permission($args) {
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
        if ($args[0] !== 'civicrm') {
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          return FALSE;
        }
    
        $config = CRM_Core_Config::singleton();
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        // Set frontend true.
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        $config->userFrameworkFrontend = TRUE;
    
        require_once 'CRM/Utils/Array.php';
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        // All profile and file URLs, as well as user dashboard and tell-a-friend are valid.
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        $arg1 = CRM_Utils_Array::value(1, $args);
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        $invalidPaths = ['admin'];
        if (in_array($arg1, $invalidPaths)) {
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          return FALSE;
        }
    
        return TRUE;
    
      }
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
      /**
       * Check a CiviCRM permission.
       *
       * @since 5.35
       *
       * @param str $permission The permission string.
       * @return bool $permitted True if allowed, false otherwise.
       */
      public function check_civicrm_permission($permission) {
    
        // Always deny if CiviCRM is not initialised.
        if (!$this->civi->initialize()) {
          return FALSE;
        }
    
        // Deny by default.
        $permitted = FALSE;
    
        // Check CiviCRM permissions.
        if (CRM_Core_Permission::check($permission)) {
          $permitted = TRUE;
        }
    
        return $permitted;
    
      }
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
      /**
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       * Get "permission denied" text.
       *
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       * Called when authentication fails in basepage_register_hooks()
       *
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       * @since 4.6
       *
       * @return string Warning message.
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       */
      public function get_permission_denied() {
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        return __('You do not have permission to access this content.', 'civicrm');
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       * Handle WordPress user events.
       *
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       * Callback function for 'user_register' hook.
       * Callback function for 'profile_update' hook.
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       *
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       * CMW: seems to (wrongly) create new CiviCRM Contact every time a user changes
       * their first_name or last_name attributes in WordPress.
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       *
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       * @since 4.6
       *
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       * @param int $user_id The numeric ID of the WordPress user.
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       */
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
      public function update_user($user_id) {
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        $user = get_userdata($user_id);
        if ($user) {
          $this->sync_user($user);
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       * Keep WordPress user synced with CiviCRM Contact.
       *
       * @since 4.6
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       *
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       * @param object $user The WordPress user object.
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       */
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
      public function sync_user($user = FALSE) {
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        // Sanity check.
        if ($user === FALSE || !($user instanceof WP_User)) {
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          return;
        }
    
        if (!$this->civi->initialize()) {
          return;
        }
    
        require_once 'CRM/Core/BAO/UFMatch.php';
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        /*
         * This does not return anything, so if we want to do anything further
         * to the CiviCRM Contact, we have to search for it all over again.
         */
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        CRM_Core_BAO_UFMatch::synchronize(
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          // User object.
          $user,
          // Update = true.
          TRUE,
          // CMS.
          'WordPress',
          // Contact Type.
          'Individual'
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       * When a WordPress user is deleted, delete the UFMatch record.
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       * Callback function for 'delete_user' hook.
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       *
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       * @since 4.6
       *
    
       * @param int $user_id The numerical ID of the WordPress user.
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       */
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
      public function delete_user_ufmatch($user_id) {
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
        if (!$this->civi->initialize()) {
          return;
        }
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        // Delete the UFMatch record.
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        require_once 'CRM/Core/BAO/UFMatch.php';
        CRM_Core_BAO_UFMatch::deleteUser($user_id);
    
      }
    
      /**
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       * Create anonymous role and define capabilities.
       *
       * Function to create 'anonymous_user' role, if 'anonymous_user' role is not
       * in the WordPress installation and assign minimum capabilities for all
       * WordPress roles.
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       *
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       * The legacy global scope function civicrm_wp_set_capabilities() is called
       * from upgrade_4_3_alpha1()
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       *
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       * @since 4.6
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       */
      public function set_wp_user_capabilities() {
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        // Define minimum capabilities (CiviCRM permissions).
        $default_min_capabilities = [
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          'access_all_custom_data' => 1,
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          'access_civimail_subscribe_unsubscribe_pages' => 1,
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          'access_uploaded_files' => 1,
          'make_online_contributions' => 1,
          'profile_create' => 1,
          'profile_edit' => 1,
          'profile_view' => 1,
          'register_for_events' => 1,
          'sign_civicrm_petition' => 1,
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          'view_event_info' => 1,
          'view_my_invoices' => 1,
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          'view_public_civimail_content' => 1,
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        ];
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        /**
         * Allow minimum capabilities to be filtered.
         *
         * @since 4.6
         *
         * @param array $default_min_capabilities The minimum capabilities.
         */
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        $min_capabilities = apply_filters('civicrm_min_capabilities', $default_min_capabilities);
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        // Assign the minimum capabilities to all WordPress roles.
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        $wp_roles = wp_roles();
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        foreach ($wp_roles->role_names as $role => $name) {
          $roleObj = $wp_roles->get_role($role);
          foreach ($min_capabilities as $capability_name => $capability_value) {
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
            if (!$roleObj->has_cap($capability_name)) {
              $roleObj->add_cap($capability_name);
            }
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          }
        }
    
        // Add the 'anonymous_user' role with minimum capabilities.
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        if (!in_array('anonymous_user', $wp_roles->roles)) {
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          add_role('anonymous_user', __('Anonymous User', 'civicrm'), $min_capabilities);
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       * Add CiviCRM access capabilities to WordPress roles.
       *
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       * This is called in register_hooks().
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       *
       * The legacy global scope function wp_civicrm_capability() is called by
       * postProcess() in civicrm/CRM/ACL/Form/WordPress/Permissions.php
       *
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       * @since 4.6
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       */
      public function set_access_capabilities() {
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        $wp_roles = wp_roles();
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        /**
         * Filter the default roles with access to CiviCRM.
         *
         * The 'access_civicrm' capability is the most basic CiviCRM capability and
         * is required to see the CiviCRM menu link in the WordPress Admin menu.
         *
         * @since 4.6
         *
         * @param array The default roles with access to CiviCRM.
         */
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        $roles = apply_filters('civicrm_access_roles', ['super admin', 'administrator']);
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        // Give access to CiviCRM to particular roles.
        foreach ($roles as $role) {
          $roleObj = $wp_roles->get_role($role);
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          if (
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
            is_object($roleObj) &&
            is_array($roleObj->capabilities) &&
            !array_key_exists('access_civicrm', $wp_roles->get_role($role)->capabilities)
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          ) {
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
            $wp_roles->add_cap($role, 'access_civicrm');
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       * Get CiviCRM Contact Type.
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       *
       * @since 4.6
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       *
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       * @param string $default The requested Contact Type.
       * @return string $ctype The computed Contact Type.
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       */
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
      public function get_civicrm_contact_type($default = NULL) {
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
        // Nonce verification not necessary here.
        // phpcs:disable WordPress.Security.NonceVerification.Recommended
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        /*
         * Here we are creating a new Contact.
         * Get the Contact Type from the POST variables if any.
         */
        if (isset($_REQUEST['ctype'])) {
    
          $ctype = sanitize_text_field(wp_unslash($_REQUEST['ctype']));
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        }
        elseif (
          isset($_REQUEST['edit']) &&
          isset($_REQUEST['edit']['ctype'])
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        ) {
    
          $ctype = sanitize_text_field(wp_unslash($_REQUEST['edit']['ctype']));
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        }
        else {
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          $ctype = $default;
        }
    
    
        // phpcs:enable WordPress.Security.NonceVerification.Recommended
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        if (
    
          $ctype !== 'Individual' &&
          $ctype !== 'Organization' &&
          $ctype !== 'Household'
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        ) {
          $ctype = $default;
        }
    
        return $ctype;
    
      }
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
      // ---------------------------------------------------------------------------
    
      /**
       * Refreshes all CiviCRM capabilities.
       *
       * @since 5.52
       */
      public function refresh_capabilities() {
    
        // Refresh capabilities assigned at plugin activation.
        $this->set_wp_user_capabilities();
    
        // Refresh access capabilities.
        $this->set_access_capabilities();
    
        /**
         * Fires when CiviCRM has refreshed the WordPress capabilities.
         *
         * @since 5.52
         */
        do_action('civicrm_capabilities_refreshed');
    
      }
    
      /**
       * Applies all CiviCRM capabilities to the custom WordPress role.
       *
       * @since 5.52
       */
      public function refresh_custom_role_capabilities() {
    
        // Get the role to apply all CiviCRM permissions to.
        $custom_role = $this->get_custom_role();
        if (empty($custom_role)) {
          return;
        }
    
        // Get all CiviCRM capabilities.
        $capabilities = $this->get_all_civicrm_capabilities();
    
        // Add the capabilities if not already added.
        foreach ($capabilities as $capability) {
          if (!$custom_role->has_cap($capability)) {
            $custom_role->add_cap($capability);
          }
        }
    
        // Delete capabilities that no longer exist.
        $this->delete_missing_capabilities($capabilities);
    
        /**
         * Fires when CiviCRM has refreshed the WordPress capabilities.
         *
         * @since 5.52
         *
         * @param array $capabilities The array of CiviCRM permissions converted to WordPress capabilities.
         * @param WP_Role $custom_role The WordPress role object.
         */
        do_action('civicrm_custom_role_capabilities_refreshed', $capabilities, $custom_role);
    
      }
    
      // ---------------------------------------------------------------------------
    
      /**
       * Gets all CiviCRM permissions converted to WordPress capabilities.
       *
       * @since 5.52
       *
       * @return array $capabilities The array of capabilities.
       */
      public function get_all_civicrm_capabilities() {
    
        // Init return.
        $capabilities = [];
    
        // Bail if no CiviCRM.
        if (!$this->civi->initialize()) {
          return $capabilities;
        }
    
        // Get all CiviCRM permissions, excluding disabled components and descriptions.
        $permissions = CRM_Core_Permission::basicPermissions(FALSE, FALSE);
    
        // Convert to WordPress capabilities.
        foreach ($permissions as $permission => $title) {
          $capabilities[] = CRM_Utils_String::munge(strtolower($permission));
        }
    
        /**
         * Filters the complete set of CiviCRM capabilities.
         *
         * @since 5.52
         *
         * @param array $capabilities The complete set of CiviCRM capabilities.
         */
        return apply_filters('civicrm_all_capabilities', $capabilities);
    
      }
    
      /**
       * Deletes CiviCRM capabilities when they no longer exist.
       *
       * This can happen when an Extension which had previously added permissions
       * is disabled or uninstalled, for example.
       *
       * Things can get a bit complicated here because capabilities can appear and
       * disappear (see above) and may have been assigned to other roles while they
       * were present. Deleting missing capabilities may therefore have unintended
       * consequences. Use the "civicrm_delete_missing_capabilities" filter if you
       * are sure that you want to delete missing capabilities.
       *
       * @since 5.52
       *
       * @param array $capabilities The complete set of CiviCRM capabilities.
       */
      public function delete_missing_capabilities($capabilities) {
    
        /**
         * Filters whether capabilities should be deleted.
         *
         * To enable deletion of capabilities, pass boolean true.
         *
         * @since 5.52
         *
         * @param bool $allow_delete False (disabled) by default.
         */
        $allow_delete = apply_filters('civicrm_delete_missing_capabilities', FALSE);
        if ($allow_delete === FALSE) {
          return;
        }
    
        // Read the stored CiviCRM permissions array.
        $stored = $this->get_saved_capabilities();
    
        // Save and bail if we don't have any stored.
        if (empty($stored)) {
          $this->save_capabilities($capabilities);
          return;
        }
    
        // Find the capabilities that are missing in the current CiviCRM data.
        $not_in_current = array_diff($stored, $capabilities);
    
        // Get the role to delete CiviCRM permissions from.
        $custom_role = $this->get_custom_role();
        if (empty($custom_role)) {
          return;
        }
    
        // Delete the capabilities if not already deleted.
        foreach ($capabilities as $capability) {
          if ($custom_role->has_cap($capability)) {
            $custom_role->remove_cap($capability);
          }
        }
    
        // Overwrite the current permissions array.
        $this->save_capabilities($capabilities);
    
      }
    
      /**
       * Gets the stored array of CiviCRM permissions formatted as WordPress capabilities.
       *
       * @since 5.52
       *
       * @return array $capabilities The array of stored capabilities.
       */
      public function get_saved_capabilities() {
    
        // Get capabilities from option.
        $capabilities = get_option('civicrm_permissions_sync_perms', 'false');
    
        // If no option exists, cast return as array.
        if ($capabilities === 'false') {
          $capabilities = [];
        }
    
        return $capabilities;
    
      }
    
      /**
       * Stores the array of CiviCRM permissions formatted as WordPress capabilities.
       *
       * @since 5.52
       *
       * @param array $capabilities The array of capabilities to store.
       */
      public function save_capabilities($capabilities) {
        update_option('civicrm_permissions_sync_perms', $capabilities);
      }
    
      // ---------------------------------------------------------------------------
    
      /**
       * Retrieves the config for the custom WordPress role.
       *
       * @since 5.52
       *
       * @return array $role_data The array of custom role data.
       */
      public function get_custom_role_data() {
    
        // Init default role data.
        $role_data = [
          'name' => $this->custom_role_name,
          'title' => __('CiviCRM Admin', 'civicrm'),
        ];
    
        /**
         * Filters the default CiviCRM custom role data.
         *
         * @since 5.52
         *
         * @param array $role_data The array of default CiviCRM custom role data.
         */
        $role_data = apply_filters('civicrm_custom_role_data', $role_data);
    
        return $role_data;
    
      }
    
      /**
       * Checks if the custom WordPress role exists.
       *
       * @since 5.52
       *
       * @return WP_Role|bool $custom_role The custom role if it exists, or false otherwise.
       */
      public function has_custom_role() {
    
        // Return the custom role if it already exists.
        $custom_role = $this->get_custom_role();
        if (!empty($custom_role)) {
          return $custom_role;
        }
    
        return FALSE;
    
      }
    
      /**
       * Retrieves the custom WordPress role.
       *
       * @since 5.52
       *
       * @return WP_Role|bool $custom_role The custom role, or false on failure.
       */
      public function get_custom_role() {
    
        // Get the default role data.
        $role_data = $this->get_custom_role_data();
    
        // Return the custom role if it exists.
        $wp_roles = wp_roles();
        if ($wp_roles->is_role($role_data['name'])) {
          $custom_role = $wp_roles->get_role($role_data['name']);
          return $custom_role;
        }
    
        return FALSE;
    
      }
    
      /**
       * Creates the custom WordPress role.
       *
       * We need a role to which we add all CiviCRM permissions. This makes all the
       * CiviCRM capabilities discoverable by other plugins.
       *
       * This method creates the role if it doesn't already exist by cloning the
       * built-in WordPress "administrator" role.
       *
       * Note: it's unlikely that you will want to grant this role to any WordPress
       * users - it is purely present to make capabilities discoverable.
       *
       * @since 5.52
       *
       * @return WP_Role|bool $custom_role The custom role, or false on failure.
       */
      public function create_custom_role() {
    
        // Return the custom role if it already exists.
        $custom_role = $this->has_custom_role();
        if (!empty($custom_role)) {
          return $custom_role;
        }
    
        // Bail if the "administrator" role doesn't exist.
        $wp_roles = wp_roles();
        if (!$wp_roles->is_role('administrator')) {
          return FALSE;
        }
    
        // Get the default role data.
        $role_data = $this->get_custom_role_data();
    
        // Add new role based on the "administrator" role.
        $admin = $wp_roles->get_role('administrator');
        $custom_role = add_role($role_data['name'], $role_data['title'], $admin->capabilities);
    
        // Return false if something went wrong.
        if (empty($custom_role)) {
          return FALSE;
        }
    
        return $custom_role;
    
      }
    
      /**
       * Deletes the custom WordPress role.
       *
       * @since 5.52
       */
      public function delete_custom_role() {
    
        // Bail if the custom role does not exist.
        $custom_role = $this->has_custom_role();
        if (empty($custom_role)) {
          return;
        }
    
        // Get the default role data.
        $role_data = $this->get_custom_role_data();
    
        // Okay, remove it.
        remove_role($role_data['name']);
    
      }
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    }