Skip to:
Content

BuddyPress.org

Changeset 9976


Ignore:
Timestamp:
06/29/2015 02:58:47 PM (11 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.