array( * 'create' => array( * 'slug' => 'foo', * 'name' => 'Foo', * 'position' => 55, * 'screen_callback' => 'my_create_screen_callback', * 'screen_save_callback' => 'my_create_screen_save_callback', * ), * 'edit' => array( // ... * ), * Only provide those arguments that you actually want to change from the * default configuration. BP_Group_Extension will do the rest. * * Note that the 'edit' screen accepts an additional parameter: 'submit_text', * which defines the text of the Submit button automatically added to the Edit * screen of the extension (defaults to 'Save Changes'). Also, the 'admin' * screen accepts two additional parameters: 'metabox_priority' and * 'metabox_context'. See the docs for add_meta_box() for more details on these * arguments. * * Prior to BuddyPress 1.7, group extension configurations were set slightly * differently. The legacy method is still supported, though deprecated. * * @since 1.1.0 */ class BP_Group_Extension { /** Public ************************************************************/ /** * Information about this extension's screens. * * @since 1.8.0 * * @var array */ public $screens = array(); /** * The name of the extending class. * * @since 1.8.0 * * @var string */ public $class_name = ''; /** * A ReflectionClass object of the current extension. * * @since 1.8.0 * * @var ReflectionClass */ public $class_reflection = null; /** * Parsed configuration parameters for the extension. * * @since 1.8.0 * * @var array */ public $params = array(); /** * Raw config params, as passed by the extending class. * * @since 2.1.0 * * @var array */ public $params_raw = array(); /** * The ID of the current group. * * @since 1.8.0 * * @var int */ public $group_id = 0; /** * The slug of the current extension. * * @since 1.1.0 * * @var string */ public $slug = ''; /** * The translatable name of the current extension. * * @since 1.1.0 * * @var string */ public $name = ''; /** * The visibility of the extension tab. 'public' or 'private'. * * @since 1.1.0 * * @var string */ public $visibility = 'public'; /** * The numeric position of the main nav item. * * @since 1.1.0 * * @var int */ public $nav_item_position = 81; /** * Whether to show the nav item. * * @since 1.1.0 * * @var bool */ public $enable_nav_item = true; /** * Whether the current user should see the navigation item. * * @since 2.1.0 * * @var bool */ public $user_can_see_nav_item; /** * The Callback function to use before showing the navigation item. * * @since 12.0.0 * * @var string */ public $show_tab_callback = ''; /** * Whether the current user can visit the tab. * * @since 2.1.0 * * @var bool */ public $user_can_visit; /** * The text of the nav item. Defaults to self::name. * * @since 1.1.0 * * @var string */ public $nav_item_name = ''; /** * The WP action that self::widget_display() is attached to. * * Default: 'groups_custom_group_boxes'. * * @since 1.1.0 * * @var string */ public $display_hook = 'groups_custom_group_boxes'; /** * The template file used to load the plugin content. * * Default: 'groups/single/plugins'. * * @since 1.1.0 * * @var string */ public $template_file = 'groups/single/plugins'; /** * The template file. * * @since 1.1.0 * * @var string */ public $edit_screen_template; /** Protected *********************************************************/ /** * Has the extension been initialized? * * @since 1.8.0 * * @var bool */ protected $initialized = false; /** * Extension properties as set by legacy extensions. * * @since 1.8.0 * * @var array */ protected $legacy_properties = array(); /** * Converted legacy parameters. * * These are the extension properties as set by legacy extensions, but * then converted to match the new format for params. * * @since 1.8.0 * * @var array */ protected $legacy_properties_converted = array(); /** * Redirect location as defined by post-edit save callback. * * @since 2.1.0 * * @var string */ protected $post_save_redirect; /** * Miscellaneous data as set by the __set() magic method. * * @since 1.8.0 * * @var array */ protected $data = array(); /** Screen Overrides **************************************************/ /* * Screen override methods are how your extension will display content * and handle form submits. Your extension should only override those * methods that it needs for its purposes. */ /** * The content of the group tab. * * @since 1.1.0 * @since 15.0.0 The `$group_id` parameter was removed since it was unused. */ public function display() { return new WP_Error( 'invalid-method', /* translators: %s: Method name. */ sprintf( __( "Method '%s' not implemented. Must be overridden in subclass.", 'buddypress' ), __METHOD__ ) ); } /** * Content displayed in a widget sidebar, if applicable. * * @since 1.1.0 */ public function widget_display() {} /* * *_screen() displays the settings form for the given context * *_screen_save() processes data submitted via the settings form * The settings_* methods are generic fallbacks, which can optionally * be overridden by the more specific edit_*, create_*, and admin_* * versions. */ /** * Provide the fallback markup for Group's Create/Admin/Edit screens. * * @since 1.8.0 * @since 15.0.0 The `$group_id` parameter was removed since it was unused. */ public function settings_screen() { return new WP_Error( 'invalid-method', /* translators: %s: Method name. */ sprintf( __( "Method '%s' not implemented. Must be overridden in subclass.", 'buddypress' ), __METHOD__ ) ); } /** * Group's Fallback handler for the Create/Admin/Edit screens. * * @since 1.8.0 * @since 15.0.0 The `$group_id` parameter was removed since it was unused. */ public function settings_screen_save() { return new WP_Error( 'invalid-method', /* translators: %s: Method name. */ sprintf( __( "Method '%s' not implemented. Must be overridden in subclass.", 'buddypress' ), __METHOD__ ) ); } /** * The content of the Manage sub tab. * * @since 1.1.0 * @since 15.0.0 The `$group_id` parameter was removed since it was unused. */ public function edit_screen() { return new WP_Error( 'invalid-method', /* translators: %s: Method name. */ sprintf( __( "Method '%s' not implemented. Must be overridden in subclass.", 'buddypress' ), __METHOD__ ) ); } /** * Group Manage sub tab handler. * * @since 1.1.0 * @since 15.0.0 The `$group_id` parameter was removed since it was unused. */ public function edit_screen_save() { return new WP_Error( 'invalid-method', /* translators: %s: Method name. */ sprintf( __( "Method '%s' not implemented. Must be overridden in subclass.", 'buddypress' ), __METHOD__ ) ); } /** * The content of the group create step tab. * * @since 1.1.0 * @since 15.0.0 The `$group_id` parameter was removed since it was unused. */ public function create_screen() { return new WP_Error( 'invalid-method', /* translators: %s: Method name. */ sprintf( __( "Method '%s' not implemented. Must be overridden in subclass.", 'buddypress' ), __METHOD__ ) ); } /** * Group create step tab handler. * * @since 1.1.0 * @since 15.0.0 The `$group_id` parameter was removed since it was unused. */ public function create_screen_save() { return new WP_Error( 'invalid-method', /* translators: %s: Method name. */ sprintf( __( "Method '%s' not implemented. Must be overridden in subclass.", 'buddypress' ), __METHOD__ ) ); } /** * The content of Group's WP Administration screen metabox. * * @since 1.8.0 * @since 15.0.0 The `$group_id` parameter was removed since it was unused. */ public function admin_screen() { return new WP_Error( 'invalid-method', /* translators: %s: Method name. */ sprintf( __( "Method '%s' not implemented. Must be overridden in subclass.", 'buddypress' ), __METHOD__ ) ); } /** * Group's WP Administration screen handler. * * @since 1.8.0 * @since 15.0.0 The `$group_id` parameter was removed since it was unused. */ public function admin_screen_save() { return new WP_Error( 'invalid-method', /* translators: %s: Method name. */ sprintf( __( "Method '%s' not implemented. Must be overridden in subclass.", 'buddypress' ), __METHOD__ ) ); } /** Setup *************************************************************/ /** * Initialize the extension, using your config settings. * * Your plugin should call this method at the very end of its * constructor, like so: * * public function __construct() { * $args = array( * 'slug' => 'my-group-extension', * 'name' => 'My Group Extension', * // ... * ); * * parent::init( $args ); * } * * @since 1.8.0 * @since 2.1.0 Added 'access' and 'show_tab' arguments to `$args`. * @since 12.0.0 Set the Group Extension screens. * * @param array $args { * Optional. Array of initialization arguments. * @type string $slug Unique, URL-safe identifier for your extension. * @type string $name Translatable name for your extension. Used to populate * navigation items. * @type string $visibility Optional. Set to 'public' for your extension (the main tab as well * as the widget) to be available to anyone who can access the group; * set to 'private' otherwise. Default: 'public'. * @type int $nav_item_position Optional. Location of the nav item in the tab list. * Default: 81. * @type bool $enable_nav_item Optional. Whether the extension's tab should be accessible to * anyone who can view the group. Default: true. * @type string $nav_item_name Optional. The translatable text you want to appear in the nav tab. * Default: the value of `$name`. * @type string $display_hook Optional. The WordPress action that the widget_display() method is * hooked to. Default: 'groups_custom_group_boxes'. * @type string $template_file Optional. Theme-relative path to the template file BP should use * to load the content of your main extension tab. * Default: 'groups/single/plugins.php'. * @type array $screens A multi-dimensional array of configuration information for the * extension screens. See docblock of {@link BP_Group_Extension} * for more details. * @type string|array $access Which users can visit the plugin's tab. Possible values: 'anyone', * 'loggedin', 'member', 'mod', 'admin' or 'noone'. ('member', 'mod', * 'admin' refer to user's role in group.) Note that 'mod' targets * only group moderators. If you want to allow access to group moderators * and admins, specify `array( 'mod', 'admin' )`. Defaults to 'anyone' * for public groups and 'member' for private groups. * @type string|array $show_tab Which users can see the plugin's navigation tab. Possible values: * 'anyone', 'loggedin', 'member', 'mod', 'admin' or 'noone'. * ('member', 'mod', 'admin' refer to user's role in group.) Note * that 'mod' targets only group moderators. If you want to show the * tab to group moderators and admins, specify * `array( 'mod', 'admin' )`. Defaults to 'anyone' for public groups * and 'member' for private groups. * @type string|array $show_tab_callback The function to execute to set the $show_tab argument. * } */ public function init( $args = array() ) { // Store the raw arguments. $this->params_raw = $args; /* * Before this init() method was introduced, plugins were * encouraged to set their config directly. For backward * compatibility with these plugins, we detect whether this is * one of those legacy plugins, and parse any legacy arguments * with those passed to init(). */ $this->parse_legacy_properties(); $args = $this->parse_args_r( $args, $this->legacy_properties_converted ); // Parse with defaults. $this->params = $this->parse_args_r( $args, array( 'slug' => $this->slug, 'name' => $this->name, 'visibility' => $this->visibility, 'nav_item_position' => $this->nav_item_position, 'enable_nav_item' => (bool) $this->enable_nav_item, 'nav_item_name' => $this->nav_item_name, 'display_hook' => $this->display_hook, 'template_file' => $this->template_file, 'screens' => $this->get_default_screens(), 'access' => null, 'show_tab' => null, 'show_tab_callback' => '', ) ); if ( $this->params['show_tab_callback'] && is_callable( $this->params['show_tab_callback'] ) ) { $this->show_tab_callback = $this->params['show_tab_callback']; } $this->initialized = true; // Specific to BP Rewrites. $bp = buddypress(); $group_extension_class = get_class( $this ); $slug = $this->params['slug']; $name = $this->params['name']; $rewrite_id_suffix = str_replace( '-', '_', $slug ); // Populate Slugs And Names to allow BP Rewrites customizations. if ( isset( $bp->groups->group_extensions[ $group_extension_class ] ) ) { $default_data = array( 'slug' => $slug, 'name' => $name, ); $bp->groups->group_extensions[ $group_extension_class ] = array( 'read' => array( $slug => array_merge( $default_data, array( 'rewrite_id' => 'bp_group_read_' . $rewrite_id_suffix, ) ), ), 'manage' => array( $slug => array_merge( $default_data, array( 'rewrite_id' => 'bp_group_manage_' . $rewrite_id_suffix, ) ), ), 'create' => array( $slug => array_merge( $default_data, array( 'rewrite_id' => 'bp_group_create_' . $rewrite_id_suffix, ) ), ), ); if ( $this->params['nav_item_name'] ) { $bp->groups->group_extensions[ $group_extension_class ]['read']['name'] = $this->params['nav_item_name']; } foreach ( $this->params['screens'] as $screen => $data ) { $screen_key = $screen; if ( 'admin' === $screen ) { continue; } if ( 'edit' === $screen ) { $screen_key = 'manage'; } if ( ! $data['enabled'] ) { unset( $bp->groups->group_extensions[ $group_extension_class ][ $screen_key ] ); continue; } if ( isset( $data['slug'] ) && $data['slug'] ) { $bp->groups->group_extensions[ $group_extension_class ][ $screen_key ][ $slug ]['slug'] = $data['slug']; } if ( isset( $data['name'] ) && $data['name'] ) { $bp->groups->group_extensions[ $group_extension_class ][ $screen_key ][ $slug ]['name'] = $data['name']; } } } } /** * The main setup routine for the extension. * * This method contains the primary logic for setting up an extension's * configuration, setting up backward compatibility for legacy plugins, * and hooking the extension's screen functions into WP and BP. * * Marked 'public' because it must be accessible to add_action(). * However, you should never need to invoke this method yourself - it * is called automatically at the right point in the load order by * bp_register_group_extension(). * * @since 1.1.0 */ public function _register() { // phpcs:ignore PSR2.Methods.MethodDeclaration.Underscore -- Retains the established method name for backward compatibility. // Detect and parse properties set by legacy extensions. $this->parse_legacy_properties(); // Initialize, if necessary. This should only happen for // legacy extensions that don't call parent::init() themselves. if ( true !== $this->initialized ) { $this->init(); } // Set some config values, based on the parsed params. $this->group_id = $this->get_group_id(); $this->slug = $this->params['slug']; $this->name = $this->params['name']; $this->visibility = $this->params['visibility']; $this->nav_item_position = $this->params['nav_item_position']; $this->nav_item_name = $this->params['nav_item_name']; $this->display_hook = $this->params['display_hook']; $this->template_file = $this->params['template_file']; // Configure 'screens': create, admin, and edit contexts. $this->setup_screens(); // Configure access-related settings. $this->setup_access_settings(); // Mirror configuration data so it's accessible to plugins // that look for it in its old locations. $this->setup_legacy_properties(); // Hook the extension into BuddyPress. $this->setup_display_hooks(); $this->setup_create_hooks(); $this->setup_edit_hooks(); $this->setup_admin_hooks(); } /** * Set up some basic info about the Extension. * * Here we collect the name of the extending class, as well as a * ReflectionClass that is used in get_screen_callback() to determine * whether your extension overrides certain callback methods. * * @since 1.8.0 */ protected function setup_class_info() { if ( empty( $this->class_name ) ) { $this->class_name = get_class( $this ); } if ( is_null( $this->class_reflection ) ) { $this->class_reflection = new ReflectionClass( $this->class_name ); } } /** * Get the current group ID. * * Check for: * - current group * - new group * - group admin * * @since 1.8.0 * * @return int */ public static function get_group_id() { // Usually this will work. $group_id = bp_get_current_group_id(); // On the admin, get the group id out of the $_GET params. if ( empty( $group_id ) && is_admin() ) { // phpcs:disable WordPress.Security.NonceVerification $admin_page = ''; if ( isset( $_GET['page'] ) ) { $admin_page = sanitize_text_field( wp_unslash( $_GET['page'] ) ); } if ( 'bp-groups' === $admin_page && isset( $_GET['gid'] ) ) { $group_id = (int) sanitize_text_field( wp_unslash( $_GET['gid'] ) ); } // phpcs:enable WordPress.Security.NonceVerification } /* * This fallback will only be hit when the create step is very * early. */ if ( empty( $group_id ) && bp_get_new_group_id() ) { $group_id = bp_get_new_group_id(); } /* * On some setups, the group id has to be fetched out of the * $_POST array * @todo Figure out why this is happening during group creation. */ // phpcs:disable WordPress.Security.NonceVerification if ( empty( $group_id ) && isset( $_POST['group_id'] ) ) { $group_id = (int) sanitize_text_field( wp_unslash( $_POST['group_id'] ) ); } // phpcs:enable WordPress.Security.NonceVerification return $group_id; } /** * Gather configuration data about your screens. * * @since 1.8.0 * * @return array */ protected function get_default_screens() { $this->setup_class_info(); $screens = array( 'create' => array( 'position' => 81, ), 'edit' => array( 'submit_text' => __( 'Save Changes', 'buddypress' ), ), 'admin' => array( 'metabox_context' => 'normal', 'metabox_priority' => 'core', ), ); foreach ( $screens as $context => &$screen ) { $screen['enabled'] = true; $screen['name'] = $this->name; $screen['slug'] = $this->slug; $screen['screen_callback'] = $this->get_screen_callback( $context, 'screen' ); $screen['screen_save_callback'] = $this->get_screen_callback( $context, 'screen_save' ); } return $screens; } /** * Set up screens array based on params. * * @since 1.8.0 */ protected function setup_screens() { foreach ( (array) $this->params['screens'] as $context => $screen ) { if ( empty( $screen['slug'] ) ) { $screen['slug'] = $this->slug; } if ( empty( $screen['name'] ) ) { $screen['name'] = $this->name; } $this->screens[ $context ] = $screen; } } /** * Set up access-related settings for this extension. * * @since 2.1.0 */ protected function setup_access_settings() { // Bail if no group ID is available. if ( empty( $this->group_id ) ) { return; } // Backward compatibility. if ( isset( $this->params['enable_nav_item'] ) ) { $this->enable_nav_item = (bool) $this->params['enable_nav_item']; } // Tab Access. $this->user_can_visit = false; /* * Backward compatibility for components that do not provide * explicit 'access' parameter. */ if ( empty( $this->params['access'] ) ) { if ( false === $this->params['enable_nav_item'] ) { $this->params['access'] = 'noone'; } else { $group = groups_get_group( $this->group_id ); if ( ! empty( $group->status ) && 'public' === $group->status ) { // Tabs in public groups are accessible to anyone by default. $this->params['access'] = 'anyone'; } else { // All other groups have members-only as the default. $this->params['access'] = 'member'; } } } // Parse multiple access conditions into an array. $access_conditions = $this->params['access']; if ( ! is_array( $access_conditions ) ) { $access_conditions = explode( ',', $access_conditions ); } /* * If the current user meets at least one condition, the * get access. */ foreach ( $access_conditions as $access_condition ) { if ( $this->user_meets_access_condition( $access_condition ) ) { $this->user_can_visit = true; break; } } // Tab Visibility. $this->user_can_see_nav_item = false; // Use the provided callback to show or hide the Group extension tab. if ( $this->show_tab_callback ) { $this->params['show_tab'] = call_user_func_array( $this->show_tab_callback, array( $this->group_id ) ); } /* * Backward compatibility for components that do not provide * explicit 'show_tab_callback' or 'show_tab' parameters. */ if ( empty( $this->params['show_tab'] ) ) { if ( false === $this->params['enable_nav_item'] ) { /* * The enable_nav_item index is only false if it's been * defined explicitly as such in the * constructor. So we always trust this value. */ $this->params['show_tab'] = 'noone'; } elseif ( isset( $this->params_raw['enable_nav_item'] ) || isset( $this->params_raw['visibility'] ) ) { /* * If enable_nav_item or visibility is passed, * we assume this is a legacy extension. * Legacy behavior is that enable_nav_item=true + * visibility=private implies members-only. */ if ( 'public' !== $this->visibility ) { $this->params['show_tab'] = 'member'; } else { $this->params['show_tab'] = 'anyone'; } } else { /* * No show_tab or enable_nav_item value is * available, so match the value of 'access'. */ $this->params['show_tab'] = $this->params['access']; } } // Parse multiple access conditions into an array. $access_conditions = $this->params['show_tab']; if ( ! is_array( $access_conditions ) ) { $access_conditions = explode( ',', $access_conditions ); } /* * If the current user meets at least one condition, the * get access. */ foreach ( $access_conditions as $access_condition ) { if ( $this->user_meets_access_condition( $access_condition ) ) { $this->user_can_see_nav_item = true; break; } } } /** * Check whether the current user meets an access condition. * * @since 2.1.0 * * @param string $access_condition 'anyone', 'loggedin', 'member', * 'mod', 'admin' or 'noone'. * @return bool */ protected function user_meets_access_condition( $access_condition ) { switch ( $access_condition ) { case 'admin': $meets_condition = groups_is_user_admin( bp_loggedin_user_id(), $this->group_id ); break; case 'mod': $meets_condition = groups_is_user_mod( bp_loggedin_user_id(), $this->group_id ); break; case 'member': $meets_condition = groups_is_user_member( bp_loggedin_user_id(), $this->group_id ); break; case 'loggedin': $meets_condition = is_user_logged_in(); break; case 'noone': $meets_condition = false; break; case 'anyone': default: $meets_condition = true; break; } return $meets_condition; } /** Display ***********************************************************/ /** * Returns the Rewrite ID of the Group Extension Item according to the context. * * @since 12.0.0 * * @param string $context Optional. One of these contexts: 'create', 'manage', 'read'. * @return string The found Rewrite ID, an empty string otherwise. */ protected function get_rewrite_id_for( $context = '' ) { $rewrite_id = ''; $group_extensions = buddypress()->groups->group_extensions; $group_extension_class = get_class( $this ); if ( isset( $group_extensions[ $group_extension_class ][ $context ][ $this->slug ]['rewrite_id'] ) ) { $rewrite_id = $group_extensions[ $group_extension_class ][ $context ][ $this->slug ]['rewrite_id']; } return $rewrite_id; } /** * Hook this extension's group tab into BuddyPress, if necessary. * * @since 1.8.0 */ protected function setup_display_hooks() { // Bail if not a group. if ( ! bp_is_group() ) { return; } // Backward compatibility only. if ( ( 'public' !== $this->visibility ) && ! buddypress()->groups->current_group->user_has_access ) { return; } // If the user can see the nav item, we create it. $user_can_see_nav_item = $this->user_can_see_nav_item(); // If the user can visit the screen, we register it. $user_can_visit = $this->user_can_visit(); if ( $user_can_see_nav_item || $user_can_visit ) { $group_permalink = bp_get_group_url( groups_get_current_group() ); } if ( $user_can_see_nav_item ) { bp_core_create_subnav_link( array( 'name' => ! $this->nav_item_name ? $this->name : $this->nav_item_name, 'slug' => $this->slug, 'parent_slug' => bp_get_current_group_slug(), 'position' => $this->nav_item_position, 'item_css_id' => 'nav-' . $this->slug, 'screen_function' => array( &$this, '_display_hook' ), 'user_has_access' => $user_can_see_nav_item, 'no_access_url' => $group_permalink, ), 'groups' ); } if ( $user_can_visit ) { bp_core_register_subnav_screen_function( array( 'slug' => $this->slug, 'parent_slug' => bp_get_current_group_slug(), 'screen_function' => array( &$this, '_display_hook' ), 'user_has_access' => $user_can_visit, 'no_access_url' => $group_permalink, ), 'groups' ); // When we are viewing the extension display page, set the title and options title. if ( bp_is_current_action( $this->slug ) ) { add_filter( 'bp_group_user_has_access', array( $this, 'group_access_protection' ), 10, 2 ); $extension_name = $this->name; add_action( 'bp_template_content_header', function () use ( $extension_name ) { echo esc_attr( $extension_name ); } ); add_action( 'bp_template_title', function () use ( $extension_name ) { echo esc_attr( $extension_name ); } ); } } // Hook the group home widget. if ( bp_is_group_home() ) { add_action( $this->display_hook, array( &$this, 'widget_display' ) ); } } /** * Hook the main display method, and loads the template file. * * @since 1.1.0 */ public function _display_hook() { // phpcs:ignore PSR2.Methods.MethodDeclaration.Underscore -- Retains the established method name for backward compatibility. add_action( 'bp_template_content', array( &$this, 'call_display' ) ); /** * Filters the template to load for the main display method. * * @since 1.0.0 * * @param string $template_file Path to the template to load. */ bp_core_load_template( apply_filters( 'bp_core_template_plugin', $this->template_file ) ); } /** * Call the display() method. * * We use this wrapper so that we can pass the group_id to the * display() callback. * * @since 2.1.1 */ public function call_display() { $this->display(); } /** * Determine whether the current user should see this nav tab. * * Note that this controls only the display of the navigation item. * Access to the tab is controlled by the user_can_visit() check. * * @since 2.1.0 * @since 15.0.0 The `$user_can_see_nav_item` parameter was removed since it was unused. * * @return bool */ public function user_can_see_nav_item() { // Always allow moderators to see nav items, even if explicitly 'noone'. if ( ( 'noone' !== $this->params['show_tab'] ) && bp_current_user_can( 'bp_moderate' ) ) { return true; } return $this->user_can_see_nav_item; } /** * Determine whether the current user has access to visit this tab. * * Note that this controls the ability of a user to access a tab. * Display of the navigation item is controlled by user_can_see_nav_item(). * * @since 2.1.0 * @since 15.0.0 The `$user_can_visit` parameter was removed since it was unused. * * @return bool */ public function user_can_visit() { // Always allow moderators to visit a tab, even if explicitly 'noone'. if ( ( 'noone' !== $this->params['access'] ) && bp_current_user_can( 'bp_moderate' ) ) { return true; } return $this->user_can_visit; } /** * Filter the access check in bp_groups_group_access_protection() for this extension. * * Note that $no_access_args is passed by reference, as there are some * circumstances where the bp_core_no_access() arguments need to be * modified before the redirect takes place. * * @since 2.1.0 * * @param bool $user_can_visit Whether or not the user can visit the tab. * @param array $no_access_args Array of args to help determine access. * @return bool */ public function group_access_protection( $user_can_visit, &$no_access_args ) { $user_can_visit = $this->user_can_visit(); if ( ! $user_can_visit && is_user_logged_in() ) { $current_group = groups_get_group( $this->group_id ); $no_access_args['message'] = __( 'You do not have access to this content.', 'buddypress' ); $no_access_args['root'] = bp_get_group_url( $current_group, bp_groups_get_path_chunks( array( 'home' ) ) ); $no_access_args['redirect'] = false; } return $user_can_visit; } /** Create ************************************************************/ /** * Hook this extension's Create step into BuddyPress, if necessary. * * @since 1.8.0 */ protected function setup_create_hooks() { if ( ! $this->is_screen_enabled( 'create' ) ) { return; } $bp = buddypress(); $screen = $this->screens['create']; if ( ! isset( $bp->groups->group_creation_steps[ $screen['slug'] ] ) ) { $create_data = array( 'name' => $screen['name'], 'slug' => $screen['slug'], 'position' => $screen['position'], ); $rewrite_id = $this->get_rewrite_id_for( 'create' ); if ( $rewrite_id ) { $create_data['rewrite_id'] = $rewrite_id; $create_data['default_slug'] = $screen['slug']; } // Insert the group creation step for the new group extension. $bp->groups->group_creation_steps[ $screen['slug'] ] = $create_data; } /* * The maybe_ methods check to see whether the create_* * callbacks should be invoked (ie, are we on the * correct group creation step). Hooked in separate * methods because current creation step info not yet * available at this point. */ add_action( 'groups_custom_create_steps', array( $this, 'maybe_create_screen' ) ); add_action( 'groups_create_group_step_save_' . $screen['slug'], array( $this, 'maybe_create_screen_save' ) ); } /** * Call the create_screen() method, if we're on the right page. * * @since 1.8.0 */ public function maybe_create_screen() { if ( ! bp_is_group_creation_step( $this->screens['create']['slug'] ) ) { return; } call_user_func( $this->screens['create']['screen_callback'] ); $this->nonce_field( 'create' ); /* * The create screen requires an additional nonce field * due to a quirk in the way the templates are built. */ wp_nonce_field( 'groups_create_save_' . bp_get_groups_current_create_step(), '_wpnonce', false ); } /** * Call the create_screen_save() method, if we're on the right page. * * @since 1.8.0 */ public function maybe_create_screen_save() { if ( ! bp_is_group_creation_step( $this->screens['create']['slug'] ) ) { return; } $this->check_nonce( 'create' ); call_user_func( $this->screens['create']['screen_save_callback'] ); } /** Edit **************************************************************/ /** * Hook this extension's Edit panel into BuddyPress, if necessary. * * @since 1.8.0 */ protected function setup_edit_hooks() { // Bail if not in a group. if ( ! bp_is_group() ) { return; } // Bail if not an edit screen. if ( ! $this->is_screen_enabled( 'edit' ) || ! bp_is_item_admin() ) { return; } $screen = $this->screens['edit']; $position = isset( $screen['position'] ) ? (int) $screen['position'] : 10; $position += 40; $current_group = groups_get_current_group(); $subnav_args = array( 'name' => $screen['name'], 'slug' => $screen['slug'], 'parent_slug' => $current_group->slug . '_manage', 'user_has_access' => bp_is_item_admin(), 'position' => $position, 'screen_function' => 'groups_screen_group_admin', ); // Should we add a menu to the Group's WP Admin Bar. if ( ! empty( $screen['show_in_admin_bar'] ) ) { $subnav_args['show_in_admin_bar'] = true; } // Add the tab to the manage navigation. bp_core_new_subnav_item( $subnav_args, 'groups' ); // Catch the edit screen and forward it to the plugin template. if ( bp_is_groups_component() && bp_is_current_action( 'admin' ) && bp_is_action_variable( $screen['slug'], 0 ) ) { $this->call_edit_screen_save(); add_action( 'groups_custom_edit_steps', array( &$this, 'call_edit_screen' ) ); /* * Determine the proper template and save for later * loading. */ if ( '' !== bp_locate_template( array( 'groups/single/home.php' ), false ) ) { $this->edit_screen_template = '/groups/single/home'; } else { add_action( 'bp_template_content_header', function () { echo '