Skip to:
Content

BuddyPress.org


Ignore:
Timestamp:
02/15/2023 10:23:05 AM (2 years ago)
Author:
imath
Message:

Improve BP_Component methods relative to setting BP Rewrites

So far BP_Component::add_rewrite_tags(),
BP_Component::add_rewrite_rules() & BP_Component::add_permastructs()
were just firing hooks. Thanks to the BP Rewrites plugin we were able to
test how we can use them to actually enjoy the WP Rewrite API in
BuddyPress. Compared to what was tested in this feature as plugin, some
improvements has been brought so that it's easier to benefit from the BP
Rewrites API for custom components (analyzing the included PHPUnit tests
can give BP plugin authors a preview about how to process).

Introduce the BP_Component::pre_query() method to avoid superfluous Post
queries when a BuddyPress page is displayed.

The src/bp-core/bp-rewrites.php file has also been inited, this is the
place where all Core component rewrites function will be placed.

Props r-a-y, johnjamesjacoby, boonebgorges

See #4954

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/bp-core/classes/class-bp-component.php

    r13399 r13422  
    5959     */
    6060    public $has_directory = false;
     61
     62    /**
     63     * Directory's permalink structure for the component.
     64     *
     65     * @since 12.0.0
     66     * @var string
     67     */
     68    public $directory_permastruct = '';
     69
     70    /**
     71     * List of available rewrite IDs for the component.
     72     *
     73     * @since 12.0.0
     74     * @var array
     75     */
     76    public $rewrite_ids = array();
    6177
    6278    /**
     
    258274                'root_slug'             => '',
    259275                'has_directory'         => false,
     276                'rewrite_ids'           => array(),
    260277                'directory_title'       => '',
    261278                'notification_callback' => '',
     
    307324            $this->has_directory = apply_filters( 'bp_' . $this->id . '_has_directory', $r['has_directory'] );
    308325
     326            $rewrite_ids = bp_parse_args(
     327                /**
     328                 * Filters the component's rewrite IDs if available.
     329                 *
     330                 * @since 12.0.0
     331                 *
     332                 * @param array $value The list of rewrite IDs for the component.
     333                 */
     334                (array) apply_filters( 'bp_' . $this->id. '_rewrite_ids', $r['rewrite_ids'] ),
     335                array_fill_keys( array_keys( bp_rewrites_get_default_url_chunks() ), '' )
     336            );
     337
     338            if ( array_filter( $rewrite_ids ) ) {
     339                foreach ( $rewrite_ids as $rewrite_id_key => $rewrite_id_value ) {
     340                    if ( ! $rewrite_id_value ) {
     341                        continue;
     342                    }
     343
     344                    $this->rewrite_ids[ sanitize_key( $rewrite_id_key ) ] = 'bp_' . str_replace( 'bp_', '', sanitize_key( $rewrite_id_value ) );
     345                }
     346            }
     347
     348            // Set the component's directory permastruct early so that it's available to build links.
     349            if ( true === $this->has_directory && isset( $this->rewrite_ids['directory'] ) ) {
     350                $this->directory_permastruct = $this->root_slug . '/%' . $this->rewrite_ids['directory'] . '%';
     351            }
     352
    309353            /**
    310354             * Filters the component's directory title.
     
    503547
    504548        // Add the rewrite tags.
    505         add_action( 'bp_add_rewrite_tags',       array( $this, 'add_rewrite_tags'       ), 10 );
     549        add_action( 'bp_add_rewrite_tags',       array( $this, 'add_rewrite_tags'       ), 10, 0 );
    506550
    507551        // Add the rewrite rules.
    508         add_action( 'bp_add_rewrite_rules',      array( $this, 'add_rewrite_rules'      ), 10 );
     552        add_action( 'bp_add_rewrite_rules',      array( $this, 'add_rewrite_rules'      ), 10, 0 );
    509553
    510554        // Add the permalink structure.
     
    833877
    834878    /**
    835      * Add any additional rewrite tags.
    836      *
    837      * @since 1.5.0
    838      *
    839      */
    840     public function add_rewrite_tags() {
     879     * Add Component's additional rewrite tags.
     880     *
     881     * @since 1.5.0
     882     * @since 12.0.0 Adds the `$rewrite_tags` parameter.
     883     *
     884     * @param array $rewrite_tags Array of arguments list used to add WordPress rewrite tags.
     885     *                            Each argument key needs to match one of `$this->rewrite_ids` keys.
     886     */
     887    public function add_rewrite_tags( $rewrite_tags = array() ) {
     888        if ( array_filter( $this->rewrite_ids ) ) {
     889            $chunks = bp_rewrites_get_default_url_chunks();
     890
     891            foreach ( $this->rewrite_ids as $rewrite_id_key => $rewrite_id_value ) {
     892                $rewrite_tag   = '%' . $rewrite_id_value . '%';
     893                $rewrite_regex = '';
     894
     895                if ( isset( $rewrite_tags[ $rewrite_id_key ] ) ) {
     896                    $rewrite_regex = $rewrite_tags[ $rewrite_id_key ];
     897                } elseif ( isset( $chunks[ $rewrite_id_key ]['regex'] ) ) {
     898                    $rewrite_regex = $chunks[ $rewrite_id_key ]['regex'];
     899                }
     900
     901                if ( ! $rewrite_regex ) {
     902                    continue;
     903                }
     904
     905                add_rewrite_tag( $rewrite_tag, $rewrite_regex );
     906            }
     907        }
    841908
    842909        /**
     
    851918
    852919    /**
    853      * Add any additional rewrite rules.
     920     * Add Component's additional rewrite rules.
    854921     *
    855922     * @since 1.9.0
    856      *
    857      */
    858     public function add_rewrite_rules() {
     923     * @since 12.0.0 Adds the `$rewrite_rules` parameter.
     924     *
     925     * @param array $rewrite_rules {
     926     *     Array of associative arrays of arguments list used to add WordPress rewrite rules.
     927     *     Each associative array needs to include the following keys.
     928     *
     929     *     @type string $regex    Regular expression to match request against. Required.
     930     *     @type string $query    The corresponding query vars for this rewrite rule. Required.
     931     *     @type int    $order    The insertion order for the rewrite rule. Required.
     932     *     @type string $priority The Priority of the new rule. Accepts 'top' or 'bottom'. Optional.
     933     *                            Default 'top'.
     934     * }
     935     */
     936    public function add_rewrite_rules( $rewrite_rules = array() ) {
     937        if ( array_filter( $this->rewrite_ids ) ) {
     938            $priority = 'top';
     939            $chunks   = array_merge( bp_rewrites_get_default_url_chunks(), $rewrite_rules );
     940
     941            $rules          = bp_sort_by_key( $chunks, 'order', 'num', true );
     942            $reversed_rules = array_reverse( $rules, true );
     943
     944            $regex = '';
     945            $query = '';
     946            $match = 1;
     947
     948            // Build rewrite rules for the component.
     949            foreach ( $reversed_rules as $rule_key => $rule_information ) {
     950                if ( ! isset( $this->rewrite_ids[ $rule_key ] ) ) {
     951                    unset( $rules[ $rule_key ] );
     952                    continue;
     953                }
     954
     955                // The query is already set, use it.
     956                if ( isset( $rule_information['query'] ) ) {
     957                    $rules[ $rule_key ]['regex'] = $rule_information['regex'];
     958                    $rules[ $rule_key ]['query'] = $rule_information['query'];
     959                } elseif ( 'directory' === $rule_key ) {
     960                    $regex = $this->root_slug;
     961                    $query = 'index.php?' . $this->rewrite_ids['directory'] . '=1';
     962
     963                    $rules[ $rule_key ]['regex'] = $regex;
     964                    $rules[ $rule_key ]['query'] = $query;
     965                } else {
     966                    $regex  = trailingslashit( $regex ) . $rule_information['regex'];
     967                    $query .= '&' . $this->rewrite_ids[ $rule_key ] . '=$matches['. $match .']';
     968                    $match += 1;
     969
     970                    $rules[ $rule_key ]['regex'] = $regex . '/?$';
     971                    $rules[ $rule_key ]['query'] = $query;
     972                }
     973            }
     974
     975            // Then register the rewrite rules.
     976            if ( $rules ) {
     977                foreach ( $rules as $rewrite_rule ) {
     978                    if ( ! isset( $rewrite_rule['regex'] ) || ! isset( $rewrite_rule['query'] ) ) {
     979                        continue;
     980                    }
     981
     982                    if ( ! isset( $rewrite_rule['priority'] ) || ! $rewrite_rule['priority'] ) {
     983                        $rewrite_rule['priority'] = $priority;
     984                    }
     985
     986                    add_rewrite_rule( $rewrite_rule['regex'], $rewrite_rule['query'], $rewrite_rule['priority'] );
     987                }
     988            }
     989        }
    859990
    860991        /**
     
    8691000
    8701001    /**
    871      * Add any permalink structures.
     1002     * Add Component's permalink structures.
    8721003     *
    8731004     * @since 1.9.0
    874      *
    875      */
    876     public function add_permastructs() {
     1005     * @since 12.0.0 Adds the `$permastructs` parameter.
     1006     *
     1007     * @param array $permastructs {
     1008     *      Array of associative arrays of arguments list used to register WordPress additional permalink structures.
     1009     *      Each array enty is keyed with the permalink structure.
     1010     *      Each associative array needs to include the following keys.
     1011     *
     1012     *      @type string $permastruct The permalink structure. Required.
     1013     *      @type array  $args        The permalink structure arguments. Optional.
     1014     * }
     1015     */
     1016    public function add_permastructs( $permastructs = array() ) {
     1017        // Always include the directory permastruct when the component has a directory.
     1018        if ( isset( $this->rewrite_ids['directory'] ) ) {
     1019            $directory_permastruct = array(
     1020                $this->rewrite_ids['directory'] => array(
     1021                    'permastruct' => $this->directory_permastruct,
     1022                    'args'        => array(),
     1023                ),
     1024            );
     1025
     1026            $permastructs = array_merge( $directory_permastruct, (array) $permastructs );
     1027        }
     1028
     1029        if ( $permastructs ) {
     1030            foreach ( $permastructs as $name => $params ) {
     1031                if ( ! $name || ! isset( $params['permastruct'] ) || ! $params['permastruct'] ) {
     1032                    continue;
     1033                }
     1034
     1035                if ( ! $params['args'] ) {
     1036                    $params['args'] = array();
     1037                }
     1038
     1039                $args = wp_parse_args(
     1040                    $params['args'],
     1041                    array(
     1042                        'with_front'  => false,
     1043                        'ep_mask'     => EP_NONE,
     1044                        'paged'       => true,
     1045                        'feed'        => false,
     1046                        'forcomments' => false,
     1047                        'walk_dirs'   => true,
     1048                        'endpoints'   => false,
     1049                    )
     1050                );
     1051
     1052                // Add the permastruct.
     1053                add_permastruct( $name, $params['permastruct'], $args );
     1054            }
     1055        }
    8771056
    8781057        /**
     
    8911070     * @since 1.9.0
    8921071     *
    893      *
    8941072     * @param object $query The main WP_Query.
    8951073     */
    8961074    public function parse_query( $query ) {
     1075        if ( is_buddypress() ) {
     1076            add_filter( 'posts_pre_query', array( $this, 'pre_query' ), 10, 2 );
     1077        }
    8971078
    8981079        /**
     
    9061087         */
    9071088        do_action_ref_array( 'bp_' . $this->id . '_parse_query', array( &$query ) );
     1089    }
     1090
     1091    /**
     1092     * Make sure to avoid querying for regular posts when displaying a BuddyPress page.
     1093     *
     1094     * @since 12.0.0
     1095     *
     1096     * @param  null     $retval A null value to use the regular WP Query.
     1097     * @param  WP_Query $query  The WP Query object.
     1098     * @return null|array Null if not displaying a BuddyPress page.
     1099     *                    An array containing the BuddyPress directory post otherwise.
     1100     */
     1101    public function pre_query( $retval = null, $query = null ) {
     1102        remove_filter( 'posts_pre_query', array( $this, 'pre_query' ), 10 );
     1103
     1104        $queried_object = $query->get_queried_object();
     1105
     1106        if ( $queried_object instanceof \WP_Post && 'buddypress' === get_post_type( $queried_object ) ) {
     1107            // Only include the queried directory post into returned posts.
     1108            $retval = array( $queried_object );
     1109        }
     1110
     1111        return $retval;
    9081112    }
    9091113
Note: See TracChangeset for help on using the changeset viewer.