[ Index ]

PHP Cross Reference of BuddyPress

title

Body

[close]

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

   1  <?php
   2  /**
   3   * BuddyPress XProfile Classes.
   4   *
   5   * @package BuddyPress
   6   * @subpackage XProfileClasses
   7   * @since 2.0.0
   8   */
   9  
  10  // Exit if accessed directly.
  11  defined( 'ABSPATH' ) || exit;
  12  
  13  /**
  14   * Represents a type of XProfile field and holds meta information about the type of value that it accepts.
  15   *
  16   * @since 2.0.0
  17   */
  18  abstract class BP_XProfile_Field_Type {
  19  
  20      /**
  21       * Validation regex rules for field type.
  22       *
  23       * @since 2.0.0
  24       * @var array Field type validation regexes.
  25       */
  26      protected $validation_regex = array();
  27  
  28      /**
  29       * Allowed values for field type.
  30       *
  31       * @since 2.0.0
  32       * @var array Field type allowed values.
  33       */
  34      protected $validation_allowed_values = array();
  35  
  36      /**
  37       * Name for field type.
  38       *
  39       * @since 2.0.0
  40       * @var string The name of this field type.
  41       */
  42      public $name = '';
  43  
  44      /**
  45       * The name of the category that this field type should be grouped with. Used on the [Users > Profile Fields] screen in wp-admin.
  46       *
  47       * @since 2.0.0
  48       * @var string
  49       */
  50      public $category = '';
  51  
  52      /**
  53       * If allowed to store null/empty values.
  54       *
  55       * @since 2.0.0
  56       * @var bool If this is set, allow BP to store null/empty values for this field type.
  57       */
  58      public $accepts_null_value = false;
  59  
  60      /**
  61       * If this is set, BP will set this field type's list of allowed values from the field's options (e.g checkbox, selectbox).
  62       *
  63       * @since 2.0.0
  64       * @var bool Does this field support options? e.g. selectbox, radio buttons, etc.
  65       */
  66      public $supports_options = false;
  67  
  68      /**
  69       * If allowed to support multiple options as default.
  70       *
  71       * @since 2.0.0
  72       * @var bool Does this field type support multiple options being set as default values? e.g. multiselectbox, checkbox.
  73       */
  74      public $supports_multiple_defaults = false;
  75  
  76      /**
  77       * If the field type supports rich text by default.
  78       *
  79       * @since 2.4.0
  80       * @var bool
  81       */
  82      public $supports_richtext = false;
  83  
  84      /**
  85       * If the field type has a type-specific settings section on the Edit Field panel.
  86       *
  87       * @since 2.7.0
  88       * @var bool|null Boolean if set explicitly by the type object, otherwise null.
  89       */
  90      protected $do_settings_section = null;
  91  
  92      /**
  93       * If object is created by an BP_XProfile_Field object.
  94       *
  95       * @since 2.0.0
  96       * @var BP_XProfile_Field If this object is created by instantiating a {@link BP_XProfile_Field},
  97       *                        this is a reference back to that object.
  98       */
  99      public $field_obj = null;
 100  
 101      /**
 102       * Constructor.
 103       *
 104       * @since 2.0.0
 105       */
 106  	public function __construct() {
 107  
 108          /**
 109           * Fires inside __construct() method for BP_XProfile_Field_Type class.
 110           *
 111           * @since 2.0.0
 112           *
 113           * @param BP_XProfile_Field_Type $this Current instance of
 114           *                                     the field type class.
 115           */
 116          do_action( 'bp_xprofile_field_type', $this );
 117      }
 118  
 119      /**
 120       * Set a regex that profile data will be asserted against.
 121       *
 122       * You can call this method multiple times to set multiple formats. When validation is performed,
 123       * it's successful as long as the new value matches any one of the registered formats.
 124       *
 125       * @since 2.0.0
 126       *
 127       * @param string $format         Regex string.
 128       * @param string $replace_format Optional; if 'replace', replaces the format instead of adding to it.
 129       *                               Defaults to 'add'.
 130       * @return BP_XProfile_Field_Type
 131       */
 132  	public function set_format( $format, $replace_format = 'add' ) {
 133  
 134          /**
 135           * Filters the regex format for the field type.
 136           *
 137           * @since 2.0.0
 138           *
 139           * @param string                 $format         Regex string.
 140           * @param string                 $replace_format Optional replace format If "replace", replaces the
 141           *                                               format instead of adding to it. Defaults to "add".
 142           * @param BP_XProfile_Field_Type $this           Current instance of the BP_XProfile_Field_Type class.
 143           */
 144          $format = apply_filters( 'bp_xprofile_field_type_set_format', $format, $replace_format, $this );
 145  
 146          if ( 'add' === $replace_format ) {
 147              $this->validation_regex[] = $format;
 148          } elseif ( 'replace' === $replace_format ) {
 149              $this->validation_regex = array( $format );
 150          }
 151  
 152          return $this;
 153      }
 154  
 155      /**
 156       * Add a value to this type's list of allowed values that profile data will be asserted against.
 157       *
 158       * @since 2.0.0
 159       * @deprecated 7.0.0 Use set_allowed_values() instead.
 160       *
 161       * @param string|array $values Whitelisted values.
 162       * @return BP_XProfile_Field_Type
 163       */
 164  	public function set_whitelist_values( $values ) {
 165          _deprecated_function( __METHOD__, '7.0.0', 'BP_XProfile_Field_Type::set_allowed_values()' );
 166          $this->set_allowed_values( $values );
 167      }
 168  
 169      /**
 170       * Add a value to this type's list of allowed values that profile data will be asserted against.
 171       *
 172       * You can call this method multiple times to set multiple formats. When validation is performed,
 173       * it's successful as long as the new value matches any one of the registered formats.
 174       *
 175       * @since 7.0.0
 176       *
 177       * @param string|array $values Allowed values.
 178       * @return BP_XProfile_Field_Type
 179       */
 180  	public function set_allowed_values( $values ) {
 181          foreach ( (array) $values as $value ) {
 182  
 183              /**
 184               * Filters values for field type's list of allowed values that profile data will be asserted against.
 185               *
 186               * @since 2.0.0
 187               * @deprecated 7.0.0 Use 'bp_xprofile_field_type_set_allowed_values' instead.
 188               *
 189               * @param string                 $value  Field value.
 190               * @param array                  $values Original array of values.
 191               * @param BP_XProfile_Field_Type $this   Current instance of the BP_XProfile_Field_Type class.
 192               */
 193              $this->validation_allowed_values[] = apply_filters_deprecated( 'bp_xprofile_field_type_set_whitelist_values', array( $value, $values, $this ), '7.0.0', 'bp_xprofile_field_type_set_allowed_values' );
 194  
 195              /**
 196               * Filters values for field type's list of allowed values that profile data will be asserted against.
 197               *
 198               * @since 7.0.0
 199               *
 200               * @param string                 $value  Field value.
 201               * @param array                  $values Original array of values.
 202               * @param BP_XProfile_Field_Type $this   Current instance of the BP_XProfile_Field_Type class.
 203               */
 204              $this->validation_allowed_values[] = apply_filters( 'bp_xprofile_field_type_set_allowed_values', $value, $values, $this );
 205          }
 206  
 207          return $this;
 208      }
 209  
 210      /**
 211       * Check the given string against the registered formats for this field type.
 212       *
 213       * This method doesn't support chaining.
 214       *
 215       * @since 2.0.0
 216       *
 217       * @param string|array $values Value to check against the registered formats.
 218       * @return bool True if the value validates
 219       */
 220  	public function is_valid( $values ) {
 221          $validated = false;
 222  
 223          // Some types of field (e.g. multi-selectbox) may have multiple values to check.
 224          foreach ( (array) $values as $value ) {
 225  
 226              // Validate the $value against the type's accepted format(s).
 227              foreach ( $this->validation_regex as $format ) {
 228                  if ( 1 === preg_match( $format, $value ) ) {
 229                      $validated = true;
 230                      continue;
 231  
 232                  } else {
 233                      $validated = false;
 234                  }
 235              }
 236          }
 237  
 238          // Handle field types with accepts_null_value set if $values is an empty array.
 239          if ( ( false === $validated ) && is_array( $values ) && empty( $values ) && $this->accepts_null_value ) {
 240              $validated = true;
 241          }
 242  
 243          // If there's a list of allowed values, make sure that each value is on that list.
 244          if ( ( true === $validated ) && ! empty( $values ) && ! empty( $this->validation_allowed_values ) ) {
 245              foreach ( (array) $values as $value ) {
 246                  if ( ! in_array( $value, $this->validation_allowed_values, true ) ) {
 247                      $validated = false;
 248                      break;
 249                  }
 250              }
 251          }
 252  
 253          /**
 254           * Filters whether or not field type is a valid format.
 255           *
 256           * @since 2.0.0
 257           *
 258           * @param bool                   $validated Whether or not the field type is valid.
 259           * @param string|array           $values    Value to check against the registered formats.
 260           * @param BP_XProfile_Field_Type $this      Current instance of the BP_XProfile_Field_Type class.
 261           */
 262          return (bool) apply_filters( 'bp_xprofile_field_type_is_valid', $validated, $values, $this );
 263      }
 264  
 265      /**
 266       * Check whether the current field type should have a settings ("options") section on the Edit Field panel.
 267       *
 268       * Falls back on `supports_options` if no value is set by the field type.
 269       *
 270       * @since 2.7.0
 271       *
 272       * @return bool
 273       */
 274  	public function do_settings_section() {
 275          if ( null === $this->do_settings_section ) {
 276              $this->do_settings_section = $this->supports_options;
 277          }
 278  
 279          return (bool) $this->do_settings_section;
 280      }
 281  
 282      /**
 283       * Output the edit field HTML for this field type.
 284       *
 285       * Must be used inside the {@link bp_profile_fields()} template loop.
 286       *
 287       * @since 2.0.0
 288       *
 289       * @param array $raw_properties Optional key/value array of permitted attributes that you want to add.
 290       * @return void
 291       */
 292      abstract public function edit_field_html( array $raw_properties = array() );
 293  
 294      /**
 295       * Output HTML for this field type on the wp-admin Profile Fields screen.
 296       *
 297       * Must be used inside the {@link bp_profile_fields()} template loop.
 298       *
 299       * @since 2.0.0
 300       *
 301       * @param array $raw_properties Optional key/value array of permitted attributes that you want to add.
 302       * @return void
 303       */
 304      abstract public function admin_field_html( array $raw_properties = array() );
 305  
 306      /**
 307       * Output the edit field options HTML for this field type.
 308       *
 309       * BuddyPress considers a field's "options" to be, for example, the items in a selectbox.
 310       * These are stored separately in the database, and their templating is handled separately.
 311       * Populate this method in a child class if it's required. Otherwise, you can leave it out.
 312       *
 313       * This templating is separate from {@link BP_XProfile_Field_Type::edit_field_html()} because
 314       * it's also used in the wp-admin screens when creating new fields, and for backwards compatibility.
 315       *
 316       * Must be used inside the {@link bp_profile_fields()} template loop.
 317       *
 318       * @since 2.0.0
 319       *
 320       * @param array $args Optional. The arguments passed to {@link bp_the_profile_field_options()}.
 321       */
 322  	public function edit_field_options_html( array $args = array() ) {}
 323  
 324      /**
 325       * Output HTML for this field type's children options on the wp-admin Profile Fields "Add Field" and "Edit Field" screens.
 326       *
 327       * You don't need to implement this method for all field types. It's used in core by the
 328       * selectbox, multi selectbox, checkbox, and radio button fields, to allow the admin to
 329       * enter the child option values (e.g. the choices in a select box).
 330       *
 331       * Must be used inside the {@link bp_profile_fields()} template loop.
 332       *
 333       * @since 2.0.0
 334       *
 335       * @param BP_XProfile_Field $current_field The current profile field on the add/edit screen.
 336       * @param string            $control_type  Optional. HTML input type used to render the current
 337       *                          field's child options.
 338       */
 339  	public function admin_new_field_html( BP_XProfile_Field $current_field, $control_type = '' ) {
 340          $type = array_search( get_class( $this ), bp_xprofile_get_field_types() );
 341          if ( false === $type ) {
 342              return;
 343          }
 344  
 345          $class            = $current_field->type != $type ? 'display: none;' : '';
 346          $current_type_obj = bp_xprofile_create_field_type( $type );
 347          ?>
 348  
 349          <div id="<?php echo esc_attr( $type ); ?>" class="postbox bp-options-box" style="<?php echo esc_attr( $class ); ?> margin-top: 15px;">
 350              <h3><?php esc_html_e( 'Please enter options for this Field:', 'buddypress' ); ?></h3>
 351              <div class="inside" aria-live="polite" aria-atomic="true" aria-relevant="all">
 352                  <p>
 353                      <label for="sort_order_<?php echo esc_attr( $type ); ?>"><?php esc_html_e( 'Sort Order:', 'buddypress' ); ?></label>
 354                      <select name="sort_order_<?php echo esc_attr( $type ); ?>" id="sort_order_<?php echo esc_attr( $type ); ?>" >
 355                          <option value="custom" <?php selected( 'custom', $current_field->order_by ); ?>><?php esc_html_e( 'Custom',     'buddypress' ); ?></option>
 356                          <option value="asc"    <?php selected( 'asc',    $current_field->order_by ); ?>><?php esc_html_e( 'Ascending',  'buddypress' ); ?></option>
 357                          <option value="desc"   <?php selected( 'desc',   $current_field->order_by ); ?>><?php esc_html_e( 'Descending', 'buddypress' ); ?></option>
 358                      </select>
 359                  </p>
 360  
 361                  <?php
 362  
 363                  // Does option have children?
 364                  $options = $current_field->get_children( true );
 365  
 366                  // If no children options exists for this field, check in $_POST
 367                  // for a submitted form (e.g. on the "new field" screen).
 368                  if ( empty( $options ) ) {
 369  
 370                      $options = array();
 371                      $i       = 1;
 372  
 373                      while ( isset( $_POST[$type . '_option'][$i] ) ) {
 374  
 375                          // Multiselectbox and checkboxes support MULTIPLE default options; all other core types support only ONE.
 376                          if ( $current_type_obj->supports_options && ! $current_type_obj->supports_multiple_defaults && isset( $_POST["isDefault_{$type}_option"][$i] ) && (int) $_POST["isDefault_{$type}_option"] === $i ) {
 377                              $is_default_option = true;
 378                          } elseif ( isset( $_POST["isDefault_{$type}_option"][$i] ) ) {
 379                              $is_default_option = (bool) $_POST["isDefault_{$type}_option"][$i];
 380                          } else {
 381                              $is_default_option = false;
 382                          }
 383  
 384                          // Grab the values from $_POST to use as the form's options.
 385                          $options[] = (object) array(
 386                              'id'                => -1,
 387                              'is_default_option' => $is_default_option,
 388                              'name'              => sanitize_text_field( stripslashes( $_POST[$type . '_option'][$i] ) ),
 389                          );
 390  
 391                          ++$i;
 392                      }
 393  
 394                      // If there are still no children options set, this must be the "new field" screen, so add one new/empty option.
 395                      if ( empty( $options ) ) {
 396                          $options[] = (object) array(
 397                              'id'                => -1,
 398                              'is_default_option' => false,
 399                              'name'              => '',
 400                          );
 401                      }
 402                  }
 403  
 404                  // Render the markup for the children options.
 405                  if ( ! empty( $options ) ) {
 406                      $default_name = '';
 407  
 408                      for ( $i = 0, $count = count( $options ); $i < $count; ++$i ) :
 409                          $j = $i + 1;
 410  
 411                          // Multiselectbox and checkboxes support MULTIPLE default options; all other core types support only ONE.
 412                          if ( $current_type_obj->supports_options && $current_type_obj->supports_multiple_defaults ) {
 413                              $default_name = '[' . $j . ']';
 414                          }
 415                          ?>
 416  
 417                          <div id="<?php echo esc_attr( "{$type}_div{$j}" ); ?>" class="bp-option sortable">
 418                              <span class="bp-option-icon grabber"></span>
 419                              <label for="<?php echo esc_attr( "{$type}_option{$j}" ); ?>" class="screen-reader-text"><?php
 420                                  /* translators: accessibility text */
 421                                  esc_html_e( 'Add an option', 'buddypress' );
 422                              ?></label>
 423                              <input type="text" name="<?php echo esc_attr( "{$type}_option[{$j}]" ); ?>" id="<?php echo esc_attr( "{$type}_option{$j}" ); ?>" value="<?php echo esc_attr( stripslashes( $options[$i]->name ) ); ?>" />
 424                              <label for="<?php echo esc_attr( "{$type}_option{$default_name}" ); ?>">
 425                                  <input type="<?php echo esc_attr( $control_type ); ?>" id="<?php echo esc_attr( "{$type}_option{$default_name}" ); ?>" name="<?php echo esc_attr( "isDefault_{$type}_option{$default_name}" ); ?>" <?php checked( $options[$i]->is_default_option, true ); ?> value="<?php echo esc_attr( $j ); ?>" />
 426                                  <?php _e( 'Default Value', 'buddypress' ); ?>
 427                              </label>
 428  
 429                              <?php if ( 1 !== $j ) : ?>
 430                                  <div class ="delete-button">
 431                                      <a href='javascript:hide("<?php echo esc_attr( "{$type}_div{$j}" ); ?>")' class="delete"><?php esc_html_e( 'Delete', 'buddypress' ); ?></a>
 432                                  </div>
 433                              <?php endif; ?>
 434  
 435                          </div>
 436  
 437                      <?php endfor; ?>
 438  
 439                      <input type="hidden" name="<?php echo esc_attr( "{$type}_option_number" ); ?>" id="<?php echo esc_attr( "{$type}_option_number" ); ?>" value="<?php echo esc_attr( $j + 1 ); ?>" />
 440                  <?php } ?>
 441  
 442                  <div id="<?php echo esc_attr( "{$type}_more" ); ?>"></div>
 443                  <p><a href="javascript:add_option('<?php echo esc_js( $type ); ?>')"><?php esc_html_e( 'Add Another Option', 'buddypress' ); ?></a></p>
 444  
 445                  <?php
 446  
 447                  /**
 448                   * Fires at the end of the new field additional settings area.
 449                   *
 450                   * @since 2.3.0
 451                   *
 452                   * @param BP_XProfile_Field $current_field Current field being rendered.
 453                   */
 454                  do_action( 'bp_xprofile_admin_new_field_additional_settings', $current_field ) ?>
 455              </div>
 456          </div>
 457  
 458          <?php
 459      }
 460  
 461      /**
 462       * Allow field types to modify submitted values before they are validated.
 463       *
 464       * In some cases, it may be appropriate for a field type to catch
 465       * submitted values and modify them before they are passed to the
 466       * is_valid() method. For example, URL validation requires the
 467       * 'http://' scheme (so that the value saved in the database is always
 468       * a fully-formed URL), but in order to allow users to enter a URL
 469       * without this scheme, BP_XProfile_Field_Type_URL prepends 'http://'
 470       * when it's not present.
 471       *
 472       * By default, this is a pass-through method that does nothing. Only
 473       * override in your own field type if you need this kind of pre-
 474       * validation filtering.
 475       *
 476       * @since 2.1.0
 477       * @since 2.4.0 Added the `$field_id` parameter.
 478       *
 479       * @param mixed      $field_value Submitted field value.
 480       * @param string|int $field_id    Optional. ID of the field.
 481       * @return mixed
 482       */
 483  	public static function pre_validate_filter( $field_value, $field_id = '' ) {
 484          return $field_value;
 485      }
 486  
 487      /**
 488       * Allow field types to modify the appearance of their values.
 489       *
 490       * By default, this is a pass-through method that does nothing. Only
 491       * override in your own field type if you need to provide custom
 492       * filtering for output values.
 493       *
 494       * @since 2.1.0
 495       * @since 2.4.0 Added `$field_id` parameter.
 496       *
 497       * @param mixed      $field_value Field value.
 498       * @param string|int $field_id    ID of the field.
 499       * @return mixed
 500       */
 501  	public static function display_filter( $field_value, $field_id = '' ) {
 502          return $field_value;
 503      }
 504  
 505      /**
 506       * Save miscellaneous settings related to this field type.
 507       *
 508       * Override in a specific field type if it requires an admin save routine.
 509       *
 510       * @since 2.7.0
 511       *
 512       * @param int   $field_id Field ID.
 513       * @param array $settings Array of settings.
 514       */
 515  	public function admin_save_settings( $field_id, $settings ) {}
 516  
 517      /** Protected *************************************************************/
 518  
 519      /**
 520       * Get a sanitized and escaped string of the edit field's HTML elements and attributes.
 521       *
 522       * Must be used inside the {@link bp_profile_fields()} template loop.
 523       * This method was intended to be static but couldn't be because php.net/lsb/ requires PHP >= 5.3.
 524       *
 525       * @since 2.0.0
 526       *
 527       * @param array $properties Optional key/value array of attributes for this edit field.
 528       * @return string
 529       */
 530  	protected function get_edit_field_html_elements( array $properties = array() ) {
 531  
 532          $r = bp_parse_args(
 533              $properties,
 534              array(
 535                  'id'   => bp_get_the_profile_field_input_name(),
 536                  'name' => bp_get_the_profile_field_input_name(),
 537              )
 538          );
 539  
 540          if ( bp_get_the_profile_field_is_required() ) {
 541              $r['aria-required'] = 'true';
 542  
 543              // Moderators can bypass field requirements.
 544              if ( ! bp_current_user_can( 'bp_moderate' ) ) {
 545                  $r[] = 'required';
 546              }
 547          }
 548  
 549          /**
 550           * Filters the edit html elements and attributes.
 551           *
 552           * @since 2.0.0
 553           *
 554           * @param array  $r     Array of parsed arguments.
 555           * @param string $value Class name for the current class instance.
 556           */
 557          $r = (array) apply_filters( 'bp_xprofile_field_edit_html_elements', $r, get_class( $this ) );
 558  
 559          return bp_get_form_field_attributes( sanitize_key( bp_get_the_profile_field_name() ), $r );
 560      }
 561  }


Generated: Sat Apr 27 01:00:55 2024 Cross-referenced by PHPXref 0.7.1