Ticket #6006: 6006.patch
File 6006.patch, 20.5 KB (added by , 9 years ago) |
---|
-
src/bp-core/bp-core-actions.php
diff --git src/bp-core/bp-core-actions.php src/bp-core/bp-core-actions.php index 2bb2334..82d0772 100644
add_action( 'bp_loaded', 'bp_register_theme_directory', 14 ); 65 65 * v---Load order 66 66 */ 67 67 add_action( 'bp_init', 'bp_core_set_uri_globals', 2 ); 68 add_action( 'bp_init', 'bp_register_taxonomies', 3 ); 68 69 add_action( 'bp_init', 'bp_setup_globals', 4 ); 69 70 add_action( 'bp_init', 'bp_setup_canonical_stack', 5 ); 70 71 add_action( 'bp_init', 'bp_setup_nav', 6 ); -
src/bp-core/bp-core-classes.php
diff --git src/bp-core/bp-core-classes.php src/bp-core/bp-core-classes.php index 1244cdf..300daf6 100644
if ( !defined( 'ABSPATH' ) ) exit; 42 42 * IDs corresponding to the users that should be returned. When this 43 43 * parameter is passed, it will override all others; BP User objects 44 44 * will be constructed using these IDs only. Default: false. 45 * @type array|string $member_type Optional. An array or comma-separated 46 * list of member types to match. 45 47 * @type string|bool $meta_key Limit results to users that have usermeta 46 48 * associated with this meta_key. Usually used with $meta_value. 47 49 * Default: false. … … class BP_User_Query { 160 162 'include' => false, 161 163 'exclude' => false, 162 164 'user_ids' => false, 165 'member_type' => '', 163 166 'meta_key' => false, 164 167 'meta_value' => false, 165 168 'populate_extras' => true, … … class BP_User_Query { 390 393 ); 391 394 } 392 395 396 // Member type. 397 if ( ! empty( $member_type ) ) { 398 $member_types = array(); 399 400 if ( ! is_array( $member_type ) ) { 401 $member_type = preg_split( '/[,\s+]/', $member_type ); 402 } 403 404 foreach ( $member_type as $mt ) { 405 if ( ! bp_get_member_type_object( $mt ) ) { 406 continue; 407 } 408 409 $member_types[] = $mt; 410 } 411 412 if ( ! empty( $member_types ) ) { 413 $member_type_tq = new WP_Tax_Query( array( 414 array( 415 'taxonomy' => 'bp_member_type', 416 'field' => 'name', 417 'operator' => 'IN', 418 'terms' => $member_types, 419 ), 420 ) ); 421 422 // Switch to the root blog, where member type taxonomies live. 423 switch_to_blog( bp_get_root_blog_id() ); 424 425 /* 426 * We won't use a JOIN so it doesn't matter what 427 * the primary table name and column are. 428 */ 429 $member_type_sql_clauses = $member_type_tq->get_sql( 'u', 'ID' ); 430 restore_current_blog(); 431 432 433 /* 434 * Grab the first term_relationships clause and 435 * convert to a subquery. 436 */ 437 if ( preg_match( '/' . $wpdb->term_relationships . '\.term_taxonomy_id.*/', $member_type_sql_clauses['where'], $matches ) ) { 438 $sql['where']['member_type'] = "u.{$this->uid_name} IN ( SELECT object_id FROM $wpdb->term_relationships WHERE {$matches[0]} )"; 439 } 440 } 441 } 442 393 443 // 'meta_key', 'meta_value' allow usermeta search 394 444 // To avoid global joins, do a separate query 395 445 if ( false !== $meta_key ) { -
src/bp-core/bp-core-dependency.php
diff --git src/bp-core/bp-core-dependency.php src/bp-core/bp-core-dependency.php index 8ce93a7..3ebb06b 100644
function bp_setup_canonical_stack() { 39 39 } 40 40 41 41 /** 42 * Fire the 'bp_register_taxonomies' action, where plugins should register taxonomies. 43 */ 44 function bp_register_taxonomies() { 45 do_action( 'bp_register_taxonomies' ); 46 } 47 48 /** 42 49 * Fire the 'bp_setup_globals' action, where plugins should initialize global settings. 43 50 */ 44 51 function bp_setup_globals() { -
new file src/bp-core/bp-core-taxonomy.php
diff --git src/bp-core/bp-core-taxonomy.php src/bp-core/bp-core-taxonomy.php new file mode 100644 index 0000000..021849e
- + 1 <?php 2 3 /** 4 * BuddyPress taxonomy functions. 5 * 6 * @since BuddyPress (2.2.0) 7 */ 8 9 /** 10 * Register our default taxonomies. 11 * 12 * @since BuddyPress (2.2.0) 13 */ 14 function bp_register_default_taxonomies() { 15 // Member Type. 16 register_taxonomy( 'bp_member_type', 'user', array( 17 'public' => false, 18 ) ); 19 } 20 add_action( 'bp_register_taxonomies', 'bp_register_default_taxonomies' ); 21 22 /** 23 * Set taxonomy terms on a BuddyPress object. 24 * 25 * @since BuddyPress (2.2.0) 26 * 27 * @see wp_set_object_terms() for a full description of function and parameters. 28 * 29 * @param int $object_id Object ID. 30 * @param string|array Term or terms to set. 31 * @param string $taxonomy Taxonomy name. 32 * @param bool $append Optional. True to append terms to existing terms. 33 * Default: false. 34 * @return array Array of term taxonomy IDs. 35 */ 36 function bp_set_object_terms( $object_id, $terms, $taxonomy, $append = false ) { 37 switch_to_blog( bp_get_root_blog_id() ); 38 $retval = wp_set_object_terms( $object_id, $terms, $taxonomy, $append ); 39 restore_current_blog(); 40 41 return $retval; 42 } 43 44 /** 45 * Get taxonomy terms for a BuddyPress object. 46 * 47 * @since BuddyPress (2.2.0) 48 * 49 * @see wp_get_object_terms() for a full description of function and parameters. 50 * 51 * @param int|array $object_ids ID or IDs of objects. 52 * @param string|array $taxonomies Name or names of taxonomies to match. 53 * @param array $args See {@see wp_get_object_terms()}. 54 * @return array 55 */ 56 function bp_get_object_terms( $object_ids, $taxonomies, $args = array() ) { 57 switch_to_blog( bp_get_root_blog_id() ); 58 $retval = wp_get_object_terms( $object_ids, $taxonomies, $args ); 59 restore_current_blog(); 60 61 return $retval; 62 } -
src/bp-loader.php
diff --git src/bp-loader.php src/bp-loader.php index 41c13e0..ebaf013 100644
class BuddyPress { 432 432 require( $this->plugin_dir . 'bp-core/bp-core-update.php' ); 433 433 require( $this->plugin_dir . 'bp-core/bp-core-options.php' ); 434 434 require( $this->plugin_dir . 'bp-core/bp-core-classes.php' ); 435 require( $this->plugin_dir . 'bp-core/bp-core-taxonomy.php' ); 435 436 require( $this->plugin_dir . 'bp-core/bp-core-filters.php' ); 436 437 require( $this->plugin_dir . 'bp-core/bp-core-avatars.php' ); 437 438 require( $this->plugin_dir . 'bp-core/bp-core-widgets.php' ); -
src/bp-members/bp-members-admin.php
diff --git src/bp-members/bp-members-admin.php src/bp-members/bp-members-admin.php index 8ca63b7..6959c50 100644
class BP_Members_Admin { 186 186 // Add user row actions for single site 187 187 add_filter( 'user_row_actions', array( $this, 'row_actions' ), 10, 2 ); 188 188 189 // Process changes to member type. 190 add_action( 'bp_members_admin_load', array( $this, 'process_member_type_update' ) ); 191 189 192 /** Signups ***********************************************************/ 190 193 191 194 if ( is_admin() ) { … … class BP_Members_Admin { 719 722 sanitize_key( $this->stats_metabox->priority ) 720 723 ); 721 724 725 // Member Type metabox. 726 $member_types = bp_get_member_types(); 727 if ( ! empty( $member_types ) ) { 728 add_meta_box( 729 'bp_members_admin_member_type', 730 _x( 'Member Type', 'members user-admin edit screen', 'buddypress' ), 731 array( $this, 'user_admin_member_type_metabox' ), 732 get_current_screen()->id, 733 'side', 734 'core' 735 ); 736 } 737 722 738 /** 723 739 * Custom metabox ? 724 740 * Plugins can restrict metabox to "bp_moderate" admins checking … … class BP_Members_Admin { 998 1014 } 999 1015 1000 1016 /** 1017 * Render the Member Type metabox. 1018 * 1019 * @access public 1020 * @since BuddyPress (2.2.0) 1021 * 1022 * @param WP_User $user The WP_User object to be edited. 1023 */ 1024 public function user_admin_member_type_metabox( $user = null ) { 1025 1026 // Bail if no user ID. 1027 if ( empty( $user->ID ) ) { 1028 return; 1029 } 1030 1031 $types = bp_get_member_types( array(), 'objects' ); 1032 $current_type = bp_get_member_type( $user->ID ); 1033 1034 ?> 1035 <select name="bp-members-profile-member-type"> 1036 <option value="" <?php selected( '', $current_type ); ?>><?php _ex( ' - ', 'member type null option', 'buddypress' ) ?></option> 1037 <?php foreach ( $types as $type ) : ?> 1038 <option value="<?php echo esc_attr( $type->name ) ?>" <?php selected( $type->name, $current_type ) ?>><?php echo esc_html( $type->labels['singular_name'] ) ?></option> 1039 <?php endforeach; ?> 1040 </select> 1041 1042 <?php 1043 1044 wp_nonce_field( 'bp-member-type-change-' . $user->ID, 'bp-member-type-nonce' ); 1045 } 1046 1047 /** 1048 * Process changes from the Member Type metabox. 1049 * 1050 * @since BuddyPress (2.2.0) 1051 * @access public 1052 */ 1053 public function process_member_type_update() { 1054 if ( ! isset( $_POST['bp-member-type-nonce'] ) || ! isset( $_POST['bp-members-profile-member-type'] ) ) { 1055 return; 1056 } 1057 1058 $user_id = $this->get_user_id(); 1059 1060 check_admin_referer( 'bp-member-type-change-' . $user_id, 'bp-member-type-nonce' ); 1061 1062 /* 1063 * If an invalid member type is passed, someone's doing something 1064 * fishy with the POST request, so we can fail silently. 1065 */ 1066 $member_type = stripslashes( $_POST['bp-members-profile-member-type'] ); 1067 if ( bp_set_member_type( $user_id, $member_type ) ) { 1068 // @todo Success messages can't be posted because other stuff happens on the pageload. 1069 } 1070 1071 } 1072 1073 /** 1001 1074 * Add a link to Profile in Users listing row actions. 1002 1075 * 1003 1076 * @access public -
src/bp-members/bp-members-functions.php
diff --git src/bp-members/bp-members-functions.php src/bp-members/bp-members-functions.php index 2f9b1b3..bd36c77 100644
function bp_live_spammer_login_error() { 2148 2148 add_action( 'login_head', 'wp_shake_js', 12 ); 2149 2149 } 2150 2150 add_action( 'login_form_bp-spam', 'bp_live_spammer_login_error' ); 2151 2152 /** Member Types *************************************************************/ 2153 2154 /** 2155 * Register a member type. 2156 * 2157 * @since BuddyPress (2.2.0) 2158 * 2159 * @param string $member_type 2160 * @param array $args 2161 * @return object|WP_Error 2162 */ 2163 function bp_register_member_type( $member_type, $args = array() ) { 2164 $bp = buddypress(); 2165 2166 if ( isset( $bp->members->types[ $member_type ] ) ) { 2167 return new WP_Error( 'bp_member_type_exists', __( 'Member type already exists.', 'buddypress' ), $member_type ); 2168 } 2169 2170 $r = bp_parse_args( $args, array( 2171 'labels' => array(), 2172 ), 'register_member_type' ); 2173 2174 $type = (object) $r; 2175 2176 // Store the post type name as data in the object (not just as the array key). 2177 $type->name = $member_type; 2178 2179 // Make sure the relevant labels have been filled in. 2180 $default_name = isset( $r['labels']['name'] ) ? $r['labels']['name'] : ucfirst( $type->name ); 2181 $r['labels'] = array_merge( array( 2182 'name' => $default_name, 2183 'singular_name' => $default_name, 2184 ), $r['labels'] ); 2185 2186 $bp->members->types[ $member_type ] = $type; 2187 2188 do_action( 'bp_registered_member_type', $member_type, $type ); 2189 2190 return $type; 2191 } 2192 2193 /** 2194 * Retrieve a member type object by name. 2195 * 2196 * @since BuddyPress (2.2.0) 2197 * 2198 * @param string $post_type The name of the member type. 2199 * @return object A member type object. 2200 */ 2201 function bp_get_member_type_object( $member_type ) { 2202 if ( empty( buddypress()->members->types[ $member_type ] ) ) { 2203 return null; 2204 } 2205 2206 return buddypress()->members->types[ $member_type ]; 2207 } 2208 2209 /** 2210 * Get a list of all registered member type objects. 2211 * 2212 * @since BuddyPres (2.2.0) 2213 * 2214 * @see bp_register_member_type() for accepted arguments. 2215 * 2216 * @param array|string $args Optional. An array of key => value arguments to match against 2217 * the post type objects. Default empty array. 2218 * @param string $output Optional. The type of output to return. Accepts post type 'names' 2219 * or 'objects'. Default 'names'. 2220 * @param string $operator Optional. The logical operation to perform. 'or' means only one 2221 * element from the array needs to match; 'and' means all elements 2222 * must match. Accepts 'or' or 'and'. Default 'and'. 2223 * @return array A list of post type names or objects. 2224 */ 2225 function bp_get_member_types( $args = array(), $output = 'names', $operator = 'and' ) { 2226 $field = 'names' == $output ? 'name' : false; 2227 2228 return wp_filter_object_list( buddypress()->members->types, $args, $operator, $field); 2229 } 2230 2231 /** 2232 * Set type for a member. 2233 * 2234 * @since BuddyPress (2.2.0) 2235 * 2236 * @param int $user_id ID of the user. 2237 * @param string $member_type Member type. 2238 * @param bool $append Optional. True to append this to existing types for user, 2239 * false to replace. Default: false. 2240 */ 2241 function bp_set_member_type( $user_id, $member_type, $append = false ) { 2242 // Pass an empty $member_type to remove a user's type. 2243 if ( ! empty( $member_type ) && ! bp_get_member_type_object( $member_type ) ) { 2244 return false; 2245 } 2246 2247 return bp_set_object_terms( $user_id, $member_type, 'bp_member_type', $append ); 2248 } 2249 2250 /** 2251 * Get type for a member. 2252 * 2253 * @since BuddyPress (2.2.0) 2254 * 2255 * @param int $user_id ID of the user. 2256 * @param bool $single Optional. Whether to return a single type string. If 2257 * multiple types are found for the user, the oldest one will be 2258 * returned. Default: true. 2259 * @return string|array|bool On success, returns a single member type (if 2260 * $single is true) or an array of member types (if $single is false). 2261 * Returns false on failure. 2262 */ 2263 function bp_get_member_type( $user_id, $single = true ) { 2264 $types = bp_get_object_terms( $user_id, 'bp_member_type' ); 2265 2266 $type = false; 2267 if ( ! empty( $types ) ) { 2268 $type = wp_list_pluck( $types, 'name' ); 2269 if ( $single ) { 2270 $type = array_pop( $type ); 2271 } 2272 } 2273 2274 return $type; 2275 } -
src/bp-members/bp-members-loader.php
diff --git src/bp-members/bp-members-loader.php src/bp-members/bp-members-loader.php index 1ab4a64..9b8b56d 100644
11 11 if ( !defined( 'ABSPATH' ) ) exit; 12 12 13 13 class BP_Members_Component extends BP_Component { 14 /** 15 * Member types. 16 * 17 * @see bp_register_member_type() 18 * 19 * @access public 20 * @since BuddyPress (2.2.0) 21 * @var array 22 */ 23 public $types = array(); 14 24 15 25 /** 16 26 * Start the members component creation process. -
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 c9f1371..d30f0fc 100644
class BP_Tests_BP_User_Query_TestCases extends BP_UnitTestCase { 407 407 $this->assertEmpty( $found_user_ids ); 408 408 } 409 409 410 /** 411 * @group member_types 412 */ 413 public function test_member_type_single_value() { 414 bp_register_member_type( 'foo' ); 415 bp_register_member_type( 'bar' ); 416 $users = $this->factory->user->create_many( 3 ); 417 bp_set_member_type( $users[0], 'foo' ); 418 bp_set_member_type( $users[1], 'bar' ); 419 420 $q = new BP_User_Query( array( 421 'member_type' => 'bar', 422 ) ); 423 424 $found = array_values( wp_list_pluck( $q->results, 'ID' ) ); 425 $this->assertEquals( array( $users[1] ), $found ); 426 } 427 428 /** 429 * @group member_types 430 */ 431 public function test_member_type_array_with_single_value() { 432 bp_register_member_type( 'foo' ); 433 bp_register_member_type( 'bar' ); 434 $users = $this->factory->user->create_many( 3 ); 435 bp_set_member_type( $users[0], 'foo' ); 436 bp_set_member_type( $users[1], 'bar' ); 437 438 $q = new BP_User_Query( array( 439 'member_type' => array( 'bar' ), 440 ) ); 441 442 $found = array_values( wp_list_pluck( $q->results, 'ID' ) ); 443 $this->assertEquals( array( $users[1] ), $found ); 444 } 445 446 /** 447 * @group member_types 448 */ 449 public function test_member_type_comma_separated_values() { 450 bp_register_member_type( 'foo' ); 451 bp_register_member_type( 'bar' ); 452 $users = $this->factory->user->create_many( 3 ); 453 bp_set_member_type( $users[0], 'foo' ); 454 bp_set_member_type( $users[1], 'bar' ); 455 456 $q = new BP_User_Query( array( 457 'member_type' => 'foo, bar', 458 ) ); 459 460 $found = array_values( wp_list_pluck( $q->results, 'ID' ) ); 461 $this->assertEqualSets( array( $users[0], $users[1] ), $found ); 462 } 463 464 /** 465 * @group member_types 466 */ 467 public function test_member_type_array_with_multiple_values() { 468 bp_register_member_type( 'foo' ); 469 bp_register_member_type( 'bar' ); 470 $users = $this->factory->user->create_many( 3 ); 471 bp_set_member_type( $users[0], 'foo' ); 472 bp_set_member_type( $users[1], 'bar' ); 473 474 $q = new BP_User_Query( array( 475 'member_type' => array( 'foo', 'bar' ), 476 ) ); 477 478 $found = array_values( wp_list_pluck( $q->results, 'ID' ) ); 479 $this->assertEqualSets( array( $users[0], $users[1] ), $found ); 480 } 481 482 /** 483 * @group member_types 484 */ 485 public function test_member_type_comma_separated_values_should_discard_non_existent_taxonomies() { 486 bp_register_member_type( 'foo' ); 487 bp_register_member_type( 'bar' ); 488 $users = $this->factory->user->create_many( 3 ); 489 bp_set_member_type( $users[0], 'foo' ); 490 bp_set_member_type( $users[1], 'bar' ); 491 492 $q = new BP_User_Query( array( 493 'member_type' => 'foo, baz', 494 ) ); 495 496 $found = array_values( wp_list_pluck( $q->results, 'ID' ) ); 497 $this->assertEqualSets( array( $users[0] ), $found ); 498 } 410 499 } -
new file tests/phpunit/testcases/members/types.php
diff --git tests/phpunit/testcases/members/types.php tests/phpunit/testcases/members/types.php new file mode 100644 index 0000000..2ee071c
- + 1 <?php 2 3 /** 4 * @group members 5 * @group member_types 6 */ 7 class BP_Tests_Members_Types extends BP_UnitTestCase { 8 public function setUp() { 9 parent::setUp(); 10 11 buddypress()->members->types = array(); 12 } 13 14 public function test_bp_register_member_type_should_fail_for_existing_member_type() { 15 bp_register_member_type( 'foo' ); 16 $this->assertWPError( bp_register_member_type( 'foo' ) ); 17 } 18 19 public function test_bp_register_member_type_should_return_type_object() { 20 $this->assertInternalType( 'object', bp_register_member_type( 'foo' ) ); 21 } 22 23 public function test_bp_register_member_type_should_store_member_type_string_as_name_property() { 24 $object = bp_register_member_type( 'foo' ); 25 $this->assertSame( 'foo', $object->name ); 26 } 27 28 public function test_bp_register_member_type_should_fill_in_missing_labels_with_ucfirst_member_type() { 29 $object = bp_register_member_type( 'foo' ); 30 foreach ( $object->labels as $label ) { 31 $this->assertSame( 'Foo', $label ); 32 } 33 } 34 35 public function test_bp_get_member_type_object_should_return_null_for_non_existent_member_type() { 36 $this->assertSame( null, bp_get_member_type_object( 'foo' ) ); 37 } 38 39 public function test_bp_get_member_type_object_should_return_type_object() { 40 bp_register_member_type( 'foo' ); 41 $this->assertInternalType( 'object', bp_get_member_type_object( 'foo' ) ); 42 } 43 44 public function test_bp_set_member_type_should_return_false_for_invalid_member_type() { 45 $this->assertFalse( bp_set_member_type( 'foo', 1 ) ); 46 } 47 48 public function test_bp_set_member_type_should_remove_member_type_when_passing_an_empty_value() { 49 $u = $this->factory->user->create(); 50 bp_register_member_type( 'foo' ); 51 bp_set_member_type( $u, 'foo' ); 52 53 // Make sure it's set up. 54 $this->assertSame( 'foo', bp_get_member_type( $u ) ); 55 56 $this->assertSame( array(), bp_set_member_type( $u, '' ) ); 57 $this->assertFalse( bp_get_member_type( $u ) ); 58 } 59 60 public function test_bp_set_member_type_success() { 61 $u = $this->factory->user->create(); 62 bp_register_member_type( 'foo' ); 63 64 $this->assertNotEmpty( bp_set_member_type( $u, 'foo' ) ); 65 } 66 67 public function test_bp_get_member_type_with_default_value_for_single() { 68 $u = $this->factory->user->create(); 69 bp_register_member_type( 'foo' ); 70 bp_register_member_type( 'bar' ); 71 bp_set_member_type( $u, 'foo' ); 72 bp_set_member_type( $u, 'bar', true ); 73 74 $this->assertSame( 'foo', bp_get_member_type( $u ) ); 75 } 76 77 public function test_bp_get_member_type_with_single_true() { 78 $u = $this->factory->user->create(); 79 bp_register_member_type( 'foo' ); 80 bp_register_member_type( 'bar' ); 81 bp_set_member_type( $u, 'foo' ); 82 bp_set_member_type( $u, 'bar', true ); 83 84 $this->assertSame( 'foo', bp_get_member_type( $u, true ) ); 85 } 86 87 public function test_bp_get_member_type_with_single_false() { 88 $u = $this->factory->user->create(); 89 bp_register_member_type( 'foo' ); 90 bp_register_member_type( 'bar' ); 91 bp_set_member_type( $u, 'foo' ); 92 bp_set_member_type( $u, 'bar', true ); 93 94 $this->assertEqualSets( array( 'foo', 'bar' ), bp_get_member_type( $u, false ) ); 95 } 96 97 public function test_bp_get_member_type_should_return_false_when_no_value_is_found() { 98 $u = $this->factory->user->create(); 99 bp_register_member_type( 'foo' ); 100 101 $this->assertFalse( bp_get_member_type( $u ) ); 102 } 103 }