Services tab add_filter('aam_service_list_filter', function ($services) { $services[] = array( 'title' => __('Multisite Settings Sync', AAM_KEY), 'description' => __('Automatically synchronize changes to the list of roles and capabilities as well as all access settings (if configured accordingly).', AAM_KEY), 'setting' => self::FEATURE_FLAG ); return $services; }, 20); } if (AAM_Core_Config::get(self::FEATURE_FLAG, true) && is_multisite()) { $this->initializeHooks(); } } /** * Initialize multisite sync hooks * * @return void * * @since 6.3.0 Optimized for Multisite setup * @since 6.2.2 Hooks to the setting clearing and policy table list * @since 6.2.0 Initial implementation of the method * * @access protected * @version 6.3.0 */ protected function initializeHooks() { $roles = AAM_Core_API::getRoles(); if (is_main_site()) { // Any changes to the user_roles option should be replicated add_action('update_option_' . $roles->role_key, function($old, $value) { $this->syncUpdatedOption('%suser_roles', $value); }, 10, 2); add_action('update_option', function($option, $old, $value) { if ($this->syncing === false) { $this->syncing = true; $list = array( AAM_Core_Config::DB_OPTION, AAM_Core_ConfigPress::DB_OPTION, AAM_Core_AccessSettings::DB_OPTION ); if (in_array($option, $list, true)) { $this->syncUpdatedOption($option, $value); } $this->syncing = false; } }, 10, 3); add_action('aam_top_right_column_action', function() { echo AAM_Backend_View::loadPartial('multisite-sync-notification'); }); add_action('add_option', function($option, $value) { if ($this->syncing === false) { $this->syncing = true; $list = array( AAM_Core_Config::DB_OPTION, AAM_Core_ConfigPress::DB_OPTION, AAM_Core_AccessSettings::DB_OPTION ); if (in_array($option, $list, true)) { $this->syncUpdatedOption($option, $value); } $this->syncing = false; } }, 10, 2); add_action('aam_clear_settings_action', function($options) { foreach($options as $option) { $this->syncDeletedOption($option); } }, PHP_INT_MAX); } add_filter('wp_insert_post_data', function($data) { if ( isset($data['post_type']) && ($data['post_type'] === AAM_Service_AccessPolicy::POLICY_CPT) ) { switch_to_blog(get_main_site_id()); } return $data; }); add_action('aam_pre_policy_fetch_action', function() { $this->switch_back_blog_id = get_current_blog_id(); switch_to_blog(get_main_site_id()); }); add_action('aam_post_policy_fetch_action', function() { switch_to_blog($this->switch_back_blog_id); }); add_action('wp', function() { if (apply_filters('aam_allowed_site_filter', true) === false) { wp_die('Access Denied', 'aam_access_denied'); } }, 999); } /** * Sync option across all sites * * @param string $option * @param mixed $value * * @return void * * @since 6.2.2 Refactored how the list of sites is fetched * @since 6.2.0 Initial implementation of the method * * @access protected * @global WPDB $wpdb * @version 6.2.2 */ protected function syncUpdatedOption($option, $value) { global $wpdb; foreach($this->getSitList() as $site) { if ($this->isSyncDisabled($site->blog_id) !== true) { AAM_Core_API::updateOption( str_replace('%s', $wpdb->get_blog_prefix($site->blog_id), $option), $value, $site->blog_id ); } } } /** * Sync deleted option across all sites * * @param string $option * * @return void * * @access protected * @global WPDB $wpdb * @version 6.3.0 */ protected function syncDeletedOption($option) { global $wpdb; foreach($this->getSitList() as $site) { if ($this->isSyncDisabled($site->blog_id) !== true) { AAM_Core_API::deleteOption( str_replace('%s', $wpdb->get_blog_prefix($site->blog_id), $option), $site->blog_id ); } } } /** * Get list of sites * * @return array * * @access protected * @version 6.2.2 */ protected function getSitList() { return get_sites(array( 'number' => PHP_INT_MAX, 'offset' => 0, 'orderby' => 'id', 'site__not_in' => array_merge( $this->getExcludedBlogs(), array(get_current_blog_id()) ) )); } /** * Get the list of excluded blogs from sync process * * @return array * * @access protected * @version 6.2.0 */ protected function getExcludedBlogs() { $excluded = array(); $config = AAM::api()->getConfig('multisite.sync.exclude.blogs', array()); if (is_string($config)) { $excluded = explode(',', $config); } elseif (is_array($config)) { $excluded = array_filter($config, function($site) { return is_numeric($site); }); } return $excluded; } /** * Check if blog has sync service disabled * * @param int $blog_id * * @return boolean * * @access protected * @version 6.3.0 */ protected function isSyncDisabled($blog_id) { $config = AAM_Core_API::getOption( AAM_Core_Config::DB_OPTION, array(), $blog_id ); return isset($config[self::FEATURE_FLAG]) && ($config[self::FEATURE_FLAG] === false); } } if (defined('AAM_KEY')) { AAM_Service_Multisite::bootstrap(); }