├── README.md ├── bp-multiblog-mode.php ├── includes ├── actions.php ├── admin.php ├── functions.php ├── index.php ├── settings.php └── sub-actions.php ├── index.php └── readme.txt /README.md: -------------------------------------------------------------------------------- 1 | # BP Multiblog Mode # 2 | 3 | Enable and customize BuddyPress on other sites in your network than the root blog. 4 | 5 | ## Description ## 6 | 7 | > This WordPress plugin requires at least [WordPress](https://wordpress.org) 4.6 and [BuddyPress](https://buddypress.org) 2.7. 8 | 9 | Run BuddyPress on your network subsites, but not all of them. Instead of defining the BP_ENABLE_MULTIBLOG constant, with this plugin you can choose on which sites BuddyPress acts as if BP_ENABLE_MULTIBLOG was defined. 10 | 11 | In addition, this plugin allows you to: 12 | 13 | * Limit the BuddyPress implementation to site members 14 | * Limit Activity Stream items to those belonging to the current site 15 | * Define Extended Profile field groups per site 16 | * Use BuddyPress avatars and/or other file uploads from the current site 17 | 18 | Note that you need to have BuddyPress network-activated in your Multisite installation for this plugin to work. 19 | 20 | ## Installation ## 21 | 22 | If you download BP Multiblog Mode manually, make sure it is uploaded to "/wp-content/plugins/bp-multiblog-mode/". 23 | 24 | Activate BP Multiblog Mode in the "Plugins" network admin panel using the "Network Activate" link. You need to use WordPress Multisite, for this plugin to work. Additionally, you need to have BuddyPress network-activated in you Multisite installation, and not have defined the `BP_ENABLE_MULTIBLOG` constant manually. 25 | 26 | ## Updates ## 27 | 28 | This plugin is not hosted in the official WordPress repository. Instead, updating is supported through use of the [GitHub Updater](https://github.com/afragen/github-updater/) plugin by @afragen and friends. 29 | 30 | ## Contribution ## 31 | 32 | You can contribute to the development of this plugin by [opening a new issue](https://github.com/lmoffereins/bp-multiblog-mode/issues/) to report a bug or request a feature in the plugin's GitHub repository. -------------------------------------------------------------------------------- /bp-multiblog-mode.php: -------------------------------------------------------------------------------- 1 | setup_globals(); 51 | $instance->includes(); 52 | $instance->setup_actions(); 53 | } 54 | 55 | return $instance; 56 | } 57 | 58 | /** 59 | * Prevent the plugin class from being loaded more than once 60 | */ 61 | private function __construct() { /* Nothing to do */ } 62 | 63 | /** Private methods *************************************************/ 64 | 65 | /** 66 | * Setup default class globals 67 | * 68 | * @since 1.0.0 69 | */ 70 | private function setup_globals() { 71 | 72 | /** Versions **********************************************************/ 73 | 74 | $this->version = '1.0.0'; 75 | 76 | /** Paths *************************************************************/ 77 | 78 | // Setup some base path and URL information 79 | $this->file = __FILE__; 80 | $this->basename = plugin_basename( $this->file ); 81 | $this->plugin_dir = plugin_dir_path( $this->file ); 82 | $this->plugin_url = plugin_dir_url ( $this->file ); 83 | 84 | // Includes 85 | $this->includes_dir = trailingslashit( $this->plugin_dir . 'includes' ); 86 | $this->includes_url = trailingslashit( $this->plugin_url . 'includes' ); 87 | 88 | // Languages 89 | $this->lang_dir = trailingslashit( $this->plugin_dir . 'languages' ); 90 | 91 | /** Identifiers *******************************************************/ 92 | 93 | $this->root_blog_id = defined( 'BP_ROOT_BLOG' ) ? (int) BP_ROOT_BLOG : get_network()->site_id; 94 | 95 | /** Misc **************************************************************/ 96 | 97 | $this->extend = new stdClass(); 98 | $this->domain = 'bp-multiblog-mode'; 99 | } 100 | 101 | /** 102 | * Include the required files 103 | * 104 | * @since 1.0.0 105 | */ 106 | private function includes() { 107 | 108 | // Core 109 | require( $this->includes_dir . 'functions.php' ); 110 | require( $this->includes_dir . 'sub-actions.php' ); 111 | 112 | // Admin 113 | if ( is_admin() ) { 114 | require( $this->includes_dir . 'admin.php' ); 115 | require( $this->includes_dir . 'settings.php' ); 116 | } 117 | 118 | // Hooks 119 | if ( $this->can_multiblog() ) { 120 | require( $this->includes_dir . 'actions.php' ); 121 | } 122 | } 123 | 124 | /** 125 | * Setup default actions and filters 126 | * 127 | * @since 1.0.0 128 | */ 129 | private function setup_actions() { 130 | 131 | // Add actions to plugin activation and deactivation hooks 132 | add_action( 'activate_' . $this->basename, 'bp_multiblog_mode_activation' ); 133 | add_action( 'deactivate_' . $this->basename, 'bp_multiblog_mode_deactivation' ); 134 | 135 | // Load textdomain 136 | add_action( 'plugins_loaded', array( $this, 'load_textdomain' ), 20 ); 137 | 138 | // Do Multiblog for the enabled site 139 | if ( $this->can_multiblog() && bp_multiblog_mode_is_enabled() ) { 140 | add_filter( 'bp_get_root_blog_id', 'get_current_blog_id' ); 141 | add_filter( 'bp_is_multiblog_mode', '__return_true' ); 142 | 143 | // Reset actual root blog where necessary 144 | add_filter( 'bp_get_taxonomy_term_site_id', array( $this, 'taxonomy_term_site_id' ), 1 ); 145 | } 146 | } 147 | 148 | /** Plugin **********************************************************/ 149 | 150 | /** 151 | * Return whether the plugin logic can be run 152 | * 153 | * Checks whether: 154 | * - BP is network activated 155 | * - BP_ENABLE_MULTIBLOG is not enabled through the constant 156 | * - there are multiple sites in the network 157 | * 158 | * @since 1.0.0 159 | * 160 | * @return bool Can we do Multiblog? 161 | */ 162 | public function can_multiblog() { 163 | return bp_is_network_activated() && ! ( defined( 'BP_ENABLE_MULTIBLOG' ) && BP_ENABLE_MULTIBLOG ) && (int) get_blog_count() > 1; 164 | } 165 | 166 | /** 167 | * Load the translation file for current language. Checks the languages 168 | * folder inside the plugin first, and then the default WordPress 169 | * languages folder. 170 | * 171 | * Note that custom translation files inside the plugin folder will be 172 | * removed on plugin updates. If you're creating custom translation 173 | * files, please use the global language folder. 174 | * 175 | * @since 1.0.0 176 | * 177 | * @uses apply_filters() Calls 'plugin_locale' with {@link get_locale()} value 178 | * @uses load_textdomain() To load the textdomain 179 | * @uses load_plugin_textdomain() To load the textdomain 180 | */ 181 | public function load_textdomain() { 182 | 183 | // Traditional WordPress plugin locale filter 184 | $locale = apply_filters( 'plugin_locale', get_locale(), $this->domain ); 185 | $mofile = sprintf( '%1$s-%2$s.mo', $this->domain, $locale ); 186 | 187 | // Setup paths to current locale file 188 | $mofile_local = $this->lang_dir . $mofile; 189 | $mofile_global = WP_LANG_DIR . '/bp-multiblog-mode/' . $mofile; 190 | 191 | // Look in global /wp-content/languages/bp-multiblog-mode folder 192 | load_textdomain( $this->domain, $mofile_global ); 193 | 194 | // Look in local /wp-content/plugins/bp-multiblog-mode/languages/ folder 195 | load_textdomain( $this->domain, $mofile_local ); 196 | 197 | // Look in global /wp-content/languages/plugins/ 198 | load_plugin_textdomain( $this->domain ); 199 | } 200 | 201 | /** Public methods **************************************************/ 202 | 203 | /** 204 | * Modify the site ID where the taxonomy terms live 205 | * 206 | * @since 1.0.0 207 | * 208 | * @param int $site_id Site ID 209 | * @return int Site ID 210 | */ 211 | public function taxonomy_term_site_id( $site_id ) { 212 | 213 | // Use the root's registered taxonomy terms 214 | if ( bp_multiblog_mode_use_root_taxonomy_terms() ) { 215 | $site_id = bp_multiblog_mode_get_root_blog_id(); 216 | } 217 | 218 | return $site_id; 219 | } 220 | } 221 | 222 | /** 223 | * Return single instance of this main plugin class 224 | * 225 | * @since 1.0.0 226 | * 227 | * @return BP Multiblog Mode class 228 | */ 229 | function bp_multiblog_mode() { 230 | return BP_Multiblog_Mode::instance(); 231 | } 232 | 233 | // Initiate plugin on bp_after_setup_actions. Only on Multisite 234 | if ( is_multisite() ) { 235 | add_action( 'bp_after_setup_actions', 'bp_multiblog_mode' ); 236 | } 237 | 238 | endif; // class_exists 239 | -------------------------------------------------------------------------------- /includes/actions.php: -------------------------------------------------------------------------------- 1 | setup_globals(); 28 | $this->setup_actions(); 29 | } 30 | 31 | /** 32 | * Define default class globals 33 | * 34 | * @since 1.0.0 35 | */ 36 | private function setup_globals() { 37 | $this->parent_page = bp_core_do_network_admin() ? 'settings.php' : 'options-general.php'; 38 | $this->settings_page = is_network_admin() ? 'bp-multiblog-mode-network' : 'bp-multiblog-mode'; 39 | $this->minimum_capability = bp_core_do_network_admin() ? 'manage_network_options' : 'manage_options'; 40 | $this->plugin_screen_id = 'settings_page_' . $this->settings_page; 41 | } 42 | 43 | /** 44 | * Define default actions and filters 45 | * 46 | * @since 1.0.0 47 | */ 48 | private function setup_actions() { 49 | 50 | // For backcompat, consider admin hook 51 | $admin_menus_hook = function_exists( 'bp_core_get_admin_settings_tabs' ) ? 'bp_admin_submenu_pages' : bp_core_admin_hook(); 52 | 53 | // Admin page 54 | add_action( $admin_menus_hook, array( $this, 'admin_menus' ) ); 55 | add_filter( 'bp_admin_head', array( $this, 'admin_head' ), 999 ); 56 | add_filter( 'bp_core_get_admin_settings_tabs', array( $this, 'admin_tabs' ) ); 57 | add_filter( 'bp_core_get_admin_tabs', array( $this, 'admin_tabs' ), 10, 2 ); 58 | 59 | // Styling 60 | add_action( 'bp_admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) ); 61 | 62 | // Settings 63 | add_action( 'bp_admin_init', array( $this, 'register_settings' ) ); 64 | add_filter( 'bp_map_meta_caps', array( $this, 'map_settings_meta_caps' ), 10, 4 ); 65 | 66 | // XProfile 67 | add_action( 'xprofile_group_after_submitbox', array( $this, 'xprofile_group_sites_metabox' ) ); 68 | add_action( 'xprofile_group_after_save', array( $this, 'xprofile_save_group_sites' ) ); 69 | add_action( 'xprofile_admin_group_action', array( $this, 'xprofile_group_admin_label' ) ); 70 | } 71 | 72 | /** Admin Page ******************************************************/ 73 | 74 | /** 75 | * Register network admin menu elements 76 | * 77 | * @since 1.0.0 78 | * 79 | * @param array $submenu_pages The BP_Admin submenu pages passed by reference 80 | */ 81 | public function admin_menus( &$submenu_pages = array() ) { 82 | 83 | // Bail when user cannot manage 84 | if ( ! bp_current_user_can( $this->minimum_capability ) ) 85 | return; 86 | 87 | // Bail when the page has no settings 88 | if ( ! bp_multiblog_mode_admin_page_has_settings( $this->settings_page ) ) 89 | return; 90 | 91 | $hooks = array(); 92 | 93 | // Core settings page 94 | $settings_page = add_submenu_page( 95 | $this->parent_page, 96 | esc_html__( 'BuddyPress Multiblog', 'bp-multiblog-mode' ), 97 | esc_html__( 'Multiblog', 'bp-multiblog-mode' ), 98 | $this->minimum_capability, 99 | 'bp-multiblog-mode', 100 | 'bp_multiblog_mode_admin_settings_page' 101 | ); 102 | 103 | $hooks[] = $settings_page; 104 | 105 | // Blend in BP's administration 106 | foreach ( $hooks as $hook ) { 107 | add_action( "admin_head-{$hook}", 'bp_core_modify_admin_menu_highlight' ); 108 | } 109 | 110 | // Add to navigation tabs 111 | if ( isset( $submenu_pages['settings'] ) ) { 112 | $submenu_pages['settings']['bp-multiblog-mode'] = $settings_page; 113 | } 114 | } 115 | 116 | /** 117 | * Hide the plugin page from the admin menu 118 | * 119 | * @see BP_Admin::admin_head() 120 | * 121 | * @since 1.0.0 122 | */ 123 | public function admin_head() { 124 | remove_submenu_page( $this->parent_page, 'bp-multiblog-mode' ); 125 | } 126 | 127 | /** 128 | * Modify the admin tabs of BP's admin page 129 | * 130 | * @since 1.0.0 131 | * 132 | * @param array $tabs Page tags 133 | * @param string $context Tabs context. Defaults to 'settings' for backcompat 134 | * @return array Page tabs 135 | */ 136 | public function admin_tabs( $tabs, $context = 'settings' ) { 137 | 138 | // Prepare tabs 139 | $settings_tabs = array(); 140 | $tools_tabs = array(); 141 | 142 | // Append Multiblog Mode page tab, when settings are registered 143 | if ( bp_multiblog_mode_admin_page_has_settings( $this->settings_page ) ) { 144 | $settings_tabs[] = array( 145 | 'id' => 'bp-multiblog-mode', 146 | 'href' => bp_get_admin_url( add_query_arg( array( 'page' => 'bp-multiblog-mode' ), 'admin.php' ) ), 147 | 'name' => esc_html__( 'Multiblog', 'bp-multiblog-mode' ), 148 | ); 149 | } 150 | 151 | // Add settings tabs 152 | if ( 'settings' === $context ) { 153 | foreach ( $settings_tabs as $tab ) { 154 | 155 | // For backcompat, only add tab once 156 | if ( ! isset( $tabs[ $tab['id'] ] ) ) { 157 | $tabs[ $tab['id'] ] = $tab; 158 | } 159 | } 160 | 161 | // Add tools tabs 162 | } else if ( 'tools' === $context ) { 163 | foreach ( $tools_tabs as $tab ) { 164 | 165 | // For backcompat, only add tab once 166 | if ( ! isset( $tabs[ $tab['id'] ] ) ) { 167 | $tabs[ $tab['id'] ] = $tab; 168 | } 169 | } 170 | } 171 | 172 | return $tabs; 173 | } 174 | 175 | /** Styling *********************************************************/ 176 | 177 | /** 178 | * Add general styling to the admin area 179 | * 180 | * @since 1.0.0 181 | */ 182 | public function enqueue_scripts() { 183 | 184 | // Define local variable(s) 185 | $styles = array(); 186 | $screen = get_current_screen(); 187 | $network = is_network_admin() ? '-network' : ''; 188 | 189 | // Network admin page 190 | if ( $screen->id === $this->plugin_screen_id ) { 191 | 192 | // Mimic post inline-edit styles for .cat-checklist 193 | $styles[] = '.form-table .widefat th, .form-table .widefat td { padding: 8px 10px; font-weight: normal; }'; 194 | $styles[] = '.form-table .widefat .check-column { width: 2.2em; }'; 195 | $styles[] = '.form-table p + .cat-checklist { margin-top: 6px; }'; 196 | $styles[] = '.form-table .widefat .column-blogname strong { display: block; margin-bottom: .2em; font-size: 14px; }'; 197 | $styles[] = '.form-table .widefat .column-blogname strong ~ span { font-size: 13px; font-style: italic; line-height: 1.5em; }'; 198 | 199 | // Small screens 200 | $styles[] = '@media screen and (max-width: 782px) {'; 201 | $styles[] = '.form-table .widefat th, .form-table .widefat td { display: table-cell; }'; 202 | $styles[] = '}'; 203 | 204 | // BP XProfile admin page 205 | } elseif ( "users_page_bp-profile-setup{$network}" === $screen->id ) { 206 | 207 | // Group detail 208 | $styles[] = '.wp-core-ui .tab-toolbar .button.group-sites { color: #555 !important; }'; 209 | $styles[] = '.wp-core-ui .tab-toolbar .button.group-sites-error { color: #f00 !important; border-color: #f00 !important; }'; 210 | 211 | // Add/edit group 212 | if ( isset( $_GET['mode'] ) && in_array( $_GET['mode'], array( 'add_group', 'edit_group' ) ) ) { 213 | 214 | // Sites metabox 215 | $styles[] = '#bp-multiblog-mode_sitediv label { margin: .5em 0; display: block; }'; 216 | $styles[] = '#bp-multiblog-mode_sitediv label .description { padding-left: 25px; display: block; opacity: .7; }'; 217 | 218 | // Small screens 219 | $styles[] = '@media screen and (max-width: 782px) {'; 220 | $styles[] = '#bp-multiblog-mode_sitediv label { max-width: none; float: none; margin: 1em 0; font-size: 16px; }'; 221 | $styles[] = '#bp-multiblog-mode_sitediv label .description { padding: 0 0 0 34px; }'; 222 | $styles[] = '}'; 223 | } 224 | } 225 | 226 | if ( ! empty( $styles ) ) { 227 | wp_add_inline_style( 'bp-admin-common-css', implode( "\n", $styles ) ); 228 | } 229 | } 230 | 231 | /** Settings ********************************************************/ 232 | 233 | /** 234 | * Register plugin settings 235 | * 236 | * @since 1.0.0 237 | */ 238 | public function register_settings() { 239 | 240 | // Bail if no sections available 241 | $sections = bp_multiblog_mode_admin_get_settings_sections(); 242 | if ( empty( $sections ) ) 243 | return false; 244 | 245 | // Loop through sections 246 | foreach ( (array) $sections as $section_id => $section ) { 247 | 248 | // Only proceed if current user can see this section 249 | if ( ! current_user_can( $section_id ) ) 250 | continue; 251 | 252 | // Only add section and fields if section has fields 253 | $fields = bp_multiblog_mode_admin_get_settings_fields_for_section( $section_id ); 254 | if ( empty( $fields ) ) 255 | continue; 256 | 257 | // Define section page 258 | if ( ! empty( $section['page'] ) ) { 259 | $page = $section['page']; 260 | } else { 261 | $page = 'bp-multiblog-mode'; 262 | } 263 | 264 | // Add the section 265 | add_settings_section( $section_id, $section['title'], $section['callback'], $page ); 266 | 267 | // Loop through fields for this section 268 | foreach ( (array) $fields as $field_id => $field ) { 269 | 270 | // Add the field 271 | if ( ! empty( $field['callback'] ) && ! empty( $field['title'] ) ) { 272 | add_settings_field( $field_id, $field['title'], $field['callback'], $page, $section_id, $field['args'] ); 273 | } 274 | 275 | // Register the setting 276 | if ( ! empty( $field['sanitize_callback'] ) ) { 277 | register_setting( $page, $field_id, $field['sanitize_callback'] ); 278 | } 279 | } 280 | } 281 | } 282 | 283 | /** 284 | * Map caps for the plugin settings 285 | * 286 | * @since 1.0.0 287 | * 288 | * @param array $caps Mapped caps 289 | * @param string $cap Required capability name 290 | * @param int $user_id User ID 291 | * @param array $args Additional arguments 292 | * @return array Mapped caps 293 | */ 294 | public function map_settings_meta_caps( $caps = array(), $cap = '', $user_id = 0, $args = array() ) { 295 | 296 | // Check the required capability 297 | switch ( $cap ) { 298 | 299 | // Settings 300 | case 'bp_multiblog_mode_settings_general_network' : 301 | case 'bp_multiblog_mode_settings_general' : 302 | $caps = array( $this->minimum_capability ); 303 | break; 304 | } 305 | 306 | return $caps; 307 | } 308 | 309 | /** XProfile ********************************************************/ 310 | 311 | /** 312 | * Add XProfile field group Sites metabox 313 | * 314 | * @since 1.0.0 315 | * 316 | * @param BP_XProfile_Group $group 317 | */ 318 | public function xprofile_group_sites_metabox( $group ) { 319 | 320 | // The primary field group is for all, so bail 321 | if ( 1 === (int) $group->id ) 322 | return; 323 | 324 | // Bail when no sites are Multiblog enabled 325 | if ( ! $sites = bp_multiblog_mode_get_enabled_sites() ) 326 | return; 327 | 328 | // Prepend the root site 329 | array_unshift( $sites, get_site( bp_multiblog_mode_get_root_blog_id() ) ); 330 | 331 | // Get the group's sites 332 | $group_sites = bp_multiblog_mode_xprofile_get_group_sites( $group->id ); 333 | 334 | ?> 335 | 336 |
337 |

