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


Generated: Mon Aug 2 01:01:43 2021 Cross-referenced by PHPXref 0.7.1