Skip to:
Content

BuddyPress.org

Changeset 9723


Ignore:
Timestamp:
04/09/2015 03:31:18 PM (4 years ago)
Author:
boonebgorges
Message:

Introduce member-type-specific Members directories.

The new 'has_directory' argument for bp_register_member_type() allows
developers to specify whether a list of members matching a given type 'foo'
should be available at http://example.com/members/type/foo/. A slug can be
passed to 'has_directory' to customize the URL used for the member type's
directory.

Note that plugins registering member types must do so at the new hook
'bp_register_member_types' in order to be able to customize the 'has_directory'
value (from its default of true).

bp_has_members() automatically detects the presence of a member type in a
URL. When no member type of the form example.com/members/type/foo/ is found,
URLs of the form example.com/members/?member_type=foo will be detected.

See #6286.

Location:
trunk
Files:
12 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/bp-core/bp-core-actions.php

    r9351 r9723  
    5656add_action( 'bp_loaded', 'bp_setup_cache_groups',       5  );
    5757add_action( 'bp_loaded', 'bp_setup_widgets',            6  );
     58add_action( 'bp_loaded', 'bp_register_member_types',    8  );
    5859add_action( 'bp_loaded', 'bp_register_theme_packages',  12 );
    5960add_action( 'bp_loaded', 'bp_register_theme_directory', 14 );
  • trunk/src/bp-core/bp-core-catchuri.php

    r9664 r9723  
    259259        if ( 'members' == $match->key ) {
    260260
    261             // Viewing a specific user
    262             if ( !empty( $bp_uri[$uri_offset + 1] ) ) {
    263 
     261            $after_member_slug = false;
     262            if ( ! empty( $bp_uri[ $uri_offset + 1 ] ) ) {
     263                $after_member_slug = $bp_uri[ $uri_offset + 1 ];
     264            }
     265
     266            // Are we viewing a specific user?
     267            if ( $after_member_slug ) {
    264268                // Switch the displayed_user based on compatibility mode
    265269                if ( bp_is_username_compatibility_mode() ) {
    266                     $bp->displayed_user->id = (int) bp_core_get_userid( urldecode( $bp_uri[$uri_offset + 1] ) );
     270                    $bp->displayed_user->id = (int) bp_core_get_userid( urldecode( $after_member_slug ) );
    267271                } else {
    268                     $bp->displayed_user->id = (int) bp_core_get_userid_from_nicename( urldecode( $bp_uri[$uri_offset + 1] ) );
     272                    $bp->displayed_user->id = (int) bp_core_get_userid_from_nicename( $after_member_slug );
    269273                }
    270 
    271                 if ( !bp_displayed_user_id() ) {
    272 
    273                     // Prevent components from loading their templates
    274                     $bp->current_component = '';
    275 
     274            }
     275
     276            // Is this a member type directory?
     277            if ( ! bp_displayed_user_id() && $after_member_slug === apply_filters( 'bp_members_member_type_base', _x( 'type', 'member type URL base', 'buddypress' ) ) && ! empty( $bp_uri[ $uri_offset + 2 ] ) ) {
     278                $matched_types = bp_get_member_types( array(
     279                    'has_directory'  => true,
     280                    'directory_slug' => $bp_uri[ $uri_offset + 2 ],
     281                ) );
     282
     283                if ( ! empty( $matched_types ) ) {
     284                    $bp->current_member_type = reset( $matched_types );
     285                    unset( $bp_uri[ $uri_offset + 1 ] );
     286                }
     287            }
     288
     289            // If the slug matches neither a member type nor a specific member, 404.
     290            if ( ! bp_displayed_user_id() && ! bp_get_current_member_type() && $after_member_slug ) {
     291                // Prevent components from loading their templates.
     292                $bp->current_component = '';
     293                bp_do_404();
     294                return;
     295            }
     296
     297            // If the displayed user is marked as a spammer, 404 (unless logged-in user is a super admin)
     298            if ( bp_displayed_user_id() && bp_is_user_spammer( bp_displayed_user_id() ) ) {
     299                if ( bp_current_user_can( 'bp_moderate' ) ) {
     300                    bp_core_add_message( __( 'This user has been marked as a spammer. Only site admins can view this profile.', 'buddypress' ), 'warning' );
     301                } else {
    276302                    bp_do_404();
    277303                    return;
    278304                }
    279 
    280                 // If the displayed user is marked as a spammer, 404 (unless logged-
    281                 // in user is a super admin)
    282                 if ( bp_displayed_user_id() && bp_is_user_spammer( bp_displayed_user_id() ) ) {
    283                     if ( bp_current_user_can( 'bp_moderate' ) ) {
    284                         bp_core_add_message( __( 'This user has been marked as a spammer. Only site admins can view this profile.', 'buddypress' ), 'warning' );
    285                     } else {
    286                         bp_do_404();
    287                         return;
    288                     }
    289                 }
    290 
    291                 // Bump the offset
     305            }
     306
     307            // Bump the offset.
     308            if ( bp_displayed_user_id() ) {
    292309                if ( isset( $bp_uri[$uri_offset + 2] ) ) {
    293310                    $bp_uri                = array_merge( array(), array_slice( $bp_uri, $uri_offset + 2 ) );
     
    299316                    $bp->current_component = '';
    300317                }
    301 
    302                 // Reset the offset
    303                 $uri_offset = 0;
    304             }
     318            }
     319
     320            // Reset the offset
     321            $uri_offset = 0;
    305322        }
    306323    }
  • trunk/src/bp-core/bp-core-dependency.php

    r9641 r9723  
    142142
    143143/**
     144 * Fire the 'bp_register_member_types' action, where plugins should register member types.
     145 *
     146 * @since BuddyPress (2.3.0)
     147 */
     148function bp_register_member_types() {
     149    do_action( 'bp_register_member_types' );
     150}
     151
     152/**
    144153 * Fire the 'bp_setup_cache_groups' action, where cache groups are registered.
    145154 *
  • trunk/src/bp-loader.php

    r9716 r9723  
    8080     */
    8181    public $action_variables = array();
     82
     83    /**
     84     * @var string Current member directory type.
     85     */
     86    public $current_member_type = '';
    8287
    8388    /**
  • trunk/src/bp-members/bp-members-functions.php

    r9625 r9723  
    24522452 *     Array of arguments describing the member type.
    24532453 *
    2454  *     @type array $labels {
     2454 *     @type array       $labels {
    24552455 *         Array of labels to use in various parts of the interface.
    24562456 *
     
    24582458 *         @type string $singular_name Singular name.
    24592459 *     }
     2460 *     @type bool|string $has_directory Whether the member type should have its own type-specific directory.
     2461 *                                      Pass `true` to use the `$member_type` string as the type's slug.
     2462 *                                      Pass a string to customize the slug. Pass `false` to disable.
     2463 *                                      Default: true.
    24602464 * }
    24612465 * @return object|WP_Error Member type object on success, WP_Error object on failure.
     
    24692473
    24702474    $r = bp_parse_args( $args, array(
    2471         'labels' => array(),
     2475        'labels'        => array(),
     2476        'has_directory' => true,
    24722477    ), 'register_member_type' );
    24732478
     
    24832488        'singular_name' => $default_name,
    24842489    ), $r['labels'] );
     2490
     2491    // Directory slug.
     2492    if ( $r['has_directory'] ) {
     2493        // A string value is intepreted as the directory slug. Otherwise fall back on member type.
     2494        if ( is_string( $r['has_directory'] ) ) {
     2495            $directory_slug = $r['has_directory'];
     2496        } else {
     2497            $directory_slug = $member_type;
     2498        }
     2499
     2500        // Sanitize for use in URLs.
     2501        $r['directory_slug'] = sanitize_title( $directory_slug );
     2502        $r['has_directory']  = true;
     2503    } else {
     2504        $r['directory_slug'] = '';
     2505        $r['has_directory']  = false;
     2506    }
    24852507
    24862508    $bp->members->types[ $member_type ] = $type = (object) $r;
     
    27152737add_action( 'wpmu_delete_user', 'bp_remove_member_type_on_user_delete' );
    27162738add_action( 'delete_user', 'bp_remove_member_type_on_user_delete' );
     2739
     2740/**
     2741 * Get the "current" member type, if one is provided, in member directories.
     2742 *
     2743 * @since BuddyPress (2.3.0)
     2744 *
     2745 * @return string
     2746 */
     2747function bp_get_current_member_type() {
     2748    return apply_filters( 'bp_get_current_member_type', buddypress()->current_member_type );
     2749}
  • trunk/src/bp-members/bp-members-template.php

    r9698 r9723  
    516516    }
    517517
     518    $member_type = bp_get_current_member_type();
     519    if ( ! $member_type && ! empty( $_GET['member_type'] ) ) {
     520        if ( is_array( $_GET['member_type'] ) ) {
     521            $member_type = $_GET['member_type'];
     522        } else {
     523            // Can be a comma-separated list.
     524            $member_type = explode( ',', $_GET['member_type'] );
     525        }
     526    }
     527
    518528    // type: active ( default ) | random | newest | popular | online | alphabetical
    519529    $r = bp_parse_args( $args, array(
     
    529539
    530540        'user_id'         => $user_id, // Pass a user_id to only show friends of this user
    531         'member_type'     => '',
     541        'member_type'     => $member_type,
    532542        'search_terms'    => null,     // Pass search_terms to filter users by their profile data
    533543
     
    17971807        return apply_filters( 'bp_get_loggedin_user_username', $username );
    17981808    }
     1809/**
     1810 * Echo the current member type message.
     1811 *
     1812 * @since BuddyPress (2.3.0)
     1813 */
     1814function bp_current_member_type_message() {
     1815    echo bp_get_current_member_type_message();
     1816}
     1817    /**
     1818     * Generate the current member type message.
     1819     *
     1820     * @since BuddyPress (2.3.0)
     1821     *
     1822     * @return string
     1823     */
     1824    function bp_get_current_member_type_message() {
     1825        $type_object = bp_get_member_type_object( bp_get_current_member_type() );
     1826
     1827        $message = sprintf( __( 'Viewing members of the type: %s', 'buddypress' ), '<strong>' . $type_object->labels['singular_name'] . '</strong>' );
     1828
     1829        return apply_filters( 'bp_get_current_member_type_message', $message );
     1830    }
    17991831
    18001832/** Signup Form ***************************************************************/
  • trunk/src/bp-templates/bp-legacy/buddypress/members/members-loop.php

    r9604 r9723  
    1313
    1414<?php do_action( 'bp_before_members_loop' ); ?>
     15
     16<?php if ( bp_get_current_member_type() ) : ?>
     17    <p class="current-member-type"><?php bp_current_member_type_message() ?></p>
     18<?php endif; ?>
    1519
    1620<?php if ( bp_has_members( bp_ajax_querystring( 'members' ) ) ) : ?>
  • trunk/src/bp-templates/bp-legacy/css/buddypress.css

    r9604 r9723  
    497497    padding: 1px 3px;
    498498}
    499 
     499#buddypress .current-member-type {
     500    font-style: italic;
     501}
    500502#buddypress .dir-form {
    501503    clear: both;
  • trunk/tests/phpunit/includes/testcase.php

    r9655 r9723  
    4545    function clean_up_global_scope() {
    4646        buddypress()->bp_nav                = buddypress()->bp_options_nav = buddypress()->action_variables = buddypress()->canonical_stack = buddypress()->unfiltered_uri = $GLOBALS['bp_unfiltered_uri'] = array();
    47         buddypress()->current_component     = buddypress()->current_item = buddypress()->current_action = '';
     47        buddypress()->current_component     = buddypress()->current_item = buddypress()->current_action = buddypress()->current_member_type = '';
    4848        buddypress()->unfiltered_uri_offset = 0;
    4949        buddypress()->is_single_item        = false;
  • trunk/tests/phpunit/testcases/members/template.php

    r9561 r9723  
    128128        $member_ids = wp_list_pluck( $members, 'ID' );
    129129        $this->assertEquals( array( $users[1]), $member_ids );
     130
     131        $GLOBALS['members_template'] = $old_members_template;
     132    }
     133
     134    /**
     135     * @group bp_has_members
     136     * @ticket BP6286
     137     */
     138    public function test_bp_has_members_should_infer_member_type_from_get_param() {
     139        bp_register_member_type( 'foo' );
     140        bp_register_member_type( 'bar' );
     141        $users = $this->factory->user->create_many( 3 );
     142        bp_set_member_type( $users[0], 'foo' );
     143        bp_set_member_type( $users[1], 'bar' );
     144
     145        global $members_template;
     146        $old_members_template = $members_template;
     147
     148        $old_get = $_GET;
     149        $_GET['member_type'] = 'bar';
     150
     151        bp_has_members();
     152
     153        $members = is_array( $members_template->members ) ? array_values( $members_template->members ) : array();
     154        $member_ids = wp_list_pluck( $members, 'ID' );
     155        $this->assertEquals( array( $users[1] ), $member_ids );
     156
     157        $GLOBALS['members_template'] = $old_members_template;
     158    }
     159
     160    /**
     161     * @group bp_has_members
     162     * @ticket BP6286
     163     */
     164    public function test_bp_has_members_should_infer_member_type_from_get_param_comma_sep() {
     165        bp_register_member_type( 'foo' );
     166        bp_register_member_type( 'bar' );
     167        bp_register_member_type( 'baz' );
     168        $users = $this->factory->user->create_many( 4 );
     169        bp_set_member_type( $users[0], 'foo' );
     170        bp_set_member_type( $users[1], 'bar' );
     171        bp_set_member_type( $users[2], 'baz' );
     172
     173        global $members_template;
     174        $old_members_template = $members_template;
     175
     176        $old_get = $_GET;
     177        $_GET['member_type'] = 'foo,bar';
     178
     179        bp_has_members();
     180
     181        $members = is_array( $members_template->members ) ? array_values( $members_template->members ) : array();
     182        $member_ids = wp_list_pluck( $members, 'ID' );
     183        $this->assertEqualSets( array( $users[0], $users[1] ), $member_ids );
    130184
    131185        $GLOBALS['members_template'] = $old_members_template;
  • trunk/tests/phpunit/testcases/members/types.php

    r9611 r9723  
    7474    }
    7575
     76    /**
     77     * @ticket BP6286
     78     */
     79    public function test_bp_register_member_type_has_directory_should_default_to_true() {
     80        $object = bp_register_member_type( 'foo', array(
     81            'has_directory' => true,
     82        ) );
     83
     84        $this->assertTrue( $object->has_directory );
     85        $this->assertSame( 'foo', $object->directory_slug );
     86    }
     87
     88    /**
     89     * @ticket BP6286
     90     */
     91    public function test_bp_register_member_type_has_directory_true() {
     92        $object = bp_register_member_type( 'foo', array(
     93            'has_directory' => true,
     94        ) );
     95
     96        $this->assertTrue( $object->has_directory );
     97        $this->assertSame( 'foo', $object->directory_slug );
     98    }
     99
     100    /**
     101     * @ticket BP6286
     102     */
     103    public function test_bp_register_member_type_should_store_has_directory_false() {
     104        $object = bp_register_member_type( 'foo', array(
     105            'has_directory' => false,
     106        ) );
     107
     108        $this->assertFalse( $object->has_directory );
     109        $this->assertSame( '', $object->directory_slug );
     110    }
     111
     112    /**
     113     * @ticket BP6286
     114     */
     115    public function test_bp_register_member_type_should_store_has_directory_string() {
     116        $object = bp_register_member_type( 'foo', array(
     117            'has_directory' => 'foos',
     118        ) );
     119
     120        $this->assertTrue( $object->has_directory );
     121        $this->assertSame( 'foos', $object->directory_slug );
     122    }
     123
    76124    public function test_bp_get_member_type_object_should_return_null_for_non_existent_member_type() {
    77125        $this->assertSame( null, bp_get_member_type_object( 'foo' ) );
  • trunk/tests/phpunit/testcases/routing/members.php

    r8958 r9723  
    1010        parent::setUp();
    1111
     12        buddypress()->members->types = array();
    1213        $this->old_current_user = get_current_user_id();
    1314        $this->set_current_user( $this->factory->user->create( array( 'user_login' => 'paulgibbs', 'role' => 'subscriber' ) ) );
     
    1516
    1617    public function tearDown() {
     18        $this->set_current_user( $this->old_current_user );
    1719        parent::tearDown();
    18         $this->set_current_user( $this->old_current_user );
    1920    }
    2021
     
    2829        $this->assertTrue( bp_is_my_profile() );
    2930    }
     31
     32    /**
     33     * @ticket BP6286
     34     * @group member_types
     35     */
     36    public function test_member_directory_with_member_type() {
     37        bp_register_member_type( 'foo' );
     38        $this->go_to( bp_get_members_directory_permalink() . 'type/foo/' );
     39        $this->assertTrue( bp_is_members_component() );
     40    }
     41
     42    /**
     43     * @ticket BP6286
     44     * @group member_types
     45     */
     46    public function test_member_directory_with_member_type_should_obey_filtered_type_slug() {
     47        bp_register_member_type( 'foo' );
     48
     49        add_filter( 'bp_members_member_type_base', array( $this, 'filter_member_type_base' ) );
     50        $this->go_to( bp_get_members_directory_permalink() . 'buddypress-member-type/foo/' );
     51        remove_filter( 'bp_members_member_type_base', array( $this, 'filter_member_type_base' ) );
     52        $this->assertTrue( bp_is_members_component() );
     53    }
     54
     55    public function filter_member_type_base( $base ) {
     56        return 'buddypress-member-type';
     57    }
     58
     59    /**
     60     * @ticket BP6286
     61     * @group member_types
     62     */
     63    public function test_member_directory_with_member_type_that_has_custom_directory_slug() {
     64        bp_register_member_type( 'foo', array( 'has_directory' => 'foos' ) );
     65        $this->go_to( bp_get_members_directory_permalink() . 'type/foos/' );
     66        $this->assertTrue( bp_is_members_component() );
     67    }
     68
     69    /**
     70     * @ticket BP6286
     71     * @group member_types
     72     */
     73    public function test_member_directory_with_member_type_should_be_overridden_by_member_with_same_nicename() {
     74        $u = $this->factory->user->create( array( 'user_nicename' => 'foo' ) );
     75        bp_register_member_type( 'foo' );
     76        $this->go_to( bp_get_members_directory_permalink() . 'type/foo/' );
     77    }
     78
     79    /**
     80     * @ticket BP6286
     81     * @group member_types
     82     */
     83    public function test_member_directory_should_404_for_member_types_that_have_no_directory() {
     84        bp_register_member_type( 'foo', array( 'has_directory' => false ) );
     85        $this->go_to( bp_get_members_directory_permalink() . 'type/foo/' );
     86        $this->assertTrue( is_404() );
     87    }
    3088}
Note: See TracChangeset for help on using the changeset viewer.