338 |
339 |

340 | 341 | 357 |

358 |
359 | 360 | 361 |
362 | 363 | id, 'group', 'multiblog_site' ); 388 | 389 | /* 390 | * We interpret an empty array as disassociating the group from all sites. This is 391 | * represented internally with the '_none' flag. 392 | */ 393 | if ( empty( $group_sites ) ) { 394 | bp_xprofile_add_meta( $group->id, 'group', 'multiblog_site', '_none' ); 395 | } 396 | 397 | /* 398 | * Unrestricted groups are represented in the database as having no 'multiblog_site'. 399 | * We detect whether a group is being set to unrestricted by checking whether the 400 | * list of sites passed to the method is the same as the list of available sites, 401 | * plus the root blog. 402 | */ 403 | $sites = bp_multiblog_mode_get_enabled_sites( array( 'fields' => 'ids' ) ); 404 | $sites[] = bp_multiblog_mode_get_root_blog_id(); 405 | 406 | sort( $group_sites ); 407 | sort( $sites ); 408 | 409 | // Only save if this is a restricted group 410 | if ( $sites !== $group_sites ) { 411 | // Save new sites. 412 | foreach ( $group_sites as $site_id ) { 413 | bp_xprofile_add_meta( $group->id, 'group', 'multiblog_site', $site_id ); 414 | } 415 | } 416 | } 417 | 418 | /** 419 | * Display a label representing the XProfile group's sites 420 | * 421 | * @since 1.0.0 422 | * 423 | * @param BP_XProfile_Group $group 424 | */ 425 | public function xprofile_group_admin_label( $group ) { 426 | 427 | // The primary field group is for all, so bail 428 | if ( 1 === (int) $group->id ) 429 | return; 430 | 431 | // Get all sites and the group's sites 432 | $sites = bp_multiblog_mode_get_enabled_sites( array( 'fields' => 'ids' ) ); 433 | $sites[] = bp_multiblog_mode_get_root_blog_id(); 434 | $group_sites = bp_multiblog_mode_xprofile_get_group_sites( $group->id ); 435 | 436 | // Bail when the group applies to all sites 437 | if ( array_values( $sites ) == $group_sites ) 438 | return; 439 | 440 | $label = ''; 441 | if ( ! empty( $group_sites ) ) { 442 | $count = count( $group_sites ); 443 | 444 | if ( 1 === $count ) { 445 | $site_id = reset( $group_sites ); 446 | $label_text = sprintf( esc_html__( 'Site: %s', 'bp-multiblog-mode' ), get_blog_option( $site_id, 'blogname' ) ); 447 | } else { 448 | $label_text = sprintf( esc_html__( 'For %d Sites', 'bp-multiblog-mode' ), $count ); 449 | } 450 | 451 | $label = '
' . $label_text . '
'; 452 | } else { 453 | $label = '
' . esc_html__( 'Unavailable to all sites', 'bp-multiblog-mode' ) . '
'; 454 | } 455 | 456 | echo $label; 457 | } 458 | } 459 | 460 | /** 461 | * Setup the extension logic for BuddyPress 462 | * 463 | * @since 1.0.0 464 | * 465 | * @uses BP_Multiblog_Mode_Admin 466 | */ 467 | function bp_multiblog_mode_admin() { 468 | bp_multiblog_mode()->admin = new BP_Multiblog_Mode_Admin; 469 | } 470 | 471 | endif; // class_exists 472 | -------------------------------------------------------------------------------- /includes/functions.php: -------------------------------------------------------------------------------- 1 | root_blog_id; 22 | } 23 | 24 | /** 25 | * Return whether the given site is the actual BP root blog 26 | * 27 | * @since 1.0.0 28 | * 29 | * @param int $site_id Optional. Site id. Defaults to the current site id. 30 | * @return bool Is this the actual BP root blog? 31 | */ 32 | function bp_multiblog_mode_is_root_blog( $site_id = 0 ) { 33 | 34 | // Default to the current site 35 | if ( empty( $site_id ) ) { 36 | $site_id = get_current_blog_id(); 37 | } 38 | 39 | // Define return value 40 | $retval = false; 41 | 42 | // Check the actual root blog ID 43 | if ( bp_multiblog_mode_get_root_blog_id() === (int) $site_id ) { 44 | $retval = true; 45 | } 46 | 47 | return $retval; 48 | } 49 | 50 | /** 51 | * Return whether the given site has Multiblog mode enabled 52 | * 53 | * @since 1.0.0 54 | * 55 | * @uses apply_filters() Calls 'bp_multiblog_mode_is_enabled' 56 | * 57 | * @param int $site_id Optional. Site id. Defaults to the current site id. 58 | * @return bool Is Multiblog mode enabled? 59 | */ 60 | function bp_multiblog_mode_is_enabled( $site_id = 0 ) { 61 | 62 | // Default to the current site 63 | if ( empty( $site_id ) ) { 64 | $site_id = get_current_blog_id(); 65 | } 66 | 67 | // Define return value 68 | $is_enabled = false; 69 | 70 | // Check the site's setting when BP is network activated, but not for the real root blog 71 | if ( bp_is_network_activated() && ! bp_multiblog_mode_is_root_blog( $site_id ) ) { 72 | $is_enabled = (bool) get_blog_option( $site_id, '_bp_multiblog_mode_enabled', false ); 73 | } 74 | 75 | /** 76 | * Filter whether Multiblog is enabled for the site 77 | * 78 | * @since 1.0.0 79 | * 80 | * @param bool $is_enabled Is Multiblog enabled 81 | * @param int $site_id Site id 82 | */ 83 | return apply_filters( 'bp_multiblog_mode_is_enabled', $is_enabled, $site_id ); 84 | } 85 | 86 | /** 87 | * Return the sites of the network 88 | * 89 | * @since 1.0.0 90 | * 91 | * @uses apply_filters() Calls 'bp_multiblog_mode_get_sites' 92 | * 93 | * @param array $query_args { 94 | * Optional. Query arguments for WP_Site_Query. 95 | * 96 | * @type bool $multiblog Whether to return only Multiblog enabled sites. 97 | * } 98 | * @return array Sites, maybe only enabled 99 | */ 100 | function bp_multiblog_mode_get_sites( $query_args = array() ) { 101 | 102 | // Provide a fallback for non-array parameter 103 | if ( ! is_array( $query_args ) ) { 104 | $query_args = array( 'multiblog' => (bool) $query_args ); 105 | } 106 | 107 | // Define query args 108 | $query_args = wp_parse_args( $query_args, array( 109 | 'network_id' => get_network()->id, 110 | 'multiblog' => false 111 | ) ); 112 | 113 | // Query Multiblog-only? 114 | $multiblog = (bool) $query_args['multiblog']; 115 | 116 | // Get the Network's sites 117 | $sites = get_sites( $query_args ); 118 | 119 | // Filter for Multiblog enabled sites 120 | if ( $multiblog ) { 121 | foreach ( $sites as $k => $site ) { 122 | 123 | // Remove the unenabled site 124 | if ( ! bp_multiblog_mode_is_enabled( is_a( $site, 'WP_Site' ) ? $site->id : (int) $site ) ) { 125 | unset( $sites[ $k ] ); 126 | } 127 | } 128 | } 129 | 130 | /** 131 | * Filter the sites of the network 132 | * 133 | * @since 1.0.0 134 | * 135 | * @param array $sites Sites 136 | * @param array $query_args Query arguments for WP_Site_Query 137 | */ 138 | return apply_filters( 'bp_multiblog_mode_get_sites', $sites, $query_args ); 139 | } 140 | 141 | /** 142 | * Return the Multiblog enabled sites of the network 143 | * 144 | * @see bp_multiblog_mode_get_sites() 145 | * 146 | * @since 1.0.0 147 | * 148 | * @param array $query_args Optional. See {@see bp_multiblog_mode_get_sites()}. 149 | * @return array Multiblog enabled sites 150 | */ 151 | function bp_multiblog_mode_get_enabled_sites( $query_args = array() ) { 152 | 153 | // Parse defaults 154 | $query_args = wp_parse_args( $query_args, array( 155 | 'multiblog' => true 156 | ) ); 157 | 158 | return bp_multiblog_mode_get_sites( $query_args ); 159 | } 160 | 161 | /** 162 | * Return whether the site uses the root's taxonomy terms 163 | * 164 | * @since 1.0.0 165 | * 166 | * @return bool Use root taxonomy terms 167 | */ 168 | function bp_multiblog_mode_use_root_taxonomy_terms() { 169 | $use_root_taxonomy_terms = ! get_option( '_bp_multiblog_mode_taxonomy_terms', false ); 170 | 171 | /** 172 | * Filter whether to use the root's taxonomy terms 173 | * 174 | * @since 1.0.0 175 | * 176 | * @param bool $use_root_taxonomy_terms Use the root's taxonomy terms 177 | */ 178 | return (bool) apply_filters( 'bp_multiblog_mode_use_root_taxonomy_terms', $use_root_taxonomy_terms ); 179 | } 180 | 181 | /** 182 | * Return the given site's user ids 183 | * 184 | * @since 1.0.0 185 | * 186 | * @uses apply_filters() Calls 'bp_multiblog_mode_get_site_users' 187 | * 188 | * @param int $site_id Optional. Site ID. Defaults to the current site. 189 | * @param array $query_args Optional. Additional query arguments for `WP_User_Query`. 190 | * @return array Site user ids 191 | */ 192 | function bp_multiblog_mode_get_site_users( $site_id = 0, $query_args = array() ) { 193 | 194 | // Define user query args 195 | $query_args = wp_parse_args( $query_args, array( 'fields' => 'ids' ) ); 196 | 197 | // Site id default is set in `WP_User_Query` 198 | if ( ! empty( $site_id ) ) { 199 | $query_args['blog_id'] = (int) $site_id; 200 | } 201 | 202 | $users = get_users( $query_args ); 203 | 204 | /** 205 | * Filter the site's users 206 | * 207 | * @since 1.0.0 208 | * 209 | * @param array $users Site user ids 210 | * @param int $site_id Site id 211 | * @param array $query_args Arguments for `WP_User_Query` 212 | */ 213 | return apply_filters( 'bp_multiblog_mode_get_site_users', $users, $site_id, $query_args ); 214 | } 215 | 216 | /** 217 | * Return the given site's user count 218 | * 219 | * @since 1.0.0 220 | * 221 | * @param int $site_id Optional. Site ID. Defaults to the current site. 222 | * @param array $query_args Optional. Additional query arguments for `WP_User_Query`. 223 | * @return int Site user count 224 | */ 225 | function bp_multiblog_mode_get_site_total_user_count( $site_id = 0, $query_args = array() ) { 226 | 227 | // Define user query args 228 | $query_args = wp_parse_args( $query_args, array( 'count_total' => true ) ); 229 | 230 | // Site id default is set in `WP_User_Query` 231 | if ( ! empty( $site_id ) ) { 232 | $query_args['blog_id'] = (int) $site_id; 233 | } 234 | 235 | $user_search = new WP_User_Query( $query_args ); 236 | 237 | return $user_search->get_results(); 238 | } 239 | 240 | /** Members *************************************************************/ 241 | 242 | /** 243 | * Return whether to limit BP content to site members 244 | * 245 | * @since 1.0.0 246 | * 247 | * @uses apply_filters() Calls 'bp_multiblog_mode_site_members' 248 | * 249 | * @return bool Limit content to site members 250 | */ 251 | function bp_multiblog_mode_limit_site_members() { 252 | $site_members = get_option( '_bp_multiblog_mode_site_members', false ); 253 | 254 | /** 255 | * Filter whether to limit BP content to site members 256 | * 257 | * @since 1.0.0 258 | * 259 | * @param bool $site_members Limit content to site members 260 | */ 261 | return (bool) apply_filters( 'bp_multiblog_mode_site_members', $site_members ); 262 | } 263 | 264 | /** 265 | * Block member profiles of non-site members 266 | * 267 | * @since 1.0.0 268 | * 269 | * @param string $member_slug Member slug 270 | * @return string Member slug 271 | */ 272 | function bp_multiblog_mode_members_block_profile( $member_slug ) { 273 | 274 | // Block access to profiles of non-site members 275 | if ( bp_multiblog_mode_limit_site_members() ) { 276 | 277 | // Get the queried user 278 | $field = bp_is_username_compatibility_mode() ? 'login' : 'slug'; 279 | $user = get_user_by( $field, $member_slug ); 280 | 281 | // Get the site members 282 | $site_members = array_map( 'intval', bp_multiblog_mode_get_site_users() ); 283 | 284 | // The queried user is not a site member 285 | if ( $user && ! in_array( $user->ID, $site_members, true ) ) { 286 | 287 | // Mock a non-existing user slug because a falsey value will result in 288 | // a failed page request unaccounted for in `bp_core_set_uri_globals()` 289 | $member_slug = '___BP_MULTIBLOG_MODE___'; 290 | } 291 | } 292 | 293 | return $member_slug; 294 | } 295 | 296 | /** 297 | * Modify the members query SQL clauses 298 | * 299 | * @since 1.0.0 300 | * 301 | * @param array $sql SQL clauses 302 | * @param BP_User_Query $query Members query 303 | * @return array SQL clauses 304 | */ 305 | function bp_multiblog_mode_members_limit_users( $sql, $query ) { 306 | 307 | // Force limit member query results to users of the current site 308 | if ( bp_multiblog_mode_limit_site_members() ) { 309 | 310 | // Get the site members 311 | $site_members = implode( ',', bp_multiblog_mode_get_site_users() ); 312 | 313 | // The queried user(s) should be a site member 314 | $sql['where']['bp_multiblog_mode_limit_site_members'] = "u.{$query->uid_name} IN ({$site_members})"; 315 | } 316 | 317 | return $sql; 318 | } 319 | 320 | /** 321 | * Modify the total site member count 322 | * 323 | * @see bp_core_get_total_member_count() 324 | * 325 | * @since 1.0.0 326 | * 327 | * @param int $count Site member count 328 | * @return int Site member count 329 | */ 330 | function bp_multiblog_mode_limit_total_member_count( $count ) { 331 | global $wpdb; 332 | 333 | // Recount total site member count 334 | if ( bp_multiblog_mode_limit_site_members() ) { 335 | 336 | // Get the site members 337 | $site_members = implode( ',', bp_multiblog_mode_get_site_users() ); 338 | 339 | // The queried user(s) should be a site member 340 | $status_sql = bp_core_get_status_sql(); 341 | $count = $wpdb->get_var( "SELECT COUNT(ID) FROM {$wpdb->users} WHERE {$status_sql} AND {$wpdb->users}.ID IN ({$site_members})" ); 342 | } 343 | 344 | return $count; 345 | } 346 | 347 | /** 348 | * Modify the active site member count 349 | * 350 | * @see bp_core_get_active_member_count() 351 | * 352 | * @since 1.0.0 353 | * 354 | * @param int $count Site member count 355 | * @return int Site member count 356 | */ 357 | function bp_multiblog_mode_limit_active_member_count( $count ) { 358 | global $wpdb; 359 | 360 | // Recount active site member count 361 | if ( bp_multiblog_mode_limit_site_members() ) { 362 | $bp = buddypress(); 363 | 364 | // Get the site members 365 | $site_members = implode( ',', bp_multiblog_mode_get_site_users() ); 366 | 367 | // Avoid a costly join by splitting the lookup. 368 | if ( is_multisite() ) { 369 | $sql = "SELECT ID FROM {$wpdb->users} WHERE (user_status != 0 OR deleted != 0 OR user_status != 0)"; 370 | } else { 371 | $sql = "SELECT ID FROM {$wpdb->users} WHERE user_status != 0"; 372 | } 373 | 374 | // The queried user(s) should be a site member 375 | $exclude_users = $wpdb->get_col( $sql ); 376 | $exclude_users_sql = !empty( $exclude_users ) ? "AND user_id NOT IN (" . implode( ',', wp_parse_id_list( $exclude_users ) ) . ")" : ''; 377 | $count = (int) $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(user_id) FROM {$bp->members->table_name_last_activity} WHERE component = %s AND type = 'last_activity' {$exclude_users_sql} AND user_id IN ({$site_members})", $bp->members->id ) ); 378 | } 379 | 380 | return $count; 381 | } 382 | 383 | /** Activity ************************************************************/ 384 | 385 | /** 386 | * Return whether to limit the activity stream to site items 387 | * 388 | * This concerns activity items that are created in the context of the site. 389 | * 390 | * @since 1.0.0 391 | * 392 | * @return bool Limit activity items to the site 393 | */ 394 | function bp_multiblog_mode_activity_limit_site_items() { 395 | $limit_site_items = get_option( '_bp_multiblog_mode_activity_stream', false ); 396 | 397 | /** 398 | * Filter whether to limit the activity stream to site items 399 | * 400 | * @since 1.0.0 401 | * 402 | * @param bool $limit_site_items Limit activity items to the site 403 | */ 404 | return (bool) apply_filters( 'bp_multiblog_mode_activity_limit_site_items', $limit_site_items ); 405 | } 406 | 407 | /** 408 | * Return whether to limit the activity stream to content of site members 409 | * 410 | * This concerns activity items that are created in the context of the wider network. 411 | * It may effect in blocking items that are created by retired/removed site members. 412 | * 413 | * @since 1.0.0 414 | * 415 | * @return bool Limit activity items to site members 416 | */ 417 | function bp_multiblog_mode_activity_limit_site_members() { 418 | 419 | // Prefer the Site Members setting 420 | $limit_site_members = bp_multiblog_mode_limit_site_members(); 421 | 422 | // Default to the Activity Site Members setting 423 | if ( ! $limit_site_members ) { 424 | $limit_site_members = get_option( '_bp_multiblog_mode_activity_limit_site_members', false ); 425 | } 426 | 427 | /** 428 | * Filter whether to limit the activity stream to content of site members 429 | * 430 | * @since 1.0.0 431 | * 432 | * @param bool $limit_site_members Limit activity items to site members 433 | */ 434 | return (bool) apply_filters( 'bp_multiblog_mode_activity_limit_site_members', $limit_site_members ); 435 | } 436 | 437 | /** 438 | * Modify the activity query WHERE statements 439 | * 440 | * @see BP_Activity_Activity::get() 441 | * 442 | * @since 1.0.0 443 | * 444 | * @param array $where Query WHERE statements 445 | * @param array $args Query arguments 446 | * @return array Query WHERE statements 447 | */ 448 | function bp_multiblog_mode_activity_limit_stream( $where, $args ) { 449 | global $wpdb; 450 | 451 | // Bail when Multiblog is not enabled 452 | if ( ! bp_multiblog_mode_is_enabled() ) 453 | return $where; 454 | 455 | // Get BuddyPress 456 | $bp = buddypress(); 457 | 458 | // Exclude activity items from deactivated components, except Blogs 459 | $components = array_diff( (array) $bp->deactivated_components, array( 'blogs' ) ); 460 | 461 | if ( $components ) { 462 | $components = "'" . implode( "','", $components ) . "'"; 463 | 464 | // Activity item(s) should not be from deactivated components 465 | $where['bp_multiblog_mode_exclude_deactivated_components'] = "a.component NOT IN ({$components})"; 466 | } 467 | 468 | // Limit activity items belonging to the current site 469 | if ( bp_multiblog_mode_activity_limit_site_items() ) { 470 | /** 471 | * Column 'item_id' can also mean id from activity/forums/groups etc. 472 | * components, so only filter blogs component activities. 473 | */ 474 | $where['bp_multiblog_mode_activity_limit_site_items'] = $wpdb->prepare( "(a.item_id = %d OR a.component <> %s)", get_current_blog_id(), 'blogs' ); 475 | } 476 | 477 | // Limit activity items created by site members 478 | if ( bp_multiblog_mode_activity_limit_site_members() ) { 479 | 480 | // Get the site members 481 | $site_members = implode( ',', bp_multiblog_mode_get_site_users() ); 482 | 483 | // Activity item creator(s) should be a site member 484 | $where['bp_multiblog_mode_activity_limit_site_members'] = "a.user_id IN ({$site_members})"; 485 | } 486 | 487 | return $where; 488 | } 489 | 490 | /** XProfile ************************************************************/ 491 | 492 | /** 493 | * Return the XProfile field group's Multiblog sites 494 | * 495 | * @see BP_XProfile_Field::get_member_types() 496 | * 497 | * @since 1.0.0 498 | * 499 | * @param int $group_id XProfile group id 500 | * @return array Site ids 501 | */ 502 | function bp_multiblog_mode_xprofile_get_group_sites( $group_id ) { 503 | 504 | // Get profile group meta 505 | $raw_sites = bp_xprofile_get_meta( $group_id, 'group', 'multiblog_site', false ); 506 | 507 | // If `$raw_sites` is not an array, it probably means this is a new group (id=0). 508 | if ( ! is_array( $raw_sites ) ) { 509 | $raw_sites = array(); 510 | } 511 | 512 | // If '_none' is found in the array, it overrides all sites. 513 | $sites = array(); 514 | if ( ! in_array( '_none', $raw_sites ) ) { 515 | $enabled_sites = bp_multiblog_mode_get_enabled_sites( array( 'fields' => 'ids' ) ); 516 | 517 | // Eliminate invalid sites saved in the database. 518 | foreach ( $raw_sites as $raw_site ) { 519 | // The root blog is a special case - it cannot be Multiblog enabled 520 | if ( bp_multiblog_mode_is_root_blog( $raw_site ) || in_array( $raw_site, $enabled_sites ) ) { 521 | $sites[] = $raw_site; 522 | } 523 | } 524 | 525 | // If no sites have been saved, intepret as *all* sites. 526 | if ( empty( $sites ) ) { 527 | $sites = array_values( $enabled_sites ); 528 | 529 | // + the root blog 530 | $sites[] = bp_multiblog_mode_get_root_blog_id(); 531 | } 532 | } 533 | 534 | return $sites; 535 | } 536 | 537 | /** 538 | * Modify the profile groups collection 539 | * 540 | * @since 1.0.0 541 | * 542 | * @param array $groups Profile groups 543 | * @param array $args Query arguments 544 | * @return array Profile groups 545 | */ 546 | function bp_multiblog_mode_xprofile_get_groups( $groups, $args ) { 547 | 548 | // Are we in the network admin? 549 | $network = is_network_admin() ? '-network' : ''; 550 | 551 | // Not when editing profile fields 552 | if ( ! is_admin() || "users_page_bp-profile-setup{$network}" !== get_current_screen()->id ) { 553 | 554 | // Eliminate unassigned groups for the current site 555 | foreach ( $groups as $k => $group ) { 556 | if ( ! in_array( get_current_blog_id(), bp_multiblog_mode_xprofile_get_group_sites( $group->id ) ) ) { 557 | unset( $groups[ $k ] ); 558 | } 559 | } 560 | 561 | $groups = array_values( $groups ); 562 | } 563 | 564 | return $groups; 565 | } 566 | 567 | /** Files ***************************************************************/ 568 | 569 | /** 570 | * Return whether the site uses the root's avatar uploads 571 | * 572 | * @since 1.0.0 573 | * 574 | * @uses apply_filters() Calls 'bp_multiblog_mode_use_root_avatar_uploads' 575 | * 576 | * @return bool Use root avatar uploads 577 | */ 578 | function bp_multiblog_mode_use_root_avatar_uploads() { 579 | $use_root_avatar_uploads = ! get_option( '_bp_multiblog_mode_avatar_uploads', false ); 580 | 581 | /** 582 | * Filter whether to use the root's avatar uploads 583 | * 584 | * @since 1.0.0 585 | * 586 | * @param bool $use_root_avatar_uploads Use the root's avatar uploads 587 | */ 588 | return (bool) apply_filters( 'bp_multiblog_mode_use_root_avatar_uploads', $use_root_avatar_uploads ); 589 | } 590 | 591 | /** 592 | * Return whether the site uses the root's file uploads 593 | * 594 | * @since 1.0.0 595 | * 596 | * @uses apply_filters() Calls 'bp_multiblog_mode_use_root_file_uploads' 597 | * 598 | * @return bool Use root file uploads 599 | */ 600 | function bp_multiblog_mode_use_root_file_uploads() { 601 | $use_root_file_uploads = ! get_option( '_bp_multiblog_mode_file_uploads', false ); 602 | 603 | /** 604 | * Filter whether to use the root's file uploads 605 | * 606 | * @since 1.0.0 607 | * 608 | * @param bool $use_root_file_uploads Use the root's file uploads 609 | */ 610 | return (bool) apply_filters( 'bp_multiblog_mode_use_root_file_uploads', $use_root_file_uploads ); 611 | } 612 | 613 | /** 614 | * Define the upload directory at the root blog 615 | * 616 | * The upload dir is fetched once and stored in the BP global. So to 617 | * override this we predefine the upload dir early, before BP tries to 618 | * set it. Deviations from this directory are counted for in filters. 619 | * 620 | * @see bp_upload_dir() 621 | * 622 | * @since 1.0.0 623 | * 624 | * @uses do_action() Calls 'bp_multiblog_mode_set_root_upload_dir' 625 | */ 626 | function bp_multiblog_mode_set_root_upload_dir() { 627 | $bp = buddypress(); 628 | 629 | if ( empty( $bp->upload_dir ) && bp_multiblog_mode_is_enabled() && bp_multiblog_mode_use_root_file_uploads() ) { 630 | 631 | // Juggle to root blog. 632 | switch_to_blog( bp_multiblog_mode_get_root_blog_id() ); 633 | 634 | // Get the upload directory (for root blog). 635 | $wp_upload_dir = wp_upload_dir(); 636 | 637 | // Juggle back to current blog. 638 | restore_current_blog(); 639 | 640 | // Bail if an error occurred. 641 | if ( ! empty( $wp_upload_dir['error'] ) ) { 642 | return false; 643 | } 644 | 645 | $bp->upload_dir = $wp_upload_dir; 646 | 647 | /** 648 | * Act after BP's upload directory is changed to BP's root upload directory 649 | * 650 | * @since 1.0.0 651 | */ 652 | do_action( 'bp_multiblog_mode_set_root_upload_dir' ); 653 | } 654 | } 655 | 656 | /** 657 | * Return the upload dir for the given site 658 | * 659 | * @since 1.0.0 660 | * 661 | * @uses apply_filters() Calls 'bp_multiblog_mode_get_upload_dir' 662 | * 663 | * @param int $site_id Optional. Site id. Defaults to the current site id. 664 | * @return array Root upload dir data 665 | */ 666 | function bp_multiblog_mode_get_upload_dir( $site_id = 0 ) { 667 | $plugin = bp_multiblog_mode(); 668 | 669 | if ( empty( $plugin->upload_dir ) ) { 670 | if ( empty( $site_id ) ) { 671 | $site_id = get_current_blog_id(); 672 | } 673 | 674 | switch_to_blog( $site_id ); 675 | 676 | // Get root upload dir 677 | $upload_dir = wp_upload_dir(); 678 | 679 | restore_current_blog(); 680 | 681 | // Bail when an error occurred 682 | if ( ! empty( $upload_dir['error'] ) ) 683 | return false; 684 | 685 | $plugin->upload_dir = $upload_dir; 686 | } 687 | 688 | /** 689 | * Filter the site's upload directory 690 | * 691 | * @since 1.0.0 692 | * 693 | * @param bool $upload_dir The site's upload directory 694 | * @param int $site_id Site id 695 | */ 696 | return apply_filters( 'bp_multiblog_mode_get_upload_dir', $plugin->upload_dir, $site_id ); 697 | } 698 | 699 | /** 700 | * Return whether to modify the avatar upload directory 701 | * 702 | * @since 1.0.0 703 | * 704 | * @return bool Modify the avatar upload dir 705 | */ 706 | function bp_multiblog_mode_modify_avatar_upload_dir() { 707 | $use_file_uploads = bp_multiblog_mode_use_root_file_uploads(); 708 | $use_avatar_uploads = bp_multiblog_mode_use_root_avatar_uploads(); 709 | 710 | /** 711 | * Modify the avatar upload directory when: 712 | * - Multiblog mode is enabled 713 | * - Upload dir is not overloaded and avatars should use the root dir 714 | * - OR Upload dir *is* overloaded and avatars should *not* use the root dir 715 | * 716 | * In either other case (both (not) from root), no filtering is needed. 717 | */ 718 | return bp_multiblog_mode_is_enabled() && ( ( ! $use_file_uploads && $use_avatar_uploads ) || ( $use_file_uploads && ! $use_avatar_uploads ) ); 719 | } 720 | 721 | /** 722 | * Modify the avatar's upload path 723 | * 724 | * @since 1.0.0 725 | * 726 | * @param string $path Avatar upload path 727 | * @return string Avatar upload path 728 | */ 729 | function bp_multiblog_mode_core_avatar_upload_path( $path ) { 730 | 731 | // Filtering required 732 | if ( bp_multiblog_mode_modify_avatar_upload_dir() && ! defined( 'BP_AVATAR_UPLOAD_PATH' ) ) { 733 | $uploads = bp_multiblog_mode_get_upload_dir( 734 | bp_multiblog_mode_use_root_avatar_uploads() 735 | ? bp_multiblog_mode_get_root_blog_id() 736 | : 0 737 | ); 738 | 739 | if ( $uploads ) { 740 | $path = $uploads['basedir']; 741 | } 742 | } 743 | 744 | return $path; 745 | } 746 | 747 | /** 748 | * Modify the avatar's base url 749 | * 750 | * @since 1.0.0 751 | * 752 | * @param string $url Avatar base url 753 | * @return string Avatar base url 754 | */ 755 | function bp_multiblog_mode_core_avatar_url( $url ) { 756 | 757 | // Filtering required 758 | if ( bp_multiblog_mode_modify_avatar_upload_dir() && ! defined( 'BP_AVATAR_URL' ) ) { 759 | $uploads = bp_multiblog_mode_get_upload_dir( 760 | bp_multiblog_mode_use_root_avatar_uploads() 761 | ? bp_multiblog_mode_get_root_blog_id() 762 | : 0 763 | ); 764 | 765 | if ( $uploads ) { 766 | $url = $uploads['baseurl']; 767 | 768 | if ( is_ssl() ) { 769 | $url = str_replace( 'http://', 'https://', $url ); 770 | } 771 | } 772 | } 773 | 774 | return $url; 775 | } 776 | -------------------------------------------------------------------------------- /includes/index.php: -------------------------------------------------------------------------------- 1 | array( 26 | 'title' => esc_html__( 'General Settings', 'bp-multiblog-mode' ), 27 | 'callback' => 'bp_multiblog_mode_admin_setting_callback_general_network_section', 28 | 'page' => 'bp-multiblog-mode-network', 29 | ), 30 | 31 | // General settings 32 | 'bp_multiblog_mode_settings_general' => array( 33 | 'title' => esc_html__( 'General Settings', 'bp-multiblog-mode' ), 34 | 'callback' => 'bp_multiblog_mode_admin_setting_callback_general_section', 35 | 'page' => 'bp-multiblog-mode', 36 | ), 37 | 38 | // Profile settings 39 | 'bp_multiblog_mode_settings_profile' => array( 40 | 'title' => esc_html__( 'Profile Settings', 'bp-multiblog-mode' ), 41 | 'callback' => 'bp_multiblog_mode_admin_setting_callback_profile_section', 42 | 'page' => 'bp-multiblog-mode', 43 | ), 44 | ) ); 45 | } 46 | 47 | /** 48 | * Return the plugin's settings fields 49 | * 50 | * @since 1.0.0 51 | * 52 | * @uses apply_filters() Calls 'bp_multiblog_mode_admin_get_settings_fields' 53 | * @return array Settings fields 54 | */ 55 | function bp_multiblog_mode_admin_get_settings_fields() { 56 | 57 | // Define settings fields 58 | $fields = array( 59 | 60 | // General Network settings 61 | 'bp_multiblog_mode_settings_general_network' => array( 62 | 63 | // Sites 64 | '_bp_multiblog_mode_sites' => array( 65 | 'title' => esc_html__( 'Sites', 'bp-multiblog-mode' ), 66 | 'callback' => 'bp_multiblog_mode_admin_setting_callback_sites', 67 | 'sanitize_callback' => false, // We do our own saving of this field 68 | 'args' => array() 69 | ), 70 | ), 71 | 72 | // General settings 73 | 'bp_multiblog_mode_settings_general' => array( 74 | 75 | // Members 76 | '_bp_multiblog_mode_site_members' => array( 77 | 'title' => esc_html__( 'Members', 'bp-multiblog-mode' ), 78 | 'callback' => 'bp_multiblog_mode_admin_setting_callback_site_members', 79 | 'sanitize_callback' => 'intval', 80 | 'args' => array() 81 | ), 82 | 83 | // Taxonomy terms 84 | '_bp_multiblog_mode_taxonomy_terms' => array( 85 | 'title' => esc_html__( 'Taxonomy terms', 'bp-multiblog-mode' ), 86 | 'callback' => 'bp_multiblog_mode_admin_setting_callback_taxonomy_terms', 87 | 'sanitize_callback' => 'intval', 88 | 'args' => array() 89 | ), 90 | ), 91 | 92 | // Profile settings 93 | 'bp_multiblog_mode_settings_profile' => array( 94 | 95 | 96 | // Avatar uploads 97 | '_bp_multiblog_mode_avatar_uploads' => array( 98 | 'title' => esc_html__( 'Avatar uploads', 'bp-multiblog-mode' ), 99 | 'callback' => 'bp_multiblog_mode_admin_setting_callback_avatar_uploads', 100 | 'sanitize_callback' => 'intval', 101 | 'args' => array() 102 | ), 103 | 104 | // File uploads 105 | '_bp_multiblog_mode_file_uploads' => array( 106 | 'title' => esc_html__( 'File uploads', 'bp-multiblog-mode' ), 107 | 'callback' => 'bp_multiblog_mode_admin_setting_callback_file_uploads', 108 | 'sanitize_callback' => 'intval', 109 | 'args' => array() 110 | ), 111 | ), 112 | ); 113 | 114 | // Activity 115 | if ( bp_is_active( 'activity' ) ) { 116 | 117 | // Activity Stream 118 | $fields['bp_multiblog_mode_settings_general']['_bp_multiblog_mode_activity_stream'] = array( 119 | 'title' => esc_html__( 'Activity stream', 'bp-multiblog-mode' ), 120 | 'callback' => 'bp_multiblog_mode_admin_setting_callback_activity_stream', 121 | 'sanitize_callback' => 'intval', 122 | 'args' => array() 123 | ); 124 | 125 | // Activity Stream Site Members 126 | if ( ! bp_multiblog_mode_limit_site_members() ) { 127 | $fields['bp_multiblog_mode_settings_general']['_bp_multiblog_mode_activity_site_members'] = array( 128 | /* Field input is in the 'Activity stream' setting */ 129 | 'sanitize_callback' => 'intval', 130 | 'args' => array() 131 | ); 132 | } 133 | } 134 | 135 | // Avatar uploads is disabled 136 | if ( bp_disable_avatar_uploads( false ) ) { 137 | unset( $fields['bp_multiblog_mode_settings_profile']['_bp_multiblog_mode_avatar_uploads'] ); 138 | } 139 | 140 | return (array) apply_filters( 'bp_multiblog_mode_admin_get_settings_fields', $fields ); 141 | } 142 | 143 | /** 144 | * Get settings fields by section 145 | * 146 | * @since 1.0.0 147 | * 148 | * @param string $section_id 149 | * @return array|bool Array of fields or False when section is invalid 150 | */ 151 | function bp_multiblog_mode_admin_get_settings_fields_for_section( $section_id = '' ) { 152 | 153 | // Bail when section is empty 154 | if ( empty( $section_id ) ) 155 | return false; 156 | 157 | $fields = bp_multiblog_mode_admin_get_settings_fields(); 158 | $retval = isset( $fields[$section_id] ) ? $fields[$section_id] : false; 159 | 160 | return $retval; 161 | } 162 | 163 | /** 164 | * Return whether the admin page has registered settings 165 | * 166 | * @since 1.0.0 167 | * 168 | * @param string $page 169 | * @return bool Does the admin page have settings? 170 | */ 171 | function bp_multiblog_mode_admin_page_has_settings( $page = '' ) { 172 | 173 | // Bail when page is empty 174 | if ( empty( $page ) ) 175 | return false; 176 | 177 | // Loop through the available sections 178 | $sections = wp_list_filter( bp_multiblog_mode_admin_get_settings_sections(), array( 'page' => $page ) ); 179 | foreach ( (array) $sections as $section_id => $section ) { 180 | 181 | // Find out whether the section has fields 182 | $fields = bp_multiblog_mode_admin_get_settings_fields_for_section( $section_id ); 183 | if ( ! empty( $fields ) ) { 184 | return true; 185 | } 186 | } 187 | 188 | return false; 189 | } 190 | 191 | /** General Network Section ***************************************************/ 192 | 193 | /** 194 | * Display the description of the General Network settings section 195 | * 196 | * @since 1.0.0 197 | */ 198 | function bp_multiblog_mode_admin_setting_callback_general_network_section() { /* Nothing to show */ } 199 | 200 | /** 201 | * Display the enable Multiblog per site setting field 202 | * 203 | * @since 1.0.0 204 | */ 205 | function bp_multiblog_mode_admin_setting_callback_sites() { 206 | 207 | // Get all sites of the current network 208 | $sites = bp_multiblog_mode_get_sites(); ?> 209 | 210 |

211 | 212 | 213 | 214 | 215 | 219 | 222 | 223 | 224 | 225 | 226 | id ); 228 | $is_main_site = is_main_site( $site->id ); 229 | $selected = get_blog_option( $site->id, '_bp_multiblog_mode_enabled', false ) || $is_root_blog; 230 | $url = $selected ? add_query_arg( 'page', 'bp-components', get_admin_url( $site->id, 'options-general.php' ) ) : get_admin_url( $site->id, 'index.php' ); 231 | 232 | $main_site = $is_root_blog && ! $is_main_site 233 | ? esc_html__( 'BuddyPress Root Site', 'bp-multiblog-mode' ) 234 | : ( $is_main_site ? esc_html__( 'Main Site', 'bp-multiblog-mode' ) : '' ); 235 | 236 | if ( $main_site ) { 237 | $main_site = ' — ' . $main_site . ''; 238 | } 239 | ?> 240 | 241 | 242 | 248 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 265 | 266 | 267 | 268 |
216 | 217 | 218 | 220 | 221 |
243 | 244 | 245 | /> 246 | 247 | 249 | 250 | blogname; ?> 251 | 252 | domain; ?> 253 |
262 | 263 | 264 |
269 | 270 | 271 | 272 | 283 | 284 |

