[ Index ]

PHP Cross Reference of BuddyPress

title

Body

[close]

/src/bp-xprofile/ -> bp-xprofile-functions.php (source)

   1  <?php
   2  /**
   3   * BuddyPress XProfile Filters.
   4   *
   5   * Business functions are where all the magic happens in BuddyPress. They will
   6   * handle the actual saving or manipulation of information. Usually they will
   7   * hand off to a database class for data access, then return
   8   * true or false on success or failure.
   9   *
  10   * @package BuddyPress
  11   * @subpackage XProfileFunctions
  12   * @since 1.5.0
  13   */
  14  
  15  // Exit if accessed directly.
  16  defined( 'ABSPATH' ) || exit;
  17  
  18  /*** Field Group Management **************************************************/
  19  
  20  /**
  21   * Fetch a set of field groups, populated with fields and field data.
  22   *
  23   * Procedural wrapper for BP_XProfile_Group::get() method.
  24   *
  25   * @since 2.1.0
  26   *
  27   * @param array $args See {@link BP_XProfile_Group::get()} for description of arguments.
  28   * @return array $groups
  29   */
  30  function bp_xprofile_get_groups( $args = array() ) {
  31  
  32      $groups = BP_XProfile_Group::get( $args );
  33  
  34      /**
  35       * Filters a set of field groups, populated with fields and field data.
  36       *
  37       * @since 2.1.0
  38       *
  39       * @param array $groups Array of field groups and field data.
  40       * @param array $args   Array of arguments used to query for groups.
  41       */
  42      return apply_filters( 'bp_xprofile_get_groups', $groups, $args );
  43  }
  44  
  45  /**
  46   * Insert a new profile field group.
  47   *
  48   * @since 1.0.0
  49   *
  50   * @param array|string $args {
  51   *    Array of arguments for field group insertion.
  52   *
  53   *    @type int|bool    $field_group_id ID of the field group to insert into.
  54   *    @type string|bool $name           Name of the group.
  55   *    @type string      $description    Field group description.
  56   *    @type bool        $can_delete     Whether or not the field group can be deleted.
  57   * }
  58   * @return boolean
  59   */
  60  function xprofile_insert_field_group( $args = '' ) {
  61  
  62      // Parse the arguments.
  63      $r = bp_parse_args(
  64          $args,
  65          array(
  66              'field_group_id' => false,
  67              'name'           => false,
  68              'description'    => '',
  69              'can_delete'     => true,
  70          ),
  71          'xprofile_insert_field_group'
  72      );
  73  
  74      // Bail if no group name.
  75      if ( empty( $r['name'] ) ) {
  76          return false;
  77      }
  78  
  79      // Create new field group object, maybe using an existing ID.
  80      $field_group              = new BP_XProfile_Group( $r['field_group_id'] );
  81      $field_group->name        = $r['name'];
  82      $field_group->description = $r['description'];
  83      $field_group->can_delete  = $r['can_delete'];
  84  
  85      return $field_group->save();
  86  }
  87  
  88  /**
  89   * Get a specific profile field group.
  90   *
  91   * @since 1.0.0
  92   *
  93   * @param int $field_group_id Field group ID to fetch.
  94   * @return false|BP_XProfile_Group
  95   */
  96  function xprofile_get_field_group( $field_group_id = 0 ) {
  97  
  98      // Try to get a specific field group by ID.
  99      $field_group = new BP_XProfile_Group( $field_group_id );
 100  
 101      // Bail if group was not found.
 102      if ( empty( $field_group->id ) ) {
 103          return false;
 104      }
 105  
 106      // Return field group.
 107      return $field_group;
 108  }
 109  
 110  /**
 111   * Delete a specific profile field group.
 112   *
 113   * @since 1.0.0
 114   *
 115   * @param int $field_group_id Field group ID to delete.
 116   * @return boolean
 117   */
 118  function xprofile_delete_field_group( $field_group_id = 0 ) {
 119  
 120      // Try to get a specific field group by ID.
 121      $field_group = xprofile_get_field_group( $field_group_id );
 122  
 123      // Bail if group was not found.
 124      if ( false === $field_group ) {
 125          return false;
 126      }
 127  
 128      // Return the results of trying to delete the field group.
 129      return $field_group->delete();
 130  }
 131  
 132  /**
 133   * Update the position of a specific profile field group.
 134   *
 135   * @since 1.0.0
 136   *
 137   * @param int $field_group_id Field group ID to update.
 138   * @param int $position       Field group position to update to.
 139   * @return boolean
 140   */
 141  function xprofile_update_field_group_position( $field_group_id = 0, $position = 0 ) {
 142      return BP_XProfile_Group::update_position( $field_group_id, $position );
 143  }
 144  
 145  /*** Field Management *********************************************************/
 146  
 147  /**
 148   * Get details of all xprofile field types.
 149   *
 150   * @since 2.0.0
 151   *
 152   * @return array Key/value pairs (field type => class name).
 153   */
 154  function bp_xprofile_get_field_types() {
 155      $fields = array(
 156          'checkbox'            => 'BP_XProfile_Field_Type_Checkbox',
 157          'datebox'             => 'BP_XProfile_Field_Type_Datebox',
 158          'multiselectbox'      => 'BP_XProfile_Field_Type_Multiselectbox',
 159          'number'              => 'BP_XProfile_Field_Type_Number',
 160          'url'                 => 'BP_XProfile_Field_Type_URL',
 161          'radio'               => 'BP_XProfile_Field_Type_Radiobutton',
 162          'selectbox'           => 'BP_XProfile_Field_Type_Selectbox',
 163          'textarea'            => 'BP_XProfile_Field_Type_Textarea',
 164          'textbox'             => 'BP_XProfile_Field_Type_Textbox',
 165          'telephone'           => 'BP_XProfile_Field_Type_Telephone',
 166          'wp-biography'        => 'BP_XProfile_Field_Type_WordPress_Biography',
 167          'wp-textbox'          => 'BP_XProfile_Field_Type_WordPress_Textbox',
 168          'checkbox_acceptance' => 'BP_XProfile_Field_Type_Checkbox_Acceptance',
 169      );
 170  
 171      /**
 172       * Filters the list of all xprofile field types.
 173       *
 174       * If you've added a custom field type in a plugin, register it with this filter.
 175       *
 176       * @since 2.0.0
 177       *
 178       * @param array $fields Array of field type/class name pairings.
 179       */
 180      return apply_filters( 'bp_xprofile_get_field_types', $fields );
 181  }
 182  
 183  /**
 184   * Creates the specified field type object; used for validation and templating.
 185   *
 186   * @since 2.0.0
 187   *
 188   * @param string $type Type of profile field to create. See {@link bp_xprofile_get_field_types()} for default core values.
 189   * @return object $value If field type unknown, returns BP_XProfile_Field_Type_Textarea.
 190   *                       Otherwise returns an instance of the relevant child class of BP_XProfile_Field_Type.
 191   */
 192  function bp_xprofile_create_field_type( $type ) {
 193  
 194      $field = bp_xprofile_get_field_types();
 195      $class = isset( $field[$type] ) ? $field[$type] : '';
 196  
 197      /**
 198       * To handle (missing) field types, fallback to a placeholder field object if a type is unknown.
 199       */
 200      if ( $class && class_exists( $class ) ) {
 201          return new $class;
 202      } else {
 203          return new BP_XProfile_Field_Type_Placeholder;
 204      }
 205  }
 206  
 207  /**
 208   * Insert or update an xprofile field.
 209   *
 210   * @since 1.1.0
 211   *
 212   * @param array|string $args {
 213   *     Array of arguments.
 214   *     @type int    $field_id          Optional. Pass the ID of an existing field to edit that field.
 215   *     @type int    $field_group_id    ID of the associated field group.
 216   *     @type int    $parent_id         Optional. ID of the parent field.
 217   *     @type string $type              Field type. Checked against a list of allowed field_types.
 218   *     @type string $name              Name of the new field.
 219   *     @type string $description       Optional. Descriptive text for the field.
 220   *     @type bool   $is_required       Optional. Whether users must provide a value for the field. Default: false.
 221   *     @type bool   $can_delete        Optional. Whether admins can delete this field in the Dashboard interface.
 222   *                                     Generally this is false only for the Name field, which is required throughout BP.
 223   *                                     Default: true.
 224   *     @type string $order_by          Optional. For field types that support options (such as 'radio'), this flag
 225   *                                     determines whether the sort order of the options will be 'default'
 226   *                                     (order created) or 'custom'.
 227   *     @type bool   $is_default_option Optional. For the 'option' field type, setting this value to true means that
 228   *                                     it'll be the default value for the parent field when the user has not yet
 229   *                                     overridden. Default: true.
 230   *     @type int    $option_order      Optional. For the 'option' field type, this determines the order in which the
 231   *                                     options appear.
 232   * }
 233   * @return bool|int False on failure, ID of new field on success.
 234   */
 235  function xprofile_insert_field( $args = '' ) {
 236  
 237      $r = bp_parse_args(
 238          $args,
 239          array(
 240              'field_id'          => null,
 241              'field_group_id'    => null,
 242              'parent_id'         => null,
 243              'type'              => '',
 244              'name'              => '',
 245              'description'       => '',
 246              'is_required'       => false,
 247              'can_delete'        => true,
 248              'order_by'          => '',
 249              'is_default_option' => false,
 250              'option_order'      => null,
 251              'field_order'       => null,
 252          )
 253      );
 254  
 255      // Field_group_id is required.
 256      if ( empty( $r['field_group_id'] ) ) {
 257          return false;
 258      }
 259  
 260      // Check this is a non-empty, valid field type.
 261      if ( ! in_array( $r['type'], (array) buddypress()->profile->field_types ) ) {
 262          return false;
 263      }
 264  
 265      // Instantiate a new field object.
 266      if ( ! empty( $r['field_id'] ) ) {
 267          $field = xprofile_get_field( $r['field_id'], null, false );
 268      } else {
 269          $field = new BP_XProfile_Field;
 270      }
 271  
 272      $field->group_id = $r['field_group_id'];
 273      $field->type     = $r['type'];
 274  
 275      // The 'name' field cannot be empty.
 276      if ( ! empty( $r['name'] ) ) {
 277          $field->name = $r['name'];
 278      }
 279  
 280      $field->description       = $r['description'];
 281      $field->order_by          = $r['order_by'];
 282      $field->parent_id         = (int) $r['parent_id'];
 283      $field->field_order       = (int) $r['field_order'];
 284      $field->option_order      = (int) $r['option_order'];
 285      $field->is_required       = (bool) $r['is_required'];
 286      $field->can_delete        = (bool) $r['can_delete'];
 287      $field->is_default_option = (bool) $r['is_default_option'];
 288  
 289      return $field->save();
 290  }
 291  
 292  /**
 293   * Get a profile field object.
 294   *
 295   * @since 1.1.0
 296   * @since 2.8.0 Added `$user_id` and `$get_data` parameters.
 297   *
 298   * @param int|object $field    ID of the field or object representing field data.
 299   * @param int|null   $user_id  Optional. ID of the user associated with the field.
 300   *                             Ignored if `$get_data` is false. If `$get_data` is
 301   *                             true, but no `$user_id` is provided, defaults to
 302   *                             logged-in user ID.
 303   * @param bool       $get_data Whether to fetch data for the specified `$user_id`.
 304   * @return BP_XProfile_Field|null Field object if found, otherwise null.
 305   */
 306  function xprofile_get_field( $field, $user_id = null, $get_data = true ) {
 307      if ( $field instanceof BP_XProfile_Field ) {
 308          $_field = $field;
 309      } elseif ( is_object( $field ) ) {
 310          $_field = new BP_XProfile_Field();
 311          $_field->fill_data( $field );
 312      } else {
 313          $_field = BP_XProfile_Field::get_instance( $field, $user_id, $get_data );
 314      }
 315  
 316      if ( ! $_field ) {
 317          return null;
 318      }
 319  
 320      return $_field;
 321  }
 322  
 323  /**
 324   * Get a profile Field Type object.
 325   *
 326   * @since 8.0.0
 327   *
 328   * @param int $field_id ID of the field.
 329   * @return BP_XProfile_Field_Type|null Field Type object if found, otherwise null.
 330   */
 331  function bp_xprofile_get_field_type( $field_id ) {
 332      $field_type = null;
 333      $field      = xprofile_get_field( $field_id, null, false );
 334  
 335      if ( $field instanceof BP_XProfile_Field ) {
 336          $field_type = $field->type_obj;
 337      }
 338  
 339      return $field_type;
 340  }
 341  
 342  /**
 343   * Delete a profile field object.
 344   *
 345   * @since 1.1.0
 346   *
 347   * @param int|object $field_id ID of the field or object representing field data.
 348   * @return bool Whether or not the field was deleted.
 349   */
 350  function xprofile_delete_field( $field_id ) {
 351      $field = new BP_XProfile_Field( $field_id );
 352      return $field->delete();
 353  }
 354  
 355  /*** Field Data Management *****************************************************/
 356  
 357  
 358  /**
 359   * Fetches profile data for a specific field for the user.
 360   *
 361   * When the field value is serialized, this function unserializes and filters
 362   * each item in the array.
 363   *
 364   * @since 1.0.0
 365   *
 366   * @param mixed  $field        The ID of the field, or the $name of the field.
 367   * @param int    $user_id      The ID of the user.
 368   * @param string $multi_format How should array data be returned? 'comma' if you want a
 369   *                             comma-separated string; 'array' if you want an array.
 370   * @return mixed The profile field data.
 371   */
 372  function xprofile_get_field_data( $field, $user_id = 0, $multi_format = 'array' ) {
 373  
 374      if ( empty( $user_id ) ) {
 375          $user_id = bp_displayed_user_id();
 376      }
 377  
 378      if ( empty( $user_id ) ) {
 379          return false;
 380      }
 381  
 382      if ( is_numeric( $field ) ) {
 383          $field_id = $field;
 384      } else {
 385          $field_id = xprofile_get_field_id_from_name( $field );
 386      }
 387  
 388      if ( empty( $field_id ) ) {
 389          return false;
 390      }
 391  
 392      $values = maybe_unserialize( BP_XProfile_ProfileData::get_value_byid( $field_id, $user_id ) );
 393  
 394      if ( is_array( $values ) ) {
 395          $data = array();
 396          foreach( (array) $values as $value ) {
 397  
 398              /**
 399               * Filters the field data value for a specific field for the user.
 400               *
 401               * @since 1.0.0
 402               *
 403               * @param string $value    Value saved for the field.
 404               * @param int    $field_id ID of the field being displayed.
 405               * @param int    $user_id  ID of the user being displayed.
 406               */
 407              $data[] = apply_filters( 'xprofile_get_field_data', $value, $field_id, $user_id );
 408          }
 409  
 410          if ( 'comma' == $multi_format ) {
 411              $data = implode( ', ', $data );
 412          }
 413      } else {
 414          /** This filter is documented in bp-xprofile/bp-xprofile-functions.php */
 415          $data = apply_filters( 'xprofile_get_field_data', $values, $field_id, $user_id );
 416      }
 417  
 418      return $data;
 419  }
 420  
 421  /**
 422   * A simple function to set profile data for a specific field for a specific user.
 423   *
 424   * @since 1.0.0
 425   *
 426   * @param int|string $field       The ID of the field, or the $name of the field.
 427   * @param int        $user_id     The ID of the user.
 428   * @param mixed      $value       The value for the field you want to set for the user.
 429   * @param bool       $is_required Whether or not the field is required.
 430   * @return bool True on success, false on failure.
 431   */
 432  function xprofile_set_field_data( $field, $user_id, $value, $is_required = false ) {
 433  
 434      if ( is_numeric( $field ) ) {
 435          $field_id = $field;
 436      } else {
 437          $field_id = xprofile_get_field_id_from_name( $field );
 438      }
 439  
 440      if ( empty( $field_id ) ) {
 441          return false;
 442      }
 443  
 444      $field          = xprofile_get_field( $field_id );
 445      $field_type     = BP_XProfile_Field::get_type( $field_id );
 446      $field_type_obj = bp_xprofile_create_field_type( $field_type );
 447  
 448      /**
 449       * Filter the raw submitted profile field value.
 450       *
 451       * Use this filter to modify the values submitted by users before
 452       * doing field-type-specific validation.
 453       *
 454       * @since 2.1.0
 455       *
 456       * @param mixed                  $value          Value passed to xprofile_set_field_data().
 457       * @param BP_XProfile_Field      $field          Field object.
 458       * @param BP_XProfile_Field_Type $field_type_obj Field type object.
 459       */
 460      $value = apply_filters( 'bp_xprofile_set_field_data_pre_validate', $value, $field, $field_type_obj );
 461  
 462      // Special-case support for integer 0 for the number field type.
 463      if ( $is_required && ! is_integer( $value ) && $value !== '0' && ( empty( $value ) || ! is_array( $value ) && ! strlen( trim( $value ) ) ) ) {
 464          return false;
 465      }
 466  
 467      /**
 468       * Certain types of fields (checkboxes, multiselects) may come through empty.
 469       * Save as empty array so this isn't overwritten by the default on next edit.
 470       *
 471       * Special-case support for integer 0 for the number field type
 472       */
 473      if ( empty( $value ) && ! is_integer( $value ) && $value !== '0' && $field_type_obj->accepts_null_value ) {
 474          $value = array();
 475      }
 476  
 477      // If the value is empty, then delete any field data that exists, unless the field is of a type
 478      // where null values are semantically meaningful.
 479      if ( empty( $value ) && ! is_integer( $value ) && $value !== '0' && ! $field_type_obj->accepts_null_value ) {
 480          xprofile_delete_field_data( $field_id, $user_id );
 481          return true;
 482      }
 483  
 484      // For certain fields, only certain parameters are acceptable, so add them to the list of allowed values.
 485      if ( $field_type_obj->supports_options ) {
 486          $field_type_obj->set_allowed_values( wp_list_pluck( $field->get_children(), 'name' ) );
 487      }
 488  
 489      // Check the value is in an accepted format for this form field.
 490      if ( ! $field_type_obj->is_valid( $value ) ) {
 491          return false;
 492      }
 493  
 494      $field_args = compact( 'field_type_obj', 'field', 'user_id', 'value', 'is_required' );
 495  
 496      /**
 497       * Return a WP_Error object or true to use your custom way of saving field values.
 498       *
 499       * @since 8.0.0
 500       *
 501       * @param boolean Whether to shortcircuit the $bp->profile->table_name_data table.
 502       * @param array $field_args {
 503       *     An array of arguments.
 504       *
 505       *     @type object            $field_type_obj Field type object.
 506       *     @type BP_XProfile_Field $field          Field object.
 507       *     @type integer           $user_id        The user ID.
 508       *     @type mixed             $value          Value passed to xprofile_set_field_data().
 509       *     @type boolean           $is_required    Whether or not the field is required.
 510       * }
 511       */
 512      $retval = apply_filters( 'bp_xprofile_set_field_data_pre_save', false, $field_args );
 513  
 514      if ( is_wp_error( $retval ) ) {
 515          return false;
 516      }
 517  
 518      if ( false === $retval ) {
 519          $field           = new BP_XProfile_ProfileData();
 520          $field->field_id = $field_id;
 521          $field->user_id  = $user_id;
 522  
 523          // Gets un/reserialized via xprofile_sanitize_data_value_before_save().
 524          $field->value    = maybe_serialize( $value );
 525  
 526          $retval = $field->save();
 527      }
 528  
 529      return $retval;
 530  }
 531  
 532  /**
 533   * Set the visibility level for this field.
 534   *
 535   * @since 1.6.0
 536   *
 537   * @param int    $field_id         The ID of the xprofile field.
 538   * @param int    $user_id          The ID of the user to whom the data belongs.
 539   * @param string $visibility_level What the visibility setting should be.
 540   * @return bool True on success
 541   */
 542  function xprofile_set_field_visibility_level( $field_id = 0, $user_id = 0, $visibility_level = '' ) {
 543      if ( empty( $field_id ) || empty( $user_id ) || empty( $visibility_level ) ) {
 544          return false;
 545      }
 546  
 547      // Check against a list of registered visibility levels.
 548      $allowed_values = bp_xprofile_get_visibility_levels();
 549      if ( !array_key_exists( $visibility_level, $allowed_values ) ) {
 550          return false;
 551      }
 552  
 553      // Stored in an array in usermeta.
 554      $current_visibility_levels = bp_get_user_meta( $user_id, 'bp_xprofile_visibility_levels', true );
 555  
 556      if ( !$current_visibility_levels ) {
 557          $current_visibility_levels = array();
 558      }
 559  
 560      $current_visibility_levels[$field_id] = $visibility_level;
 561  
 562      return bp_update_user_meta( $user_id, 'bp_xprofile_visibility_levels', $current_visibility_levels );
 563  }
 564  
 565  /**
 566   * Get the visibility level for a field.
 567   *
 568   * @since 2.0.0
 569   *
 570   * @param int $field_id The ID of the xprofile field.
 571   * @param int $user_id The ID of the user to whom the data belongs.
 572   * @return string
 573   */
 574  function xprofile_get_field_visibility_level( $field_id = 0, $user_id = 0 ) {
 575      $current_level = '';
 576  
 577      if ( empty( $field_id ) || empty( $user_id ) ) {
 578          return $current_level;
 579      }
 580  
 581      $current_levels = bp_get_user_meta( $user_id, 'bp_xprofile_visibility_levels', true );
 582      $current_level  = isset( $current_levels[ $field_id ] ) ? $current_levels[ $field_id ] : '';
 583  
 584      // Use the user's stored level, unless custom visibility is disabled.
 585      $field = xprofile_get_field( $field_id, null, false );
 586      if ( isset( $field->allow_custom_visibility ) && 'disabled' === $field->allow_custom_visibility ) {
 587          $current_level = $field->default_visibility;
 588      }
 589  
 590      // If we're still empty, it means that overrides are permitted, but the
 591      // user has not provided a value. Use the default value.
 592      if ( empty( $current_level ) ) {
 593          $current_level = $field->default_visibility;
 594      }
 595  
 596      return $current_level;
 597  }
 598  
 599  /**
 600   * Delete XProfile field data.
 601   *
 602   * @since 1.1.0
 603   *
 604   * @param string $field   Field to delete.
 605   * @param int    $user_id User ID to delete field from.
 606   * @return bool Whether or not the field was deleted.
 607   */
 608  function xprofile_delete_field_data( $field = '', $user_id = 0 ) {
 609  
 610      // Get the field ID.
 611      if ( is_numeric( $field ) ) {
 612          $field_id = (int) $field;
 613      } else {
 614          $field_id = xprofile_get_field_id_from_name( $field );
 615      }
 616  
 617      // Bail if field or user ID are empty.
 618      if ( empty( $field_id ) || empty( $user_id ) ) {
 619          return false;
 620      }
 621  
 622      // Get the profile field data to delete.
 623      $field = new BP_XProfile_ProfileData( $field_id, $user_id );
 624  
 625      // Delete the field data.
 626      return $field->delete();
 627  }
 628  
 629  /**
 630   * Check if field is a required field.
 631   *
 632   * @since 1.1.0
 633   *
 634   * @param int $field_id ID of the field to check for.
 635   * @return bool Whether or not field is required.
 636   */
 637  function xprofile_check_is_required_field( $field_id ) {
 638      $field  = new BP_XProfile_Field( $field_id );
 639      $retval = false;
 640  
 641      if ( isset( $field->is_required ) ) {
 642          $retval = $field->is_required;
 643      }
 644  
 645      return (bool) $retval;
 646  }
 647  
 648  /**
 649   * Returns the ID for the field based on the field name.
 650   *
 651   * @since 1.0.0
 652   *
 653   * @param string $field_name The name of the field to get the ID for.
 654   * @return int|null $field_id on success, false on failure.
 655   */
 656  function xprofile_get_field_id_from_name( $field_name ) {
 657      return BP_XProfile_Field::get_id_from_name( $field_name );
 658  }
 659  
 660  /**
 661   * Fetches a random piece of profile data for the user.
 662   *
 663   * @since 1.0.0
 664   *
 665   * @global BuddyPress $bp           The one true BuddyPress instance.
 666   * @global object     $wpdb         WordPress DB access object.
 667   * @global object     $current_user WordPress global variable containing current logged in user information.
 668   *
 669   * @param int  $user_id          User ID of the user to get random data for.
 670   * @param bool $exclude_fullname Optional; whether or not to exclude the full name field as random data.
 671   *                               Defaults to true.
 672   * @return string|bool The fetched random data for the user, or false if no data or no match.
 673   */
 674  function xprofile_get_random_profile_data( $user_id, $exclude_fullname = true ) {
 675      $field_data = BP_XProfile_ProfileData::get_random( $user_id, $exclude_fullname );
 676  
 677      if ( empty( $field_data ) ) {
 678          return false;
 679      }
 680  
 681      $field_data[0]->value = xprofile_format_profile_field( $field_data[0]->type, $field_data[0]->value );
 682  
 683      if ( empty( $field_data[0]->value ) ) {
 684          return false;
 685      }
 686  
 687      /**
 688       * Filters a random piece of profile data for the user.
 689       *
 690       * @since 1.0.0
 691       *
 692       * @param array $field_data Array holding random profile data.
 693       */
 694      return apply_filters( 'xprofile_get_random_profile_data', $field_data );
 695  }
 696  
 697  /**
 698   * Formats a profile field according to its type. [ TODO: Should really be moved to filters ]
 699   *
 700   * @since 1.0.0
 701   *
 702   * @param string $field_type  The type of field: datebox, selectbox, textbox etc.
 703   * @param string $field_value The actual value.
 704   * @return string|bool The formatted value, or false if value is empty.
 705   */
 706  function xprofile_format_profile_field( $field_type, $field_value ) {
 707  
 708      if ( empty( $field_value ) ) {
 709          return false;
 710      }
 711  
 712      $field_value = bp_unserialize_profile_field( $field_value );
 713  
 714      if ( 'datebox' != $field_type ) {
 715          $content = $field_value;
 716          $field_value = str_replace( ']]>', ']]&gt;', $content );
 717      }
 718  
 719      return xprofile_filter_format_field_value_by_type( stripslashes_deep( $field_value ), $field_type );
 720  }
 721  
 722  /**
 723   * Update the field position for a provided field.
 724   *
 725   * @since 1.1.0
 726   *
 727   * @param int $field_id       ID of the field to update.
 728   * @param int $position       Position to update the field to.
 729   * @param int $field_group_id Group ID for group the field is in.
 730   * @return bool
 731   */
 732  function xprofile_update_field_position( $field_id, $position, $field_group_id ) {
 733      return BP_XProfile_Field::update_position( $field_id, $position, $field_group_id );
 734  }
 735  
 736  /**
 737   * Replace the displayed and logged-in users fullnames with the xprofile name, if required.
 738   *
 739   * The Members component uses the logged-in user's display_name to set the
 740   * value of buddypress()->loggedin_user->fullname. However, in cases where
 741   * profile sync is disabled, display_name may diverge from the xprofile
 742   * fullname field value, and the xprofile field should take precedence.
 743   *
 744   * Runs at bp_setup_globals:100 to ensure that all components have loaded their
 745   * globals before attempting any overrides.
 746   *
 747   * @since 2.0.0
 748   */
 749  function xprofile_override_user_fullnames() {
 750      // If sync is enabled, the two names will match. No need to continue.
 751      if ( ! bp_disable_profile_sync() ) {
 752          return;
 753      }
 754  
 755      if ( bp_loggedin_user_id() ) {
 756          buddypress()->loggedin_user->fullname = bp_core_get_user_displayname( bp_loggedin_user_id() );
 757      }
 758  
 759      if ( bp_displayed_user_id() ) {
 760          buddypress()->displayed_user->fullname = bp_core_get_user_displayname( bp_displayed_user_id() );
 761      }
 762  }
 763  add_action( 'bp_setup_globals', 'xprofile_override_user_fullnames', 100 );
 764  
 765  /**
 766   * When search_terms are passed to BP_User_Query, search against xprofile fields.
 767   *
 768   * @since 2.0.0
 769   *
 770   * @param array         $sql   Clauses in the user_id SQL query.
 771   * @param BP_User_Query $query User query object.
 772   * @return array
 773   */
 774  function bp_xprofile_bp_user_query_search( $sql, BP_User_Query $query ) {
 775      global $wpdb;
 776  
 777      if ( empty( $query->query_vars['search_terms'] ) || empty( $sql['where']['search'] ) ) {
 778          return $sql;
 779      }
 780  
 781      $bp = buddypress();
 782  
 783      $search_terms_clean = bp_esc_like( wp_kses_normalize_entities( $query->query_vars['search_terms'] ) );
 784  
 785      if ( $query->query_vars['search_wildcard'] === 'left' ) {
 786          $search_terms_nospace = '%' . $search_terms_clean;
 787          $search_terms_space   = '%' . $search_terms_clean . ' %';
 788      } elseif ( $query->query_vars['search_wildcard'] === 'right' ) {
 789          $search_terms_nospace =        $search_terms_clean . '%';
 790          $search_terms_space   = '% ' . $search_terms_clean . '%';
 791      } else {
 792          $search_terms_nospace = '%' . $search_terms_clean . '%';
 793          $search_terms_space   = '%' . $search_terms_clean . '%';
 794      }
 795  
 796      // Combine the core search (against wp_users) into a single OR clause
 797      // with the xprofile_data search.
 798      $matched_user_ids = $wpdb->get_col( $wpdb->prepare(
 799          "SELECT user_id FROM {$bp->profile->table_name_data} WHERE value LIKE %s OR value LIKE %s",
 800          $search_terms_nospace,
 801          $search_terms_space
 802      ) );
 803  
 804      if ( ! empty( $matched_user_ids ) ) {
 805          $search_core     = $sql['where']['search'];
 806          $search_combined = " ( u.{$query->uid_name} IN (" . implode(',', $matched_user_ids) . ") OR {$search_core} )";
 807          $sql['where']['search'] = $search_combined;
 808      }
 809  
 810      return $sql;
 811  }
 812  add_action( 'bp_user_query_uid_clauses', 'bp_xprofile_bp_user_query_search', 10, 2 );
 813  
 814  /**
 815   * Syncs Xprofile data to the standard built in WordPress profile data.
 816   *
 817   * @since 1.0.0
 818   * @since 9.2.0 Adds the $args arguments to catch hook's additional arguments.
 819   *
 820   * @param int   $user_id ID of the user to sync.
 821   * @param array $args    Hook's additional arguments.
 822   * @return bool
 823   */
 824  function xprofile_sync_wp_profile( $user_id = 0, ...$args ) {
 825  
 826      // Bail if profile syncing is disabled.
 827      if ( bp_disable_profile_sync() ) {
 828          return true;
 829      }
 830  
 831      if ( empty( $user_id ) ) {
 832          $user_id = bp_loggedin_user_id();
 833      }
 834  
 835      if ( empty( $user_id ) ) {
 836          return false;
 837      }
 838  
 839      $fullname_field_id = (int) bp_xprofile_fullname_field_id();
 840      $usermeta          = array();
 841      $userdata          = array();
 842  
 843      if ( isset( $args[1]['meta'] ) ) {
 844          $usermeta = $args[1]['meta'];
 845      } elseif ( isset( $args[3] ) ) {
 846          $usermeta = $args[3];
 847      }
 848  
 849      if ( isset( $usermeta['profile_field_ids'] ) ) {
 850          $xprofile_fields = wp_parse_id_list( $usermeta['profile_field_ids'] );
 851          $xprofile_fields = array_diff( $xprofile_fields, array( $fullname_field_id ) );
 852  
 853          foreach ( $xprofile_fields as $xprofile_field_id ) {
 854              $field_type = bp_xprofile_get_field_type( $xprofile_field_id );
 855  
 856              $field_key = 'field_' . $xprofile_field_id;
 857              if ( isset( $field_type->wp_user_key ) && isset( $usermeta[ $field_key ] ) && $usermeta[ $field_key ] ) {
 858                  $userdata[ $field_type->wp_user_key ] = $usermeta[ $field_key ];
 859              }
 860          }
 861      }
 862  
 863      $fullname = xprofile_get_field_data( $fullname_field_id, $user_id );
 864      $space    = strpos( $fullname, ' ' );
 865  
 866      if ( false === $space ) {
 867          if ( ! isset( $userdata['first_name'] ) ) {
 868              $userdata['first_name'] = $fullname;
 869          }
 870  
 871          if ( ! isset( $userdata['last_name'] ) ) {
 872              $userdata['last_name'] = '';
 873          }
 874      } else {
 875          if ( ! isset( $userdata['first_name'] ) ) {
 876              $userdata['first_name'] = substr( $fullname, 0, $space );
 877          }
 878  
 879          if ( ! isset( $userdata['last_name'] ) ) {
 880              $userdata['last_name'] = trim( substr( $fullname, $space, strlen( $fullname ) ) );
 881          }
 882      }
 883  
 884      bp_update_user_meta( $user_id, 'nickname',   $fullname  );
 885      bp_update_user_meta( $user_id, 'first_name', $userdata['first_name'] );
 886      bp_update_user_meta( $user_id, 'last_name',  $userdata['last_name']  );
 887  
 888      wp_update_user( array( 'ID' => $user_id, 'display_name' => $fullname ) );
 889  }
 890  add_action( 'bp_core_signup_user', 'xprofile_sync_wp_profile', 10, 5 );
 891  add_action( 'bp_core_activated_user', 'xprofile_sync_wp_profile', 10, 3 );
 892  
 893  /**
 894   * Syncs the standard built in WordPress profile data to XProfile.
 895   *
 896   * @since 1.2.4
 897   *
 898   * @param object $errors Array of errors. Passed by reference.
 899   * @param bool   $update Whether or not being upated.
 900   * @param object $user   User object whose profile is being synced. Passed by reference.
 901   */
 902  function xprofile_sync_bp_profile( &$errors, $update, &$user ) {
 903  
 904      // Bail if profile syncing is disabled.
 905      if ( bp_disable_profile_sync() || ! $update || $errors->get_error_codes() ) {
 906          return;
 907      }
 908  
 909      xprofile_set_field_data( bp_xprofile_fullname_field_id(), $user->ID, $user->display_name );
 910  }
 911  add_action( 'user_profile_update_errors', 'xprofile_sync_bp_profile', 10, 3 );
 912  
 913  /**
 914   * Update the WP display, last, and first name fields when the xprofile display name field is updated.
 915   *
 916   * @since 3.0.0
 917   *
 918   * @param BP_XProfile_ProfileData $data Current instance of the profile data being saved.
 919   */
 920  function xprofile_sync_wp_profile_on_single_field_set( $data ) {
 921  
 922      if ( bp_xprofile_fullname_field_id() !== $data->field_id ) {
 923          return;
 924      }
 925  
 926      xprofile_sync_wp_profile( $data->user_id );
 927  }
 928  add_action( 'xprofile_data_after_save', 'xprofile_sync_wp_profile_on_single_field_set' );
 929  
 930  /**
 931   * When a user is deleted, we need to clean up the database and remove all the
 932   * profile data from each table. Also we need to clean anything up in the
 933   * usermeta table that this component uses.
 934   *
 935   * @since 1.0.0
 936   *
 937   * @param int $user_id The ID of the deleted user.
 938   */
 939  function xprofile_remove_data( $user_id ) {
 940      BP_XProfile_ProfileData::delete_data_for_user( $user_id );
 941  }
 942  add_action( 'wpmu_delete_user',  'xprofile_remove_data' );
 943  add_action( 'bp_make_spam_user', 'xprofile_remove_data' );
 944  
 945  /**
 946   * Deletes user XProfile data on the 'delete_user' hook.
 947   *
 948   * @since 6.0.0
 949   *
 950   * @param int $user_id The ID of the deleted user.
 951   */
 952  function xprofile_remove_data_on_delete_user( $user_id ) {
 953      if ( ! bp_remove_user_data_on_delete_user_hook( 'xprofile', $user_id ) ) {
 954          return;
 955      }
 956  
 957      xprofile_remove_data( $user_id );
 958  }
 959  add_action( 'delete_user', 'xprofile_remove_data_on_delete_user' );
 960  
 961  /*** XProfile Meta ****************************************************/
 962  
 963  /**
 964   * Delete a piece of xprofile metadata.
 965   *
 966   * @since 1.5.0
 967   *
 968   * @param int         $object_id   ID of the object the metadata belongs to.
 969   * @param string      $object_type Type of object. 'group', 'field', or 'data'.
 970   * @param string|bool $meta_key    Key of the metadata being deleted. If omitted, all
 971   *                                 metadata for the object will be deleted.
 972   * @param mixed       $meta_value  Optional. If provided, only metadata that matches
 973   *                                 the value will be permitted.
 974   * @param bool        $delete_all  Optional. If true, delete matching metadata entries
 975   *                                 for all objects, ignoring the specified object_id. Otherwise, only
 976   *                                 delete matching metadata entries for the specified object.
 977   *                                 Default: false.
 978   * @return bool True on success, false on failure.
 979   */
 980  function bp_xprofile_delete_meta( $object_id, $object_type, $meta_key = false, $meta_value = false, $delete_all = false ) {
 981      global $wpdb;
 982  
 983      // Sanitize object type.
 984      if ( ! in_array( $object_type, array( 'group', 'field', 'data' ) ) ) {
 985          return false;
 986      }
 987  
 988      // Legacy - if no meta_key is passed, delete all for the item.
 989      if ( empty( $meta_key ) ) {
 990          $table_key  = 'xprofile_' . $object_type . 'meta';
 991          $table_name = $wpdb->{$table_key};
 992          $keys = $wpdb->get_col( $wpdb->prepare( "SELECT meta_key FROM {$table_name} WHERE object_type = %s AND object_id = %d", $object_type, $object_id ) );
 993  
 994          // Force delete_all to false if deleting all for object.
 995          $delete_all = false;
 996      } else {
 997          $keys = array( $meta_key );
 998      }
 999  
1000      add_filter( 'query', 'bp_filter_metaid_column_name' );
1001      add_filter( 'query', 'bp_xprofile_filter_meta_query' );
1002  
1003      $retval = false;
1004      foreach ( $keys as $key ) {
1005          $retval = delete_metadata( 'xprofile_' . $object_type, $object_id, $key, $meta_value, $delete_all );
1006      }
1007  
1008      remove_filter( 'query', 'bp_xprofile_filter_meta_query' );
1009      remove_filter( 'query', 'bp_filter_metaid_column_name' );
1010  
1011      return $retval;
1012  }
1013  
1014  /**
1015   * Get a piece of xprofile metadata.
1016   *
1017   * Note that the default value of $single is true, unlike in the case of the
1018   * underlying get_metadata() function. This is for backward compatibility.
1019   *
1020   * @since 1.5.0
1021   *
1022   * @param int    $object_id   ID of the object the metadata belongs to.
1023   * @param string $object_type Type of object. 'group', 'field', or 'data'.
1024   * @param string $meta_key    Key of the metadata being fetched. If omitted, all
1025   *                            metadata for the object will be retrieved.
1026   * @param bool   $single      Optional. If true, return only the first value of the
1027   *                            specified meta_key. This parameter has no effect if meta_key is not
1028   *                            specified. Default: true.
1029   * @return mixed An array of values if `$single` is false.
1030   *               The value of the meta field if `$single` is true.
1031   *               False for an invalid `$object_type` (one of `group`, `field`, `data`).
1032   *               False for an invalid `$object_id` (non-numeric, zero, or negative value),
1033   *               or if `$meta_type` is not specified.
1034   *               An empty string if a valid but non-existing object ID is passed.
1035   */
1036  function bp_xprofile_get_meta( $object_id, $object_type, $meta_key = '', $single = true ) {
1037      // Sanitize object type.
1038      if ( ! in_array( $object_type, array( 'group', 'field', 'data' ) ) ) {
1039          return false;
1040      }
1041  
1042      add_filter( 'query', 'bp_filter_metaid_column_name' );
1043      add_filter( 'query', 'bp_xprofile_filter_meta_query' );
1044      $retval = get_metadata( 'xprofile_' . $object_type, $object_id, $meta_key, $single );
1045      remove_filter( 'query', 'bp_filter_metaid_column_name' );
1046      remove_filter( 'query', 'bp_xprofile_filter_meta_query' );
1047  
1048      return $retval;
1049  }
1050  
1051  /**
1052   * Update a piece of xprofile metadata.
1053   *
1054   * @since 1.5.0
1055   *
1056   * @param int    $object_id   ID of the object the metadata belongs to.
1057   * @param string $object_type Type of object. 'group', 'field', or 'data'.
1058   * @param string $meta_key    Key of the metadata being updated.
1059   * @param string $meta_value  Value of the metadata being updated.
1060   * @param mixed  $prev_value  Optional. If specified, only update existing
1061   *                            metadata entries with the specified value.
1062   *                            Otherwise update all entries.
1063   * @return bool|int Returns false on failure. On successful update of existing
1064   *                  metadata, returns true. On successful creation of new metadata,
1065   *                  returns the integer ID of the new metadata row.
1066   */
1067  function bp_xprofile_update_meta( $object_id, $object_type, $meta_key, $meta_value, $prev_value = '' ) {
1068      add_filter( 'query', 'bp_filter_metaid_column_name' );
1069      add_filter( 'query', 'bp_xprofile_filter_meta_query' );
1070      $retval = update_metadata( 'xprofile_' . $object_type, $object_id, $meta_key, $meta_value, $prev_value );
1071      remove_filter( 'query', 'bp_xprofile_filter_meta_query' );
1072      remove_filter( 'query', 'bp_filter_metaid_column_name' );
1073  
1074      return $retval;
1075  }
1076  
1077  /**
1078   * Add a piece of xprofile metadata.
1079   *
1080   * @since 2.0.0
1081   *
1082   * @param int    $object_id   ID of the object the metadata belongs to.
1083   * @param string $object_type Type of object. 'group', 'field', or 'data'.
1084   * @param string $meta_key    Metadata key.
1085   * @param mixed  $meta_value  Metadata value.
1086   * @param bool   $unique      Optional. Whether to enforce a single metadata value
1087   *                            for the given key. If true, and the object already
1088   *                            has a value for the key, no change will be made.
1089   *                            Default false.
1090   * @return int|bool The meta ID on successful update, false on failure.
1091   */
1092  function bp_xprofile_add_meta( $object_id, $object_type, $meta_key, $meta_value, $unique = false ) {
1093      add_filter( 'query', 'bp_filter_metaid_column_name' );
1094      add_filter( 'query', 'bp_xprofile_filter_meta_query' );
1095      $retval = add_metadata( 'xprofile_' . $object_type , $object_id, $meta_key, $meta_value, $unique );
1096      remove_filter( 'query', 'bp_filter_metaid_column_name' );
1097      remove_filter( 'query', 'bp_xprofile_filter_meta_query' );
1098  
1099      return $retval;
1100  }
1101  
1102  /**
1103   * Updates the fieldgroup metadata.
1104   *
1105   * @since 1.5.0
1106   *
1107   * @param int    $field_group_id Group ID for the group field belongs to.
1108   * @param string $meta_key       Meta key to update.
1109   * @param string $meta_value     Meta value to update to.
1110   * @return bool|int
1111   */
1112  function bp_xprofile_update_fieldgroup_meta( $field_group_id, $meta_key, $meta_value ) {
1113      return bp_xprofile_update_meta( $field_group_id, 'group', $meta_key, $meta_value );
1114  }
1115  
1116  /**
1117   * Updates the field metadata.
1118   *
1119   * @since 1.5.0
1120   *
1121   * @param int    $field_id   Field ID to update.
1122   * @param string $meta_key   Meta key to update.
1123   * @param string $meta_value Meta value to update to.
1124   * @return bool|int
1125   */
1126  function bp_xprofile_update_field_meta( $field_id, $meta_key, $meta_value ) {
1127      return bp_xprofile_update_meta( $field_id, 'field', $meta_key, $meta_value );
1128  }
1129  
1130  /**
1131   * Updates the fielddata metadata.
1132   *
1133   * @since 1.5.0
1134   *
1135   * @param int    $field_data_id Field ID to update.
1136   * @param string $meta_key      Meta key to update.
1137   * @param string $meta_value    Meta value to update to.
1138   * @return bool|int
1139   */
1140  function bp_xprofile_update_fielddata_meta( $field_data_id, $meta_key, $meta_value ) {
1141      return bp_xprofile_update_meta( $field_data_id, 'data', $meta_key, $meta_value );
1142  }
1143  
1144  /**
1145   * Return the field ID for the Full Name xprofile field.
1146   *
1147   * @since 2.0.0
1148   *
1149   * @return int Field ID.
1150   */
1151  function bp_xprofile_fullname_field_id() {
1152      $id = wp_cache_get( 'fullname_field_id', 'bp_xprofile' );
1153  
1154      if ( false === $id ) {
1155          global $wpdb;
1156  
1157          $bp = buddypress();
1158          $id = $wpdb->get_var( $wpdb->prepare( "SELECT id FROM {$bp->profile->table_name_fields} WHERE name = %s", addslashes( bp_xprofile_fullname_field_name() ) ) );
1159  
1160          wp_cache_set( 'fullname_field_id', $id, 'bp_xprofile' );
1161      }
1162  
1163      return absint( $id );
1164  }
1165  
1166  /**
1167   * Return the field name for the Full Name xprofile field.
1168   *
1169   * @since 1.5.0
1170   *
1171   * @return string The field name.
1172   */
1173  function bp_xprofile_fullname_field_name() {
1174  
1175      /**
1176       * Filters the field name for the Full Name xprofile field.
1177       *
1178       * @since 1.5.0
1179       *
1180       * @param string $value BP_XPROFILE_FULLNAME_FIELD_NAME Full name field constant.
1181       */
1182      return apply_filters( 'bp_xprofile_fullname_field_name', BP_XPROFILE_FULLNAME_FIELD_NAME );
1183  }
1184  
1185  /**
1186   * Is rich text enabled for this profile field?
1187   *
1188   * By default, rich text is enabled for textarea fields and disabled for all other field types.
1189   *
1190   * @since 2.4.0
1191   *
1192   * @param int|null $field_id Optional. Default current field ID.
1193   * @return bool
1194   */
1195  function bp_xprofile_is_richtext_enabled_for_field( $field_id = null ) {
1196      if ( ! $field_id ) {
1197          $field_id = bp_get_the_profile_field_id();
1198      }
1199  
1200      $field = xprofile_get_field( $field_id, null, false );
1201  
1202      $enabled = false;
1203      if ( $field instanceof BP_XProfile_Field ) {
1204          $enabled = (bool) $field->type_obj->supports_richtext;
1205      }
1206  
1207      /**
1208       * Filters whether richtext is enabled for the given field.
1209       *
1210       * @since 2.4.0
1211       *
1212       * @param bool $enabled  True if richtext is enabled for the field, otherwise false.
1213       * @param int  $field_id ID of the field.
1214       */
1215      return apply_filters( 'bp_xprofile_is_richtext_enabled_for_field', $enabled, $field_id );
1216  }
1217  
1218  /**
1219   * Get visibility levels out of the $bp global.
1220   *
1221   * @since 1.6.0
1222   *
1223   * @return array
1224   */
1225  function bp_xprofile_get_visibility_levels() {
1226  
1227      /**
1228       * Filters the visibility levels out of the $bp global.
1229       *
1230       * @since 1.6.0
1231       *
1232       * @param array $visibility_levels Array of visibility levels.
1233       */
1234      return apply_filters( 'bp_xprofile_get_visibility_levels', buddypress()->profile->visibility_levels );
1235  }
1236  
1237  /**
1238   * Get the ids of fields that are hidden for this displayed/loggedin user pair.
1239   *
1240   * This is the function primarily responsible for profile field visibility. It works by determining
1241   * the relationship between the displayed_user (ie the profile owner) and the current_user (ie the
1242   * profile viewer). Then, based on that relationship, we query for the set of fields that should
1243   * be excluded from the profile loop.
1244   *
1245   * @since 1.6.0
1246   *
1247   * @see BP_XProfile_Group::get()
1248   *   or if you have added your own custom levels.
1249   *
1250   * @param int $displayed_user_id The id of the user the profile fields belong to.
1251   * @param int $current_user_id   The id of the user viewing the profile.
1252   * @return array An array of field ids that should be excluded from the profile query
1253   */
1254  function bp_xprofile_get_hidden_fields_for_user( $displayed_user_id = 0, $current_user_id = 0 ) {
1255      if ( !$displayed_user_id ) {
1256          $displayed_user_id = bp_displayed_user_id();
1257      }
1258  
1259      if ( !$displayed_user_id ) {
1260          return array();
1261      }
1262  
1263      if ( !$current_user_id ) {
1264          $current_user_id = bp_loggedin_user_id();
1265      }
1266  
1267      // @todo - This is where you'd swap out for current_user_can() checks.
1268      $hidden_levels = bp_xprofile_get_hidden_field_types_for_user( $displayed_user_id, $current_user_id );
1269      $hidden_fields = bp_xprofile_get_fields_by_visibility_levels( $displayed_user_id, $hidden_levels );
1270  
1271      /**
1272       * Filters the ids of fields that are hidden for this displayed/loggedin user pair.
1273       *
1274       * @since 1.6.0
1275       *
1276       * @param array $hidden_fields     Array of hidden fields for the displayed/logged in user.
1277       * @param int   $displayed_user_id ID of the displayed user.
1278       * @param int   $current_user_id   ID of the current user.
1279       */
1280      return apply_filters( 'bp_xprofile_get_hidden_fields_for_user', $hidden_fields, $displayed_user_id, $current_user_id );
1281  }
1282  
1283  /**
1284   * Get the visibility levels that should be hidden for this user pair.
1285   *
1286   * Field visibility is determined based on the relationship between the
1287   * logged-in user, the displayed user, and the visibility setting for the
1288   * current field. (See bp_xprofile_get_hidden_fields_for_user().) This
1289   * utility function speeds up this matching by fetching the visibility levels
1290   * that should be hidden for the current user pair.
1291   *
1292   * @since 1.8.2
1293   *
1294   * @see bp_xprofile_get_hidden_fields_for_user()
1295   *
1296   * @param int $displayed_user_id The id of the user the profile fields belong to.
1297   * @param int $current_user_id   The id of the user viewing the profile.
1298   * @return array An array of visibility levels hidden to the current user.
1299   */
1300  function bp_xprofile_get_hidden_field_types_for_user( $displayed_user_id = 0, $current_user_id = 0 ) {
1301  
1302      // Current user is logged in.
1303      if ( ! empty( $current_user_id ) ) {
1304  
1305          // Nothing's private when viewing your own profile, or when the
1306          // current user is an admin.
1307          if ( $displayed_user_id == $current_user_id || bp_current_user_can( 'bp_moderate' ) ) {
1308              $hidden_levels = array();
1309  
1310          // If the current user and displayed user are friends, show all.
1311          } elseif ( bp_is_active( 'friends' ) && friends_check_friendship( $displayed_user_id, $current_user_id ) ) {
1312              $hidden_levels = array( 'adminsonly', );
1313  
1314          // Current user is logged in but not friends, so exclude friends-only.
1315          } else {
1316              $hidden_levels = array( 'friends', 'adminsonly', );
1317          }
1318  
1319      // Current user is not logged in, so exclude friends-only, loggedin, and adminsonly.
1320      } else {
1321          $hidden_levels = array( 'friends', 'loggedin', 'adminsonly', );
1322      }
1323  
1324      /**
1325       * Filters the visibility levels that should be hidden for this user pair.
1326       *
1327       * @since 2.0.0
1328       *
1329       * @param array $hidden_fields     Array of hidden fields for the displayed/logged in user.
1330       * @param int   $displayed_user_id ID of the displayed user.
1331       * @param int   $current_user_id   ID of the current user.
1332       */
1333      return apply_filters( 'bp_xprofile_get_hidden_field_types_for_user', $hidden_levels, $displayed_user_id, $current_user_id );
1334  }
1335  
1336  /**
1337   * Fetch an array of the xprofile fields that a given user has marked with certain visibility levels.
1338   *
1339   * @since 1.6.0
1340   *
1341   * @see bp_xprofile_get_hidden_fields_for_user()
1342   *
1343   * @param int   $user_id The id of the profile owner.
1344   * @param array $levels  An array of visibility levels ('public', 'friends', 'loggedin', 'adminsonly' etc) to be
1345   *                       checked against.
1346   * @return array $field_ids The fields that match the requested visibility levels for the given user.
1347   */
1348  function bp_xprofile_get_fields_by_visibility_levels( $user_id, $levels = array() ) {
1349      if ( !is_array( $levels ) ) {
1350          $levels = (array)$levels;
1351      }
1352  
1353      $user_visibility_levels = (array) bp_get_user_meta( $user_id, 'bp_xprofile_visibility_levels', true );
1354  
1355      // Parse the user-provided visibility levels with the default levels, which may take
1356      // precedence.
1357      $default_visibility_levels = BP_XProfile_Group::fetch_default_visibility_levels();
1358  
1359      foreach( (array) $default_visibility_levels as $d_field_id => $defaults ) {
1360          // If the admin has forbidden custom visibility levels for this field, replace
1361          // the user-provided setting with the default specified by the admin.
1362          if ( isset( $defaults['allow_custom'] ) && isset( $defaults['default'] ) && 'disabled' == $defaults['allow_custom'] ) {
1363              $user_visibility_levels[$d_field_id] = $defaults['default'];
1364          }
1365      }
1366  
1367      $field_ids = array();
1368      foreach( $user_visibility_levels as $field_id => $field_visibility ) {
1369          if ( in_array( $field_visibility, $levels ) ) {
1370              $field_ids[] = $field_id;
1371          }
1372      }
1373  
1374      // Never allow the fullname field to be excluded.
1375      if ( in_array( 1, $field_ids ) ) {
1376          $key = array_search( 1, $field_ids );
1377          unset( $field_ids[$key] );
1378      }
1379  
1380      return $field_ids;
1381  }
1382  
1383  /**
1384   * Formats datebox field values passed through a POST request.
1385   *
1386   * @since 2.8.0
1387   *
1388   * @param int $field_id The id of the current field being looped through.
1389   * @return void This function only changes the global $_POST that should contain
1390   *              the datebox data.
1391   */
1392  function bp_xprofile_maybe_format_datebox_post_data( $field_id ) {
1393      if ( ! isset( $_POST['field_' . $field_id] ) ) {
1394          if ( ! empty( $_POST['field_' . $field_id . '_day'] ) && ! empty( $_POST['field_' . $field_id . '_month'] ) && ! empty( $_POST['field_' . $field_id . '_year'] ) ) {
1395              // Concatenate the values.
1396              $date_value = $_POST['field_' . $field_id . '_day'] . ' ' . $_POST['field_' . $field_id . '_month'] . ' ' . $_POST['field_' . $field_id . '_year'];
1397  
1398              // Check that the concatenated value can be turned into a timestamp.
1399              if ( $timestamp = strtotime( $date_value ) ) {
1400                  // Add the timestamp to the global $_POST that should contain the datebox data.
1401                  $_POST['field_' . $field_id] = date( 'Y-m-d H:i:s', $timestamp );
1402              }
1403          }
1404      }
1405  }
1406  
1407  /**
1408   * Finds and exports personal data associated with an email address from the XProfile tables.
1409   *
1410   * @since 4.0.0
1411   *
1412   * @param string $email_address  The users email address.
1413   * @return array An array of personal data.
1414   */
1415  function bp_xprofile_personal_data_exporter( $email_address ) {
1416      $email_address = trim( $email_address );
1417  
1418      $data_to_export = array();
1419  
1420      $user = get_user_by( 'email', $email_address );
1421  
1422      if ( ! $user ) {
1423          return array(
1424              'data' => array(),
1425              'done' => true,
1426          );
1427      }
1428  
1429      $user_data_to_export = array();
1430  
1431      $user_profile_data = BP_XProfile_ProfileData::get_all_for_user( $user->ID );
1432      foreach ( $user_profile_data as $field_name => $field ) {
1433          // Skip non-array fields, which don't belong to XProfile.
1434          if ( ! is_array( $field ) ) {
1435              continue;
1436          }
1437  
1438          // Re-pull the data so that BuddyPress formats and sanitizes properly.
1439          $value = xprofile_get_field_data( $field['field_id'], $user->ID, 'comma' );
1440          $user_data_to_export[] = array(
1441              'name'  => $field_name,
1442              'value' => $value,
1443          );
1444      }
1445  
1446      $data_to_export[] = array(
1447          'group_id'    => 'bp_xprofile',
1448          'group_label' => __( 'Extended Profile Data', 'buddypress' ),
1449          'item_id'     => "bp-xprofile-{$user->ID}",
1450          'data'        => $user_data_to_export,
1451      );
1452  
1453      return array(
1454          'data' => $data_to_export,
1455          'done' => true,
1456      );
1457  }
1458  
1459  /**
1460   * Returns the list of supporterd WordPress field meta keys.
1461   *
1462   * @since 8.0.0
1463   *
1464   * @return string[] List of supported WordPress user keys.
1465   */
1466  function bp_xprofile_get_wp_user_keys() {
1467      return array_merge(
1468          array( 'first_name', 'last_name', 'user_url', 'description' ),
1469          array_keys( wp_get_user_contact_methods() )
1470      );
1471  }
1472  
1473  /**
1474   * Returns the signup field IDs.
1475   *
1476   * @since 8.0.0
1477   *
1478   * @return int[] The signup field IDs.
1479   */
1480  function bp_xprofile_get_signup_field_ids() {
1481      $signup_field_ids = wp_cache_get( 'signup_fields', 'bp_xprofile' );
1482  
1483      if ( ! $signup_field_ids ) {
1484          global $wpdb;
1485          $bp = buddypress();
1486  
1487          $signup_field_ids = $wpdb->get_col( "SELECT object_id FROM {$bp->profile->table_name_meta} WHERE object_type = 'field' AND meta_key = 'signup_position' ORDER BY CONVERT(meta_value, SIGNED) ASC" );
1488  
1489          wp_cache_set( 'signup_fields', $signup_field_ids, 'bp_xprofile' );
1490      }
1491  
1492      return array_map( 'intval', $signup_field_ids );
1493  }
1494  
1495  /**
1496   * Returns xProfile loop's signup arguments.
1497   *
1498   * @since 8.0.0
1499   *
1500   * @param array $extra Optional extra arguments.
1501   * @return array The xProfile loop's signup arguments.
1502   */
1503  function bp_xprofile_signup_args( $extra = array() ) {
1504      $signup_fields = (array) bp_xprofile_get_signup_field_ids();
1505      $default_args  = array(
1506          'fetch_fields'     => true,
1507          'fetch_field_data' => false,
1508      );
1509  
1510      // No signup fields? Let's bring back primary group.
1511      if ( ! $signup_fields && bp_is_register_page() ) {
1512          $default_args['profile_group_id'] = 1;
1513      } else {
1514          $default_args['signup_fields_only'] = true;
1515      }
1516  
1517      return array_merge( $default_args, $extra );
1518  }


Generated: Tue Oct 26 01:00:55 2021 Cross-referenced by PHPXref 0.7.1