Skip to:
Content

BuddyPress.org

Ticket #4954: 4954.patch

File 4954.patch, 132.5 KB (added by imath, 5 years ago)
  • src/bp-activity/bp-activity-template.php

    diff --git src/bp-activity/bp-activity-template.php src/bp-activity/bp-activity-template.php
    index fc0e82a76..052b46b38 100644
    function bp_activity_comment_form_nojs_display() { 
    23502350        function bp_get_activity_comment_form_nojs_display() {
    23512351                global $activities_template;
    23522352
    2353                 if ( isset( $_GET['ac'] ) && ( $_GET['ac'] === ( $activities_template->activity->id . '/' ) ) ) {
     2353                $compare_with = $activities_template->activity->id . '/';
     2354                if ( bp_use_wp_rewrites() && ! bp_has_pretty_links() ) {
     2355                        $compare_with = (string) $activities_template->activity->id;
     2356                }
     2357
     2358                if ( isset( $_GET['ac'] ) && ( $_GET['ac'] === $compare_with ) ) {
    23542359                        return 'style="display: block"';
    23552360                }
    23562361
  • src/bp-activity/classes/class-bp-activity-component.php

    diff --git src/bp-activity/classes/class-bp-activity-component.php src/bp-activity/classes/class-bp-activity-component.php
    index e72d8460d..a5da9353c 100644
    class BP_Activity_Component extends BP_Component { 
    180180                        'slug'                  => BP_ACTIVITY_SLUG,
    181181                        'root_slug'             => isset( $bp->pages->activity->slug ) ? $bp->pages->activity->slug : BP_ACTIVITY_SLUG,
    182182                        'has_directory'         => true,
     183                        'rewrite_ids'           => array(
     184                                'directory'                    => 'bp_activities',
     185                                'single_item_action'           => 'bp_activity_action',
     186                                'single_item_action_variables' => 'bp_activity_action_variables',
     187                        ),
    183188                        'directory_title'       => isset( $bp->pages->activity->title ) ? $bp->pages->activity->title : $default_directory_title,
    184189                        'notification_callback' => 'bp_activity_format_notifications',
    185190                        'search_string'         => __( 'Search Activity...', 'buddypress' ),
    class BP_Activity_Component extends BP_Component { 
    226231                        'position'            => 10,
    227232                        'screen_function'     => 'bp_activity_screen_my_activity',
    228233                        'default_subnav_slug' => 'just-me',
    229                         'item_css_id'         => $this->id
     234                        'item_css_id'         => $this->id,
     235                        'rewrite_id'          => 'bp_member_' . $slug,
    230236                );
    231237
    232238                // Add the subnav items to the activity nav item if we are using a theme that supports this.
    class BP_Activity_Component extends BP_Component { 
    435441
    436442                parent::setup_cache_groups();
    437443        }
     444
     445        /**
     446         * Add the component's rewrite tags.
     447         *
     448         * @since 6.0.0
     449         *
     450         * @param array $rewrite_tags Optional. See BP_Component::add_rewrite_tags() for
     451         *                            description.
     452         */
     453        public function add_rewrite_tags( $rewrite_tags = array() ) {
     454                if ( ! bp_use_wp_rewrites() ) {
     455                        return parent::add_rewrite_tags( $rewrite_tags );
     456                }
     457
     458                $rewrite_tags = array(
     459                        'directory' => array(
     460                                'id'    => '%' . $this->rewrite_ids['directory'] . '%',
     461                                'regex' => '([1]{1,})',
     462                        ),
     463                        'single-item-action' => array(
     464                                'id'      => '%' . $this->rewrite_ids['single_item_action'] . '%',
     465                                'regex'   => '([^/]+)',
     466                        ),
     467                        'single-item-action-variables' => array(
     468                                'id'      => '%' . $this->rewrite_ids['single_item_action_variables'] . '%',
     469                                'regex'   => '([^/]+)',
     470                        ),
     471                );
     472
     473                parent::add_rewrite_tags( $rewrite_tags );
     474        }
     475
     476        /**
     477         * Add the component's rewrite rules.
     478         *
     479         * @since 6.0.0
     480         *
     481         * @param array $rewrite_rules Optional. See BP_Component::add_rewrite_rules() for
     482         *                             description.
     483         */
     484        public function add_rewrite_rules( $rewrite_rules = array() ) {
     485                if ( ! bp_use_wp_rewrites() ) {
     486                        return parent::add_rewrite_rules( $rewrite_rules );
     487                }
     488
     489                $rewrite_rules = array(
     490                        'paged-directory' => array(
     491                                'regex' => $this->root_slug . '/page/?([0-9]{1,})/?$',
     492                                'query' => 'index.php?' . $this->rewrite_ids['directory'] . '=1&paged=$matches[1]',
     493                        ),
     494                        'single-item-action-variables' => array(
     495                                'regex' => $this->root_slug . '/([^/]+)\/(.+?)/?$',
     496                                'query' => 'index.php?' . $this->rewrite_ids['directory'] . '=1&' . $this->rewrite_ids['single_item_action'] . '=$matches[1]&' . $this->rewrite_ids['single_item_action_variables'] . '=$matches[2]',
     497                        ),
     498                        'single-item-action' => array(
     499                                'regex' => $this->root_slug . '/([^/]+)/?$',
     500                                'query' => 'index.php?' . $this->rewrite_ids['directory'] . '=1&' . $this->rewrite_ids['single_item_action'] . '=$matches[1]',
     501                        ),
     502                        'directory' => array(
     503                                'regex' => $this->root_slug,
     504                                'query' => 'index.php?' . $this->rewrite_ids['directory'] . '=1',
     505                        ),
     506                );
     507
     508                parent::add_rewrite_rules( $rewrite_rules );
     509        }
     510
     511        /**
     512         * Add the component's directory permastructs.
     513         *
     514         * @since 6.0.0
     515         *
     516         * @param array $structs Optional. See BP_Component::add_permastructs() for
     517         *                       description.
     518         */
     519        public function add_permastructs( $structs = array() ) {
     520                if ( ! bp_use_wp_rewrites() ) {
     521                        return parent::add_permastructs( $structs );
     522                }
     523
     524                $permastructs = array(
     525                        // Directory permastruct.
     526                        $this->rewrite_ids['directory'] => array(
     527                                'struct' => $this->directory_permastruct,
     528                                'args'   => array(),
     529                        ),
     530                );
     531
     532                parent::add_permastructs( $permastructs );
     533        }
     534
     535        /**
     536         * Parse the WP_Query and eventually display the component's directory or single item.
     537         *
     538         * @since 6.0.0
     539         *
     540         * @param WP_Query $query Required. See BP_Component::parse_query() for
     541         *                        description.
     542         */
     543        public function parse_query( WP_Query $query ) {
     544                if ( ! bp_use_wp_rewrites() ) {
     545                        return parent::parse_query( $query );
     546                }
     547
     548                $is_activity_component  = 1 === (int) $query->get( $this->rewrite_ids['directory'] );
     549                $bp                     = buddypress();
     550
     551                if ( $is_activity_component ) {
     552                        $bp->current_component = 'activity';
     553
     554                        $current_action = $query->get( $this->rewrite_ids['single_item_action'] );
     555                        if ( $current_action ) {
     556                                $bp->current_action = $current_action;
     557                        }
     558
     559                        $action_variables = $query->get( $this->rewrite_ids['single_item_action_variables'] );
     560                        if ( $action_variables ) {
     561                                if ( ! is_array( $action_variables ) )  {
     562                                        $bp->action_variables = explode( '/', ltrim( $action_variables, '/' ) );
     563                                } else {
     564                                        $bp->action_variables = $action_variables;
     565                                }
     566                        }
     567
     568                        /**
     569                         * Set the BuddyPress queried object.
     570                         */
     571                        $query->queried_object    = get_post( $bp->pages->activity->id );
     572                        $query->queried_object_id = $query->queried_object->ID;
     573                }
     574
     575                parent::parse_query( $query );
     576        }
    438577}
  • src/bp-blogs/bp-blogs-template.php

    diff --git src/bp-blogs/bp-blogs-template.php src/bp-blogs/bp-blogs-template.php
    index a985d22cb..e036bf678 100644
    function bp_blogs_directory_permalink() { 
    9595                return apply_filters( 'bp_get_blogs_directory_permalink', trailingslashit( bp_get_root_domain() . '/' . bp_get_blogs_root_slug() ) );
    9696        }
    9797
     98/**
     99 * Output the create blog link.
     100 *
     101 * @since 6.0.0
     102 *
     103 */
     104function bp_blog_create_link() {
     105        echo esc_url( bp_get_blog_create_link() );
     106}
     107        /**
     108         * Return the create blog link.
     109         *
     110         * @since 6.0.0
     111         *
     112         * @return string The URL of the create blog link.
     113         */
     114        function bp_get_blog_create_link() {
     115
     116                /**
     117                 * Filters the blog create blog link.
     118                 *
     119                 * @since 6.0.0
     120                 *
     121                 * @param string $value Permalink URL for the create blog link.
     122                 */
     123                return apply_filters( 'bp_get_blog_create_link', trailingslashit( bp_get_root_domain() . '/' . bp_get_blogs_root_slug() ) . 'create/' );
     124        }
     125
    98126/**
    99127 * Rewind the blogs and reset blog index.
    100128 */
    function bp_blog_create_button() { 
    13541382                        'component'  => 'blogs',
    13551383                        'link_text'  => __( 'Create a Site', 'buddypress' ),
    13561384                        'link_class' => 'blog-create no-ajax',
    1357                         'link_href'  => trailingslashit( bp_get_blogs_directory_permalink() . 'create' ),
     1385                        'link_href'  => bp_get_blog_create_link(),
    13581386                        'wrapper'    => false,
    13591387                        'block_self' => false,
    13601388                );
  • src/bp-blogs/classes/class-bp-blogs-component.php

    diff --git src/bp-blogs/classes/class-bp-blogs-component.php src/bp-blogs/classes/class-bp-blogs-component.php
    index a1be1e808..4bc8a1008 100644
    class BP_Blogs_Component extends BP_Component { 
    7575                        'slug'                  => BP_BLOGS_SLUG,
    7676                        'root_slug'             => isset( $bp->pages->blogs->slug ) ? $bp->pages->blogs->slug : BP_BLOGS_SLUG,
    7777                        'has_directory'         => is_multisite(), // Non-multisite installs don't need a top-level Sites directory, since there's only one site.
     78                        'rewrite_ids'           => array(
     79                                'directory'                    => 'bp_blogs',
     80                                'single_item_action'           => 'bp_blogs_action',
     81                                'single_item_action_variables' => 'bp_blogs_action_variables',
     82                        ),
    7883                        'directory_title'       => isset( $bp->pages->blogs->title ) ? $bp->pages->blogs->title : $default_directory_title,
    7984                        'notification_callback' => 'bp_blogs_format_notifications',
    8085                        'search_string'         => __( 'Search sites...', 'buddypress' ),
    class BP_Blogs_Component extends BP_Component { 
    233238                        'position'            => 30,
    234239                        'screen_function'     => 'bp_blogs_screen_my_blogs',
    235240                        'default_subnav_slug' => 'my-sites',
    236                         'item_css_id'         => $this->id
     241                        'item_css_id'         => $this->id,
     242                        'rewrite_id'          => 'bp_member_' . $slug,
    237243                );
    238244
    239245                $sub_nav[] = array(
    class BP_Blogs_Component extends BP_Component { 
    300306                                        'parent'   => 'my-account-' . $this->id,
    301307                                        'id'       => 'my-account-' . $this->id . '-create',
    302308                                        'title'    => __( 'Create a Site', 'buddypress' ),
    303                                         'href'     => trailingslashit( bp_get_blogs_directory_permalink() . 'create' ),
     309                                        'href'     => bp_get_blog_create_link(),
    304310                                        'position' => 99
    305311                                );
    306312                        }
    class BP_Blogs_Component extends BP_Component { 
    352358
    353359                parent::setup_cache_groups();
    354360        }
     361
     362        /**
     363         * Add the component's rewrite tags.
     364         *
     365         * @since 6.0.0
     366         *
     367         * @param array $rewrite_tags Optional. See BP_Component::add_rewrite_tags() for
     368         *                            description.
     369         */
     370        public function add_rewrite_tags( $rewrite_tags = array() ) {
     371                if ( ! bp_use_wp_rewrites() || ! is_multisite() ) {
     372                        return parent::add_rewrite_tags( $rewrite_tags );
     373                }
     374
     375                $rewrite_tags = array(
     376                        'directory' => array(
     377                                'id'    => '%' . $this->rewrite_ids['directory'] . '%',
     378                                'regex' => '([1]{1,})',
     379                        ),
     380                        'single-item-action' => array(
     381                                'id'      => '%' . $this->rewrite_ids['single_item_action'] . '%',
     382                                'regex'   => '([^/]+)',
     383                        ),
     384                        'single-item-action-variables' => array(
     385                                'id'      => '%' . $this->rewrite_ids['single_item_action_variables'] . '%',
     386                                'regex'   => '([^/]+)',
     387                        ),
     388                );
     389
     390                parent::add_rewrite_tags( $rewrite_tags );
     391        }
     392
     393        /**
     394         * Add the component's rewrite rules.
     395         *
     396         * @since 6.0.0
     397         *
     398         * @param array $rewrite_rules Optional. See BP_Component::add_rewrite_rules() for
     399         *                             description.
     400         */
     401        public function add_rewrite_rules( $rewrite_rules = array() ) {
     402                if ( ! bp_use_wp_rewrites() || ! is_multisite() ) {
     403                        return parent::add_rewrite_rules( $rewrite_rules );
     404                }
     405
     406                $rewrite_rules = array(
     407                        'paged-directory' => array(
     408                                'regex' => $this->root_slug . '/page/?([0-9]{1,})/?$',
     409                                'query' => 'index.php?' . $this->rewrite_ids['directory'] . '=1&paged=$matches[1]',
     410                        ),
     411                        'single-item-action-variables' => array(
     412                                'regex' => $this->root_slug . '/([^/]+)\/(.+?)/?$',
     413                                'query' => 'index.php?' . $this->rewrite_ids['directory'] . '=1&' . $this->rewrite_ids['single_item_action'] . '=$matches[1]&' . $this->rewrite_ids['single_item_action_variables'] . '=$matches[2]',
     414                        ),
     415                        'single-item-action' => array(
     416                                'regex' => $this->root_slug . '/([^/]+)/?$',
     417                                'query' => 'index.php?' . $this->rewrite_ids['directory'] . '=1&' . $this->rewrite_ids['single_item_action'] . '=$matches[1]',
     418                        ),
     419                        'directory' => array(
     420                                'regex' => $this->root_slug,
     421                                'query' => 'index.php?' . $this->rewrite_ids['directory'] . '=1',
     422                        ),
     423                );
     424
     425                parent::add_rewrite_rules( $rewrite_rules );
     426        }
     427
     428        /**
     429         * Add the component's directory permastructs.
     430         *
     431         * @since 6.0.0
     432         *
     433         * @param array $structs Optional. See BP_Component::add_permastructs() for
     434         *                       description.
     435         */
     436        public function add_permastructs( $structs = array() ) {
     437                if ( ! bp_use_wp_rewrites() || ! is_multisite() ) {
     438                        return parent::add_permastructs( $structs );
     439                }
     440
     441                $permastructs = array(
     442                        // Directory permastruct.
     443                        $this->rewrite_ids['directory'] => array(
     444                                'struct' => $this->directory_permastruct,
     445                                'args'   => array(),
     446                        ),
     447                );
     448
     449                parent::add_permastructs( $permastructs );
     450        }
     451
     452        /**
     453         * Parse the WP_Query and eventually display the component's directory or single item.
     454         *
     455         * @since 6.0.0
     456         *
     457         * @param WP_Query $query Required. See BP_Component::parse_query() for
     458         *                        description.
     459         */
     460        public function parse_query( WP_Query $query ) {
     461                if ( ! bp_use_wp_rewrites() || ! is_multisite() ) {
     462                        return parent::parse_query( $query );
     463                }
     464
     465                $is_blogs_component  = 1 === (int) $query->get( $this->rewrite_ids['directory'] );
     466                $bp                     = buddypress();
     467
     468                if ( $is_blogs_component ) {
     469                        $bp->current_component = 'blogs';
     470
     471                        $current_action = $query->get( $this->rewrite_ids['single_item_action'] );
     472                        if ( $current_action ) {
     473                                $bp->current_action = $current_action;
     474                        }
     475
     476                        $action_variables = $query->get( $this->rewrite_ids['single_item_action_variables'] );
     477                        if ( $action_variables ) {
     478                                if ( ! is_array( $action_variables ) )  {
     479                                        $bp->action_variables = explode( '/', ltrim( $action_variables, '/' ) );
     480                                } else {
     481                                        $bp->action_variables = $action_variables;
     482                                }
     483                        }
     484
     485                        /**
     486                         * Set the BuddyPress queried object.
     487                         */
     488                        $query->queried_object    = get_post( $bp->pages->blogs->id );
     489                        $query->queried_object_id = $query->queried_object->ID;
     490                }
     491
     492                parent::parse_query( $query );
     493        }
    355494}
  • src/bp-core/admin/bp-core-admin-components.php

    diff --git src/bp-core/admin/bp-core-admin-components.php src/bp-core/admin/bp-core-admin-components.php
    index 11dbfe722..55c9fd772 100644
    function bp_core_admin_components_settings_handler() { 
    268268                // Load up BuddyPress.
    269269                $bp = buddypress();
    270270
     271                // Save a copy of the current active components
     272                $active_components = $bp->active_components;
     273
    271274                // Save settings and upgrade schema.
    272275                require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
    273276                require_once( $bp->plugin_dir . '/bp-core/admin/bp-core-admin-schema.php' );
    function bp_core_admin_components_settings_handler() { 
    278281                bp_core_install( $bp->active_components );
    279282                bp_core_add_page_mappings( $bp->active_components );
    280283                bp_update_option( 'bp-active-components', $bp->active_components );
     284
     285                // Compare the copy of active components with submitted one to eventually update rewrite rules.
     286                if ( bp_use_wp_rewrites() && array_diff_key( $active_components, $bp->active_components ) ) {
     287                        bp_delete_rewrite_rules();
     288                }
    281289        }
    282290
    283291        // Where are we redirecting to?
  • src/bp-core/admin/bp-core-admin-functions.php

    diff --git src/bp-core/admin/bp-core-admin-functions.php src/bp-core/admin/bp-core-admin-functions.php
    index 609453741..82198bfc6 100644
    function bp_core_activation_notice() { 
    239239        }
    240240
    241241        // Add notice if no rewrite rules are enabled.
    242         if ( empty( $wp_rewrite->permalink_structure ) ) {
     242        if ( empty( $wp_rewrite->permalink_structure ) && ! bp_use_wp_rewrites() ) {
    243243                bp_core_add_admin_notice( sprintf( __( '<strong>BuddyPress is almost ready</strong>. You must <a href="%s">update your permalink structure</a> to something other than the default for it to work.', 'buddypress' ), admin_url( 'options-permalink.php' ) ), 'error' );
    244244        }
    245245
    function bp_core_get_admin_tabs( $active_tab = '' ) { 
    435435                ),
    436436        );
    437437
     438        if ( bp_use_wp_rewrites() ) {
     439                $tabs['1'] = array(
     440                        'href' => bp_get_admin_url( add_query_arg( array( 'page' => 'bp-rewrites-settings' ), 'admin.php' ) ),
     441                        'name' => __( 'URLs', 'buddypress' )
     442                );
     443        }
     444
    438445        /**
    439446         * Filters the tab data used in our wp-admin screens.
    440447         *
  • new file src/bp-core/admin/bp-core-admin-rewrites.php

    diff --git src/bp-core/admin/bp-core-admin-rewrites.php src/bp-core/admin/bp-core-admin-rewrites.php
    new file mode 100644
    index 000000000..852ac0d4c
    - +  
     1<?php
     2/**
     3 * BuddyPress Admin Rewrites Functions.
     4 *
     5 * @package BuddyPress
     6 * @subpackage CoreAdministration
     7 * @since 6.0.0
     8 */
     9
     10// Exit if accessed directly.
     11defined( 'ABSPATH' ) || exit;
     12
     13/**
     14 * Renders BuddyPress URLs admin panel.
     15 *
     16 * @since 6.0.O
     17 */
     18function bp_core_admin_rewrites_settings() {
     19        $bp = buddypress();
     20?>
     21
     22        <div class="wrap">
     23
     24                <h1><?php esc_html_e( 'BuddyPress URLs', 'buddypress' ); ?> </h1>
     25
     26                <h2 class="nav-tab-wrapper"><?php bp_core_admin_tabs( __( 'URLs', 'buddypress' ) ); ?></h2>
     27                <form action="" method="post" id="bp-admin-rewrites-form">
     28
     29                        <?php foreach ( $bp->pages as $component_id => $directory_data ) : ?>
     30
     31                                <h2><?php echo esc_html( $directory_data->title ); ?></h2>
     32                                <table class="form-table" role="presentation">
     33                                        <tr>
     34                                                <th scope="row">
     35                                                        <label for="<?php printf( esc_attr__( '%s-directory-slug', 'buddypress' ), $component_id ); ?>">
     36                                                                <?php printf( esc_html__( 'Directory slug', 'buddypress' ), $directory_data->title ); ?>
     37                                                        </label>
     38                                                </th>
     39                                                <td>
     40                                                        <input type="text" class="code" name="<?php printf( 'components[%d][post_name]', absint( $directory_data->id ) ); ?>" id="<?php printf( esc_attr__( '%s-directory-slug', 'buddypress' ), $component_id ); ?>" value="<?php echo esc_attr( $directory_data->slug ); ?>">
     41                                                </td>
     42                                        </tr>
     43                                </table>
     44
     45                                <?php if ( 'members' === $component_id ) : ?>
     46                                        <h3><?php esc_html_e( 'Single Member primary navigation slugs', 'buddypress' ); ?></h3>
     47                                        <table class="form-table" role="presentation">
     48                                                <?php foreach ( $bp->members->nav->get_primary() as $primary_nav_item ) :
     49                                                        if ( ! isset( $primary_nav_item['rewrite_id'] ) || ! $primary_nav_item['rewrite_id'] ) {
     50                                                                continue;
     51                                                        }
     52                                                ?>
     53                                                        <tr>
     54                                                                <th scope="row">
     55                                                                        <label style="margin-left: 2em; display: inline-block; vertical-align: middle" for="<?php printf( esc_attr__( '%s-slug', 'buddypress' ), $primary_nav_item['rewrite_id'] ); ?>">
     56                                                                                <?php printf( esc_html__( '"%s" slug', 'buddypress' ), $primary_nav_item['name'] ); ?>
     57                                                                        </label>
     58                                                                </th>
     59                                                                <td>
     60                                                                        <input type="text" class="code" name="<?php printf( 'components[%1$d][_bp_component_slugs][%2$s]', absint( $directory_data->id ), esc_attr( $primary_nav_item['rewrite_id'] ) ); ?>" id="<?php printf( esc_attr__( '%s-slug', 'buddypress' ), $primary_nav_item['rewrite_id'] ); ?>" value="<?php echo esc_attr( bp_rewrites_get_slug( $component_id, $primary_nav_item['rewrite_id'], $primary_nav_item['slug'] ) ); ?>">
     61                                                                </td>
     62                                                        </tr>
     63                                                <?php endforeach ; ?>
     64                                        </table>
     65                                <?php endif ; ?>
     66
     67                        <?php endforeach ; ?>
     68
     69                        <p class="submit clear">
     70                                <input class="button-primary" type="submit" name="bp-admin-rewrites-submit" id="bp-admin-rewrites-submit" value="<?php esc_attr_e( 'Save Settings', 'buddypress' ) ?>"/>
     71                        </p>
     72
     73                        <?php wp_nonce_field( 'bp-admin-rewrites-setup' ); ?>
     74
     75                </form>
     76        </div>
     77
     78<?php
     79}
     80
     81/**
     82 * Switch directory pages between the `page` & the `bp_directories`
     83 * post types and update WP Nav items.
     84 *
     85 * This is what allowes a user to test our new parser, making sure he can
     86 * come back to the legacy one in case a plugin/theme is not ready yet.
     87 *
     88 * @since 6.0.0
     89 *
     90 * @param bool $use_rewrite Whether to use the Legacy parser or the WP Rewrites.
     91 */
     92function bp_core_admin_rewrites_update_directory_pages( $use_rewrite = false ) {
     93        $bp_pages          = bp_core_get_directory_pages();
     94        $nav_menu_item_ids = array();
     95
     96        $post_type   = 'page';
     97        $item_object = 'bp_directories';
     98        if ( $use_rewrite ) {
     99                $post_type = 'bp_directories';
     100                $item_object = 'page';
     101        }
     102
     103        foreach ( $bp_pages as $bp_page ) {
     104                $nav_menu_item_ids[] = $bp_page->id;
     105
     106                // Switch the post type.
     107                wp_update_post( array( 'ID' => $bp_page->id, 'post_type' => $post_type ) );
     108        }
     109
     110        // Update nav menu items!
     111        $nav_menus = wp_get_nav_menus( array( 'hide_empty' => true ) );
     112        foreach ( $nav_menus as $nav_menu ) {
     113                $items = wp_get_nav_menu_items( $nav_menu->term_id );
     114
     115                foreach( $items as $item ) {
     116                        if ( $item_object !== $item->object || ! in_array( $item->object_id, $nav_menu_item_ids, true ) ) {
     117                                continue;
     118                        }
     119
     120                        wp_update_nav_menu_item( $nav_menu->term_id, $item->ID, array(
     121                                'menu-item-db-id'       => $item->db_id,
     122                                'menu-item-object-id'   => $item->object_id,
     123                                'menu-item-object'      => $post_type,
     124                                'menu-item-parent-id'   => $item->menu_item_parent,
     125                                'menu-item-position'    => $item->menu_order,
     126                                'menu-item-type'        => 'post_type',
     127                                'menu-item-title'       => $item->title,
     128                                'menu-item-url'         => $item->url,
     129                                'menu-item-description' => $item->description,
     130                                'menu-item-attr-title'  => $item->attr_title,
     131                                'menu-item-target'      => $item->target,
     132                                'menu-item-classes'     => implode( ' ', (array) $item->classes ),
     133                                'menu-item-xfn'         => $item->xfn,
     134                                'menu-item-status'      => 'publish',
     135                        ) );
     136                }
     137        }
     138}
     139
     140/**
     141 * Handle saving of the BuddyPress customizable slugs.
     142 *
     143 * @since 6.0.0
     144 */
     145function bp_core_admin_rewrites_setup_handler() {
     146
     147        if ( ! isset( $_POST['bp-admin-rewrites-submit'] ) ) {
     148                return;
     149        }
     150
     151        check_admin_referer( 'bp-admin-rewrites-setup' );
     152
     153        $base_url = bp_get_admin_url( add_query_arg( 'page', 'bp-rewrites-settings', 'admin.php' ) );
     154
     155        if ( ! isset( $_POST['components'] ) ) {
     156                wp_safe_redirect( add_query_arg( 'error', 'true', $base_url ) );
     157        }
     158
     159        $current_page_slugs   = wp_list_pluck( bp_core_get_directory_pages(), 'slug', 'id' );
     160        $directory_slug_edits = array();
     161        foreach ( $_POST['components'] as $page_id => $slugs ) {
     162                $postarr = array();
     163
     164                if ( ! isset( $current_page_slugs[ $page_id ] ) )  {
     165                        continue;
     166                }
     167
     168                $postarr['ID'] = $page_id;
     169
     170                if ( $current_page_slugs[ $page_id ] !== $slugs['post_name'] ) {
     171                        $directory_slug_edits[] = $page_id;
     172                        $postarr['post_name'] = $slugs['post_name'];
     173                }
     174
     175                if ( isset( $slugs['_bp_component_slugs'] ) && is_array( $slugs['_bp_component_slugs'] ) ) {
     176                        $postarr['meta_input']['_bp_component_slugs'] = array_map( 'sanitize_title', $slugs['_bp_component_slugs'] );
     177                }
     178
     179                wp_update_post( $postarr );
     180        }
     181
     182        // Make sure the WP rewrites will be regenarated at next page load.
     183        if ( $directory_slug_edits ) {
     184                bp_delete_rewrite_rules();
     185        }
     186
     187        wp_safe_redirect( add_query_arg( 'updated', 'true', $base_url ) );
     188}
     189add_action( 'bp_admin_init', 'bp_core_admin_rewrites_setup_handler' );
  • src/bp-core/admin/bp-core-admin-settings.php

    diff --git src/bp-core/admin/bp-core-admin-settings.php src/bp-core/admin/bp-core-admin-settings.php
    index 2bab95e9e..bf6920825 100644
    function bp_admin_setting_callback_theme_package_id() { 
    7979        <?php endif;
    8080}
    8181
     82function bp_admin_setting_callback_use_wp_rewrites() {
     83?>
     84
     85        <input id="_bp_use_wp_rewrites" name="_bp_use_wp_rewrites" type="checkbox" value="1" <?php checked( bp_use_wp_rewrites() ); ?> />
     86        <strong><?php esc_html_e( 'Experimental', 'buddypress' ); ?></strong>
     87        <p id="_bp_use_wp_rewrites_description" class="description">
     88                <?php esc_html_e( 'By enabling this option, you will be able to try a more WordPress friendly way of building/analysing BuddyPress URLs.', 'buddypress' ); ?>&nbsp;
     89                <?php esc_html_e( 'The "Pages" tab will be replaced by a "URLs" one, and you will be able to customize BuddyPress URLs.', 'buddypress' ); ?>&nbsp;
     90                <?php esc_html_e( 'If some of your BuddyPress plugins are not ready yet for this great feature, no worries: you can come back at any time to our legacy way of building/analysing BuddyPress URLs by disabling this option.', 'buddypress' ); ?>
     91        </p>
     92<?php
     93}
     94
    8295/** Activity *******************************************************************/
    8396
    8497/**
    function bp_core_admin_settings_save() { 
    294307        if ( isset( $_GET['page'] ) && 'bp-settings' == $_GET['page'] && !empty( $_POST['submit'] ) ) {
    295308                check_admin_referer( 'buddypress-options' );
    296309
     310                // Maybe update rewrite rules.
     311                $use_rewrite = bp_use_wp_rewrites();
     312                if ( ( ! isset( $_POST['_bp_use_wp_rewrites'] ) && $use_rewrite ) || ( isset( $_POST['_bp_use_wp_rewrites'] ) && ! $use_rewrite ) ) {
     313                        bp_delete_rewrite_rules();
     314                        bp_core_admin_rewrites_update_directory_pages( isset( $_POST['_bp_use_wp_rewrites'] ) );
     315                }
     316
    297317                // Because many settings are saved with checkboxes, and thus will have no values
    298318                // in the $_POST array when unchecked, we loop through the registered settings.
    299319                if ( isset( $wp_settings_fields['buddypress'] ) ) {
  • src/bp-core/bp-core-buddybar.php

    diff --git src/bp-core/bp-core-buddybar.php src/bp-core/bp-core-buddybar.php
    index c78061049..b08fe59f3 100644
    defined( 'ABSPATH' ) || exit; 
    3434 *     @type callable    $screen_function         The callback function that will run when the nav item is clicked.
    3535 *     @type bool|string $default_subnav_slug     Optional. The slug of the default subnav item to select when the nav
    3636 *                                                item is clicked.
     37 *     @type string      $rewrite_id              Optional. The rewrite id to allow slug customization.
    3738 * }
    3839 * @param string       $component The component the navigation is attached to. Defaults to 'members'.
    3940 * @return null|false Returns false on failure.
    function bp_core_new_nav_item( $args, $component = 'members' ) { 
    5253                'site_admin_only'         => false, // Can only site admins see this nav item?
    5354                'position'                => 99,    // Index of where this nav item should be positioned.
    5455                'screen_function'         => false, // The name of the function to run when clicked.
    55                 'default_subnav_slug'     => false  // The slug of the default subnav item to select when clicked.
     56                'default_subnav_slug'     => false, // The slug of the default subnav item to select when clicked.
     57                'rewrite_id'              => '',    // The rewrite id to allow slug customization.
    5658        );
    5759
    5860        $r = wp_parse_args( $args, $defaults );
    function bp_core_new_nav_item( $args, $component = 'members' ) { 
    9698 * @since 2.6.0 Introduced the `$component` parameter. Began returning a BP_Core_Nav_Item
    9799 *              object on success.
    98100 * @since 4.0.0 Introduced `$component_id` argument.
     101 * @since 6.0.0 Introduced the dynamic filter `bp_{$component}_nav_add_item_link`.
    99102 *
    100103 * @param array|string $args {
    101104 *     Array describing the new nav item.
    function bp_core_new_nav_item( $args, $component = 'members' ) { 
    113116 *     @type callable    $screen_function         The callback function that will run when the nav item is clicked.
    114117 *     @type bool|string $default_subnav_slug     Optional. The slug of the default subnav item to select when the nav
    115118 *                                                item is clicked.
     119 *     @type string      $rewrite_id              Optional. The rewrite id to allow slug customization.
    116120 * }
    117121 * @param string       $component Optional. Component that the nav belongs to.
    118122 * @return false|array Returns false on failure, new nav item on success.
    function bp_core_create_nav_link( $args = '', $component = 'members' ) { 
    129133                'site_admin_only'         => false, // Can only site admins see this nav item?
    130134                'position'                => 99,    // Index of where this nav item should be positioned.
    131135                'screen_function'         => false, // The name of the function to run when clicked.
    132                 'default_subnav_slug'     => false  // The slug of the default subnav item to select when clicked.
     136                'default_subnav_slug'     => false, // The slug of the default subnav item to select when clicked.
     137                'rewrite_id'              => '',    // The rewrite id to allow slug customization.
    133138        );
    134139
    135140        $r = wp_parse_args( $args, $defaults );
    function bp_core_create_nav_link( $args = '', $component = 'members' ) { 
    152157                $r['item_css_id'] = $r['slug'];
    153158        }
    154159
    155         $nav_item = array(
     160        /**
     161         * Filter here to edit the component's nav item parameters just before it is added.
     162         *
     163         * The dynamic portion of the hook will be the component's id the nav item is created for.
     164         *
     165         * @since 6.0.0
     166         *
     167         * @param array $value {
     168         *     Array describing the new nav item.
     169         *     @type string      $component_id            Optional. The ID of the component registering this nav item. Defaults to the
     170         *                                                the value of `$slug`.
     171         *     @type string      $name                    Display name for the nav item.
     172         *     @type string      $slug                    Unique URL slug for the nav item.
     173         *     @type string      $link                    The link for the nav item.
     174         *     @type bool|string $item_css_id             Optional. 'id' attribute for the nav item. Default: the value of `$slug`.
     175         *     @type bool        $show_for_displayed_user Optional. Whether the nav item should be visible when viewing a
     176         *                                                member profile other than your own. Default: true.
     177         *     @type int         $position                Optional. Numerical index specifying where the item should appear in
     178         *                                                the nav array. Default: 99.
     179         *     @type callable    $screen_function         The callback function that will run when the nav item is clicked.
     180         *     @type bool|string $default_subnav_slug     Optional. The slug of the default subnav item to select when the nav
     181         *                                                item is clicked.
     182         *     @type string      $rewrite_id              Optional. The rewrite id to allow slug customization.
     183         * }
     184         */
     185        $nav_item = apply_filters( "bp_{$component}_nav_add_item_link", array(
    156186                'component_id'            => $r['component_id'],
    157187                'name'                    => $r['name'],
    158188                'slug'                    => $r['slug'],
    function bp_core_create_nav_link( $args = '', $component = 'members' ) { 
    161191                'show_for_displayed_user' => $r['show_for_displayed_user'],
    162192                'position'                => $r['position'],
    163193                'screen_function'         => &$r['screen_function'],
    164                 'default_subnav_slug'     => $r['default_subnav_slug']
    165         );
     194                'default_subnav_slug'     => $r['default_subnav_slug'],
     195                'rewrite_id'              => $r['rewrite_id'],
     196        ) );
    166197
    167198        // Add the item to the nav.
    168199        buddypress()->{$component}->nav->add_nav( $nav_item );
    function bp_core_new_subnav_item( $args, $component = null ) { 
    475506 *
    476507 * @since 2.4.0
    477508 * @since 2.6.0 Introduced the `$component` parameter. Began returning a BP_Core_Nav_Item object on success.
     509 * @since 6.0.0 Introduced the dynamic filter `bp_{$component}_subnav_add_item_link`.
    478510 *
    479511 * @param array|string $args {
    480512 *     Array describing the new subnav item.
    function bp_core_create_subnav_link( $args = '', $component = 'members' ) { 
    551583                $r['item_css_id'] = $r['slug'];
    552584        }
    553585
    554         $subnav_item = array(
     586        /**
     587        * Filter here to edit the component's sub nav item parameters just before it is added.
     588        *
     589        * The dynamic portion of the hook will be the component's id the nav item is created for.
     590        *
     591        * @since 6.0.0
     592        *
     593        * @param array $value {
     594        *     Array describing the new nav item.
     595        *     @type string      $name              Display name for the subnav item.
     596        *     @type string      $link              The link for the subnav item.
     597        *     @type string      $slug              Unique URL slug for the subnav item.
     598        *     @type string      $parent_slug       Slug of the top-level nav item under which the
     599        *                                          new subnav item should be added.
     600        *     @type bool|string $item_css_id       Optional. 'id' attribute for the subnav item. Default: the value of `$slug`.
     601        *     @type int         $position          Optional. Numerical index specifying where the item should appear in
     602        *                                          the subnav array. Default: 99.
     603        *     @type bool        $user_has_access   Optional. True if the logged-in user has access to the
     604        *                                          subnav item, otherwise false. Can be set dynamically
     605        *                                          when registering the subnav; eg, use bp_is_my_profile()
     606        *                                          to restrict access to profile owners only. Default: true.
     607        *     @type string      $no_access_url     The link to redirect to if the user can't access the subnav item.
     608        *     @type callable    $screen_function   The callback function that will run when the subnav item is clicked.
     609        *     @type bool        $show_in_admin_bar Optional. Whether the subnav item should be added into
     610        *                                          the group's "Edit" Admin Bar menu for group admins.
     611        *                                          Default: false.
     612        * }
     613        */
     614        $subnav_item = apply_filters( "bp_{$component}_subnav_add_item_link", array(
    555615                'name'              => $r['name'],
    556616                'link'              => $r['link'],
    557617                'slug'              => $r['slug'],
    function bp_core_create_subnav_link( $args = '', $component = 'members' ) { 
    562622                'no_access_url'     => $r['no_access_url'],
    563623                'screen_function'   => &$r['screen_function'],
    564624                'show_in_admin_bar' => (bool) $r['show_in_admin_bar'],
    565         );
     625        ) );
    566626
    567627        buddypress()->{$component}->nav->add_nav( $subnav_item );
    568628
  • src/bp-core/bp-core-catchuri.php

    diff --git src/bp-core/bp-core-catchuri.php src/bp-core/bp-core-catchuri.php
    index c7dd4aef8..68fd13863 100644
    function bp_core_load_template( $templates ) { 
    515515                        $wp_query->is_page     = true;
    516516                        $wp_query->is_singular = true;
    517517                        $wp_query->is_404      = false;
     518
     519                        if ( bp_use_wp_rewrites() ) {
     520                                $wp_query->is_home = false;
     521                        }
    518522                }
    519523
    520524                /**
  • src/bp-core/bp-core-functions.php

    diff --git src/bp-core/bp-core-functions.php src/bp-core/bp-core-functions.php
    index f3c8be614..61e90c5cb 100644
    function bp_core_get_directory_pages() { 
    628628                                                }
    629629
    630630                                                $pages->{$component_id}->slug = implode( '/', array_reverse( (array) $slug ) );
     631
     632                                                if ( bp_use_wp_rewrites() ) {
     633                                                        $pages->{$component_id}->custom_slugs = get_post_meta( $page_name->ID, '_bp_component_slugs', true );
     634                                                }
    631635                                        }
    632636
    633637                                        unset( $slug );
  • src/bp-core/bp-core-options.php

    diff --git src/bp-core/bp-core-options.php src/bp-core/bp-core-options.php
    index 7a88ca551..f449b8406 100644
    function bp_get_default_options() { 
    7474                // Email unsubscribe salt.
    7575                'bp-emails-unsubscribe-salt'           => '',
    7676
     77                // Rewrites
     78                '_bp_use_wp_rewrites'                  => false,
     79
    7780                /* Groups ************************************************************/
    7881
    7982                // @todo Move this into the groups component
    function bp_get_theme_package_id( $default = 'legacy' ) { 
    750753         */
    751754        return apply_filters( 'bp_get_theme_package_id', bp_get_option( '_bp_theme_package_id', $default ) );
    752755}
     756
     757/**
     758 * Check wether BuddyPress is using WP Rewrites.
     759 *
     760 * @since 6.0.0
     761 *
     762 * @param bool $default Optional. Fallback value if not found in the database.
     763 *                      Default: false.
     764 * @return bool True if BuddyPress uses WP Rewrites, otherwise false.
     765 */
     766function bp_use_wp_rewrites( $default = false ) {
     767
     768        /**
     769         * Filters wether BuddyPress should use WP Rewrites.
     770         *
     771         * @since 6.0.0
     772         *
     773         * @param bool $value Whether or not Rewrites are enabled.
     774         */
     775        return apply_filters( 'bp_use_wp_rewrites', bp_get_option( '_bp_use_wp_rewrites', $default ) );
     776}
  • new file src/bp-core/bp-core-rewrites.php

    diff --git src/bp-core/bp-core-rewrites.php src/bp-core/bp-core-rewrites.php
    new file mode 100644
    index 000000000..c588e15b5
    - +  
     1<?php
     2/**
     3 * BuddyPress Rewrites.
     4 *
     5 * @package BuddyPress
     6 * @subpackage Core
     7 * @since 6.0.0
     8 */
     9
     10// Exit if accessed directly.
     11defined( 'ABSPATH' ) || exit;
     12
     13/**
     14 * Delete rewrite rules, so that they are automatically rebuilt on
     15 * the subsequent page load.
     16 *
     17 * @since 6.0.0
     18 */
     19function bp_delete_rewrite_rules() {
     20        delete_option( 'rewrite_rules' );
     21}
     22
     23/**
     24 * Are pretty links active ?
     25 *
     26 * @since 6.0.0
     27 *
     28 * @return bool True if pretty links are on. False otherwise.
     29 */
     30function bp_has_pretty_links() {
     31        return !! get_option( 'permalink_structure', '' );
     32}
     33
     34/**
     35 * Let's experiment WordPress URL rewriting in BuddyPress!
     36 *
     37 * If the Custom URLs option is active, this will neutralize our
     38 * legacy parser in favor of the WP URL Rewrites API.
     39 *
     40 * @since 6.0.0
     41 */
     42function bp_disable_legacy_url_parser() {
     43        if ( ! bp_use_wp_rewrites() ) {
     44                return;
     45        }
     46
     47        // First let's neutalize our legacy URL parser.
     48        remove_action( 'bp_init', 'bp_core_set_uri_globals', 2 );
     49
     50        // These hooks need to happen later.
     51        remove_action( 'bp_init', 'bp_setup_canonical_stack', 5 );
     52        add_action( 'bp_parse_query', 'bp_setup_canonical_stack', 11 );
     53        remove_action( 'bp_init', 'bp_setup_title', 8 );
     54        add_action( 'bp_parse_query', 'bp_setup_title', 14 );
     55
     56        /**
     57         * This hook needs to happen later on front-end only.
     58         *
     59         * @see `bp_nav_menu_get_loggedin_pages()`
     60         */
     61        if ( ! is_admin() ) {
     62                remove_action( 'bp_init', 'bp_setup_nav', 6 );
     63                add_action( 'bp_parse_query', 'bp_setup_nav', 12 );
     64        }
     65
     66        // Then register a custom post type to use for the directory pages.
     67        register_post_type( 'bp_directories', array(
     68                'label'               => _x( 'BuddyPress directories', 'Post type label used in the Admin menu.', 'buddypress' ),
     69                'labels'              => array(
     70                        'singular_name' => _x( 'BuddyPress directory', 'Post type singular name', 'buddypress' ),
     71                ),
     72                'description'         => __( 'The BuddyPress directories post type is used when the custom URLs option is active.', 'buddypress' ),
     73                'public'              => false,
     74                'hierarchical'        => true,
     75                'exclude_from_search' => true,
     76                'publicly_queryable'  => false,
     77                'show_in_nav_menus'   => true,
     78                'show_in_rest'        => false,
     79                'supports'            => array( 'title' ),
     80                'has_archive'         => false,
     81                'rewrite'             => false,
     82                'query_var'           => false,
     83                'delete_with_user'    => false,
     84        ) );
     85
     86        /**
     87         * Then start using a new way of building BuddyPress URLs.
     88         *
     89         * Using filters let us safelyt edit our legacy way of building URLs.
     90         */
     91        $filters = array(
     92                'bp_core_get_user_domain' => array(
     93                        'function' => '_bp_rewrites_get_user_link',
     94                        'num_args' => 3,
     95                ),
     96                'bp_get_members_directory_permalink' => array(
     97                        'function' => '_bp_rewrites_get_users_link',
     98                        'num_args' => 1,
     99                ),
     100                'bp_get_member_type_directory_permalink' => array(
     101                        'function' => '_bp_rewrites_get_users_type_link',
     102                        'num_args' => 2,
     103                ),
     104                'bp_members_nav_add_item_link' => array(
     105                        'function' => '_bp_rewrites_members_nav_link',
     106                        'num_args' => 1,
     107                ),
     108                'bp_members_subnav_add_item_link' => array(
     109                        'function' => '_bp_rewrites_members_nav_link',
     110                        'num_args' => 1,
     111                ),
     112                'bp_activity_admin_nav' => array(
     113                        'function' => '_bp_rewrites_user_admin_nav_link',
     114                        'num_args' => 1,
     115                ),
     116                'bp_blogs_admin_nav' => array(
     117                        'function' => '_bp_rewrites_user_admin_nav_link',
     118                        'num_args' => 1,
     119                ),
     120                'bp_friends_admin_nav' => array(
     121                        'function' => '_bp_rewrites_user_admin_nav_link',
     122                        'num_args' => 1,
     123                ),
     124                'bp_groups_admin_nav' => array(
     125                        'function' => '_bp_rewrites_user_admin_nav_link',
     126                        'num_args' => 1,
     127                ),
     128                'bp_messages_admin_nav' => array(
     129                        'function' => '_bp_rewrites_user_admin_nav_link',
     130                        'num_args' => 1,
     131                ),
     132                'bp_notifications_admin_nav' => array(
     133                        'function' => '_bp_rewrites_user_admin_nav_link',
     134                        'num_args' => 1,
     135                ),
     136                'bp_settings_admin_nav' => array(
     137                        'function' => '_bp_rewrites_user_admin_nav_link',
     138                        'num_args' => 1,
     139                        'priority' => 3, // After xProfile filter.
     140                ),
     141                'bp_xprofile_admin_nav' => array(
     142                        'function' => '_bp_rewrites_user_admin_nav_link',
     143                        'num_args' => 1,
     144                ),
     145                'bp_get_the_profile_group_edit_form_action' => array(
     146                        'function' => '_bp_rewrites_xprofile_group_edit_url',
     147                        'num_args' => 2,
     148                ),
     149                'bp_members_edit_profile_url' => array(
     150                        'function' => '_bp_rewrites_edit_profile_url',
     151                        'num_args' => 3,
     152                ),
     153                'bp_get_signup_page'  => array(
     154                        'function' => '_bp_rewrites_get_signup_link',
     155                        'num_args' => 1,
     156                ),
     157                'bp_get_activation_page'  => array(
     158                        'function' => '_bp_rewrites_get_activation_link',
     159                        'num_args' => 3,
     160                ),
     161                'bp_get_group_permalink' => array(
     162                        'function' => '_bp_rewrites_get_group_url',
     163                        'num_args' => 2,
     164                ),
     165                'bp_get_groups_directory_permalink' => array(
     166                        'function' => '_bp_rewrites_get_groups_url',
     167                        'num_args' => 1,
     168                ),
     169                'bp_get_group_type_directory_permalink' => array(
     170                        'function' => '_bp_rewrites_get_group_type_url',
     171                        'num_args' => 2,
     172                ),
     173                'bp_groups_subnav_add_item_link' => array(
     174                        'function' => '_bp_rewrites_groups_nav_link',
     175                        'num_args' => 1,
     176                ),
     177                'bp_get_groups_action_link' => array(
     178                        'function' => '_bp_rewrites_get_group_admin_link',
     179                        'num_args' => 4,
     180                ),
     181                'bp_group_admin_form_action' => array(
     182                        'function' => '_bp_rewrites_get_group_admin_form_url',
     183                        'num_args' => 3,
     184                ),
     185                'bp_get_group_create_link' => array(
     186                        'function' => '_bp_rewrites_get_group_create_link',
     187                        'num_args' => 2,
     188                ),
     189                'bp_get_activity_directory_permalink' => array(
     190                        'function' => '_bp_rewrites_get_activities_url',
     191                        'num_args' => 1,
     192                ),
     193                'bp_get_activity_post_form_action' => array(
     194                        'function' => '_bp_rewrites_get_activity_post_form_action',
     195                        'num_args' => 1,
     196                ),
     197                'bp_get_activity_comment_form_action' => array(
     198                        'function' => '_bp_rewrites_get_activity_comment_form_action',
     199                        'num_args' => 1,
     200                ),
     201                'bp_activity_get_permalink' => array(
     202                        'function' => '_bp_rewrites_get_activity_url',
     203                        'num_args' => 2,
     204                ),
     205                'bp_activity_permalink_redirect_url' => array(
     206                        'function' => '_bp_rewrites_get_activity_permalink_redirect_url',
     207                        'num_args' => 2,
     208                ),
     209                'bp_get_activity_comment_link' => array(
     210                        'function' => '_bp_rewrites_get_activity_comment_url',
     211                        'num_args' => 1,
     212                ),
     213                'bp_get_activity_favorite_link' => array(
     214                        'function' => '_bp_rewrites_get_activity_favorite_url',
     215                        'num_args' => 1,
     216                ),
     217                'bp_get_activity_unfavorite_link' => array(
     218                        'function' => '_bp_rewrites_get_activity_unfavorite_url',
     219                        'num_args' => 1,
     220                ),
     221                'bp_get_activity_delete_url' => array(
     222                        'function' => '_bp_rewrites_get_activity_delete_url',
     223                        'num_args' => 1,
     224                ),
     225                'bp_get_sitewide_activity_feed_link' => array(
     226                        'function' => '_bp_rewrites_get_sitewide_activity_feed_url',
     227                        'num_args' => 1,
     228                ),
     229                'bp_get_activities_member_rss_link' => array(
     230                        'function' => '_bp_rewrites_get_activities_member_rss_url',
     231                        'num_args' => 1,
     232                ),
     233                'bp_get_blogs_directory_permalink' => array(
     234                        'function' => '_bp_rewrites_get_blogs_url',
     235                        'num_args' => 1,
     236                ),
     237                'bp_get_blog_create_link' => array(
     238                        'function' => '_bp_rewrites_get_blog_create_url',
     239                        'num_args' => 1,
     240                ),
     241        );
     242
     243        foreach ( $filters as $legacy => $rewrite ) {
     244                if ( ! isset( $rewrite['priority'] ) ) {
     245                        $rewrite['priority'] = 1;
     246                }
     247
     248                add_filter( $legacy, $rewrite['function'], $rewrite['priority'], $rewrite['num_args'] );
     249        }
     250}
     251add_action( 'bp_init', 'bp_disable_legacy_url_parser', 1 );
     252
     253/**
     254 * Make sure WP Nav Menus still use the right links.
     255 *
     256 * @since 6.0.0
     257 *
     258 * @param  string  $link The post type link.
     259 * @param  WP_Post $post The post type object.
     260 * @return string        The post type link.
     261 */
     262function bp_page_directory_link( $link, WP_Post $post ) {
     263        if ( 'bp_directories' !== get_post_type( $post ) ) {
     264                return $link;
     265        }
     266
     267        $directory_pages = wp_filter_object_list( (array) bp_core_get_directory_pages(), array( 'id' => $post->ID ) ) ;
     268        $component       = key( $directory_pages );
     269
     270        return bp_rewrites_get_link( array( 'component_id' => $component ) );
     271}
     272add_filter( 'post_type_link', 'bp_page_directory_link', 1, 2 );
     273
     274/**
     275 * Get needed data to find a member single item from the request.
     276 *
     277 * @since 6.0.0
     278 *
     279 * @param string $request The request used during parsing.
     280 * @return array Data to find a member single item from the request.
     281 */
     282function bp_rewrites_get_member_data( $request = '' ) {
     283        $member_data = array( 'field' => 'slug' );
     284
     285        if ( bp_is_username_compatibility_mode() ) {
     286                $member_data = array( 'field' => 'login' );
     287        }
     288
     289        if ( bp_core_enable_root_profiles() ) {
     290                if ( ! $request ) {
     291                        $request = $GLOBALS['wp']->request;
     292                }
     293
     294                $request_chunks = explode( '/', ltrim( $request, '/' ) );
     295                $member_chunk   = reset( $request_chunks );
     296
     297                // Try to get an existing member to eventually reset the WP Query.
     298                $member_data['object'] = get_user_by( $member_data['field'], $member_chunk );
     299        }
     300
     301        return $member_data;
     302}
     303
     304function bp_rewrites_get_member_slug( $user_id = 0 ) {
     305        $bp = buddypress();
     306
     307        $prop = 'user_nicename';
     308        if ( bp_is_username_compatibility_mode() ) {
     309                $prop = 'user_login';
     310        }
     311
     312        if ( (int) $user_id === (int) bp_displayed_user_id() ) {
     313                $slug = isset( $bp->displayed_user->userdata->{$prop} ) ? $bp->displayed_user->userdata->{$prop} : null;
     314        } elseif ( (int) $user_id === (int) bp_loggedin_user_id() ) {
     315                $slug = isset( $bp->loggedin_user->userdata->{$prop} ) ? $bp->loggedin_user->userdata->{$prop} : null;
     316        } else {
     317                $slug = bp_core_get_username( $user_id );
     318        }
     319
     320        return $slug;
     321}
     322
     323/**
     324 * Makes sure BuddyPress globals are set during Ajax requests.
     325 *
     326 * @since 6.0.0
     327 */
     328function bp_parse_ajax_referer_query() {
     329        if ( ! wp_doing_ajax() || ! bp_use_wp_rewrites() ) {
     330                return;
     331        }
     332
     333        $bp       = buddypress();
     334        $bp->ajax = (object) array(
     335                'WP' => new WP(),
     336        );
     337
     338        bp_reset_query( bp_get_referer_path(), $GLOBALS['wp_query'] );
     339}
     340add_action( 'bp_admin_init', 'bp_parse_ajax_referer_query' );
     341
     342/**
     343 * Resets the query to fit our permalink structure if needed.
     344 *
     345 * This is used for specific cases such as Root Member's profile or Ajax.
     346 *
     347 * @since 6.0.0
     348 *
     349 * @param string $bp_request A specific BuddyPress request.
     350 * @param WP_Query $query The WordPress query object.
     351 */
     352function bp_reset_query( $bp_request = '', WP_Query $query ) {
     353        global $wp;
     354        $bp = buddypress();
     355
     356        // Back up request uri.
     357        $reset_server_request_uri = $_SERVER['REQUEST_URI'];
     358
     359        // Temporarly override it.
     360        if ( isset( $wp->request ) ) {
     361                $_SERVER['REQUEST_URI'] = str_replace( $wp->request, $bp_request, $reset_server_request_uri );
     362
     363                // Reparse request.
     364                $wp->parse_request();
     365
     366                // Reparse query.
     367                bp_remove_all_filters( 'parse_query' );
     368                $query->parse_query( $wp->query_vars );
     369                bp_restore_all_filters( 'parse_query' );
     370
     371        } elseif ( isset( $bp->ajax ) ) {
     372                $_SERVER['REQUEST_URI'] = $bp_request;
     373
     374                if ( bp_has_pretty_links() ) {
     375                        $bp->ajax->WP->parse_request();
     376
     377                        // Extra step to check for root profiles.
     378                        $member = bp_rewrites_get_member_data( $bp->ajax->WP->request );
     379                        if ( isset( $member['object'] ) && $member['object'] ) {
     380                                $_SERVER['REQUEST_URI'] = trailingslashit( $bp->members->root_slug ) . $bp->ajax->WP->request;
     381
     382                                // Reparse the request.
     383                                $bp->ajax->WP->parse_request();
     384                        }
     385
     386                        $matched_query = $bp->ajax->WP->matched_query;
     387                } else {
     388                        $matched_query = wp_parse_url( $bp_request, PHP_URL_QUERY );
     389                }
     390
     391                $query->parse_query( $matched_query );
     392
     393                // BP Parse the request in components only once per Ajax request.
     394                remove_action( 'parse_query', 'bp_parse_query', 2 );
     395        }
     396
     397        // Restore request uri.
     398        $_SERVER['REQUEST_URI'] = $reset_server_request_uri;
     399
     400        // The query is reset.
     401        return true;
     402}
     403
     404/**
     405 * Returns the slug to use for the nav item of the requested component.
     406 *
     407 * @since 6.0.0
     408 *
     409 * @param string $component_id The BuddyPress component's ID.
     410 * @param string $rewrite_id   The nav item's rewrite ID.
     411 * @param string $default_slug The nav item's default slug.
     412 * @return string              The slug to use for the nav item of the requested component.
     413 */
     414function bp_rewrites_get_slug( $component_id = '', $rewrite_id = '', $default_slug = '' ) {
     415        $directory_pages = bp_core_get_directory_pages();
     416        $slug            = $default_slug;
     417
     418        if ( ! isset( $directory_pages->{$component_id}->custom_slugs ) || ! $rewrite_id ) {
     419                return $slug;
     420        }
     421
     422        $custom_slugs = (array) $directory_pages->{$component_id}->custom_slugs;
     423        if ( isset( $custom_slugs[ $rewrite_id ] ) && $custom_slugs[ $rewrite_id ] ) {
     424                $slug = $custom_slugs[ $rewrite_id ];
     425        }
     426
     427        return $slug;
     428}
     429
     430function bp_rewrites_get_custom_slug_rewrite_id( $component_id = '', $slug = '' ) {
     431        $directory_pages = bp_core_get_directory_pages();
     432
     433        if ( ! isset( $directory_pages->{$component_id}->custom_slugs ) || ! $slug ) {
     434                return null;
     435        }
     436
     437        $custom_slugs = (array) $directory_pages->{$component_id}->custom_slugs;
     438
     439        // If there's a match it's a custom slug.
     440        return array_search( $slug, $custom_slugs );
     441}
     442
     443/**
     444 * Builds a BuddyPress link using the WP Rewrite API.
     445 *
     446 * @todo Allow customization using `bp_rewrites_get_slug()`
     447 *       Describe parameter.
     448 *
     449 * @since 6.0.0
     450 *
     451 * @param array $args
     452 * @return string The BuddyPress link.
     453 */
     454function bp_rewrites_get_link( $args = array() ) {
     455        $bp   = buddypress();
     456        $link = '#';
     457
     458        $r = wp_parse_args( $args, array(
     459                'component_id'                 => '',
     460                'directory_type'               => '',
     461                'single_item'                  => '',
     462                'single_item_component'        => '',
     463                'single_item_action'           => '',
     464                'single_item_action_variables' => array(),
     465        ) );
     466
     467        $is_pretty_links = bp_has_pretty_links();
     468
     469        if ( ! isset( $bp->{$r['component_id']} ) ) {
     470                return $link;
     471        }
     472
     473        $component = $bp->{$r['component_id']};
     474        unset( $r['component_id'] );
     475
     476        // Using plain links.
     477        if ( ! $is_pretty_links ) {
     478                if ( ! isset( $r['member_register'] ) && ! isset( $r['member_activate'] ) ) {
     479                        $r['directory'] = 1;
     480                }
     481
     482                $r              = array_filter( $r );
     483                $qv             = array();
     484
     485                foreach ( $component->rewrite_ids as $key => $rewrite_id ) {
     486                        if ( ! isset( $r[ $key ] ) ) {
     487                                continue;
     488                        }
     489
     490                        $qv[ $rewrite_id ] = $r[ $key ];
     491                }
     492
     493                $link = add_query_arg( $qv, home_url( '/' ) );
     494
     495        // Using pretty links.
     496        } else {
     497                if ( ! isset( $component->rewrite_ids['directory'] ) || ! isset( $component->directory_permastruct ) ) {
     498                        return $link;
     499                }
     500
     501                if ( isset( $r['member_register'] ) ) {
     502                        $link = str_replace( '%' . $component->rewrite_ids['member_register'] . '%', '', $component->register_permastruct );
     503                        unset( $r['member_register'] );
     504                } elseif ( isset( $r['member_activate'] ) ) {
     505                        $link = str_replace( '%' . $component->rewrite_ids['member_activate'] . '%', '', $component->activate_permastruct );
     506                        unset( $r['member_activate'] );
     507                } elseif ( isset( $r['create_single_item'] ) ) {
     508                        $link = str_replace( '%' . $component->rewrite_ids['directory'] . '%', 'create', $component->directory_permastruct );
     509                        unset( $r['create_single_item'] );
     510                } else {
     511                        $link = str_replace( '%' . $component->rewrite_ids['directory'] . '%', $r['single_item'], $component->directory_permastruct );
     512
     513                        // Remove the members directory slug when root profiles are on.
     514                        if ( bp_core_enable_root_profiles() && 'members' === $component->id && isset( $r['single_item'] ) && $r['single_item'] ) {
     515                                $link = str_replace( $bp->members->root_slug . '/', '', $link );
     516                        }
     517
     518                        unset( $r['single_item'] );
     519                }
     520
     521                $r = array_filter( $r );
     522
     523                if ( isset( $r['directory_type'] ) && $r['directory_type'] ) {
     524                        if ( 'members' === $component->id ) {
     525                                array_unshift( $r, bp_get_members_member_type_base() );
     526                        } elseif ( 'groups' === $component->id ) {
     527                                array_unshift( $r, bp_get_groups_group_type_base() );
     528                        } else {
     529                                unset( $r['directory_type'] );
     530                        }
     531                }
     532
     533                if ( isset( $r['single_item_action_variables'] ) && $r['single_item_action_variables'] ) {
     534                        $r['single_item_action_variables'] = join( '/', (array) $r['single_item_action_variables'] );
     535                }
     536
     537                if ( isset( $r['create_single_item_variables'] ) && $r['create_single_item_variables'] ) {
     538                        $r['create_single_item_variables'] = join( '/', (array) $r['create_single_item_variables'] );
     539                }
     540
     541                $link = home_url( user_trailingslashit( '/' . rtrim( $link, '/' ) . '/' . join( '/', $r ) ) );
     542        }
     543
     544        return $link;
     545}
     546
     547function _bp_rewrites_get_user_link( $link = '', $user_id = 0, $username = '' ) {
     548        if ( ! $user_id ) {
     549                return $link;
     550        }
     551
     552        $bp = buddypress();
     553        if ( ! $username ) {
     554                $username = bp_rewrites_get_member_slug( $user_id );
     555        }
     556
     557        return bp_rewrites_get_link( array(
     558                'component_id' => 'members',
     559                'single_item'  => $username,
     560        ) );
     561}
     562
     563function _bp_rewrites_get_users_link( $link = '' ) {
     564        return bp_rewrites_get_link( array(
     565                'component_id' => 'members',
     566        ) );
     567}
     568
     569function _bp_rewrites_get_users_type_link( $link = '', $type = null ) {
     570        if ( ! isset( $type->directory_slug ) ) {
     571                return $link;
     572        }
     573
     574        return bp_rewrites_get_link( array(
     575                'component_id'   => 'members',
     576                'directory_type' => $type->directory_slug,
     577        ) );
     578}
     579
     580/**
     581 * Edit the link parameter of the members primary/secondary nav item links.
     582 *
     583 * @see bp_core_create_nav_link() for description of parameters.
     584 *
     585 * @since 6.0.0
     586 *
     587 * @param  array $args The arguments used to create the primary/secondary nav item.
     588 * @return array       The arguments used to create the primary/secondary nav item.
     589 */
     590function _bp_rewrites_members_nav_link( $args = array() ) {
     591        $bp      = buddypress();
     592        $user_id = bp_displayed_user_id();
     593        if ( ! $user_id ) {
     594                $user_id = bp_loggedin_user_id();
     595        }
     596
     597        $username = bp_rewrites_get_member_slug( $user_id );
     598        if ( ! $username ) {
     599                return $args;
     600        }
     601
     602        if ( 'bp_members_nav_add_item_link' === current_filter() ) {
     603                $link_params = array(
     604                        'component_id'          => 'members',
     605                        'single_item'           => $username,
     606                        'single_item_component' => bp_rewrites_get_slug( 'members', $args['rewrite_id'], $args['slug'] ),
     607                );
     608        } else {
     609                $parent_nav = $bp->members->nav->get_primary( array( 'slug' => $args['parent_slug'] ), false );
     610                if ( ! $parent_nav ) {
     611                        return $args;
     612                }
     613
     614                $parent_nav = reset( $parent_nav );
     615                if ( ! isset( $parent_nav->rewrite_id ) ) {
     616                        return $args;
     617                }
     618
     619                $link_params = array(
     620                        'component_id'          => 'members',
     621                        'single_item'           => $username,
     622                        'single_item_component' => bp_rewrites_get_slug( 'members', $parent_nav->rewrite_id, $args['parent_slug'] ),
     623                        'single_item_action'    => $args['slug'],
     624                );
     625        }
     626
     627        if ( ! isset( $link_params ) ) {
     628                return $args;
     629        }
     630
     631        // Override the nav link.
     632        $args['link'] = bp_rewrites_get_link( $link_params );
     633
     634        return $args;
     635}
     636
     637function _bp_rewrites_user_admin_nav_link( $wp_admin_nav = array() ) {
     638        $bp = buddypress();
     639        $username = bp_rewrites_get_member_slug( bp_loggedin_user_id() );
     640        if ( ! $username ) {
     641                return $wp_admin_nav;
     642        }
     643
     644        $parent         = '';
     645        $component_slug = '';
     646        $link_args      = array(
     647                'component_id' => 'members',
     648                'single_item'  => $username,
     649        );
     650
     651        foreach ( $wp_admin_nav as $index_nav => $nav_item ) {
     652                $component      = '';
     653                $component_url  = '';
     654
     655                if ( bp_has_pretty_links() ) {
     656                        $url_parts = explode( '/', rtrim( wp_parse_url( $wp_admin_nav[ $index_nav ]['href'], PHP_URL_PATH ), '/' ) );
     657                } else {
     658                        $url_parts = wp_parse_args( wp_parse_url( $wp_admin_nav[ $index_nav ]['href'], PHP_URL_QUERY ), array() );
     659
     660                        if ( isset( $url_parts['bp_member'] ) ) {
     661                                // Move added slugs to the `bp_member` query var at the end of the URL parts.
     662                                $url_parts = array_merge(
     663                                        $url_parts,
     664                                        explode( '/', rtrim( str_replace( $username, '', $url_parts['bp_member'] ), '/' ) )
     665                                );
     666
     667                                // Make sure the `bp_member` query var is consistent.
     668                                $url_parts['bp_member'] = $username;
     669                        }
     670                }
     671
     672                $slug = end( $url_parts );
     673
     674                // Make sure to reset the item action at each loop.
     675                $link_args['single_item_action']    = '';
     676
     677                // This is the single item compnent's main nav item.
     678                if ( $bp->my_account_menu_id === $nav_item['parent'] ) {
     679                        /**
     680                         * Make sure to reset the item component, component slug and parent
     681                         * at each main nav item change.
     682                         */
     683                        $link_args['single_item_component'] = '';
     684                        $component_slug                     = '';
     685                        $parent                             = '';
     686
     687                        $component      = str_replace( 'my-account-', '', $nav_item['id'] );
     688                        $parent         = $nav_item['id'];
     689                        $component_slug = $slug;
     690
     691                        // Specific to Extended Profiles.
     692                        if ( 'xprofile' === $component ) {
     693                                $component = 'profile';
     694                        }
     695
     696                        $link_args['single_item_component'] = bp_rewrites_get_slug( 'members', 'bp_member_' . $component, $component_slug );
     697                        $wp_admin_nav[ $index_nav ]['href'] = bp_rewrites_get_link( $link_args );
     698                }
     699
     700                if ( $component_slug && $parent === $nav_item['parent'] && false !== strpos( $nav_item['href'], $username ) ) {
     701                        $link_args['single_item_action']    = $slug !== $component_slug ? $slug : '';
     702                        $wp_admin_nav[ $index_nav ]['href'] = bp_rewrites_get_link( $link_args );
     703                }
     704        }
     705
     706        return $wp_admin_nav;
     707}
     708
     709function _bp_rewrites_edit_profile_url( $profile_link = '', $url = '', $user_id = 0 ) {
     710        if ( ! is_admin() && bp_is_active( 'xprofile' ) ) {
     711                $profile_link = bp_rewrites_get_link( array(
     712                        'component_id'          => 'members',
     713                        'single_item'           => bp_rewrites_get_member_slug( $user_id ),
     714                        'single_item_component' => bp_rewrites_get_slug( 'members', 'bp_member_profile', bp_get_profile_slug() ),
     715                        'single_item_action'    => 'edit'
     716                ) );
     717        }
     718
     719        return $profile_link;
     720}
     721
     722function _bp_rewrites_get_signup_link( $link = '' ) {
     723        return bp_rewrites_get_link( array(
     724                'component_id'    => 'members',
     725                'member_register' => 1,
     726        ) );
     727}
     728
     729function _bp_rewrites_get_activation_link( $link = '', $key = '', $has_custom_activation_page = false ) {
     730        if ( ! $has_custom_activation_page ) {
     731                return $link;
     732        }
     733
     734        $link_params = array(
     735                'component_id'    => 'members',
     736                'member_activate' => 1,
     737        );
     738
     739        if ( $key ) {
     740                $link_params['member_activate_key'] = $key;
     741        }
     742
     743        return bp_rewrites_get_link( $link_params );
     744}
     745
     746function _bp_rewrites_get_group_url( $link = '', $group = null ) {
     747        if ( ! isset( $group->id ) || ! $group->id ) {
     748                return $link;
     749        }
     750
     751        return bp_rewrites_get_link( array(
     752                'component_id' => 'groups',
     753                'single_item'  => bp_get_group_slug( $group ),
     754        ) );
     755}
     756
     757function _bp_rewrites_get_groups_url( $link = '' ) {
     758        return bp_rewrites_get_link( array(
     759                'component_id' => 'groups',
     760        ) );
     761}
     762
     763function _bp_rewrites_get_group_type_url( $link = '', $type = null ) {
     764        if ( ! isset( $type->directory_slug ) ) {
     765                return $link;
     766        }
     767
     768        return bp_rewrites_get_link( array(
     769                'component_id'   => 'groups',
     770                'directory_type' => $type->directory_slug,
     771        ) );
     772}
     773
     774/**
     775 * Edit the link parameter of the group's secondary nav item links.
     776 *
     777 * @see bp_core_create_subnav_link() for description of parameters.
     778 *
     779 * @since 6.0.0
     780 *
     781 * @param  array $args The arguments used to create the secondary nav item.
     782 * @return array       The arguments used to create the secondary nav item.
     783 */
     784function _bp_rewrites_groups_nav_link( $args = array() ) {
     785        if ( ! isset( $args['parent_slug'] ) || ! isset( $args['slug'] ) ) {
     786                return $args;
     787        }
     788
     789        $single_item        = $args['parent_slug'];
     790        $single_item_action = $args['slug'];
     791
     792        if ( false !== strpos( $single_item, '_manage' ) ) {
     793                $single_item_action = 'admin';
     794                $single_item = str_replace( '_manage', '', $single_item );
     795        }
     796
     797        $link_params = array(
     798                'component_id'       => 'groups',
     799                'single_item'        => $single_item,
     800                'single_item_action' => $single_item_action,
     801        );
     802
     803        if ( 'admin' === $single_item_action && 'admin' !== $args['slug'] ) {
     804                $link_params['single_item_action_variables'] = explode( '/', $args['slug'] );
     805        }
     806
     807        $args['link'] = bp_rewrites_get_link( $link_params );
     808
     809        return $args;
     810}
     811
     812function _bp_rewrites_get_group_admin_link( $link = '', $action = '', $query_args = array(), $nonce = false ) {
     813        if ( ! $action ) {
     814                return $link;
     815        }
     816
     817        $group = groups_get_current_group();
     818        if ( ! isset( $group->slug ) ) {
     819                return $link;
     820        }
     821
     822        $single_item_action_variables = explode( '/', rtrim( $action, '/' ) );
     823        $single_item_action           = array_shift( $single_item_action_variables );
     824
     825        $link = bp_rewrites_get_link( array(
     826                'component_id'                 => 'groups',
     827                'single_item'                  => $group->slug,
     828                'single_item_action'           => $single_item_action,
     829                'single_item_action_variables' => $single_item_action_variables,
     830        ) );
     831
     832        if ( $query_args && is_array( $query_args ) ) {
     833                $link = add_query_arg( $query_args, $link );
     834        }
     835
     836        if ( true === $nonce ) {
     837                $link = wp_nonce_url( $link );
     838        } elseif ( is_string( $nonce ) ) {
     839                $link = wp_nonce_url( $link, $nonce );
     840        }
     841
     842        return $link;
     843}
     844
     845function _bp_rewrites_get_group_admin_form_url( $link = '', $group = null, $page = '' ) {
     846        if ( ! isset( $group->slug ) || ! $page ) {
     847                return $link;
     848        }
     849
     850        return bp_rewrites_get_link( array(
     851                'component_id'                 => 'groups',
     852                'single_item'                  => $group->slug,
     853                'single_item_action'           => 'admin',
     854                'single_item_action_variables' => array( $page ),
     855        ) );
     856}
     857
     858function _bp_rewrites_get_group_create_link( $link = '', $step = '' ) {
     859        $link_params = array(
     860                'component_id'       => 'groups',
     861                'create_single_item' => 1,
     862        );
     863
     864        if ( $step ) {
     865                $link_params['create_single_item_variables'] = array( 'step', $step );
     866        }
     867
     868        return bp_rewrites_get_link( $link_params );
     869}
     870
     871function _bp_rewrites_get_activities_url( $link = '' ) {
     872        return bp_rewrites_get_link( array(
     873                'component_id' => 'activity',
     874        ) );
     875}
     876
     877function _bp_rewrites_get_activity_post_form_action( $link = '' ) {
     878        return bp_rewrites_get_link( array(
     879                'component_id'       => 'activity',
     880                'single_item_action' => 'post',
     881        ) );
     882}
     883
     884function _bp_rewrites_get_activity_comment_form_action( $link = '' ) {
     885        return bp_rewrites_get_link( array(
     886                'component_id'       => 'activity',
     887                'single_item_action' => 'reply',
     888        ) );
     889}
     890
     891function _bp_rewrites_get_activity_url( $link = '', $activity = null ) {
     892        if ( ! isset( $activity->primary_link ) || $link === $activity->primary_link ) {
     893                return $link;
     894        }
     895
     896        $link_params = array(
     897                'component_id'                 => 'activity',
     898                'single_item_action'           => 'p',
     899                'single_item_action_variables' => array( $activity->id ),
     900        );
     901
     902        if ( 'activity_comment' === $activity->type ) {
     903                $link_params['single_item_action_variables'] = array( $activity->item_id );
     904        }
     905
     906        $link = bp_rewrites_get_link( $link_params );
     907
     908        if ( 'activity_comment' === $activity->type ) {
     909                $link .= '#acomment-' . $activity->id;
     910        }
     911
     912        return $link;
     913}
     914
     915function _bp_rewrites_get_activity_comment_url( $link = '' ) {
     916        if ( bp_has_pretty_links() ) {
     917                return $link;
     918        }
     919
     920        $url_parts = explode( '/', $link );
     921        $query_var = wp_parse_args( ltrim( $url_parts[0], '?' ), array( 'ac' => 0 ) );
     922        $anchor    = end( $url_parts );
     923
     924        if ( bp_is_activity_directory() ) {
     925                $link = _bp_rewrites_get_activities_url();
     926
     927        } else {
     928                global $activities_template;
     929
     930                $link = bp_rewrites_get_link( array(
     931                        'component_id'                 => 'activity',
     932                        'single_item_action'           => 'p',
     933                        'single_item_action_variables' => array( $activities_template->activity->id ),
     934                ) );
     935        }
     936
     937        return add_query_arg( $query_var, $link ) . $anchor;
     938}
     939
     940function _bp_rewrites_get_activity_favorite_url( $link = '' ) {
     941        global $activities_template;
     942
     943        $link = bp_rewrites_get_link( array(
     944                'component_id'                 => 'activity',
     945                'single_item_action'           => 'favorite',
     946                'single_item_action_variables' => array( $activities_template->activity->id ),
     947        ) );
     948
     949        return wp_nonce_url( $link, 'mark_favorite' );
     950}
     951
     952function _bp_rewrites_get_activity_unfavorite_url(  $link = '' ) {
     953        global $activities_template;
     954
     955        $link = bp_rewrites_get_link( array(
     956                'component_id'                 => 'activity',
     957                'single_item_action'           => 'unfavorite',
     958                'single_item_action_variables' => array( $activities_template->activity->id ),
     959        ) );
     960
     961        return wp_nonce_url( $link, 'unmark_favorite' );
     962}
     963
     964function _bp_rewrites_get_activity_delete_url( $link = '' ) {
     965        global $activities_template;
     966        $query_vars = wp_parse_args( wp_parse_url( $link, PHP_URL_QUERY ), array() );
     967
     968        $link = bp_rewrites_get_link( array(
     969                'component_id'                 => 'activity',
     970                'single_item_action'           => 'delete',
     971                'single_item_action_variables' => array( $activities_template->activity->id ),
     972        ) );
     973
     974        return add_query_arg( $query_vars, $link );
     975}
     976
     977function _bp_rewrites_get_sitewide_activity_feed_url( $link = '' ) {
     978        return bp_rewrites_get_link( array(
     979                'component_id'       => 'activity',
     980                'single_item_action' => 'feed',
     981        ) );
     982}
     983
     984function _bp_rewrites_get_activities_member_rss_url( $link = '' ) {
     985        $link_params = array(
     986                'component_id'          => 'members',
     987                'single_item'           => bp_rewrites_get_member_slug( bp_displayed_user_id() ),
     988                'single_item_component' => bp_rewrites_get_slug( 'members', 'bp_member_activity', bp_get_activity_slug() ),
     989        );
     990
     991        if ( bp_is_user_activity() ) {
     992                if ( bp_is_user_friends_activity() ) {
     993                        $link_params['single_item_action'] = bp_get_friends_slug();
     994                        $link_params['single_item_action_variables'] = 'feed';
     995                } elseif( bp_is_user_groups_activity() ) {
     996                        $link_params['single_item_action'] = bp_get_groups_slug();
     997                        $link_params['single_item_action_variables'] = 'feed';
     998                } elseif( 'favorites' === bp_current_action() ) {
     999                        $link_params['single_item_action'] = 'favorites';
     1000                        $link_params['single_item_action_variables'] = 'feed';
     1001                } elseif( 'mentions' === bp_current_action() && bp_activity_do_mentions() ) {
     1002                        $link_params['single_item_action'] = 'mentions';
     1003                        $link_params['single_item_action_variables'] = 'feed';
     1004                } else {
     1005                        $link_params['single_item_action'] = 'feed';
     1006                }
     1007        }
     1008
     1009        return bp_rewrites_get_link( $link_params );
     1010}
     1011
     1012function _bp_rewrites_get_activity_permalink_redirect_url( $redirect = '', $activity = null ) {
     1013        if ( ! $redirect || ! isset( $activity->user_id ) ) {
     1014                return $redirect;
     1015        }
     1016
     1017        // This shouldn't happen so often!
     1018        if ( bp_is_active( 'groups') && 'groups' === $activity->component && ! $activity->user_id ) {
     1019                $group = groups_get_group( $activity->item_id );
     1020
     1021                $link_params = array(
     1022                        'component_id'                 => 'groups',
     1023                        'single_item'                  => bp_get_group_slug( $group ),
     1024                        'single_item_action'           => bp_get_activity_slug(),
     1025                        'single_item_action_variables' => array( $activity->id ),
     1026                );
     1027        } else {
     1028                $link_params = array(
     1029                        'component_id'          => 'members',
     1030                        'single_item'           => bp_rewrites_get_member_slug( $activity->user_id ),
     1031                        'single_item_component' => bp_rewrites_get_slug( 'members', 'bp_member_activity', bp_get_activity_slug() ),
     1032                        'single_item_action'    => $activity->id,
     1033                );
     1034        }
     1035
     1036        $redirect = bp_rewrites_get_link( $link_params );
     1037
     1038        // If set, add the original query string back onto the redirect URL.
     1039        if ( isset( $_SERVER['QUERY_STRING'] ) ) {
     1040                $query_vars = array();
     1041                wp_parse_str( $_SERVER['QUERY_STRING'], $query_vars );
     1042                $exclude_vars = array_intersect_key( $query_vars, array_flip( buddypress()->activity->rewrite_ids ) );
     1043                $query_vars = array_diff_key( $query_vars, $exclude_vars );
     1044
     1045                if ( $query_vars ) {
     1046                        $redirect = add_query_arg( urlencode_deep( $query_vars ), $redirect );
     1047                }
     1048        }
     1049
     1050        return $redirect;
     1051}
     1052
     1053function _bp_rewrites_get_blogs_url( $link = '' ) {
     1054        return bp_rewrites_get_link( array(
     1055                'component_id' => 'blogs',
     1056        ) );
     1057}
     1058
     1059function _bp_rewrites_get_blog_create_url( $link = '' ) {
     1060        return bp_rewrites_get_link( array(
     1061                'component_id'       => 'blogs',
     1062                'single_item_action' => 'create',
     1063        ) );
     1064}
     1065
     1066function _bp_rewrites_xprofile_group_edit_url( $link = '', $field_group_id = 0 ) {
     1067        if ( ! $field_group_id ) {
     1068                return $link;
     1069        }
     1070
     1071        return bp_rewrites_get_link( array(
     1072                'component_id'                 => 'members',
     1073                'single_item'                  => bp_rewrites_get_member_slug( bp_displayed_user_id() ),
     1074                'single_item_component'        => bp_rewrites_get_slug( 'members', 'bp_member_profile', bp_get_profile_slug() ),
     1075                'single_item_action'           => 'edit',
     1076                'single_item_action_variables' => array( 'group', $field_group_id ),
     1077        ) );
     1078}
  • src/bp-core/bp-core-taxonomy.php

    diff --git src/bp-core/bp-core-taxonomy.php src/bp-core/bp-core-taxonomy.php
    index 14334e00d..cdfb6ee0e 100644
    defined( 'ABSPATH' ) || exit; 
    2222function bp_register_default_taxonomies() {
    2323        // Member Type.
    2424        register_taxonomy( bp_get_member_type_tax_name(), 'user', array(
    25                 'public' => false,
     25                'public'  => false,
     26                /**
     27                 * Prevents WordPress Taxonomy rewrite rules to be automaticaly generated.
     28                 * Rewrite rules for the Member Type Taxonomy is handled within the Members
     29                 * component class {@see BP_Members_Component::add_rewrite_rules()}}.
     30                 */
     31                'rewrite' => false,
    2632        ) );
    2733
    2834        // Email type.
  • src/bp-core/bp-core-template-loader.php

    diff --git src/bp-core/bp-core-template-loader.php src/bp-core/bp-core-template-loader.php
    index a4750638a..7e2a1c61c 100644
    function bp_add_template_stack_locations( $stacks = array() ) { 
    469469 * @param WP_Query $posts_query WP_Query object.
    470470 */
    471471function bp_parse_query( $posts_query ) {
     472        $bp_is_doing_ajax = isset( buddypress()->ajax->WP );
    472473
    473         // Bail if $posts_query is not the main loop.
    474         if ( ! $posts_query->is_main_query() ) {
     474        // Bail if $posts_query is not the main loop and not done in BP Ajax context.
     475        if ( ! $bp_is_doing_ajax && ! $posts_query->is_main_query() ) {
    475476                return;
    476477        }
    477478
    function bp_parse_query( $posts_query ) { 
    480481                return;
    481482        }
    482483
    483         // Bail if in admin.
    484         if ( is_admin() ) {
     484        // Bail if in admin and not done in BP Ajax context.
     485        if ( ! $bp_is_doing_ajax && is_admin() ) {
    485486                return;
    486487        }
    487488
  • src/bp-core/classes/class-bp-admin.php

    diff --git src/bp-core/classes/class-bp-admin.php src/bp-core/classes/class-bp-admin.php
    index 4f0bd257a..aabe4bdc6 100644
    class BP_Admin { 
    123123                require( $this->admin_dir . 'bp-core-admin-components.php' );
    124124                require( $this->admin_dir . 'bp-core-admin-slugs.php'      );
    125125                require( $this->admin_dir . 'bp-core-admin-tools.php'      );
     126                require $this->admin_dir . 'bp-core-admin-rewrites.php';
    126127        }
    127128
    128129        /**
    class BP_Admin { 
    234235                        'bp_core_admin_components_settings'
    235236                );
    236237
    237                 $hooks[] = add_submenu_page(
    238                         $this->settings_page,
    239                         __( 'BuddyPress Pages', 'buddypress' ),
    240                         __( 'BuddyPress Pages', 'buddypress' ),
    241                         $this->capability,
    242                         'bp-page-settings',
    243                         'bp_core_admin_slugs_settings'
    244                 );
     238                if ( bp_use_wp_rewrites() ) {
     239                        $hooks[] = add_submenu_page(
     240                                $this->settings_page,
     241                                __( 'BuddyPress URLs', 'buddypress' ),
     242                                __( 'BuddyPress URLs', 'buddypress' ),
     243                                $this->capability,
     244                                'bp-rewrites-settings',
     245                                'bp_core_admin_rewrites_settings'
     246                        );
     247                } else {
     248                        $hooks[] = add_submenu_page(
     249                                $this->settings_page,
     250                                __( 'BuddyPress Pages', 'buddypress' ),
     251                                __( 'BuddyPress Pages', 'buddypress' ),
     252                                $this->capability,
     253                                'bp-page-settings',
     254                                'bp_core_admin_slugs_settings'
     255                        );
     256                }
    245257
    246258                $hooks[] = add_submenu_page(
    247259                        $this->settings_page,
    class BP_Admin { 
    394406                add_settings_field( '_bp_theme_package_id', __( 'Template Pack', 'buddypress' ), 'bp_admin_setting_callback_theme_package_id', 'buddypress', 'bp_main', array( 'label_for' => '_bp_theme_package_id' ) );
    395407                register_setting( 'buddypress', '_bp_theme_package_id', 'sanitize_text_field' );
    396408
     409                // Rewrites.
     410                add_settings_field( '_bp_use_wp_rewrites', __( 'Custom URLs', 'buddypress' ), 'bp_admin_setting_callback_use_wp_rewrites', 'buddypress', 'bp_main', array( 'label_for' => '_bp_use_wp_rewrites' ) );
     411                register_setting( 'buddypress', '_bp_use_wp_rewrites', 'intval' );
     412
    397413                /* XProfile Section **************************************************/
    398414
    399415                if ( bp_is_active( 'xprofile' ) ) {
    class BP_Admin { 
    516532        public function admin_head() {
    517533
    518534                // Settings pages.
    519                 remove_submenu_page( $this->settings_page, 'bp-page-settings' );
    520                 remove_submenu_page( $this->settings_page, 'bp-settings'      );
    521                 remove_submenu_page( $this->settings_page, 'bp-credits'       );
     535                remove_submenu_page( $this->settings_page, 'bp-page-settings'     );
     536                remove_submenu_page( $this->settings_page, 'bp-settings'          );
     537                remove_submenu_page( $this->settings_page, 'bp-credits'           );
     538                remove_submenu_page( $this->settings_page, 'bp-rewrites-settings' );
    522539
    523540                // Network Admin Tools.
    524541                remove_submenu_page( 'network-tools', 'network-tools' );
  • src/bp-core/classes/class-bp-component.php

    diff --git src/bp-core/classes/class-bp-component.php src/bp-core/classes/class-bp-component.php
    index 4802bf07f..196f40c79 100644
    class BP_Component { 
    236236                        'slug'                  => $this->id,
    237237                        'root_slug'             => $default_root_slug,
    238238                        'has_directory'         => false,
     239                        'rewrite_ids'           => array(),
    239240                        'directory_title'       => '',
    240241                        'notification_callback' => '',
    241242                        'search_string'         => '',
    class BP_Component { 
    261262                 */
    262263                $this->root_slug             = apply_filters( 'bp_' . $this->id . '_root_slug',             $r['root_slug']             );
    263264
     265                /**
     266                 * Filters the component's rewrite IDs if available.
     267                 *
     268                 * @since 6.0.0
     269                 *
     270                 * @param array $value The list of rewrite IDs of the component.
     271                 */
     272                $this->rewrite_ids           = apply_filters( 'bp_' . $this->id . '_rewrite_ids',           $r['rewrite_ids']           );
     273
    264274                /**
    265275                 * Filters the component's top-level directory if available.
    266276                 *
    class BP_Component { 
    270280                 */
    271281                $this->has_directory         = apply_filters( 'bp_' . $this->id . '_has_directory',         $r['has_directory']         );
    272282
     283                // Set the component's directory permastruct early so that it's available to build links.
     284                if ( $this->has_directory && isset( $this->rewrite_ids['directory'] ) ) {
     285                        $this->directory_permastruct = $this->root_slug . '/%' . $this->rewrite_ids['directory'] . '%';
     286                }
     287
    273288                /**
    274289                 * Filters the component's directory title.
    275290                 *
    class BP_Component { 
    768783         * Add any additional rewrite tags.
    769784         *
    770785         * @since 1.5.0
     786         * @since 6.0.0 Added the `$rewrite_tags` parameter.
     787         *
     788         * @param array $rewrite tags {
     789         *      Associative array of arguments list used to register WordPress permastructs.
     790         *      The main array keys describe the rules type and allow individual edits if needed.
    771791         *
     792         *      @type string $id    The name of the new rewrite tag. Required.
     793         *      @type string $regex The regular expression to substitute the tag for in rewrite rules.
     794         *                          Required.
     795         * }
    772796         */
    773         public function add_rewrite_tags() {
     797        public function add_rewrite_tags( $rewrite_tags = array() ) {
     798                if ( $rewrite_tags ) {
     799                        foreach ( (array) $rewrite_tags as $rewrite_tag ) {
     800                                if ( ! isset( $rewrite_tag['id'] ) || ! isset( $rewrite_tag['regex'] ) ) {
     801                                        continue;
     802                                }
     803
     804                                add_rewrite_tag( $rewrite_tag['id'], $rewrite_tag['regex'] );
     805                        }
     806                }
    774807
    775808                /**
    776809                 * Fires in the add_rewrite_tags method inside BP_Component.
    class BP_Component { 
    786819         * Add any additional rewrite rules.
    787820         *
    788821         * @since 1.9.0
     822         * @since 6.0.0 Added the `$rewrite_rules` parameter.
     823         *
     824         * @param array $rewrite_rules {
     825         *      Associative array of arguments list used to register WordPress permastructs.
     826         *      The main array keys describe the rules type and allow individual edits if needed.
    789827         *
     828         *      @type string $regex    Regular expression to match request against. Required.
     829         *      @type string $query    The corresponding query vars for this rewrite rule. Required.
     830         *      @type string $priority The Priority of the new rule. Accepts 'top' or 'bottom'. Optional.
     831         *                             Default 'top'.
     832         * }
    790833         */
    791         public function add_rewrite_rules() {
     834        public function add_rewrite_rules( $rewrite_rules = array() ) {
     835                $priority = 'top';
     836
     837                if ( $rewrite_rules ) {
     838                        foreach ( $rewrite_rules as $rewrite_rule ) {
     839                                if ( ! isset( $rewrite_rule['regex'] ) || ! isset( $rewrite_rule['query'] ) ) {
     840                                        continue;
     841                                }
     842
     843                                if ( ! isset( $rewrite_rule['priority'] ) || ! ! $rewrite_rule['priority'] ) {
     844                                        $rewrite_rule['priority'] = $priority;
     845                                }
     846
     847                                add_rewrite_rule( $rewrite_rule['regex'], $rewrite_rule['query'], $rewrite_rule['priority'] );
     848                        }
     849                }
    792850
    793851                /**
    794852                 * Fires in the add_rewrite_rules method inside BP_Component.
    class BP_Component { 
    804862         * Add any permalink structures.
    805863         *
    806864         * @since 1.9.0
     865         * @since 6.0.0 Added the `$structs` parameter.
    807866         *
     867         * @param array $structs {
     868         *      Associative array of arguments list used to register WordPress permastructs.
     869         *      The main array keys hold the name argument of the `add_permastruct()` function.
     870         *
     871         *      @type string $struct The permalink structure. Required.
     872         *      @type array  $args   The permalink structure arguments. Optional
     873         * }
    808874         */
    809         public function add_permastructs() {
     875        public function add_permastructs( $structs = array() ) {
     876                if ( ! $structs ) {
     877                        return;
     878                }
     879
     880                foreach ( (array) $structs as $name => $params ) {
     881                        if ( ! $name || ! isset( $params['struct'] ) || ! $params['struct'] ) {
     882                                continue;
     883                        }
     884
     885                        if ( ! $params['args'] ) {
     886                                $params['args'] = array();
     887                        }
     888
     889                        $args = wp_parse_args( $params['args'], array(
     890                                'with_front'  => false,
     891                                'ep_mask'     => EP_NONE,
     892                                'paged'       => true,
     893                                'feed'        => false,
     894                                'forcomments' => false,
     895                                'walk_dirs'   => true,
     896                                'endpoints'   => false,
     897                        ) );
     898
     899                        // Add the permastruct.
     900                        add_permastruct( $name, $params['struct'], $args );
     901                }
    810902
    811903                /**
    812904                 * Fires in the add_permastructs method inside BP_Component.
    class BP_Component { 
    824916         * @since 1.9.0
    825917         *
    826918         *
    827          * @param object $query The main WP_Query.
     919         * @param WP_Query $query The main WP_Query.
    828920         */
    829         public function parse_query( $query ) {
     921        public function parse_query( WP_Query $query ) {
     922                if ( bp_use_wp_rewrites() && is_buddypress() ) {
     923                        add_filter( 'posts_pre_query', array( $this, 'posts_pre_query' ), 10, 2 );
     924                }
    830925
    831926                /**
    832927                 * Fires in the parse_query method inside BP_Component.
    class BP_Component { 
    835930                 *
    836931                 * @since 1.9.0
    837932                 *
    838                  * @param object $query Main WP_Query object. Passed by reference.
     933                 * @param WP_Query $query Main WP_Query object. Passed by reference.
    839934                 */
    840935                do_action_ref_array( 'bp_' . $this->id . '_parse_query', array( &$query ) );
    841936        }
    842937
     938        /**
     939         * Make sure to avoid querying for regular posts when displaying a BuddyPress page.
     940         *
     941         * @since 6.0.0
     942         *
     943         * @param  null       $return A null value to use the regular WP Query.
     944         * @param  WP_Query   $query  The WP Query object.
     945         * @return null|array         Null if not displaying a BuddyPress page.
     946         *                            An array containing the BuddyPress directory Post otherwise.
     947         */
     948        public function posts_pre_query( $return = null, WP_Query $query ) {
     949                remove_filter( 'posts_pre_query', array( $this, 'posts_pre_query' ), 10, 2 );
     950
     951                $queried_object = $query->get_queried_object();
     952
     953                if ( is_a( $queried_object, 'WP_Post' ) && 'bp_directories' === get_post_type( $queried_object ) ) {
     954                        return array( $queried_object );
     955                }
     956
     957                return null;
     958        }
     959
    843960        /**
    844961         * Generate any additional rewrite rules.
    845962         *
  • src/bp-friends/classes/class-bp-friends-component.php

    diff --git src/bp-friends/classes/class-bp-friends-component.php src/bp-friends/classes/class-bp-friends-component.php
    index 90a244b75..5f76030cc 100644
    class BP_Friends_Component extends BP_Component { 
    186186                        'position'            => 60,
    187187                        'screen_function'     => 'friends_screen_my_friends',
    188188                        'default_subnav_slug' => 'my-friends',
    189                         'item_css_id'         => $this->id
     189                        'item_css_id'         => $this->id,
     190                        'rewrite_id'          => 'bp_member_' . $slug,
    190191                );
    191192
    192193                // Add the subnav items to the friends nav item.
  • src/bp-groups/actions/create.php

    diff --git src/bp-groups/actions/create.php src/bp-groups/actions/create.php
    index fa196caa7..16a7e9d88 100644
    function groups_action_create_group() { 
    4444
    4545                $reset_steps = true;
    4646                $keys        = array_keys( $bp->groups->group_creation_steps );
    47                 bp_core_redirect( trailingslashit( bp_get_groups_directory_permalink() . 'create/step/' . array_shift( $keys ) ) );
     47                bp_core_redirect( bp_get_group_create_link( array_shift( $keys ) ) );
    4848        }
    4949
    5050        // If this is a creation step that is not recognized, just redirect them back to the first screen.
    5151        if ( bp_get_groups_current_create_step() && empty( $bp->groups->group_creation_steps[bp_get_groups_current_create_step()] ) ) {
    5252                bp_core_add_message( __('There was an error saving group details. Please try again.', 'buddypress'), 'error' );
    53                 bp_core_redirect( trailingslashit( bp_get_groups_directory_permalink() . 'create' ) );
     53                bp_core_redirect( bp_get_group_create_link() );
    5454        }
    5555
    5656        // Fetch the currently completed steps variable.
    function groups_action_create_group() { 
    6464                // Only allow the group creator to continue to edit the new group.
    6565                if ( ! bp_is_group_creator( $bp->groups->current_group, bp_loggedin_user_id() ) ) {
    6666                        bp_core_add_message( __( 'Only the group creator may continue editing this group.', 'buddypress' ), 'error' );
    67                         bp_core_redirect( trailingslashit( bp_get_groups_directory_permalink() . 'create' ) );
     67                        bp_core_redirect( bp_get_group_create_link() );
    6868                }
    6969        }
    7070
    function groups_action_create_group() { 
    7777                if ( 'group-details' == bp_get_groups_current_create_step() ) {
    7878                        if ( empty( $_POST['group-name'] ) || empty( $_POST['group-desc'] ) || !strlen( trim( $_POST['group-name'] ) ) || !strlen( trim( $_POST['group-desc'] ) ) ) {
    7979                                bp_core_add_message( __( 'Please fill in all of the required fields', 'buddypress' ), 'error' );
    80                                 bp_core_redirect( trailingslashit( bp_get_groups_directory_permalink() . 'create/step/' . bp_get_groups_current_create_step() ) );
     80                                bp_core_redirect( bp_get_group_create_link( bp_get_groups_current_create_step() ) );
    8181                        }
    8282
    8383                        $new_group_id = isset( $bp->groups->new_group_id ) ? $bp->groups->new_group_id : 0;
    8484
    8585                        if ( !$bp->groups->new_group_id = groups_create_group( array( 'group_id' => $new_group_id, 'name' => $_POST['group-name'], 'description' => $_POST['group-desc'], 'slug' => groups_check_slug( sanitize_title( esc_attr( $_POST['group-name'] ) ) ), 'date_created' => bp_core_current_time(), 'status' => 'public' ) ) ) {
    8686                                bp_core_add_message( __( 'There was an error saving group details. Please try again.', 'buddypress' ), 'error' );
    87                                 bp_core_redirect( trailingslashit( bp_get_groups_directory_permalink() . 'create/step/' . bp_get_groups_current_create_step() ) );
     87                                bp_core_redirect( bp_get_group_create_link( bp_get_groups_current_create_step() ) );
    8888                        }
    8989                }
    9090
    function groups_action_create_group() { 
    103103
    104104                        if ( !$bp->groups->new_group_id = groups_create_group( array( 'group_id' => $bp->groups->new_group_id, 'status' => $group_status, 'enable_forum' => $group_enable_forum ) ) ) {
    105105                                bp_core_add_message( __( 'There was an error saving group details. Please try again.', 'buddypress' ), 'error' );
    106                                 bp_core_redirect( trailingslashit( bp_get_groups_directory_permalink() . 'create/step/' . bp_get_groups_current_create_step() ) );
     106                                bp_core_redirect( bp_get_group_create_link( bp_get_groups_current_create_step() ) );
    107107                        }
    108108
    109109                        // Save group types.
    function groups_action_create_group() { 
    216216                                }
    217217                        }
    218218
    219                         bp_core_redirect( trailingslashit( bp_get_groups_directory_permalink() . 'create/step/' . $next_step ) );
     219                        bp_core_redirect( bp_get_group_create_link( $next_step ) );
    220220                }
    221221        }
    222222
    function groups_action_create_group() { 
    235235                }
    236236
    237237                bp_core_add_message( $message, $error );
    238                 bp_core_redirect( trailingslashit( bp_get_groups_directory_permalink() . 'create/step/group-invites' ) );
     238                bp_core_redirect( bp_get_group_create_link( 'group-invites' ) );
    239239        }
    240240
    241241        // Group avatar is handled separately.
    function groups_action_sort_creation_steps() { 
    337337         * @since 2.3.0
    338338         */
    339339        do_action( 'groups_action_sort_creation_steps' );
    340 }
    341  No newline at end of file
     340}
  • src/bp-groups/bp-groups-template.php

    diff --git src/bp-groups/bp-groups-template.php src/bp-groups/bp-groups-template.php
    index 575eeaceb..87f2e9f5b 100644
    function bp_groups_directory_permalink() { 
    121121                return apply_filters( 'bp_get_groups_directory_permalink', trailingslashit( bp_get_root_domain() . '/' . bp_get_groups_root_slug() ) );
    122122        }
    123123
     124/**
     125 * Output the create group link.
     126 *
     127 * @since 6.0.0
     128 *
     129 * @param string $step The group creation step name.
     130 */
     131function bp_group_create_link( $step = '' ) {
     132        echo esc_url( bp_get_group_create_link( $step ) );
     133}
     134
     135        /**
     136         * Return the create group link.
     137         *
     138         * @since 6.0.0
     139         *
     140         * @param  string $step The group creation step name.
     141         * @return string
     142         */
     143        function bp_get_group_create_link( $step = '' ) {
     144                $link = trailingslashit( bp_get_groups_directory_permalink() . 'create' );
     145
     146                if ( $step ) {
     147                        $link = trailingslashit( $link . 'step/' . $step );
     148                }
     149
     150                /**
     151                 * Filters the create group link.
     152                 *
     153                 * @since 6.0.0
     154                 *
     155                 * @param string $link The create group link.
     156                 * @param string $step The group creation step name.
     157                 */
     158                return apply_filters( 'bp_get_group_create_link', $link, $step );
     159        }
     160
    124161/**
    125162 * Output group type directory permalink.
    126163 *
    function bp_group_admin_form_action( $page = false ) { 
    29082945                 *
    29092946                 * @since 1.0.0
    29102947                 * @since 2.5.0 Added the `$group` parameter.
     2948                 * @since 6.0.0 Added the `$page` parameter.
    29112949                 *
    29122950                 * @param string $value Action attribute for a group admin form.
    29132951                 * @param object $group Group object.
     2952                 * @param string $page  The Admin page slug.
    29142953                 */
    2915                 return apply_filters( 'bp_group_admin_form_action', trailingslashit( bp_get_group_permalink( $group ) . 'admin/' . $page ), $group );
     2954                return apply_filters( 'bp_group_admin_form_action', trailingslashit( bp_get_group_permalink( $group ) . 'admin/' . $page ), $group, $page );
    29162955        }
    29172956
    29182957/**
    function bp_group_create_button() { 
    34493488                        'component'  => 'groups',
    34503489                        'link_text'  => __( 'Create a Group', 'buddypress' ),
    34513490                        'link_class' => 'group-create no-ajax',
    3452                         'link_href'  => trailingslashit( bp_get_groups_directory_permalink() . 'create' ),
     3491                        'link_href'  => bp_get_group_create_link(),
    34533492                        'wrapper'    => false,
    34543493                        'block_self' => false,
    34553494                );
    function bp_group_creation_form_action() { 
    45464585        function bp_get_group_creation_form_action() {
    45474586                $bp = buddypress();
    45484587
    4549                 if ( !bp_action_variable( 1 ) ) {
     4588                if ( ! bp_action_variable( 1 ) ) {
    45504589                        $keys = array_keys( $bp->groups->group_creation_steps );
    45514590                        $bp->action_variables[1] = array_shift( $keys );
    45524591                }
    function bp_group_creation_form_action() { 
    45584597                 *
    45594598                 * @param string $value Action to be used with group creation form.
    45604599                 */
    4561                 return apply_filters( 'bp_get_group_creation_form_action', trailingslashit( bp_get_groups_directory_permalink() . 'create/step/' . bp_action_variable( 1 ) ) );
     4600                return apply_filters( 'bp_get_group_creation_form_action', bp_get_group_create_link( bp_action_variable( 1 ) ) );
    45624601        }
    45634602
    45644603/**
  • src/bp-groups/classes/class-bp-groups-component.php

    diff --git src/bp-groups/classes/class-bp-groups-component.php src/bp-groups/classes/class-bp-groups-component.php
    index f7d45658d..71d89bd52 100644
    class BP_Groups_Component extends BP_Component { 
    212212                }
    213213        }
    214214
     215        /**
     216         * Get the current Group object using its slug.
     217         *
     218         * @since 6.0.0
     219         *
     220         * @param  string               $group_slug The Group slug used into the URL path.
     221         * @return int|BP_Groups_Group  The current group found. 0 otherwise.
     222         */
     223        public function get_current_group( $group_slug = '' ) {
     224                if ( ! bp_is_groups_component() || ! $group_slug ) {
     225                        return 0;
     226                }
     227
     228                // Get the BuddyPress main instance.
     229                $bp = buddypress();
     230
     231                // Try to find a group ID matching the requested slug.
     232                $group_id = BP_Groups_Group::group_exists( $group_slug );
     233                if ( ! $group_id ) {
     234                        $group_id = BP_Groups_Group::get_id_by_previous_slug( $group_slug );
     235                }
     236
     237                // The Group was not found?
     238                if ( ! $group_id ) {
     239                        return 0;
     240                }
     241
     242                // Set the single item and init the current group.
     243                $bp->is_single_item  = true;
     244                $current_group       = 0;
     245
     246                /**
     247                 * Filters the current PHP Class being used.
     248                 *
     249                 * @since 1.5.0
     250                 *
     251                 * @param string $value Name of the class being used.
     252                 */
     253                $current_group_class = apply_filters( 'bp_groups_current_group_class', 'BP_Groups_Group' );
     254
     255                if ( $current_group_class == 'BP_Groups_Group' ) {
     256                        $current_group = groups_get_group( $group_id );
     257
     258                } else {
     259
     260                        /**
     261                         * Filters the current group object being instantiated from previous filter.
     262                         *
     263                         * @since 1.5.0
     264                         *
     265                         * @param object $value Newly instantiated object for the group.
     266                         */
     267                        $current_group = apply_filters( 'bp_groups_current_group_object', new $current_group_class( $group_id ) );
     268                }
     269
     270                // We have a group let's add some other usefull things.
     271                if ( $current_group ) {
     272                        // Using "item" not "group" for generic support in other components.
     273                        if ( bp_current_user_can( 'bp_moderate' ) ) {
     274                                bp_update_is_item_admin( true, 'groups' );
     275                        } else {
     276                                bp_update_is_item_admin( groups_is_user_admin( bp_loggedin_user_id(), $current_group->id ), 'groups' );
     277                        }
     278
     279                        // If the user is not an admin, check if they are a moderator.
     280                        if ( ! bp_is_item_admin() ) {
     281                                bp_update_is_item_mod( groups_is_user_mod( bp_loggedin_user_id(), $current_group->id ), 'groups' );
     282                        }
     283
     284                        // Check once if the current group has a custom front template.
     285                        $current_group->front_template = bp_groups_get_front_template( $current_group );
     286
     287                        // Initialize the nav for the groups component.
     288                        $this->nav = new BP_Core_Nav( $current_group->id );
     289                }
     290
     291                return $current_group;
     292        }
     293
    215294        /**
    216295         * Set up component global data.
    217296         *
    class BP_Groups_Component extends BP_Component { 
    254333                        'slug'                  => BP_GROUPS_SLUG,
    255334                        'root_slug'             => isset( $bp->pages->groups->slug ) ? $bp->pages->groups->slug : BP_GROUPS_SLUG,
    256335                        'has_directory'         => true,
     336                        'rewrite_ids'     => array(
     337                                'directory'                    => 'bp_groups',
     338                                'directory_type'               => 'bp_groups_type',
     339                                'create_single_item'           => 'bp_group_create',
     340                                'create_single_item_variables' => 'bp_group_create_variables',
     341                                'single_item'                  => 'bp_group',
     342                                'single_item_action'           => 'bp_group_action',
     343                                'single_item_action_variables' => 'bp_group_action_variables',
     344                        ),
    257345                        'directory_title'       => isset( $bp->pages->groups->title ) ? $bp->pages->groups->title : $default_directory_title,
    258346                        'notification_callback' => 'groups_format_notifications',
    259347                        'search_string'         => _x( 'Search Groups...', 'Component directory search', 'buddypress' ),
    class BP_Groups_Component extends BP_Component { 
    266354                /* Single Group Globals **********************************************/
    267355
    268356                // Are we viewing a single group?
    269                 if ( bp_is_groups_component()
    270                         && ( ( $group_id = BP_Groups_Group::group_exists( bp_current_action() ) )
    271                                 || ( $group_id = BP_Groups_Group::get_id_by_previous_slug( bp_current_action() ) ) )
    272                         ) {
    273                         $bp->is_single_item  = true;
     357                $this->current_group = $this->get_current_group( bp_current_action() );
    274358
     359                if ( $this->current_group ) {
    275360                        /**
    276                          * Filters the current PHP Class being used.
    277                          *
    278                          * @since 1.5.0
    279                          *
    280                          * @param string $value Name of the class being used.
     361                         * When in a single group, the first action is bumped down one because of the
     362                         * group name, so we need to adjust this and set the group name to current_item.
    281363                         */
    282                         $current_group_class = apply_filters( 'bp_groups_current_group_class', 'BP_Groups_Group' );
    283 
    284                         if ( $current_group_class == 'BP_Groups_Group' ) {
    285                                 $this->current_group = groups_get_group( $group_id );
    286 
    287                         } else {
    288 
    289                                 /**
    290                                  * Filters the current group object being instantiated from previous filter.
    291                                  *
    292                                  * @since 1.5.0
    293                                  *
    294                                  * @param object $value Newly instantiated object for the group.
    295                                  */
    296                                 $this->current_group = apply_filters( 'bp_groups_current_group_object', new $current_group_class( $group_id ) );
    297                         }
    298 
    299                         // When in a single group, the first action is bumped down one because of the
    300                         // group name, so we need to adjust this and set the group name to current_item.
    301364                        $bp->current_item   = bp_current_action();
    302365                        $bp->current_action = bp_action_variable( 0 );
    303366                        array_shift( $bp->action_variables );
    304 
    305                         // Using "item" not "group" for generic support in other components.
    306                         if ( bp_current_user_can( 'bp_moderate' ) ) {
    307                                 bp_update_is_item_admin( true, 'groups' );
    308                         } else {
    309                                 bp_update_is_item_admin( groups_is_user_admin( bp_loggedin_user_id(), $this->current_group->id ), 'groups' );
    310                         }
    311 
    312                         // If the user is not an admin, check if they are a moderator.
    313                         if ( ! bp_is_item_admin() ) {
    314                                 bp_update_is_item_mod  ( groups_is_user_mod  ( bp_loggedin_user_id(), $this->current_group->id ), 'groups' );
    315                         }
    316 
    317                         // Check once if the current group has a custom front template.
    318                         $this->current_group->front_template = bp_groups_get_front_template( $this->current_group );
    319 
    320                         // Initialize the nav for the groups component.
    321                         $this->nav = new BP_Core_Nav( $this->current_group->id );
    322 
    323                 // Set current_group to 0 to prevent debug errors.
    324                 } else {
    325                         $this->current_group = 0;
    326367                }
    327368
    328369                // Set group type if available.
    class BP_Groups_Component extends BP_Component { 
    548589                        'position'            => 70,
    549590                        'screen_function'     => 'groups_screen_my_groups',
    550591                        'default_subnav_slug' => 'my-groups',
    551                         'item_css_id'         => $this->id
     592                        'item_css_id'         => $this->id,
     593                        'rewrite_id'          => 'bp_member_' . $slug,
    552594                );
    553595
    554596                if ( ! empty( $user_domain ) ) {
    class BP_Groups_Component extends BP_Component { 
    839881                                        'parent'   => 'my-account-' . $this->id,
    840882                                        'id'       => 'my-account-' . $this->id . '-create',
    841883                                        'title'    => _x( 'Create a Group', 'My Account Groups sub nav', 'buddypress' ),
    842                                         'href'     => trailingslashit( bp_get_groups_directory_permalink() . 'create' ),
     884                                        'href'     => bp_get_group_create_link(),
    843885                                        'position' => 90
    844886                                );
    845887                        }
    class BP_Groups_Component extends BP_Component { 
    919961                // Group Type.
    920962                register_taxonomy( 'bp_group_type', 'bp_group', array(
    921963                        'public' => false,
     964                        /**
     965                         * Prevents WordPress Taxonomy rewrite rules to be automaticaly generated.
     966                         * Rewrite rules for the Group Type Taxonomy is handled within the Groups
     967                         * component class {@see BP_Groups_Component::add_rewrite_rules()}}.
     968                         */
     969                        'rewrite' => false,
    922970                ) );
    923971        }
     972
     973        /**
     974         * Add the component's rewrite tags.
     975         *
     976         * @since 6.0.0
     977         *
     978         * @param array $rewrite_tags Optional. See BP_Component::add_rewrite_tags() for
     979         *                            description.
     980         */
     981        public function add_rewrite_tags( $rewrite_tags = array() ) {
     982                if ( ! bp_use_wp_rewrites() ) {
     983                        return parent::add_rewrite_tags( $rewrite_tags );
     984                }
     985
     986                $rewrite_tags = array(
     987                        'directory' => array(
     988                                'id'    => '%' . $this->rewrite_ids['directory'] . '%',
     989                                'regex' => '([1]{1,})',
     990                        ),
     991                        'directory-type' => array(
     992                                'id'    => '%' . $this->rewrite_ids['directory_type'] . '%',
     993                                'regex' => '([^/]+)',
     994                        ),
     995                        'create-single-item' => array(
     996                                'id'      => '%' . $this->rewrite_ids['create_single_item'] . '%',
     997                                'regex'   => '([1]{1,})',
     998                        ),
     999                        'create-single-item-variables' => array(
     1000                                'id'      => '%' . $this->rewrite_ids['create_single_item_variables'] . '%',
     1001                                'regex'   => '([^/]+)',
     1002                        ),
     1003                        'single-item' => array(
     1004                                'id'      => '%' . $this->rewrite_ids['single_item'] . '%',
     1005                                'regex'   => '([^/]+)',
     1006                        ),
     1007                        'single-item-action' => array(
     1008                                'id'      => '%' . $this->rewrite_ids['single_item_action'] . '%',
     1009                                'regex'   => '([^/]+)',
     1010                        ),
     1011                        'single-item-action-variables' => array(
     1012                                'id'      => '%' . $this->rewrite_ids['single_item_action_variables'] . '%',
     1013                                'regex'   => '([^/]+)',
     1014                        ),
     1015                );
     1016
     1017                parent::add_rewrite_tags( $rewrite_tags );
     1018        }
     1019
     1020        /**
     1021         * Add the component's rewrite rules.
     1022         *
     1023         * @since 6.0.0
     1024         *
     1025         * @param array $rewrite_rules Optional. See BP_Component::add_rewrite_rules() for
     1026         *                             description.
     1027         */
     1028        public function add_rewrite_rules( $rewrite_rules = array() ) {
     1029                if ( ! bp_use_wp_rewrites() ) {
     1030                        return parent::add_rewrite_rules( $rewrite_rules );
     1031                }
     1032
     1033                $rewrite_rules = array(
     1034                        'create-single-item-variables' => array(
     1035                                'regex' => $this->root_slug . '/create\/(.+?)/?$' ,
     1036                                'query' => 'index.php?' . $this->rewrite_ids['directory'] . '=1&' . $this->rewrite_ids['create_single_item'] . '=1&' . $this->rewrite_ids['create_single_item_variables'] . '=$matches[1]',
     1037                        ),
     1038                        'create-single-item' => array(
     1039                                'regex' => $this->root_slug . '/create/?$' ,
     1040                                'query' => 'index.php?' . $this->rewrite_ids['directory'] . '=1&' . $this->rewrite_ids['create_single_item'] . '=1',
     1041                        ),
     1042                        'paged-directory-type' => array(
     1043                                'regex' => $this->root_slug . '/' . bp_get_groups_group_type_base() . '/([^/]+)/page/?([0-9]{1,})/?$' ,
     1044                                'query' => 'index.php?' . $this->rewrite_ids['directory'] . '=1&' . $this->rewrite_ids['directory_type'] . '=$matches[1]&paged=$matches[2]',
     1045                        ),
     1046                        'directory-type' => array(
     1047                                'regex' => $this->root_slug . '/' . bp_get_groups_group_type_base() . '/([^/]+)/?$' ,
     1048                                'query' => 'index.php?' . $this->rewrite_ids['directory'] . '=1&' . $this->rewrite_ids['directory_type'] . '=$matches[1]',
     1049                        ),
     1050                        'paged-directory' => array(
     1051                                'regex' => $this->root_slug . '/page/?([0-9]{1,})/?$',
     1052                                'query' => 'index.php?' . $this->rewrite_ids['directory'] . '=1&paged=$matches[1]',
     1053                        ),
     1054                        'single-item-action-variables' => array(
     1055                                'regex' => $this->root_slug . '/([^/]+)\/([^/]+)\/(.+?)/?$',
     1056                                'query' => 'index.php?' . $this->rewrite_ids['directory'] . '=1&' . $this->rewrite_ids['single_item'] . '=$matches[1]&' . $this->rewrite_ids['single_item_action'] . '=$matches[2]&' . $this->rewrite_ids['single_item_action_variables'] . '=$matches[3]',
     1057                        ),
     1058                        'single-item-action' => array(
     1059                                'regex' => $this->root_slug . '/([^/]+)\/([^/]+)/?$',
     1060                                'query' => 'index.php?' . $this->rewrite_ids['directory'] . '=1&' . $this->rewrite_ids['single_item'] . '=$matches[1]&' . $this->rewrite_ids['single_item_action'] . '=$matches[2]',
     1061                        ),
     1062                        'single-item' => array(
     1063                                'regex' => $this->root_slug . '/([^/]+)/?$',
     1064                                'query' => 'index.php?' . $this->rewrite_ids['directory'] . '=1&' . $this->rewrite_ids['single_item'] . '=$matches[1]',
     1065                        ),
     1066                        'directory' => array(
     1067                                'regex' => $this->root_slug,
     1068                                'query' => 'index.php?' . $this->rewrite_ids['directory'] . '=1',
     1069                        ),
     1070                );
     1071
     1072                parent::add_rewrite_rules( $rewrite_rules );
     1073        }
     1074
     1075        /**
     1076         * Add the component's directory permastructs.
     1077         *
     1078         * @since 6.0.0
     1079         *
     1080         * @param array $structs Optional. See BP_Component::add_permastructs() for
     1081         *                       description.
     1082         */
     1083        public function add_permastructs( $structs = array() ) {
     1084                if ( ! bp_use_wp_rewrites() ) {
     1085                        return parent::add_permastructs( $structs );
     1086                }
     1087
     1088                $permastructs = array(
     1089                        // Directory permastruct.
     1090                        $this->rewrite_ids['directory'] => array(
     1091                                'struct' => $this->directory_permastruct,
     1092                                'args'   => array(),
     1093                        ),
     1094                );
     1095
     1096                parent::add_permastructs( $permastructs );
     1097        }
     1098
     1099        /**
     1100         * Parse the WP_Query and eventually display the component's directory or single item.
     1101         *
     1102         * @since 6.0.0
     1103         *
     1104         * @param WP_Query $query Required. See BP_Component::parse_query() for
     1105         *                        description.
     1106         */
     1107        public function parse_query( WP_Query $query ) {
     1108                if ( ! bp_use_wp_rewrites() ) {
     1109                        return parent::parse_query( $query );
     1110                }
     1111
     1112                $is_groups_component = 1 === (int) $query->get( $this->rewrite_ids['directory'] );
     1113                $bp                  = buddypress();
     1114                $group_type          = false;
     1115
     1116                if ( $is_groups_component ) {
     1117                        $bp->current_component = 'groups';
     1118                        $group_slug            = $query->get( $this->rewrite_ids['single_item'] );
     1119                        $group_type_slug       = $query->get( $this->rewrite_ids['directory_type'] );
     1120                        $is_group_create       = 1 === (int) $query->get( $this->rewrite_ids['create_single_item'] );
     1121
     1122                        if ( $group_slug ) {
     1123                                $this->current_group = $this->get_current_group( $group_slug );
     1124
     1125                                if ( ! $this->current_group ) {
     1126                                        bp_do_404();
     1127                                        return;
     1128                                }
     1129
     1130                                // Set the current item using the group slug.
     1131                                $bp->current_item = $group_slug;
     1132
     1133                                $current_action = $query->get( $this->rewrite_ids['single_item_action'] );
     1134                                if ( $current_action ) {
     1135                                        $bp->current_action = $current_action;
     1136                                }
     1137
     1138                                $action_variables = $query->get( $this->rewrite_ids['single_item_action_variables'] );
     1139                                if ( $action_variables ) {
     1140                                        if ( ! is_array( $action_variables ) )  {
     1141                                                $bp->action_variables = explode( '/', ltrim( $action_variables, '/' ) );
     1142                                        } else {
     1143                                                $bp->action_variables = $action_variables;
     1144                                        }
     1145                                }
     1146                        } elseif ( $group_type_slug ) {
     1147                                $group_type = bp_groups_get_group_types( array(
     1148                                        'has_directory'  => true,
     1149                                        'directory_slug' => $group_type_slug,
     1150                                ) );
     1151
     1152                                if ( $group_type ) {
     1153                                        $group_type                   = reset( $group_type );
     1154                                        $this->current_directory_type = $group_type;
     1155                                        $bp->current_action           = bp_get_groups_group_type_base();
     1156                                        $bp->action_variables         = array( $group_type_slug );
     1157                                } else {
     1158                                        bp_do_404();
     1159                                        return;
     1160                                }
     1161                        } elseif ( $is_group_create ) {
     1162                                $bp->current_action = 'create';
     1163
     1164                                if ( bp_user_can_create_groups() && isset( $_COOKIE['bp_new_group_id'] ) ) {
     1165                                        $bp->groups->new_group_id = (int) $_COOKIE['bp_new_group_id'];
     1166                                }
     1167
     1168                                $create_variables = $query->get( $this->rewrite_ids['create_single_item_variables'] );
     1169                                if ( $create_variables ) {
     1170                                        if ( ! is_array( $create_variables ) )  {
     1171                                                $bp->action_variables = explode( '/', ltrim( $create_variables, '/' ) );
     1172                                        } else {
     1173                                                $bp->action_variables = $create_variables;
     1174                                        }
     1175                                }
     1176                        }
     1177
     1178                        /**
     1179                         * Set the BuddyPress queried object.
     1180                         */
     1181                        $query->queried_object    = get_post( $bp->pages->groups->id );
     1182                        $query->queried_object_id = $query->queried_object->ID;
     1183
     1184                        if ( $this->current_group ) {
     1185                                $query->queried_object->single_item_name = $this->current_group->name;
     1186                        } elseif ( $group_type ) {
     1187                                $query->queried_object->directory_type_name = $group_type;
     1188                        }
     1189                }
     1190
     1191                parent::parse_query( $query );
     1192        }
    9241193}
  • src/bp-groups/screens/single/admin.php

    diff --git src/bp-groups/screens/single/admin.php src/bp-groups/screens/single/admin.php
    index 027a77064..4340bc08d 100644
     
    1313 * @since 1.0.0
    1414 */
    1515function groups_screen_group_admin() {
    16         if ( !bp_is_groups_component() || !bp_is_current_action( 'admin' ) )
     16        if ( ! bp_is_groups_component() || ! bp_is_current_action( 'admin' ) ) {
    1717                return false;
     18        }
    1819
    19         if ( bp_action_variables() )
     20        if ( bp_action_variables() ) {
    2021                return false;
     22        }
    2123
    22         bp_core_redirect( bp_get_group_permalink( groups_get_current_group() ) . 'admin/edit-details/' );
    23 }
    24  No newline at end of file
     24        bp_core_redirect( bp_get_group_admin_form_action( 'edit-details', groups_get_current_group() ) );
     25}
  • src/bp-groups/screens/single/admin/edit-details.php

    diff --git src/bp-groups/screens/single/admin/edit-details.php src/bp-groups/screens/single/admin/edit-details.php
    index 27f180c88..e1fee0b92 100644
    function groups_screen_group_admin_edit_details() { 
    5353                         */
    5454                        do_action( 'groups_group_details_edited', $bp->groups->current_group->id );
    5555
    56                         bp_core_redirect( bp_get_group_permalink( groups_get_current_group() ) . 'admin/edit-details/' );
     56                        bp_core_redirect( bp_get_group_admin_form_action( 'edit-details', groups_get_current_group() ) );
    5757                }
    5858
    5959                /**
    function groups_screen_group_admin_edit_details() { 
    7575                bp_core_load_template( apply_filters( 'groups_template_group_admin', 'groups/single/home' ) );
    7676        }
    7777}
    78 add_action( 'bp_screens', 'groups_screen_group_admin_edit_details' );
    79  No newline at end of file
     78add_action( 'bp_screens', 'groups_screen_group_admin_edit_details' );
  • src/bp-members/bp-members-functions.php

    diff --git src/bp-members/bp-members-functions.php src/bp-members/bp-members-functions.php
    index 58fd1777e..9ffdcd868 100644
    function bp_core_signup_avatar_upload_dir() { 
    21732173function bp_core_signup_send_validation_email( $user_id, $user_email, $key, $salutation = '' ) {
    21742174        $args = array(
    21752175                'tokens' => array(
    2176                         'activate.url' => esc_url( trailingslashit( bp_get_activation_page() ) . "{$key}/" ),
     2176                        'activate.url' => esc_url( trailingslashit( bp_get_activation_page( $key ) ) ),
    21772177                        'key'          => $key,
    21782178                        'user.email'   => $user_email,
    21792179                        'user.id'      => $user_id,
  • src/bp-members/bp-members-template.php

    diff --git src/bp-members/bp-members-template.php src/bp-members/bp-members-template.php
    index 17701f866..d3eec37f3 100644
    function bp_get_displayed_user_nav() { 
    14781478                        $selected = ' class="current selected"';
    14791479                }
    14801480
    1481                 if ( bp_loggedin_user_domain() ) {
    1482                         $link = str_replace( bp_loggedin_user_domain(), bp_displayed_user_domain(), $user_nav_item->link );
     1481                /**
     1482                 * Rewrites directly set the displayed user link. This substitution is
     1483                 * only required when BuddyPress is using the legacy URL parser.
     1484                 */
     1485                if ( ! bp_use_wp_rewrites() ) {
     1486                        if ( bp_loggedin_user_domain() ) {
     1487                                $link = str_replace( bp_loggedin_user_domain(), bp_displayed_user_domain(), $user_nav_item->link );
     1488                        } else {
     1489                                $link = trailingslashit( bp_displayed_user_domain() . $user_nav_item->link );
     1490                        }
    14831491                } else {
    1484                         $link = trailingslashit( bp_displayed_user_domain() . $user_nav_item->link );
     1492                        $link = $user_nav_item->link;
    14851493                }
    14861494
    14871495                /**
    function bp_has_custom_activation_page() { 
    20892097 * Output the URL of the activation page.
    20902098 *
    20912099 * @since 1.0.0
     2100 * @since 6.0.0 Added the `$key` parameter.
     2101 *
     2102 * @param string $key The activation key.
    20922103 */
    2093 function bp_activation_page() {
    2094         echo esc_url( bp_get_activation_page() );
     2104function bp_activation_page( $key = '' ) {
     2105        echo esc_url( bp_get_activation_page( $key ) );
    20952106}
    20962107        /**
    20972108         * Get the URL of the activation page.
    20982109         *
    20992110         * @since 1.2.0
     2111         * @since 6.0.0 Added the `$key` parameter.
    21002112         *
     2113         * @param string $key The activation key.
    21012114         * @return string
    21022115         */
    2103         function bp_get_activation_page() {
    2104                 if ( bp_has_custom_activation_page() ) {
     2116        function bp_get_activation_page( $key = '' ) {
     2117                $has_custom_activation_page = bp_has_custom_activation_page();
     2118
     2119                if ( $has_custom_activation_page ) {
    21052120                        $page = trailingslashit( bp_get_root_domain() . '/' . bp_get_activate_slug() );
     2121
     2122                        if ( $key ) {
     2123                                $page .= $key . '/';
     2124                        }
    21062125                } else {
    21072126                        $page = trailingslashit( bp_get_root_domain() ) . 'wp-activate.php';
     2127
     2128                        if ( $key ) {
     2129                                $page = add_query_arg( 'key', $key, $page );
     2130                        }
    21082131                }
    21092132
    21102133                /**
    21112134                 * Filters the URL of the activation page.
    21122135                 *
    21132136                 * @since 1.2.0
     2137                 * @since 6.0.0 Added the `$key` & `$has_custom_activation_page` parameters.
    21142138                 *
    2115                  * @param string $page URL to the activation page.
     2139                 * @param string $page                       URL to the activation page.
     2140                 * @param string $key                        The activation key.
     2141                 * @param bool   $has_custom_activation_page Whether the site has a custom activation
     2142                 *                                           page or not.
    21162143                 */
    2117                 return apply_filters( 'bp_get_activation_page', $page );
     2144                return apply_filters( 'bp_get_activation_page', $page, $key, $has_custom_activation_page );
    21182145        }
    21192146
    21202147/**
  • src/bp-members/classes/class-bp-members-component.php

    diff --git src/bp-members/classes/class-bp-members-component.php src/bp-members/classes/class-bp-members-component.php
    index 20c3eccee..f3a71a77c 100644
    class BP_Members_Component extends BP_Component { 
    160160                        'slug'            => BP_MEMBERS_SLUG,
    161161                        'root_slug'       => isset( $bp->pages->members->slug ) ? $bp->pages->members->slug : BP_MEMBERS_SLUG,
    162162                        'has_directory'   => true,
     163                        'rewrite_ids'     => array(
     164                                'directory'                    => 'bp_members',
     165                                'directory_type'               => 'bp_members_type',
     166                                'single_item'                  => 'bp_member',
     167                                'single_item_component'        => 'bp_member_component',
     168                                'single_item_action'           => 'bp_member_action',
     169                                'single_item_action_variables' => 'bp_member_action_variables',
     170                                'member_register'              => 'bp_register',
     171                                'member_activate'              => 'bp_activate',
     172                                'member_activate_key'          => 'bp_activate_key',
     173                        ),
    163174                        'directory_title' => isset( $bp->pages->members->title ) ? $bp->pages->members->title : $default_directory_title,
    164175                        'search_string'   => __( 'Search Members...', 'buddypress' ),
    165176                        'global_tables'   => array(
    class BP_Members_Component extends BP_Component { 
    170181
    171182                parent::setup_globals( $args );
    172183
     184                // Set-up Extra permastructs for the register and activate pages
     185                $this->register_permastruct = bp_get_signup_slug() . '/%' . $this->rewrite_ids['member_register'] . '%';
     186                $this->activate_permastruct = bp_get_activate_slug() . '/%' . $this->rewrite_ids['member_activate'] . '%';
     187
    173188                /** Logged in user ***************************************************
    174189                 */
    175190
    class BP_Members_Component extends BP_Component { 
    256271                        $bp->canonical_stack['base_url'] = bp_displayed_user_domain();
    257272
    258273                        if ( bp_current_component() ) {
    259                                 $bp->canonical_stack['component'] = bp_current_component();
     274                                $item_component = bp_current_component();
     275                                $bp->canonical_stack['component'] = $item_component;
     276
     277                                if ( bp_use_wp_rewrites() ) {
     278                                        $bp->canonical_stack['component'] = bp_rewrites_get_slug( 'members', 'bp_member_' . $item_component, $item_component );
     279                                }
    260280                        }
    261281
    262282                        if ( bp_current_action() ) {
    class BP_Members_Component extends BP_Component { 
    337357                                'position'            => 20,
    338358                                'screen_function'     => 'bp_members_screen_display_profile',
    339359                                'default_subnav_slug' => 'public',
    340                                 'item_css_id'         => buddypress()->profile->id
     360                                'item_css_id'         => buddypress()->profile->id,
     361                                'rewrite_id'          => 'bp_member_profile',
    341362                        );
    342363                }
    343364
    class BP_Members_Component extends BP_Component { 
    367388                                'position'            => 5,
    368389                                'screen_function'     => 'bp_members_screen_display_profile',
    369390                                'default_subnav_slug' => 'public',
     391                                'rewrite_id'          => 'bp_member_front',
    370392                        );
    371393
    372394                        // We need a dummy subnav for the front page to load.
    class BP_Members_Component extends BP_Component { 
    456478
    457479                parent::setup_cache_groups();
    458480        }
     481
     482        /**
     483         * Add the component's rewrite tags.
     484         *
     485         * @since 6.0.0
     486         *
     487         * @param array $rewrite_tags Optional. See BP_Component::add_rewrite_tags() for
     488         *                            description.
     489         */
     490        public function add_rewrite_tags( $rewrite_tags = array() ) {
     491                if ( ! bp_use_wp_rewrites() ) {
     492                        return parent::add_rewrite_tags( $rewrite_tags );
     493                }
     494
     495                $rewrite_tags = array(
     496                        'directory' => array(
     497                                'id'    => '%' . $this->rewrite_ids['directory'] . '%',
     498                                'regex' => '([1]{1,})',
     499                        ),
     500                        'directory-type' => array(
     501                                'id'    => '%' . $this->rewrite_ids['directory_type'] . '%',
     502                                'regex' => '([^/]+)',
     503                        ),
     504                        'member-register' => array(
     505                                'id'    => '%' . $this->rewrite_ids['member_register'] . '%',
     506                                'regex' => '([1]{1,})',
     507                        ),
     508                        'member-activate' => array(
     509                                'id'    => '%' . $this->rewrite_ids['member_activate'] . '%',
     510                                'regex' => '([1]{1,})',
     511                        ),
     512                        'member-activate-key' => array(
     513                                'id'    => '%' . $this->rewrite_ids['member_activate_key'] . '%',
     514                                'regex' => '([^/]+)',
     515                        ),
     516                        'single-item' => array(
     517                                'id'      => '%' . $this->rewrite_ids['single_item'] . '%',
     518                                'regex'   => '([^/]+)',
     519                        ),
     520                        'single-item-component' => array(
     521                                'id'      => '%' . $this->rewrite_ids['single_item_component'] . '%',
     522                                'regex'   => '([^/]+)',
     523                        ),
     524                        'single-item-action' => array(
     525                                'id'      => '%' . $this->rewrite_ids['single_item_action'] . '%',
     526                                'regex'   => '([^/]+)',
     527                        ),
     528                        'single-item-action-variables' => array(
     529                                'id'      => '%' . $this->rewrite_ids['single_item_action_variables'] . '%',
     530                                'regex'   => '([^/]+)',
     531                        ),
     532                );
     533
     534                parent::add_rewrite_tags( $rewrite_tags );
     535        }
     536
     537        /**
     538         * Add the component's rewrite rules.
     539         *
     540         * @since 6.0.0
     541         *
     542         * @param array $rewrite_rules Optional. See BP_Component::add_rewrite_rules() for
     543         *                             description.
     544         */
     545        public function add_rewrite_rules( $rewrite_rules = array() ) {
     546                if ( ! bp_use_wp_rewrites() ) {
     547                        return parent::add_rewrite_rules( $rewrite_rules );
     548                }
     549
     550                $rewrite_rules = array(
     551                        'member-register' => array(
     552                                'regex' => bp_get_signup_slug(),
     553                                'query' => 'index.php?' . $this->rewrite_ids['member_register'] . '=1',
     554                        ),
     555                        'member-activate-key' => array(
     556                                'regex' => bp_get_activate_slug() . '/([^/]+)/?$',
     557                                'query' => 'index.php?' . $this->rewrite_ids['member_activate'] . '=1&' . $this->rewrite_ids['member_activate_key'] . '=$matches[1]',
     558                        ),
     559                        'member-activate' => array(
     560                                'regex' => bp_get_activate_slug(),
     561                                'query' => 'index.php?' . $this->rewrite_ids['member_activate'] . '=1',
     562                        ),
     563                        'paged-directory-type' => array(
     564                                'regex' => $this->root_slug . '/' . bp_get_members_member_type_base() . '/([^/]+)/page/?([0-9]{1,})/?$' ,
     565                                'query' => 'index.php?' . $this->rewrite_ids['directory'] . '=1&' . $this->rewrite_ids['directory_type'] . '=$matches[1]&paged=$matches[2]',
     566                        ),
     567                        'directory-type' => array(
     568                                'regex' => $this->root_slug . '/' . bp_get_members_member_type_base() . '/([^/]+)/?$' ,
     569                                'query' => 'index.php?' . $this->rewrite_ids['directory'] . '=1&' . $this->rewrite_ids['directory_type'] . '=$matches[1]',
     570                        ),
     571                        'paged-directory' => array(
     572                                'regex' => $this->root_slug . '/page/?([0-9]{1,})/?$',
     573                                'query' => 'index.php?' . $this->rewrite_ids['directory'] . '=1&paged=$matches[1]',
     574                        ),
     575                        'single-item-action-variables' => array(
     576                                'regex' => $this->root_slug . '/([^/]+)\/([^/]+)\/([^/]+)\/(.+?)/?$',
     577                                'query' => 'index.php?' . $this->rewrite_ids['directory'] . '=1&' . $this->rewrite_ids['single_item'] . '=$matches[1]&' . $this->rewrite_ids['single_item_component'] . '=$matches[2]&' . $this->rewrite_ids['single_item_action'] . '=$matches[3]&' . $this->rewrite_ids['single_item_action_variables'] . '=$matches[4]',
     578                        ),
     579                        'single-item-action' => array(
     580                                'regex' => $this->root_slug . '/([^/]+)\/([^/]+)\/([^/]+)/?$',
     581                                'query' => 'index.php?' . $this->rewrite_ids['directory'] . '=1&' . $this->rewrite_ids['single_item'] . '=$matches[1]&' . $this->rewrite_ids['single_item_component'] . '=$matches[2]&' . $this->rewrite_ids['single_item_action'] . '=$matches[3]',
     582                        ),
     583                        'single-item-component' => array(
     584                                'regex' => $this->root_slug . '/([^/]+)\/([^/]+)/?$',
     585                                'query' => 'index.php?' . $this->rewrite_ids['directory'] . '=1&' . $this->rewrite_ids['single_item'] . '=$matches[1]&' . $this->rewrite_ids['single_item_component'] . '=$matches[2]',
     586                        ),
     587                        'single-item' => array(
     588                                'regex' => $this->root_slug . '/([^/]+)/?$',
     589                                'query' => 'index.php?' . $this->rewrite_ids['directory'] . '=1&' . $this->rewrite_ids['single_item'] . '=$matches[1]',
     590                        ),
     591                        'directory' => array(
     592                                'regex' => $this->root_slug,
     593                                'query' => 'index.php?' . $this->rewrite_ids['directory'] . '=1',
     594                        ),
     595                );
     596
     597                parent::add_rewrite_rules( $rewrite_rules );
     598        }
     599
     600        /**
     601         * Add the component's directory permastructs.
     602         *
     603         * @since 6.0.0
     604         *
     605         * @param array $structs Optional. See BP_Component::add_permastructs() for
     606         *                       description.
     607         */
     608        public function add_permastructs( $structs = array() ) {
     609                if ( ! bp_use_wp_rewrites() ) {
     610                        return parent::add_permastructs( $structs );
     611                }
     612
     613                $permastructs = array(
     614                        // Directory permastruct.
     615                        $this->rewrite_ids['directory'] => array(
     616                                'struct' => $this->directory_permastruct,
     617                                'args'   => array(),
     618                        ),
     619                        // Register permastruct.
     620                        $this->rewrite_ids['member_register'] => array(
     621                                'struct' => $this->register_permastruct,
     622                                'args'   => array(),
     623                        ),
     624                        // Activate permastruct.
     625                        $this->rewrite_ids['member_activate'] => array(
     626                                'struct' => $this->activate_permastruct,
     627                                'args'   => array(),
     628                        ),
     629                );
     630
     631                parent::add_permastructs( $permastructs );
     632        }
     633
     634        /**
     635         * Parse the WP_Query and eventually display the component's directory or single item.
     636         *
     637         * @since 6.0.0
     638         *
     639         * @param WP_Query $query Required. See BP_Component::parse_query() for
     640         *                        description.
     641         */
     642        public function parse_query( WP_Query $query ) {
     643                if ( ! bp_use_wp_rewrites() ) {
     644                        return parent::parse_query( $query );
     645                }
     646
     647                // Init the current member and member type.
     648                $member       = false;
     649                $member_type  = false;
     650                $member_data  = bp_rewrites_get_member_data();
     651
     652                if ( isset( $member_data['object'] ) && $member_data['object'] ) {
     653                        bp_reset_query( trailingslashit( $this->root_slug ) . $GLOBALS['wp']->request, $query );
     654                        $member = $member_data['object'];
     655
     656                        // Make sure the Member's screen is fired.
     657                        add_action( 'bp_screens', 'bp_members_screen_display_profile', 3 );
     658                }
     659
     660                $is_members_component   = 1 === (int) $query->get( $this->rewrite_ids['directory'] );
     661                $is_register_component  = 1 === (int) $query->get( $this->rewrite_ids['member_register'] );
     662                $is_activate_component  = 1 === (int) $query->get( $this->rewrite_ids['member_activate'] );
     663                $bp                     = buddypress();
     664
     665                if ( $is_members_component ) {
     666                        $bp->current_component = 'members';
     667                        $member_slug           = $query->get( $this->rewrite_ids['single_item'] );
     668                        $member_type_slug      = $query->get( $this->rewrite_ids['directory_type'] );
     669
     670
     671                        if ( $member_slug ) {
     672                                $bp->current_component = '';
     673
     674                                // Unless root profiles are on, the member shouldn't be set yet.
     675                                if ( ! $member ) {
     676                                        $member = get_user_by( $member_data['field'], $member_slug );
     677
     678                                        if ( ! $member ) {
     679                                                bp_do_404();
     680                                                return;
     681                                        }
     682                                }
     683
     684                                // If the member is marked as a spammer, 404 (unless logged-in user is a super admin).
     685                                if ( bp_is_user_spammer( $member->ID ) ) {
     686                                        if ( bp_current_user_can( 'bp_moderate' ) ) {
     687                                                bp_core_add_message( __( 'This user has been marked as a spammer. Only site admins can view this profile.', 'buddypress' ), 'warning' );
     688                                        } else {
     689                                                bp_do_404();
     690                                                return;
     691                                        }
     692                                }
     693
     694                                // Set the displayed user and the current item.
     695                                $bp->displayed_user->id = $member->ID;
     696                                $bp->current_item       = $member_slug;
     697
     698                                // The core userdata of the user who is currently being displayed.
     699                                if ( ! isset( $bp->displayed_user->userdata ) || ! $bp->displayed_user->userdata ) {
     700                                        $bp->displayed_user->userdata = bp_core_get_core_userdata( bp_displayed_user_id() );
     701                                }
     702
     703                                // Fetch the full name displayed user.
     704                                if ( ! isset( $bp->displayed_user->fullname ) || ! $bp->displayed_user->fullname ) {
     705                                        $bp->displayed_user->fullname = '';
     706                                        if ( isset( $bp->displayed_user->userdata->display_name ) ) {
     707                                                $bp->displayed_user->fullname = $bp->displayed_user->userdata->display_name;
     708                                        }
     709                                }
     710
     711                                // The domain for the user currently being displayed.
     712                                if ( ! isset( $bp->displayed_user->domain ) || ! $bp->displayed_user->domain ) {
     713                                        $bp->displayed_user->domain   = bp_core_get_user_domain( bp_displayed_user_id() );
     714                                }
     715
     716                                // If A user is displayed, check if there is a front template
     717                                if ( bp_get_displayed_user() ) {
     718                                        $bp->displayed_user->front_template = bp_displayed_user_get_front_template();
     719                                }
     720
     721                                $member_component = $query->get( $this->rewrite_ids['single_item_component'] );
     722                                if ( $member_component ) {
     723
     724                                        // Check if the member's component slug has been customized.
     725                                        $item_component_rewrite_id = bp_rewrites_get_custom_slug_rewrite_id( 'members', $member_component );
     726                                        if ( $item_component_rewrite_id ) {
     727                                                $member_component = str_replace( 'bp_member_', '', $item_component_rewrite_id );
     728                                        }
     729
     730                                        $bp->current_component = $member_component;
     731                                }
     732
     733                                $current_action = $query->get( $this->rewrite_ids['single_item_action'] );
     734                                if ( $current_action ) {
     735                                        $bp->current_action = $current_action;
     736                                }
     737
     738                                $action_variables = $query->get( $this->rewrite_ids['single_item_action_variables'] );
     739                                if ( $action_variables ) {
     740                                        if ( ! is_array( $action_variables ) )  {
     741                                                $bp->action_variables = explode( '/', ltrim( $action_variables, '/' ) );
     742                                        } else {
     743                                                $bp->action_variables = $action_variables;
     744                                        }
     745                                }
     746
     747                        // Is this a member type query ?
     748                        } elseif ( $member_type_slug ) {
     749                                $member_type = bp_get_member_types( array(
     750                                        'has_directory'  => true,
     751                                        'directory_slug' => $member_type_slug,
     752                                ) );
     753
     754                                if ( $member_type ) {
     755                                        $member_type             = reset( $member_type );
     756                                        $bp->current_member_type = $member_type;
     757                                } else {
     758                                        $bp->current_component = '';
     759                                        bp_do_404();
     760                                        return;
     761                                }
     762                        }
     763
     764                        /**
     765                         * Set the BuddyPress queried object.
     766                         */
     767                        $query->queried_object    = get_post( $bp->pages->members->id );
     768                        $query->queried_object_id = $query->queried_object->ID;
     769
     770                        if ( $member ) {
     771                                $query->queried_object->single_item_name = $member->display_name;
     772                        } elseif ( $member_type ) {
     773                                $query->queried_object->directory_type_name = $member_type;
     774                        }
     775
     776                // Handle the custom registration page.
     777                } elseif ( $is_register_component ) {
     778                        $bp->current_component = 'register';
     779
     780                // Handle the custom activation page.
     781                } elseif ( $is_activate_component ) {
     782                        $bp->current_component = 'activate';
     783
     784                        $current_action = $query->get( $this->rewrite_ids['member_activate_key'] );
     785                        if ( $current_action ) {
     786                                $bp->current_action = $current_action;
     787                        }
     788                }
     789
     790                parent::parse_query( $query );
     791        }
    459792}
  • src/bp-members/screens/activate.php

    diff --git src/bp-members/screens/activate.php src/bp-members/screens/activate.php
    index 581a6fd7d..f8e5984f3 100644
    function bp_members_action_activate_account() { 
    100100        // If there were errors, add a message and redirect.
    101101        if ( ! empty( $user->errors ) ) {
    102102                bp_core_add_message( $user->get_error_message(), 'error' );
    103                 bp_core_redirect( trailingslashit( bp_get_root_domain() . '/' . $bp->pages->activate->slug ) );
     103                bp_core_redirect( bp_get_activation_page() );
    104104        }
    105105
    106106        bp_core_add_message( __( 'Your account is now active!', 'buddypress' ) );
    107107        bp_core_redirect( add_query_arg( 'activated', '1', bp_get_activation_page() ) );
    108108
    109109}
    110 add_action( 'bp_actions', 'bp_members_action_activate_account' );
    111  No newline at end of file
     110add_action( 'bp_actions', 'bp_members_action_activate_account' );
  • src/bp-messages/classes/class-bp-messages-component.php

    diff --git src/bp-messages/classes/class-bp-messages-component.php src/bp-messages/classes/class-bp-messages-component.php
    index b9ccc35ee..ea8303939 100644
    class BP_Messages_Component extends BP_Component { 
    231231                        'show_for_displayed_user' => $access,
    232232                        'screen_function'         => 'messages_screen_inbox',
    233233                        'default_subnav_slug'     => 'inbox',
    234                         'item_css_id'             => $this->id
     234                        'item_css_id'             => $this->id,
     235                        'rewrite_id'              => 'bp_member_' . $slug,
    235236                );
    236237
    237238                // Add the subnav items to the profile.
  • src/bp-notifications/classes/class-bp-notifications-component.php

    diff --git src/bp-notifications/classes/class-bp-notifications-component.php src/bp-notifications/classes/class-bp-notifications-component.php
    index 52716bfe8..8a442d53b 100644
    class BP_Notifications_Component extends BP_Component { 
    180180                        'screen_function'         => 'bp_notifications_screen_unread',
    181181                        'default_subnav_slug'     => 'unread',
    182182                        'item_css_id'             => $this->id,
     183                        'rewrite_id'              => 'bp_member_' . $slug,
    183184                );
    184185
    185186                // Add the subnav items to the notifications nav item.
  • src/bp-settings/classes/class-bp-settings-component.php

    diff --git src/bp-settings/classes/class-bp-settings-component.php src/bp-settings/classes/class-bp-settings-component.php
    index dda4a928d..fff17e9c5 100644
    class BP_Settings_Component extends BP_Component { 
    144144                        'position'                => 100,
    145145                        'show_for_displayed_user' => $access,
    146146                        'screen_function'         => 'bp_settings_screen_general',
    147                         'default_subnav_slug'     => 'general'
     147                        'default_subnav_slug'     => 'general',
     148                        'rewrite_id'              => 'bp_member_' . $slug,
    148149                );
    149150
    150151                // Add General Settings nav item.
  • src/bp-templates/bp-nouveau/includes/blogs/functions.php

    diff --git src/bp-templates/bp-nouveau/includes/blogs/functions.php src/bp-templates/bp-nouveau/includes/blogs/functions.php
    index 548c28be9..fb0c28639 100644
    function bp_nouveau_get_blogs_directory_nav_items() { 
    4747                                'component' => 'blogs',
    4848                                'slug'      => 'create', // slug is used because BP_Core_Nav requires it, but it's the scope
    4949                                'li_class'  => array( 'no-ajax', 'site-create', 'create-button' ),
    50                                 'link'      => trailingslashit( bp_get_blogs_directory_permalink() . 'create' ),
     50                                'link'      => bp_get_blog_create_link(),
    5151                                'text'      => __( 'Create a Site', 'buddypress' ),
    5252                                'count'     => false,
    5353                                'position'  => 999,
  • src/bp-templates/bp-nouveau/includes/groups/functions.php

    diff --git src/bp-templates/bp-nouveau/includes/groups/functions.php src/bp-templates/bp-nouveau/includes/groups/functions.php
    index e0f18356c..7af4c2b17 100644
    function bp_nouveau_get_groups_directory_nav_items() { 
    532532                                'component' => 'groups',
    533533                                'slug'      => 'create', // slug is used because BP_Core_Nav requires it, but it's the scope
    534534                                'li_class'  => array( 'no-ajax', 'group-create', 'create-button' ),
    535                                 'link'      => trailingslashit( bp_get_groups_directory_permalink() . 'create' ),
     535                                'link'      => bp_get_group_create_link(),
    536536                                'text'      => __( 'Create a Group', 'buddypress' ),
    537537                                'count'     => false,
    538538                                'position'  => 999,
  • src/bp-templates/bp-nouveau/includes/template-tags.php

    diff --git src/bp-templates/bp-nouveau/includes/template-tags.php src/bp-templates/bp-nouveau/includes/template-tags.php
    index 8662aa552..12936e3b9 100644
    function bp_nouveau_nav_link() { 
    10391039                        $link = $nav_item->link;
    10401040                }
    10411041
    1042                 if ( 'personal' === $bp_nouveau->displayed_nav && ! empty( $nav_item->primary ) ) {
    1043                         if ( bp_loggedin_user_domain() ) {
    1044                                 $link = str_replace( bp_loggedin_user_domain(), bp_displayed_user_domain(), $link );
    1045                         } else {
    1046                                 $link = trailingslashit( bp_displayed_user_domain() . $link );
     1042                /**
     1043                 * Rewrites directly set the displayed user link. This substitution is
     1044                 * only required when BuddyPress is using the legacy URL parser.
     1045                 */
     1046                if ( ! bp_use_wp_rewrites() ) {
     1047                        if ( 'personal' === $bp_nouveau->displayed_nav && ! empty( $nav_item->primary ) ) {
     1048                                if ( bp_loggedin_user_domain() ) {
     1049                                        $link = str_replace( bp_loggedin_user_domain(), bp_displayed_user_domain(), $link );
     1050                                } else {
     1051                                        $link = trailingslashit( bp_displayed_user_domain() . $link );
     1052                                }
    10471053                        }
    10481054                }
    10491055
  • src/bp-xprofile/bp-xprofile-template.php

    diff --git src/bp-xprofile/bp-xprofile-template.php src/bp-xprofile/bp-xprofile-template.php
    index 6f5a3c10a..1cd1bc07a 100644
    function bp_the_profile_group_description() { 
    363363 * Output the XProfile group edit form action.
    364364 *
    365365 * @since 1.1.0
     366 * @since 6.0.0 Added the `$fields_group_id` parameter.
     367 *
     368 * @param int $fields_group_id The ID of the group of fields.
    366369 */
    367 function bp_the_profile_group_edit_form_action() {
    368         echo bp_get_the_profile_group_edit_form_action();
     370function bp_the_profile_group_edit_form_action( $fields_group_id = 0 ) {
     371        echo bp_get_the_profile_group_edit_form_action( $fields_group_id );
    369372}
    370373
    371374        /**
    372375         * Return the XProfile group edit form action.
    373376         *
    374377         * @since 1.1.0
     378         * @since 6.0.0 Added the `$fields_group_id` parameter.
    375379         *
     380         * @param int $fields_group_id The ID of the group of fields.    *
    376381         * @return string
    377382         */
    378         function bp_get_the_profile_group_edit_form_action() {
    379                 global $group;
     383        function bp_get_the_profile_group_edit_form_action( $fields_group_id = 0 ) {
     384                if ( ! $fields_group_id ) {
     385                        global $group;
     386
     387                        $fields_group_id =& $group->id;
     388                }
     389
    380390
    381391                // Build the form action URL.
    382                 $form_action = trailingslashit( bp_displayed_user_domain() . bp_get_profile_slug() . '/edit/group/' . $group->id );
     392                $form_action = trailingslashit( bp_displayed_user_domain() . bp_get_profile_slug() . '/edit/group/' . $fields_group_id );
    383393
    384394                /**
    385395                 * Filters the action for the XProfile group edit form.
    386396                 *
    387397                 * @since 1.1.0
     398                 * @since 6.0.0 Added the `$fields_group_id` parameter.
    388399                 *
    389                  * @param string $value URL for the action attribute on the
    390                  *                      profile group edit form.
     400                 * @param string $form_action     URL for the action attribute on the
     401                 *                                profile group edit form.
     402                 * @param int    $fields_group_id The ID of the group of fields.
    391403                 */
    392                 return apply_filters( 'bp_get_the_profile_group_edit_form_action', $form_action );
     404                return apply_filters( 'bp_get_the_profile_group_edit_form_action', $form_action, $fields_group_id );
    393405        }
    394406
    395407/**
  • src/bp-xprofile/classes/class-bp-xprofile-component.php

    diff --git src/bp-xprofile/classes/class-bp-xprofile-component.php src/bp-xprofile/classes/class-bp-xprofile-component.php
    index 8b619afc9..ee11963f2 100644
    class BP_XProfile_Component extends BP_Component { 
    254254                        'position'            => 20,
    255255                        'screen_function'     => 'xprofile_screen_display_profile',
    256256                        'default_subnav_slug' => 'public',
    257                         'item_css_id'         => $this->id
     257                        'item_css_id'         => $this->id,
     258                        'rewrite_id'          => 'bp_member_' . $slug,
    258259                );
    259260
    260261                // Add the subnav items to the profile.
  • src/bp-xprofile/screens/edit.php

    diff --git src/bp-xprofile/screens/edit.php src/bp-xprofile/screens/edit.php
    index e0b85c0e0..49814a096 100644
    function xprofile_screen_edit_profile() { 
    2222
    2323        // Make sure a group is set.
    2424        if ( ! bp_action_variable( 1 ) ) {
    25                 bp_core_redirect( trailingslashit( bp_displayed_user_domain() . bp_get_profile_slug() . '/edit/group/1' ) );
     25                bp_core_redirect( bp_get_the_profile_group_edit_form_action( 1 ) );
    2626        }
    2727
    2828        // Check the field group exists.
    function xprofile_screen_edit_profile() { 
    4242
    4343                // Check we have field ID's.
    4444                if ( empty( $_POST['field_ids'] ) ) {
    45                         bp_core_redirect( trailingslashit( bp_displayed_user_domain() . bp_get_profile_slug() . '/edit/group/' . bp_action_variable( 1 ) ) );
     45                        bp_core_redirect( bp_get_the_profile_group_edit_form_action( bp_action_variable( 1 ) ) );
    4646                }
    4747
    4848                // Explode the posted field IDs into an array so we know which
    function xprofile_screen_edit_profile() { 
    134134                        }
    135135
    136136                        // Redirect back to the edit screen to display the updates and message.
    137                         bp_core_redirect( trailingslashit( bp_displayed_user_domain() . bp_get_profile_slug() . '/edit/group/' . bp_action_variable( 1 ) ) );
     137                        bp_core_redirect( bp_get_the_profile_group_edit_form_action( bp_action_variable( 1 ) ) );
    138138                }
    139139        }
    140140
    function xprofile_screen_edit_profile() { 
    153153         * @param string $template Path to the XProfile edit template to load.
    154154         */
    155155        bp_core_load_template( apply_filters( 'xprofile_template_edit_profile', 'members/single/home' ) );
    156 }
    157  No newline at end of file
     156}
  • src/class-buddypress.php

    diff --git src/class-buddypress.php src/class-buddypress.php
    index e6d8d609b..1eb9cbc28 100644
    class BuddyPress { 
    474474                require( $this->plugin_dir . 'bp-core/bp-core-cssjs.php'            );
    475475                require( $this->plugin_dir . 'bp-core/bp-core-update.php'           );
    476476                require( $this->plugin_dir . 'bp-core/bp-core-options.php'          );
     477                require( $this->plugin_dir . 'bp-core/bp-core-rewrites.php'         );
    477478                require( $this->plugin_dir . 'bp-core/bp-core-taxonomy.php'         );
    478479                require( $this->plugin_dir . 'bp-core/bp-core-filters.php'          );
    479480                require( $this->plugin_dir . 'bp-core/bp-core-attachments.php'      );