Skip to:
Content

BuddyPress.org

Ticket #7472: bp-xprofile-admin.php

File bp-xprofile-admin.php, 22.4 KB (added by NicolasKulka, 9 years ago)

Patch

Line 
1<?php
2/**
3 * BuddyPress XProfile Admin.
4 *
5 * @package BuddyPress
6 * @subpackage XProfileAdmin
7 * @since 1.0.0
8 */
9
10// Exit if accessed directly.
11defined( 'ABSPATH' ) || exit;
12
13/**
14 * Creates the administration interface menus and checks to see if the DB
15 * tables are set up.
16 *
17 * @since 1.0.0
18 *
19 * @return bool
20 */
21function xprofile_add_admin_menu() {
22
23        // Bail if current user cannot moderate community.
24        if ( ! bp_current_user_can( 'bp_moderate' ) ) {
25                return false;
26        }
27
28        add_users_page( _x( 'Profile Fields', 'xProfile admin page title', 'buddypress' ), _x( 'Profile Fields', 'Admin Users menu', 'buddypress' ), 'manage_options', 'bp-profile-setup', 'xprofile_admin' );
29}
30add_action( bp_core_admin_hook(), 'xprofile_add_admin_menu' );
31
32/**
33 * Handles all actions for the admin area for creating, editing and deleting
34 * profile groups and fields.
35 *
36 * @since 1.0.0
37 *
38 * @param string $message Message to display.
39 * @param string $type    Type of action to be displayed.
40 */
41function xprofile_admin( $message = '', $type = 'error' ) {
42
43        // What mode?
44        $mode = ! empty( $_GET['mode'] )
45                ? sanitize_key( $_GET['mode'] )
46                : false;
47
48        // Group ID
49        $group_id = ! empty( $_GET['group_id'] )
50                ? intval( $_GET['group_id'] )
51                : false;
52
53        // Field ID
54        $field_id = ! empty( $_GET['field_id'] )
55                ? intval( $_GET['field_id'] )
56                : false;
57
58        // Option ID
59        $option_id = ! empty( $_GET['option_id'] )
60                ? intval( $_GET['option_id'] )
61                : false;
62
63        // Allowed modes
64        $allowed_modes = array(
65                'add_group',
66                'edit_group',
67                'delete_group',
68                'add_field',
69                'edit_field',
70                'delete_field',
71                'delete_option'
72        );
73
74        // Is an allowed mode
75        if ( in_array( $mode, $allowed_modes, true ) ) {
76
77                // All group actions
78                if ( false !== $group_id ) {
79
80                        // Add field to group
81                        if ( 'add_field' == $mode ) {
82                                xprofile_admin_manage_field( $group_id );
83
84                        // Edit field of group
85                        } elseif ( ! empty( $field_id ) && 'edit_field' === $mode ) {
86                                xprofile_admin_manage_field( $group_id, $field_id );
87
88                        // Delete group
89                        } elseif ( 'delete_group' === $mode ) {
90                                xprofile_admin_delete_group( $group_id );
91
92                        // Edit group
93                        } elseif ( 'edit_group' === $mode ) {
94                                xprofile_admin_manage_group( $group_id );
95                        }
96
97                // Delete field
98                } elseif ( ( false !== $field_id ) && ( 'delete_field' === $mode ) ) {
99                        xprofile_admin_delete_field( $field_id, 'field');
100
101                // Delete option
102                } elseif ( ! empty( $option_id ) && 'delete_option' === $mode ) {
103                        xprofile_admin_delete_field( $option_id, 'option' );
104
105                // Add group
106                } elseif ( 'add_group' == $mode ) {
107                        xprofile_admin_manage_group();
108                }
109
110        } else {
111                xprofile_admin_screen( $message, $type );
112        }
113}
114
115/**
116 * Output the main XProfile management screen.
117 *
118 * @since 2.3.0
119 *
120 * @param string $message Feedback message.
121 * @param string $type    Feedback type.
122 *
123 * @todo Improve error message output
124 */
125function xprofile_admin_screen( $message = '', $type = 'error' ) {
126
127        // Validate type.
128        $type = preg_replace( '|[^a-z]|i', '', $type );
129
130        // Get all of the profile groups & fields.
131        $groups = bp_xprofile_get_groups( array(
132                'fetch_fields' => true
133        ) ); ?>
134
135        <div class="wrap">
136
137                <h1>
138                        <?php _ex( 'Profile Fields', 'Settings page header', 'buddypress'); ?>
139                        <a id="add_group" class="add-new-h2" href="users.php?page=bp-profile-setup&amp;mode=add_group"><?php _e( 'Add New Field Group', 'buddypress' ); ?></a>
140                </h1>
141
142                <form action="" id="profile-field-form" method="post">
143
144                        <?php
145
146                        wp_nonce_field( 'bp_reorder_fields', '_wpnonce_reorder_fields'        );
147                        wp_nonce_field( 'bp_reorder_groups', '_wpnonce_reorder_groups', false );
148
149                        if ( ! empty( $message ) ) :
150                                $type = ( $type == 'error' ) ? 'error' : 'updated'; ?>
151
152                                <div id="message" class="<?php echo $type; ?> fade">
153                                        <p><?php echo esc_html( $message ); ?></p>
154                                </div>
155
156                        <?php endif; ?>
157
158                        <div id="tabs" aria-live="polite" aria-atomic="true" aria-relevant="all">
159                                <ul id="field-group-tabs">
160
161                                        <?php if ( !empty( $groups ) ) : foreach ( $groups as $group ) : ?>
162
163                                                <li id="group_<?php echo esc_attr( $group->id ); ?>">
164                                                        <a href="#tabs-<?php echo esc_attr( $group->id ); ?>" class="ui-tab">
165                                                                <?php
166                                                                /** This filter is documented in bp-xprofile/bp-xprofile-template.php */
167                                                                echo esc_html( apply_filters( 'bp_get_the_profile_group_name', $group->name ) );
168                                                                ?>
169
170                                                                <?php if ( !$group->can_delete ) : ?>
171                                                                        <?php _e( '(Primary)', 'buddypress'); ?>
172                                                                <?php endif; ?>
173
174                                                        </a>
175                                                </li>
176
177                                        <?php endforeach; endif; ?>
178
179                                </ul>
180
181                                <?php if ( !empty( $groups ) ) : foreach ( $groups as $group ) : ?>
182
183                                        <noscript>
184                                                <h3><?php
185                                                /** This filter is documented in bp-xprofile/bp-xprofile-template.php */
186                                                echo esc_html( apply_filters( 'bp_get_the_profile_group_name', $group->name ) );
187                                                ?></h3>
188                                        </noscript>
189
190                                        <div id="tabs-<?php echo esc_attr( $group->id ); ?>" class="tab-wrapper">
191                                                <div class="tab-toolbar">
192                                                        <div class="tab-toolbar-left">
193                                                                <a class="button-primary" href="users.php?page=bp-profile-setup&amp;group_id=<?php echo esc_attr( $group->id ); ?>&amp;mode=add_field"><?php _e( 'Add New Field', 'buddypress' ); ?></a>
194                                                                <a class="button edit" href="users.php?page=bp-profile-setup&amp;mode=edit_group&amp;group_id=<?php echo esc_attr( $group->id ); ?>"><?php _ex( 'Edit Group', 'Edit Profile Fields Group', 'buddypress' ); ?></a>
195
196                                                                <?php if ( $group->can_delete ) : ?>
197
198                                                                        <div class="delete-button">
199                                                                                <a class="confirm submitdelete deletion ajax-option-delete" href="users.php?page=bp-profile-setup&amp;mode=delete_group&amp;group_id=<?php echo esc_attr( $group->id ); ?>"><?php _ex( 'Delete Group', 'Delete Profile Fields Group', 'buddypress' ); ?></a>
200                                                                        </div>
201
202                                                                <?php endif; ?>
203
204                                                                <?php
205
206                                                                /**
207                                                                 * Fires at end of action buttons in xprofile management admin.
208                                                                 *
209                                                                 * @since 2.2.0
210                                                                 *
211                                                                 * @param BP_XProfile_Group $group BP_XProfile_Group object
212                                                                 *                                 for the current group.
213                                                                 */
214                                                                do_action( 'xprofile_admin_group_action', $group ); ?>
215
216                                                        </div>
217                                                </div>
218
219                                                <?php if ( ! empty( $group->description ) ) : ?>
220
221                                                        <p><?php
222                                                        /** This filter is documented in bp-xprofile/bp-xprofile-template.php */
223                                                        echo esc_html( apply_filters( 'bp_get_the_profile_group_description', $group->description ) );
224                                                        ?></p>
225
226                                                <?php endif; ?>
227
228                                                <fieldset id="<?php echo esc_attr( $group->id ); ?>" class="connectedSortable field-group" aria-live="polite" aria-atomic="true" aria-relevant="all">
229                                                        <legend class="screen-reader-text"><?php
230                                                        /** This filter is documented in bp-xprofile/bp-xprofile-template.php */
231                                                        /* translators: accessibility text */
232                                                        printf( esc_html__( 'Fields for "%s" Group', 'buddypress' ), apply_filters( 'bp_get_the_profile_group_name', $group->name ) );
233                                                        ?></legend>
234
235                                                        <?php
236
237                                                        if ( !empty( $group->fields ) ) :
238                                                                foreach ( $group->fields as $field ) {
239
240                                                                        // Load the field.
241                                                                        $field = xprofile_get_field( $field->id );
242
243                                                                        $class = '';
244                                                                        if ( empty( $field->can_delete ) ) {
245                                                                                $class = ' core nodrag';
246                                                                        }
247
248                                                                        /**
249                                                                         * This function handles the WYSIWYG profile field
250                                                                         * display for the xprofile admin setup screen.
251                                                                         */
252                                                                        xprofile_admin_field( $field, $group, $class );
253
254                                                                } // end for
255
256                                                        else : // !$group->fields ?>
257
258                                                                <p class="nodrag nofields"><?php _e( 'There are no fields in this group.', 'buddypress' ); ?></p>
259
260                                                        <?php endif; // End $group->fields. ?>
261
262                                                </fieldset>
263
264                                                <?php if ( empty( $group->can_delete ) ) : ?>
265
266                                                        <p><?php esc_html_e( '* Fields in this group appear on the signup page.', 'buddypress' ); ?></p>
267
268                                                <?php endif; ?>
269
270                                        </div>
271
272                                <?php endforeach; else : ?>
273
274                                        <div id="message" class="error"><p><?php _ex( 'You have no groups.', 'You have no profile fields groups.', 'buddypress' ); ?></p></div>
275                                        <p><a href="users.php?page=bp-profile-setup&amp;mode=add_group"><?php _ex( 'Add New Group', 'Add New Profile Fields Group', 'buddypress' ); ?></a></p>
276
277                                <?php endif; ?>
278
279                        </div>
280                </form>
281        </div>
282
283<?php
284}
285
286/**
287 * Handles the adding or editing of groups.
288 *
289 * @since 1.0.0
290 *
291 * @param int|null $group_id Group ID to manage.
292 */
293function xprofile_admin_manage_group( $group_id = null ) {
294        global $message, $type;
295
296        // Get the field group.
297        $group = new BP_XProfile_Group( $group_id );
298
299        // Updating.
300        if ( isset( $_POST['save_group'] ) ) {
301
302                // Check nonce
303                check_admin_referer( 'bp_xprofile_admin_group', 'bp_xprofile_admin_group' );
304
305                // Validate $_POSTed data.
306                if ( BP_XProfile_Group::admin_validate() ) {
307
308                        // Set the group name.
309                        $group->name = $_POST['group_name'];
310
311                        // Set the group description.
312                        if ( ! empty( $_POST['group_description'] ) ) {
313                                $group->description = $_POST['group_description'];
314                        } else {
315                                $group->description = '';
316                        }
317
318                        // Attempt to save the field group.
319                        if ( false === $group->save() ) {
320                                $message = __( 'There was an error saving the group. Please try again.', 'buddypress' );
321                                $type    = 'error';
322
323                        // Save successful.
324                        } else {
325                                $message = __( 'The group was saved successfully.', 'buddypress' );
326                                $type    = 'success';
327
328                                // @todo remove these old options
329                                if ( 1 == $group_id ) {
330                                        bp_update_option( 'bp-xprofile-base-group-name', $group->name );
331                                }
332
333                                /**
334                                 * Fires at the end of the group adding/saving process, if successful.
335                                 *
336                                 * @since 1.0.0
337                                 *
338                                 * @param BP_XProfile_Group $group Current BP_XProfile_Group object.
339                                 */
340                                do_action( 'xprofile_groups_saved_group', $group );
341                        }
342
343                        xprofile_admin_screen( $message, $type );
344
345                } else {
346                        $group->render_admin_form( $message );
347                }
348        } else {
349                $group->render_admin_form();
350        }
351}
352
353/**
354 * Handles the deletion of profile data groups.
355 *
356 * @since 1.0.0
357 *
358 * @param int $group_id ID of the group to delete.
359 */
360function xprofile_admin_delete_group( $group_id ) {
361        global $message, $type;
362
363        $group = new BP_XProfile_Group( $group_id );
364
365        if ( !$group->delete() ) {
366                $message = _x( 'There was an error deleting the group. Please try again.', 'Error when deleting profile fields group', 'buddypress' );
367                $type    = 'error';
368        } else {
369                $message = _x( 'The group was deleted successfully.', 'Profile fields group was deleted successfully', 'buddypress' );
370                $type    = 'success';
371
372                /**
373                 * Fires at the end of group deletion process, if successful.
374                 *
375                 * @since 1.0.0
376                 *
377                 * @param BP_XProfile_Group $group Current BP_XProfile_Group object.
378                 */
379                do_action( 'xprofile_groups_deleted_group', $group );
380        }
381
382        xprofile_admin_screen( $message, $type );
383}
384
385/**
386 * Handles the adding or editing of profile field data for a user.
387 *
388 * @since 1.0.0
389 *
390 * @param int      $group_id ID of the group.
391 * @param int|null $field_id ID of the field being managed.
392 */
393function xprofile_admin_manage_field( $group_id, $field_id = null ) {
394        global $wpdb, $message, $groups;
395
396        $bp = buddypress();
397
398        if ( is_null( $field_id ) ) {
399                $field = new BP_XProfile_Field();
400        } else {
401                $field = xprofile_get_field( $field_id );
402        }
403
404        $field->group_id = $group_id;
405
406        if ( isset( $_POST['saveField'] ) ) {
407
408                // Check nonce
409                check_admin_referer( 'bp_xprofile_admin_field', 'bp_xprofile_admin_field' );
410
411                if ( BP_XProfile_Field::admin_validate() ) {
412                        $field->is_required = $_POST['required'];
413                        $field->type        = $_POST['fieldtype'];
414                        $field->name        = $_POST['title'];
415
416                        if ( ! empty( $_POST['description'] ) ) {
417                                $field->description = $_POST['description'];
418                        } else {
419                                $field->description = '';
420                        }
421
422                        if ( ! empty( $_POST["sort_order_{$field->type}"] ) ) {
423                                $field->order_by = $_POST["sort_order_{$field->type}"];
424                        }
425
426                        $field->field_order = $wpdb->get_var( $wpdb->prepare( "SELECT field_order FROM {$bp->profile->table_name_fields} WHERE id = %d", $field_id ) );
427                        if ( ! is_numeric( $field->field_order ) || is_wp_error( $field->field_order ) ) {
428                                $field->field_order = (int) $wpdb->get_var( $wpdb->prepare( "SELECT max(field_order) FROM {$bp->profile->table_name_fields} WHERE group_id = %d", $group_id ) );
429                                $field->field_order++;
430                        }
431
432                        // For new profile fields, set the $field_id. For existing profile
433                        // fields, this will overwrite $field_id with the same value.
434                        $field_id = $field->save();
435
436                        if ( empty( $field_id ) ) {
437                                $message = __( 'There was an error saving the field. Please try again.', 'buddypress' );
438                                $type    = 'error';
439                        } else {
440                                $message = __( 'The field was saved successfully.', 'buddypress' );
441                                $type    = 'success';
442
443                                // @todo remove these old options
444                                if ( 1 == $field_id ) {
445                                        bp_update_option( 'bp-xprofile-fullname-field-name', $field->name );
446                                }
447
448                                // Set member types.
449                                if ( isset( $_POST['has-member-types'] ) ) {
450                                        $member_types = array();
451                                        if ( isset( $_POST['member-types'] ) ) {
452                                                $member_types = stripslashes_deep( $_POST['member-types'] );
453                                        }
454
455                                        $field->set_member_types( $member_types );
456                                }
457
458                                // Validate default visibility.
459                                if ( ! empty( $_POST['default-visibility'] ) && in_array( $_POST['default-visibility'], wp_list_pluck( bp_xprofile_get_visibility_levels(), 'id' ) ) ) {
460                                        bp_xprofile_update_field_meta( $field_id, 'default_visibility', $_POST['default-visibility'] );
461                                }
462
463                                // Validate custom visibility.
464                                if ( ! empty( $_POST['allow-custom-visibility'] ) && in_array( $_POST['allow-custom-visibility'], array( 'allowed', 'disabled' ) ) ) {
465                                        bp_xprofile_update_field_meta( $field_id, 'allow_custom_visibility', $_POST['allow-custom-visibility'] );
466                                }
467
468                                // Validate signup.
469                                if ( ! empty( $_POST['signup-position'] ) ) {
470                                        bp_xprofile_update_field_meta( $field_id, 'signup_position', (int) $_POST['signup-position'] );
471                                } else {
472                                        bp_xprofile_delete_meta( $field_id, 'field', 'signup_position' );
473                                }
474
475                                // Save autolink settings.
476                                if ( isset( $_POST['do_autolink'] ) && 'on' === wp_unslash( $_POST['do_autolink'] ) ) {
477                                        bp_xprofile_update_field_meta( $field_id, 'do_autolink', 'on' );
478                                } else {
479                                        bp_xprofile_update_field_meta( $field_id, 'do_autolink', 'off' );
480                                }
481
482                                if ( $field->type_obj->do_settings_section() ) {
483                                        $settings = isset( $_POST['field-settings'] ) ? wp_unslash( $_POST['field-settings'] ) : array();
484                                        $field->admin_save_settings( $settings );
485                                }
486
487                                /**
488                                 * Fires at the end of the process to save a field for a user, if successful.
489                                 *
490                                 * @since 1.0.0
491                                 *
492                                 * @param BP_XProfile_Field $field Current BP_XProfile_Field object.
493                                 */
494                                do_action( 'xprofile_fields_saved_field', $field );
495
496                                $groups = bp_xprofile_get_groups();
497                        }
498
499                        xprofile_admin_screen( $message, $type );
500
501                } else {
502                        $field->render_admin_form( $message );
503                }
504        } else {
505                $field->render_admin_form();
506        }
507}
508
509/**
510 * Handles the deletion of a profile field (or field option).
511 *
512 * @since 1.0.0
513 *
514 * @global string $message The feedback message to show.
515 * @global string $type The type of feedback message to show.
516 *
517 * @param int    $field_id    The field to delete.
518 * @param string $field_type  The type of field being deleted.
519 * @param bool   $delete_data Should the field data be deleted too.
520 */
521function xprofile_admin_delete_field( $field_id, $field_type = 'field', $delete_data = false ) {
522        global $message, $type;
523
524        // Switch type to 'option' if type is not 'field'.
525        // @todo trust this param.
526        $field_type  = ( 'field' == $field_type ) ? __( 'field', 'buddypress' ) : __( 'option', 'buddypress' );
527        $field       = xprofile_get_field( $field_id );
528
529        if ( !$field->delete( (bool) $delete_data ) ) {
530                $message = sprintf( __( 'There was an error deleting the %s. Please try again.', 'buddypress' ), $field_type );
531                $type    = 'error';
532        } else {
533                $message = sprintf( __( 'The %s was deleted successfully!', 'buddypress' ), $field_type );
534                $type    = 'success';
535
536                /**
537                 * Fires at the end of the field deletion process, if successful.
538                 *
539                 * @since 1.0.0
540                 *
541                 * @param BP_XProfile_Field $field Current BP_XProfile_Field object.
542                 */
543                do_action( 'xprofile_fields_deleted_field', $field );
544        }
545
546        xprofile_admin_screen( $message, $type );
547}
548
549/**
550 * Handles the ajax reordering of fields within a group.
551 *
552 * @since 1.0.0
553 */
554function xprofile_ajax_reorder_fields() {
555
556        // Check the nonce.
557        check_admin_referer( 'bp_reorder_fields', '_wpnonce_reorder_fields' );
558
559        if ( empty( $_POST['field_order'] ) ) {
560                return false;
561        }
562
563        parse_str( $_POST['field_order'], $order );
564
565        $field_group_id = $_POST['field_group_id'];
566
567        foreach ( (array) $order['draggable_field'] as $position => $field_id ) {
568                xprofile_update_field_position( (int) $field_id, (int) $position, (int) $field_group_id );
569        }
570}
571add_action( 'wp_ajax_xprofile_reorder_fields', 'xprofile_ajax_reorder_fields' );
572
573/**
574 * Handles the reordering of field groups.
575 *
576 * @since 1.5.0
577 */
578function xprofile_ajax_reorder_field_groups() {
579
580        // Check the nonce.
581        check_admin_referer( 'bp_reorder_groups', '_wpnonce_reorder_groups' );
582
583        if ( empty( $_POST['group_order'] ) ) {
584                return false;
585        }
586
587        parse_str( $_POST['group_order'], $order );
588
589        foreach ( (array) $order['group'] as $position => $field_group_id ) {
590                xprofile_update_field_group_position( (int) $field_group_id, (int) $position );
591        }
592}
593add_action( 'wp_ajax_xprofile_reorder_groups', 'xprofile_ajax_reorder_field_groups' );
594
595/**
596 * Handles the WYSIWYG display of each profile field on the edit screen.
597 *
598 * @since 1.5.0
599 *
600 * @param BP_XProfile_Field   $admin_field Admin field.
601 * @param object $admin_group Admin group object.
602 * @param string $class       Classes to append to output.
603 */
604function xprofile_admin_field( $admin_field, $admin_group, $class = '' ) {
605        global $field;
606
607        $field = $admin_field;
608
609        $field_edit_url = add_query_arg(
610                array(
611                        'page'     => 'bp-profile-setup',
612                        'group_id' => (int) $field->group_id,
613                        'field_id' => (int) $field->id,
614                        'mode'     => 'edit_field'
615                ),
616                admin_url( 'users.php' )
617        );
618
619        if ( $field->can_delete ) {
620                $field_delete_url = add_query_arg(
621                        array(
622                                'page'     => 'bp-profile-setup',
623                                'field_id' => (int) $field->id,
624                                'mode'     => 'delete_field'
625                        ),
626                        admin_url( 'users.php' ) . '#tabs-' . (int) $field->group_id
627                );
628        }
629        ?>
630
631        <fieldset id="draggable_field_<?php echo esc_attr( $field->id ); ?>" class="sortable<?php echo ' ' . $field->type; if ( !empty( $class ) ) echo ' ' . $class; ?>">
632                <legend>
633                        <span>
634                                <?php bp_the_profile_field_name(); ?>
635
636                                <?php if ( empty( $field->can_delete )                                    ) : ?><?php esc_html_e( '(Primary)',  'buddypress' ); endif; ?>
637                                <?php bp_the_profile_field_required_label(); ?>
638                                <?php if ( bp_xprofile_get_meta( $field->id, 'field', 'signup_position' ) ) : ?><?php esc_html_e( '(Sign-up)',  'buddypress' ); endif; ?>
639                                <?php if ( bp_get_member_types() ) : echo $field->get_member_type_label(); endif; ?>
640
641                                <?php
642
643                                /**
644                                 * Fires at end of legend above the name field in base xprofile group.
645                                 *
646                                 * @since 2.2.0
647                                 *
648                                 * @param BP_XProfile_Field $field Current BP_XProfile_Field
649                                 *                                 object being rendered.
650                                 */
651                                do_action( 'xprofile_admin_field_name_legend', $field ); ?>
652                        </span>
653                </legend>
654                <div class="field-wrapper">
655
656                        <?php
657                        if ( in_array( $field->type, array_keys( bp_xprofile_get_field_types() ) ) ) {
658                                $field_type = bp_xprofile_create_field_type( $field->type );
659                                $field_type->admin_field_html();
660                        } else {
661
662                                /**
663                                 * Fires after the input if the current field is not in default field types.
664                                 *
665                                 * @since 1.5.0
666                                 *
667                                 * @param BP_XProfile_Field $field Current BP_XProfile_Field
668                                 *                                 object being rendered.
669                                 * @param int               $value Integer 1.
670                                 */
671                                do_action( 'xprofile_admin_field', $field, 1 );
672                        }
673                        ?>
674
675                        <?php if ( $field->description ) : ?>
676
677                                <p class="description"><?php echo esc_attr( $field->description ); ?></p>
678
679                        <?php endif; ?>
680
681                        <div class="actions">
682                                <a class="button edit" href="<?php echo esc_url( $field_edit_url ); ?>"><?php _ex( 'Edit', 'Edit field link', 'buddypress' ); ?></a>
683
684                                <?php if ( $field->can_delete ) : ?>
685
686                                        <div class="delete-button">
687                                                <a class="confirm submit-delete deletion" href="<?php echo esc_url( $field_delete_url ); ?>"><?php _ex( 'Delete', 'Delete field link', 'buddypress' ); ?></a>
688                                        </div>
689
690                                <?php endif; ?>
691
692                                <?php
693
694                                /**
695                                 * Fires at end of field management links in xprofile management admin.
696                                 *
697                                 * @since 2.2.0
698                                 *
699                                 * @param BP_XProfile_Group $group BP_XProfile_Group object
700                                 *                                 for the current group.
701                                 */
702                                do_action( 'xprofile_admin_field_action', $field ); ?>
703
704                        </div>
705                </div>
706        </fieldset>
707
708<?php
709}
710
711/**
712 * Print <option> elements containing the xprofile field types.
713 *
714 * @since 2.0.0
715 *
716 * @param string $select_field_type The name of the field type that should be selected.
717 *                                  Will defaults to "textbox" if NULL is passed.
718 */
719function bp_xprofile_admin_form_field_types( $select_field_type ) {
720        $categories = array();
721
722        if ( is_null( $select_field_type ) ) {
723                $select_field_type = 'textbox';
724        }
725
726        // Sort each field type into its category.
727        foreach ( bp_xprofile_get_field_types() as $field_name => $field_class ) {
728                $field_type_obj = new $field_class;
729                $the_category   = $field_type_obj->category;
730
731                // Fallback to a catch-all if category not set.
732                if ( ! $the_category ) {
733                        $the_category = _x( 'Other', 'xprofile field type category', 'buddypress' );
734                }
735
736                if ( isset( $categories[$the_category] ) ) {
737                        $categories[$the_category][] = array( $field_name, $field_type_obj );
738                } else {
739                        $categories[$the_category] = array( array( $field_name, $field_type_obj ) );
740                }
741        }
742
743        // Sort the categories alphabetically. ksort()'s SORT_NATURAL is only in PHP >= 5.4 :((.
744        uksort( $categories, 'strnatcmp' );
745
746        // Loop through each category and output form <options>.
747        foreach ( $categories as $category => $fields ) {
748                printf( '<optgroup label="%1$s">', esc_attr( $category ) );  // Already i18n'd in each profile type class.
749
750                // Sort these fields types alphabetically.
751                uasort( $fields, function( $a, $b ) { return strnatcmp( $a[1]->name, $b[1]->name ); } );
752
753                foreach ( $fields as $field_type_obj ) {
754                        $field_name     = $field_type_obj[0];
755                        $field_type_obj = $field_type_obj[1];
756
757                        printf( '<option value="%1$s" %2$s>%3$s</option>', esc_attr( $field_name ), selected( $select_field_type, $field_name, false ), esc_html( $field_type_obj->name ) );
758                }
759
760                printf( '</optgroup>' );
761        }
762}
763
764// Load the xprofile user admin.
765add_action( 'bp_init', array( 'BP_XProfile_User_Admin', 'register_xprofile_user_admin' ), 11 );