285 | 286 | 295 | 296 | /> 297 | 298 | 299 | 308 | 309 | /> 310 | 311 | 312 | 321 | 322 |

323 | 324 |

325 | /> 326 | 327 |

328 | 329 | 330 | 331 |

332 | /> 333 | 334 |

335 | 336 | 354 | 355 | /> 356 | 357 | 358 | 367 | 368 | /> 369 | 370 | 371 | admin->settings_page; 388 | 389 | // For backcompat, check tabbed header 390 | $is_tabbed_header = function_exists( 'bp_core_admin_tabbed_screen_header' ); 391 | 392 | if ( $is_tabbed_header ) : ?> 393 | 394 | 395 | 396 | 397 | 398 |
399 | 400 |

401 | 402 | 403 | 404 | 405 | 406 |
407 |
408 | 409 | 410 | 411 | 412 | 413 |

414 | 415 |

416 | 417 |
418 |
419 | 420 | 421 | 422 |
423 | 424 | $settings ) { 455 | foreach( $settings as $setting_name => $setting ) { 456 | $value = isset( $_POST[$setting_name] ) ? $_POST[$setting_name] : ''; 457 | 458 | bp_update_option( $setting_name, $value ); 459 | } 460 | } 461 | } 462 | 463 | bp_core_redirect( add_query_arg( array( 'page' => 'bp-multiblog-mode', 'updated' => 'true' ), bp_get_admin_url( 'admin.php' ) ) ); 464 | } 465 | } 466 | -------------------------------------------------------------------------------- /includes/sub-actions.php: -------------------------------------------------------------------------------- 1 |