Skip to:
Content

BuddyPress.org


Ignore:
Timestamp:
02/15/2023 10:23:05 AM (3 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.