Skip to:
Content

BuddyPress.org

Ticket #6418: 6418.diff

File 6418.diff, 17.4 KB (added by boonebgorges, 9 years ago)
  • src/bp-core/classes/class-bp-user-query.php

    diff --git src/bp-core/classes/class-bp-user-query.php src/bp-core/classes/class-bp-user-query.php
    index 8739266..b288460 100644
    defined( 'ABSPATH' ) || exit; 
    3838 *                                              override all others; BP User objects will be constructed using these
    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.
    4346 *     @type string|bool       $meta_value      When used with $meta_key, limits results to users whose usermeta value
    class BP_User_Query { 
    166169                                'exclude'         => 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,
    171176                                'xprofile_query'  => false,
    class BP_User_Query { 
    418423                        );
    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                                 }
     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                }
    453430
    454                                 $member_type_sql_clauses = $member_type_tq->get_sql( 'u', $this->uid_name );
     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' );
    455434
    456                                 if ( $switched ) {
    457                                         restore_current_blog();
    458                                 }
     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                }
    459439
    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                         }
     440                if ( ! empty( $member_type_clause ) ) {
     441                        $sql['where']['member_type'] = $member_type_clause;
    467442                }
    468443
    469444                // 'meta_key', 'meta_value' allow usermeta search
    class BP_User_Query { 
    774749                        }
    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}
  • src/bp-members/bp-members-functions.php

    diff --git src/bp-members/bp-members-functions.php src/bp-members/bp-members-functions.php
    index 2f4acc9..596e83b 100644
    add_action( 'bp_setup_globals', 'bp_core_define_slugs', 11 ); 
    8585 *     @type string       $meta_key        Limit to users with a meta_key. Default: false.
    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.
    9093 *     @type int          $page            Page of results. Default: 1.
    function bp_core_get_users( $args = '' ) { 
    104107                'meta_key'        => false,        // Limit to users who have this piece of usermeta
    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
    109114                'page'            => 1,            // The page to return if limiting per page
  • src/bp-members/bp-members-template.php

    diff --git src/bp-members/bp-members-template.php src/bp-members/bp-members-template.php
    index 45bfcf4..8a867d3 100644
    class BP_Core_Members_Template { 
    289289         * @param array        $page_arg        Optional. The string used as a query parameter in pagination links.
    290290         *                                      Default: 'upage'.
    291291         * @param array|string $member_type     Array or comma-separated string of member types to limit results to.
     292         * @param array|string $member_type__in     Array or comma-separated string of member types to limit results to.
     293         * @param array|string $member_type__not_in     Array or comma-separated string of member types to exclude from results.
    292294         */
    293         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 = '' ) {
     295        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 = '' ) {
    294296
    295297                $this->pag_arg  = sanitize_key( $page_arg );
    296298                $this->pag_page = bp_sanitize_pagination_arg( $this->pag_arg, $page_number );
    class BP_Core_Members_Template { 
    300302                if ( !empty( $_REQUEST['letter'] ) )
    301303                        $this->members = BP_Core_User::get_users_by_letter( $_REQUEST['letter'], $this->pag_num, $this->pag_page, $populate_extras, $exclude );
    302304                else
    303                         $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 ) );
     305                        $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 ) );
    304306
    305307                if ( !$max || $max >= (int) $this->members['total'] )
    306308                        $this->total_member_count = (int) $this->members['total'];
    function bp_rewind_members() { 
    494496 *                                                  user. When on a user's Friends page, defaults to the ID of the
    495497 *                                                  displayed user. Otherwise defaults to 0.
    496498 *     @type string|array          $member_type     Array or comma-separated list of member types to limit results to.
     499 *     @type string|array          $member_type__in     Array or comma-separated list of member types to limit results to.
     500 *     @type string|array          $member_type__not_in     Array or comma-separated list of member types to exclude from results.
    497501 *     @type string                $search_terms    Limit results by a search term. Default: null.
    498502 *     @type string                $meta_key        Limit results by the presence of a usermeta key.
    499503 *           Default: false.
    function bp_has_members( $args = '' ) { 
    539543
    540544                'user_id'         => $user_id, // Pass a user_id to only show friends of this user
    541545                'member_type'     => $member_type,
     546                'member_type__in'     => '',
     547                'member_type__not_in'     => '',
    542548                'search_terms'    => null,     // Pass search_terms to filter users by their profile data
    543549
    544550                'meta_key'        => false,        // Only return users with this usermeta
    function bp_has_members( $args = '' ) { 
    575581                $r['meta_key'],
    576582                $r['meta_value'],
    577583                $r['page_arg'],
    578                 $r['member_type']
     584                $r['member_type'],
     585                $r['member_type__in'],
     586                $r['member_type__not_in']
    579587        );
    580588
    581589        /**
  • tests/phpunit/testcases/core/class-bp-user-query.php

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