Skip to:
Content

BuddyPress.org

Ticket #5192: 5192.diff

File 5192.diff, 17.5 KB (added by boonebgorges, 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 ) { 
    361361                                        bp_update_option( 'bp-xprofile-fullname-field-name', $field->name );
    362362                                }
    363363
     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
    364374                                // Validate default visibility
    365375                                if ( ! empty( $_POST['default-visibility'] ) && in_array( $_POST['default-visibility'], wp_list_pluck( bp_xprofile_get_visibility_levels(), 'id' ) ) ) {
    366376                                        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 { 
    124124        public $data;
    125125
    126126        /**
     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        /**
    127136         * Initialize and/or populate profile field
    128137         *
    129138         * @since BuddyPress (1.1.0)
    class BP_XProfile_Field { 
    457466                $wpdb->query( $sql );
    458467        }
    459468
     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
    460576        /** Static Methods ********************************************************/
    461577
    462578        public static function get_type( $field_id = 0 ) {
    class BP_XProfile_Field { 
    718834                                                        // Output the required metabox
    719835                                                        $this->required_metabox();
    720836
     837                                                        // Output the Member Types metabox.
     838                                                        $this->member_type_metabox();
     839
    721840                                                        // Output the field visibility metaboxes
    722841                                                        $this->visibility_metabox();
    723842
    class BP_XProfile_Field { 
    864983        }
    865984
    866985        /**
     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        /**
    8671038         * Private method used to output field visibility metaboxes
    8681039         *
    8691040         * @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 { 
    333333
    334334                // Fetch the fields
    335335                $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
    336357                $field_ids = wp_list_pluck( $fields, 'id' );
    337358
    338359                // 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 */
     7class 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 { 
    113113        }
    114114
    115115        /**
     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        /**
    116257         * @group save_xprofile_group_name
    117258         */
    118259        public function test_save_xprofile_group_name() {