Skip to:
Content

BuddyPress.org

Changeset 9976


Ignore:
Timestamp:
06/29/2015 02:58:47 PM (10 years ago)
Author:
boonebgorges
Message:

Add 'member_typein' and 'member_typenot_in' support to bp_has_members() stack.

Props lakrisgubben.
Fixes #6418.

Location:
trunk
Files:
4 edited

Legend:

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

    r9819 r9976  
    3939 *                                              IDs only. Default: false.
    4040 *     @type array|string      $member_type     Array or comma-separated list of member types to limit results to.
     41 *     @type array|string      $member_type__in Array or comma-separated list of member types to limit results to.
     42 *     @type array|string      $member_type__not_in Array or comma-separated list of member types that will be
     43 *                                      excluded from results.
    4144 *     @type string|bool       $meta_key        Limit results to users that have usermeta associated with this meta_key.
    4245 *                                              Usually used with $meta_value. Default: false.
     
    167170                'user_ids'        => false,
    168171                'member_type'     => '',
     172                'member_type__in' => '',
     173                'member_type__not_in' => '',
    169174                'meta_key'        => false,
    170175                'meta_value'      => false,
     
    419424        }
    420425
    421         // Member type.
    422         if ( ! empty( $member_type ) ) {
    423             $member_types = array();
    424 
    425             if ( ! is_array( $member_type ) ) {
    426                 $member_type = preg_split( '/[,\s+]/', $member_type );
    427             }
    428 
    429             foreach ( $member_type as $mt ) {
    430                 if ( ! bp_get_member_type_object( $mt ) ) {
    431                     continue;
    432                 }
    433 
    434                 $member_types[] = $mt;
    435             }
    436 
    437             if ( ! empty( $member_types ) ) {
    438                 $member_type_tq = new WP_Tax_Query( array(
    439                     array(
    440                         'taxonomy' => 'bp_member_type',
    441                         'field'    => 'name',
    442                         'operator' => 'IN',
    443                         'terms'    => $member_types,
    444                     ),
    445                 ) );
    446 
    447                 // Switch to the root blog, where member type taxonomies live.
    448                 $switched = false;
    449                 if ( ! bp_is_root_blog() ) {
    450                     switch_to_blog( bp_get_root_blog_id() );
    451                     $switched = true;
    452                 }
    453 
    454                 $member_type_sql_clauses = $member_type_tq->get_sql( 'u', $this->uid_name );
    455 
    456                 if ( $switched ) {
    457                     restore_current_blog();
    458                 }
    459 
    460                 // Grab the first term_relationships clause and convert to a subquery.
    461                 if ( preg_match( '/' . $wpdb->term_relationships . '\.term_taxonomy_id IN \([0-9, ]+\)/', $member_type_sql_clauses['where'], $matches ) ) {
    462                     $sql['where']['member_type'] = "u.{$this->uid_name} IN ( SELECT object_id FROM $wpdb->term_relationships WHERE {$matches[0]} )";
    463                 } elseif ( false !== strpos( $member_type_sql_clauses['where'], '0 = 1' ) ) {
    464                     $sql['where']['member_type'] = $this->no_results['where'];
    465                 }
    466             }
     426        // Only use $member_type__in if $member_type is not set.
     427        if ( empty( $member_type ) && ! empty( $member_type__in ) ) {
     428            $member_type = $member_type__in;
     429        }
     430
     431        // Member types to exclude. Note that this takes precedence over inclusions.
     432        if ( ! empty( $member_type__not_in ) ) {
     433            $member_type_clause = $this->get_sql_clause_for_member_types( $member_type__not_in, 'NOT IN' );
     434
     435        // Member types to include.
     436        } elseif ( ! empty( $member_type ) ) {
     437            $member_type_clause = $this->get_sql_clause_for_member_types( $member_type, 'IN' );
     438        }
     439
     440        if ( ! empty( $member_type_clause ) ) {
     441            $sql['where']['member_type'] = $member_type_clause;
    467442        }
    468443
     
    775750        }
    776751    }
     752
     753    /**
     754     * Get a SQL clause representing member_type include/exclusion.
     755     *
     756     * @since 2.4.0
     757     *
     758     * @param string|array $member_types Array or comma-separated list of member types.
     759     * @param string       $operator     'IN' or 'NOT IN'.
     760     */
     761    protected function get_sql_clause_for_member_types( $member_types, $operator ) {
     762        global $wpdb;
     763
     764        // Sanitize.
     765        if ( 'NOT IN' !== $operator ) {
     766            $operator = 'IN';
     767        }
     768
     769        // Parse and sanitize types.
     770        if ( ! is_array( $member_types ) ) {
     771            $member_types = preg_split( '/[,\s+]/', $member_types );
     772        }
     773
     774        $types = array();
     775        foreach ( $member_types as $mt ) {
     776            if ( bp_get_member_type_object( $mt ) ) {
     777                $types[] = $mt;
     778            }
     779        }
     780
     781        $tax_query = new WP_Tax_Query( array(
     782            array(
     783                'taxonomy' => 'bp_member_type',
     784                'field'    => 'name',
     785                'operator' => $operator,
     786                'terms'    => $types,
     787            ),
     788        ) );
     789
     790        // Switch to the root blog, where member type taxonomies live.
     791        $switched = false;
     792        if ( ! bp_is_root_blog() ) {
     793            switch_to_blog( bp_get_root_blog_id() );
     794            $switched = true;
     795        }
     796
     797        $sql_clauses = $tax_query->get_sql( 'u', $this->uid_name );
     798
     799        if ( $switched ) {
     800            restore_current_blog();
     801        }
     802
     803        $clause = '';
     804
     805        // no_results clauses are the same between IN and NOT IN.
     806        if ( false !== strpos( $sql_clauses['where'], '0 = 1' ) ) {
     807            $clause = $this->no_results['where'];
     808
     809        // The tax_query clause generated for NOT IN can be used almost as-is. We just trim the leading 'AND'.
     810        } elseif ( 'NOT IN' === $operator ) {
     811            $clause = preg_replace( '/^\s*AND\s*/', '', $sql_clauses['where'] );
     812
     813        // IN clauses must be converted to a subquery.
     814        } elseif ( preg_match( '/' . $wpdb->term_relationships . '\.term_taxonomy_id IN \([0-9, ]+\)/', $sql_clauses['where'], $matches ) ) {
     815            $clause = "u.{$this->uid_name} IN ( SELECT object_id FROM $wpdb->term_relationships WHERE {$matches[0]} )";
     816        }
     817
     818        return $clause;
     819    }
    777820}
  • trunk/src/bp-members/bp-members-functions.php

    r9877 r9976  
    8686 *     @type string       $meta_value      Limit to users with a meta_value (with meta_key). Default: false.
    8787 *     @type array|string $member_type     Array or comma-separated string of member types.
     88 *     @type array|string $member_type__in Array or comma-separated string of member types.
     89 *                                         `$member_type` takes precedence over this parameter.
     90 *     @type array|string $member_type__not_in Array or comma-separated string of member types to be excluded.
    8891 *     @type mixed        $include         Limit results by user IDs. Default: false.
    8992 *     @type int          $per_page        Results per page. Default: 20.
     
    105108        'meta_value'      => false,        // With meta_key, limit to users where usermeta matches this value
    106109        'member_type'     => '',
     110        'member_type__in' => '',
     111        'member_type__not_in' => '',
    107112        'include'         => false,        // Pass comma separated list of user_ids to limit to only these users
    108113        'per_page'        => 20,           // The number of results to return per page
  • trunk/src/bp-members/bp-members-template.php

    r9935 r9976  
    319319     *                                      Default: 'upage'.
    320320     * @param array|string $member_type     Array or comma-separated string of member types to limit results to.
    321      */
    322     function __construct( $type, $page_number, $per_page, $max, $user_id, $search_terms, $include, $populate_extras, $exclude, $meta_key, $meta_value, $page_arg = 'upage', $member_type = '' ) {
     321     * @param array|string $member_type__in     Array or comma-separated string of member types to limit results to.
     322     * @param array|string $member_type__not_in     Array or comma-separated string of member types to exclude from results.
     323     */
     324    function __construct( $type, $page_number, $per_page, $max, $user_id, $search_terms, $include, $populate_extras, $exclude, $meta_key, $meta_value, $page_arg = 'upage', $member_type = '', $member_type__in = '', $member_type__not_in = '' ) {
    323325
    324326        $this->pag_arg  = sanitize_key( $page_arg );
     
    330332            $this->members = BP_Core_User::get_users_by_letter( $_REQUEST['letter'], $this->pag_num, $this->pag_page, $populate_extras, $exclude );
    331333        else
    332             $this->members = bp_core_get_users( array( 'type' => $this->type, 'per_page' => $this->pag_num, 'page' => $this->pag_page, 'user_id' => $user_id, 'include' => $include, 'search_terms' => $search_terms, 'populate_extras' => $populate_extras, 'exclude' => $exclude, 'meta_key' => $meta_key, 'meta_value' => $meta_value, 'member_type' => $member_type ) );
     334            $this->members = bp_core_get_users( array( 'type' => $this->type, 'per_page' => $this->pag_num, 'page' => $this->pag_page, 'user_id' => $user_id, 'include' => $include, 'search_terms' => $search_terms, 'populate_extras' => $populate_extras, 'exclude' => $exclude, 'meta_key' => $meta_key, 'meta_value' => $meta_value, 'member_type' => $member_type, 'member_type__in' => $member_type__in, 'member_type__not_in' => $member_type__not_in ) );
    333335
    334336        if ( !$max || $max >= (int) $this->members['total'] )
     
    524526 *                                                  displayed user. Otherwise defaults to 0.
    525527 *     @type string|array          $member_type     Array or comma-separated list of member types to limit results to.
     528 *     @type string|array          $member_type__in     Array or comma-separated list of member types to limit results to.
     529 *     @type string|array          $member_type__not_in     Array or comma-separated list of member types to exclude from results.
    526530 *     @type string                $search_terms    Limit results by a search term. Default: null.
    527531 *     @type string                $meta_key        Limit results by the presence of a usermeta key.
     
    569573        'user_id'         => $user_id, // Pass a user_id to only show friends of this user
    570574        'member_type'     => $member_type,
     575        'member_type__in'     => '',
     576        'member_type__not_in'     => '',
    571577        'search_terms'    => null,     // Pass search_terms to filter users by their profile data
    572578
     
    605611        $r['meta_value'],
    606612        $r['page_arg'],
    607         $r['member_type']
     613        $r['member_type'],
     614        $r['member_type__in'],
     615        $r['member_type__not_in']
    608616    );
    609617
  • trunk/tests/phpunit/testcases/core/class-bp-user-query.php

    r9819 r9976  
    500500
    501501    /**
     502     * @group member_types
     503     */
     504    public function test_member_type__in_single_value() {
     505        bp_register_member_type( 'foo' );
     506        bp_register_member_type( 'bar' );
     507        $users = $this->factory->user->create_many( 3 );
     508        bp_set_member_type( $users[0], 'foo' );
     509        bp_set_member_type( $users[1], 'bar' );
     510
     511        $q = new BP_User_Query( array(
     512            'member_type__in' => 'bar',
     513        ) );
     514
     515        $found = array_values( wp_list_pluck( $q->results, 'ID' ) );
     516        $this->assertEquals( array( $users[1] ), $found );
     517    }
     518
     519    /**
     520     * @group member_types
     521     */
     522    public function test_member_type__in_array_with_single_value() {
     523        bp_register_member_type( 'foo' );
     524        bp_register_member_type( 'bar' );
     525        $users = $this->factory->user->create_many( 3 );
     526        bp_set_member_type( $users[0], 'foo' );
     527        bp_set_member_type( $users[1], 'bar' );
     528
     529        $q = new BP_User_Query( array(
     530            'member_type__in' => array( 'bar' ),
     531        ) );
     532
     533        $found = array_values( wp_list_pluck( $q->results, 'ID' ) );
     534        $this->assertEquals( array( $users[1] ), $found );
     535    }
     536
     537    /**
     538     * @group member_types
     539     */
     540    public function test_member_type__in_comma_separated_values() {
     541        bp_register_member_type( 'foo' );
     542        bp_register_member_type( 'bar' );
     543        $users = $this->factory->user->create_many( 3 );
     544        bp_set_member_type( $users[0], 'foo' );
     545        bp_set_member_type( $users[1], 'bar' );
     546
     547        $q = new BP_User_Query( array(
     548            'member_type__in' => 'foo, bar',
     549        ) );
     550
     551        $found = array_values( wp_list_pluck( $q->results, 'ID' ) );
     552        $this->assertEqualSets( array( $users[0], $users[1] ), $found );
     553    }
     554
     555    /**
     556     * @group member_types
     557     */
     558    public function test_member_type__in_array_with_multiple_values() {
     559        bp_register_member_type( 'foo' );
     560        bp_register_member_type( 'bar' );
     561        $users = $this->factory->user->create_many( 3 );
     562        bp_set_member_type( $users[0], 'foo' );
     563        bp_set_member_type( $users[1], 'bar' );
     564
     565        $q = new BP_User_Query( array(
     566            'member_type__in' => array( 'foo', 'bar' ),
     567        ) );
     568
     569        $found = array_values( wp_list_pluck( $q->results, 'ID' ) );
     570        $this->assertEqualSets( array( $users[0], $users[1] ), $found );
     571    }
     572
     573    /**
     574     * @group member_types
     575     */
     576    public function test_member_type__in_comma_separated_values_should_discard_non_existent_taxonomies() {
     577        bp_register_member_type( 'foo' );
     578        bp_register_member_type( 'bar' );
     579        $users = $this->factory->user->create_many( 3 );
     580        bp_set_member_type( $users[0], 'foo' );
     581        bp_set_member_type( $users[1], 'bar' );
     582
     583        $q = new BP_User_Query( array(
     584            'member_type__in' => 'foo, baz',
     585        ) );
     586
     587        $found = array_values( wp_list_pluck( $q->results, 'ID' ) );
     588        $this->assertEqualSets( array( $users[0] ), $found );
     589    }
     590
     591    /**
     592     * @group member_types
     593     */
     594    public function test_should_return_no_results_when_no_users_match_the_specified_member_type__in() {
     595        bp_register_member_type( 'foo' );
     596        $users = $this->factory->user->create_many( 3 );
     597
     598        $q = new BP_User_Query( array(
     599            'member_type__in' => 'foo, baz',
     600        ) );
     601
     602        $this->assertEmpty( $q->results );
     603    }
     604
     605    /**
     606     * @group member_types
     607     */
     608    public function test_member_type_should_take_precedence_over_member_type__in() {
     609        bp_register_member_type( 'foo' );
     610        bp_register_member_type( 'bar' );
     611        $users = $this->factory->user->create_many( 3 );
     612        bp_set_member_type( $users[0], 'foo' );
     613        bp_set_member_type( $users[1], 'bar' );
     614
     615        $q = new BP_User_Query( array(
     616            'member_type__in' => 'foo',
     617            'member_type' => 'bar'
     618        ) );
     619
     620        $found = array_values( wp_list_pluck( $q->results, 'ID' ) );
     621        $this->assertEqualSets( array( $users[1] ), $found );
     622    }
     623
     624    /**
     625     * @group member_types
     626     */
     627    public function test_member_type__not_in_returns_members_from_other_types_and_members_with_no_types() {
     628        bp_register_member_type( 'foo' );
     629        bp_register_member_type( 'bar' );
     630        $users = $this->factory->user->create_many( 3 );
     631        bp_set_member_type( $users[0], 'foo' );
     632        bp_set_member_type( $users[1], 'bar' );
     633
     634        $q = new BP_User_Query( array(
     635            'member_type__not_in' => 'foo',
     636        ) );
     637
     638        $found = array_values( wp_list_pluck( $q->results, 'ID' ) );
     639        $this->assertEqualSets( array( $users[1], $users[2] ), $found );
     640    }
     641
     642    /**
     643     * @group member_types
     644     */
     645    public function test_should_return_no_results_when_all_users_match_the_specified_member_type__not_in() {
     646        bp_register_member_type( 'foo' );
     647        $users = $this->factory->user->create_many( 3 );
     648        bp_set_member_type( $users[0], 'foo' );
     649        bp_set_member_type( $users[1], 'foo' );
     650        bp_set_member_type( $users[2], 'foo' );
     651
     652        $q = new BP_User_Query( array(
     653            'member_type__not_in' => 'foo',
     654        ) );
     655
     656        $this->assertEmpty( $q->results );
     657    }
     658
     659    /**
     660     * @group member_types
     661     */
     662    public function test_member_type__not_in_takes_precedence_over_member_type() {
     663        bp_register_member_type( 'foo' );
     664        $users = $this->factory->user->create_many( 3 );
     665        bp_set_member_type( $users[0], 'foo' );
     666        bp_set_member_type( $users[1], 'foo' );
     667        bp_set_member_type( $users[2], 'foo' );
     668
     669        $q = new BP_User_Query( array(
     670            'member_type__not_in' => 'foo',
     671            'member_type' => 'foo'
     672        ) );
     673
     674        $this->assertEmpty( $q->results );
     675    }
     676
     677    /**
     678     * @group member_types
     679     */
     680    public function test_member_type__not_in_takes_precedence_over_member_type__in() {
     681        bp_register_member_type( 'foo' );
     682        $users = $this->factory->user->create_many( 3 );
     683        bp_set_member_type( $users[0], 'foo' );
     684        bp_set_member_type( $users[1], 'foo' );
     685        bp_set_member_type( $users[2], 'foo' );
     686
     687        $q = new BP_User_Query( array(
     688            'member_type__not_in' => 'foo',
     689            'member_type__in' => 'foo'
     690        ) );
     691
     692        $this->assertEmpty( $q->results );
     693    }
     694
     695    /**
    502696     * @group cache
    503697     * @group member_types
Note: See TracChangeset for help on using the changeset viewer.