Ticket #7162: 7162.3.patch
File 7162.3.patch, 63.8 KB (added by , 4 years 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..99a5b4b5d 100644
function show_options( forWhat ) { 95 95 jQuery( '#do-autolink' ).val( do_autolink ); 96 96 } 97 97 98 // Show/hides metaboxes according to selected field type supports. 99 jQuery( '#field-type-visibiliy-metabox, #field-type-required-metabox, #field-type-autolink-metabox, #field-type-member-types' ).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 112 if ( -1 !== XProfileAdmin.hide_member_types_metabox.indexOf( forWhat ) ) { 113 jQuery( '#field-type-member-types' ).hide(); 114 } 115 98 116 jQuery( document ).trigger( 'bp-xprofile-show-options', forWhat ); 99 117 } 100 118 … … function titleHint( id ) { 173 191 174 192 titleprompt.on( 'click', function(){ 175 193 jQuery(this).addClass('screen-reader-text'); 176 title. focus();194 title.trigger( 'focus' ); 177 195 }); 178 196 179 197 title.on( 'blur', function(){ … … function titleHint( id ) { 184 202 titleprompt.addClass('screen-reader-text'); 185 203 }).on( 'keydown', function(e){ 186 204 titleprompt.addClass('screen-reader-text'); 187 jQuery(this). unbind(e);205 jQuery(this).off( e ); 188 206 }); 189 207 } 190 208 191 jQuery( document ).ready(function() {209 jQuery( function() { 192 210 193 211 // Set focus in Field Title, if we're on the right page. 194 212 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 ) { 493 493 $field->type = $_POST['fieldtype']; 494 494 $field->name = $_POST['title']; 495 495 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 496 513 if ( ! empty( $_POST['description'] ) ) { 497 514 $field->description = $_POST['description']; 498 515 } else { … … function xprofile_admin_manage_field( $group_id, $field_id = null ) { 537 554 538 555 // Validate default visibility. 539 556 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 ); 541 564 } 542 565 543 566 // Validate custom visibility. 544 567 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 ); 546 575 } 547 576 548 577 // Validate signup. … … function xprofile_admin_manage_field( $group_id, $field_id = null ) { 552 581 bp_xprofile_delete_meta( $field_id, 'field', 'signup_position' ); 553 582 } 554 583 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 555 589 // Save autolink settings. 556 if ( isset( $_POST['do_autolink'] ) && 'on' === wp_unslash( $_POST['do_autolink'] )) {590 if ( 'on' === $do_autolink ) { 557 591 bp_xprofile_update_field_meta( $field_id, 'do_autolink', 'on' ); 558 592 } else { 559 593 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 302 302 303 303 // List actions to clear super cached pages on, if super cache is installed. 304 304 add_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 */ 313 function bp_xprofile_reset_user_mid_cache( $user_id ) { 314 wp_cache_delete( $user_id, 'bp_user_mid' ); 315 } 316 add_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..94478187e 100644
function xprofile_add_admin_js() { 51 51 // types that support options, for use in showing/hiding the 52 52 // "please enter options for this field" section. 53 53 $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 'hide_member_types_metabox' => array(), 60 'text' => array( 57 61 'defaultValue' => __( 'Default Value', 'buddypress' ), 58 62 'deleteLabel' => __( 'Delete', 'buddypress' ), 59 63 ), … … function xprofile_add_admin_js() { 64 68 if ( $field->do_settings_section() ) { 65 69 $strings['do_settings_section_field_types'][] = $field_type; 66 70 } 71 72 if ( isset( $field::$supported_features ) && is_array( $field::$supported_features ) ) { 73 foreach ( $field::$supported_features as $feature => $support ) { 74 if ( isset( $strings['hide_' . $feature . '_metabox'] ) && ! $support ) { 75 $strings['hide_' . $feature . '_metabox'][] = $field_type; 76 } 77 } 78 } 67 79 } 68 80 69 81 // 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 352 352 * @return string 353 353 */ 354 354 function 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 355 360 if ( bp_xprofile_is_richtext_enabled_for_field( $field_id ) ) { 356 361 // The xprofile_filter_kses() expects a BP_XProfile_ProfileData object. 357 362 $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..9764102f4 100644
function bp_xprofile_get_field_types() { 159 159 'textarea' => 'BP_XProfile_Field_Type_Textarea', 160 160 'textbox' => 'BP_XProfile_Field_Type_Textbox', 161 161 'telephone' => 'BP_XProfile_Field_Type_Telephone', 162 'wp-biography' => 'BP_XProfile_Field_Type_WordPress_Biography', 163 'wp-textbox' => 'BP_XProfile_Field_Type_WordPress_Textbox', 162 164 ); 163 165 164 166 /** … … function xprofile_get_field( $field, $user_id = null, $get_data = true ) { 310 312 return $_field; 311 313 } 312 314 315 /** 316 * Get a profile Field Type object. 317 * 318 * @since 8.0.0 319 * 320 * @param int $field_id ID of the field. 321 * @return BP_XProfile_Field_Type|null Field Type object if found, otherwise null. 322 */ 323 function bp_xprofile_get_field_type( $field_id ) { 324 $field_type = null; 325 $field = xprofile_get_field( $field_id, null, false ); 326 327 if ( $field instanceof BP_XProfile_Field ) { 328 $field_type = $field->type_obj; 329 } 330 331 return $field_type; 332 } 333 313 334 /** 314 335 * Delete a profile field object. 315 336 * … … function xprofile_set_field_data( $field, $user_id, $value, $is_required = false 462 483 return false; 463 484 } 464 485 465 $field = new BP_XProfile_ProfileData(); 466 $field->field_id = $field_id; 467 $field->user_id = $user_id; 486 $field_args = compact( 'field_type_obj', 'field', 'user_id', 'value', 'is_required' ); 468 487 469 // Gets un/reserialized via xprofile_sanitize_data_value_before_save(). 470 $field->value = maybe_serialize( $value ); 488 /** 489 * Return a WP_Error object or true to use your custom way of saving field values. 490 * 491 * @since 8.0.0 492 * 493 * @param boolean Whether to shortcircuit the $bp->profile->table_name_data table. 494 * @param array $field_args { 495 * An array of arguments. 496 * 497 * @type object $field_type_obj Field type object. 498 * @type BP_XProfile_Field $field Field object. 499 * @type integer $user_id The user ID. 500 * @type mixed $value Value passed to xprofile_set_field_data(). 501 * @type boolean $is_required Whether or not the field is required. 502 * } 503 */ 504 $retval = apply_filters( 'bp_xprofile_set_field_data_pre_save', false, $field_args ); 471 505 472 return $field->save(); 506 if ( is_wp_error( $retval ) ) { 507 return false; 508 } 509 510 if ( false === $retval ) { 511 $field = new BP_XProfile_ProfileData(); 512 $field->field_id = $field_id; 513 $field->user_id = $user_id; 514 515 // Gets un/reserialized via xprofile_sanitize_data_value_before_save(). 516 $field->value = maybe_serialize( $value ); 517 518 $retval = $field->save(); 519 } 520 521 return $retval; 473 522 } 474 523 475 524 /** … … function bp_xprofile_personal_data_exporter( $email_address ) { 1357 1406 'done' => true, 1358 1407 ); 1359 1408 } 1409 1410 /** 1411 * Returns the list of supporterd WordPress field meta keys. 1412 * 1413 * @since 8.0.0 1414 * 1415 * @return string[] List of supported WordPress user keys. 1416 */ 1417 function bp_xprofile_get_wp_user_keys() { 1418 return array_merge( 1419 array( 'first_name', 'last_name', 'user_url', 'description' ), 1420 array_keys( wp_get_user_contact_methods() ) 1421 ); 1422 } -
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; 14 14 * Query for XProfile groups and fields. 15 15 * 16 16 * @since 1.0.0 17 * @since 2.4.0 Introduced `$member_type` argument. 18 * @since 8.0.0 Introduced `$hide_field_types` argument. 17 19 * 18 20 * @global object $profile_template 19 21 * @see BP_XProfile_Group::get() for full description of `$args` array. … … defined( 'ABSPATH' ) || exit; 31 33 * @type bool $fetch_field_data Default: true. 32 34 * @type bool $fetch_visibility_level Defaults to true when an admin is viewing a profile, or when a user is 33 35 * 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. 36 39 * @type bool $update_meta_cache Default: true. 37 40 * } 38 41 * … … function bp_has_profile( $args = '' ) { 64 67 'fetch_visibility_level' => $fetch_visibility_level_default, 65 68 'exclude_groups' => false, // Comma-separated list of profile field group IDs to exclude. 66 69 '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. 67 71 'update_meta_cache' => true, 68 72 ), 'has_profile' ); 69 73 -
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 { 410 410 'bp_xprofile_data', 411 411 'bp_xprofile_fields', 412 412 'bp_xprofile_groups', 413 'xprofile_meta' 413 'xprofile_meta', 414 'bp_user_mid', 414 415 ) ); 415 416 416 417 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 { 105 105 * 106 106 * @since 1.5.0 107 107 * @since 2.4.0 Introduced `$member_type` argument. 108 * @since 8.0.0 Introduced `$hide_field_types` argument. 108 109 * 109 110 * @param array|string $args { 110 111 * An array of arguments. All items are optional. … … class BP_XProfile_Data_Template { 120 121 * @type int|bool $hide_empty_fields Should empty fields be skipped. 121 122 * @type int|bool $fetch_visibility_level Fetch visibility levels. 122 123 * @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. 123 125 * } 124 126 */ 125 127 public function __construct( $args = '' ) { … … class BP_XProfile_Data_Template { 156 158 'fetch_visibility_level' => false, 157 159 'exclude_groups' => false, 158 160 'exclude_fields' => false, 161 'hide_field_types' => array(), 159 162 'update_meta_cache' => true 160 163 ) ); 161 164 -
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. 11 defined( 'ABSPATH' ) || exit; 12 13 /** 14 * WordPress Biography xProfile field type. 15 * 16 * @since 8.0.0 17 */ 18 class 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..3c5828a73
- + 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. 11 defined( 'ABSPATH' ) || exit; 12 13 /** 14 * WordPress xProfile regular field type. 15 * 16 * @since 8.0.0 17 */ 18 class 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 $this->wp_user_key = ''; 33 34 $this->set_format( '/^.*$/', 'replace' ); 35 36 /** 37 * Fires inside __construct() method for BP_XProfile_Field_Type_WordPress_Textbox class. 38 * 39 * @since 8.0.0 40 * 41 * @param BP_XProfile_Field_Type_WordPress_Textbox $this Instance of the field type object. 42 */ 43 do_action( 'bp_xprofile_field_type_wordpress_textbox', $this ); 44 45 /* 46 * As we are using an xProfile field meta to store the WordPress field meta key we need 47 * to make sure $this->wp_user_key is set before once the field has been populated. 48 */ 49 add_action( 'bp_xprofile_field', array( $this, 'set_wp_user_key' ), 10 ); 50 } 51 52 /** 53 * Sets the WordPress field wp_user_key property before saving the xProfile field. 54 * 55 * @since 8.0.0 56 * 57 * @param BP_XProfile_Field $field Field object. 58 */ 59 public function set_wp_user_key( $field ) { 60 if ( ! $this->wp_user_key && 'wp-textbox' === $field->type ) { 61 $this->wp_user_key = self::get_field_settings( $field->id ); 62 } 63 } 64 65 /** 66 * Gets the WordPress field value during an xProfile fields loop. 67 * 68 * This function is used inside `BP_XProfile_ProfileData::get_data_for_user()` 69 * to include the WordPress field value into the xProfile fields loop. 70 * 71 * @since 8.0.0 72 * 73 * @param integer $user_id The user ID. 74 * @param integer $field_id The xProfile field ID. 75 * @return array An array containing the metadata `id`, `value` and `table_name`. 76 */ 77 public function get_field_value( $user_id, $field_id = 0 ) { 78 if ( ! $this->wp_user_key ) { 79 $this->wp_user_key = self::get_field_settings( $field_id ); 80 } 81 82 return parent::get_field_value( $user_id, $field_id ); 83 } 84 85 /** 86 * Sanitize the user field before saving it to db. 87 * 88 * @since 8.0.0 89 * 90 * @param string $value The user field value. 91 * @return string The sanitized field value. 92 */ 93 public function sanitize_for_db( $value ) { 94 if ( 'user_url' === $this->wp_user_key ) { 95 return esc_url_raw( $value ); 96 } 97 98 return sanitize_text_field( $value ); 99 } 100 101 /** 102 * Sanitize the user field before displaying it as an attribute. 103 * 104 * @since 8.0.0 105 * 106 * @param string $value The user field value. 107 * @return string The sanitized field value. 108 */ 109 public function sanitize_for_output( $value, $user_id = 0 ) { 110 if ( ! $user_id ) { 111 $user_id = bp_displayed_user_id(); 112 } 113 114 return sanitize_user_field( $this->wp_user_key, $value, $user_id, 'attribute' ); 115 } 116 117 /** 118 * Output the edit field HTML for this field type. 119 * 120 * Must be used inside the {@link bp_profile_fields()} template loop. 121 * 122 * @since 8.0.0 123 * 124 * @param array $raw_properties Optional key/value array of 125 * {@link http://dev.w3.org/html5/markup/textarea.html permitted attributes} 126 * that you want to add. 127 */ 128 public function edit_field_html( array $raw_properties = array() ) { 129 /* 130 * User_id is a special optional parameter that certain other fields 131 * types pass to {@link bp_the_profile_field_options()}. 132 */ 133 if ( ! is_admin() && isset( $raw_properties['user_id'] ) ) { 134 unset( $raw_properties['user_id'] ); 135 } 136 137 $user_id = bp_displayed_user_id(); 138 if ( isset( $raw_properties['user_id'] ) && $raw_properties['user_id'] ) { 139 $user_id = (int) $raw_properties['user_id']; 140 unset( $raw_properties['user_id'] ); 141 } 142 143 if ( ! $this->wp_user_key ) { 144 $this->wp_user_key = self::get_field_settings( bp_get_the_profile_field_id() ); 145 } 146 147 if ( 'user_url' === $this->wp_user_key ) { 148 if ( bp_displayed_user_id() ) { 149 $field_value = bp_get_displayed_user()->userdata->{$this->wp_user_key}; 150 } elseif ( $user_id ) { 151 $user = get_user_by( 'id', $user_id ); 152 $field_value = $user->{$this->wp_user_key}; 153 } 154 } else { 155 $field_value = bp_get_user_meta( $user_id, $this->wp_user_key, true ); 156 } 157 158 $r = wp_parse_args( $raw_properties, array( 159 'type' => 'text', 160 'value' => $this->sanitize_for_output( $field_value, $user_id ), 161 ) ); 162 ?> 163 164 <legend id="<?php bp_the_profile_field_input_name(); ?>-1"> 165 <?php bp_the_profile_field_name(); ?> 166 <?php bp_the_profile_field_required_label(); ?> 167 </legend> 168 169 <?php 170 171 /** This action is documented in bp-xprofile/bp-xprofile-classes */ 172 do_action( bp_get_the_profile_field_errors_action() ); ?> 173 174 <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"> 175 176 <?php if ( bp_get_the_profile_field_description() ) : ?> 177 <p class="description" id="<?php bp_the_profile_field_input_name(); ?>-3"><?php bp_the_profile_field_description(); ?></p> 178 <?php endif; ?> 179 180 <?php 181 } 182 183 /** 184 * Output HTML for this field type on the wp-admin Profile Fields screen. 185 * 186 * Must be used inside the {@link bp_profile_fields()} template loop. 187 * 188 * @since 8.0.0 189 * 190 * @param array $raw_properties Optional key/value array of permitted attributes that you want to add. 191 */ 192 public function admin_field_html( array $raw_properties = array() ) { 193 $r = wp_parse_args( $raw_properties, array( 194 'type' => 'text' 195 ) ); ?> 196 197 <label for="<?php bp_the_profile_field_input_name(); ?>" class="screen-reader-text"><?php 198 /* translators: accessibility text */ 199 esc_html_e( 'WordPress field', 'buddypress' ); 200 ?></label> 201 <input <?php echo $this->get_edit_field_html_elements( $r ); ?>> 202 203 <?php 204 } 205 206 /** 207 * Get settings for a given WordPress field. 208 * 209 * @since 8.0.0 210 * 211 * @param int $field_id ID of the field. 212 * @return string The meta_key used for this field. 213 */ 214 public static function get_field_settings( $field_id ) { 215 $wp_user_key = bp_xprofile_get_meta( $field_id, 'field', 'wp_user_key', true ); 216 217 return sanitize_key( $wp_user_key ); 218 } 219 220 /** 221 * Save settings from the field edit screen in the Dashboard. 222 * 223 * @since 8.0.0 224 * 225 * @param int $field_id ID of the field. 226 * @param array $settings Array of settings. 227 * @return bool True on success. 228 */ 229 public function admin_save_settings( $field_id, $settings ) { 230 $existing_setting = self::get_field_settings( $field_id ); 231 $setting = ''; 232 233 if ( isset( $settings['wp_user_key'] ) ) { 234 $setting = sanitize_key( $settings['wp_user_key'] ); 235 } 236 237 if ( $setting && $setting !== $existing_setting ) { 238 bp_xprofile_update_meta( $field_id, 'field', 'wp_user_key', $setting ); 239 } 240 241 return true; 242 } 243 244 /** 245 * This method usually outputs HTML for this field type's children options on the wp-admin Profile Fields 246 * "Add Field" and "Edit Field" screens, but for this field type, we don't want it, so it's stubbed out. 247 * 248 * @since 8.0.0 249 * 250 * @param BP_XProfile_Field $current_field The current profile field on the add/edit screen. 251 * @param string $control_type Optional. HTML input type used to render the 252 * current field's child options. 253 */ 254 public function admin_new_field_html( BP_XProfile_Field $current_field, $control_type = '' ) { 255 $type = array_search( get_class( $this ), bp_xprofile_get_field_types() ); 256 257 if ( false === $type ) { 258 return; 259 } 260 261 $style = 'margin-top: 15px;'; 262 if ( $current_field->type !== $type ) { 263 $style .= ' display: none;'; 264 }; 265 266 $setting = self::get_field_settings( $current_field->id ); 267 268 $wp_labels = array_merge( 269 array( 270 'first_name' => _x( 'First Name', 'xpofile wp-textbox field type label', 'buddypress' ), 271 'last_name' => _x( 'Last Name', 'xpofile wp-textbox field type label', 'buddypress' ), 272 'user_url' => _x( 'Website', 'xpofile wp-textbox field type label', 'buddypress' ), 273 ), 274 wp_get_user_contact_methods() 275 ); 276 ?> 277 <div id="<?php echo esc_attr( $type ); ?>" class="postbox bp-options-box" style="<?php echo esc_attr( $style ); ?>"> 278 <h3><?php esc_html_e( 'Select the information you want to use for your WordPress field.', 'buddypress' ); ?></h3> 279 280 <div class="inside" aria-live="polite" aria-atomic="true" aria-relevant="all"> 281 <div class="bp-option"> 282 <ul> 283 <?php 284 foreach ( $this->supported_keys as $key ) { 285 if ( 'description' === $key || ! isset( $wp_labels[ $key ] ) ) { 286 continue; 287 } 288 289 printf( 290 '<li> 291 <label for="wp-textbox-wp_user_key-%1$s"> 292 <input type="radio" id="wp-textbox-wp_user_key-%1$s" name="field-settings[wp_user_key]" value="%1$s" %2$s/> 293 %3$s 294 </label> 295 </li>', 296 esc_attr( $key ), 297 checked( $key, $setting, false ), 298 esc_html( $wp_labels[ $key ] ) 299 ); 300 } 301 ?> 302 </ul> 303 </div> 304 </div> 305 </div> 306 <?php 307 } 308 309 /** 310 * Format WordPress field values for display. 311 * 312 * @since 8.0.0 313 * 314 * @param string $field_value The field value, as saved in the database. 315 * @param string|int $field_id Optional. ID of the field. 316 * @return string The sanitized WordPress field. 317 */ 318 public static function display_filter( $field_value, $field_id = '' ) { 319 $wp_user_key = self::get_field_settings( $field_id ); 320 321 if ( ! $wp_user_key ) { 322 return ''; 323 } 324 325 if ( 'user_url' === $wp_user_key ) { 326 $sanitized_website = sanitize_user_field( $wp_user_key, $field_value, bp_displayed_user_id(), 'attribute' ); 327 return sprintf( '<a href="%1$s" rel="nofollow">%1$s</a>', $sanitized_website ); 328 } 329 330 return sanitize_user_field( $wp_user_key, $field_value, bp_displayed_user_id(), 'display' ); 331 } 332 } -
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..153cae0cc
- + 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. 11 defined( '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 */ 18 abstract 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 * WordPress field's visibility setting. 38 * 39 * Defaults to 'public'. This property enforces Field's default visibility. 40 * 41 * @since 8.0.0 42 * 43 * @return string The WordPress field's visibility setting. 44 */ 45 public $visibility = 'public'; 46 47 /** 48 * Supported features for the WordPress field type. 49 * 50 * @since 8.0.0 51 * @var bool[] The WordPress field supported features. 52 */ 53 public static $supported_features = array( 54 'switch_fieldtype' => false, 55 'required' => false, 56 'do_autolink' => false, 57 'allow_custom_visibility' => false, 58 'member_types' => false, 59 ); 60 61 /** 62 * Constructor for the WordPress field type. 63 * 64 * @since 8.0.0 65 */ 66 public function __construct() { 67 parent::__construct(); 68 69 /** 70 * Fires inside __construct() method for BP_XProfile_Field_Type_WordPress class. 71 * 72 * @since 8.0.0 73 * 74 * @param BP_XProfile_Field_Type_WordPress $this Instance of the field type object. 75 */ 76 do_action( 'bp_xprofile_field_type_wordpress', $this ); 77 78 // Use the `$wpdb->usermeta` table instead of the $bp->profile->table_name_data one. 79 add_filter( 'bp_xprofile_set_field_data_pre_save', array( $this, 'set_field_value' ), 10, 2 ); 80 81 // Set the supported keys. 82 $this->supported_keys = bp_xprofile_get_wp_user_keys(); 83 } 84 85 /** 86 * Sanitize the user field before inserting it into db. 87 * 88 * @since 8.0.0 89 * 90 * @param string $value The user field value. 91 */ 92 abstract public function sanitize_for_db( $value ); 93 94 /** 95 * Sanitize the user field before displaying it as an attribute. 96 * 97 * @since 8.0.0 98 * 99 * @param string $value The user field value. 100 * @param integer $user_id The user ID. 101 */ 102 abstract public function sanitize_for_output( $value, $user_id = 0 ); 103 104 /** 105 * Sets the WordPress field value. 106 * 107 * @since 8.0.0 108 * 109 * @param boolean $retval Whether to shortcircuit the $bp->profile->table_name_data table. 110 * Default `false`. 111 * @param array $field_args { 112 * An array of arguments. 113 * 114 * @type object $field_type_obj Field type object. 115 * @type BP_XProfile_Field $field Field object. 116 * @type integer $user_id The user ID. 117 * @type mixed $value Value passed to xprofile_set_field_data(). 118 * @type boolean $is_required Whether or not the field is required. 119 * } 120 * @return boolean Whether to shortcircuit the $bp->profile->table_name_data table. 121 */ 122 public function set_field_value( $retval = false, $field_args = array() ) { 123 // Check the wp_user_key is valid and supported. 124 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 ) ) { 125 return false; 126 } 127 128 $wp_user_field_value = $this->sanitize_for_db( $field_args['value'] ); 129 $bp_displayed_user = bp_get_displayed_user(); 130 131 if ( isset( $bp_displayed_user->updated_keys ) ) { 132 $bp_displayed_user->updated_keys[ $this->wp_user_key ] = $wp_user_field_value; 133 $retval = true; 134 } else { 135 $retval = wp_update_user( 136 array( 137 'ID' => (int) $field_args['user_id'], 138 $this->wp_user_key => $wp_user_field_value, 139 ) 140 ); 141 } 142 143 if ( ! is_wp_error( $retval ) ) { 144 $retval = true; 145 } 146 147 return $retval; 148 } 149 150 /** 151 * Gets the WordPress field value during an xProfile fields loop. 152 * 153 * This function is used inside `BP_XProfile_ProfileData::get_data_for_user()` 154 * to include the WordPress field value into the xProfile fields loop. 155 * 156 * @since 8.0.0 157 * 158 * @param integer $user_id The user ID. 159 * @param integer $field_id The xProfile field ID. 160 * @return array An array containing the metadata `id`, `value` and `table_name`. 161 */ 162 public function get_field_value( $user_id, $field_id = 0 ) { 163 global $wpdb; 164 $wp_field = array( 165 'id' => 0, 166 'value' => '', 167 'table_name' => $wpdb->usermeta, 168 ); 169 170 if ( 'user_url' === $this->wp_user_key ) { 171 if ( bp_displayed_user_id() ) { 172 $wp_field['value'] = bp_get_displayed_user()->userdata->{$this->wp_user_key}; 173 } elseif ( $user_id ) { 174 $user = get_user_by( 'id', $user_id ); 175 $wp_field['value'] = $user->{$this->wp_user_key}; 176 } 177 178 $wp_field['id'] = $user_id; 179 $wp_field['table_name'] = $wpdb->users; 180 } else { 181 $umeta_key = $this->wp_user_key; 182 $user_mid = wp_cache_get( $user_id, 'bp_user_mid' ); 183 if ( ! $user_mid ) { 184 $user_mid = array(); 185 } 186 187 if ( ! $user_mid ) { 188 $list_values = bp_get_user_meta( $user_id, $umeta_key ); 189 190 if ( is_array( $list_values ) ) { 191 $wp_field['value'] = reset( $list_values ); 192 $wp_field['id'] = key( $list_values ); 193 194 if ( 0 === $wp_field['id'] ) { 195 /* 196 * We can't just update the WP User Meta cache to key again meta values with meta_ids because of 197 * `return maybe_unserialize( $meta_cache[ $meta_key ][0] );` in `get_metadata_raw()`. 198 */ 199 $user_meta_cache = wp_cache_get( $user_id, 'user_meta' ); 200 201 if ( $user_meta_cache ) { 202 $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 ) ); 203 204 if ( $metas ) { 205 foreach ( $user_meta_cache as $meta_key => $meta_values ) { 206 if ( ! in_array( $meta_key, $this->supported_keys, true ) ) { 207 continue; 208 } 209 210 foreach ( $meta_values as $meta_value ) { 211 $meta_object = wp_list_filter( $metas, array( 'meta_key' => $meta_key, 'meta_value' => $meta_value ) ); 212 213 if ( 1 === count( $meta_object ) ) { 214 $meta_object = reset( $meta_object ); 215 $user_mid[ $meta_key ][ $meta_object->umeta_id ] = $meta_value; 216 217 // Set the meta_id for the requested field. 218 if ( $umeta_key === $meta_key ) { 219 $wp_field['id'] = $meta_object->umeta_id; 220 } 221 } 222 } 223 } 224 } 225 226 // Set the User mid cache. 227 wp_cache_set( $user_id, $user_mid, 'bp_user_mid' ); 228 } 229 } 230 } 231 } 232 233 if ( isset( $user_mid[ $umeta_key ] ) ) { 234 $wp_field['value'] = reset( $user_mid[ $umeta_key ] ); 235 $wp_field['id'] = key( $user_mid[ $umeta_key ] ); 236 } 237 } 238 239 return $wp_field; 240 } 241 } -
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..7a03ae89f 100644
class BP_XProfile_Field { 182 182 $this->type_obj = bp_xprofile_create_field_type( 'textbox' ); 183 183 $this->type_obj->field_obj = $this; 184 184 } 185 186 /** 187 * Fires when the xProfile field object has been constructed. 188 * 189 * @since 8.0.0 190 * 191 * @param BP_XProfile_Field $this The xProfile field object. 192 */ 193 do_action( 'bp_xprofile_field', $this ); 185 194 } 186 195 187 196 /** … … class BP_XProfile_Field { 806 815 */ 807 816 public function get_default_visibility() { 808 817 if ( ! isset( $this->default_visibility ) ) { 809 $this->default_visibility = bp_xprofile_get_meta( $this->id, 'field', 'default_visibility' ); 818 $this->default_visibility = 'public'; 819 $this->visibility = ''; 820 821 if ( isset( $this->type_obj->visibility ) && $this->type_obj->visibility ) { 822 $this->visibility = $this->type_obj->visibility; 823 } 824 825 if ( $this->field_type_supports( 'allow_custom_visibility' ) ) { 826 $this->visibility = bp_xprofile_get_meta( $this->id, 'field', 'default_visibility' ); 827 } 810 828 811 if ( ! $this->default_visibility ) {812 $this->default_visibility = 'public';829 if ( $this->visibility ) { 830 $this->default_visibility = $this->visibility; 813 831 } 814 832 } 815 833 … … class BP_XProfile_Field { 1317 1335 <?php 1318 1336 } 1319 1337 1338 /** 1339 * Gets field type supports. 1340 * 1341 * @since 8.0.0 1342 * 1343 * @return bool[] Supported features. 1344 */ 1345 public function get_field_type_supports() { 1346 $supports = array( 1347 'switch_fieldtype' => true, 1348 'allow_required' => true, 1349 'allow_autolink' => true, 1350 'allow_custom_visibility' => true, 1351 'member_types' => true, 1352 ); 1353 1354 if ( isset( $this->type_obj ) && $this->type_obj ) { 1355 $field_type = $this->type_obj; 1356 1357 if ( isset( $field_type::$supported_features ) ) { 1358 $supports = array_merge( $supports, $field_type::$supported_features ); 1359 } 1360 } 1361 1362 return $supports; 1363 } 1364 1365 /** 1366 * Checks whether the field type supports the requested feature. 1367 * 1368 * @since 8.0.0 1369 * 1370 * @param string $support The name of the feature. 1371 * @return boolean True if the field type supports the feature. False otherwise. 1372 */ 1373 public function field_type_supports( $support = '' ) { 1374 $retval = true; 1375 $features = $this->get_field_type_supports(); 1376 1377 if ( isset( $features[ $support ] ) ) { 1378 $retval = $features[ $support ]; 1379 } 1380 1381 return $retval; 1382 } 1383 1320 1384 /** 1321 1385 * Private method used to display the submit metabox. 1322 1386 * … … class BP_XProfile_Field { 1442 1506 private function member_type_metabox() { 1443 1507 1444 1508 // The primary field is for all, so bail. 1445 if ( 1 === (int) $this->id ) {1509 if ( 1 === (int) $this->id || ! $this->field_type_supports( 'member_types' ) ) { 1446 1510 return; 1447 1511 } 1448 1512 … … class BP_XProfile_Field { 1455 1519 1456 1520 ?> 1457 1521 1458 <div id=" member-types-div" class="postbox">1522 <div id="field-type-member-types" class="postbox"> 1459 1523 <h2><?php _e( 'Member Types', 'buddypress' ); ?></h2> 1460 1524 <div class="inside"> 1461 1525 <p class="description"><?php _e( 'This field should be available to:', 'buddypress' ); ?></p> … … class BP_XProfile_Field { 1496 1560 */ 1497 1561 private function visibility_metabox() { 1498 1562 1499 // Default field cannot have custom visibility.1500 if ( true === $this->is_default_field() ) {1563 // Default field and field types not supporting the feature cannot have custom visibility. 1564 if ( true === $this->is_default_field() || ! $this->field_type_supports( 'allow_custom_visibility' ) ) { 1501 1565 return; 1502 1566 } ?> 1503 1567 1504 <div class="postbox" >1568 <div class="postbox" id="field-type-visibiliy-metabox"> 1505 1569 <h2><label for="default-visibility"><?php esc_html_e( 'Visibility', 'buddypress' ); ?></label></h2> 1506 1570 <div class="inside"> 1507 1571 <div> … … class BP_XProfile_Field { 1545 1609 */ 1546 1610 private function required_metabox() { 1547 1611 1548 // Default field is alwaysrequired.1549 if ( true === $this->is_default_field() ) {1612 // Default field and field types not supporting the feature cannot be required. 1613 if ( true === $this->is_default_field() || ! $this->field_type_supports( 'required' ) ) { 1550 1614 return; 1551 1615 } ?> 1552 1616 1553 <div class="postbox" >1617 <div class="postbox" id="field-type-required-metabox"> 1554 1618 <h2><label for="required"><?php esc_html_e( 'Requirement', 'buddypress' ); ?></label></h2> 1555 1619 <div class="inside"> 1556 1620 <select name="required" id="required"> … … class BP_XProfile_Field { 1571 1635 * @return void If default field id 1. 1572 1636 */ 1573 1637 private function autolink_metabox() { 1574 ?>1575 1638 1576 <div class="postbox"> 1639 // Field types not supporting the feature cannot use autolink. 1640 if ( ! $this->field_type_supports( 'do_autolink' ) ) { 1641 return; 1642 } ?> 1643 1644 <div class="postbox" id="field-type-autolink-metabox"> 1577 1645 <h2><?php esc_html_e( 'Autolink', 'buddypress' ); ?></h2> 1578 1646 <div class="inside"> 1579 1647 <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 { 1606 1674 // Default field cannot change type. 1607 1675 if ( true === $this->is_default_field() ) { 1608 1676 return; 1609 } ?> 1677 } 1678 ?> 1610 1679 1611 1680 <div class="postbox"> 1612 1681 <h2><label for="fieldtype"><?php esc_html_e( 'Type', 'buddypress'); ?></label></h2> 1613 1682 <div class="inside" aria-live="polite" aria-atomic="true" aria-relevant="all"> 1614 <select name="fieldtype" id="fieldtype" onchange="show_options(this.value)"> 1683 <?php if ( ! $this->field_type_supports( 'switch_fieldtype' ) ) : ?> 1684 <input type="text" disabled="true" value="<?php echo esc_attr( $this->type_obj->name ); ?>"> 1685 <input type="hidden" name="fieldtype" id="fieldtype" value="<?php echo esc_attr( $this->type ); ?>"> 1615 1686 1616 <?php bp_xprofile_admin_form_field_types( $this->type ); ?> 1687 <?php else : ?> 1688 <select name="fieldtype" id="fieldtype" onchange="show_options(this.value)"> 1617 1689 1618 </select> 1690 <?php bp_xprofile_admin_form_field_types( $this->type ); ?> 1691 1692 </select> 1693 <?php endif; ?> 1619 1694 1620 1695 <?php 1621 1696 … … class BP_XProfile_Field { 1642 1717 // Nonce. 1643 1718 wp_nonce_field( 'bp_xprofile_admin_field', 'bp_xprofile_admin_field' ); 1644 1719 1645 // Field 1 is the fullname field, which cannot have custom visibility. 1646 if ( false === $this->is_default_field() ) { 1647 return; 1648 } ?> 1720 // Init default field hidden inputs. 1721 $default_field_hidden_inputs = array(); 1722 $hidden_fields = array( 1723 'required' => array( 1724 'name' => 'required', 1725 'id' => 'required', 1726 'value' => '0', 1727 ), 1728 'default_visibility' => array( 1729 'name' => 'default-visibility', 1730 'id' => 'default-visibility', 1731 'value' => $this->get_default_visibility(), 1732 ), 1733 'allow_custom_visibility' => array( 1734 'name' => 'allow-custom-visibility', 1735 'id' => 'allow-custom-visibility', 1736 'value' => 'disabled', 1737 ), 1738 'do_autolink' => array( 1739 'name' => 'do_autolink', 1740 'id' => 'do-autolink', 1741 'value' => '', 1742 ), 1743 ); 1649 1744 1650 <input type="hidden" name="required" id="required" value="1" /> 1651 <input type="hidden" name="fieldtype" id="fieldtype" value="textbox" /> 1745 // Field 1 is the fullname field, which is required. 1746 if ( true === $this->is_default_field() ) { 1747 $default_field_required = $hidden_fields['required']; 1748 $default_field_required['value'] = '1'; 1749 1750 $default_field_hidden_inputs = array( 1751 $default_field_required, 1752 array( 1753 'name' => 'fieldtype', 1754 'id' => 'fieldtype', 1755 'value' => 'textbox', 1756 ), 1757 ); 1758 } 1652 1759 1653 <?php 1760 $supports = $this->get_field_type_supports(); 1761 if ( $supports ) { 1762 foreach ( $supports as $feature => $support ) { 1763 if ( true === $support || in_array( $feature, array( 'switch_fieldtype', 'member_types' ), true ) ) { 1764 continue; 1765 } 1766 1767 $default_field_hidden_inputs[] = $hidden_fields[ $feature ]; 1768 1769 if ( 'allow_custom_visibility' === $feature ) { 1770 $default_field_hidden_inputs[] = $hidden_fields['default_visibility']; 1771 } 1772 } 1773 } 1774 1775 if ( ! $default_field_hidden_inputs ) { 1776 return; 1777 } 1778 1779 foreach ( $default_field_hidden_inputs as $default_field_hidden_input ) { 1780 printf( 1781 '<input type="hidden" name="%1$s" id="%2$s" value="%3$s"/>', 1782 esc_attr( $default_field_hidden_input['name'] ), 1783 esc_attr( $default_field_hidden_input['id'] ), 1784 esc_attr( $default_field_hidden_input['value'] ), 1785 ); 1786 } 1654 1787 } 1655 1788 1656 1789 /** -
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 { 237 237 * and field data. 238 238 * 239 239 * @since 1.2.0 240 * @since 2.4.0 Introduced `$member_type` argument. 241 * @since 8.0.0 Introduced `$hide_field_types` argument. 240 242 * 241 243 * @global object $wpdb WordPress DB access object. 242 244 * … … class BP_XProfile_Group { 256 258 * @type bool $fetch_fields Whether to fetch each group's fields. Default: false. 257 259 * @type bool $fetch_field_data Whether to fetch data for each field. Requires a $user_id. 258 260 * 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. 261 264 * @type bool $update_meta_cache Whether to pre-fetch xprofilemeta for all retrieved groups, fields, 262 265 * and data. Default: true. 263 266 * } … … class BP_XProfile_Group { 278 281 'fetch_visibility_level' => false, 279 282 'exclude_groups' => false, 280 283 'exclude_fields' => false, 284 'hide_field_types' => array(), 281 285 'update_meta_cache' => true, 282 286 ) ); 283 287 … … class BP_XProfile_Group { 338 342 // Pull field objects from the cache. 339 343 $fields = array(); 340 344 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; 342 352 } 343 353 344 354 // Store field IDs for meta cache priming. … … class BP_XProfile_Group { 346 356 347 357 // Maybe fetch field data. 348 358 if ( ! empty( $r['fetch_field_data'] ) ) { 359 $field_type_objects = wp_list_pluck( $fields, 'type_obj', 'id' ); 349 360 350 361 // Get field data for user ID. 351 362 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 ); 353 364 } 354 365 355 366 // 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..618fab6fc 100644
class BP_XProfile_ProfileData { 316 316 * Get a user's profile data for a set of fields. 317 317 * 318 318 * @since 2.0.0 319 * @since 8.0.0 Checks if a null field data is an xProfile WP Field. 320 * Adds a new parameter `$field_type_objects` to pass the list of field type objects. 319 321 * 320 * @param int $user_id ID of user whose data is being queried. 321 * @param array $field_ids Array of field IDs to query for. 322 * @param int $user_id ID of user whose data is being queried. 323 * @param array $field_ids Array of field IDs to query for. 324 * @param array $field_type_objects Array of field type objects keyed by the queried filed IDs. 322 325 * @return array 323 326 */ 324 public static function get_data_for_user( $user_id, $field_ids ) {327 public static function get_data_for_user( $user_id, $field_ids, $field_type_objects = array() ) { 325 328 global $wpdb; 326 329 327 330 $data = array(); … … class BP_XProfile_ProfileData { 339 342 foreach ( $uncached_data as $ud ) { 340 343 $d = new stdClass; 341 344 $d->id = $ud->id; 345 $d->table_name = $bp->profile->table_name_data; 342 346 $d->user_id = $ud->user_id; 343 347 $d->field_id = $ud->field_id; 344 348 $d->value = $ud->value; … … class BP_XProfile_ProfileData { 359 363 // If no value was found, cache an empty item 360 364 // to avoid future cache misses. 361 365 } else { 362 $d = new stdClass; 363 $d->id = ''; 366 $d = new stdClass; 367 368 // Check WordPress if it's a WordPress field. 369 if ( isset( $field_type_objects[ $field_id ]->wp_user_key ) ) { 370 $meta = $field_type_objects[ $field_id ]->get_field_value( $user_id, $field_id ); 371 $d->id = $meta['id']; 372 $d->value = $meta['value']; 373 $d->table_name = $meta['table_name']; 374 375 } else { 376 $d->id = ''; 377 $d->value = ''; 378 } 379 380 $d->table_name = ''; 364 381 $d->user_id = $user_id; 365 382 $d->field_id = $field_id; 366 $d->value = '';367 383 $d->last_updated = ''; 368 384 369 385 wp_cache_set( $cache_key, $d, 'bp_xprofile_data' ); … … class BP_XProfile_ProfileData { 396 412 * Get all of the profile information for a specific user. 397 413 * 398 414 * @since 1.2.0 415 * @since 8.0.0 Checks if a null field data is an xProfile WP Field. 399 416 * 400 417 * @param int $user_id ID of the user. 401 418 * @return array … … class BP_XProfile_ProfileData { 430 447 'field_group_name' => $group->name, 431 448 'field_id' => $field->id, 432 449 'field_type' => $field->type, 433 'field_data' => $field->data->value,434 450 ); 451 452 if ( is_null( $field->data ) ) { 453 if ( 1 === $field->id ) { 454 $profile_data[ $field->name ]['field_data'] = $user->display_name; 455 } elseif ( isset( $field->type_obj ) && $field->type_obj instanceof BP_XProfile_Field_Type && isset( $field->type_obj->wp_user_key ) ) { 456 $meta = $field->type_obj->get_field_value( $user->ID, $field->id ); 457 458 if ( isset( $meta['value'] ) ) { 459 $profile_data[ $field->name ]['field_data'] = $meta['value']; 460 } 461 } else { 462 $profile_data[ $field->name ]['field_data'] = false; 463 } 464 } else { 465 $profile_data[ $field->name ]['field_data'] = $field->data->value; 466 } 435 467 } 436 468 } 437 469 } … … class BP_XProfile_ProfileData { 475 507 * Supports multiple user IDs. 476 508 * 477 509 * @since 1.0.0 510 * @since 8.0.0 Checks if a null field data is an xProfile WP Field. 478 511 * 479 512 * @param int $field_id ID of the field. 480 513 * @param int|array|null $user_ids ID or IDs of user(s). … … class BP_XProfile_ProfileData { 524 557 // No data found for the user, so we fake it to 525 558 // avoid cache misses and PHP notices. 526 559 } else { 527 $d = new stdClass; 528 $d->id = ''; 560 $d = new stdClass; 561 $field_type = bp_xprofile_get_field_type( $field_id ); 562 563 // Check WordPress if it's a WordPress field. 564 if ( isset( $field_type->wp_user_key ) ) { 565 $meta = $field_type->get_field_value( $user_id, $field_id ); 566 $d->id = $meta['id']; 567 $d->value = $meta['value']; 568 $d->table_name = $meta['table_name']; 569 570 } else { 571 $d->id = ''; 572 $d->value = ''; 573 } 574 575 $d->table_name = ''; 529 576 $d->user_id = $id; 530 577 $d->field_id = $field_id; 531 $d->value = '';532 578 $d->last_updated = ''; 533 579 } 534 580 … … class BP_XProfile_ProfileData { 570 616 * Get profile field values by field name and user ID. 571 617 * 572 618 * @since 1.0.0 619 * @deprecated 8.0.0 This function is not used anymore. 573 620 * 574 621 * @param array|string $fields Field(s) to get. 575 622 * @param int|null $user_id User ID to get field data for. 576 623 * @return array|bool 577 624 */ 578 625 public static function get_value_byfieldname( $fields, $user_id = null ) { 626 _deprecated_function( __FUNCTION__, '8.0.0' ); 579 627 global $wpdb; 580 628 581 629 if ( empty( $fields ) ) { -
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 { 272 272 273 273 $r = bp_parse_args( $args['args'], array( 274 274 'profile_group_id' => 0, 275 'user_id' => $user->ID 275 'user_id' => $user->ID, 276 'hide_field_types' => array( 'wp-textbox', 'wp-biography' ), 276 277 ), 'bp_xprofile_user_admin_profile_loop_args' ); 277 278 278 279 // 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() { 50 50 $posted_field_ids = wp_parse_id_list( $_POST['field_ids'] ); 51 51 $is_required = array(); 52 52 53 $bp_displayed_user = bp_get_displayed_user(); 54 $bp_displayed_user->updated_keys = array(); 55 53 56 // Loop through the posted fields formatting any datebox values then validate the field. 54 57 foreach ( (array) $posted_field_ids as $field_id ) { 55 58 bp_xprofile_maybe_format_datebox_post_data( $field_id ); … … function xprofile_screen_edit_profile() { 126 129 */ 127 130 do_action( 'xprofile_updated_profile', bp_displayed_user_id(), $posted_field_ids, $errors, $old_values, $new_values ); 128 131 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 129 150 // Set the feedback messages. 130 151 if ( !empty( $errors ) ) { 131 152 bp_core_add_message( __( 'There was a problem updating some of your profile information. Please try again.', 'buddypress' ), 'error' ); … … function xprofile_screen_edit_profile() { 153 174 * @param string $template Path to the XProfile edit template to load. 154 175 */ 155 176 bp_core_load_template( apply_filters( 'xprofile_template_edit_profile', 'members/single/home' ) ); 156 } 157 No newline at end of file 177 } -
new file tests/phpunit/assets/bptest-xprofile-field-type.php
diff --git tests/phpunit/assets/bptest-xprofile-field-type.php tests/phpunit/assets/bptest-xprofile-field-type.php new file mode 100644 index 000000000..c1feee310
- + 1 <?php 2 3 // Testing Field Type class. 4 class BPTest_XProfile_Field_Type extends BP_XProfile_Field_Type { 5 public $visibility = 'adminsonly'; 6 7 public static $supported_features = array( 8 'required' => true, 9 'do_autolink' => false, 10 'allow_custom_visibility' => false, 11 'member_types' => true, 12 ); 13 14 public function __construct() { 15 parent::__construct(); 16 17 $this->category = _x( 'Single Fields', 'xprofile field type category', 'buddypress' ); 18 $this->name = _x( 'Test Field', 'xprofile field type', 'buddypress' ); 19 20 $this->set_format( '/^.*$/', 'replace' ); 21 } 22 23 public function edit_field_html( array $raw_properties = array() ) { 24 return; 25 } 26 27 public function admin_field_html( array $raw_properties = array() ) { 28 return; 29 } 30 } -
new file tests/phpunit/testcases/xprofile/class-bp-xprofile-field-type-wordpress.php
diff --git tests/phpunit/testcases/xprofile/class-bp-xprofile-field-type-wordpress.php tests/phpunit/testcases/xprofile/class-bp-xprofile-field-type-wordpress.php new file mode 100644 index 000000000..a5fa5cdf4
- + 1 <?php 2 /** 3 * @group xprofile 4 * @group BP_Tests_XProfile_Field_Type_WordPress 5 * @ticket BP7162 6 */ 7 class BP_Tests_XProfile_Field_Type_WordPress extends BP_UnitTestCase { 8 9 public function test_wp_textbox_validate_string() { 10 $field = bp_xprofile_create_field_type( 'wp-textbox' ); 11 $this->assertTrue( $field->is_valid( 'Hello WordPress Fields!' ) ); 12 } 13 14 /** 15 * @group xprofile_set_field_data 16 */ 17 public function test_wp_textbox_set_last_name_field_data() { 18 $user_id = self::factory()->user->create(); 19 $group_id = self::factory()->xprofile_group->create(); 20 $field_id = self::factory()->xprofile_field->create( 21 array( 22 'field_group_id' => $group_id, 23 'type' => 'wp-textbox', 24 'name' => 'WP Last Name', 25 ) 26 ); 27 28 // Set the WP User Key. 29 bp_xprofile_update_meta( $field_id, 'field', 'wp_user_key', 'last_name' ); 30 31 $field_data = xprofile_set_field_data( $field_id, $user_id, 'bar' ); 32 33 $user = get_user_by( 'id', $user_id ); 34 35 $this->assertEquals( 'bar', $user->last_name ); 36 } 37 38 /** 39 * @group bp_xprofile_get_groups 40 */ 41 public function test_wp_textbox_get_user_url_field_data() { 42 $user_id = self::factory()->user->create( 43 array( 44 'user_url' => 'https://buddypress.org', 45 ) 46 ); 47 $group_id = self::factory()->xprofile_group->create(); 48 $field_id = self::factory()->xprofile_field->create( 49 array( 50 'field_group_id' => $group_id, 51 'type' => 'wp-textbox', 52 'name' => 'WP User URL', 53 ) 54 ); 55 56 // Set the WP User Key. 57 bp_xprofile_update_meta( $field_id, 'field', 'wp_user_key', 'user_url' ); 58 59 $groups = bp_xprofile_get_groups( 60 array( 61 'profile_group_id' => $group_id, 62 'user_id' => $user_id, 63 'fetch_fields' => true, 64 'fetch_field_data' => true, 65 ) 66 ); 67 $group = reset( $groups ); 68 $field = reset( $group->fields ); 69 70 $this->assertEquals( 'https://buddypress.org', $field->data->value ); 71 } 72 73 /** 74 * @group xprofile_get_field_data 75 */ 76 public function test_wp_textbox_get_first_name_field_value() { 77 $user_id = self::factory()->user->create( 78 array( 79 'first_name' => 'foo', 80 ) 81 ); 82 $group_id = self::factory()->xprofile_group->create(); 83 $field_id = self::factory()->xprofile_field->create( 84 array( 85 'field_group_id' => $group_id, 86 'type' => 'wp-textbox', 87 'name' => 'WP First Name', 88 ) 89 ); 90 91 // Set the WP User Key. 92 bp_xprofile_update_meta( $field_id, 'field', 'wp_user_key', 'first_name' ); 93 94 $field_data = xprofile_get_field_data( $field_id, $user_id ); 95 96 $this->assertEquals( 'foo', $field_data ); 97 } 98 99 /** 100 * @group bp_member_profile_data 101 * @group bp_get_member_profile_data 102 */ 103 public function test_wp_biography_get_field_value() { 104 global $members_template; 105 $reset_members_template = $members_template; 106 107 $user_id = self::factory()->user->create( 108 array( 109 'description' => 'The BuddyPress community is awesome!', 110 ) 111 ); 112 $group_id = self::factory()->xprofile_group->create(); 113 $field_id = self::factory()->xprofile_field->create( 114 array( 115 'field_group_id' => $group_id, 116 'type' => 'wp-biography', 117 'name' => 'About Me', 118 ) 119 ); 120 121 $members_template = new BP_Core_Members_Template( 122 array( 123 'include' => $user_id, 124 'type' => 'alphabetical', 125 'page' => 1, 126 'per_page' => 1, 127 ) 128 ); 129 130 bp_the_member(); 131 132 $profile_data = bp_get_member_profile_data( 133 array( 134 'field' => 'About Me' 135 ) 136 ); 137 138 $members_template = $reset_members_template; 139 140 $this->assertEquals( 'The BuddyPress community is awesome!', $profile_data ); 141 } 142 } -
tests/phpunit/testcases/xprofile/class-bp-xprofile-field-type.php
diff --git tests/phpunit/testcases/xprofile/class-bp-xprofile-field-type.php tests/phpunit/testcases/xprofile/class-bp-xprofile-field-type.php index 06de7ffda..b199c9583 100644
1 1 <?php 2 // Include the xProfile Test Type 3 include_once BP_TESTS_DIR . 'assets/bptest-xprofile-field-type.php'; 4 2 5 /** 3 6 * @group xprofile 4 7 * @group BP_XProfile_Field_Type 5 8 */ 6 9 class BP_Tests_XProfile_Field_Type extends BP_UnitTestCase { 10 11 public function setUp() { 12 parent::setUp(); 13 14 add_filter( 'bp_xprofile_get_field_types', array( $this, 'get_field_types' ) ); 15 } 16 17 public function tearDown() { 18 parent::tearDown(); 19 20 remove_filter( 'bp_xprofile_get_field_types', array( $this, 'get_field_types' ) ); 21 } 22 7 23 public function test_unregistered_field_type_returns_textbox() { 8 24 $field = bp_xprofile_create_field_type( 'fakeyfield' ); 9 25 $this->assertEquals( get_class( $field ), 'BP_XProfile_Field_Type_Placeholder' ); … … class BP_Tests_XProfile_Field_Type extends BP_UnitTestCase { 183 199 $this->assertTrue( $field->is_valid( '555-2368' ) ); 184 200 $this->assertTrue( $field->is_valid( '(212) 664-7665' ) ); 185 201 } 202 203 /** 204 * @ticket BP7162 205 */ 206 public function test_xprofile_field_type_test_supports() { 207 $group_id = self::factory()->xprofile_group->create(); 208 $field_id = self::factory()->xprofile_field->create( 209 array( 210 'field_group_id' => $group_id, 211 'type' => 'test-field-type', 212 'name' => 'Test Supports', 213 ) 214 ); 215 216 $field = xprofile_get_field( $field_id, null, false ); 217 218 $this->assertTrue( $field->field_type_supports( 'switch_fieldtype' ) ); 219 $this->assertFalse( $field->field_type_supports( 'do_autolink' ) ); 220 $this->assertFalse( $field->field_type_supports( 'allow_custom_visibility' ) ); 221 $this->assertTrue( $field->field_type_supports( 'required' ) ); 222 $this->assertTrue( $field->field_type_supports( 'member_types' ) ); 223 $this->assertEquals( 'adminsonly', $field->get_default_visibility() ); 224 } 225 226 public function get_field_types( $types ) { 227 $types['test-field-type'] = 'BPTest_XProfile_Field_Type'; 228 return $types; 229 } 186 230 }