Skip to:
Content

BuddyPress.org

Ticket #7162: 7162.2.patch

File 7162.2.patch, 50.4 KB (added by imath, 7 months ago)
  • src/bp-xprofile/admin/js/admin.js

    diff --git src/bp-xprofile/admin/js/admin.js src/bp-xprofile/admin/js/admin.js
    index f4f522489..708189630 100644
    function show_options( forWhat ) { 
    9595                jQuery( '#do-autolink' ).val( do_autolink );
    9696        }
    9797
     98        // Show/hides metaboxes according to selected field type supports.
     99        jQuery( '#field-type-visibiliy-metabox, #field-type-required-metabox, #field-type-autolink-metabox' ).show();
     100        if ( -1 !== XProfileAdmin.hide_required_metabox.indexOf( forWhat ) ) {
     101                jQuery( '#field-type-required-metabox' ).hide();
     102        }
     103
     104        if ( -1 !== XProfileAdmin.hide_allow_custom_visibility_metabox.indexOf( forWhat ) ) {
     105                jQuery( '#field-type-visibiliy-metabox' ).hide();
     106        }
     107
     108        if ( -1 !== XProfileAdmin.hide_do_autolink_metabox.indexOf( forWhat ) ) {
     109                jQuery( '#field-type-autolink-metabox' ).hide();
     110        }
     111
    98112        jQuery( document ).trigger( 'bp-xprofile-show-options', forWhat );
    99113}
    100114
    function titleHint( id ) { 
    173187
    174188        titleprompt.on( 'click', function(){
    175189                jQuery(this).addClass('screen-reader-text');
    176                 title.focus();
     190                title.trigger( 'focus' );
    177191        });
    178192
    179193        title.on( 'blur', function(){
    function titleHint( id ) { 
    184198                titleprompt.addClass('screen-reader-text');
    185199        }).on( 'keydown', function(e){
    186200                titleprompt.addClass('screen-reader-text');
    187                 jQuery(this).unbind(e);
     201                jQuery(this).off( e );
    188202        });
    189203}
    190204
    191 jQuery( document ).ready( function() {
     205jQuery( function() {
    192206
    193207        // Set focus in Field Title, if we're on the right page.
    194208        jQuery( '#bp-xprofile-add-field #title' ).trigger( 'focus' );
  • src/bp-xprofile/bp-xprofile-admin.php

    diff --git src/bp-xprofile/bp-xprofile-admin.php src/bp-xprofile/bp-xprofile-admin.php
    index a81793949..5bd8a899d 100644
    function xprofile_admin_manage_field( $group_id, $field_id = null ) { 
    493493                        $field->type        = $_POST['fieldtype'];
    494494                        $field->name        = $_POST['title'];
    495495
     496                        /*
     497                         * By default a Textbox field is created. To run field type's feature
     498                         * checks we need to set it to what it really is early.
     499                         */
     500                        if ( is_null( $field_id ) ) {
     501                                $field_type = bp_xprofile_create_field_type( $field->type );
     502
     503                                // If it's a placeholder, then the field type is not registered.
     504                                if ( ! $field_type instanceof BP_XProfile_Field_Type_Placeholder ) {
     505                                        $field->type_obj = $field_type;
     506                                }
     507                        }
     508
     509                        if ( ! $field->field_type_supports( 'required' ) ) {
     510                                $field->is_required = "0";
     511                        }
     512
    496513                        if ( ! empty( $_POST['description'] ) ) {
    497514                                $field->description = $_POST['description'];
    498515                        } else {
    function xprofile_admin_manage_field( $group_id, $field_id = null ) { 
    537554
    538555                                // Validate default visibility.
    539556                                if ( ! empty( $_POST['default-visibility'] ) && in_array( $_POST['default-visibility'], wp_list_pluck( bp_xprofile_get_visibility_levels(), 'id' ) ) ) {
    540                                         bp_xprofile_update_field_meta( $field_id, 'default_visibility', $_POST['default-visibility'] );
     557                                        $default_visibility = $_POST['default-visibility'];
     558
     559                                        if ( ! $field->field_type_supports( 'allow_custom_visibility' ) ) {
     560                                                $default_visibility = 'public';
     561                                        }
     562
     563                                        bp_xprofile_update_field_meta( $field_id, 'default_visibility', $default_visibility );
    541564                                }
    542565
    543566                                // Validate custom visibility.
    544567                                if ( ! empty( $_POST['allow-custom-visibility'] ) && in_array( $_POST['allow-custom-visibility'], array( 'allowed', 'disabled' ) ) ) {
    545                                         bp_xprofile_update_field_meta( $field_id, 'allow_custom_visibility', $_POST['allow-custom-visibility'] );
     568                                        $allow_custom_visibility = $_POST['allow-custom-visibility'];
     569
     570                                        if ( ! $field->field_type_supports( 'allow_custom_visibility' ) ) {
     571                                                $allow_custom_visibility = 'disabled';
     572                                        }
     573
     574                                        bp_xprofile_update_field_meta( $field_id, 'allow_custom_visibility', $allow_custom_visibility );
    546575                                }
    547576
    548577                                // Validate signup.
    function xprofile_admin_manage_field( $group_id, $field_id = null ) { 
    552581                                        bp_xprofile_delete_meta( $field_id, 'field', 'signup_position' );
    553582                                }
    554583
     584                                $do_autolink = '';
     585                                if ( $field->field_type_supports( 'do_autolink' ) && isset( $_POST['do_autolink'] ) && $_POST['do_autolink'] ) {
     586                                        $do_autolink = wp_unslash( $_POST['do_autolink'] );
     587                                }
     588
    555589                                // Save autolink settings.
    556                                 if ( isset( $_POST['do_autolink'] ) && 'on' === wp_unslash( $_POST['do_autolink'] ) ) {
     590                                if ( 'on' === $do_autolink ) {
    557591                                        bp_xprofile_update_field_meta( $field_id, 'do_autolink', 'on' );
    558592                                } else {
    559593                                        bp_xprofile_update_field_meta( $field_id, 'do_autolink', 'off' );
  • src/bp-xprofile/bp-xprofile-cache.php

    diff --git src/bp-xprofile/bp-xprofile-cache.php src/bp-xprofile/bp-xprofile-cache.php
    index 57a48aa8b..5c5badae5 100644
    add_action( 'xprofile_field_after_save', 'bp_xprofile_reset_groups_cache_increme 
    302302
    303303// List actions to clear super cached pages on, if super cache is installed.
    304304add_action( 'xprofile_updated_profile', 'bp_core_clear_cache' );
     305
     306/**
     307 * Resets the User Metadata ids cache.
     308 *
     309 * @since 8.0.0
     310 *
     311 * @param integer $user_id The user ID.
     312 */
     313function bp_xprofile_reset_user_mid_cache( $user_id ) {
     314        wp_cache_delete( $user_id, 'bp_user_mid' );
     315}
     316add_action( 'profile_update', 'bp_xprofile_reset_user_mid_cache', 10, 1 );
  • src/bp-xprofile/bp-xprofile-cssjs.php

    diff --git src/bp-xprofile/bp-xprofile-cssjs.php src/bp-xprofile/bp-xprofile-cssjs.php
    index dd44fb6ce..1b6982f7f 100644
    function xprofile_add_admin_js() { 
    5151                // types that support options, for use in showing/hiding the
    5252                // "please enter options for this field" section.
    5353                $strings = array(
    54                         'do_settings_section_field_types' => array(),
    55                         'do_autolink'                     => '',
    56                         'text'                            => array(
     54                        'do_settings_section_field_types'      => array(),
     55                        'do_autolink'                          => '',
     56                        'hide_do_autolink_metabox'             => array(),
     57                        'hide_allow_custom_visibility_metabox' => array(),
     58                        'hide_required_metabox'                => array(),
     59                        'text'                                 => array(
    5760                                'defaultValue' => __( 'Default Value', 'buddypress' ),
    5861                                'deleteLabel'  => __( 'Delete', 'buddypress' ),
    5962                        ),
    function xprofile_add_admin_js() { 
    6467                        if ( $field->do_settings_section() ) {
    6568                                $strings['do_settings_section_field_types'][] = $field_type;
    6669                        }
     70
     71                        if ( isset( $field::$supported_features ) && is_array( $field::$supported_features ) ) {
     72                                foreach ( $field::$supported_features as $feature => $support ) {
     73                                        if ( isset( $strings['hide_' . $feature . '_metabox'] ) && ! $support ) {
     74                                                $strings['hide_' . $feature . '_metabox'][] = $field_type;
     75                                        }
     76                                }
     77                        }
    6778                }
    6879
    6980                // Load 'autolink' setting into JS so that we can provide smart defaults when switching field type.
  • src/bp-xprofile/bp-xprofile-filters.php

    diff --git src/bp-xprofile/bp-xprofile-filters.php src/bp-xprofile/bp-xprofile-filters.php
    index 66e2780c8..7a2fc06be 100644
    function xprofile_filter_pre_validate_value_by_field_type( $value, $field, $fiel 
    352352 * @return string
    353353 */
    354354function bp_xprofile_escape_field_data( $value, $field_type, $field_id ) {
     355        // Sanitization for these types is directly done into their `display_filter()` method.
     356        if ( 'wp-biography' === $field_type || 'wp-textbox' === $field_type ) {
     357                return $value;
     358        }
     359
    355360        if ( bp_xprofile_is_richtext_enabled_for_field( $field_id ) ) {
    356361                // The xprofile_filter_kses() expects a BP_XProfile_ProfileData object.
    357362                $data_obj = null;
  • src/bp-xprofile/bp-xprofile-functions.php

    diff --git src/bp-xprofile/bp-xprofile-functions.php src/bp-xprofile/bp-xprofile-functions.php
    index 060b2ff61..7ba336414 100644
    function bp_xprofile_get_field_types() { 
    159159                'textarea'       => 'BP_XProfile_Field_Type_Textarea',
    160160                'textbox'        => 'BP_XProfile_Field_Type_Textbox',
    161161                'telephone'      => 'BP_XProfile_Field_Type_Telephone',
     162                'wp-biography'   => 'BP_XProfile_Field_Type_WordPress_Biography',
     163                'wp-textbox'     => 'BP_XProfile_Field_Type_WordPress_Textbox',
    162164        );
    163165
    164166        /**
    function xprofile_set_field_data( $field, $user_id, $value, $is_required = false 
    462464                return false;
    463465        }
    464466
    465         $field           = new BP_XProfile_ProfileData();
    466         $field->field_id = $field_id;
    467         $field->user_id  = $user_id;
     467        $field_args = compact( 'field_type_obj', 'field', 'user_id', 'value', 'is_required' );
    468468
    469         // Gets un/reserialized via xprofile_sanitize_data_value_before_save().
    470         $field->value    = maybe_serialize( $value );
     469        /**
     470         * Return a WP_Error object or true to use your custom way of saving field values.
     471         *
     472         * @since 8.0.0
     473         *
     474         * @param boolean Whether to shortcircuit the $bp->profile->table_name_data table.
     475         * @param array $field_args {
     476         *     An array of arguments.
     477         *
     478         *     @type object            $field_type_obj Field type object.
     479         *     @type BP_XProfile_Field $field          Field object.
     480         *     @type integer           $user_id        The user ID.
     481         *     @type mixed             $value          Value passed to xprofile_set_field_data().
     482         *     @type boolean           $is_required    Whether or not the field is required.
     483         * }
     484         */
     485        $retval = apply_filters( 'bp_xprofile_set_field_data_pre_save', false, $field_args );
    471486
    472         return $field->save();
     487        if ( is_wp_error( $retval ) ) {
     488                return false;
     489        }
     490
     491        if ( false === $retval ) {
     492                $field           = new BP_XProfile_ProfileData();
     493                $field->field_id = $field_id;
     494                $field->user_id  = $user_id;
     495
     496                // Gets un/reserialized via xprofile_sanitize_data_value_before_save().
     497                $field->value    = maybe_serialize( $value );
     498
     499                $retval = $field->save();
     500        }
     501
     502        return $retval;
    473503}
    474504
    475505/**
    function bp_xprofile_personal_data_exporter( $email_address ) { 
    13571387                'done' => true,
    13581388        );
    13591389}
     1390
     1391/**
     1392 * Returns the list of supporterd WordPress field meta keys.
     1393 *
     1394 * @since 8.0.0
     1395 *
     1396 * @return string[] List of supported WordPress user keys.
     1397 */
     1398function bp_xprofile_get_wp_user_keys() {
     1399        return array_merge(
     1400                array( 'first_name', 'last_name', 'user_url', 'description' ),
     1401                array_keys( wp_get_user_contact_methods() )
     1402        );
     1403}
  • src/bp-xprofile/bp-xprofile-template.php

    diff --git src/bp-xprofile/bp-xprofile-template.php src/bp-xprofile/bp-xprofile-template.php
    index 5ef8f9f72..10b5188c9 100644
    defined( 'ABSPATH' ) || exit; 
    1414 * Query for XProfile groups and fields.
    1515 *
    1616 * @since 1.0.0
     17 * @since 2.4.0 Introduced `$member_type` argument.
     18 * @since 8.0.0 Introduced `$hide_field_types` argument.
    1719 *
    1820 * @global object $profile_template
    1921 * @see BP_XProfile_Group::get() for full description of `$args` array.
    defined( 'ABSPATH' ) || exit; 
    3133 *     @type bool         $fetch_field_data       Default: true.
    3234 *     @type bool         $fetch_visibility_level Defaults to true when an admin is viewing a profile, or when a user is
    3335 *                                                viewing her own profile, or during registration. Otherwise false.
    34  *     @type int|bool     $exclude_groups         Default: false.
    35  *     @type int|bool     $exclude_fields         Default: false
     36 *     @type int[]|bool   $exclude_groups         Default: false.
     37 *     @type int[]|bool   $exclude_fields         Default: false.
     38 *     @type string[]     $hide_field_types       Default: empty array.
    3639 *     @type bool         $update_meta_cache      Default: true.
    3740 * }
    3841 *
    function bp_has_profile( $args = '' ) { 
    6467                'fetch_visibility_level' => $fetch_visibility_level_default,
    6568                'exclude_groups'         => false, // Comma-separated list of profile field group IDs to exclude.
    6669                'exclude_fields'         => false, // Comma-separated list of profile field IDs to exclude.
     70                'hide_field_types'       => array(), // List of field types to hide from profile fields loop.
    6771                'update_meta_cache'      => true,
    6872        ), 'has_profile' );
    6973
  • src/bp-xprofile/classes/class-bp-xprofile-component.php

    diff --git src/bp-xprofile/classes/class-bp-xprofile-component.php src/bp-xprofile/classes/class-bp-xprofile-component.php
    index 8350c9ab6..2976fdf5a 100644
    class BP_XProfile_Component extends BP_Component { 
    410410                        'bp_xprofile_data',
    411411                        'bp_xprofile_fields',
    412412                        'bp_xprofile_groups',
    413                         'xprofile_meta'
     413                        'xprofile_meta',
     414                        'bp_user_mid',
    414415                ) );
    415416
    416417                parent::setup_cache_groups();
  • src/bp-xprofile/classes/class-bp-xprofile-data-template.php

    diff --git src/bp-xprofile/classes/class-bp-xprofile-data-template.php src/bp-xprofile/classes/class-bp-xprofile-data-template.php
    index 8f81db54d..8aa3a4909 100644
    class BP_XProfile_Data_Template { 
    105105         *
    106106         * @since 1.5.0
    107107         * @since 2.4.0 Introduced `$member_type` argument.
     108         * @since 8.0.0 Introduced `$hide_field_types` argument.
    108109         *
    109110         * @param array|string $args {
    110111         *     An array of arguments. All items are optional.
    class BP_XProfile_Data_Template { 
    120121         *     @type int|bool     $hide_empty_fields       Should empty fields be skipped.
    121122         *     @type int|bool     $fetch_visibility_level  Fetch visibility levels.
    122123         *     @type int|bool     $update_meta_cache       Should metadata cache be updated.
     124         *     @type string[]     $hide_field_types        List of field types to hide form loop. Default: empty array.
    123125         * }
    124126         */
    125127        public function __construct( $args = '' ) {
    class BP_XProfile_Data_Template { 
    156158                        'fetch_visibility_level' => false,
    157159                        'exclude_groups'         => false,
    158160                        'exclude_fields'         => false,
     161                        'hide_field_types'       => array(),
    159162                        'update_meta_cache'      => true
    160163                ) );
    161164
  • new file src/bp-xprofile/classes/class-bp-xprofile-field-type-wordpress-biography.php

    diff --git src/bp-xprofile/classes/class-bp-xprofile-field-type-wordpress-biography.php src/bp-xprofile/classes/class-bp-xprofile-field-type-wordpress-biography.php
    new file mode 100644
    index 000000000..f8e14d6c5
    - +  
     1<?php
     2/**
     3 * BuddyPress XProfile Classes.
     4 *
     5 * @package BuddyPress
     6 * @subpackage XProfileClasses
     7 * @since 8.0.0
     8 */
     9
     10// Exit if accessed directly.
     11defined( 'ABSPATH' ) || exit;
     12
     13/**
     14 * WordPress Biography xProfile field type.
     15 *
     16 * @since 8.0.0
     17 */
     18class BP_XProfile_Field_Type_WordPress_Biography extends BP_XProfile_Field_Type_WordPress {
     19
     20        /**
     21         * Constructor for the WordPress biography field type.
     22         *
     23         * @since 8.0.0
     24         */
     25        public function __construct() {
     26                parent::__construct();
     27
     28                $this->category           = _x( 'WordPress Fields', 'xprofile field type category', 'buddypress' );
     29                $this->name               = _x( 'Biography', 'xprofile field type', 'buddypress' );
     30                $this->accepts_null_value = true;
     31                $this->wp_user_key        = 'description';
     32
     33                $this->set_format( '/^.*$/m', 'replace' );
     34
     35                /**
     36                 * Fires inside __construct() method for BP_XProfile_Field_Type_WordPress_Biography class.
     37                 *
     38                 * @since 8.0.0
     39                 *
     40                 * @param BP_XProfile_Field_Type_WordPress_Biography $this Instance of the field type object.
     41                 */
     42                do_action( 'bp_xprofile_field_type_wordpress_biography', $this );
     43        }
     44
     45        /**
     46         * Sanitize the user field before saving it to db.
     47         *
     48         * @since 8.0.0
     49         *
     50         * @param string $value The user field value.
     51         * @return string The sanitized field value.
     52         */
     53        public function sanitize_for_db( $value ) {
     54                return trim( $value );
     55        }
     56
     57        /**
     58         * Sanitize the user field before displaying it as an attribute.
     59         *
     60         * @since 8.0.0
     61         *
     62         * @param string $value The user field value.
     63         * @param integer $user_id The user ID.
     64         * @return string The sanitized field value.
     65         */
     66        public function sanitize_for_output( $value, $user_id = 0 ) {
     67                if ( ! $user_id ) {
     68                        $user_id = bp_displayed_user_id();
     69                }
     70
     71                return sanitize_user_field( $this->wp_user_key, $value, $user_id, 'attribute' );
     72        }
     73
     74        /**
     75         * Output the edit field HTML for this field type.
     76         *
     77         * Must be used inside the {@link bp_profile_fields()} template loop.
     78         *
     79         * @since 8.0.0
     80         *
     81         * @param array $raw_properties Optional key/value array of
     82         *                              {@link http://dev.w3.org/html5/markup/textarea.html permitted attributes}
     83         *                              that you want to add.
     84         */
     85        public function edit_field_html( array $raw_properties = array() ) {
     86                /*
     87                 * User_id is a special optional parameter that certain other fields
     88                 * types pass to {@link bp_the_profile_field_options()}.
     89                 */
     90                if ( ! is_admin() && isset( $raw_properties['user_id'] ) ) {
     91                        unset( $raw_properties['user_id'] );
     92                }
     93
     94                $user_id = bp_displayed_user_id();
     95                if ( isset( $raw_properties['user_id'] ) && $raw_properties['user_id'] ) {
     96                        $user_id = (int) $raw_properties['user_id'];
     97                        unset( $raw_properties['user_id'] );
     98                }
     99                ?>
     100
     101                <label for="<?php bp_the_profile_field_input_name(); ?>">
     102                        <?php bp_the_profile_field_name(); ?>
     103                        <?php bp_the_profile_field_required_label(); ?>
     104                </label>
     105
     106                <?php
     107                /** This action is documented in bp-xprofile/bp-xprofile-classes */
     108                do_action( bp_get_the_profile_field_errors_action() );
     109
     110                $r = wp_parse_args( $raw_properties, array(
     111                        'cols' => 40,
     112                        'rows' => 5,
     113                ) );
     114                ?>
     115
     116                <textarea <?php echo $this->get_edit_field_html_elements( $r ); ?>><?php
     117                        echo $this->sanitize_for_output( bp_get_user_meta( $user_id, $this->wp_user_key, true ), $user_id );
     118                ?></textarea>
     119
     120                <?php
     121        }
     122
     123        /**
     124         * Output HTML for this field type on the wp-admin Profile Fields screen.
     125         *
     126         * Must be used inside the {@link bp_profile_fields()} template loop.
     127         *
     128         * @since 8.0.0
     129         *
     130         * @param array $raw_properties Optional key/value array of permitted attributes that you want to add.
     131         */
     132        public function admin_field_html( array $raw_properties = array() ) {
     133                $r = bp_parse_args( $raw_properties, array(
     134                        'cols' => 40,
     135                        'rows' => 5,
     136                ) ); ?>
     137
     138                <textarea <?php echo $this->get_edit_field_html_elements( $r ); ?>></textarea>
     139
     140                <?php
     141        }
     142
     143        /**
     144         * This method usually outputs HTML for this field type's children options on the wp-admin Profile Fields
     145         * "Add Field" and "Edit Field" screens, but for this field type, we don't want it, so it's stubbed out.
     146         *
     147         * @since 8.0.0
     148         *
     149         * @param BP_XProfile_Field $current_field The current profile field on the add/edit screen.
     150         * @param string            $control_type  Optional. HTML input type used to render the
     151         *                                         current field's child options.
     152         */
     153        public function admin_new_field_html( BP_XProfile_Field $current_field, $control_type = '' ) {}
     154
     155        /**
     156         * Format WordPress Biography for display.
     157         *
     158         * @since 8.0.0
     159         *
     160         * @param string     $field_value The field value, as saved in the database.
     161         * @param string|int $field_id    Optional. ID of the field.
     162         * @return string The sanitized WordPress field.
     163         */
     164        public static function display_filter( $field_value, $field_id = '' ) {
     165                return sanitize_user_field( 'description', $field_value, bp_displayed_user_id(), 'display' );
     166        }
     167}
  • new file src/bp-xprofile/classes/class-bp-xprofile-field-type-wordpress-textbox.php

    diff --git src/bp-xprofile/classes/class-bp-xprofile-field-type-wordpress-textbox.php src/bp-xprofile/classes/class-bp-xprofile-field-type-wordpress-textbox.php
    new file mode 100644
    index 000000000..c47f27cdd
    - +  
     1<?php
     2/**
     3 * BuddyPress XProfile Classes.
     4 *
     5 * @package BuddyPress
     6 * @subpackage XProfileClasses
     7 * @since 8.0.0
     8 */
     9
     10// Exit if accessed directly.
     11defined( 'ABSPATH' ) || exit;
     12
     13/**
     14 * WordPress xProfile regular field type.
     15 *
     16 * @since 8.0.0
     17 */
     18class BP_XProfile_Field_Type_WordPress_Textbox extends BP_XProfile_Field_Type_WordPress {
     19
     20        /**
     21         * Constructor for the WordPress regular field type.
     22         *
     23         * @since 8.0.0
     24         */
     25        public function __construct() {
     26                parent::__construct();
     27
     28                $this->category            = _x( 'WordPress Fields', 'xprofile field type category', 'buddypress' );
     29                $this->name                = _x( 'Text field', 'xprofile field type', 'buddypress' );
     30                $this->accepts_null_value  = true;
     31                $this->do_settings_section = true;
     32
     33                $this->wp_user_key = '';
     34                if ( isset( $this->field_obj->id ) ) {
     35                        $this->wp_user_key = self::get_field_settings( $this->field_obj->id );
     36                }
     37
     38                $this->set_format( '/^.*$/', 'replace' );
     39
     40                /**
     41                 * Fires inside __construct() method for BP_XProfile_Field_Type_WordPress_Textbox class.
     42                 *
     43                 * @since 8.0.0
     44                 *
     45                 * @param BP_XProfile_Field_Type_WordPress_Textbox $this Instance of the field type object.
     46                 */
     47                do_action( 'bp_xprofile_field_type_wordpress_textbox', $this );
     48
     49                /*
     50                 * As we are using an xProfile field meta to store the WordPress field meta key we need to make
     51                 * sure $this->wp_user_key is set before trying to save a field.
     52                 */
     53                add_filter( 'bp_xprofile_set_field_data_pre_validate', array( $this, 'set_wp_user_key' ), 10, 2 );
     54        }
     55
     56        /**
     57         * Gets the WordPress field value during an xProfile fields loop.
     58         *
     59         * This function is used inside `BP_XProfile_ProfileData::get_data_for_user()`
     60         * to include the WordPress field value into the xProfile fields loop.
     61         *
     62         * @since 8.0.0
     63         *
     64         * @param integer $user_id The user ID.
     65         * @param integer $field_id The xProfile field ID.
     66         * @return array An array containing the metadata `id`, `value` and `table_name`.
     67         */
     68        public function get_field_value( $user_id, $field_id = 0 ) {
     69                if ( ! $this->wp_user_key ) {
     70                        $this->wp_user_key = self::get_field_settings( $field_id );
     71                }
     72
     73                return parent::get_field_value( $user_id, $field_id );
     74        }
     75
     76        /**
     77         * Sets the WordPress field wp_user_key property before saving the xProfile field.
     78         *
     79         * @since 8.0.0
     80         *
     81         * @param mixed                  $value Value passed to xprofile_set_field_data().
     82         * @param BP_XProfile_Field      $field Field object.
     83         * @return mixed Unchanged value.
     84         */
     85        public function set_wp_user_key( $value, $field ) {
     86                if ( ! $this->wp_user_key && 'wp-textbox' === $field->type ) {
     87                        $this->wp_user_key = self::get_field_settings( $field->id );
     88                }
     89
     90                return $value;
     91        }
     92
     93        /**
     94         * Sanitize the user field before saving it to db.
     95         *
     96         * @since 8.0.0
     97         *
     98         * @param string $value The user field value.
     99         * @return string The sanitized field value.
     100         */
     101        public function sanitize_for_db( $value ) {
     102                if ( 'user_url' === $this->wp_user_key ) {
     103                        return esc_url_raw( $value );
     104                }
     105
     106                return sanitize_text_field( $value );
     107        }
     108
     109        /**
     110         * Sanitize the user field before displaying it as an attribute.
     111         *
     112         * @since 8.0.0
     113         *
     114         * @param string $value The user field value.
     115         * @return string The sanitized field value.
     116         */
     117        public function sanitize_for_output( $value, $user_id = 0 ) {
     118                if ( ! $user_id ) {
     119                        $user_id = bp_displayed_user_id();
     120                }
     121
     122                return sanitize_user_field( $this->wp_user_key, $value, $user_id, 'attribute' );
     123        }
     124
     125        /**
     126         * Output the edit field HTML for this field type.
     127         *
     128         * Must be used inside the {@link bp_profile_fields()} template loop.
     129         *
     130         * @since 8.0.0
     131         *
     132         * @param array $raw_properties Optional key/value array of
     133         *                              {@link http://dev.w3.org/html5/markup/textarea.html permitted attributes}
     134         *                              that you want to add.
     135         */
     136        public function edit_field_html( array $raw_properties = array() ) {
     137                /*
     138                 * User_id is a special optional parameter that certain other fields
     139                 * types pass to {@link bp_the_profile_field_options()}.
     140                 */
     141                if ( ! is_admin() && isset( $raw_properties['user_id'] ) ) {
     142                        unset( $raw_properties['user_id'] );
     143                }
     144
     145                $user_id = bp_displayed_user_id();
     146                if ( isset( $raw_properties['user_id'] ) && $raw_properties['user_id'] ) {
     147                        $user_id = (int) $raw_properties['user_id'];
     148                        unset( $raw_properties['user_id'] );
     149                }
     150
     151                if ( ! $this->wp_user_key ) {
     152                        $this->wp_user_key = self::get_field_settings( bp_get_the_profile_field_id() );
     153                }
     154
     155                if ( 'user_url' === $this->wp_user_key ) {
     156                        if ( bp_displayed_user_id() ) {
     157                                $field_value = bp_get_displayed_user()->userdata->{$this->wp_user_key};
     158                        } elseif ( $user_id ) {
     159                                $user = get_user_by( 'id', $user_id );
     160                                $field_value = $user->{$this->wp_user_key};
     161                        }
     162                } else {
     163                        $field_value = bp_get_user_meta( $user_id, $this->wp_user_key, true );
     164                }
     165
     166                $r = wp_parse_args( $raw_properties, array(
     167                        'type'  => 'text',
     168                        'value' => $this->sanitize_for_output( $field_value, $user_id ),
     169                ) );
     170                ?>
     171
     172                <legend id="<?php bp_the_profile_field_input_name(); ?>-1">
     173                        <?php bp_the_profile_field_name(); ?>
     174                        <?php bp_the_profile_field_required_label(); ?>
     175                </legend>
     176
     177                <?php
     178
     179                /** This action is documented in bp-xprofile/bp-xprofile-classes */
     180                do_action( bp_get_the_profile_field_errors_action() ); ?>
     181
     182                <input <?php echo $this->get_edit_field_html_elements( $r ); ?> aria-labelledby="<?php bp_the_profile_field_input_name(); ?>-1" aria-describedby="<?php bp_the_profile_field_input_name(); ?>-3">
     183
     184                <?php if ( bp_get_the_profile_field_description() ) : ?>
     185                        <p class="description" id="<?php bp_the_profile_field_input_name(); ?>-3"><?php bp_the_profile_field_description(); ?></p>
     186                <?php endif; ?>
     187
     188                <?php
     189        }
     190
     191        /**
     192         * Output HTML for this field type on the wp-admin Profile Fields screen.
     193         *
     194         * Must be used inside the {@link bp_profile_fields()} template loop.
     195         *
     196         * @since 8.0.0
     197         *
     198         * @param array $raw_properties Optional key/value array of permitted attributes that you want to add.
     199         */
     200        public function admin_field_html( array $raw_properties = array() ) {
     201                $r = wp_parse_args( $raw_properties, array(
     202                        'type' => 'text'
     203                ) ); ?>
     204
     205                <label for="<?php bp_the_profile_field_input_name(); ?>" class="screen-reader-text"><?php
     206                        /* translators: accessibility text */
     207                        esc_html_e( 'WordPress field', 'buddypress' );
     208                ?></label>
     209                <input <?php echo $this->get_edit_field_html_elements( $r ); ?>>
     210
     211                <?php
     212        }
     213
     214        /**
     215         * Get settings for a given WordPress field.
     216         *
     217         * @since 8.0.0
     218         *
     219         * @param int $field_id ID of the field.
     220         * @return string The meta_key used for this field.
     221         */
     222        public static function get_field_settings( $field_id ) {
     223                $wp_user_key = bp_xprofile_get_meta( $field_id, 'field', 'wp_user_key', true );
     224
     225                return sanitize_key( $wp_user_key );
     226        }
     227
     228        /**
     229         * Save settings from the field edit screen in the Dashboard.
     230         *
     231         * @since 8.0.0
     232         *
     233         * @param int   $field_id ID of the field.
     234         * @param array $settings Array of settings.
     235         * @return bool True on success.
     236         */
     237        public function admin_save_settings( $field_id, $settings ) {
     238                $existing_setting = self::get_field_settings( $field_id );
     239                $setting = '';
     240
     241                if ( isset( $settings['wp_user_key'] ) ) {
     242                        $setting = sanitize_key( $settings['wp_user_key'] );
     243                }
     244
     245                if ( $setting && $setting !== $existing_setting ) {
     246                        bp_xprofile_update_meta( $field_id, 'field', 'wp_user_key', $setting );
     247                }
     248
     249                return true;
     250        }
     251
     252        /**
     253         * This method usually outputs HTML for this field type's children options on the wp-admin Profile Fields
     254         * "Add Field" and "Edit Field" screens, but for this field type, we don't want it, so it's stubbed out.
     255         *
     256         * @since 8.0.0
     257         *
     258         * @param BP_XProfile_Field $current_field The current profile field on the add/edit screen.
     259         * @param string            $control_type  Optional. HTML input type used to render the
     260         *                                         current field's child options.
     261         */
     262        public function admin_new_field_html( BP_XProfile_Field $current_field, $control_type = '' ) {
     263                $type = array_search( get_class( $this ), bp_xprofile_get_field_types() );
     264
     265                if ( false === $type ) {
     266                        return;
     267                }
     268
     269                $style = 'margin-top: 15px;';
     270                if ( $current_field->type !== $type ) {
     271                        $style .= ' display: none;';
     272                };
     273
     274                $setting = self::get_field_settings( $current_field->id );
     275
     276                $wp_labels = array_merge(
     277                        array(
     278                                'first_name' => _x( 'First Name', 'xpofile wp-textbox field type label', 'buddypress' ),
     279                                'last_name'  => _x( 'Last Name', 'xpofile wp-textbox field type label', 'buddypress' ),
     280                                'user_url'   => _x( 'Website', 'xpofile wp-textbox field type label', 'buddypress' ),
     281                        ),
     282                        wp_get_user_contact_methods()
     283                );
     284                ?>
     285                <div id="<?php echo esc_attr( $type ); ?>" class="postbox bp-options-box" style="<?php echo esc_attr( $style ); ?>">
     286                        <h3><?php esc_html_e( 'Select the information you want to use for your WordPress field.', 'buddypress' ); ?></h3>
     287
     288                        <div class="inside" aria-live="polite" aria-atomic="true" aria-relevant="all">
     289                                <div class="bp-option">
     290                                        <ul>
     291                                                <?php
     292                                                foreach ( $this->supported_keys as $key ) {
     293                                                        if ( 'description' === $key || ! isset( $wp_labels[ $key ] ) ) {
     294                                                                continue;
     295                                                        }
     296
     297                                                        printf(
     298                                                                '<li>
     299                                                                        <label for="wp-textbox-wp_user_key-%1$s">
     300                                                                                <input type="radio" id="wp-textbox-wp_user_key-%1$s" name="field-settings[wp_user_key]" value="%1$s" %2$s/>
     301                                                                                %3$s
     302                                                                        </label>
     303                                                                </li>',
     304                                                                esc_attr( $key ),
     305                                                                checked( $key, $setting, false ),
     306                                                                esc_html( $wp_labels[ $key ] )
     307                                                        );
     308                                                }
     309                                                ?>
     310                                        </ul>
     311                                </div>
     312                        </div>
     313                </div>
     314                <?php
     315        }
     316
     317        /**
     318         * Format WordPress field values for display.
     319         *
     320         * @since 8.0.0
     321         *
     322         * @param string     $field_value The field value, as saved in the database.
     323         * @param string|int $field_id    Optional. ID of the field.
     324         * @return string The sanitized WordPress field.
     325         */
     326        public static function display_filter( $field_value, $field_id = '' ) {
     327                $wp_user_key = self::get_field_settings( $field_id );
     328
     329                if ( ! $wp_user_key ) {
     330                        return '';
     331                }
     332
     333                if ( 'user_url' === $wp_user_key ) {
     334                        $sanitized_website = sanitize_user_field( $wp_user_key, $field_value, bp_displayed_user_id(), 'attribute' );
     335                        return sprintf( '<a href="%1$s" rel="nofollow">%1$s</a>', $sanitized_website );
     336                }
     337
     338                return sanitize_user_field( $wp_user_key, $field_value, bp_displayed_user_id(), 'display' );
     339        }
     340}
  • new file src/bp-xprofile/classes/class-bp-xprofile-field-type-wordpress.php

    diff --git src/bp-xprofile/classes/class-bp-xprofile-field-type-wordpress.php src/bp-xprofile/classes/class-bp-xprofile-field-type-wordpress.php
    new file mode 100644
    index 000000000..0a881b24d
    - +  
     1<?php
     2/**
     3 * BuddyPress XProfile Classes.
     4 *
     5 * @package BuddyPress
     6 * @subpackage XProfileClasses
     7 * @since 8.0.0
     8 */
     9
     10// Exit if accessed directly.
     11defined( 'ABSPATH' ) || exit;
     12
     13/**
     14 * Base class for xprofile field types that set/get WordPress profile data from usermeta.
     15 *
     16 * @since 8.0.0
     17 */
     18abstract class BP_XProfile_Field_Type_WordPress extends BP_XProfile_Field_Type {
     19
     20        /**
     21         * The usermeta key for the WordPress field.
     22         *
     23         * @since 8.0.0
     24         * @var string The meta key name of this WordPress field.
     25         */
     26        public $wp_user_key = '';
     27
     28        /**
     29         * The WordPress supported user keys.
     30         *
     31         * @since 8.0.0
     32         * @var string[] The WordPress supported user keys.
     33         */
     34        public $supported_keys = array();
     35
     36        /**
     37         * Supported features for the WordPress field type.
     38         *
     39         * @since 8.0.0
     40         * @var bool[] The WordPress field supported features.
     41         */
     42        public static $supported_features = array(
     43                'switch_fieldtype'        => false,
     44                'required'                => false,
     45                'do_autolink'             => false,
     46                'allow_custom_visibility' => false,
     47        );
     48
     49        /**
     50         * Constructor for the WordPress field type.
     51         *
     52         * @since 8.0.0
     53         */
     54        public function __construct() {
     55                parent::__construct();
     56
     57                /**
     58                 * Fires inside __construct() method for BP_XProfile_Field_Type_WordPress class.
     59                 *
     60                 * @since 8.0.0
     61                 *
     62                 * @param BP_XProfile_Field_Type_WordPress $this Instance of the field type object.
     63                 */
     64                do_action( 'bp_xprofile_field_type_wordpress', $this );
     65
     66                // Use the `$wpdb->usermeta` table instead of the $bp->profile->table_name_data one.
     67                add_filter( 'bp_xprofile_set_field_data_pre_save', array( $this, 'set_field_value' ), 10, 2 );
     68
     69                // Set the supported keys.
     70                $this->supported_keys = bp_xprofile_get_wp_user_keys();
     71        }
     72
     73        /**
     74         * Sanitize the user field before inserting it into db.
     75         *
     76         * @since 8.0.0
     77         *
     78         * @param string $value The user field value.
     79         */
     80        abstract public function sanitize_for_db( $value );
     81
     82        /**
     83         * Sanitize the user field before displaying it as an attribute.
     84         *
     85         * @since 8.0.0
     86         *
     87         * @param string $value The user field value.
     88         * @param integer $user_id The user ID.
     89         */
     90        abstract public function sanitize_for_output( $value, $user_id = 0 );
     91
     92        /**
     93         * Sets the WordPress field value.
     94         *
     95         * @since 8.0.0
     96         *
     97         * @param boolean $retval Whether to shortcircuit the $bp->profile->table_name_data table.
     98         *                        Default `false`.
     99         * @param array $field_args {
     100         *     An array of arguments.
     101         *
     102         *     @type object            $field_type_obj Field type object.
     103         *     @type BP_XProfile_Field $field          Field object.
     104         *     @type integer           $user_id        The user ID.
     105         *     @type mixed             $value          Value passed to xprofile_set_field_data().
     106         *     @type boolean           $is_required    Whether or not the field is required.
     107         * }
     108         * @return boolean Whether to shortcircuit the $bp->profile->table_name_data table.
     109         */
     110        public function set_field_value( $retval = false, $field_args = array() ) {
     111                // Check the wp_user_key is valid and supported.
     112                if ( ! isset( $field_args['field']->type_obj->wp_user_key ) || $this->wp_user_key !== $field_args['field']->type_obj->wp_user_key || ! in_array( $field_args['field']->type_obj->wp_user_key, $this->supported_keys, true ) ) {
     113                        return false;
     114                }
     115
     116                $wp_user_field_value = $this->sanitize_for_db( $field_args['value'] );
     117                $bp_displayed_user   = bp_get_displayed_user();
     118
     119                if ( isset( $bp_displayed_user->updated_keys ) ) {
     120                        $bp_displayed_user->updated_keys[ $this->wp_user_key ] = $wp_user_field_value;
     121                        $retval = true;
     122                } else {
     123                        $retval = wp_update_user(
     124                                array(
     125                                        'ID'               => (int) $field_args['user_id'],
     126                                        $this->wp_user_key => $wp_user_field_value,
     127                                )
     128                        );
     129                }
     130
     131                if ( ! is_wp_error( $retval ) ) {
     132                        $retval = true;
     133                }
     134
     135                return $retval;
     136        }
     137
     138        /**
     139         * Gets the WordPress field value during an xProfile fields loop.
     140         *
     141         * This function is used inside `BP_XProfile_ProfileData::get_data_for_user()`
     142         * to include the WordPress field value into the xProfile fields loop.
     143         *
     144         * @since 8.0.0
     145         *
     146         * @param integer $user_id The user ID.
     147         * @param integer $field_id The xProfile field ID.
     148         * @return array An array containing the metadata `id`, `value` and `table_name`.
     149         */
     150        public function get_field_value( $user_id, $field_id = 0 ) {
     151                global $wpdb;
     152                $wp_field = array(
     153                        'id'         => 0,
     154                        'value'      => '',
     155                        'table_name' => $wpdb->usermeta,
     156                );
     157
     158                if ( 'user_url' === $this->wp_user_key ) {
     159                        if ( bp_displayed_user_id() ) {
     160                                $wp_field['value'] = bp_get_displayed_user()->userdata->{$this->wp_user_key};
     161                        } elseif ( $user_id ) {
     162                                $user = get_user_by( 'id', $user_id );
     163                                $wp_field['value'] = $user->{$this->wp_user_key};
     164                        }
     165
     166                        $wp_field['id']         = $user_id;
     167                        $wp_field['table_name'] = $wpdb->users;
     168                } else {
     169                        $umeta_key = $this->wp_user_key;
     170                        $user_mid  = wp_cache_get( $user_id, 'bp_user_mid' );
     171                        if ( ! $user_mid ) {
     172                                $user_mid = array();
     173                        }
     174
     175                        if ( ! $user_mid ) {
     176                                $list_values   = bp_get_user_meta( $user_id, $umeta_key );
     177                                $wp_field['value'] = reset( $list_values );
     178                                $wp_field['id']    = key( $list_values );
     179
     180                                if ( 0 === $wp_field['id'] ) {
     181                                        /*
     182                                        * We can't just update the WP User Meta cache to key again meta values with meta_ids because of
     183                                        * `return maybe_unserialize( $meta_cache[ $meta_key ][0] );` in `get_metadata_raw()`.
     184                                        */
     185                                        $user_meta_cache = wp_cache_get( $user_id, 'user_meta' );
     186
     187                                        if ( $user_meta_cache ) {
     188                                                $metas = $wpdb->get_results( $wpdb->prepare( "SELECT umeta_id, meta_key, meta_value FROM {$wpdb->usermeta} WHERE user_id = %d ORDER BY umeta_id ASC", $user_id ) );
     189
     190                                                if ( $metas ) {
     191                                                        foreach ( $user_meta_cache as $meta_key => $meta_values ) {
     192                                                                if ( ! in_array( $meta_key, $this->supported_keys, true ) ) {
     193                                                                        continue;
     194                                                                }
     195
     196                                                                foreach ( $meta_values as $meta_value ) {
     197                                                                        $meta_object = wp_list_filter( $metas, array( 'meta_key' => $meta_key, 'meta_value' => $meta_value ) );
     198
     199                                                                        if ( 1 === count( $meta_object ) ) {
     200                                                                                $meta_object = reset( $meta_object );
     201                                                                                $user_mid[ $meta_key ][ $meta_object->umeta_id ] = $meta_value;
     202
     203                                                                                // Set the meta_id for the requested field.
     204                                                                                if ( $umeta_key === $meta_key ) {
     205                                                                                        $wp_field['id'] = $meta_object->umeta_id;
     206                                                                                }
     207                                                                        }
     208                                                                }
     209                                                        }
     210                                                }
     211
     212                                                // Set the User mid cache.
     213                                                wp_cache_set( $user_id, $user_mid, 'bp_user_mid' );
     214                                        }
     215                                }
     216                        }
     217
     218                        if ( isset( $user_mid[ $umeta_key ] ) ) {
     219                                $wp_field['value'] = reset( $user_mid[ $umeta_key ] );
     220                                $wp_field['id']    = key( $user_mid[ $umeta_key ] );
     221                        }
     222                }
     223
     224                return $wp_field;
     225        }
     226}
  • 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 cfe021c43..5648e5471 100644
    class BP_XProfile_Field { 
    13171317        <?php
    13181318        }
    13191319
     1320        /**
     1321         * Gets field type supports.
     1322         *
     1323         * @since 8.0.0
     1324         *
     1325         * @return bool[] Supported features.
     1326         */
     1327        public function get_field_type_supports() {
     1328                $supports = array(
     1329                        'switch_fieldtype'        => true,
     1330                        'allow_required'          => true,
     1331                        'allow_autolink'          => true,
     1332                        'allow_custom_visibility' => true,
     1333                );
     1334
     1335                if ( isset( $this->type_obj ) && $this->type_obj ) {
     1336                        $field_type = $this->type_obj;
     1337
     1338                        if ( isset( $field_type::$supported_features ) ) {
     1339                                $supports = array_merge( $supports, $field_type::$supported_features );
     1340                        }
     1341                }
     1342
     1343                return $supports;
     1344        }
     1345
     1346        /**
     1347         * Checks whether the field type supports the requested feature.
     1348         *
     1349         * @since 8.0.0
     1350         *
     1351         * @param string $support The name of the feature.
     1352         * @return boolean True if the field type supports the feature. False otherwise.
     1353         */
     1354        public function field_type_supports( $support = '' ) {
     1355                $retval   = true;
     1356                $features = $this->get_field_type_supports();
     1357
     1358                if ( isset( $features[ $support ] ) ) {
     1359                        $retval = $features[ $support ];
     1360                }
     1361
     1362                return $retval;
     1363        }
     1364
    13201365        /**
    13211366         * Private method used to display the submit metabox.
    13221367         *
    class BP_XProfile_Field { 
    14961541         */
    14971542        private function visibility_metabox() {
    14981543
    1499                 // Default field cannot have custom visibility.
    1500                 if ( true === $this->is_default_field() ) {
     1544                // Default field and field types not supporting the feature cannot have custom visibility.
     1545                if ( true === $this->is_default_field() || ! $this->field_type_supports( 'allow_custom_visibility' ) ) {
    15011546                        return;
    15021547                } ?>
    15031548
    1504                 <div class="postbox">
     1549                <div class="postbox" id="field-type-visibiliy-metabox">
    15051550                        <h2><label for="default-visibility"><?php esc_html_e( 'Visibility', 'buddypress' ); ?></label></h2>
    15061551                        <div class="inside">
    15071552                                <div>
    class BP_XProfile_Field { 
    15451590         */
    15461591        private function required_metabox() {
    15471592
    1548                 // Default field is always required.
    1549                 if ( true === $this->is_default_field() ) {
     1593                // Default field and field types not supporting the feature cannot be required.
     1594                if ( true === $this->is_default_field() || ! $this->field_type_supports( 'required' ) ) {
    15501595                        return;
    15511596                } ?>
    15521597
    1553                 <div class="postbox">
     1598                <div class="postbox" id="field-type-required-metabox">
    15541599                        <h2><label for="required"><?php esc_html_e( 'Requirement', 'buddypress' ); ?></label></h2>
    15551600                        <div class="inside">
    15561601                                <select name="required" id="required">
    class BP_XProfile_Field { 
    15711616         * @return void If default field id 1.
    15721617         */
    15731618        private function autolink_metabox() {
    1574                 ?>
    15751619
    1576                 <div class="postbox">
     1620                // Field types not supporting the feature cannot use autolink.
     1621                if ( ! $this->field_type_supports( 'do_autolink' ) ) {
     1622                        return;
     1623                } ?>
     1624
     1625                <div class="postbox" id="field-type-autolink-metabox">
    15771626                        <h2><?php esc_html_e( 'Autolink', 'buddypress' ); ?></h2>
    15781627                        <div class="inside">
    15791628                                <p class="description"><?php esc_html_e( 'On user profiles, link this field to a search of the Members directory, using the field value as a search term.', 'buddypress' ); ?></p>
    class BP_XProfile_Field { 
    16061655                // Default field cannot change type.
    16071656                if ( true === $this->is_default_field() ) {
    16081657                        return;
    1609                 } ?>
     1658                }
     1659                ?>
    16101660
    16111661                <div class="postbox">
    16121662                        <h2><label for="fieldtype"><?php esc_html_e( 'Type', 'buddypress'); ?></label></h2>
    16131663                        <div class="inside" aria-live="polite" aria-atomic="true" aria-relevant="all">
    1614                                 <select name="fieldtype" id="fieldtype" onchange="show_options(this.value)">
     1664                                <?php if ( ! $this->field_type_supports( 'switch_fieldtype' ) ) : ?>
     1665                                        <input type="text" disabled="true" value="<?php echo esc_attr( $this->type_obj->name ); ?>">
     1666                                        <input type="hidden" name="fieldtype" id="fieldtype" value="<?php echo esc_attr( $this->type ); ?>">
    16151667
    1616                                         <?php bp_xprofile_admin_form_field_types( $this->type ); ?>
     1668                                <?php else : ?>
     1669                                        <select name="fieldtype" id="fieldtype" onchange="show_options(this.value)">
    16171670
    1618                                 </select>
     1671                                                <?php bp_xprofile_admin_form_field_types( $this->type ); ?>
     1672
     1673                                        </select>
     1674                                <?php endif; ?>
    16191675
    16201676                                <?php
    16211677
    class BP_XProfile_Field { 
    16421698                // Nonce.
    16431699                wp_nonce_field( 'bp_xprofile_admin_field', 'bp_xprofile_admin_field' );
    16441700
    1645                 // Field 1 is the fullname field, which cannot have custom visibility.
    1646                 if ( false === $this->is_default_field() ) {
    1647                         return;
    1648                 } ?>
     1701                // Init default field hidden inputs.
     1702                $default_field_hidden_inputs = array();
     1703                $hidden_fields = array(
     1704                        'required' => array(
     1705                                'name'  => 'required',
     1706                                'id'    => 'required',
     1707                                'value' => '0',
     1708                        ),
     1709                        'default_visibility' => array(
     1710                                'name'  => 'default-visibility',
     1711                                'id'    => 'default-visibility',
     1712                                'value' => 'public',
     1713                        ),
     1714                        'allow_custom_visibility' => array(
     1715                                'name'  => 'allow-custom-visibility',
     1716                                'id'    => 'allow-custom-visibility',
     1717                                'value' => 'disabled',
     1718                        ),
     1719                        'do_autolink' => array(
     1720                                'name'  => 'do_autolink',
     1721                                'id'    => 'do-autolink',
     1722                                'value' => '',
     1723                        ),
     1724                );
    16491725
    1650                 <input type="hidden" name="required"  id="required"  value="1"       />
    1651                 <input type="hidden" name="fieldtype" id="fieldtype" value="textbox" />
     1726                // Field 1 is the fullname field, which is required.
     1727                if ( true === $this->is_default_field() ) {
     1728                        $default_field_required          = $hidden_fields['required'];
     1729                        $default_field_required['value'] = '1';
     1730
     1731                        $default_field_hidden_inputs = array(
     1732                                $default_field_required,
     1733                                array(
     1734                                        'name'  => 'fieldtype',
     1735                                        'id'    => 'fieldtype',
     1736                                        'value' => 'textbox',
     1737                                ),
     1738                        );
     1739                }
    16521740
    1653                 <?php
     1741                $supports = $this->get_field_type_supports();
     1742                if ( $supports ) {
     1743                        foreach ( $supports as $feature => $support ) {
     1744                                if ( true === $support || 'switch_fieldtype' === $feature ) {
     1745                                        continue;
     1746                                }
     1747
     1748                                $default_field_hidden_inputs[] = $hidden_fields[ $feature ];
     1749
     1750                                if ( 'allow_custom_visibility' === $feature ) {
     1751                                        $default_field_hidden_inputs[] = $hidden_fields['default_visibility'];
     1752                                }
     1753                        }
     1754                }
     1755
     1756                if ( ! $default_field_hidden_inputs ) {
     1757                        return;
     1758                }
     1759
     1760                foreach ( $default_field_hidden_inputs as $default_field_hidden_input ) {
     1761                        printf(
     1762                                '<input type="hidden" name="%1$s" id="%2$s" value="%3$s"/>',
     1763                                esc_attr( $default_field_hidden_input['name'] ),
     1764                                esc_attr( $default_field_hidden_input['id'] ),
     1765                                esc_attr( $default_field_hidden_input['value'] ),
     1766                        );
     1767                }
    16541768        }
    16551769
    16561770        /**
  • 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 60bd589cd..b6f196838 100644
    class BP_XProfile_Group { 
    237237         * and field data.
    238238         *
    239239         * @since 1.2.0
     240         * @since 2.4.0 Introduced `$member_type` argument.
     241         * @since 8.0.0 Introduced `$hide_field_types` argument.
    240242         *
    241243         * @global object $wpdb WordPress DB access object.
    242244         *
    class BP_XProfile_Group { 
    256258         *      @type bool         $fetch_fields      Whether to fetch each group's fields. Default: false.
    257259         *      @type bool         $fetch_field_data  Whether to fetch data for each field. Requires a $user_id.
    258260         *                                            Default: false.
    259          *      @type array        $exclude_groups    Comma-separated list or array of group IDs to exclude.
    260          *      @type array        $exclude_fields    Comma-separated list or array of field IDs to exclude.
     261         *      @type int[]|bool   $exclude_groups    Comma-separated list or array of group IDs to exclude.
     262         *      @type int[]|bool   $exclude_fields    Comma-separated list or array of field IDs to exclude.
     263         *      @type string[]     $hide_field_types  List of field types to hide form loop. Default: empty array.
    261264         *      @type bool         $update_meta_cache Whether to pre-fetch xprofilemeta for all retrieved groups, fields,
    262265         *                                            and data. Default: true.
    263266         * }
    class BP_XProfile_Group { 
    278281                        'fetch_visibility_level' => false,
    279282                        'exclude_groups'         => false,
    280283                        'exclude_fields'         => false,
     284                        'hide_field_types'       => array(),
    281285                        'update_meta_cache'      => true,
    282286                ) );
    283287
    class BP_XProfile_Group { 
    338342                // Pull field objects from the cache.
    339343                $fields = array();
    340344                foreach ( $field_ids as $field_id ) {
    341                         $fields[] = xprofile_get_field( $field_id, null, false );
     345                        $_field = xprofile_get_field( $field_id, null, false );
     346
     347                        if ( in_array( $_field->type, $r['hide_field_types'], true ) ) {
     348                                continue;
     349                        }
     350
     351                        $fields[] = $_field;
    342352                }
    343353
    344354                // Store field IDs for meta cache priming.
    class BP_XProfile_Group { 
    346356
    347357                // Maybe fetch field data.
    348358                if ( ! empty( $r['fetch_field_data'] ) ) {
     359                        $field_type_objects = wp_list_pluck( $fields, 'type_obj', 'id' );
    349360
    350361                        // Get field data for user ID.
    351362                        if ( ! empty( $field_ids ) && ! empty( $r['user_id'] ) ) {
    352                                 $field_data = BP_XProfile_ProfileData::get_data_for_user( $r['user_id'], $field_ids );
     363                                $field_data = BP_XProfile_ProfileData::get_data_for_user( $r['user_id'], $field_ids, $field_type_objects );
    353364                        }
    354365
    355366                        // Remove data-less fields, if necessary.
  • src/bp-xprofile/classes/class-bp-xprofile-profiledata.php

    diff --git src/bp-xprofile/classes/class-bp-xprofile-profiledata.php src/bp-xprofile/classes/class-bp-xprofile-profiledata.php
    index 9553b2e30..f9e0d9ed8 100644
    class BP_XProfile_ProfileData { 
    321321         * @param array $field_ids Array of field IDs to query for.
    322322         * @return array
    323323         */
    324         public static function get_data_for_user( $user_id, $field_ids ) {
     324        public static function get_data_for_user( $user_id, $field_ids, $field_type_objects = array() ) {
    325325                global $wpdb;
    326326
    327327                $data = array();
    class BP_XProfile_ProfileData { 
    339339                        foreach ( $uncached_data as $ud ) {
    340340                                $d               = new stdClass;
    341341                                $d->id           = $ud->id;
     342                                $d->table_name   = $bp->profile->table_name_data;
    342343                                $d->user_id      = $ud->user_id;
    343344                                $d->field_id     = $ud->field_id;
    344345                                $d->value        = $ud->value;
    class BP_XProfile_ProfileData { 
    359360                                // If no value was found, cache an empty item
    360361                                // to avoid future cache misses.
    361362                                } else {
    362                                         $d               = new stdClass;
    363                                         $d->id           = '';
     363                                        $d = new stdClass;
     364
     365                                        // Check WordPress if it's a WordPress field.
     366                                        if ( isset( $field_type_objects[ $field_id ]->wp_user_key ) ) {
     367                                                $meta          = $field_type_objects[ $field_id ]->get_field_value( $user_id, $field_id );
     368                                                $d->id         = $meta['id'];
     369                                                $d->value      = $meta['value'];
     370                                                $d->table_name = $meta['table_name'];
     371
     372                                        } else {
     373                                                $d->id    = '';
     374                                                $d->value = '';
     375                                        }
     376
     377                                        $d->table_name   = '';
    364378                                        $d->user_id      = $user_id;
    365379                                        $d->field_id     = $field_id;
    366                                         $d->value        = '';
    367380                                        $d->last_updated = '';
    368381
    369382                                        wp_cache_set( $cache_key, $d, 'bp_xprofile_data' );
  • src/bp-xprofile/classes/class-bp-xprofile-user-admin.php

    diff --git src/bp-xprofile/classes/class-bp-xprofile-user-admin.php src/bp-xprofile/classes/class-bp-xprofile-user-admin.php
    index 73db1afec..ef71072c5 100644
    class BP_XProfile_User_Admin { 
    272272
    273273                $r = bp_parse_args( $args['args'], array(
    274274                        'profile_group_id' => 0,
    275                         'user_id'          => $user->ID
     275                        'user_id'          => $user->ID,
     276                        'hide_field_types' => array( 'wp-textbox', 'wp-biography' ),
    276277                ), 'bp_xprofile_user_admin_profile_loop_args' );
    277278
    278279                // We really need these args.
  • src/bp-xprofile/screens/edit.php

    diff --git src/bp-xprofile/screens/edit.php src/bp-xprofile/screens/edit.php
    index e0b85c0e0..4689ebbcf 100644
    function xprofile_screen_edit_profile() { 
    5050                $posted_field_ids = wp_parse_id_list( $_POST['field_ids'] );
    5151                $is_required      = array();
    5252
     53                $bp_displayed_user = bp_get_displayed_user();
     54                $bp_displayed_user->updated_keys = array();
     55
    5356                // Loop through the posted fields formatting any datebox values then validate the field.
    5457                foreach ( (array) $posted_field_ids as $field_id ) {
    5558                        bp_xprofile_maybe_format_datebox_post_data( $field_id );
    function xprofile_screen_edit_profile() { 
    126129                         */
    127130                        do_action( 'xprofile_updated_profile', bp_displayed_user_id(), $posted_field_ids, $errors, $old_values, $new_values );
    128131
     132                        // Some WP User keys have been updated: let's update the WP fiels all together.
     133                        if ( $bp_displayed_user->updated_keys ) {
     134                                $user_id = wp_update_user(
     135                                        array_merge(
     136                                                array(
     137                                                        'ID' => bp_displayed_user_id(),
     138                                                ),
     139                                                $bp_displayed_user->updated_keys
     140                                        )
     141                                );
     142
     143                                $bp_displayed_user->updated_keys = array();
     144
     145                                if ( is_wp_error( $user_id ) ) {
     146                                        $errors = true;
     147                                }
     148                        }
     149
    129150                        // Set the feedback messages.
    130151                        if ( !empty( $errors ) ) {
    131152                                bp_core_add_message( __( 'There was a problem updating some of your profile information. Please try again.', 'buddypress' ), 'error' );
    function xprofile_screen_edit_profile() { 
    153174         * @param string $template Path to the XProfile edit template to load.
    154175         */
    155176        bp_core_load_template( apply_filters( 'xprofile_template_edit_profile', 'members/single/home' ) );
    156 }
    157  No newline at end of file
     177}