[ Index ]

PHP Cross Reference of BuddyPress

title

Body

[close]

/src/bp-xprofile/classes/ -> class-bp-xprofile-field.php (source)

   1  <?php
   2  /**
   3   * BuddyPress XProfile Classes.
   4   *
   5   * @package BuddyPress
   6   * @subpackage XProfileClasses
   7   * @since 1.0.0
   8   */
   9  
  10  // Exit if accessed directly.
  11  defined( 'ABSPATH' ) || exit;
  12  
  13  /**
  14   * Class to help set up XProfile fields.
  15   *
  16   * @since 1.0.0
  17   */
  18  class BP_XProfile_Field {
  19  
  20      /**
  21       * Field ID.
  22       *
  23       * @since 1.0.0
  24       * @var int ID of field.
  25       */
  26      public $id;
  27  
  28      /**
  29       * Field group ID.
  30       *
  31       * @since 1.0.0
  32       * @var int Field group ID for field.
  33       */
  34      public $group_id;
  35  
  36      /**
  37       * Field parent ID.
  38       *
  39       * @since 1.0.0
  40       * @var int Parent ID of field.
  41       */
  42      public $parent_id;
  43  
  44      /**
  45       * Field type.
  46       *
  47       * @since 1.0.0
  48       * @var string Field type.
  49       */
  50      public $type;
  51  
  52      /**
  53       * Field name.
  54       *
  55       * @since 1.0.0
  56       * @var string Field name.
  57       */
  58      public $name;
  59  
  60      /**
  61       * Field description.
  62       *
  63       * @since 1.0.0
  64       * @var string Field description.
  65       */
  66      public $description;
  67  
  68      /**
  69       * Required field?
  70       *
  71       * @since 1.0.0
  72       * @var bool Is field required to be filled out?
  73       */
  74      public $is_required;
  75  
  76      /**
  77       * Deletable field?
  78       *
  79       * @since 1.0.0
  80       * @var int Can field be deleted?
  81       */
  82      public $can_delete = '1';
  83  
  84      /**
  85       * Field position.
  86       *
  87       * @since 1.0.0
  88       * @var int Field position.
  89       */
  90      public $field_order;
  91  
  92      /**
  93       * Option order.
  94       *
  95       * @since 1.0.0
  96       * @var int Option order.
  97       */
  98      public $option_order;
  99  
 100      /**
 101       * Order child fields.
 102       *
 103       * @since 1.0.0
 104       * @var string Order child fields by.
 105       */
 106      public $order_by;
 107  
 108      /**
 109       * Is this the default option?
 110       *
 111       * @since 1.0.0
 112       * @var bool Is this the default option for this field?
 113       */
 114      public $is_default_option;
 115  
 116      /**
 117       * Field data visibility.
 118       *
 119       * @since 1.9.0
 120       * @since 2.4.0 Property marked protected. Now accessible by magic method or by `get_default_visibility()`.
 121       * @var string Default field data visibility.
 122       */
 123      protected $default_visibility;
 124  
 125      /**
 126       * Is the visibility able to be modified?
 127       *
 128       * @since 2.3.0
 129       * @since 2.4.0 Property marked protected. Now accessible by magic method or by `get_allow_custom_visibility()`.
 130       * @var string Members are allowed/disallowed to modify data visibility.
 131       */
 132      protected $allow_custom_visibility;
 133  
 134      /**
 135       * Whether values from this field are autolinked to directory searches.
 136       *
 137       * @since 2.5.0
 138       * @var bool
 139       */
 140      public $do_autolink;
 141  
 142      /**
 143       * Field type option.
 144       *
 145       * @since 2.0.0
 146       * @var BP_XProfile_Field_Type Field type object used for validation.
 147       */
 148      public $type_obj = null;
 149  
 150      /**
 151       * Field data for user ID.
 152       *
 153       * @since 2.0.0
 154       * @var BP_XProfile_ProfileData Field data for user ID.
 155       */
 156      public $data;
 157  
 158      /**
 159       * Member types to which the profile field should be applied.
 160       *
 161       * @since 2.4.0
 162       * @var array Array of member types.
 163       */
 164      protected $member_types;
 165  
 166      /**
 167       * Initialize and/or populate profile field.
 168       *
 169       * @since 1.1.0
 170       *
 171       * @param int|null $id Field ID.
 172       * @param int|null $user_id User ID.
 173       * @param bool     $get_data Get data.
 174       */
 175  	public function __construct( $id = null, $user_id = null, $get_data = true ) {
 176  
 177          if ( ! empty( $id ) ) {
 178              $this->populate( $id, $user_id, $get_data );
 179  
 180          // Initialize the type obj to prevent fatals when creating new profile fields.
 181          } else {
 182              $this->type_obj            = bp_xprofile_create_field_type( 'textbox' );
 183              $this->type_obj->field_obj = $this;
 184          }
 185      }
 186  
 187      /**
 188       * Populate a profile field object.
 189       *
 190       * @since 1.1.0
 191       *
 192       * @global object $wpdb
 193       * @global object $userdata
 194       *
 195       * @param int      $id Field ID.
 196       * @param int|null $user_id User ID.
 197       * @param bool     $get_data Get data.
 198       */
 199  	public function populate( $id, $user_id = null, $get_data = true ) {
 200          global $wpdb, $userdata;
 201  
 202          if ( empty( $user_id ) ) {
 203              $user_id = isset( $userdata->ID ) ? $userdata->ID : 0;
 204          }
 205  
 206          $field = wp_cache_get( $id, 'bp_xprofile_fields' );
 207          if ( false === $field ) {
 208              $bp = buddypress();
 209  
 210              $field = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$bp->profile->table_name_fields} WHERE id = %d", $id ) );
 211  
 212              if ( ! $field ) {
 213                  return false;
 214              }
 215  
 216              wp_cache_add( $id, $field, 'bp_xprofile_fields' );
 217          }
 218  
 219          $this->fill_data( $field );
 220  
 221          if ( ! empty( $get_data ) && ! empty( $user_id ) ) {
 222              $this->data = $this->get_field_data( $user_id );
 223          }
 224      }
 225  
 226      /**
 227       * Retrieve a `BP_XProfile_Field` instance.
 228       *
 229       * @since 2.4.0
 230       * @since 2.8.0 Added `$user_id` and `$get_data` parameters.
 231       *
 232       * @static
 233       *
 234       * @param int      $field_id ID of the field.
 235       * @param int|null $user_id  Optional. ID of the user associated with the field.
 236       *                           Ignored if `$get_data` is false. If `$get_data` is
 237       *                           true, but no `$user_id` is provided, defaults to
 238       *                           logged-in user ID.
 239       * @param bool     $get_data Whether to fetch data for the specified `$user_id`.
 240       * @return BP_XProfile_Field|false Field object if found, otherwise false.
 241       */
 242  	public static function get_instance( $field_id, $user_id = null, $get_data = true ) {
 243          global $wpdb;
 244  
 245          $field_id = (int) $field_id;
 246          if ( ! $field_id ) {
 247              return false;
 248          }
 249  
 250          return new self( $field_id, $user_id, $get_data );
 251      }
 252  
 253      /**
 254       * Fill object vars based on data passed to the method.
 255       *
 256       * @since 2.4.0
 257       *
 258       * @param array|object $args Array or object representing the `BP_XProfile_Field` properties.
 259       *                           Generally, this is a row from the fields database table.
 260       */
 261  	public function fill_data( $args ) {
 262          if ( is_object( $args ) ) {
 263              $args = (array) $args;
 264          }
 265  
 266          $int_fields = array(
 267              'id', 'is_required', 'group_id', 'parent_id', 'is_default_option',
 268              'field_order', 'option_order', 'can_delete'
 269          );
 270  
 271          foreach ( $args as $k => $v ) {
 272              if ( 'name' === $k || 'description' === $k ) {
 273                  $v = stripslashes( $v );
 274              }
 275  
 276              // Cast numeric strings as integers.
 277              if ( true === in_array( $k, $int_fields ) ) {
 278                  $v = (int) $v;
 279              }
 280  
 281              $this->{$k} = $v;
 282          }
 283  
 284          // Create the field type and store a reference back to this object.
 285          $this->type_obj            = bp_xprofile_create_field_type( $this->type );
 286          $this->type_obj->field_obj = $this;
 287      }
 288  
 289      /**
 290       * Magic getter.
 291       *
 292       * @since 2.4.0
 293       *
 294       * @param string $key Property name.
 295       * @return string|null
 296       */
 297  	public function __get( $key ) {
 298          switch ( $key ) {
 299              case 'default_visibility' :
 300                  return $this->get_default_visibility();
 301                  break;
 302  
 303              case 'allow_custom_visibility' :
 304                  return $this->get_allow_custom_visibility();
 305                  break;
 306          }
 307      }
 308  
 309      /**
 310       * Magic issetter.
 311       *
 312       * @since 2.4.0
 313       *
 314       * @param string $key Property name.
 315       * @return bool
 316       */
 317  	public function __isset( $key ) {
 318          switch ( $key ) {
 319              // Backward compatibility for when these were public methods.
 320              case 'allow_custom_visibility' :
 321              case 'default_visibility' :
 322                  return true;
 323                  break;
 324          }
 325      }
 326  
 327      /**
 328       * Delete a profile field.
 329       *
 330       * @since 1.1.0
 331       *
 332       * @global object $wpdb
 333       *
 334       * @param boolean $delete_data Whether or not to delete data.
 335       * @return boolean
 336       */
 337  	public function delete( $delete_data = false ) {
 338          global $wpdb;
 339  
 340          // Prevent deletion if no ID is present.
 341          // Prevent deletion by url when can_delete is false.
 342          // Prevent deletion of option 1 since this invalidates fields with options.
 343          if ( empty( $this->id ) || empty( $this->can_delete ) || ( $this->parent_id && $this->option_order == 1 ) ) {
 344              return false;
 345          }
 346  
 347          /**
 348           * Fires before the current field instance gets deleted.
 349           *
 350           * @since 3.0.0
 351           *
 352           * @param BP_XProfile_Field $this        Current instance of the field being deleted. Passed by reference.
 353           * @param bool              $delete_data Whether or not to delete data.
 354           */
 355          do_action_ref_array( 'xprofile_field_before_delete', array( &$this, $delete_data ) );
 356  
 357          $bp  = buddypress();
 358          $sql = $wpdb->prepare( "DELETE FROM {$bp->profile->table_name_fields} WHERE id = %d OR parent_id = %d", $this->id, $this->id );
 359  
 360          if ( ! $wpdb->query( $sql ) ) {
 361              return false;
 362          }
 363  
 364          // Delete all metadata for this field.
 365          bp_xprofile_delete_meta( $this->id, 'field' );
 366  
 367          // Delete the data in the DB for this field.
 368          if ( true === $delete_data ) {
 369              BP_XProfile_ProfileData::delete_for_field( $this->id );
 370          }
 371  
 372          /**
 373           * Fires after the current field instance gets deleted.
 374           *
 375           * @since 3.0.0
 376           *
 377           * @param BP_XProfile_Field $this        Current instance of the field being deleted. Passed by reference.
 378           * @param bool              $delete_data Whether or not to delete data.
 379           */
 380          do_action_ref_array( 'xprofile_field_after_delete', array( &$this, $delete_data ) );
 381  
 382          return true;
 383      }
 384  
 385      /**
 386       * Save a profile field.
 387       *
 388       * @since 1.1.0
 389       *
 390       * @global object $wpdb
 391       *
 392       * @return boolean
 393       */
 394  	public function save() {
 395          global $wpdb;
 396  
 397          $bp = buddypress();
 398  
 399          $this->group_id     = apply_filters( 'xprofile_field_group_id_before_save',     $this->group_id,     $this->id );
 400          $this->parent_id    = apply_filters( 'xprofile_field_parent_id_before_save',    $this->parent_id,    $this->id );
 401          $this->type         = apply_filters( 'xprofile_field_type_before_save',         $this->type,         $this->id );
 402          $this->name         = apply_filters( 'xprofile_field_name_before_save',         $this->name,         $this->id );
 403          $this->description  = apply_filters( 'xprofile_field_description_before_save',  $this->description,  $this->id );
 404          $this->is_required  = apply_filters( 'xprofile_field_is_required_before_save',  $this->is_required,  $this->id );
 405          $this->order_by        = apply_filters( 'xprofile_field_order_by_before_save',     $this->order_by,     $this->id );
 406          $this->field_order  = apply_filters( 'xprofile_field_field_order_before_save',  $this->field_order,  $this->id );
 407          $this->option_order = apply_filters( 'xprofile_field_option_order_before_save', $this->option_order, $this->id );
 408          $this->can_delete   = apply_filters( 'xprofile_field_can_delete_before_save',   $this->can_delete,   $this->id );
 409          $this->type_obj     = bp_xprofile_create_field_type( $this->type );
 410  
 411          /**
 412           * Fires before the current field instance gets saved.
 413           *
 414           * Please use this hook to filter the properties above. Each part will be passed in.
 415           *
 416           * @since 1.0.0
 417           *
 418           * @param BP_XProfile_Field $this Current instance of the field being saved.
 419           */
 420          do_action_ref_array( 'xprofile_field_before_save', array( $this ) );
 421  
 422          $is_new_field = is_null( $this->id );
 423  
 424          if ( ! $is_new_field ) {
 425              $sql = $wpdb->prepare( "UPDATE {$bp->profile->table_name_fields} SET group_id = %d, parent_id = 0, type = %s, name = %s, description = %s, is_required = %d, order_by = %s, field_order = %d, option_order = %d, can_delete = %d, is_default_option = %d WHERE id = %d", $this->group_id, $this->type, $this->name, $this->description, $this->is_required, $this->order_by, $this->field_order, $this->option_order, $this->can_delete, $this->is_default_option, $this->id );
 426          } else {
 427              $sql = $wpdb->prepare( "INSERT INTO {$bp->profile->table_name_fields} (group_id, parent_id, type, name, description, is_required, order_by, field_order, option_order, can_delete, is_default_option ) VALUES ( %d, %d, %s, %s, %s, %d, %s, %d, %d, %d, %d )", $this->group_id, $this->parent_id, $this->type, $this->name, $this->description, $this->is_required, $this->order_by, $this->field_order, $this->option_order, $this->can_delete, $this->is_default_option );
 428          }
 429  
 430          /**
 431           * Check for null so field options can be changed without changing any
 432           * other part of the field. The described situation will return 0 here.
 433           */
 434          if ( $wpdb->query( $sql ) !== null ) {
 435  
 436              if ( $is_new_field ) {
 437                  $this->id = $wpdb->insert_id;
 438              }
 439  
 440              // Only do this if we are editing an existing field.
 441              if ( ! $is_new_field ) {
 442  
 443                  /**
 444                   * Remove any radio or dropdown options for this
 445                   * field. They will be re-added if needed.
 446                   * This stops orphan options if the user changes a
 447                   * field from a radio button field to a text box.
 448                   */
 449                  $this->delete_children();
 450              }
 451  
 452              /**
 453               * Check to see if this is a field with child options.
 454               * We need to add the options to the db, if it is.
 455               */
 456              if ( $this->type_obj->supports_options ) {
 457  
 458                  $parent_id = $this->id;
 459  
 460                  // Allow plugins to filter the field's child options (i.e. the items in a selectbox).
 461                  $post_option  = ! empty( $_POST["{$this->type}_option"]           ) ? $_POST["{$this->type}_option"]           : '';
 462                  $post_default = ! empty( $_POST["isDefault_{$this->type}_option"] ) ? $_POST["isDefault_{$this->type}_option"] : '';
 463  
 464                  /**
 465                   * Filters the submitted field option value before saved.
 466                   *
 467                   * @since 1.5.0
 468                   *
 469                   * @param string            $post_option Submitted option value.
 470                   * @param BP_XProfile_Field $type        Current field type being saved for.
 471                   */
 472                  $options      = apply_filters( 'xprofile_field_options_before_save', $post_option,  $this->type );
 473  
 474                  /**
 475                   * Filters the default field option value before saved.
 476                   *
 477                   * @since 1.5.0
 478                   *
 479                   * @param string            $post_default Default option value.
 480                   * @param BP_XProfile_Field $type         Current field type being saved for.
 481                   */
 482                  $defaults     = apply_filters( 'xprofile_field_default_before_save', $post_default, $this->type );
 483  
 484                  $counter = 1;
 485                  if ( !empty( $options ) ) {
 486                      foreach ( (array) $options as $option_key => $option_value ) {
 487                          $is_default = 0;
 488  
 489                          if ( is_array( $defaults ) ) {
 490                              if ( isset( $defaults[ $option_key ] ) ) {
 491                                  $is_default = 1;
 492                              }
 493                          } else {
 494                              if ( (int) $defaults == $option_key ) {
 495                                  $is_default = 1;
 496                              }
 497                          }
 498  
 499                          if ( '' != $option_value ) {
 500                              $sql = $wpdb->prepare( "INSERT INTO {$bp->profile->table_name_fields} (group_id, parent_id, type, name, description, is_required, option_order, is_default_option) VALUES (%d, %d, 'option', %s, '', 0, %d, %d)", $this->group_id, $parent_id, $option_value, $counter, $is_default );
 501                              if ( ! $wpdb->query( $sql ) ) {
 502                                  return false;
 503                              }
 504                          }
 505  
 506                          $counter++;
 507                      }
 508                  }
 509              }
 510  
 511              /**
 512               * Fires after the current field instance gets saved.
 513               *
 514               * @since 1.0.0
 515               *
 516               * @param BP_XProfile_Field $this Current instance of the field being saved.
 517               */
 518              do_action_ref_array( 'xprofile_field_after_save', array( $this ) );
 519  
 520              // Recreate type_obj in case someone changed $this->type via a filter.
 521              $this->type_obj            = bp_xprofile_create_field_type( $this->type );
 522              $this->type_obj->field_obj = $this;
 523  
 524              return $this->id;
 525          } else {
 526              return false;
 527          }
 528      }
 529  
 530      /**
 531       * Get field data for a user ID.
 532       *
 533       * @since 1.2.0
 534       *
 535       * @param int $user_id ID of the user to get field data for.
 536       * @return BP_XProfile_ProfileData
 537       */
 538  	public function get_field_data( $user_id = 0 ) {
 539          return new BP_XProfile_ProfileData( $this->id, $user_id );
 540      }
 541  
 542      /**
 543       * Get all child fields for this field ID.
 544       *
 545       * @since 1.2.0
 546       *
 547       * @global object $wpdb
 548       *
 549       * @param bool $for_editing Whether or not the field is for editing.
 550       * @return array
 551       */
 552  	public function get_children( $for_editing = false ) {
 553          global $wpdb;
 554  
 555          // This is done here so we don't have problems with sql injection.
 556          if ( empty( $for_editing ) && ( 'asc' === $this->order_by ) ) {
 557              $sort_sql = 'ORDER BY name ASC';
 558          } elseif ( empty( $for_editing ) && ( 'desc' === $this->order_by ) ) {
 559              $sort_sql = 'ORDER BY name DESC';
 560          } else {
 561              $sort_sql = 'ORDER BY option_order ASC';
 562          }
 563  
 564          // This eliminates a problem with getting all fields when there is no
 565          // id for the object.
 566          if ( empty( $this->id ) ) {
 567              $parent_id = -1;
 568          } else {
 569              $parent_id = $this->id;
 570          }
 571  
 572          $bp  = buddypress();
 573          $sql = $wpdb->prepare( "SELECT * FROM {$bp->profile->table_name_fields} WHERE parent_id = %d AND group_id = %d {$sort_sql}", $parent_id, $this->group_id );
 574  
 575          $children = $wpdb->get_results( $sql );
 576  
 577          /**
 578           * Filters the found children for a field.
 579           *
 580           * @since 1.2.5
 581           * @since 3.0.0 Added the `$this` parameter.
 582           *
 583           * @param object            $children    Found children for a field.
 584           * @param bool              $for_editing Whether or not the field is for editing.
 585           * @param BP_XProfile_Field $this        Field object
 586           */
 587          return apply_filters( 'bp_xprofile_field_get_children', $children, $for_editing, $this );
 588      }
 589  
 590      /**
 591       * Delete all field children for this field.
 592       *
 593       * @since 1.2.0
 594       *
 595       * @global object $wpdb
 596       */
 597  	public function delete_children() {
 598          global $wpdb;
 599  
 600          $bp  = buddypress();
 601          $sql = $wpdb->prepare( "DELETE FROM {$bp->profile->table_name_fields} WHERE parent_id = %d", $this->id );
 602  
 603          $wpdb->query( $sql );
 604      }
 605  
 606      /**
 607       * Gets the member types to which this field should be available.
 608       *
 609       * Will not return inactive member types, even if associated metadata is found.
 610       *
 611       * 'null' is a special pseudo-type, which represents users that do not have a member type.
 612       *
 613       * @since 2.4.0
 614       *
 615       * @return array Array of member type names.
 616       */
 617  	public function get_member_types() {
 618          if ( ! is_null( $this->member_types ) ) {
 619              return $this->member_types;
 620          }
 621  
 622          $raw_types = bp_xprofile_get_meta( $this->id, 'field', 'member_type', false );
 623  
 624          // If `$raw_types` is not an array, it probably means this is a new field (id=0).
 625          if ( ! is_array( $raw_types ) ) {
 626              $raw_types = array();
 627          }
 628  
 629          // If '_none' is found in the array, it overrides all types.
 630          $types = array();
 631          if ( ! in_array( '_none', $raw_types ) ) {
 632              $registered_types = bp_get_member_types();
 633  
 634              // Eliminate invalid member types saved in the database.
 635              foreach ( $raw_types as $raw_type ) {
 636                  // 'null' is a special case - it represents users without a type.
 637                  if ( 'null' === $raw_type || isset( $registered_types[ $raw_type ] ) ) {
 638                      $types[] = $raw_type;
 639                  }
 640              }
 641  
 642              // If no member types have been saved, interpret as *all* member types.
 643              if ( empty( $types ) ) {
 644                  $types = array_values( $registered_types );
 645  
 646                  // + the "null" type, ie users without a type.
 647                  $types[] = 'null';
 648              }
 649          }
 650  
 651          /**
 652           * Filters the member types to which an XProfile object should be applied.
 653           *
 654           * @since 2.4.0
 655           *
 656           * @param array             $types Member types.
 657           * @param BP_XProfile_Field $field Field object.
 658           */
 659          $this->member_types = apply_filters( 'bp_xprofile_field_member_types', $types, $this );
 660  
 661          return $this->member_types;
 662      }
 663  
 664      /**
 665       * Sets the member types for this field.
 666       *
 667       * @since 2.4.0
 668       *
 669       * @param array $member_types Array of member types. Can include 'null' (users with no type) in addition to any
 670       *                            registered types.
 671       * @param bool  $append       Whether to append to existing member types. If false, all existing member type
 672       *                            associations will be deleted before adding your `$member_types`. Default false.
 673       * @return array Member types for the current field, after being saved.
 674       */
 675  	public function set_member_types( $member_types, $append = false ) {
 676          // Unset invalid member types.
 677          $types = array();
 678          foreach ( $member_types as $member_type ) {
 679              // 'null' is a special case - it represents users without a type.
 680              if ( 'null' === $member_type || bp_get_member_type_object( $member_type ) ) {
 681                  $types[] = $member_type;
 682              }
 683          }
 684  
 685          // When `$append` is false, delete all existing types before adding new ones.
 686          if ( ! $append ) {
 687              bp_xprofile_delete_meta( $this->id, 'field', 'member_type' );
 688  
 689              /*
 690               * We interpret an empty array as disassociating the field from all types. This is
 691               * represented internally with the '_none' flag.
 692               */
 693              if ( empty( $types ) ) {
 694                  bp_xprofile_add_meta( $this->id, 'field', 'member_type', '_none' );
 695              }
 696          }
 697  
 698          /*
 699           * Unrestricted fields are represented in the database as having no 'member_type'.
 700           * We detect whether a field is being set to unrestricted by checking whether the
 701           * list of types passed to the method is the same as the list of registered types,
 702           * plus the 'null' pseudo-type.
 703           */
 704          $_rtypes  = bp_get_member_types();
 705          $rtypes   = array_values( $_rtypes );
 706          $rtypes[] = 'null';
 707  
 708          sort( $types );
 709          sort( $rtypes );
 710  
 711          // Only save if this is a restricted field.
 712          if ( $types !== $rtypes ) {
 713              // Save new types.
 714              foreach ( $types as $type ) {
 715                  bp_xprofile_add_meta( $this->id, 'field', 'member_type', $type );
 716              }
 717          }
 718  
 719          // Reset internal cache of member types.
 720          $this->member_types = null;
 721  
 722          /**
 723           * Fires after a field's member types have been updated.
 724           *
 725           * @since 2.4.0
 726           *
 727           * @param BP_XProfile_Field $this Field object.
 728           */
 729          do_action( 'bp_xprofile_field_set_member_type', $this );
 730  
 731          // Refetch fresh items from the database.
 732          return $this->get_member_types();
 733      }
 734  
 735      /**
 736       * Gets a label representing the field's member types.
 737       *
 738       * This label is displayed alongside the field's name on the Profile Fields Dashboard panel.
 739       *
 740       * @since 2.4.0
 741       *
 742       * @return string
 743       */
 744  	public function get_member_type_label() {
 745          // Field 1 is always displayed to everyone, so never gets a label.
 746          if ( 1 == $this->id ) {
 747              return '';
 748          }
 749  
 750          // Return an empty string if no member types are registered.
 751          $all_types = bp_get_member_types();
 752          if ( empty( $all_types ) ) {
 753              return '';
 754          }
 755  
 756          $member_types = $this->get_member_types();
 757  
 758          // If the field applies to all member types, show no message.
 759          $all_types[] = 'null';
 760          if ( array_values( $all_types ) == $member_types ) {
 761              return '';
 762          }
 763  
 764          $label = '';
 765          if ( ! empty( $member_types ) ) {
 766              $has_null = false;
 767              $member_type_labels = array();
 768              foreach ( $member_types as $member_type ) {
 769                  if ( 'null' === $member_type ) {
 770                      $has_null = true;
 771                      continue;
 772                  } else {
 773                      $mt_obj = bp_get_member_type_object( $member_type );
 774                      $member_type_labels[] = $mt_obj->labels['name'];
 775                  }
 776              }
 777  
 778              // Alphabetical sort.
 779              natcasesort( $member_type_labels );
 780              $member_type_labels = array_values( $member_type_labels );
 781  
 782              // Add the 'null' option to the end of the list.
 783              if ( $has_null ) {
 784                  $member_type_labels[] = __( 'Users with no member type', 'buddypress' );
 785              }
 786  
 787              /* translators: %s: comma separated list of member types */
 788              $label = sprintf( __( '(Member types: %s)', 'buddypress' ), implode( ', ', array_map( 'esc_html', $member_type_labels ) ) );
 789          } else {
 790              $label = '<span class="member-type-none-notice">' . __( '(Unavailable to all members)', 'buddypress' ) . '</span>';
 791          }
 792  
 793          return $label;
 794      }
 795  
 796      /**
 797       * Get the field's default visibility setting.
 798       *
 799       * Lazy-loaded to reduce overhead.
 800       *
 801       * Defaults to 'public' if no visibility setting is found in the database.
 802       *
 803       * @since 2.4.0
 804       *
 805       * @return string
 806       */
 807  	public function get_default_visibility() {
 808          if ( ! isset( $this->default_visibility ) ) {
 809              $this->default_visibility = bp_xprofile_get_meta( $this->id, 'field', 'default_visibility' );
 810  
 811              if ( ! $this->default_visibility ) {
 812                  $this->default_visibility = 'public';
 813              }
 814          }
 815  
 816          return $this->default_visibility;
 817      }
 818  
 819      /**
 820       * Get whether the field's default visibility can be overridden by users.
 821       *
 822       * Lazy-loaded to reduce overhead.
 823       *
 824       * Defaults to 'allowed'.
 825       *
 826       * @since 4.4.0
 827       *
 828       * @return string 'disabled' or 'allowed'.
 829       */
 830  	public function get_allow_custom_visibility() {
 831          if ( ! isset( $this->allow_custom_visibility ) ) {
 832              $allow_custom_visibility = bp_xprofile_get_meta( $this->id, 'field', 'allow_custom_visibility' );
 833  
 834              if ( 'disabled' === $allow_custom_visibility ) {
 835                  $this->allow_custom_visibility = 'disabled';
 836              } else {
 837                  $this->allow_custom_visibility = 'allowed';
 838              }
 839          }
 840  
 841          return $this->allow_custom_visibility;
 842      }
 843  
 844      /**
 845       * Get whether the field values should be auto-linked to a directory search.
 846       *
 847       * Lazy-loaded to reduce overhead.
 848       *
 849       * Defaults to true for multi and default fields, false for single fields.
 850       *
 851       * @since 2.5.0
 852       *
 853       * @return bool
 854       */
 855  	public function get_do_autolink() {
 856          if ( ! isset( $this->do_autolink ) ) {
 857              $do_autolink = bp_xprofile_get_meta( $this->id, 'field', 'do_autolink' );
 858  
 859              if ( '' === $do_autolink ) {
 860                  $this->do_autolink = $this->type_obj->supports_options;
 861              } else {
 862                  $this->do_autolink = 'on' === $do_autolink;
 863              }
 864          }
 865  
 866          /**
 867           * Filters the autolink property of the field.
 868           *
 869           * @since 6.0.0
 870           *
 871           * @param bool              $do_autolink The autolink property of the field.
 872           * @param BP_XProfile_Field $this Field object.
 873           */
 874          return apply_filters( 'bp_xprofile_field_do_autolink', $this->do_autolink, $this );
 875      }
 876  
 877      /* Static Methods ********************************************************/
 878  
 879      /**
 880       * Get the type for provided field ID.
 881       *
 882       * @param int $field_id Field ID to get type of.
 883       * @return bool|null|string
 884       */
 885  	public static function get_type( $field_id = 0 ) {
 886          global $wpdb;
 887  
 888          // Bail if no field ID.
 889          if ( empty( $field_id ) ) {
 890              return false;
 891          }
 892  
 893          $bp   = buddypress();
 894          $sql  = $wpdb->prepare( "SELECT type FROM {$bp->profile->table_name_fields} WHERE id = %d", $field_id );
 895          $type = $wpdb->get_var( $sql );
 896  
 897          // Return field type.
 898          if ( ! empty( $type ) ) {
 899              return $type;
 900          }
 901  
 902          return false;
 903      }
 904  
 905      /**
 906       * Delete all fields in a field group.
 907       *
 908       * @since 1.2.0
 909       *
 910       * @global object $wpdb
 911       *
 912       * @param int $group_id ID of the field group to delete fields from.
 913       * @return boolean
 914       */
 915  	public static function delete_for_group( $group_id = 0 ) {
 916          global $wpdb;
 917  
 918          // Bail if no group ID.
 919          if ( empty( $group_id ) ) {
 920              return false;
 921          }
 922  
 923          $bp      = buddypress();
 924          $sql     = $wpdb->prepare( "DELETE FROM {$bp->profile->table_name_fields} WHERE group_id = %d", $group_id );
 925          $deleted = $wpdb->get_var( $sql );
 926  
 927          // Return true if fields were deleted.
 928          if ( false !== $deleted ) {
 929              return true;
 930          }
 931  
 932          return false;
 933      }
 934  
 935      /**
 936       * Get field ID from field name.
 937       *
 938       * @since 1.5.0
 939       *
 940       * @global object $wpdb
 941       *
 942       * @param string $field_name Name of the field to query the ID for.
 943       * @return int|null Field ID on success; null on failure.
 944       */
 945  	public static function get_id_from_name( $field_name = '' ) {
 946          global $wpdb;
 947  
 948          $bp = buddypress();
 949  
 950          if ( empty( $bp->profile->table_name_fields ) || empty( $field_name ) ) {
 951              return false;
 952          }
 953  
 954          $id = bp_core_get_incremented_cache( $field_name, 'bp_xprofile_fields_by_name' );
 955          if ( false === $id ) {
 956              $sql = $wpdb->prepare( "SELECT id FROM {$bp->profile->table_name_fields} WHERE name = %s AND parent_id = 0", $field_name );
 957              $id = $wpdb->get_var( $sql );
 958              bp_core_set_incremented_cache( $field_name, 'bp_xprofile_fields_by_name', $id );
 959          }
 960  
 961          return is_numeric( $id ) ? (int) $id : $id;
 962      }
 963  
 964      /**
 965       * Update field position and/or field group when relocating.
 966       *
 967       * @since 1.5.0
 968       *
 969       * @global object $wpdb
 970       *
 971       * @param int      $field_id       ID of the field to update.
 972       * @param int|null $position       Field position to update.
 973       * @param int|null $field_group_id ID of the field group.
 974       * @return boolean
 975       */
 976  	public static function update_position( $field_id, $position = null, $field_group_id = null ) {
 977          global $wpdb;
 978  
 979          // Bail if invalid position or field group.
 980          if ( ! is_numeric( $position ) || ! is_numeric( $field_group_id ) ) {
 981              return false;
 982          }
 983  
 984          // Get table name and field parent.
 985          $table_name = buddypress()->profile->table_name_fields;
 986          $sql        = $wpdb->prepare( "UPDATE {$table_name} SET field_order = %d, group_id = %d WHERE id = %d", $position, $field_group_id, $field_id );
 987          $parent     = $wpdb->query( $sql );
 988  
 989          $retval = false;
 990  
 991          // Update $field_id with new $position and $field_group_id.
 992          if ( ! empty( $parent ) && ! is_wp_error( $parent ) ) {
 993  
 994              // Update any children of this $field_id.
 995              $sql = $wpdb->prepare( "UPDATE {$table_name} SET group_id = %d WHERE parent_id = %d", $field_group_id, $field_id );
 996              $wpdb->query( $sql );
 997  
 998              // Invalidate profile field and group query cache.
 999              wp_cache_delete( $field_id, 'bp_xprofile_fields' );
1000  
1001              $retval = $parent;
1002          }
1003  
1004          bp_core_reset_incrementor( 'bp_xprofile_groups' );
1005  
1006          return $retval;
1007      }
1008  
1009      /**
1010       * Gets the IDs of fields applicable for a given member type or array of member types.
1011       *
1012       * @since 2.4.0
1013       *
1014       * @param string|array $member_types Member type or array of member types. Use 'any' to return unrestricted
1015       *                                   fields (those available for anyone, regardless of member type).
1016       * @return array Multi-dimensional array, with field IDs as top-level keys, and arrays of member types
1017       *               associated with each field as values.
1018       */
1019  	public static function get_fields_for_member_type( $member_types ) {
1020          global $wpdb;
1021  
1022          $fields = array();
1023  
1024          if ( empty( $member_types ) ) {
1025              $member_types = array( 'any' );
1026          } elseif ( ! is_array( $member_types ) ) {
1027              $member_types = array( $member_types );
1028          }
1029  
1030          $bp = buddypress();
1031  
1032          // Pull up all recorded field member type data.
1033          $mt_meta = wp_cache_get( 'field_member_types', 'bp_xprofile' );
1034          if ( false === $mt_meta ) {
1035              $mt_meta = $wpdb->get_results( "SELECT object_id, meta_value FROM {$bp->profile->table_name_meta} WHERE meta_key = 'member_type' AND object_type = 'field'" );
1036              wp_cache_set( 'field_member_types', $mt_meta, 'bp_xprofile' );
1037          }
1038  
1039          // Keep track of all fields with recorded member_type metadata.
1040          $all_recorded_field_ids = wp_list_pluck( $mt_meta, 'object_id' );
1041  
1042          // Sort member_type matches in arrays, keyed by field_id.
1043          foreach ( $mt_meta as $_mt_meta ) {
1044              if ( ! isset( $fields[ $_mt_meta->object_id ] ) ) {
1045                  $fields[ $_mt_meta->object_id ] = array();
1046              }
1047  
1048              $fields[ $_mt_meta->object_id ][] = $_mt_meta->meta_value;
1049          }
1050  
1051          /*
1052           * Filter out fields that don't match any passed types, or those marked '_none'.
1053           * The 'any' type is implicitly handled here: it will match no types.
1054           */
1055          foreach ( $fields as $field_id => $field_types ) {
1056              if ( ! array_intersect( $field_types, $member_types ) ) {
1057                  unset( $fields[ $field_id ] );
1058              }
1059          }
1060  
1061          // Any fields with no member_type metadata are available to all member types.
1062          if ( ! in_array( '_none', $member_types ) ) {
1063              if ( ! empty( $all_recorded_field_ids ) ) {
1064                  $all_recorded_field_ids_sql = implode( ',', array_map( 'absint', $all_recorded_field_ids ) );
1065                  $unrestricted_field_ids = $wpdb->get_col( "SELECT id FROM {$bp->profile->table_name_fields} WHERE id NOT IN ({$all_recorded_field_ids_sql})" );
1066              } else {
1067                  $unrestricted_field_ids = $wpdb->get_col( "SELECT id FROM {$bp->profile->table_name_fields}" );
1068              }
1069  
1070              // Append the 'null' pseudo-type.
1071              $all_member_types   = bp_get_member_types();
1072              $all_member_types   = array_values( $all_member_types );
1073              $all_member_types[] = 'null';
1074  
1075              foreach ( $unrestricted_field_ids as $unrestricted_field_id ) {
1076                  $fields[ $unrestricted_field_id ] = $all_member_types;
1077              }
1078          }
1079  
1080          return $fields;
1081      }
1082  
1083      /**
1084       * Validate form field data on submission.
1085       *
1086       * @since 2.2.0
1087       *
1088       * @global $message
1089       *
1090       * @return boolean
1091       */
1092  	public static function admin_validate() {
1093          global $message;
1094  
1095          // Check field name.
1096          if ( ! isset( $_POST['title'] ) || ( '' === $_POST['title'] ) ) {
1097              $message = esc_html__( 'Profile fields must have a name.', 'buddypress' );
1098              return false;
1099          }
1100  
1101          // Check field requirement.
1102          if ( ! isset( $_POST['required'] ) ) {
1103              $message = esc_html__( 'Profile field requirement is missing.', 'buddypress' );
1104              return false;
1105          }
1106  
1107          // Check field type.
1108          if ( empty( $_POST['fieldtype'] ) ) {
1109              $message = esc_html__( 'Profile field type is missing.', 'buddypress' );
1110              return false;
1111          }
1112  
1113          // Check that field is of valid type.
1114          if ( ! in_array( $_POST['fieldtype'], array_keys( bp_xprofile_get_field_types() ), true ) ) {
1115              /* translators: %s: field type name */
1116              $message = sprintf( esc_html__( 'The profile field type %s is not registered.', 'buddypress' ), '<code>' . esc_attr( $_POST['fieldtype'] ) . '</code>' );
1117              return false;
1118          }
1119  
1120          // Get field type so we can check for and validate any field options.
1121          $field_type = bp_xprofile_create_field_type( $_POST['fieldtype'] );
1122  
1123          // Field type requires options.
1124          if ( true === $field_type->supports_options ) {
1125  
1126              // Build the field option key.
1127              $option_name = sanitize_key( $_POST['fieldtype'] ) . '_option';
1128  
1129              // Check for missing or malformed options.
1130              if ( empty( $_POST[ $option_name ] ) || ! is_array( $_POST[ $option_name ] ) ) {
1131                  $message = esc_html__( 'These field options are invalid.', 'buddypress' );
1132                  return false;
1133              }
1134  
1135              // Trim out empty field options.
1136              $field_values  = array_values( $_POST[ $option_name ] );
1137              $field_options = array_map( 'sanitize_text_field', $field_values );
1138              $field_count   = count( $field_options );
1139  
1140              // Check for missing or malformed options.
1141              if ( 0 === $field_count ) {
1142                  /* translators: %s: field type name */
1143                  $message = sprintf( esc_html__( '%s require at least one option.', 'buddypress' ), $field_type->name );
1144                  return false;
1145              }
1146  
1147              // If only one option exists, it cannot be an empty string.
1148              if ( ( 1 === $field_count ) && ( '' === $field_options[0] ) ) {
1149                  /* translators: %s: field type name */
1150                  $message = sprintf( esc_html__( '%s require at least one option.', 'buddypress' ), $field_type->name );
1151                  return false;
1152              }
1153          }
1154  
1155          return true;
1156      }
1157  
1158      /**
1159       * Save miscellaneous settings for this field.
1160       *
1161       * Some field types have type-specific settings, which are saved here.
1162       *
1163       * @since 2.7.0
1164       *
1165       * @param array $settings Array of settings.
1166       */
1167  	public function admin_save_settings( $settings ) {
1168          return $this->type_obj->admin_save_settings( $this->id, $settings );
1169      }
1170  
1171      /**
1172       * Populates the items for radio buttons, checkboxes, and dropdown boxes.
1173       */
1174  	public function render_admin_form_children() {
1175          foreach ( array_keys( bp_xprofile_get_field_types() ) as $field_type ) {
1176              $type_obj = bp_xprofile_create_field_type( $field_type );
1177              $type_obj->admin_new_field_html( $this );
1178          }
1179      }
1180  
1181      /**
1182       * Oupput the admin form for this field.
1183       *
1184       * @since 1.9.0
1185       *
1186       * @param string $message Message to display.
1187       */
1188  	public function render_admin_form( $message = '' ) {
1189  
1190          // Users Admin URL.
1191          $users_url = bp_get_admin_url( 'users.php' );
1192  
1193          // Add New.
1194          if ( empty( $this->id ) ) {
1195              $title  = __( 'Add New Field', 'buddypress' );
1196              $button    = __( 'Save',          'buddypress' );
1197              $action = add_query_arg( array(
1198                  'page'     => 'bp-profile-setup',
1199                  'mode'     => 'add_field',
1200                  'group_id' => (int) $this->group_id
1201              ), $users_url . '#tabs-' . (int) $this->group_id );
1202  
1203              if ( !empty( $_POST['saveField'] ) ) {
1204                  $this->name        = $_POST['title'];
1205                  $this->description = $_POST['description'];
1206                  $this->is_required = $_POST['required'];
1207                  $this->type        = $_POST['fieldtype'];
1208                  $this->field_order = $_POST['field_order'];
1209  
1210                  if ( ! empty( $_POST["sort_order_{$this->type}"] ) ) {
1211                      $this->order_by = $_POST["sort_order_{$this->type}"];
1212                  }
1213              }
1214  
1215          // Edit.
1216          } else {
1217              $title  = __( 'Edit Field', 'buddypress' );
1218              $button    = __( 'Update',     'buddypress' );
1219              $action = add_query_arg( array(
1220                  'page'     => 'bp-profile-setup',
1221                  'mode'     => 'edit_field',
1222                  'group_id' => (int) $this->group_id,
1223                  'field_id' => (int) $this->id
1224              ), $users_url . '#tabs-' . (int) $this->group_id );
1225          } ?>
1226  
1227          <div class="wrap">
1228  
1229              <h1 class="wp-heading-inline"><?php echo esc_html( $title ); ?></h1>
1230              <hr class="wp-header-end">
1231  
1232              <?php if ( !empty( $message ) ) : ?>
1233  
1234                  <div id="message" class="error fade notice is-dismissible">
1235                      <p><?php echo esc_html( $message ); ?></p>
1236                  </div>
1237  
1238              <?php endif; ?>
1239  
1240              <form id="bp-xprofile-add-field" action="<?php echo esc_url( $action ); ?>" method="post">
1241                  <div id="poststuff">
1242                      <div id="post-body" class="metabox-holder columns-<?php echo ( 1 == get_current_screen()->get_columns() ) ? '1' : '2'; ?>">
1243                          <div id="post-body-content">
1244  
1245                              <?php
1246  
1247                              // Output the name & description fields.
1248                              $this->name_and_description(); ?>
1249  
1250                          </div><!-- #post-body-content -->
1251  
1252                          <div id="postbox-container-1" class="postbox-container">
1253  
1254                              <?php
1255  
1256                              // Output the sumbit metabox.
1257                              $this->submit_metabox( $button );
1258  
1259                              // Output the required metabox.
1260                              $this->required_metabox();
1261  
1262                              // Output the Member Types metabox.
1263                              $this->member_type_metabox();
1264  
1265                              // Output the field visibility metaboxes.
1266                              $this->visibility_metabox();
1267  
1268                              // Output the autolink metabox.
1269                              $this->autolink_metabox();
1270  
1271  
1272                              /**
1273                               * Fires after XProfile Field sidebar metabox.
1274                               *
1275                               * @since 2.2.0
1276                               *
1277                               * @param BP_XProfile_Field $this Current XProfile field.
1278                               */
1279                              do_action( 'xprofile_field_after_sidebarbox', $this ); ?>
1280  
1281                          </div>
1282  
1283                          <div id="postbox-container-2" class="postbox-container">
1284  
1285                              <?php
1286  
1287                              /**
1288                               * Fires before XProfile Field content metabox.
1289                               *
1290                               * @since 2.3.0
1291                               *
1292                               * @param BP_XProfile_Field $this Current XProfile field.
1293                               */
1294                              do_action( 'xprofile_field_before_contentbox', $this );
1295  
1296                              // Output the field attributes metabox.
1297                              $this->type_metabox();
1298  
1299                              // Output hidden inputs for default field.
1300                              $this->default_field_hidden_inputs();
1301  
1302                              /**
1303                               * Fires after XProfile Field content metabox.
1304                               *
1305                               * @since 2.2.0
1306                               *
1307                               * @param BP_XProfile_Field $this Current XProfile field.
1308                               */
1309                              do_action( 'xprofile_field_after_contentbox', $this ); ?>
1310  
1311                          </div>
1312                      </div><!-- #post-body -->
1313                  </div><!-- #poststuff -->
1314              </form>
1315          </div>
1316  
1317      <?php
1318      }
1319  
1320      /**
1321       * Private method used to display the submit metabox.
1322       *
1323       * @since 2.3.0
1324       *
1325       * @param string $button_text Text to put on button.
1326       */
1327  	private function submit_metabox( $button_text = '' ) {
1328  
1329          // Setup the URL for deleting
1330          $users_url  = bp_get_admin_url( 'users.php' );
1331          $cancel_url = add_query_arg( array(
1332              'page' => 'bp-profile-setup'
1333          ), $users_url );
1334  
1335  
1336          // Delete.
1337          if ( $this->can_delete ) {
1338              $delete_url = wp_nonce_url( add_query_arg( array(
1339                  'page'     => 'bp-profile-setup',
1340                  'mode'     => 'delete_field',
1341                  'field_id' => (int) $this->id
1342              ), $users_url ), 'bp_xprofile_delete_field-' . $this->id, 'bp_xprofile_delete_field' );
1343          }
1344          /**
1345           * Fires before XProfile Field submit metabox.
1346           *
1347           * @since 2.1.0
1348           *
1349           * @param BP_XProfile_Field $this Current XProfile field.
1350           */
1351          do_action( 'xprofile_field_before_submitbox', $this ); ?>
1352  
1353          <div id="submitdiv" class="postbox">
1354              <h2><?php esc_html_e( 'Submit', 'buddypress' ); ?></h2>
1355              <div class="inside">
1356                  <div id="submitcomment" class="submitbox">
1357                      <div id="major-publishing-actions">
1358  
1359                          <?php
1360  
1361                          /**
1362                           * Fires at the beginning of the XProfile Field publishing actions section.
1363                           *
1364                           * @since 2.1.0
1365                           *
1366                           * @param BP_XProfile_Field $this Current XProfile field.
1367                           */
1368                          do_action( 'xprofile_field_submitbox_start', $this ); ?>
1369  
1370                          <input type="hidden" name="field_order" id="field_order" value="<?php echo esc_attr( $this->field_order ); ?>" />
1371  
1372                          <?php if ( ! empty( $button_text ) ) : ?>
1373  
1374                              <div id="publishing-action">
1375                                  <input type="submit" name="saveField" value="<?php echo esc_attr( $button_text ); ?>" class="button-primary" />
1376                              </div>
1377  
1378                          <?php endif; ?>
1379  
1380                          <div id="delete-action">
1381                              <?php if ( ! empty( $this->id ) && isset( $delete_url ) ) : ?>
1382                                  <a href="<?php echo esc_url( $delete_url ); ?>" class="submitdelete deletion"><?php esc_html_e( 'Delete', 'buddypress' ); ?></a>
1383                              <?php endif; ?>
1384  
1385                              <div><a href="<?php echo esc_url( $cancel_url ); ?>" class="deletion"><?php esc_html_e( 'Cancel', 'buddypress' ); ?></a></div>
1386                          </div>
1387  
1388                          <?php wp_nonce_field( 'xprofile_delete_option' ); ?>
1389  
1390                          <div class="clear"></div>
1391                      </div>
1392                  </div>
1393              </div>
1394          </div>
1395  
1396          <?php
1397  
1398          /**
1399           * Fires after XProfile Field submit metabox.
1400           *
1401           * @since 2.1.0
1402           *
1403           * @param BP_XProfile_Field $this Current XProfile field.
1404           */
1405          do_action( 'xprofile_field_after_submitbox', $this );
1406      }
1407  
1408      /**
1409       * Private method used to output field name and description fields.
1410       *
1411       * @since 2.3.0
1412       */
1413  	private function name_and_description() {
1414      ?>
1415  
1416          <div id="titlediv">
1417              <div class="titlewrap">
1418                  <label id="title-prompt-text" for="title"><?php echo esc_html_x( 'Name (required)', 'XProfile admin edit field', 'buddypress' ); ?></label>
1419                  <input type="text" name="title" id="title" value="<?php echo esc_attr( $this->name ); ?>" autocomplete="off" />
1420              </div>
1421          </div>
1422  
1423          <div class="postbox">
1424              <h2><?php echo esc_html_x( 'Description', 'XProfile admin edit field', 'buddypress' ); ?></h2>
1425              <div class="inside">
1426                  <label for="description" class="screen-reader-text"><?php
1427                      /* translators: accessibility text */
1428                      esc_html_e( 'Add description', 'buddypress' );
1429                  ?></label>
1430                  <textarea name="description" id="description" rows="8" cols="60"><?php echo esc_textarea( $this->description ); ?></textarea>
1431              </div>
1432          </div>
1433  
1434      <?php
1435      }
1436  
1437      /**
1438       * Private method used to output field Member Type metabox.
1439       *
1440       * @since 2.4.0
1441       */
1442  	private function member_type_metabox() {
1443  
1444          // The primary field is for all, so bail.
1445          if ( 1 === (int) $this->id ) {
1446              return;
1447          }
1448  
1449          // Bail when no member types are registered.
1450          if ( ! $member_types = bp_get_member_types( array(), 'objects' ) ) {
1451              return;
1452          }
1453  
1454          $field_member_types = $this->get_member_types();
1455  
1456          ?>
1457  
1458          <div id="member-types-div" class="postbox">
1459              <h2><?php _e( 'Member Types', 'buddypress' ); ?></h2>
1460              <div class="inside">
1461                  <p class="description"><?php _e( 'This field should be available to:', 'buddypress' ); ?></p>
1462  
1463                  <ul>
1464                      <?php foreach ( $member_types as $member_type ) : ?>
1465                      <li>
1466                          <label for="member-type-<?php echo $member_type->labels['name']; ?>">
1467                              <input name="member-types[]" id="member-type-<?php echo $member_type->labels['name']; ?>" class="member-type-selector" type="checkbox" value="<?php echo $member_type->name; ?>" <?php checked( in_array( $member_type->name, $field_member_types ) ); ?>/>
1468                              <?php echo $member_type->labels['name']; ?>
1469                          </label>
1470                      </li>
1471                      <?php endforeach; ?>
1472  
1473                      <li>
1474                          <label for="member-type-none">
1475                              <input name="member-types[]" id="member-type-none" class="member-type-selector" type="checkbox" value="null" <?php checked( in_array( 'null', $field_member_types ) ); ?>/>
1476                              <?php _e( 'Users with no member type', 'buddypress' ); ?>
1477                          </label>
1478                      </li>
1479  
1480                  </ul>
1481                  <p class="description member-type-none-notice<?php if ( ! empty( $field_member_types ) ) : ?> hide<?php endif; ?>"><?php _e( 'Unavailable to all members.', 'buddypress' ) ?></p>
1482              </div>
1483  
1484              <input type="hidden" name="has-member-types" value="1" />
1485          </div>
1486  
1487          <?php
1488      }
1489  
1490      /**
1491       * Private method used to output field visibility metaboxes.
1492       *
1493       * @since 2.3.0
1494       *
1495       * @return void If default field id 1.
1496       */
1497  	private function visibility_metabox() {
1498  
1499          // Default field cannot have custom visibility.
1500          if ( true === $this->is_default_field() ) {
1501              return;
1502          } ?>
1503  
1504          <div class="postbox">
1505              <h2><label for="default-visibility"><?php esc_html_e( 'Visibility', 'buddypress' ); ?></label></h2>
1506              <div class="inside">
1507                  <div>
1508                      <select name="default-visibility" id="default-visibility">
1509  
1510                          <?php foreach( bp_xprofile_get_visibility_levels() as $level ) : ?>
1511  
1512                              <option value="<?php echo esc_attr( $level['id'] ); ?>" <?php selected( $this->get_default_visibility(), $level['id'] ); ?>>
1513                                  <?php echo esc_html( $level['label'] ); ?>
1514                              </option>
1515  
1516                          <?php endforeach ?>
1517  
1518                      </select>
1519                  </div>
1520  
1521                  <div>
1522                      <ul>
1523                          <li>
1524                              <input type="radio" id="allow-custom-visibility-allowed" name="allow-custom-visibility" value="allowed" <?php checked( $this->get_allow_custom_visibility(), 'allowed' ); ?> />
1525                              <label for="allow-custom-visibility-allowed"><?php esc_html_e( 'Allow members to override', 'buddypress' ); ?></label>
1526                          </li>
1527                          <li>
1528                              <input type="radio" id="allow-custom-visibility-disabled" name="allow-custom-visibility" value="disabled" <?php checked( $this->get_allow_custom_visibility(), 'disabled' ); ?> />
1529                              <label for="allow-custom-visibility-disabled"><?php esc_html_e( 'Enforce field visibility', 'buddypress' ); ?></label>
1530                          </li>
1531                      </ul>
1532                  </div>
1533              </div>
1534          </div>
1535  
1536          <?php
1537      }
1538  
1539      /**
1540       * Output the metabox for setting if field is required or not.
1541       *
1542       * @since 2.3.0
1543       *
1544       * @return void If default field.
1545       */
1546  	private function required_metabox() {
1547  
1548          // Default field is always required.
1549          if ( true === $this->is_default_field() ) {
1550              return;
1551          } ?>
1552  
1553          <div class="postbox">
1554              <h2><label for="required"><?php esc_html_e( 'Requirement', 'buddypress' ); ?></label></h2>
1555              <div class="inside">
1556                  <select name="required" id="required">
1557                      <option value="0"<?php selected( $this->is_required, '0' ); ?>><?php esc_html_e( 'Not Required', 'buddypress' ); ?></option>
1558                      <option value="1"<?php selected( $this->is_required, '1' ); ?>><?php esc_html_e( 'Required',     'buddypress' ); ?></option>
1559                  </select>
1560              </div>
1561          </div>
1562  
1563      <?php
1564      }
1565  
1566      /**
1567       * Private method used to output autolink metabox.
1568       *
1569       * @since 2.5.0
1570       *
1571       * @return void If default field id 1.
1572       */
1573  	private function autolink_metabox() {
1574          ?>
1575  
1576          <div class="postbox">
1577              <h2><?php esc_html_e( 'Autolink', 'buddypress' ); ?></h2>
1578              <div class="inside">
1579                  <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>
1580  
1581                  <p>
1582                      <label for="do-autolink" class="screen-reader-text"><?php
1583                          /* translators: accessibility text */
1584                          esc_html_e( 'Autolink status for this field', 'buddypress' );
1585                      ?></label>
1586                      <select name="do_autolink" id="do-autolink">
1587                          <option value="on" <?php selected( $this->get_do_autolink() ); ?>><?php esc_html_e( 'Enabled', 'buddypress' ); ?></option>
1588                          <option value="" <?php selected( $this->get_do_autolink(), false ); ?>><?php esc_html_e( 'Disabled', 'buddypress' ); ?></option>
1589                      </select>
1590                  </p>
1591              </div>
1592          </div>
1593  
1594          <?php
1595      }
1596  
1597      /**
1598       * Output the metabox for setting what type of field this is.
1599       *
1600       * @since 2.3.0
1601       *
1602       * @return void If default field.
1603       */
1604  	private function type_metabox() {
1605  
1606          // Default field cannot change type.
1607          if ( true === $this->is_default_field() ) {
1608              return;
1609          } ?>
1610  
1611          <div class="postbox">
1612              <h2><label for="fieldtype"><?php esc_html_e( 'Type', 'buddypress'); ?></label></h2>
1613              <div class="inside" aria-live="polite" aria-atomic="true" aria-relevant="all">
1614                  <select name="fieldtype" id="fieldtype" onchange="show_options(this.value)">
1615  
1616                      <?php bp_xprofile_admin_form_field_types( $this->type ); ?>
1617  
1618                  </select>
1619  
1620                  <?php
1621  
1622                  // Deprecated filter, don't use. Go look at {@link BP_XProfile_Field_Type::admin_new_field_html()}.
1623                  do_action( 'xprofile_field_additional_options', $this );
1624  
1625                  $this->render_admin_form_children(); ?>
1626  
1627              </div>
1628          </div>
1629  
1630      <?php
1631      }
1632  
1633      /**
1634       * Output hidden fields used by default field.
1635       *
1636       * @since 2.3.0
1637       *
1638       * @return void If not default field.
1639       */
1640  	private function default_field_hidden_inputs() {
1641  
1642          // Nonce.
1643          wp_nonce_field( 'bp_xprofile_admin_field', 'bp_xprofile_admin_field' );
1644  
1645          // Field 1 is the fullname field, which cannot have custom visibility.
1646          if ( false === $this->is_default_field() ) {
1647              return;
1648          } ?>
1649  
1650          <input type="hidden" name="required"  id="required"  value="1"       />
1651          <input type="hidden" name="fieldtype" id="fieldtype" value="textbox" />
1652  
1653          <?php
1654      }
1655  
1656      /**
1657       * Return if a field ID is the default field.
1658       *
1659       * @since 2.3.0
1660       *
1661       * @param int $field_id ID of field to check.
1662       * @return bool
1663       */
1664  	private function is_default_field( $field_id = 0 ) {
1665  
1666          // Fallback to current field ID if none passed.
1667          if ( empty( $field_id ) ) {
1668              $field_id = $this->id;
1669          }
1670  
1671          // Compare & return.
1672          return (bool) ( 1 === (int) $field_id );
1673      }
1674  }


Generated: Wed Dec 2 01:01:35 2020 Cross-referenced by PHPXref 0.7.1