Ticket #7162: 7162.patch
File 7162.patch, 41.0 KB (added by , 4 years ago) |
---|
-
src/bp-xprofile/bp-xprofile-admin.php
diff --git src/bp-xprofile/bp-xprofile-admin.php src/bp-xprofile/bp-xprofile-admin.php index 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-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..7ba336414 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_set_field_data( $field, $user_id, $value, $is_required = false 462 464 return false; 463 465 } 464 466 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' ); 468 468 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 ); 471 486 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; 473 503 } 474 504 475 505 /** … … function bp_xprofile_personal_data_exporter( $email_address ) { 1357 1387 'done' => true, 1358 1388 ); 1359 1389 } 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 */ 1398 function 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/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(); -
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..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. 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 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. 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 * 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..c8b0257ef 100644
class BP_XProfile_Field { 1317 1317 <?php 1318 1318 } 1319 1319 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 'allo_custom_visibility' => true, 1333 ); 1334 1335 if ( isset( $this->type_obj ) && $this->type_obj ) { 1336 $field_type = $this->type_obj; 1337 $parent_field_type = get_parent_class( $field_type ); 1338 1339 if ( 'BP_XProfile_Field_Type_WordPress' === $parent_field_type && isset( $field_type::$supported_features ) ) { 1340 $supports = array_merge( $supports, $field_type::$supported_features ); 1341 } 1342 } 1343 1344 return $supports; 1345 } 1346 1347 /** 1348 * Checks whether the field type supports the requested feature. 1349 * 1350 * @since 8.0.0 1351 * 1352 * @param string $support The name of the feature. 1353 * @return boolean True if the field type supports the feature. False otherwise. 1354 */ 1355 public function field_type_supports( $support = '' ) { 1356 $retval = true; 1357 $features = $this->get_field_type_supports(); 1358 1359 if ( isset( $features[ $support ] ) ) { 1360 $retval = $features[ $support ]; 1361 } 1362 1363 return $retval; 1364 } 1365 1320 1366 /** 1321 1367 * Private method used to display the submit metabox. 1322 1368 * … … class BP_XProfile_Field { 1496 1542 */ 1497 1543 private function visibility_metabox() { 1498 1544 1499 // Default field cannot have custom visibility.1500 if ( true === $this->is_default_field() ) {1545 // Default field and field types not supporting the feature cannot have custom visibility. 1546 if ( true === $this->is_default_field() || ! $this->field_type_supports( 'allow_custom_visibility' ) ) { 1501 1547 return; 1502 1548 } ?> 1503 1549 … … class BP_XProfile_Field { 1545 1591 */ 1546 1592 private function required_metabox() { 1547 1593 1548 // Default field is alwaysrequired.1549 if ( true === $this->is_default_field() ) {1594 // Default field and field types not supporting the feature cannot be required. 1595 if ( true === $this->is_default_field() || ! $this->field_type_supports( 'required' ) ) { 1550 1596 return; 1551 1597 } ?> 1552 1598 … … class BP_XProfile_Field { 1571 1617 * @return void If default field id 1. 1572 1618 */ 1573 1619 private function autolink_metabox() { 1574 ?> 1620 1621 // Field types not supporting the feature cannot use autolink. 1622 if ( ! $this->field_type_supports( 'do_autolink' ) ) { 1623 return; 1624 } ?> 1575 1625 1576 1626 <div class="postbox"> 1577 1627 <h2><?php esc_html_e( 'Autolink', 'buddypress' ); ?></h2> … … class BP_XProfile_Field { 1606 1656 // Default field cannot change type. 1607 1657 if ( true === $this->is_default_field() ) { 1608 1658 return; 1609 } ?> 1659 } 1660 ?> 1610 1661 1611 1662 <div class="postbox"> 1612 1663 <h2><label for="fieldtype"><?php esc_html_e( 'Type', 'buddypress'); ?></label></h2> 1613 1664 <div class="inside" aria-live="polite" aria-atomic="true" aria-relevant="all"> 1614 <select name="fieldtype" id="fieldtype" onchange="show_options(this.value)"> 1665 <?php if ( ! $this->field_type_supports( 'switch_fieldtype' ) ) : ?> 1666 <input type="text" disabled="true" value="<?php echo esc_attr( $this->type_obj->name ); ?>"> 1667 <input type="hidden" name="fieldtype" id="fieldtype" value="<?php echo esc_attr( $this->type ); ?>"> 1615 1668 1616 <?php bp_xprofile_admin_form_field_types( $this->type ); ?> 1669 <?php else : ?> 1670 <select name="fieldtype" id="fieldtype" onchange="show_options(this.value)"> 1617 1671 1618 </select> 1672 <?php bp_xprofile_admin_form_field_types( $this->type ); ?> 1673 1674 </select> 1675 <?php endif; ?> 1619 1676 1620 1677 <?php 1621 1678 … … class BP_XProfile_Field { 1642 1699 // Nonce. 1643 1700 wp_nonce_field( 'bp_xprofile_admin_field', 'bp_xprofile_admin_field' ); 1644 1701 1645 // Field 1 is the fullname field, which cannot have custom visibility. 1646 if ( false === $this->is_default_field() ) { 1647 return; 1648 } ?> 1702 // Init default field hidden inputs. 1703 $default_field_hidden_inputs = array(); 1704 $hidden_fields = array( 1705 'required' => array( 1706 'name' => 'required', 1707 'id' => 'required', 1708 'value' => '0', 1709 ), 1710 'default_visibility' => array( 1711 'name' => 'default-visibility', 1712 'id' => 'default-visibility', 1713 'value' => 'public', 1714 ), 1715 'allow_custom_visibility' => array( 1716 'name' => 'allow-custom-visibility', 1717 'id' => 'allow-custom-visibility', 1718 'value' => 'disabled', 1719 ), 1720 'do_autolink' => array( 1721 'name' => 'do_autolink', 1722 'id' => 'do-autolink', 1723 'value' => '', 1724 ), 1725 ); 1726 1727 // Field 1 is the fullname field, which is required. 1728 if ( true === $this->is_default_field() ) { 1729 $default_field_required = $hidden_fields['required']; 1730 $default_field_required['value'] = '1'; 1731 1732 $default_field_hidden_inputs = array( 1733 $default_field_required, 1734 array( 1735 'name' => 'fieldtype', 1736 'id' => 'fieldtype', 1737 'value' => 'textbox', 1738 ), 1739 ); 1740 } 1649 1741 1650 <input type="hidden" name="required" id="required" value="1" /> 1651 <input type="hidden" name="fieldtype" id="fieldtype" value="textbox" /> 1742 $supports = $this->get_field_type_supports(); 1743 if ( $supports ) { 1744 foreach ( $supports as $feature => $support ) { 1745 if ( true === $support || 'switch_fieldtype' === $feature ) { 1746 continue; 1747 } 1652 1748 1653 <?php 1749 $default_field_hidden_inputs[] = $hidden_fields[ $feature ]; 1750 1751 if ( 'allow_custom_visibility' === $feature ) { 1752 $default_field_hidden_inputs[] = $hidden_fields['default_visibility']; 1753 } 1754 } 1755 } 1756 1757 if ( ! $default_field_hidden_inputs ) { 1758 return; 1759 } 1760 1761 foreach ( $default_field_hidden_inputs as $default_field_hidden_input ) { 1762 printf( 1763 '<input type="hidden" name="%1$s" id="%2$s" value="%3$s"/>', 1764 esc_attr( $default_field_hidden_input['name'] ), 1765 esc_attr( $default_field_hidden_input['id'] ), 1766 esc_attr( $default_field_hidden_input['value'] ), 1767 ); 1768 } 1654 1769 } 1655 1770 1656 1771 /** -
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..f70cc2b59 100644
class BP_XProfile_Group { 346 346 347 347 // Maybe fetch field data. 348 348 if ( ! empty( $r['fetch_field_data'] ) ) { 349 $field_type_objects = wp_list_pluck( $fields, 'type_obj', 'id' ); 349 350 350 351 // Get field data for user ID. 351 352 if ( ! empty( $field_ids ) && ! empty( $r['user_id'] ) ) { 352 $field_data = BP_XProfile_ProfileData::get_data_for_user( $r['user_id'], $field_ids );353 $field_data = BP_XProfile_ProfileData::get_data_for_user( $r['user_id'], $field_ids, $field_type_objects ); 353 354 } 354 355 355 356 // 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 { 321 321 * @param array $field_ids Array of field IDs to query for. 322 322 * @return array 323 323 */ 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() ) { 325 325 global $wpdb; 326 326 327 327 $data = array(); … … class BP_XProfile_ProfileData { 339 339 foreach ( $uncached_data as $ud ) { 340 340 $d = new stdClass; 341 341 $d->id = $ud->id; 342 $d->table_name = $bp->profile->table_name_data; 342 343 $d->user_id = $ud->user_id; 343 344 $d->field_id = $ud->field_id; 344 345 $d->value = $ud->value; … … class BP_XProfile_ProfileData { 359 360 // If no value was found, cache an empty item 360 361 // to avoid future cache misses. 361 362 } 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 = ''; 364 378 $d->user_id = $user_id; 365 379 $d->field_id = $field_id; 366 $d->value = '';367 380 $d->last_updated = ''; 368 381 369 382 wp_cache_set( $cache_key, $d, 'bp_xprofile_data' ); -
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 }