· 5 years ago · Aug 15, 2020, 09:34 AM
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 BuddyBoss\XProfile
11 * @since BuddyPress 1.5.0
12 */
13
14// Exit if accessed directly.
15defined( 'ABSPATH' ) || exit;
16
17/*** Field Group Management **************************************************/
18
19/**
20 * Fetch a set of field groups, populated with fields and field data.
21 *
22 * Procedural wrapper for BP_XProfile_Group::get() method.
23 *
24 * @since BuddyPress 2.1.0
25 *
26 * @param array $args See {@link BP_XProfile_Group::get()} for description of arguments.
27 * @return array $groups
28 */
29function bp_xprofile_get_groups( $args = array() ) {
30
31 /**
32 * For repeaters, automatically set the parameter value
33 * to determine if we should display only the template fields
34 * or only the clone fields
35 */
36
37 if ( ! isset( $args['repeater_show_main_fields_only'] ) ) {
38 $repeater_show_main_fields_only = true;
39
40 // If on a user profile
41 if ( 'profile' == bp_current_component() ) {
42 $repeater_show_main_fields_only = false;
43 }
44
45 $args['repeater_show_main_fields_only'] = apply_filters( 'bp_xprofile_get_groups_repeater_show_main_fields_only', $repeater_show_main_fields_only );
46 }
47
48 $groups = BP_XProfile_Group::get( $args );
49
50 /**
51 * Filters a set of field groups, populated with fields and field data.
52 *
53 * @since BuddyPress 2.1.0
54 *
55 * @param array $groups Array of field groups and field data.
56 * @param array $args Array of arguments used to query for groups.
57 */
58 return apply_filters( 'bp_xprofile_get_groups', $groups, $args );
59}
60
61/**
62 * Insert a new profile field group.
63 *
64 * @since BuddyPress 1.0.0
65 *
66 * @param array|string $args {
67 * Array of arguments for field group insertion.
68 *
69 * @type int|bool $field_group_id ID of the field group to insert into.
70 * @type string|bool $name Name of the group.
71 * @type string $description Field group description.
72 * @type bool $can_delete Whether or not the field group can be deleted.
73 * }
74 * @return boolean
75 */
76function xprofile_insert_field_group( $args = '' ) {
77
78 // Parse the arguments.
79 $r = bp_parse_args(
80 $args,
81 array(
82 'field_group_id' => false,
83 'name' => false,
84 'description' => '',
85 'can_delete' => true,
86 ),
87 'xprofile_insert_field_group'
88 );
89
90 // Bail if no group name.
91 if ( empty( $r['name'] ) ) {
92 return false;
93 }
94
95 // Create new field group object, maybe using an existing ID.
96 $field_group = new BP_XProfile_Group( $r['field_group_id'] );
97 $field_group->name = $r['name'];
98 $field_group->description = $r['description'];
99 $field_group->can_delete = $r['can_delete'];
100
101 return $field_group->save();
102}
103
104/**
105 * Get a specific profile field group.
106 *
107 * @since BuddyPress 1.0.0
108 *
109 * @param int $field_group_id Field group ID to fetch.
110 * @return false|BP_XProfile_Group
111 */
112function xprofile_get_field_group( $field_group_id = 0 ) {
113
114 // Try to get a specific field group by ID.
115 $field_group = new BP_XProfile_Group( $field_group_id );
116
117 // Bail if group was not found.
118 if ( empty( $field_group->id ) ) {
119 return false;
120 }
121
122 // Return field group.
123 return $field_group;
124}
125
126/**
127 * Delete a specific profile field group.
128 *
129 * @since BuddyPress 1.0.0
130 *
131 * @param int $field_group_id Field group ID to delete.
132 * @return boolean
133 */
134function xprofile_delete_field_group( $field_group_id = 0 ) {
135
136 // Try to get a specific field group by ID.
137 $field_group = xprofile_get_field_group( $field_group_id );
138
139 // Bail if group was not found.
140 if ( false === $field_group ) {
141 return false;
142 }
143
144 // Return the results of trying to delete the field group.
145 return $field_group->delete();
146}
147
148/**
149 * Update the position of a specific profile field group.
150 *
151 * @since BuddyPress 1.0.0
152 *
153 * @param int $field_group_id Field group ID to update.
154 * @param int $position Field group position to update to.
155 * @return boolean
156 */
157function xprofile_update_field_group_position( $field_group_id = 0, $position = 0 ) {
158 return BP_XProfile_Group::update_position( $field_group_id, $position );
159}
160
161/*** Field Management *********************************************************/
162
163/**
164 * Get details of all xprofile field types.
165 *
166 * @since BuddyPress 2.0.0
167 *
168 * @return array Key/value pairs (field type => class name).
169 */
170function bp_xprofile_get_field_types() {
171 $fields = array(
172 'checkbox' => 'BP_XProfile_Field_Type_Checkbox',
173 'datebox' => 'BP_XProfile_Field_Type_Datebox',
174 'multiselectbox' => 'BP_XProfile_Field_Type_Multiselectbox',
175 'number' => 'BP_XProfile_Field_Type_Number',
176 'url' => 'BP_XProfile_Field_Type_URL',
177 'radio' => 'BP_XProfile_Field_Type_Radiobutton',
178 'selectbox' => 'BP_XProfile_Field_Type_Selectbox',
179 'textarea' => 'BP_XProfile_Field_Type_Textarea',
180 'textbox' => 'BP_XProfile_Field_Type_Textbox',
181 'telephone' => 'BP_XProfile_Field_Type_Telephone',
182 'gender' => 'BP_XProfile_Field_Type_Gender',
183 'socialnetworks' => 'BP_XProfile_Field_Type_Social_Networks',
184 );
185
186 if ( function_exists( 'bp_member_type_enable_disable' ) && true === bp_member_type_enable_disable() ) {
187 $fields['membertypes'] = 'BP_XProfile_Field_Type_Member_Types';
188 }
189
190 /**
191 * Filters the list of all xprofile field types.
192 *
193 * If you've added a custom field type in a plugin, register it with this filter.
194 *
195 * @since BuddyPress 2.0.0
196 *
197 * @param array $fields Array of field type/class name pairings.
198 */
199 return apply_filters( 'bp_xprofile_get_field_types', $fields );
200}
201
202/**
203 * Creates the specified field type object; used for validation and templating.
204 *
205 * @since BuddyPress 2.0.0
206 *
207 * @param string $type Type of profile field to create. See {@link bp_xprofile_get_field_types()} for default core values.
208 * @return object $value If field type unknown, returns BP_XProfile_Field_Type_Textarea.
209 * Otherwise returns an instance of the relevant child class of BP_XProfile_Field_Type.
210 */
211function bp_xprofile_create_field_type( $type ) {
212
213 $field = bp_xprofile_get_field_types();
214 $class = isset( $field[ $type ] ) ? $field[ $type ] : '';
215
216 /**
217 * To handle (missing) field types, fallback to a placeholder field object if a type is unknown.
218 */
219 if ( $class && class_exists( $class ) ) {
220 return new $class();
221 } else {
222 return new BP_XProfile_Field_Type_Placeholder();
223 }
224}
225
226/**
227 * Insert or update an xprofile field.
228 *
229 * @since BuddyPress 1.1.0
230 *
231 * @param array|string $args {
232 * Array of arguments.
233 * @type int $field_id Optional. Pass the ID of an existing field to edit that field.
234 * @type int $field_group_id ID of the associated field group.
235 * @type int $parent_id Optional. ID of the parent field.
236 * @type string $type Field type. Checked against a field_types whitelist.
237 * @type string $name Name of the new field.
238 * @type string $description Optional. Descriptive text for the field.
239 * @type bool $is_required Optional. Whether users must provide a value for the field. Default: false.
240 * @type bool $can_delete Optional. Whether admins can delete this field in the Dashboard interface.
241 * Generally this is false only for the Name field, which is required throughout BP.
242 * Default: true.
243 * @type string $order_by Optional. For field types that support options (such as 'radio'), this flag
244 * determines whether the sort order of the options will be 'default'
245 * (order created) or 'custom'.
246 * @type bool $is_default_option Optional. For the 'option' field type, setting this value to true means that
247 * it'll be the default value for the parent field when the user has not yet
248 * overridden. Default: true.
249 * @type int $option_order Optional. For the 'option' field type, this determines the order in which the
250 * options appear.
251 * }
252 * @return bool|int False on failure, ID of new field on success.
253 */
254function xprofile_insert_field( $args = '' ) {
255
256 $r = wp_parse_args(
257 $args,
258 array(
259 'field_id' => null,
260 'field_group_id' => null,
261 'parent_id' => null,
262 'type' => '',
263 'name' => '',
264 'description' => '',
265 'is_required' => false,
266 'can_delete' => true,
267 'order_by' => '',
268 'is_default_option' => false,
269 'option_order' => null,
270 'field_order' => null,
271 )
272 );
273
274 // Field_group_id is required.
275 if ( empty( $r['field_group_id'] ) ) {
276 return false;
277 }
278
279 // Check this is a non-empty, valid field type.
280 if ( ! in_array( $r['type'], (array) buddypress()->profile->field_types ) ) {
281 return false;
282 }
283
284 // Instantiate a new field object.
285 if ( ! empty( $r['field_id'] ) ) {
286 $field = xprofile_get_field( $r['field_id'] );
287 } else {
288 $field = new BP_XProfile_Field();
289 }
290
291 $field->group_id = $r['field_group_id'];
292 $field->type = $r['type'];
293
294 // The 'name' field cannot be empty.
295 if ( ! empty( $r['name'] ) ) {
296 $field->name = $r['name'];
297 }
298
299 $field->description = $r['description'];
300 $field->order_by = $r['order_by'];
301 $field->parent_id = (int) $r['parent_id'];
302 $field->field_order = (int) $r['field_order'];
303 $field->option_order = (int) $r['option_order'];
304 $field->is_required = (bool) $r['is_required'];
305 $field->can_delete = (bool) $r['can_delete'];
306 $field->is_default_option = (bool) $r['is_default_option'];
307
308 return $field->save();
309}
310
311/**
312 * Get a profile field object.
313 *
314 * @since BuddyPress 1.1.0
315 * @since BuddyPress 2.8.0 Added `$user_id` and `$get_data` parameters.
316 *
317 * @param int|object $field ID of the field or object representing field data.
318 * @param int|null $user_id Optional. ID of the user associated with the field.
319 * Ignored if `$get_data` is false. If `$get_data` is
320 * true, but no `$user_id` is provided, defaults to
321 * logged-in user ID.
322 * @param bool $get_data Whether to fetch data for the specified `$user_id`.
323 * @return BP_XProfile_Field|null Field object if found, otherwise null.
324 */
325function xprofile_get_field( $field, $user_id = null, $get_data = true ) {
326 if ( $field instanceof BP_XProfile_Field ) {
327 $_field = $field;
328 } elseif ( is_object( $field ) ) {
329 $_field = new BP_XProfile_Field();
330 $_field->fill_data( $field );
331 } else {
332 $_field = BP_XProfile_Field::get_instance( $field, $user_id, $get_data );
333 }
334
335 if ( ! $_field ) {
336 return null;
337 }
338
339 return $_field;
340}
341
342/**
343 * Delete a profile field object.
344 *
345 * @since BuddyPress 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 */
350function 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 BuddyPress 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 */
372function 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 BuddyPress 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 BuddyPress 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 */
432function 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 BuddyPress 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 whitelist.
485 if ( $field_type_obj->supports_options ) {
486 $field_type_obj->set_whitelist_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 = new BP_XProfile_ProfileData();
495 $field->field_id = $field_id;
496 $field->user_id = $user_id;
497
498 // Gets un/reserialized via xprofile_sanitize_data_value_before_save()
499 $field->value = maybe_serialize( $value );
500
501 return $field->save();
502}
503
504/**
505 * Set the visibility level for this field.
506 *
507 * @since BuddyPress 1.6.0
508 *
509 * @param int $field_id The ID of the xprofile field.
510 * @param int $user_id The ID of the user to whom the data belongs.
511 * @param string $visibility_level What the visibity setting should be.
512 * @return bool True on success
513 */
514function xprofile_set_field_visibility_level( $field_id = 0, $user_id = 0, $visibility_level = '' ) {
515 if ( empty( $field_id ) || empty( $user_id ) || empty( $visibility_level ) ) {
516 return false;
517 }
518
519 // Check against a whitelist.
520 $allowed_values = bp_xprofile_get_visibility_levels();
521 if ( ! array_key_exists( $visibility_level, $allowed_values ) ) {
522 return false;
523 }
524
525 // Stored in an array in usermeta.
526 $current_visibility_levels = bp_get_user_meta( $user_id, 'bp_xprofile_visibility_levels', true );
527
528 if ( ! $current_visibility_levels ) {
529 $current_visibility_levels = array();
530 }
531
532 $current_visibility_levels[ $field_id ] = $visibility_level;
533
534 return bp_update_user_meta( $user_id, 'bp_xprofile_visibility_levels', $current_visibility_levels );
535}
536
537/**
538 * Get the visibility level for a field.
539 *
540 * @since BuddyPress 2.0.0
541 *
542 * @param int $field_id The ID of the xprofile field.
543 * @param int $user_id The ID of the user to whom the data belongs.
544 * @return string
545 */
546function xprofile_get_field_visibility_level( $field_id = 0, $user_id = 0 ) {
547 $current_level = '';
548
549 if ( empty( $field_id ) || empty( $user_id ) ) {
550 return $current_level;
551 }
552
553 $current_levels = bp_get_user_meta( $user_id, 'bp_xprofile_visibility_levels', true );
554 $current_level = isset( $current_levels[ $field_id ] ) ? $current_levels[ $field_id ] : '';
555
556 // Use the user's stored level, unless custom visibility is disabled.
557 $field = xprofile_get_field( $field_id );
558 if ( isset( $field->allow_custom_visibility ) && 'disabled' === $field->allow_custom_visibility ) {
559 $current_level = $field->default_visibility;
560 }
561
562 // If we're still empty, it means that overrides are permitted, but the
563 // user has not provided a value. Use the default value.
564 if ( empty( $current_level ) ) {
565 $current_level = $field->default_visibility;
566 }
567
568 return $current_level;
569}
570
571/**
572 * Delete XProfile field data.
573 *
574 * @since BuddyPress 1.1.0
575 *
576 * @param string $field Field to delete.
577 * @param int $user_id User ID to delete field from.
578 * @return bool Whether or not the field was deleted.
579 */
580function xprofile_delete_field_data( $field = '', $user_id = 0 ) {
581
582 // Get the field ID.
583 if ( is_numeric( $field ) ) {
584 $field_id = (int) $field;
585 } else {
586 $field_id = xprofile_get_field_id_from_name( $field );
587 }
588
589 // Bail if field or user ID are empty.
590 if ( empty( $field_id ) || empty( $user_id ) ) {
591 return false;
592 }
593
594 // Get the profile field data to delete.
595 $field = new BP_XProfile_ProfileData( $field_id, $user_id );
596
597 // Delete the field data.
598 return $field->delete();
599}
600
601/**
602 * Check if field is a required field.
603 *
604 * @since BuddyPress 1.1.0
605 *
606 * @param int $field_id ID of the field to check for.
607 * @return bool Whether or not field is required.
608 */
609function xprofile_check_is_required_field( $field_id ) {
610 $field = new BP_XProfile_Field( $field_id );
611 $retval = false;
612
613 if ( isset( $field->is_required ) ) {
614 $retval = $field->is_required;
615 }
616
617 return (bool) $retval;
618}
619
620/**
621 * Validate profile field.
622 *
623 * @since BuddyBoss 1.0.0
624 */
625function xprofile_validate_field( $field_id, $value, $UserId ) {
626 return apply_filters( 'xprofile_validate_field', '', $field_id, $value, $UserId );
627}
628
629/**
630 * Returns the ID for the field based on the field name.
631 *
632 * @since BuddyPress 1.0.0
633 *
634 * @param string $field_name The name of the field to get the ID for.
635 * @return int|null $field_id on success, false on failure.
636 */
637function xprofile_get_field_id_from_name( $field_name ) {
638 return BP_XProfile_Field::get_id_from_name( $field_name );
639}
640
641/**
642 * Fetches a random piece of profile data for the user.
643 *
644 * @since BuddyPress 1.0.0
645 *
646 * @global BuddyPress $bp The one true BuddyPress instance.
647 * @global wpdb $wpdb WordPress database abstraction object.
648 * @global object $current_user WordPress global variable containing current logged in user information.
649 *
650 * @param int $user_id User ID of the user to get random data for.
651 * @param bool $exclude_fullname Optional; whether or not to exclude the full name field as random data.
652 * Defaults to true.
653 * @return string|bool The fetched random data for the user, or false if no data or no match.
654 */
655function xprofile_get_random_profile_data( $user_id, $exclude_fullname = true ) {
656 $field_data = BP_XProfile_ProfileData::get_random( $user_id, $exclude_fullname );
657
658 if ( empty( $field_data ) ) {
659 return false;
660 }
661
662 $field_data[0]->value = xprofile_format_profile_field( $field_data[0]->type, $field_data[0]->value );
663
664 if ( empty( $field_data[0]->value ) ) {
665 return false;
666 }
667
668 /**
669 * Filters a random piece of profile data for the user.
670 *
671 * @since BuddyPress 1.0.0
672 *
673 * @param array $field_data Array holding random profile data.
674 */
675 return apply_filters( 'xprofile_get_random_profile_data', $field_data );
676}
677
678/**
679 * Formats a profile field according to its type. [ TODO: Should really be moved to filters ]
680 *
681 * @since BuddyPress 1.0.0
682 *
683 * @param string $field_type The type of field: datebox, selectbox, textbox etc.
684 * @param string $field_value The actual value.
685 * @return string|bool The formatted value, or false if value is empty.
686 */
687function xprofile_format_profile_field( $field_type, $field_value ) {
688
689 if ( empty( $field_value ) ) {
690 return false;
691 }
692
693 $field_value = bp_unserialize_profile_field( $field_value );
694
695 if ( 'datebox' != $field_type ) {
696 $content = $field_value;
697 $field_value = str_replace( ']]>', ']]>', $content );
698 }
699
700 return xprofile_filter_format_field_value_by_type( stripslashes_deep( $field_value ), $field_type );
701}
702
703/**
704 * Update the field position for a provided field.
705 *
706 * @since BuddyPress 1.1.0
707 *
708 * @param int $field_id ID of the field to update.
709 * @param int $position Position to update the field to.
710 * @param int $field_group_id Group ID for group the field is in.
711 * @return bool
712 */
713function xprofile_update_field_position( $field_id, $position, $field_group_id ) {
714 return BP_XProfile_Field::update_position( $field_id, $position, $field_group_id );
715}
716
717/**
718 * Replace the displayed and logged-in users fullnames with the xprofile name, if required.
719 *
720 * The Members component uses the logged-in user's display_name to set the
721 * value of buddypress()->loggedin_user->fullname. However, in cases where
722 * profile sync is disabled, display_name may diverge from the xprofile
723 * fullname field value, and the xprofile field should take precedence.
724 *
725 * Runs at bp_setup_globals:100 to ensure that all components have loaded their
726 * globals before attempting any overrides.
727 *
728 * @since BuddyPress 2.0.0
729 */
730function xprofile_override_user_fullnames() {
731 // If sync is enabled, the two names will match. No need to continue.
732 if ( ! bp_disable_profile_sync() ) {
733 return;
734 }
735
736 if ( bp_loggedin_user_id() ) {
737 buddypress()->loggedin_user->fullname = bp_core_get_user_displayname( bp_loggedin_user_id() );
738 }
739
740 if ( bp_displayed_user_id() ) {
741 buddypress()->displayed_user->fullname = bp_core_get_user_displayname( bp_displayed_user_id() );
742 }
743}
744add_action( 'bp_setup_globals', 'xprofile_override_user_fullnames', 100 );
745
746/**
747 * Setup the avatar upload directory for a user.
748 *
749 * @since BuddyPress 1.0.0
750 *
751 * @package BuddyBoss Core
752 *
753 * @param string $directory The root directory name. Optional.
754 * @param int $user_id The user ID. Optional.
755 * @return array Array containing the path, URL, and other helpful settings.
756 */
757function xprofile_avatar_upload_dir( $directory = 'avatars', $user_id = 0 ) {
758
759 // Use displayed user if no user ID was passed.
760 if ( empty( $user_id ) ) {
761 $user_id = bp_displayed_user_id();
762 }
763
764 // Failsafe against accidentally nooped $directory parameter.
765 if ( empty( $directory ) ) {
766 $directory = 'avatars';
767 }
768
769 $path = bp_core_avatar_upload_path() . '/' . $directory . '/' . $user_id;
770 $newbdir = $path;
771 $newurl = bp_core_avatar_url() . '/' . $directory . '/' . $user_id;
772 $newburl = $newurl;
773 $newsubdir = '/' . $directory . '/' . $user_id;
774
775 /**
776 * Filters the avatar upload directory for a user.
777 *
778 * @since BuddyPress 1.1.0
779 *
780 * @param array $value Array containing the path, URL, and other helpful settings.
781 */
782 return apply_filters(
783 'xprofile_avatar_upload_dir',
784 array(
785 'path' => $path,
786 'url' => $newurl,
787 'subdir' => $newsubdir,
788 'basedir' => $newbdir,
789 'baseurl' => $newburl,
790 'error' => false,
791 )
792 );
793}
794
795/**
796 * When search_terms are passed to BP_User_Query, search against xprofile fields.
797 *
798 * @since BuddyPress 2.0.0
799 *
800 * @param array $sql Clauses in the user_id SQL query.
801 * @param BP_User_Query $query User query object.
802 * @return array
803 */
804function bp_xprofile_bp_user_query_search( $sql, BP_User_Query $query ) {
805 global $wpdb;
806
807 if ( empty( $query->query_vars['search_terms'] ) || empty( $sql['where']['search'] ) ) {
808 return $sql;
809 }
810
811 $bp = buddypress();
812
813 $search_terms_clean = bp_esc_like( wp_kses_normalize_entities( $query->query_vars['search_terms'] ) );
814
815 if ( $query->query_vars['search_wildcard'] === 'left' ) {
816 $search_terms_nospace = '%' . $search_terms_clean;
817 $search_terms_space = '%' . $search_terms_clean . ' %';
818 } elseif ( $query->query_vars['search_wildcard'] === 'right' ) {
819 $search_terms_nospace = $search_terms_clean . '%';
820 $search_terms_space = '% ' . $search_terms_clean . '%';
821 } else {
822 $search_terms_nospace = '%' . $search_terms_clean . '%';
823 $search_terms_space = '%' . $search_terms_clean . '%';
824 }
825
826 // Combine the core search (against wp_users) into a single OR clause
827 // with the xprofile_data search.
828 $matched_user_ids = $wpdb->get_col(
829 $wpdb->prepare(
830 "SELECT user_id FROM {$bp->profile->table_name_data} WHERE value LIKE %s OR value LIKE %s",
831 $search_terms_nospace,
832 $search_terms_space
833 )
834 );
835
836 // Checked profile fields based on privacy settings of particular user while searching
837 if ( ! empty( $matched_user_ids ) ) {
838 $matched_user_data = $wpdb->get_results(
839 $wpdb->prepare(
840 "SELECT * FROM {$bp->profile->table_name_data} WHERE value LIKE %s OR value LIKE %s",
841 $search_terms_nospace,
842 $search_terms_space
843 )
844 );
845
846 foreach ( $matched_user_data as $key => $user ) {
847 $field_visibility = xprofile_get_field_visibility_level( $user->field_id, $user->user_id );
848 if ( 'adminsonly' === $field_visibility && ! current_user_can( 'administrator' ) ) {
849 if ( ( $key = array_search( $user->user_id, $matched_user_ids ) ) !== false ) {
850 unset( $matched_user_ids[ $key ] );
851 }
852 }
853 if ( 'friends' === $field_visibility && ! current_user_can( 'administrator' ) && false === friends_check_friendship( intval( $user->user_id ), bp_loggedin_user_id() ) ) {
854 if ( ( $key = array_search( $user->user_id, $matched_user_ids ) ) !== false ) {
855 unset( $matched_user_ids[ $key ] );
856 }
857 }
858 }
859 }
860
861 if ( ! empty( $matched_user_ids ) ) {
862 $search_core = $sql['where']['search'];
863 $search_combined = " ( u.{$query->uid_name} IN (" . implode( ',', $matched_user_ids ) . ") OR {$search_core} )";
864 $sql['where']['search'] = $search_combined;
865 }
866
867 return $sql;
868}
869add_action( 'bp_user_query_uid_clauses', 'bp_xprofile_bp_user_query_search', 10, 2 );
870
871/**
872 * Sync xprofile data to the standard built in WordPress profile data.
873 *
874 * @since BuddyPress 1.0.0
875 *
876 * @param int $user_id ID of the user to sync.
877 * @return bool
878 */
879function xprofile_sync_wp_profile( $user_id = 0, $field_id = null ) {
880
881 // Bail if profile syncing is disabled.
882 if ( bp_disable_profile_sync() ) {
883 return true;
884 }
885
886 if ( empty( $user_id ) ) {
887 $user_id = bp_loggedin_user_id();
888 }
889
890 if ( empty( $user_id ) ) {
891 return false;
892 }
893
894 // Get First, Last and Nickname field id from DB.
895 $firstname_id = bp_xprofile_firstname_field_id();
896 $lastname_id = bp_xprofile_lastname_field_id();
897 $nickname_id = bp_xprofile_nickname_field_id();
898
899 if ( ! $field_id || $field_id == $firstname_id ) {
900 $firstname = xprofile_get_field_data( bp_xprofile_firstname_field_id(), $user_id );
901 bp_update_user_meta( $user_id, 'first_name', $firstname );
902 }
903
904 if ( ! $field_id || $field_id == $lastname_id ) {
905 $lastname = xprofile_get_field_data( bp_xprofile_lastname_field_id(), $user_id );
906 bp_update_user_meta( $user_id, 'last_name', $lastname );
907 }
908
909 if ( ! $field_id || $field_id == $nickname_id ) {
910 $nickname = xprofile_get_field_data( bp_xprofile_nickname_field_id(), $user_id );
911 bp_update_user_meta( $user_id, 'nickname', $nickname );
912 }
913
914 bp_xprofile_update_display_name( $user_id );
915}
916add_action( 'bp_core_signup_user', 'xprofile_sync_wp_profile' );
917add_action( 'bp_core_activated_user', 'xprofile_sync_wp_profile' );
918
919/**
920 * Update display_name in user database.
921 *
922 * @since BuddyBoss 1.0.0
923 */
924function bp_xprofile_update_display_name( $user_id ) {
925 wp_update_user(
926 array(
927 'ID' => $user_id,
928 'display_name' => bp_core_get_user_displayname( $user_id ),
929 )
930 );
931}
932
933/**
934 * When a user is deleted, we need to clean up the database and remove all the
935 * profile data from each table. Also we need to clean anything up in the
936 * usermeta table that this component uses.
937 *
938 * @since BuddyPress 1.0.0
939 *
940 * @param int $user_id The ID of the deleted user.
941 */
942function xprofile_remove_data( $user_id ) {
943 BP_XProfile_ProfileData::delete_data_for_user( $user_id );
944}
945add_action( 'wpmu_delete_user', 'xprofile_remove_data' );
946add_action( 'delete_user', 'xprofile_remove_data' );
947add_action( 'bp_make_spam_user', 'xprofile_remove_data' );
948
949/*** XProfile Meta ****************************************************/
950
951/**
952 * Delete a piece of xprofile metadata.
953 *
954 * @since BuddyPress 1.5.0
955 *
956 * @param int $object_id ID of the object the metadata belongs to.
957 * @param string $object_type Type of object. 'group', 'field', or 'data'.
958 * @param string|bool $meta_key Key of the metadata being deleted. If omitted, all
959 * metadata for the object will be deleted.
960 * @param mixed $meta_value Optional. If provided, only metadata that matches
961 * the value will be permitted.
962 * @param bool $delete_all Optional. If true, delete matching metadata entries
963 * for all objects, ignoring the specified object_id. Otherwise, only
964 * delete matching metadata entries for the specified object.
965 * Default: false.
966 * @return bool True on success, false on failure.
967 */
968function bp_xprofile_delete_meta( $object_id, $object_type, $meta_key = false, $meta_value = false, $delete_all = false ) {
969 global $wpdb;
970
971 // Sanitize object type.
972 if ( ! in_array( $object_type, array( 'group', 'field', 'data' ) ) ) {
973 return false;
974 }
975
976 // Legacy - if no meta_key is passed, delete all for the item.
977 if ( empty( $meta_key ) ) {
978 $table_key = 'xprofile_' . $object_type . 'meta';
979 $table_name = $wpdb->{$table_key};
980 $keys = $wpdb->get_col( $wpdb->prepare( "SELECT meta_key FROM {$table_name} WHERE object_type = %s AND object_id = %d", $object_type, $object_id ) );
981
982 // Force delete_all to false if deleting all for object.
983 $delete_all = false;
984 } else {
985 $keys = array( $meta_key );
986 }
987
988 add_filter( 'query', 'bp_filter_metaid_column_name' );
989 add_filter( 'query', 'bp_xprofile_filter_meta_query' );
990
991 $retval = false;
992 foreach ( $keys as $key ) {
993 $retval = delete_metadata( 'xprofile_' . $object_type, $object_id, $key, $meta_value, $delete_all );
994 }
995
996 remove_filter( 'query', 'bp_xprofile_filter_meta_query' );
997 remove_filter( 'query', 'bp_filter_metaid_column_name' );
998
999 return $retval;
1000}
1001
1002/**
1003 * Get a piece of xprofile metadata.
1004 *
1005 * Note that the default value of $single is true, unlike in the case of the
1006 * underlying get_metadata() function. This is for backward compatibility.
1007 *
1008 * @since BuddyPress 1.5.0
1009 *
1010 * @param int $object_id ID of the object the metadata belongs to.
1011 * @param string $object_type Type of object. 'group', 'field', or 'data'.
1012 * @param string $meta_key Key of the metadata being fetched. If omitted, all
1013 * metadata for the object will be retrieved.
1014 * @param bool $single Optional. If true, return only the first value of the
1015 * specified meta_key. This parameter has no effect if meta_key is not
1016 * specified. Default: true.
1017 * @return mixed Meta value if found. False on failure.
1018 */
1019function bp_xprofile_get_meta( $object_id, $object_type, $meta_key = '', $single = true ) {
1020 // Sanitize object type.
1021 if ( ! in_array( $object_type, array( 'group', 'field', 'data' ) ) ) {
1022 return false;
1023 }
1024
1025 add_filter( 'query', 'bp_filter_metaid_column_name' );
1026 add_filter( 'query', 'bp_xprofile_filter_meta_query' );
1027 $retval = get_metadata( 'xprofile_' . $object_type, $object_id, $meta_key, $single );
1028 remove_filter( 'query', 'bp_filter_metaid_column_name' );
1029 remove_filter( 'query', 'bp_xprofile_filter_meta_query' );
1030
1031 return $retval;
1032}
1033
1034/**
1035 * Update a piece of xprofile metadata.
1036 *
1037 * @since BuddyPress 1.5.0
1038 *
1039 * @param int $object_id ID of the object the metadata belongs to.
1040 * @param string $object_type Type of object. 'group', 'field', or 'data'.
1041 * @param string $meta_key Key of the metadata being updated.
1042 * @param string $meta_value Value of the metadata being updated.
1043 * @param mixed $prev_value Optional. If specified, only update existing
1044 * metadata entries with the specified value.
1045 * Otherwise update all entries.
1046 * @return bool|int Returns false on failure. On successful update of existing
1047 * metadata, returns true. On successful creation of new metadata,
1048 * returns the integer ID of the new metadata row.
1049 */
1050function bp_xprofile_update_meta( $object_id, $object_type, $meta_key, $meta_value, $prev_value = '' ) {
1051 add_filter( 'query', 'bp_filter_metaid_column_name' );
1052 add_filter( 'query', 'bp_xprofile_filter_meta_query' );
1053 $retval = update_metadata( 'xprofile_' . $object_type, $object_id, $meta_key, $meta_value, $prev_value );
1054 remove_filter( 'query', 'bp_xprofile_filter_meta_query' );
1055 remove_filter( 'query', 'bp_filter_metaid_column_name' );
1056
1057 return $retval;
1058}
1059
1060/**
1061 * Add a piece of xprofile metadata.
1062 *
1063 * @since BuddyPress 2.0.0
1064 *
1065 * @param int $object_id ID of the object the metadata belongs to.
1066 * @param string $object_type Type of object. 'group', 'field', or 'data'.
1067 * @param string $meta_key Metadata key.
1068 * @param mixed $meta_value Metadata value.
1069 * @param bool $unique Optional. Whether to enforce a single metadata value
1070 * for the given key. If true, and the object already
1071 * has a value for the key, no change will be made.
1072 * Default false.
1073 * @return int|bool The meta ID on successful update, false on failure.
1074 */
1075function bp_xprofile_add_meta( $object_id, $object_type, $meta_key, $meta_value, $unique = false ) {
1076 add_filter( 'query', 'bp_filter_metaid_column_name' );
1077 add_filter( 'query', 'bp_xprofile_filter_meta_query' );
1078 $retval = add_metadata( 'xprofile_' . $object_type, $object_id, $meta_key, $meta_value, $unique );
1079 remove_filter( 'query', 'bp_filter_metaid_column_name' );
1080 remove_filter( 'query', 'bp_xprofile_filter_meta_query' );
1081
1082 return $retval;
1083}
1084
1085/**
1086 * Updates the fieldgroup metadata.
1087 *
1088 * @since BuddyPress 1.5.0
1089 *
1090 * @param int $field_group_id Group ID for the group field belongs to.
1091 * @param string $meta_key Meta key to update.
1092 * @param string $meta_value Meta value to update to.
1093 * @return bool|int
1094 */
1095function bp_xprofile_update_fieldgroup_meta( $field_group_id, $meta_key, $meta_value ) {
1096 return bp_xprofile_update_meta( $field_group_id, 'group', $meta_key, $meta_value );
1097}
1098
1099/**
1100 * Updates the field metadata.
1101 *
1102 * @since BuddyPress 1.5.0
1103 *
1104 * @param int $field_id Field ID to update.
1105 * @param string $meta_key Meta key to update.
1106 * @param string $meta_value Meta value to update to.
1107 * @return bool|int
1108 */
1109function bp_xprofile_update_field_meta( $field_id, $meta_key, $meta_value ) {
1110 return bp_xprofile_update_meta( $field_id, 'field', $meta_key, $meta_value );
1111}
1112
1113/**
1114 * Updates the fielddata metadata.
1115 *
1116 * @since BuddyPress 1.5.0
1117 *
1118 * @param int $field_data_id Field ID to update.
1119 * @param string $meta_key Meta key to update.
1120 * @param string $meta_value Meta value to update to.
1121 * @return bool|int
1122 */
1123function bp_xprofile_update_fielddata_meta( $field_data_id, $meta_key, $meta_value ) {
1124 return bp_xprofile_update_meta( $field_data_id, 'data', $meta_key, $meta_value );
1125}
1126
1127/**
1128 * Return the field ID for the Full Name xprofile field.
1129 *
1130 * @since BuddyPress 2.0.0
1131 *
1132 * @return int Field ID.
1133 */
1134function bp_xprofile_fullname_field_id() {
1135 $id = wp_cache_get( 'fullname_field_id', 'bp_xprofile' );
1136
1137 if ( false === $id ) {
1138 global $wpdb;
1139
1140 $bp = buddypress();
1141
1142 if ( isset( $bp->profile->table_name_fields ) ) {
1143 $id = $wpdb->get_var( $wpdb->prepare( "SELECT id FROM {$bp->profile->table_name_fields} WHERE name = %s", addslashes( bp_xprofile_fullname_field_name() ) ) );
1144 } else {
1145 $table = bp_core_get_table_prefix() . 'bp_xprofile_fields';
1146 $id = $wpdb->get_var( $wpdb->prepare( "SELECT id FROM {$table} WHERE name = %s", addslashes( bp_xprofile_fullname_field_name() ) ) );
1147 }
1148
1149 wp_cache_set( 'fullname_field_id', $id, 'bp_xprofile' );
1150 }
1151
1152 return absint( $id );
1153}
1154
1155/**
1156 * Get the group id of the base name field
1157 *
1158 * @since BuddyBoss 1.0.0
1159 */
1160function bp_xprofile_base_group_id( $defalut = 1, $get_option = true ) {
1161 if ( is_multisite() ) {
1162 $field_id = get_site_option( 'bp-xprofile-base-group-id' );
1163 }
1164
1165 if ( empty( $field_id ) && $get_option ) {
1166 $field_id = bp_get_option( 'bp-xprofile-base-group-id', $defalut );
1167 }
1168
1169 return (int) apply_filters( 'bp_xprofile_base_group_id', $field_id );
1170}
1171
1172/**
1173 * Get the field id of the first name field
1174 *
1175 * @since BuddyBoss 1.0.0
1176 */
1177function bp_xprofile_firstname_field_id( $defalut = 1, $get_option = true ) {
1178 $field_id = 0;
1179
1180 if ( is_multisite() ) {
1181 $field_id = get_site_option( 'bp-xprofile-firstname-field-id' );
1182 }
1183
1184 if ( empty( $field_id ) && $get_option ) {
1185 $field_id = bp_get_option( 'bp-xprofile-firstname-field-id', $defalut );
1186 }
1187
1188 return (int) apply_filters( 'bp_xprofile_firstname_field_id', $field_id );
1189}
1190
1191/**
1192 * Get the field id of the last name field
1193 *
1194 * @since BuddyBoss 1.0.0
1195 */
1196function bp_xprofile_lastname_field_id( $defalut = 0, $get_option = true ) {
1197 $field_id = 0;
1198
1199 if ( is_multisite() ) {
1200 $field_id = get_site_option( 'bp-xprofile-lastname-field-id' );
1201 }
1202
1203 if ( empty( $field_id ) && $get_option ) {
1204 $field_id = bp_get_option( 'bp-xprofile-lastname-field-id', $defalut );
1205 }
1206
1207 return (int) apply_filters( 'bp_xprofile_lastname_field_id', $field_id );
1208}
1209
1210/**
1211 * Get the field id of the nick name field, fallback to default fullname field
1212 *
1213 * @since BuddyBoss 1.0.0
1214 */
1215function bp_xprofile_nickname_field_id( $no_fallback = false, $get_option = true ) {
1216 $field_id = 0;
1217
1218 if ( is_multisite() ) {
1219 $field_id = get_site_option( 'bp-xprofile-nickname-field-id', $no_fallback ? 0 : 0 );
1220 }
1221
1222 if ( empty( $field_id ) && $get_option ) {
1223 $field_id = bp_get_option( 'bp-xprofile-nickname-field-id', $no_fallback ? 0 : 0 );
1224 }
1225
1226 // Set nickname field id to 0(zero) if first name and nickname both are same.
1227 $first_name_id = bp_xprofile_firstname_field_id();
1228 if ( $first_name_id === (int) $field_id ) {
1229 $field_id = 0;
1230 }
1231
1232 return (int) apply_filters( 'bp_xprofile_nickname_field_id', $field_id );
1233}
1234
1235/**
1236 * Return the field name for the Full Name xprofile field.
1237 *
1238 * @since BuddyPress 1.5.0
1239 *
1240 * @return string The field name.
1241 */
1242function bp_xprofile_fullname_field_name() {
1243 $field_name = BP_XPROFILE_FULLNAME_FIELD_NAME;
1244
1245 /**
1246 * Get the nickname field if is set
1247 *
1248 * @since BuddyBoss 1.0.0
1249 */
1250 if ( $nickname_field_id = bp_xprofile_nickname_field_id( true ) ) {
1251 $field_name = xprofile_get_field( $nickname_field_id )->name;
1252 }
1253
1254 /**
1255 * Filters the field name for the Full Name xprofile field.
1256 *
1257 * @since BuddyPress 1.5.0
1258 *
1259 * @param string $value BP_XPROFILE_FULLNAME_FIELD_NAME Full name field constant.
1260 */
1261 return apply_filters( 'bp_xprofile_fullname_field_name', $field_name );
1262}
1263
1264/**
1265 * Is rich text enabled for this profile field?
1266 *
1267 * By default, rich text is enabled for textarea fields and disabled for all other field types.
1268 *
1269 * @since BuddyPress 2.4.0
1270 *
1271 * @param int|null $field_id Optional. Default current field ID.
1272 * @return bool
1273 */
1274function bp_xprofile_is_richtext_enabled_for_field( $field_id = null ) {
1275 if ( ! $field_id ) {
1276 $field_id = bp_get_the_profile_field_id();
1277 }
1278
1279 $field = xprofile_get_field( $field_id );
1280
1281 $enabled = false;
1282 if ( $field instanceof BP_XProfile_Field ) {
1283 $enabled = (bool) $field->type_obj->supports_richtext;
1284 }
1285
1286 /**
1287 * Filters whether richtext is enabled for the given field.
1288 *
1289 * @since BuddyPress 2.4.0
1290 *
1291 * @param bool $enabled True if richtext is enabled for the field, otherwise false.
1292 * @param int $field_id ID of the field.
1293 */
1294 return apply_filters( 'bp_xprofile_is_richtext_enabled_for_field', $enabled, $field_id );
1295}
1296
1297/**
1298 * Get visibility levels out of the $bp global.
1299 *
1300 * @since BuddyPress 1.6.0
1301 *
1302 * @return array
1303 */
1304function bp_xprofile_get_visibility_levels() {
1305
1306 /**
1307 * Filters the visibility levels out of the $bp global.
1308 *
1309 * @since BuddyPress 1.6.0
1310 *
1311 * @param array $visibility_levels Array of visibility levels.
1312 */
1313 return apply_filters( 'bp_xprofile_get_visibility_levels', buddypress()->profile->visibility_levels );
1314}
1315
1316/**
1317 * Get the ids of fields that are hidden for this displayed/loggedin user pair.
1318 *
1319 * This is the function primarily responsible for profile field visibility. It works by determining
1320 * the relationship between the displayed_user (ie the profile owner) and the current_user (ie the
1321 * profile viewer). Then, based on that relationship, we query for the set of fields that should
1322 * be excluded from the profile loop.
1323 *
1324 * @since BuddyPress 1.6.0
1325 *
1326 * @see BP_XProfile_Group::get()
1327 * or if you have added your own custom levels.
1328 *
1329 * @param int $displayed_user_id The id of the user the profile fields belong to.
1330 * @param int $current_user_id The id of the user viewing the profile.
1331 * @return array An array of field ids that should be excluded from the profile query
1332 */
1333function bp_xprofile_get_hidden_fields_for_user( $displayed_user_id = 0, $current_user_id = 0 ) {
1334 if ( ! $displayed_user_id ) {
1335 $displayed_user_id = bp_displayed_user_id();
1336 }
1337
1338 if ( ! $displayed_user_id ) {
1339 return array();
1340 }
1341
1342 if ( ! $current_user_id ) {
1343 $current_user_id = bp_loggedin_user_id();
1344 }
1345
1346 // @todo - This is where you'd swap out for current_user_can() checks
1347 $hidden_levels = bp_xprofile_get_hidden_field_types_for_user( $displayed_user_id, $current_user_id );
1348 $hidden_fields = bp_xprofile_get_fields_by_visibility_levels( $displayed_user_id, $hidden_levels );
1349
1350 /**
1351 * Filters the ids of fields that are hidden for this displayed/loggedin user pair.
1352 *
1353 * @since BuddyPress 1.6.0
1354 *
1355 * @param array $hidden_fields Array of hidden fields for the displayed/logged in user.
1356 * @param int $displayed_user_id ID of the displayed user.
1357 * @param int $current_user_id ID of the current user.
1358 */
1359 return apply_filters( 'bp_xprofile_get_hidden_fields_for_user', $hidden_fields, $displayed_user_id, $current_user_id );
1360}
1361
1362/**
1363 * Get the visibility levels that should be hidden for this user pair.
1364 *
1365 * Field visibility is determined based on the relationship between the
1366 * logged-in user, the displayed user, and the visibility setting for the
1367 * current field. (See bp_xprofile_get_hidden_fields_for_user().) This
1368 * utility function speeds up this matching by fetching the visibility levels
1369 * that should be hidden for the current user pair.
1370 *
1371 * @since BuddyPress 1.8.2
1372 *
1373 * @see bp_xprofile_get_hidden_fields_for_user()
1374 *
1375 * @param int $displayed_user_id The id of the user the profile fields belong to.
1376 * @param int $current_user_id The id of the user viewing the profile.
1377 * @return array An array of visibility levels hidden to the current user.
1378 */
1379function bp_xprofile_get_hidden_field_types_for_user( $displayed_user_id = 0, $current_user_id = 0 ) {
1380
1381 // Current user is logged in.
1382 if ( ! empty( $current_user_id ) ) {
1383
1384 // Nothing's private when viewing your own profile, or when the
1385 // current user is an admin.
1386 if ( $displayed_user_id == $current_user_id || bp_current_user_can( 'bp_moderate' ) ) {
1387 $hidden_levels = array();
1388
1389 // If the current user and displayed user are friends, show all.
1390 } elseif ( bp_is_active( 'friends' ) && friends_check_friendship( $displayed_user_id, $current_user_id ) ) {
1391 $hidden_levels = array( 'adminsonly' );
1392
1393 // Current user is logged in but not friends, so exclude friends-only.
1394 } else {
1395 $hidden_levels = array( 'friends', 'adminsonly' );
1396 }
1397
1398 // Current user is not logged in, so exclude friends-only, loggedin, and adminsonly.
1399 } else {
1400 $hidden_levels = array( 'friends', 'loggedin', 'adminsonly' );
1401 }
1402
1403 /**
1404 * Filters the visibility levels that should be hidden for this user pair.
1405 *
1406 * @since BuddyPress 2.0.0
1407 *
1408 * @param array $hidden_fields Array of hidden fields for the displayed/logged in user.
1409 * @param int $displayed_user_id ID of the displayed user.
1410 * @param int $current_user_id ID of the current user.
1411 */
1412 return apply_filters( 'bp_xprofile_get_hidden_field_types_for_user', $hidden_levels, $displayed_user_id, $current_user_id );
1413}
1414
1415/**
1416 * Fetch an array of the xprofile fields that a given user has marked with certain visibility levels.
1417 *
1418 * @since BuddyPress 1.6.0
1419 *
1420 * @see bp_xprofile_get_hidden_fields_for_user()
1421 *
1422 * @param int $user_id The id of the profile owner.
1423 * @param array $levels An array of visibility levels ('public', 'friends', 'loggedin', 'adminsonly' etc) to be
1424 * checked against.
1425 * @return array $field_ids The fields that match the requested visibility levels for the given user.
1426 */
1427function bp_xprofile_get_fields_by_visibility_levels( $user_id, $levels = array() ) {
1428 if ( ! is_array( $levels ) ) {
1429 $levels = (array) $levels;
1430 }
1431
1432 $user_visibility_levels = bp_get_user_meta( $user_id, 'bp_xprofile_visibility_levels', true );
1433
1434 // Parse the user-provided visibility levels with the default levels, which may take
1435 // precedence.
1436 $default_visibility_levels = BP_XProfile_Group::fetch_default_visibility_levels();
1437
1438 foreach ( (array) $default_visibility_levels as $d_field_id => $defaults ) {
1439 // If the admin has forbidden custom visibility levels for this field, replace
1440 // the user-provided setting with the default specified by the admin.
1441 if ( isset( $defaults['allow_custom'] ) && isset( $defaults['default'] ) && 'disabled' == $defaults['allow_custom'] ) {
1442 $user_visibility_levels[ $d_field_id ] = $defaults['default'];
1443 }
1444 }
1445
1446 $field_ids = array();
1447 foreach ( (array) $user_visibility_levels as $field_id => $field_visibility ) {
1448 if ( in_array( $field_visibility, $levels ) ) {
1449 $field_ids[] = $field_id;
1450 }
1451 }
1452
1453 // Never allow the fullname field to be excluded.
1454 if ( in_array( 1, $field_ids ) ) {
1455 $key = array_search( 1, $field_ids );
1456 unset( $field_ids[ $key ] );
1457 }
1458
1459 return $field_ids;
1460}
1461
1462/**
1463 * Formats datebox field values passed through a POST request.
1464 *
1465 * @since BuddyPress 2.8.0
1466 *
1467 * @param int $field_id The id of the current field being looped through.
1468 * @return void This function only changes the global $_POST that should contain
1469 * the datebox data.
1470 */
1471function bp_xprofile_maybe_format_datebox_post_data( $field_id ) {
1472 if ( ! isset( $_POST[ 'field_' . $field_id ] ) ) {
1473 if ( ! empty( $_POST[ 'field_' . $field_id . '_day' ] ) && ! empty( $_POST[ 'field_' . $field_id . '_month' ] ) && ! empty( $_POST[ 'field_' . $field_id . '_year' ] ) ) {
1474 // Concatenate the values.
1475 $date_value = $_POST[ 'field_' . $field_id . '_day' ] . ' ' . $_POST[ 'field_' . $field_id . '_month' ] . ' ' . $_POST[ 'field_' . $field_id . '_year' ];
1476
1477 $timestamp = strtotime( $date_value );
1478
1479 // Check that the concatenated value can be turned into a timestamp.
1480 if ( false !== $timestamp ) {
1481
1482 // Add the timestamp to the global $_POST that should contain the datebox data.
1483 $_POST[ 'field_' . $field_id ] = date( 'Y-m-d H:i:s', $timestamp );
1484 }
1485 }
1486 }
1487}
1488
1489/**
1490 * Determine a user's "mentionname", the name used for that user in @-mentions.
1491 *
1492 * @since BuddyPress 1.9.0
1493 *
1494 * @param int|string $user_id ID of the user to get @-mention name for.
1495 * @return string $mentionname User name appropriate for @-mentions.
1496 */
1497function bp_activity_get_user_mentionname( $user_id ) {
1498 $mentionname = '';
1499
1500 $userdata = bp_core_get_core_userdata( $user_id );
1501
1502 if ( $userdata ) {
1503 if ( bp_is_username_compatibility_mode() ) {
1504 $mentionname = str_replace( ' ', '-', $userdata->user_login );
1505 } else {
1506 $mentionname = get_user_meta( $userdata->ID, 'nickname', true );
1507 }
1508 }
1509
1510 return $mentionname;
1511}
1512
1513/**
1514 * Options for at mention js script
1515 *
1516 * @since BuddyBoss 1.0.0
1517 */
1518function bp_at_mention_default_options() {
1519 return apply_filters(
1520 'bp_at_mention_js_options',
1521 array(
1522 'selectors' => array( '.bp-suggestions', '#comments form textarea', '.wp-editor-area', '.bbp-the-content' ),
1523 'insert_tpl' => '@${ID}',
1524 'display_tpl' => '<li data-value="@${ID}"><img src="${image}" /><span class="username">@${ID}</span><small>${name}</small></li>',
1525 'extra_options' => array(),
1526 )
1527 );
1528}
1529
1530/**
1531 * Social Networks xprofile field provider.
1532 *
1533 * @since BuddyBoss 1.0.0
1534 *
1535 * @return array
1536 */
1537function bp_xprofile_social_network_provider() {
1538
1539 $options = array();
1540
1541 $options[] = (object) array(
1542 'id' => 1,
1543 'is_default_option' => false,
1544 'name' => __( 'Facebook', 'buddyboss' ),
1545 'value' => 'facebook',
1546 'svg' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path fill="#333" d="M16 0c-8.8 0-16 7.2-16 16s7.2 16 16 16c8.8 0 16-7.2 16-16s-7.2-16-16-16v0zM20.192 10.688h-1.504c-1.184 0-1.376 0.608-1.376 1.408v1.792h2.784l-0.384 2.816h-2.4v7.296h-2.912v-7.296h-2.496v-2.816h2.496v-2.080c-0.096-2.496 1.408-3.808 3.616-3.808 0.992 0 1.888 0.096 2.176 0.096v2.592z"></path></svg>',
1547 );
1548 $options[] = (object) array(
1549 'id' => 2,
1550 'is_default_option' => false,
1551 'name' => __( 'Flickr', 'buddyboss' ),
1552 'value' => 'flickr',
1553 'svg' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path fill="#333" d="M16 0c-8.837 0-16 7.212-16 16.109s7.163 16.109 16 16.109 16-7.212 16-16.109-7.163-16.109-16-16.109zM9 21c-2.761 0-5-2.239-5-5s2.239-5 5-5 5 2.239 5 5c0 2.761-2.239 5-5 5zM23 21c-2.761 0-5-2.239-5-5s2.239-5 5-5 5 2.239 5 5c0 2.761-2.239 5-5 5z"></path></svg>',
1554 );
1555 $options[] = (object) array(
1556 'id' => 3,
1557 'is_default_option' => false,
1558 'name' => __( 'Google+', 'buddyboss' ),
1559 'value' => 'google',
1560 'svg' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path fill="#333" d="M16 0c-8.838 0-16 7.162-16 16s7.162 16 16 16 16-7.163 16-16-7.163-16-16-16zM12 24c-4.425 0-8-3.575-8-8s3.575-8 8-8c2.162 0 3.969 0.787 5.363 2.094l-2.175 2.088c-0.594-0.569-1.631-1.231-3.188-1.231-2.731 0-4.963 2.263-4.963 5.050s2.231 5.050 4.963 5.050c3.169 0 4.356-2.275 4.538-3.45h-4.537v-2.744h7.556c0.069 0.4 0.125 0.8 0.125 1.325 0 4.575-3.063 7.819-7.681 7.819zM26 16v2h-2v-2h-2v-2h2v-2h2v2h2v2h-2z"></path></svg>',
1561 );
1562 $options[] = (object) array(
1563 'id' => 4,
1564 'is_default_option' => false,
1565 'name' => __( 'Instagram', 'buddyboss' ),
1566 'value' => 'instagram',
1567 'svg' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path fill="#333" d="M16 19.104c-1.696 0-3.104-1.408-3.104-3.104 0-1.728 1.408-3.104 3.104-3.104 1.728 0 3.104 1.376 3.104 3.104 0 1.696-1.376 3.104-3.104 3.104zM19.616 12.896c-0.32 0-0.512-0.192-0.416-0.384v-2.208c0-0.192 0.192-0.416 0.416-0.416h2.176c0.224 0 0.416 0.224 0.416 0.416v2.208c0 0.192-0.192 0.384-0.416 0.384h-2.176zM16 0c-8.8 0-16 7.2-16 16s7.2 16 16 16c8.8 0 16-7.2 16-16s-7.2-16-16-16v0zM24 22.112c0 0.992-0.896 1.888-1.888 1.888h-12.224c-0.992 0-1.888-0.8-1.888-1.888v-12.224c0-1.088 0.896-1.888 1.888-1.888h12.224c0.992 0 1.888 0.8 1.888 1.888v12.224zM20.896 16c0 2.688-2.208 4.896-4.896 4.896s-4.896-2.208-4.896-4.896c0-0.416 0.096-0.896 0.192-1.312h-1.504v7.008c0 0.192 0.224 0.416 0.416 0.416h11.488c0.192 0 0.416-0.224 0.416-0.416v-7.008h-1.504c0.192 0.416 0.288 0.896 0.288 1.312z"></path></svg>',
1568 );
1569 $options[] = (object) array(
1570 'id' => 5,
1571 'is_default_option' => false,
1572 'name' => __( 'LinkedIn', 'buddyboss' ),
1573 'value' => 'linkedIn',
1574 'svg' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path fill="#333" d="M10 0.4c-5.302 0-9.6 4.298-9.6 9.6s4.298 9.6 9.6 9.6 9.6-4.298 9.6-9.6-4.298-9.6-9.6-9.6zM7.65 13.979h-1.944v-6.256h1.944v6.256zM6.666 6.955c-0.614 0-1.011-0.435-1.011-0.973 0-0.549 0.409-0.971 1.036-0.971s1.011 0.422 1.023 0.971c0 0.538-0.396 0.973-1.048 0.973zM14.75 13.979h-1.944v-3.467c0-0.807-0.282-1.355-0.985-1.355-0.537 0-0.856 0.371-0.997 0.728-0.052 0.127-0.065 0.307-0.065 0.486v3.607h-1.945v-4.26c0-0.781-0.025-1.434-0.051-1.996h1.689l0.089 0.869h0.039c0.256-0.408 0.883-1.010 1.932-1.010 1.279 0 2.238 0.857 2.238 2.699v3.699z"></path></svg>',
1575 );
1576 $options[] = (object) array(
1577 'id' => 6,
1578 'is_default_option' => false,
1579 'name' => __( 'Medium', 'buddyboss' ),
1580 'value' => 'medium',
1581 'svg' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 28 28"><path fill="#333" d="M9.328 6.578v18.328c0 0.484-0.234 0.938-0.766 0.938-0.187 0-0.359-0.047-0.516-0.125l-7.266-3.641c-0.438-0.219-0.781-0.781-0.781-1.25v-17.813c0-0.391 0.187-0.75 0.609-0.75 0.25 0 0.469 0.125 0.688 0.234l7.984 4c0.016 0.016 0.047 0.063 0.047 0.078zM10.328 8.156l8.344 13.531-8.344-4.156v-9.375zM28 8.437v16.469c0 0.516-0.297 0.875-0.812 0.875-0.266 0-0.516-0.078-0.734-0.203l-6.891-3.437zM27.953 6.563c0 0.063-8.078 13.172-8.703 14.172l-6.094-9.906 5.063-8.234c0.172-0.281 0.484-0.438 0.812-0.438 0.141 0 0.281 0.031 0.406 0.094l8.453 4.219c0.031 0.016 0.063 0.047 0.063 0.094z"></path></svg>',
1582 );
1583 $options[] = (object) array(
1584 'id' => 7,
1585 'is_default_option' => false,
1586 'name' => __( 'Meetup', 'buddyboss' ),
1587 'value' => 'meetup',
1588 'svg' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path fill="#333" d="M31.971 26.984c-0.405-2.575-5.165-0.592-5.461-3.412-0.417-3.997 5.533-12.612 5.063-15.963-0.417-3.007-2.455-3.64-4.22-3.675-1.712-0.027-2.164 0.243-2.744 0.58-0.337 0.195-0.816 0.58-1.483-0.055-0.445-0.424-0.743-0.715-1.207-1.092-0.243-0.189-0.621-0.432-1.26-0.527-0.635-0.095-1.464 0-1.989 0.223-0.527 0.229-0.936 0.621-1.368 0.999-0.431 0.377-1.529 1.597-2.548 1.145-0.447-0.193-1.944-0.941-3.029-1.407-2.084-0.903-5.096 0.56-6.181 2.488-1.617 2.865-4.8 14.137-5.285 15.62-1.079 3.336 1.376 6.053 4.679 5.899 1.403-0.068 2.333-0.573 3.216-2.184 0.512-0.924 5.305-13.449 5.664-14.057 0.263-0.431 1.125-1.004 1.853-0.633 0.735 0.377 0.883 1.159 0.775 1.895-0.181 1.193-3.559 8.839-3.695 9.7-0.216 1.471 0.479 2.285 2.009 2.365 1.045 0.055 2.089-0.316 2.912-1.88 0.465-0.869 5.799-11.555 6.269-12.269 0.52-0.781 0.937-1.039 1.471-1.011 0.412 0.020 1.065 0.128 0.904 1.355-0.163 1.207-4.457 9.040-4.901 10.961-0.608 2.569 0.803 5.165 3.121 6.304 1.483 0.728 7.96 1.968 7.436-1.369z"></path></svg>',
1589 );
1590 $options[] = (object) array(
1591 'id' => 8,
1592 'is_default_option' => false,
1593 'name' => __( 'Pinterest', 'buddyboss' ),
1594 'value' => 'pinterest',
1595 'svg' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 28"><path fill="#333" d="M24 14c0 6.625-5.375 12-12 12-1.188 0-2.312-0.172-3.406-0.5 0.453-0.719 0.969-1.641 1.219-2.562 0 0 0.141-0.531 0.844-3.297 0.406 0.797 1.625 1.5 2.922 1.5 3.859 0 6.484-3.516 6.484-8.234 0-3.547-3.016-6.875-7.609-6.875-5.688 0-8.563 4.094-8.563 7.5 0 2.063 0.781 3.906 2.453 4.594 0.266 0.109 0.516 0 0.594-0.313 0.063-0.203 0.187-0.734 0.25-0.953 0.078-0.313 0.047-0.406-0.172-0.672-0.484-0.578-0.797-1.313-0.797-2.359 0-3.031 2.266-5.75 5.906-5.75 3.219 0 5 1.969 5 4.609 0 3.453-1.531 6.375-3.813 6.375-1.25 0-2.188-1.031-1.891-2.312 0.359-1.516 1.062-3.156 1.062-4.25 0-0.984-0.531-1.813-1.625-1.813-1.281 0-2.312 1.328-2.312 3.109 0 0 0 1.141 0.391 1.906-1.313 5.563-1.547 6.531-1.547 6.531-0.219 0.906-0.234 1.922-0.203 2.766-4.234-1.859-7.187-6.078-7.187-11 0-6.625 5.375-12 12-12s12 5.375 12 12z"></path></svg>',
1596 );
1597 $options[] = (object) array(
1598 'id' => 9,
1599 'is_default_option' => false,
1600 'name' => __( 'Quora', 'buddyboss' ),
1601 'value' => 'quora',
1602 'svg' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 28 28"><path fill="#333" d="M19.609 12.297c0-6.516-2.031-9.859-6.797-9.859-4.688 0-6.719 3.344-6.719 9.859 0 6.484 2.031 9.797 6.719 9.797 0.75 0 1.422-0.078 2.047-0.266v0c-0.969-1.906-2.109-3.828-4.328-3.828-0.422 0-0.844 0.063-1.234 0.25l-0.766-1.516c0.922-0.797 2.406-1.422 4.312-1.422 2.984 0 4.5 1.437 5.719 3.266 0.703-1.563 1.047-3.672 1.047-6.281zM25.703 22.172h1.828c0.109 1.125-0.453 5.828-5.563 5.828-3.094 0-4.719-1.797-5.953-3.891v0c-1.016 0.281-2.109 0.422-3.203 0.422-6.25 0-12.359-4.984-12.359-12.234 0-7.313 6.125-12.297 12.359-12.297 6.359 0 12.406 4.953 12.406 12.297 0 4.094-1.906 7.422-4.672 9.562 0.891 1.344 1.813 2.234 3.094 2.234 1.406 0 1.969-1.078 2.063-1.922z"></path></svg>',
1603 );
1604 $options[] = (object) array(
1605 'id' => 10,
1606 'is_default_option' => false,
1607 'name' => __( 'Reddit', 'buddyboss' ),
1608 'value' => 'reddit',
1609 'svg' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 28 28"><path fill="#333" d="M17.109 18.234c0.141 0.141 0.141 0.359 0 0.484-0.891 0.891-2.609 0.969-3.109 0.969s-2.219-0.078-3.109-0.969c-0.141-0.125-0.141-0.344 0-0.484 0.125-0.125 0.344-0.125 0.469 0 0.562 0.578 1.781 0.766 2.641 0.766s2.063-0.187 2.641-0.766c0.125-0.125 0.344-0.125 0.469 0zM12.313 15.406c0 0.766-0.625 1.391-1.391 1.391-0.781 0-1.406-0.625-1.406-1.391 0-0.781 0.625-1.406 1.406-1.406 0.766 0 1.391 0.625 1.391 1.406zM18.484 15.406c0 0.766-0.625 1.391-1.406 1.391-0.766 0-1.391-0.625-1.391-1.391 0-0.781 0.625-1.406 1.391-1.406 0.781 0 1.406 0.625 1.406 1.406zM22.406 13.531c0-1.031-0.844-1.859-1.875-1.859-0.531 0-1 0.219-1.344 0.562-1.266-0.875-2.969-1.437-4.859-1.5l0.984-4.422 3.125 0.703c0 0.766 0.625 1.391 1.391 1.391 0.781 0 1.406-0.641 1.406-1.406s-0.625-1.406-1.406-1.406c-0.547 0-1.016 0.328-1.25 0.781l-3.453-0.766c-0.172-0.047-0.344 0.078-0.391 0.25l-1.078 4.875c-1.875 0.078-3.563 0.641-4.828 1.516-0.344-0.359-0.828-0.578-1.359-0.578-1.031 0-1.875 0.828-1.875 1.859 0 0.75 0.438 1.375 1.062 1.687-0.063 0.281-0.094 0.578-0.094 0.875 0 2.969 3.344 5.375 7.453 5.375 4.125 0 7.469-2.406 7.469-5.375 0-0.297-0.031-0.609-0.109-0.891 0.609-0.313 1.031-0.938 1.031-1.672zM28 14c0 7.734-6.266 14-14 14s-14-6.266-14-14 6.266-14 14-14 14 6.266 14 14z"></path></svg>',
1610 );
1611 $options[] = (object) array(
1612 'id' => 11,
1613 'is_default_option' => false,
1614 'name' => __( 'Snapchat', 'buddyboss' ),
1615 'value' => 'snapchat',
1616 'svg' => '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M12 0c-6.627 0-12 5.373-12 12s5.373 12 12 12 12-5.373 12-12-5.373-12-12-12zm5.126 16.475c-.057.077-.103.4-.178.655-.086.295-.356.262-.656.203-.437-.085-.827-.109-1.281-.034-.785.131-1.601 1.292-2.969 1.292-1.472 0-2.238-1.156-3.054-1.292-.832-.138-1.31.084-1.597.084-.221 0-.307-.135-.34-.247-.074-.251-.12-.581-.178-.66-.565-.087-1.84-.309-1.873-.878-.008-.148.096-.279.243-.303 1.872-.308 3.063-2.419 2.869-2.877-.138-.325-.735-.442-.986-.541-.648-.256-.739-.55-.7-.752.053-.28.395-.468.68-.468.275 0 .76.367 1.138.158-.055-.982-.194-2.387.156-3.171.667-1.496 2.129-2.236 3.592-2.236 1.473 0 2.946.75 3.608 2.235.349.783.212 2.181.156 3.172.357.197.799-.167 1.107-.167.302 0 .712.204.719.545.005.267-.233.497-.708.684-.255.101-.848.217-.986.541-.198.468 1.03 2.573 2.869 2.876.146.024.251.154.243.303-.033.569-1.314.791-1.874.878z"/></svg>',
1617 );
1618 $options[] = (object) array(
1619 'id' => 12,
1620 'is_default_option' => false,
1621 'name' => __( 'Telegram', 'buddyboss' ),
1622 'value' => 'telegram',
1623 'svg' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 2000 2000"><g fill="#333" transform="matrix(0.10801485,0,0,-0.10804828,-68.2169,2112.9105)"><path d="M 9680,19553 C 8348,19524 7000,19183 5730,18554 4664,18027 3741,17331 3029,16520 2267,15650 1708,14741 1295,13700 1016,12998 825,12287 721,11570 609,10796 602,9963 701,9170 895,7612 1551,5987 2501,4710 2989,4053 3482,3554 4165,3023 5450,2027 7020,1358 8610,1130 c 484,-69 716,-85 1280,-85 477,0 563,4 930,41 1173,117 2426,511 3535,1110 837,451 1651,1068 2209,1673 999,1083 1678,2232 2129,3606 591,1800 606,3697 43,5510 -173,559 -328,930 -620,1490 -539,1035 -1238,1989 -1882,2572 -1057,956 -2188,1616 -3514,2051 -985,324 -2018,478 -3040,455 z m 4495,-5612 c 28,-14 81,-55 118,-92 115,-114 153,-230 144,-436 -4,-108 -68,-414 -771,-3723 -421,-1983 -778,-3651 -792,-3707 -106,-428 -321,-562 -684,-424 -126,48 -12,-34 -2045,1475 -214,159 -394,289 -401,290 -6,1 -258,-237 -559,-529 -301,-291 -582,-556 -624,-587 -128,-97 -288,-168 -378,-168 -18,0 -33,5 -33,10 0,17 180,2323 183,2342 1,9 457,432 1012,940 556,508 1529,1397 2163,1976 633,579 1159,1066 1167,1082 36,70 6,103 -98,108 -67,3 -77,1 -147,-35 -41,-22 -739,-458 -1550,-969 C 8047,9709 7059,9088 7042,9083 c -10,-2 -535,154 -1168,347 -632,193 -1186,362 -1230,376 -104,31 -195,90 -230,151 -71,120 -1,279 172,393 100,66 167,93 989,410 402,155 984,380 1295,500 311,120 1011,390 1555,600 545,210 1661,641 2480,957 820,316 1744,673 2055,793 311,120 619,239 685,265 210,81 267,95 380,92 82,-2 109,-6 150,-26 z" /></g></svg>',
1624 );
1625 $options[] = (object) array(
1626 'id' => 13,
1627 'is_default_option' => false,
1628 'name' => __( 'Tumblr', 'buddyboss' ),
1629 'value' => 'tumblr',
1630 'svg' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path fill="#333" d="M10 0.4c-5.302 0-9.6 4.298-9.6 9.6s4.298 9.6 9.6 9.6 9.6-4.298 9.6-9.6-4.298-9.6-9.6-9.6zM12.577 14.141c-0.393 0.188-0.748 0.318-1.066 0.395-0.318 0.074-0.662 0.113-1.031 0.113-0.42 0-0.791-0.055-1.114-0.162s-0.598-0.26-0.826-0.459c-0.228-0.197-0.386-0.41-0.474-0.633-0.088-0.225-0.132-0.549-0.132-0.973v-3.262h-1.016v-1.314c0.359-0.119 0.67-0.289 0.927-0.512 0.257-0.221 0.464-0.486 0.619-0.797s0.263-0.707 0.322-1.185h1.307v2.35h2.18v1.458h-2.18v2.385c0 0.539 0.028 0.885 0.085 1.037 0.056 0.154 0.161 0.275 0.315 0.367 0.204 0.123 0.437 0.185 0.697 0.185 0.466 0 0.928-0.154 1.388-0.461v1.468z"></path></svg>',
1631 );
1632 $options[] = (object) array(
1633 'id' => 14,
1634 'is_default_option' => false,
1635 'name' => __( 'Twitch', 'buddyboss' ),
1636 'value' => 'twitch',
1637 'svg' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 333334 333334" fill-rule="evenodd" clip-rule="evenodd"><path fill="#333" d="M166667 0c92047 0 166667 74620 166667 166667s-74620 166667-166667 166667S0 258714 0 166667 74620 0 166667 0zm-55369 98779v105771h35251v20048c545-519 851-797 1144-1090 5944-5930 11904-11845 17813-17811 843-851 1685-1196 2882-1192 12319 40 24639 48 36958-24 905-5 2030-472 2674-1108 7680-7575 15274-15237 22935-22831 859-851 1170-1700 1169-2885-30-25681-22-51361-22-77043v-1836H111299zm95369 75234h-14630v-44767h14630v44767zm-40077-44764v44706h-14896v-44706h14896zm-40007 120108v-19807H86463c-40-830-98-1472-98-2115-4-37267-4-74534 18-111802 1-1078 192-2200 529-3224 2956-8996 5991-17968 8931-26969 381-1166 861-1584 2105-1596h60c49098 38 98194 33 147291 33 481-1 963 0 1647 0v2079c0 32119-8 64237 29 96356v63c-11 1306-409 2217-1339 3143-14244 14187-28460 28404-42648 42649-941 945-1864 1340-3205 1331-8642-61-17285 9-25927-67-1656-15-2839 418-4017 1622-5701 5827-11486 11572-17287 17300-551 545-1418 1083-2144 1090-3620 35-7240 47-10860 49h-2173c-3379-2-6758-8-10137-13-170 0-341-61-654-121z"/></svg>',
1638 );
1639 $options[] = (object) array(
1640 'id' => 15,
1641 'is_default_option' => false,
1642 'name' => __( 'Twitter', 'buddyboss' ),
1643 'value' => 'twitter',
1644 'svg' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path fill="#333" d="M16 0c-8.8 0-16 7.2-16 16s7.2 16 16 16c8.8 0 16-7.2 16-16s-7.2-16-16-16v0zM22.4 12.704v0.384c0 4.32-3.296 9.312-9.312 9.312-1.888 0-3.584-0.512-4.992-1.504h0.8c1.504 0 3.008-0.512 4.096-1.408-1.376 0-2.592-0.992-3.104-2.304 0.224 0 0.416 0.128 0.608 0.128 0.32 0 0.608 0 0.896-0.128-1.504-0.288-2.592-1.6-2.592-3.2v0c0.416 0.224 0.896 0.416 1.504 0.416-0.896-0.608-1.504-1.6-1.504-2.688 0-0.608 0.192-1.216 0.416-1.728 1.6 2.016 4 3.328 6.784 3.424-0.096-0.224-0.096-0.512-0.096-0.704 0-1.792 1.504-3.296 3.296-3.296 0.896 0 1.792 0.384 2.4 0.992 0.704-0.096 1.504-0.416 2.112-0.8-0.224 0.8-0.8 1.408-1.408 1.792 0.704-0.096 1.312-0.288 1.888-0.48-0.576 0.8-1.184 1.376-1.792 1.792v0z"></path></svg>',
1645 );
1646 $options[] = (object) array(
1647 'id' => 16,
1648 'is_default_option' => false,
1649 'name' => __( 'VK', 'buddyboss' ),
1650 'value' => 'vk',
1651 'svg' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path fill="#333" d="M 10,0 C 4.4770833,0 0,4.4770833 0,10 0,15.522917 4.4770833,20 10,20 15.522917,20 20,15.522917 20,10 20,4.4770833 15.522917,0 10,0 Z m 3.845833,11.282292 c 0,0 0.884375,0.872916 1.102084,1.278125 0.0062,0.0083 0.0094,0.01667 0.01146,0.02083 0.08854,0.148958 0.109375,0.264583 0.06563,0.351042 -0.07292,0.14375 -0.322917,0.214583 -0.408333,0.220833 h -1.5625 c -0.108334,0 -0.335417,-0.02813 -0.610417,-0.217708 -0.211458,-0.147917 -0.419792,-0.390625 -0.622917,-0.627084 -0.303125,-0.352083 -0.565625,-0.65625 -0.830208,-0.65625 a 0.31770833,0.31770833 0 0 0 -0.09896,0.01563 c -0.2,0.06458 -0.45625,0.35 -0.45625,1.110417 0,0.2375 -0.1875,0.373958 -0.319792,0.373958 H 9.4 c -0.24375,0 -1.5135417,-0.08542 -2.6385417,-1.271875 C 5.384375,10.427083 4.1447917,7.5125 4.134375,7.4854167 4.05625,7.296875 4.2177083,7.1958333 4.39375,7.1958333 h 1.578125 c 0.2104167,0 0.2791667,0.128125 0.3270833,0.2416667 0.05625,0.1322917 0.2625,0.6583333 0.6010417,1.25 0.5489583,0.9645833 0.8854167,1.35625 1.1552083,1.35625 A 0.3125,0.3125 0 0 0 8.2,10.00625 C 8.5520833,9.8104167 8.4864583,8.5552083 8.4708333,8.2947917 c 0,-0.048958 -0.00104,-0.5614584 -0.18125,-0.8072917 C 8.1604167,7.309375 7.940625,7.2416667 7.8072917,7.2166667 A 0.57291667,0.57291667 0 0 1 8.0145833,7.040625 C 8.25625,6.9197917 8.6916667,6.9020833 9.1239583,6.9020833 h 0.240625 c 0.4687497,0.00625 0.5895837,0.036458 0.7593747,0.079167 0.34375,0.082292 0.351042,0.3041667 0.320834,1.0635417 -0.0094,0.215625 -0.01875,0.459375 -0.01875,0.746875 0,0.0625 -0.0031,0.1291666 -0.0031,0.2 -0.01042,0.3864583 -0.02292,0.825 0.25,1.0052083 a 0.225,0.225 0 0 0 0.11875,0.034375 c 0.09479,0 0.380208,0 1.153125,-1.3260414 A 10.122917,10.122917 0 0 0 12.564608,7.378125 c 0.01563,-0.027083 0.06146,-0.1104167 0.115625,-0.1427083 A 0.27708333,0.27708333 0 0 1 12.8094,7.2052083 h 1.855208 c 0.202084,0 0.340625,0.030208 0.366667,0.1083334 C 15.077105,7.4375 15.022975,7.815625 14.176067,8.9625 l -0.378125,0.4989583 c -0.767709,1.0062497 -0.767709,1.0572917 0.04792,1.8208337 z" /></svg>',
1652 );
1653 $options[] = (object) array(
1654 'id' => 17,
1655 'is_default_option' => false,
1656 'name' => __( 'WhatsApp', 'buddyboss' ),
1657 'value' => 'whatsapp',
1658 'svg' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 960 960"><g fill="#333" transform="matrix(0.1202871,0,0,-0.12028135,-73.507161,1105.1649)"><path d="m 4370,9183 c -19,-1 -87,-8 -150,-14 C 3870,9137 3530,9058 3200,8935 2127,8532 1268,7673 865,6600 547,5752 527,4817 809,3953 1236,2644 2331,1636 3676,1315 c 519,-125 1088,-142 1622,-49 362,62 742,189 1092,363 763,380 1401,1017 1781,1781 283,569 420,1148 421,1780 1,836 -241,1607 -720,2297 -226,325 -550,659 -877,905 -696,521 -1550,804 -2410,796 -99,0 -196,-3 -215,-5 z m 650,-1443 c 356,-55 643,-159 930,-338 567,-354 938,-843 1106,-1457 72,-264 99,-493 91,-782 -5,-215 -24,-362 -67,-528 -75,-286 -203,-555 -384,-811 -387,-545 -896,-880 -1536,-1013 -197,-40 -310,-51 -529,-51 -380,-1 -709,74 -1060,241 -68,33 -131,59 -140,59 -9,0 -70,-18 -136,-39 -329,-107 -1223,-391 -1232,-391 -13,0 4,54 246,773 l 191,567 -51,92 c -145,261 -251,591 -290,903 -19,151 -16,474 5,629 78,569 328,1063 737,1461 314,305 644,498 1048,614 124,36 374,84 491,95 112,10 449,-3 580,-24 z" /><path d="m 4400,7329 c -514,-63 -1008,-330 -1338,-724 -258,-307 -425,-687 -478,-1090 -25,-187 -14,-465 25,-656 50,-242 130,-450 248,-645 36,-60 75,-125 86,-145 l 21,-36 -127,-374 c -69,-205 -124,-375 -122,-377 2,-2 175,50 384,117 208,66 387,121 397,121 9,0 51,-20 93,-45 174,-101 416,-200 591,-239 169,-39 276,-50 465,-50 322,1 596,60 872,189 570,266 991,772 1143,1373 46,184 62,313 62,512 0,201 -18,353 -61,516 -101,383 -293,709 -578,984 -304,294 -665,478 -1079,551 -136,24 -477,34 -604,18 z m -389,-860 c 10,-5 26,-24 38,-42 36,-58 221,-565 221,-605 0,-52 -43,-121 -139,-224 -101,-109 -102,-118 -28,-241 125,-210 308,-413 487,-539 111,-79 338,-198 378,-198 31,0 83,49 211,200 40,47 82,93 93,103 44,38 93,19 446,-169 108,-57 205,-114 215,-126 21,-26 22,-84 1,-185 -30,-145 -78,-221 -186,-295 -209,-141 -443,-175 -658,-95 -551,205 -714,298 -986,563 -280,274 -578,711 -666,979 -71,216 -53,449 49,635 45,80 193,231 243,248 39,13 254,6 281,-9 z" /></g></svg>',
1659 );
1660 $options[] = (object) array(
1661 'id' => 18,
1662 'is_default_option' => false,
1663 'name' => __( 'YouTube', 'buddyboss' ),
1664 'value' => 'youTube',
1665 'svg' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path fill="#333" d="M16 0c-8.8 0-16 7.2-16 16s7.2 16 16 16c8.8 0 16-7.2 16-16s-7.2-16-16-16v0zM24 16.608c0 1.28-0.192 2.592-0.192 2.592s-0.192 1.088-0.608 1.6c-0.608 0.608-1.312 0.608-1.6 0.704-2.208 0.192-5.6 0.192-5.6 0.192s-4.192 0-5.408-0.192c-0.384-0.096-1.184 0-1.792-0.704-0.512-0.512-0.608-1.6-0.608-1.6s-0.192-1.312-0.192-2.592v-1.216c0-1.28 0.192-2.592 0.192-2.592s0.224-1.088 0.608-1.6c0.608-0.608 1.312-0.608 1.6-0.704 2.208-0.192 5.6-0.192 5.6-0.192s3.392 0 5.6 0.192c0.288 0 0.992 0 1.6 0.704 0.512 0.512 0.608 1.6 0.608 1.6s0.192 1.312 0.192 2.592v1.216zM14.304 18.112l4.384-2.304-4.384-2.208v4.512z"></path></svg>',
1666 );
1667
1668 return apply_filters( 'bp_xprofile_fields_social_networks_provider', $options );
1669}
1670
1671/**
1672 * Add social networks button to the member header area.
1673 *
1674 * @return string
1675 * @since BuddyBoss 1.0.0
1676 */
1677function bp_get_user_social_networks_urls( $user_id = null ) {
1678
1679 global $wpdb;
1680 global $bp;
1681
1682 $social_networks_id = (int) $wpdb->get_var( "SELECT a.id FROM {$bp->table_prefix}bp_xprofile_fields a WHERE parent_id = 0 AND type = 'socialnetworks' " );
1683
1684 $html = '';
1685
1686 $original_option_values = array();
1687
1688 $user = ( $user_id !== null && $user_id > 0 ) ? $user_id : bp_displayed_user_id();
1689
1690 if ( $social_networks_id > 0 ) {
1691 $providers = bp_xprofile_social_network_provider();
1692
1693 $original_option_values = maybe_unserialize( BP_XProfile_ProfileData::get_value_byid( $social_networks_id, $user ) );
1694
1695 if ( isset( $original_option_values ) && ! empty( $original_option_values ) ) {
1696 foreach ( $original_option_values as $key => $original_option_value ) {
1697 if ( '' !== $original_option_value ) {
1698 $key = bp_social_network_search_key( $key, $providers );
1699
1700 $html .= '<span class="social ' . $providers[ $key ]->value . '"><a target="_blank" data-balloon-pos="up" data-balloon="' . $providers[ $key ]->name . '" href="' . esc_url( $original_option_value ) . '">' . $providers[ $key ]->svg . '</a></span>';
1701 }
1702 }
1703 }
1704 }
1705
1706 if ( $html !== '' ) {
1707 $level = xprofile_get_field_visibility_level( $social_networks_id, bp_displayed_user_id() );
1708
1709 if ( bp_displayed_user_id() === bp_loggedin_user_id() ) {
1710 $html = '<div class="social-networks-wrap">' . $html . '</div>';
1711 } elseif ( 'public' === $level ) {
1712 $html = '<div class="social-networks-wrap">' . $html . '</div>';
1713 } elseif ( 'loggedin' === $level && is_user_logged_in() ) {
1714 $html = '<div class="social-networks-wrap">' . $html . '</div>';
1715 } elseif ( 'friends' === $level && is_user_logged_in() ) {
1716 $member_friend_status = friends_check_friendship_status( bp_loggedin_user_id(), bp_displayed_user_id() );
1717
1718 if ( 'is_friend' === $member_friend_status ) {
1719 $html = '<div class="social-networks-wrap">' . $html . '</div>';
1720 } else {
1721 $html = '';
1722 }
1723 }
1724 }
1725
1726 return apply_filters( 'bp_get_user_social_networks_urls', $html, $original_option_values, $social_networks_id );
1727}
1728
1729/**
1730 * Decide need to add profile field select box or not.
1731 *
1732 * @since BuddyBoss 1.1.3
1733 *
1734 * @return bool
1735 */
1736function bp_check_member_type_field_have_options() {
1737
1738 $arr = array();
1739
1740 // Get posts of custom post type selected.
1741 $posts = new \WP_Query(
1742 array(
1743 'posts_per_page' => - 1,
1744 'post_type' => bp_get_member_type_post_type(),
1745 'orderby' => 'title',
1746 'order' => 'ASC',
1747 )
1748 );
1749 if ( $posts ) {
1750 foreach ( $posts->posts as $post ) {
1751 $enabled = get_post_meta( $post->ID, '_bp_member_type_enable_profile_field', true );
1752 if ( '' === $enabled || '1' === $enabled ) {
1753 $arr[] = $post->ID;
1754 }
1755 }
1756 }
1757
1758 if ( empty( $arr ) ) {
1759 return false;
1760 } else {
1761 return true;
1762 }
1763
1764}
1765
1766/**
1767 * Get the display_name for member based on user_id
1768 *
1769 * @since BuddyBoss 1.0.0
1770 *
1771 * @param string $display_name
1772 * @param int $user_id
1773 *
1774 * @return string
1775 */
1776function bp_xprofile_get_member_display_name( $user_id = null ) {
1777 // some cases it calls the filter directly, therefore no user id is passed
1778 if ( ! $user_id ) {
1779 return false;
1780 }
1781
1782 $user = get_userdata( $user_id );
1783
1784 // empty user or deleted user check.
1785 if ( empty( $user ) ) {
1786 return false;
1787 }
1788
1789 $format = bp_get_option( 'bp-display-name-format' );
1790
1791 $display_name = '';
1792
1793 switch ( $format ) {
1794 case 'first_name':
1795 // Get First Name Field Id.
1796 $first_name_id = (int) bp_get_option( 'bp-xprofile-firstname-field-id' );
1797
1798 $display_name = xprofile_get_field_data( $first_name_id, $user_id );
1799
1800 if ( '' === $display_name ) {
1801 $display_name = get_user_meta( $user_id, 'first_name', true );
1802 if ( empty( $display_name ) ) {
1803 $display_name = get_user_meta( $user_id, 'nickname', true );
1804 }
1805 xprofile_set_field_data( $first_name_id, $user_id, $display_name );
1806 }
1807
1808 // Get Nick Name Field Id.
1809 $nickname_id = (int) bp_get_option( 'bp-xprofile-nickname-field-id' );
1810 $nick_name = xprofile_get_field_data( $nickname_id, $user_id );
1811
1812 if ( '' === trim( $nick_name ) ) {
1813 // make sure nickname is valid
1814 $nickname = get_user_meta( $user_id, 'nickname', true );
1815 $nickname = sanitize_title( $nickname );
1816 $invalid = bp_xprofile_validate_nickname_value( '', $nickname_id, $nickname, $user_id );
1817
1818 // or use the user_nicename
1819 if ( ! $nickname || $invalid ) {
1820 $nickname = ( isset( $user->user_nicename ) ) ? $user->user_nicename : '';
1821 }
1822 xprofile_set_field_data( $nickname_id, $user_id, $nickname );
1823 }
1824
1825 break;
1826 case 'first_last_name':
1827 // Get First Name Field Id.
1828 $first_name_id = (int) bp_get_option( 'bp-xprofile-firstname-field-id' );
1829 // Get Last Name Field Id.
1830 $last_name_id = (int) bp_get_option( 'bp-xprofile-lastname-field-id' );
1831 $result_first_name = xprofile_get_field_data( $first_name_id, $user_id );
1832 $result_last_name = xprofile_get_field_data( $last_name_id, $user_id );
1833
1834 if ( '' === $result_first_name ) {
1835 $result_first_name = get_user_meta( $user_id, 'first_name', true );
1836 if ( empty( $result_first_name ) ) {
1837 $result_first_name = get_user_meta( $user_id, 'nickname', true );
1838 }
1839 xprofile_set_field_data( $first_name_id, $user_id, $result_first_name );
1840 }
1841
1842 if ( '' === $result_last_name ) {
1843 $result_last_name = get_user_meta( $user_id, 'last_name', true );
1844 xprofile_set_field_data( $last_name_id, $user_id, $result_last_name );
1845 }
1846
1847 $display_name = implode(
1848 ' ',
1849 array_filter(
1850 array(
1851 isset( $result_first_name ) ? $result_first_name : '',
1852 isset( $result_last_name ) ? $result_last_name : '',
1853 )
1854 )
1855 );
1856
1857 // Get Nick Name Field Id.
1858 $nickname_id = (int) bp_get_option( 'bp-xprofile-nickname-field-id' );
1859 $nick_name = xprofile_get_field_data( $nickname_id, $user_id );
1860
1861 if ( '' === trim( $nick_name ) ) {
1862 // make sure nickname is valid
1863 $nickname = get_user_meta( $user_id, 'nickname', true );
1864 $nickname = sanitize_title( $nickname );
1865 $invalid = bp_xprofile_validate_nickname_value( '', $nickname_id, $nickname, $user_id );
1866
1867 // or use the user_nicename
1868 if ( ! $nickname || $invalid ) {
1869 $nickname = $user->user_nicename;
1870 }
1871 xprofile_set_field_data( $nickname_id, $user_id, $nickname );
1872 }
1873
1874 break;
1875 case 'nickname':
1876 // Get Nick Name Field Id.
1877 $nickname_id = (int) bp_get_option( 'bp-xprofile-nickname-field-id' );
1878 $display_name = xprofile_get_field_data( $nickname_id, $user_id );
1879
1880 if ( '' === trim( $display_name ) ) {
1881 // make sure nickname is valid
1882 $nickname = get_user_meta( $user_id, 'nickname', true );
1883 $nickname = sanitize_title( $nickname );
1884 $invalid = bp_xprofile_validate_nickname_value( '', $nickname_id, $nickname, $user_id );
1885
1886 // or use the user_nicename
1887 if ( ! $nickname || $invalid ) {
1888 $nickname = $user->user_nicename;
1889 }
1890 xprofile_set_field_data( $nickname_id, $user_id, $nickname );
1891 $display_name = $nickname;
1892
1893 }
1894 break;
1895 }
1896
1897 return apply_filters( 'bp_xprofile_get_member_display_name', trim( $display_name ), $user_id );
1898}
1899
1900/**
1901 * Sync the standard built in WordPress profile data to xprofile data.
1902 *
1903 * @since BuddyBoss 1.4.7
1904 *
1905 * @param int $user_id sync specified user id first name, last name and nickname.
1906 *
1907 * @return void
1908 */
1909function bp_xprofile_sync_bp_profile( $user_id ) {
1910
1911 if ( empty( $user_id ) ) {
1912 return;
1913 }
1914
1915 $user = get_user_by( 'id', $user_id );
1916
1917 if ( isset( $user->first_name ) ) {
1918 xprofile_set_field_data( bp_xprofile_firstname_field_id(), $user->ID, $user->first_name );
1919 }
1920
1921 if ( isset( $user->last_name ) ) {
1922 xprofile_set_field_data( bp_xprofile_lastname_field_id(), $user->ID, $user->last_name );
1923 }
1924
1925 if ( isset( $user->nickname ) ) {
1926 xprofile_set_field_data( bp_xprofile_nickname_field_id(), $user->ID, $user->nickname );
1927 }
1928
1929}
1930add_action( 'profile_update', 'bp_xprofile_sync_bp_profile', 999, 1 );
1931
1932/**
1933 * Sync the standard built in xprofile data to WordPress data.
1934 *
1935 * @since BuddyBoss 1.4.7
1936 *
1937 * @param int $user_id ID for the user whose profile is being saved.
1938 * @param array $posted_field_ids Array of field IDs that were edited.
1939 * @param bool $errors Whether or not any errors occurred.
1940 * @param array $old_values Array of original values before update.
1941 * @param array $new_values Array of newly saved values after update.
1942 *
1943 * @return void
1944 */
1945
1946function bp_xprofile_sync_wp_profile( $user_id, $posted_field_ids, $errors, $old_values, $new_values ) {
1947
1948 if ( ! empty( $errors ) ) {
1949 return;
1950 }
1951
1952 foreach ( $new_values as $field_id => $new_value ) {
1953
1954 // Get First, Last and Nickname field id from DB.
1955 $firstname_id = bp_xprofile_firstname_field_id();
1956 $lastname_id = bp_xprofile_lastname_field_id();
1957 $nickname_id = bp_xprofile_nickname_field_id();
1958
1959 if ( ! $field_id || $field_id == $firstname_id ) {
1960 bp_update_user_meta( $user_id, 'first_name', $new_value['value'] );
1961 }
1962
1963 if ( ! $field_id || $field_id == $lastname_id ) {
1964 bp_update_user_meta( $user_id, 'last_name', $new_value['value'] );
1965 }
1966
1967 if ( ! $field_id || $field_id == $nickname_id ) {
1968 bp_update_user_meta( $user_id, 'nickname', $new_value['value'] );
1969 }
1970
1971 }
1972
1973 bp_xprofile_update_display_name( $user_id );
1974}
1975add_action( 'xprofile_updated_profile', 'bp_xprofile_sync_wp_profile', 999, 5 );
1976
1977/**
1978 * Return Transient name using logged in User ID.
1979 *
1980 * @param string $key - Transient prefix key
1981 * @param int $widget_id - Widget id part of transient name string
1982 *
1983 * @return string $transient_name
1984 *
1985 * @since BuddyBoss 1.4.9
1986 */
1987function bp_xprofile_get_profile_completion_transient_name( $key, $widget_id ) {
1988
1989 $user_id = get_current_user_id();
1990 $transient_name = $key . $user_id . $widget_id;
1991
1992 return apply_filters( 'bp_xprofile_get_profile_completion_transient_name', $transient_name );
1993
1994}
1995
1996/**
1997 * Function returns user progress data by checking if data already exists in transient first. IF NO then follow checking the progress logic.
1998 *
1999 * Clear transient when 1) Widget form settings update. 2) When Logged user profile updated. 3) When new profile fields added/updated/deleted.
2000 *
2001 * @param array $profile_groups - set of fieldset selected to show in progress
2002 * @param array $profile_phototype - profile or cover photo selected to show in progress
2003 * @param int $widget_id - Widget id specific user progress
2004 *
2005 * @return array $user_progress - user progress to render profile completion
2006 *
2007 * @since BuddyBoss 1.4.9
2008 */
2009function bp_xprofile_get_user_progress_data( $profile_groups, $profile_phototype, $widget_id ) {
2010
2011 $user_progress = array();
2012
2013 // Check if data avail in transient.
2014 $pc_transient_name = bp_xprofile_get_profile_completion_transient_name( bp_core_get_profile_completion_key(), $widget_id );
2015 $pc_transient_data = get_transient( $pc_transient_name );
2016
2017 if ( ! empty( $pc_transient_data ) ) {
2018
2019 $user_progress = $pc_transient_data;
2020
2021 } else {
2022
2023 // Get logged in user Progress.
2024 $user_progress_arr = bp_xprofile_get_user_progress( $profile_groups, $profile_phototype );
2025
2026 // Format User Progress array to pass on to the template.
2027 $user_progress = bp_xprofile_get_user_progress_formatted( $user_progress_arr );
2028
2029 // set Transient here with 3hours expiration.
2030 set_transient( $pc_transient_name, $user_progress, HOUR_IN_SECONDS * 3 );
2031 }
2032
2033 return $user_progress;
2034}
2035
2036/**
2037 * Function returns logged in user progress based on options selected in the widget form.
2038 *
2039 * @param array $group_ids - set of fieldset selected to show in progress
2040 * @param array $photo_types - profile or cover photo selected to show in progress
2041 *
2042 * @return array progress_details - raw details to calculate user progress
2043 *
2044 * @since BuddyBoss 1.4.9
2045 */
2046function bp_xprofile_get_user_progress( $group_ids, $photo_types ) {
2047
2048 /* User Progress specific VARS. */
2049 $user_id = get_current_user_id();
2050 $progress_details = array();
2051 $grand_total_fields = 0;
2052 $grand_completed_fields = 0;
2053
2054 /* Profile Photo */
2055
2056 // check if profile photo option still enabled.
2057 $is_profile_photo_disabled = bp_disable_avatar_uploads();
2058 if ( ! $is_profile_photo_disabled && in_array( 'profile_photo', $photo_types ) ) {
2059
2060 ++ $grand_total_fields;
2061
2062 $is_profile_photo_uploaded = ( bp_get_user_has_avatar( $user_id ) ) ? 1 : 0;
2063
2064 if ( $is_profile_photo_uploaded ) {
2065 ++ $grand_completed_fields;
2066 }
2067
2068 $progress_details['photo_type']['profile_photo'] = array(
2069 'is_uploaded' => $is_profile_photo_uploaded,
2070 'name' => __( 'Profile Photo', 'buddyboss' ),
2071 );
2072
2073 }
2074
2075 /* Cover Photo */
2076
2077 // check if cover photo option still enabled.
2078 $is_cover_photo_disabled = bp_disable_cover_image_uploads();
2079 if ( ! $is_cover_photo_disabled && in_array( 'cover_photo', $photo_types ) ) {
2080
2081 ++ $grand_total_fields;
2082
2083 $is_cover_photo_uploaded = ( bp_attachments_get_user_has_cover_image( $user_id ) ) ? 1 : 0;
2084
2085 if ( $is_cover_photo_uploaded ) {
2086 ++ $grand_completed_fields;
2087 }
2088
2089 $progress_details['photo_type']['cover_photo'] = array(
2090 'is_uploaded' => $is_cover_photo_uploaded,
2091 'name' => __( 'Cover Photo', 'buddyboss' ),
2092 );
2093
2094 }
2095
2096 /* Groups Fields */
2097
2098 // Get Groups and Group fields with Loggedin user data.
2099 $profile_groups = bp_xprofile_get_groups(
2100 array(
2101 'fetch_fields' => true,
2102 'fetch_field_data' => true,
2103 'user_id' => $user_id,
2104 'repeater_show_main_fields_only' => false,
2105 )
2106 );
2107
2108 foreach ( $profile_groups as $single_group_details ) {
2109
2110 if ( empty( $single_group_details->fields ) ) {
2111 continue;
2112 }
2113
2114 /* Single Group Specific VARS */
2115 $group_id = $single_group_details->id;
2116 $single_group_progress = array();
2117
2118 // Consider only selected Groups ids from the widget form settings, skip all others.
2119 if ( ! in_array( $group_id, $group_ids ) ) {
2120 continue;
2121 }
2122
2123 // Check if Current Group is repeater if YES then get number of fields inside current group.
2124 $is_group_repeater_str = bp_xprofile_get_meta( $group_id, 'group', 'is_repeater_enabled', true );
2125 $is_group_repeater = ( 'on' === $is_group_repeater_str ) ? true : false;
2126
2127 /* Loop through all the fields and check if fields completed or not. */
2128 $group_total_fields = 0;
2129 $group_completed_fields = 0;
2130 foreach ( $single_group_details->fields as $group_single_field ) {
2131
2132 // If current group is repeater then only consider first set of fields.
2133 if ( $is_group_repeater ) {
2134
2135 // If field not a "clone number 1" then stop. That means proceed with the first set of fields and restrict others.
2136 $field_id = $group_single_field->id;
2137 $clone_number = bp_xprofile_get_meta( $field_id, 'field', '_clone_number', true );
2138 if ( $clone_number > 1 ) {
2139 continue;
2140 }
2141 }
2142
2143 $field_data_value = maybe_unserialize( $group_single_field->data->value );
2144
2145 if ( ! empty( $field_data_value ) ) {
2146 ++ $group_completed_fields;
2147 }
2148
2149 ++ $group_total_fields;
2150 }
2151
2152 /* Prepare array to return group specific progress details */
2153 $single_group_progress['group_name'] = $single_group_details->name;
2154 $single_group_progress['group_total_fields'] = $group_total_fields;
2155 $single_group_progress['group_completed_fields'] = $group_completed_fields;
2156
2157 $grand_total_fields += $group_total_fields;
2158 $grand_completed_fields += $group_completed_fields;
2159
2160 $progress_details['groups'][ $group_id ] = $single_group_progress;
2161
2162 }
2163
2164 /* Total Fields vs completed fields to calculate progress percentage. */
2165 $progress_details['total_fields'] = $grand_total_fields;
2166 $progress_details['completed_fields'] = $grand_completed_fields;
2167
2168 /**
2169 * Filter returns User Progress array.
2170 *
2171 * @since BuddyBoss 1.2.5
2172 */
2173 return apply_filters( 'xprofile_pc_user_progress', $progress_details );
2174}
2175
2176/**
2177 * Function formats user progress to pass on to templates.
2178 *
2179 * @param array $user_progress_arr - raw details to calculate user progress
2180 *
2181 * @return array $user_prgress_formatted - user progress to render profile completion
2182 *
2183 * @since BuddyBoss 1.4.9
2184 */
2185function bp_xprofile_get_user_progress_formatted( $user_progress_arr ) {
2186
2187 /* Groups */
2188
2189 $loggedin_user_domain = bp_loggedin_user_domain();
2190 $profile_slug = bp_get_profile_slug();
2191
2192 // Calculate Total Progress percentage.
2193 $profile_completion_percentage = round( ( $user_progress_arr['completed_fields'] * 100 ) / $user_progress_arr['total_fields'] );
2194 $user_prgress_formatted = array(
2195 'completion_percentage' => $profile_completion_percentage,
2196 );
2197
2198 // Group specific details
2199 $listing_number = 1;
2200 foreach ( $user_progress_arr['groups'] as $group_id => $group_details ) {
2201
2202 $group_link = trailingslashit( $loggedin_user_domain . $profile_slug . '/edit/group/' . $group_id );
2203
2204 $user_prgress_formatted['groups'][] = array(
2205 'number' => $listing_number,
2206 'label' => $group_details['group_name'],
2207 'link' => $group_link,
2208 'is_group_completed' => ( $group_details['group_total_fields'] === $group_details['group_completed_fields'] ) ? true : false,
2209 'total' => $group_details['group_total_fields'],
2210 'completed' => $group_details['group_completed_fields'],
2211 );
2212
2213 $listing_number ++;
2214 }
2215
2216 /* Profile Photo */
2217 if ( isset( $user_progress_arr['photo_type']['profile_photo'] ) ) {
2218
2219 $change_avatar_link = trailingslashit( $loggedin_user_domain . $profile_slug . '/change-avatar' );
2220 $is_profile_uploaded = ( 1 === $user_progress_arr['photo_type']['profile_photo']['is_uploaded'] );
2221
2222 $user_prgress_formatted['groups'][] = array(
2223 'number' => $listing_number,
2224 'label' => $user_progress_arr['photo_type']['profile_photo']['name'],
2225 'link' => $change_avatar_link,
2226 'is_group_completed' => ( $is_profile_uploaded ) ? true : false,
2227 'total' => 1,
2228 'completed' => ( $is_profile_uploaded ) ? 1 : 0,
2229 );
2230
2231 $listing_number ++;
2232 }
2233
2234 /* Cover Photo */
2235 if ( isset( $user_progress_arr['photo_type']['cover_photo'] ) ) {
2236
2237 $change_cover_link = trailingslashit( $loggedin_user_domain . $profile_slug . '/change-cover-image' );
2238 $is_cover_uploaded = ( 1 === $user_progress_arr['photo_type']['cover_photo']['is_uploaded'] );
2239
2240 $user_prgress_formatted['groups'][] = array(
2241 'number' => $listing_number,
2242 'label' => $user_progress_arr['photo_type']['cover_photo']['name'],
2243 'link' => $change_cover_link,
2244 'is_group_completed' => ( $is_cover_uploaded ) ? true : false,
2245 'total' => 1,
2246 'completed' => ( $is_cover_uploaded ) ? 1 : 0,
2247 );
2248
2249 $listing_number ++;
2250 }
2251
2252 /**
2253 * Filter returns User Progress array in the template friendly format.
2254 *
2255 * @since BuddyBoss 1.2.5
2256 */
2257 return apply_filters( 'xprofile_pc_user_progress_formatted', $user_prgress_formatted );
2258}
2259