, Ruben Garcia * @since 1.4.0 */ // Exit if accessed directly if( !defined( 'ABSPATH' ) ) exit; /** * Initializes GamiPress on multisite installs * * @since 1.4.0 */ function gamipress_init_multisite() { global $wpdb; if( is_multisite() ) { // Update GamiPress database if network wide active if( gamipress_is_network_wide_active() ) { // Setup WordPress database tables GamiPress()->db->posts = $wpdb->base_prefix . 'posts'; GamiPress()->db->postmeta = $wpdb->base_prefix . 'postmeta'; GamiPress()->db->users = $wpdb->base_prefix . 'users'; GamiPress()->db->usermeta = $wpdb->base_prefix . 'usermeta'; // Setup GamiPress database tables GamiPress()->db->logs = $wpdb->base_prefix . 'gamipress_logs'; GamiPress()->db->logs_meta = $wpdb->base_prefix . 'gamipress_logs_meta'; GamiPress()->db->user_earnings = $wpdb->base_prefix . 'gamipress_user_earnings'; GamiPress()->db->user_earnings_meta = $wpdb->base_prefix . 'gamipress_user_earnings_meta'; } } } add_action( 'gamipress_init', 'gamipress_init_multisite', 1 ); /** * Create array of blog ids in network * * @since 1.0.0 * * @return array Array of blog_ids */ function gamipress_get_network_site_ids() { global $wpdb; $cache = gamipress_get_cache( 'gamipress_blog_ids', false, false ); if( is_multisite() ) { // If result already cached, return it if( is_array( $cache ) ) { $blog_ids = $cache; } else { $blog_ids = $wpdb->get_results( "SELECT blog_id FROM " . $wpdb->base_prefix . "blogs" ); gamipress_set_cache( 'gamipress_blog_ids', $blog_ids ); } foreach ($blog_ids as $key => $value ) { $sites[] = $value->blog_id; } } else { $sites[] = get_current_blog_id(); } return $sites; } /** * Replace per site queries to root site when GamiPress is active network wide * * @since 1.4.0 * * @param string $request * @param WP_Query $wp_query * * @return string */ function gamipress_network_wide_post_request( $request, $wp_query ) { global $wpdb; // If GamiPress is active network wide and we are not in main site, then filter all queries to our post types if( gamipress_is_network_wide_active() && ! is_main_site() && isset( $wp_query->query_vars['post_type'] ) ) { $post_type = $wp_query->query_vars['post_type']; if( is_array( $post_type ) ) { $post_type = $post_type[0]; } if( in_array( $post_type, array( 'points-type', 'achievement-type', 'rank-type' ) ) || in_array( $post_type, gamipress_get_requirement_types_slugs() ) || in_array( $post_type, gamipress_get_achievement_types_slugs() ) || in_array( $post_type, gamipress_get_rank_types_slugs() ) ) { // Replace {prefix}{site}posts to {prefix}posts $request = str_replace( $wpdb->posts, "{$wpdb->base_prefix}posts", $request ); // Replace {prefix}{site}postmeta to {prefix}postmeta $request = str_replace( $wpdb->postmeta, "{$wpdb->base_prefix}postmeta", $request ); } } return $request; } add_filter( 'posts_request', 'gamipress_network_wide_post_request', 10, 2 ); /** * Check if GamiPress is network wide active * * @since 1.4.0 * * @return bool */ function gamipress_is_network_wide_active() { // Available filter to disable network data centralization if( apply_filters( 'gamipress_disable_network_data_centralization', false ) ) { GamiPress()->network_wide_active = false; return false; } if( GamiPress()->network_wide_active === null ) { if( ! is_multisite() ) { // Set to false if not is a multisite install GamiPress()->network_wide_active = false; } else { // Normally the is_plugin_active_for_network() function is only available in the admin area if ( ! function_exists( 'is_plugin_active_for_network' ) ) { require_once ABSPATH . '/wp-admin/includes/plugin.php'; } GamiPress()->network_wide_active = is_plugin_active_for_network( 'gamipress/gamipress.php' ); } } return GamiPress()->network_wide_active; } /** * Check if a plugin is active on any site of network * * @since 1.4.8 * * @param string $plugin Path to the main plugin file from plugins directory. * * @return bool */ function gamipress_is_plugin_active_on_network( $plugin ) { $active_sites = gamipress_get_plugin_active_sites( $plugin ); return ! empty( $active_sites ); } /** * Get all sites a plugin is active * * @since 1.4.8 * * @param string $plugin Path to the main plugin file from plugins directory. * * @return array */ function gamipress_get_plugin_active_sites( $plugin ) { // Bail if not is a multisite install if( ! is_multisite() ) { return array( get_current_blog_id() ); } // If plugin is active network wide, return all sites if( is_plugin_active_for_network( $plugin ) ) { return gamipress_get_network_site_ids(); } $sites_active = array(); // Store a copy of the original ID for later $blog_id = get_current_blog_id(); // Loop through all sites foreach( gamipress_get_network_site_ids() as $site_blog_id ) { // Get active plugins in this site and check if plugin is active $active_plugins = gamipress_get_active_plugins_in_site( $site_blog_id ); if( in_array( $plugin, $active_plugins, true ) ) { $sites_active[] = $site_blog_id; } } // Restore the original blog so the sky doesn't fall if ( $blog_id != get_current_blog_id() && is_multisite() ) { restore_current_blog(); } return $sites_active; } /** * Get active plugins in a site (used to cache results) * * @since 1.4.8 * * @param int $site_blog_id Site ID. * * @return array */ function gamipress_get_active_plugins_in_site( $site_blog_id = null ) { if( $site_blog_id === null ) { $site_blog_id = get_current_blog_id(); } $cache = gamipress_get_cache( 'gamipress_active_plugins', array(), false ); if( ! is_array( $cache ) ) { $cache = array(); } // If result already cached, return it if( isset( $cache[$site_blog_id] ) ) { return $cache[$site_blog_id]; } // Store a copy of the original ID for later $blog_id = get_current_blog_id(); // If we're polling a different blog, switch to it if ( $blog_id != $site_blog_id ) { switch_to_blog( $site_blog_id ); } // Get active plugins in this site $cache[$site_blog_id] = (array) get_option( 'active_plugins', array() ); // Restore the original blog if ( $blog_id != $site_blog_id && is_multisite() ) { restore_current_blog(); } gamipress_set_cache( 'gamipress_active_plugins', $cache ); return $cache[$site_blog_id]; } /** * On save settings, also update GamiPress site option to make it network wide accessible * * @since 1.4.0 * * @param string $override * @param mixed $options * @param CMB2 $cmb * * @return mixed */ function gamipress_save_network_settings( $override, $options, $cmb ) { if( gamipress_is_network_wide_active() ) { // Set options as network option update_site_option( 'gamipress_settings', $options ); } return $override; } add_action( 'cmb2_override_option_save_gamipress_settings', 'gamipress_save_network_settings', 10, 3 ); /** * Filter the post edit link to return edit link from main site * * @since 1.4.0 * * @param string $link The edit link. * @param int $post_id Post ID. * @param string $context The link context. If set to 'display' then ampersands are encoded. * * @return string */ function gamipress_main_site_edit_post_link( $link, $post_id, $context ) { if( ! gamipress_is_network_wide_active() || is_main_site() ) { return $link; } // Try to get the post type of current site $post_type = get_post_type( $post_id ); if( ! $post_type ) { // If this post not exists on current site, then get his post type from main site $post_type = gamipress_get_post_type( $post_id ); } if( in_array( $post_type, array( 'points-type', 'achievement-type', 'rank-type' ) ) || in_array( $post_type, gamipress_get_requirement_types_slugs() ) || in_array( $post_type, gamipress_get_achievement_types_slugs() ) || in_array( $post_type, gamipress_get_rank_types_slugs() ) ) { $post_type_object = get_post_type_object( $post_type ); if ( 'display' == $context ) $action = '&action=edit'; else $action = '&action=edit'; $link = get_admin_url( get_main_site_id(), sprintf( $post_type_object->_edit_link . $action, $post_id ) ); } return $link; } add_filter( 'get_edit_post_link', 'gamipress_main_site_edit_post_link', 10, 3 ); /** * Override CMB2 can save function to avoid issues on multisite installs * * @since 1.4.9 * * @param bool $can_save * @param object $cmb * * @return bool */ function gamipress_network_can_save_meta_boxes( $can_save, $cmb ) { global $post; if( is_multisite() && $post ) { // Custom can save check $can_save = ( $cmb->prop( 'save_fields' ) // check nonce && isset( $_POST[ $cmb->nonce() ] ) && wp_verify_nonce( $_POST[ $cmb->nonce() ], $cmb->nonce() ) // check if autosave && ! ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) // get the metabox types & compare it to this type && ( in_array( $post->post_type, $cmb->box_types() ) ) // Don't do updates during a switch-to-blog instance. //&& ! ( is_multisite() && ms_is_switched() ) // Removed, ms_is_switched() always returns true ); } return $can_save; } add_filter( 'cmb2_can_save', 'gamipress_network_can_save_meta_boxes', 10, 2 ); /** * Force to clean switched sites global to avoid issues with other plugins (since wp_restore_blog() doesn't cleans it) * * @since 1.5.7 */ function gamipress_fix_network_wp_insert_post() { if ( is_multisite() && ms_is_switched() ) { // Force to clean switched sites global $GLOBALS['_wp_switched_stack'] = array(); } } add_action( 'wp_insert_post', 'gamipress_fix_network_wp_insert_post', 9 ); /** * Switch to main site * * @since 1.6.3 * @updated 2.1.0 Update the $gamipress_original_blog_id global var * * @return int The blog ID before switch to main site */ function gamipress_switch_to_main_site() { global $gamipress_original_blog_id; $gamipress_original_blog_id = get_current_blog_id(); // Switch to main site if not already on main site if( ! is_main_site() ) { switch_to_blog( get_main_site_id() ); } return $gamipress_original_blog_id; } /** * Switch to main site just if GamiPress is network wide active * * @since 1.6.3 * * @return int The blog ID before switch to main site */ function gamipress_switch_to_main_site_if_network_wide_active() { // Switch to main site if GamiPress is network wide active if( gamipress_is_network_wide_active() ) { return gamipress_switch_to_main_site(); } return get_current_blog_id(); } /** * Get the original site ID even if GamiPress has switched to main site * * @since 2.1.0 * * @return int The blog ID before switch to main site */ function gamipress_get_original_site_id() { global $gamipress_original_blog_id; return ( $gamipress_original_blog_id ? $gamipress_original_blog_id : get_current_blog_id() ); }