Ticket #5192: 5192.diff
File 5192.diff, 17.5 KB (added by , 9 years ago) |
---|
-
src/bp-xprofile/bp-xprofile-admin.php
diff --git src/bp-xprofile/bp-xprofile-admin.php src/bp-xprofile/bp-xprofile-admin.php index 55c4b6d..5d93acb 100644
function xprofile_admin_manage_field( $group_id, $field_id = null ) { 361 361 bp_update_option( 'bp-xprofile-fullname-field-name', $field->name ); 362 362 } 363 363 364 // Set member types. 365 if ( isset( $_POST['has-member-types'] ) ) { 366 $member_types = array(); 367 if ( isset( $_POST['member-types'] ) ) { 368 $member_types = stripslashes_deep( $_POST['member-types'] ); 369 } 370 371 $field->set_member_types( $member_types ); 372 } 373 364 374 // Validate default visibility 365 375 if ( ! empty( $_POST['default-visibility'] ) && in_array( $_POST['default-visibility'], wp_list_pluck( bp_xprofile_get_visibility_levels(), 'id' ) ) ) { 366 376 bp_xprofile_update_field_meta( $field_id, 'default_visibility', $_POST['default-visibility'] ); -
src/bp-xprofile/classes/class-bp-xprofile-field.php
diff --git src/bp-xprofile/classes/class-bp-xprofile-field.php src/bp-xprofile/classes/class-bp-xprofile-field.php index 4d08bca..5897461 100644
class BP_XProfile_Field { 124 124 public $data; 125 125 126 126 /** 127 * Member types to which the profile field should be applied. 128 * 129 * @since BuddyPress (2.4.0) 130 * @access protected 131 * @var array Array of member types. 132 */ 133 protected $member_types; 134 135 /** 127 136 * Initialize and/or populate profile field 128 137 * 129 138 * @since BuddyPress (1.1.0) … … class BP_XProfile_Field { 457 466 $wpdb->query( $sql ); 458 467 } 459 468 469 /** 470 * Get the member types to which this field should be available. 471 * 472 * @since BuddyPress (2.4.0) 473 */ 474 public function get_member_types() { 475 if ( ! is_null( $this->member_types ) ) { 476 return $this->member_types; 477 } 478 479 $raw_types = bp_xprofile_get_meta( $this->id, 'field', 'member-type', false ); 480 481 // If `$raw_types` is not an array, it probably means this is a new field (id=0). 482 if ( ! is_array( $raw_types ) ) { 483 $raw_types = array(); 484 } 485 486 // If '_none' is found in the array, it overrides all types. 487 $types = array(); 488 if ( ! in_array( '_none', $raw_types ) ) { 489 $registered_types = bp_get_member_types(); 490 491 // Eliminate invalid member types saved in the database. 492 foreach ( $raw_types as $raw_type ) { 493 // 'none' is a special case - it represents users without a type. 494 if ( 'none' === $raw_type || isset( $registered_types[ $raw_type ] ) ) { 495 $types[] = $raw_type; 496 } 497 } 498 499 // If no member types have been saved, intepret as *all* member types. 500 if ( empty( $types ) ) { 501 $types = array_values( $registered_types ); 502 503 // + the "none" type, ie users without a type. 504 $types[] = 'none'; 505 } 506 } 507 508 /** 509 * Filters the member types to which an XProfile object should be applied. 510 * 511 * @since BuddyPress (2.4.0) 512 * 513 * @param array $types Member types. 514 * @param BP_XProfile_Field $field Field object. 515 */ 516 $this->member_types = apply_filters( 'bp_xprofile_field_member_types', $types, $this ); 517 518 return $this->member_types; 519 } 520 521 /** 522 * Set the member types for this field. 523 * 524 * @since BuddyPress (2.4.0) 525 * 526 * @param array $member_types Array of member types. 527 * @param bool $append Whether to append to existing member types. If false, all existing member type 528 * associations will be deleted before adding your `$member_types`. Default false. 529 * @return array Member types for the current field, after being saved. 530 */ 531 public function set_member_types( $member_types, $append = false ) { 532 // Unset invalid member types. 533 $types = array(); 534 foreach ( $member_types as $member_type ) { 535 // 'none' is a special case - it represents users without a type. 536 if ( 'none' === $member_type || bp_get_member_type_object( $member_type ) ) { 537 $types[] = $member_type; 538 } 539 } 540 541 // When `$append` is false, delete all existing types before adding new ones. 542 if ( ! $append ) { 543 bp_xprofile_delete_meta( $this->id, 'field', 'member-type' ); 544 545 /* 546 * We interpret an empty array as disassociating the field from all types. This is 547 * represented internally with the '_none' flag. 548 */ 549 if ( empty( $types ) ) { 550 bp_xprofile_add_meta( $this->id, 'field', 'member-type', '_none' ); 551 } 552 } 553 554 // "All types" is represented in the database with no meta entries. 555 $registered_types = bp_get_member_types(); 556 $rtypes = array_values( $registered_types ); 557 $rtypes[] = 'none'; 558 559 sort( $types ); 560 sort( $rtypes ); 561 562 if ( $types !== $rtypes ) { 563 // Save new types. 564 foreach ( $types as $type ) { 565 bp_xprofile_add_meta( $this->id, 'field', 'member-type', $type ); 566 } 567 } 568 569 // Reset internal cache of member types. 570 $this->member_types = null; 571 572 // Refetch fresh items from the database. 573 return $this->get_member_types(); 574 } 575 460 576 /** Static Methods ********************************************************/ 461 577 462 578 public static function get_type( $field_id = 0 ) { … … class BP_XProfile_Field { 718 834 // Output the required metabox 719 835 $this->required_metabox(); 720 836 837 // Output the Member Types metabox. 838 $this->member_type_metabox(); 839 721 840 // Output the field visibility metaboxes 722 841 $this->visibility_metabox(); 723 842 … … class BP_XProfile_Field { 864 983 } 865 984 866 985 /** 986 * Private method used to output field Member Type metabox. 987 * 988 * @since BuddyPress (2.4.0) 989 */ 990 private function member_type_metabox() { 991 992 // The primary field is for all, so bail. 993 if ( 1 === (int) $this->id ) { 994 return; 995 } 996 997 // Bail when no member types are registered. 998 if ( ! $member_types = bp_get_member_types( array(), 'objects' ) ) { 999 return; 1000 } 1001 1002 $field_member_types = $this->get_member_types(); 1003 1004 ?> 1005 1006 <div id="for_member_types" class="postbox"> 1007 <h3><?php _e( 'Member Types', 'bp-xprofile-field-for-member-types' ); ?></h3> 1008 <div class="inside"> 1009 <p class="description"><?php _e( 'This field should be available to:', 'bp-xprofile-field-for-member-types' ); ?></p> 1010 1011 <ul> 1012 <?php foreach ( $member_types as $member_type ) : ?> 1013 <li> 1014 <label> 1015 <input name="member-types[]" type="checkbox" value="<?php echo $member_type->name; ?>" <?php checked( in_array( $member_type->name, $field_member_types ) ); ?>/> 1016 <?php echo $member_type->labels['name']; ?> 1017 </label> 1018 </li> 1019 <?php endforeach; ?> 1020 1021 <li> 1022 <label> 1023 <input name="member-types[]" type="checkbox" value="none" <?php checked( in_array( 'none', $field_member_types ) ); ?>/> 1024 <?php _e( 'Users with no member type', 'bp-xprofile-field-for-member-types' ); ?> 1025 </label> 1026 </li> 1027 1028 </ul> 1029 </div> 1030 1031 <input type="hidden" name="has-member-types" value="1" /> 1032 </div> 1033 1034 <?php 1035 } 1036 1037 /** 867 1038 * Private method used to output field visibility metaboxes 868 1039 * 869 1040 * @since BuddyPress (2.3.0) -
src/bp-xprofile/classes/class-bp-xprofile-group.php
diff --git src/bp-xprofile/classes/class-bp-xprofile-group.php src/bp-xprofile/classes/class-bp-xprofile-group.php index f7477f1..9056da9 100644
class BP_XProfile_Group { 333 333 334 334 // Fetch the fields 335 335 $fields = $wpdb->get_results( "SELECT id, name, description, type, group_id, is_required FROM {$bp->profile->table_name_fields} WHERE group_id IN ( {$group_ids_in} ) AND parent_id = 0 {$exclude_fields_sql} ORDER BY field_order" ); 336 337 // Remove fields based on member-type restrictions, if necessary. 338 if ( $r['user_id'] ) { 339 $user_member_types = bp_get_member_type( $r['user_id'], false ); 340 if ( empty( $user_member_types ) ) { 341 $user_member_types = array( 'none' ); 342 } 343 344 foreach ( $fields as $k => $_field ) { 345 $field_obj = new BP_XProfile_Field( $_field->id ); 346 $field_member_types = $field_obj->get_member_types(); 347 $matching_types = array_intersect( $user_member_types, $field_member_types ); 348 if ( empty( $matching_types ) ) { 349 unset( $fields[ $k ] ); 350 } 351 } 352 353 // Reset indexes. 354 $fields = array_values( $fields ); 355 } 356 336 357 $field_ids = wp_list_pluck( $fields, 'id' ); 337 358 338 359 // Store field IDs for meta cache priming -
new file tests/phpunit/testcases/xprofile/BP_XProfile_Field/member_types.php
diff --git tests/phpunit/testcases/xprofile/BP_XProfile_Field/member_types.php tests/phpunit/testcases/xprofile/BP_XProfile_Field/member_types.php new file mode 100644 index 0000000..9039a01
- + 1 <?php 2 3 /** 4 * @group member_types 5 * @group xprofile 6 */ 7 class BP_Tests_XProfile_BpXprofileField_MemberTypes extends BP_UnitTestCase { 8 protected $field_group_id; 9 protected $field_id; 10 protected $field; 11 12 public function setUp() { 13 parent::setUp(); 14 bp_register_member_type( 'foo' ); 15 bp_register_member_type( 'bar' ); 16 17 $this->field_group_id = $this->factory->xprofile_group->create(); 18 $this->field_id = $this->factory->xprofile_field->create( array( 'field_group_id' => $this->field_group_id ) ); 19 $this->field = new BP_XProfile_Field( $this->field_id ); 20 } 21 22 public function tearDown() { 23 buddypress()->members->types = array(); 24 parent::tearDown(); 25 } 26 27 public function test_get_single_member_type() { 28 bp_xprofile_add_meta( $this->field_id, 'field', 'member-type', 'foo' ); 29 $this->assertEqualSets( array( 'foo' ), $this->field->get_member_types() ); 30 } 31 32 public function test_get_multiple_member_types() { 33 bp_xprofile_add_meta( $this->field_id, 'field', 'member-type', 'foo' ); 34 bp_xprofile_add_meta( $this->field_id, 'field', 'member-type', 'bar' ); 35 $this->assertEqualSets( array( 'foo', 'bar' ), $this->field->get_member_types() ); 36 } 37 38 public function test_invalid_member_types_should_not_be_returned() { 39 bp_xprofile_add_meta( $this->field_id, 'field', 'member-type', 'foo' ); 40 bp_xprofile_add_meta( $this->field_id, 'field', 'member-type', 'phony' ); 41 $this->assertEquals( array( 'foo' ), $this->field->get_member_types() ); 42 } 43 44 public function test_when_no_stored_types_are_found_all_registered_member_types_as_well_as_null_type_should_be_returned() { 45 $this->assertEqualSets( array( 'none', 'foo', 'bar' ), $this->field->get_member_types() ); 46 } 47 48 public function test__none_meta_should_result_in_empty_array() { 49 bp_xprofile_add_meta( $this->field_id, 'field', 'member-type', '_none' ); 50 $this->assertEquals( array(), $this->field->get_member_types() ); 51 } 52 53 public function test__none_meta_should_override_other_values() { 54 bp_xprofile_add_meta( $this->field_id, 'field', 'member-type', '_none' ); 55 bp_xprofile_add_meta( $this->field_id, 'field', 'member-type', 'foo' ); 56 $this->assertEquals( array(), $this->field->get_member_types() ); 57 } 58 59 public function test_set_should_not_append_by_default() { 60 bp_xprofile_add_meta( $this->field_id, 'field', 'member-type', 'foo' ); 61 $this->assertEquals( array( 'bar' ), $this->field->set_member_types( array( 'bar' ) ) ); 62 } 63 64 public function test_set_should_not_append_when_append_is_set_to_false() { 65 bp_xprofile_add_meta( $this->field_id, 'field', 'member-type', 'foo' ); 66 $this->assertEquals( array( 'bar' ), $this->field->set_member_types( array( 'bar', false ) ) ); 67 } 68 69 public function test_set_should_append_when_append_is_set_to_true() { 70 bp_xprofile_add_meta( $this->field_id, 'field', 'member-type', 'foo' ); 71 $this->assertEqualSets( array( 'foo', 'bar' ), $this->field->set_member_types( array( 'bar' ), true ) ); 72 } 73 74 public function test_set_empty_array_with_append_true_should_have_no_effect_on_saved_types() { 75 bp_xprofile_add_meta( $this->field_id, 'field', 'member-type', 'foo' ); 76 $this->assertEqualSets( array( 'foo' ), $this->field->set_member_types( array(), true ) ); 77 } 78 79 public function test_set_empty_array_with_append_false_should_result_in_field_being_associated_with_no_member_types() { 80 bp_xprofile_add_meta( $this->field_id, 'field', 'member-type', 'foo' ); 81 $this->assertEqualSets( array(), $this->field->set_member_types( array() ) ); 82 } 83 84 public function test_set_should_interpret_null_flag_properly() { 85 $this->assertEqualSets( array( 'none' ), $this->field->set_member_types( array( 'none' ) ) ); 86 } 87 88 public function test_set_all_types_plus_none_should_result_in_nothing_stored_in_db() { 89 $types = array( 'none', 'foo', 'bar' ); 90 $this->assertEqualSets( $types, $this->field->set_member_types( $types ) ); 91 92 $types_db = bp_xprofile_get_meta( $this->field_id, 'field', 'member-type', false ); 93 $this->assertEqualSets( array(), $types_db ); 94 } 95 } -
tests/phpunit/testcases/xprofile/class-bp-xprofile-group.php
diff --git tests/phpunit/testcases/xprofile/class-bp-xprofile-group.php tests/phpunit/testcases/xprofile/class-bp-xprofile-group.php index 6a0492b..6f736fc 100644
class BP_Tests_BP_XProfile_Group extends BP_UnitTestCase { 113 113 } 114 114 115 115 /** 116 * @group member_types 117 */ 118 public function test_member_type_restrictions_should_be_ignored_when_user_id_is_null() { 119 $g = $this->factory->xprofile_group->create(); 120 $f = $this->factory->xprofile_field->create( array( 'field_group_id' => $g ) ); 121 bp_register_member_type( 'foo' ); 122 123 $field = new BP_XProfile_Field( $f ); 124 $field->set_member_types( array( 'foo' ) ); 125 126 $found_groups = BP_XProfile_Group::get( array( 127 'user_id' => false, 128 'fetch_fields' => true, 129 ) ); 130 131 // The groups aren't indexed, so we have to go looking for it. 132 foreach ( $found_groups as $fg ) { 133 if ( $g == $fg->id ) { 134 $the_group = $fg; 135 } 136 } 137 138 $this->assertContains( $f, wp_list_pluck( $fg->fields, 'id' ) ); 139 } 140 141 /** 142 * @group member_types 143 */ 144 public function test_member_type_restrictions_should_be_ignored_when_user_id_is_0() { 145 $g = $this->factory->xprofile_group->create(); 146 $f = $this->factory->xprofile_field->create( array( 'field_group_id' => $g ) ); 147 bp_register_member_type( 'foo' ); 148 149 $field = new BP_XProfile_Field( $f ); 150 $field->set_member_types( array( 'foo' ) ); 151 152 $found_groups = BP_XProfile_Group::get( array( 153 'user_id' => 0, 154 'fetch_fields' => true, 155 ) ); 156 157 // The groups aren't indexed, so we have to go looking for it. 158 foreach ( $found_groups as $fg ) { 159 if ( $g == $fg->id ) { 160 $the_group = $fg; 161 } 162 } 163 164 $this->assertContains( $f, wp_list_pluck( $fg->fields, 'id' ) ); 165 } 166 167 /** 168 * @group member_types 169 */ 170 public function test_member_type_restrictions_should_be_obeyed_for_nonzero_user_id() { 171 $g = $this->factory->xprofile_group->create(); 172 $f1 = $this->factory->xprofile_field->create( array( 'field_group_id' => $g ) ); 173 $f2 = $this->factory->xprofile_field->create( array( 'field_group_id' => $g ) ); 174 $f3 = $this->factory->xprofile_field->create( array( 'field_group_id' => $g ) ); 175 $f4 = $this->factory->xprofile_field->create( array( 'field_group_id' => $g ) ); 176 bp_register_member_type( 'foo' ); 177 bp_register_member_type( 'bar' ); 178 179 // Field 1 is visible only to 'foo' users. 180 $field1 = new BP_XProfile_Field( $f1 ); 181 $field1->set_member_types( array( 'foo' ) ); 182 183 // Field 2 is visible only to 'bar' users. 184 $field2 = new BP_XProfile_Field( $f2 ); 185 $field2->set_member_types( array( 'bar' ) ); 186 187 // Field 3 is visible to all users (no member type set). 188 189 // Field 4 is visible to no one. 190 $field4 = new BP_XProfile_Field( $f4 ); 191 $field4->set_member_types( array() ); 192 193 // User is in 'foo', so should have f1 and f3 only. 194 $u = $this->factory->user->create(); 195 bp_set_member_type( $u, 'foo' ); 196 197 $found_groups = BP_XProfile_Group::get( array( 198 'user_id' => $u, 199 'fetch_fields' => true, 200 ) ); 201 202 // The groups aren't indexed, so we have to go looking for it. 203 foreach ( $found_groups as $fg ) { 204 if ( $g == $fg->id ) { 205 $the_group = $fg; 206 } 207 } 208 209 $this->assertContains( $f1, wp_list_pluck( $fg->fields, 'id' ) ); 210 $this->assertContains( $f3, wp_list_pluck( $fg->fields, 'id' ) ); 211 $this->assertNotContains( $f2, wp_list_pluck( $fg->fields, 'id' ) ); 212 $this->assertNotContains( $f4, wp_list_pluck( $fg->fields, 'id' ) ); 213 } 214 215 /** 216 * @group member_types 217 */ 218 public function test_member_type_restrictions_should_be_obeyed_for_nonzero_user_id_with_no_member_types() { 219 $g = $this->factory->xprofile_group->create(); 220 $f1 = $this->factory->xprofile_field->create( array( 'field_group_id' => $g ) ); 221 $f2 = $this->factory->xprofile_field->create( array( 'field_group_id' => $g ) ); 222 $f3 = $this->factory->xprofile_field->create( array( 'field_group_id' => $g ) ); 223 bp_register_member_type( 'foo' ); 224 bp_register_member_type( 'bar' ); 225 226 // Field 1 is visible only to 'foo' users. 227 $field1 = new BP_XProfile_Field( $f1 ); 228 $field1->set_member_types( array( 'foo' ) ); 229 230 // Field 2 is visible only to 'none' users. 231 $field2 = new BP_XProfile_Field( $f2 ); 232 $field2->set_member_types( array( 'none' ) ); 233 234 // Field 3 is visible to all users (no member type set). 235 236 // User has no member types, so should see f2 and f3 . 237 $u = $this->factory->user->create(); 238 239 $found_groups = BP_XProfile_Group::get( array( 240 'user_id' => $u, 241 'fetch_fields' => true, 242 ) ); 243 244 // The groups aren't indexed, so we have to go looking for it. 245 foreach ( $found_groups as $fg ) { 246 if ( $g == $fg->id ) { 247 $the_group = $fg; 248 } 249 } 250 251 $this->assertNotContains( $f1, wp_list_pluck( $fg->fields, 'id' ) ); 252 $this->assertContains( $f2, wp_list_pluck( $fg->fields, 'id' ) ); 253 $this->assertContains( $f3, wp_list_pluck( $fg->fields, 'id' ) ); 254 } 255 256 /** 116 257 * @group save_xprofile_group_name 117 258 */ 118 259 public function test_save_xprofile_group_name() {