diff --git src/bp-core/bp-core-template.php src/bp-core/bp-core-template.php index abfb275..4dd2dd4 100644 --- src/bp-core/bp-core-template.php +++ src/bp-core/bp-core-template.php @@ -2271,6 +2271,19 @@ function bp_is_user() { } /** + * Is the current page a user custom front page? + * + * Will return true anytime there is a custom front page for the displayed user. + * + * @since 2.6.0 + * + * @return bool True if the current page is a user custom front page. + */ +function bp_is_user_front() { + return (bool) ( bp_is_user() && bp_is_current_component( 'front' ) ); +} + +/** * Is the current page a user's activity stream page? * * Eg http://example.com/members/joe/activity/ (or any subpages thereof). diff --git src/bp-members/bp-members-functions.php src/bp-members/bp-members-functions.php index 5f6fe13..1f5ffdb 100644 --- src/bp-members/bp-members-functions.php +++ src/bp-members/bp-members-functions.php @@ -2480,6 +2480,31 @@ function bp_live_spammer_login_error() { } add_action( 'login_form_bp-spam', 'bp_live_spammer_login_error' ); +/** + * Get the displayed user Object + * + * @since 2.6.0 + * + * @return object The displayed user object, null otherwise. + */ +function bp_get_displayed_user() { + $bp = buddypress(); + + $displayed_user = null; + if ( ! empty( $bp->displayed_user->id ) ) { + $displayed_user = $bp->displayed_user; + } + + /** + * Filters the displayed_user object corresponding to the displayed member. + * + * @since 2.6.0 + * + * @param object $displayed_user The displayed_user object. + */ + return apply_filters( 'bp_get_displayed_user', $displayed_user ); +} + /** Member Types *************************************************************/ /** diff --git src/bp-members/bp-members-template.php src/bp-members/bp-members-template.php index f31a3d9..632e779 100644 --- src/bp-members/bp-members-template.php +++ src/bp-members/bp-members-template.php @@ -1326,6 +1326,98 @@ function bp_get_loggedin_user_nav() { } /** + * Output the contents of the current user's home page. + * + * @since 2.6.0 + */ +function bp_displayed_user_front_template_part() { + $located = bp_displayed_user_get_front_template(); + + if ( false !== $located ) { + $slug = str_replace( '.php', '', $located ); + $name = null; + + /** + * Let plugins adding an action to bp_get_template_part get it from here + * + * @param string $slug Template part slug requested. + * @param string $name Template part name requested. + */ + do_action( 'get_template_part_' . $slug, $slug, $name ); + + load_template( $located, true ); + } + + return $located; +} + +/** + * Locate a custom user front template if it exists. + * + * @since 2.6.0 + * + * @param object|null $displayed_user Optional. Falls back to current user if not passed. + * @return string|bool Path to front template on success; boolean false on failure. + */ +function bp_displayed_user_get_front_template( $displayed_user = null ) { + if ( ! is_object( $displayed_user ) || empty( $displayed_user->id ) ) { + $displayed_user = bp_get_displayed_user(); + } + + if ( ! isset( $displayed_user->id ) ) { + return false; + } + + if ( isset( $displayed_user->front_template ) ) { + return $displayed_user->front_template; + } + + // Init the hierarchy + $template_names = array( + 'members/single/front-id-' . sanitize_file_name( $displayed_user->id ) . '.php', + 'members/single/front-nicename-' . sanitize_file_name( $displayed_user->userdata->user_nicename ) . '.php', + ); + + /** + * Check for member types and add it to the hierarchy + * + * Make sure to register your member + * type using the hook 'bp_register_member_types' + */ + if ( bp_get_member_types() ) { + $displayed_user_member_type = bp_get_member_type( $displayed_user->id ); + if ( ! $displayed_user_member_type ) { + $displayed_user_member_type = 'none'; + } + + $template_names[] = 'members/single/front-member-type-' . sanitize_file_name( $displayed_user_member_type ) . '.php'; + } + + // Add The generic template to the end of the hierarchy + $template_names[] = 'members/single/front.php'; + + /** + * Filters the hierarchy of user front templates corresponding to a specific user. + * + * @since 2.6.0 + * + * @param array $template_names Array of template paths. + */ + return bp_locate_template( apply_filters( 'bp_displayed_user_get_front_template', $template_names ), false, true ); +} + +/** + * Check if the displayed user has a custom front template. + * + * @since 2.6.0 + */ +function bp_displayed_user_has_front_template() { + $displayed_user = bp_get_displayed_user(); + + return ! empty( $displayed_user->front_template ); +} + +/** * Render the navigation markup for the displayed user. * * @since 1.1.0 diff --git src/bp-members/classes/class-bp-members-component.php src/bp-members/classes/class-bp-members-component.php index edf49a4..73b45e0 100644 --- src/bp-members/classes/class-bp-members-component.php +++ src/bp-members/classes/class-bp-members-component.php @@ -153,6 +153,11 @@ class BP_Members_Component extends BP_Component { // Initialize the nav for the members component. $this->nav = new BP_Core_Nav(); + // If A user is displayed, check if there is a front template + if ( bp_get_displayed_user() ) { + $bp->displayed_user->front_template = bp_displayed_user_get_front_template(); + } + /** Signup *********************************************************** */ @@ -178,15 +183,14 @@ class BP_Members_Component extends BP_Component { /** Default Profile Component **************************************** */ - - if ( defined( 'BP_DEFAULT_COMPONENT' ) && BP_DEFAULT_COMPONENT ) { + if ( bp_displayed_user_has_front_template() ) { + $bp->default_component = 'front'; + } elseif ( defined( 'BP_DEFAULT_COMPONENT' ) && BP_DEFAULT_COMPONENT ) { $bp->default_component = BP_DEFAULT_COMPONENT; + } elseif ( bp_is_active( 'activity' ) && isset( $bp->pages->activity ) ) { + $bp->default_component = bp_get_activity_slug(); } else { - if ( bp_is_active( 'activity' ) && isset( $bp->pages->activity ) ) { - $bp->default_component = bp_get_activity_slug(); - } else { - $bp->default_component = ( 'xprofile' === $bp->profile->id ) ? 'profile' : $bp->profile->id; - } + $bp->default_component = ( 'xprofile' === $bp->profile->id ) ? 'profile' : $bp->profile->id; } /** Canonical Component Stack **************************************** @@ -242,13 +246,15 @@ class BP_Members_Component extends BP_Component { */ public function setup_nav( $main_nav = array(), $sub_nav = array() ) { - // Bail if XProfile component is active. - if ( bp_is_active( 'xprofile' ) ) { + // Don't set up navigation if there's no member. + if ( ! is_user_logged_in() && ! bp_is_user() ) { return; } - // Don't set up navigation if there's no member. - if ( ! is_user_logged_in() && ! bp_is_user() ) { + $is_xprofile_active = bp_is_active( 'xprofile' ); + + // Bail if XProfile component is active and there's no custom front page for the user. + if ( ! bp_displayed_user_has_front_template() && $is_xprofile_active ) { return; } @@ -261,33 +267,103 @@ class BP_Members_Component extends BP_Component { return; } - $slug = bp_get_profile_slug(); - $profile_link = trailingslashit( $user_domain . $slug ); - - // Setup the main navigation. - $main_nav = array( - 'name' => _x( 'Profile', 'Member profile main navigation', 'buddypress' ), - 'slug' => $slug, - 'position' => 20, - 'screen_function' => 'bp_members_screen_display_profile', - 'default_subnav_slug' => 'public', - 'item_css_id' => buddypress()->profile->id - ); + // Set slug to profile in case the xProfile component is not active + $slug = bp_get_profile_slug(); + + // Defaults to empty navs + $this->main_nav = array(); + $this->sub_nav = array(); + + if ( ! $is_xprofile_active ) { + $this->main_nav = array( + 'name' => _x( 'Profile', 'Member profile main navigation', 'buddypress' ), + 'slug' => $slug, + 'position' => 20, + 'screen_function' => 'bp_members_screen_display_profile', + 'default_subnav_slug' => 'public', + 'item_css_id' => buddypress()->profile->id + ); + } - // Setup the subnav items for the member profile. - $sub_nav[] = array( + /** + * Setup the subnav items for the member profile. + * + * This is required in case there's a custom front or in case the xprofile component + * is not active. + */ + $this->sub_nav = array( 'name' => _x( 'View', 'Member profile view', 'buddypress' ), 'slug' => 'public', - 'parent_url' => $profile_link, + 'parent_url' => trailingslashit( $user_domain . $slug ), 'parent_slug' => $slug, 'screen_function' => 'bp_members_screen_display_profile', 'position' => 10 ); + /** + * If there's a front template the members component nav + * will be there to display the user's front page. + */ + if ( bp_displayed_user_has_front_template() ) { + $main_nav = array( + 'name' => _x( 'Home', 'Member Home page', 'buddypress' ), + 'slug' => 'front', + 'position' => 5, + 'screen_function' => 'bp_members_screen_display_profile', + 'default_subnav_slug' => 'public', + ); + + // We need a dummy subnav for the front page to load. + $front_subnav = $this->sub_nav; + $front_subnav['parent_slug'] = 'front'; + + // In case the subnav is displayed in the front template + $front_subnav['parent_url'] = trailingslashit( $user_domain . 'front' ); + + // Set the subnav + $sub_nav[] = $front_subnav; + + /** + * If the profile component is not active, we need to create a new + * nav to display the WordPress profile. + */ + if ( ! $is_xprofile_active ) { + add_action( 'bp_members_setup_nav', array( $this, 'setup_profile_nav' ) ); + } + + /** + * If there's no front template and xProfile is not active, the members + * component nav will be there to display the WordPress profile + */ + } else { + $main_nav = $this->main_nav; + $sub_nav[] = $this->sub_nav; + } + + parent::setup_nav( $main_nav, $sub_nav ); } /** + * Set up a profile nav in case the xProfile + * component is not active and a front template is + * used. + * + * @since 2.6.0 + */ + public function setup_profile_nav() { + if ( empty( $this->main_nav ) || empty( $this->sub_nav ) ) { + return; + } + + // Add the main nav + bp_core_new_nav_item( $this->main_nav, 'members' ); + + // Add the sub nav item. + bp_core_new_subnav_item( $this->sub_nav, 'members' ); + } + + /** * Set up the title for pages and