Skip to:
Content

BuddyPress.org

Ticket #5220: 5220.04.patch

File 5220.04.patch, 121.5 KB (added by DJPaul, 13 years ago)
  • bp-members/admin/css/admin.css

    diff --git a/bp-members/admin/css/admin.css b/bp-members/admin/css/admin.css
    index 5473fe5..5d295da 100644
    a b div#profile-page.wrap form#your-profile ul#profile-nav {  
    1515        width:100%;
    1616}
    1717
    18 div#community-profile-page h2:first-of-type {
    19         margin-bottom:1em;
    20 }
    21 
    22 div#community-profile-page  h2.profile-section {
    23         border-bottom:dotted 1px #ccc;
    24 }
    25 
    2618div#community-profile-page ul#profile-nav {
    2719        border-bottom:solid 1px #ccc;
    2820        width:100%;
    … … div#community-profile-page p.not-activated {  
    10496        color:red;
    10597}
    10698
    107 div#community-profile-page .form-table td.admin-field-visibility-td {
    108         padding:5px 5px 15px 5px;
     99.alt {
     100        background: none;
    109101}
    110 
    111 div#community-profile-page .form-table tr.admin-field-visibility-tr {
    112         border-bottom:dotted 1px #ccc;
     102.bp-profile-field {
     103        border-bottom: dotted 1px #ccc;
     104        font-size: 14px;
     105        margin: 15px 0;
    113106}
    114 
    115 div#community-profile-page .form-table tr.admin-field-visibility-tr:last-child{
    116         border:none;
     107.bp-profile-field:last-child {
     108        border-bottom: 0;
    117109}
    118 
    119 div#community-profile-page .field-visibility-settings legend,
    120 div#community-profile-page .field-visibility-settings-notoggle {
     110.bp-profile-field p {
    121111        font-size: 14px;
    122         font-style: italic;
    123         color:#666;
    124112}
    125 
    126 div#community-profile-page .field-visibility-settings ul {
    127         margin:0;
    128         font-size: 13px;
     113.bp-profile-field .datebox > label,
     114.bp-profile-field .radio > label,
     115.bp-profile-field > label {  /* label takes on left side 200px */
     116        display: inline-block;
     117        font-weight: 600;
     118        text-align: left;
     119        vertical-align: middle;
     120        width: 200px;
    129121}
    130122
    131 div#community-profile-page .field-visibility-settings ul li {
    132         display:inline-block;
    133         margin-right:1em;
     123.field_type_textarea > label,
     124.field_type_multiselectbox > label,
     125.field_type_radio .radio > label,
     126.field_type_checkbox .checkbox > label {  /* these fields are usually pretty tall, so align the label for better consistency */
     127        vertical-align: top;
    134128}
    135 
    136 div#community-profile-page .form-table td.admin-field-radio label,
    137 div#community-profile-page .form-table td.admin-field-checkbox label {
    138         display:block;
     129.bp-profile-field .description {  /* description also sits in the right side column */
     130        margin: 10px 0 10px 200px;
     131        text-align: left;
    139132}
    140 
    141 .field-visibility-settings {
     133.clear-value {  /* 'clear value' option also sits in the right side column */
     134        display: block;
     135        font-size: 12px;
     136        margin-left: 200px;
     137}
     138.field_type_checkbox .checkbox > label + label {  /* force checkboxes to new lines, in the right side column */
     139        display: block;
     140        margin-left: 200px;
     141        width: auto;
     142}
     143.field_type_radio .radio div:not(.field-visibility-settings) label {  /* force radio buttons to new lines */
     144        display: block;
     145}
     146.field_type_radio .radio div:not(.field-visibility-settings) {  /* make the radio buttons sit in the right side column */
     147        display: inline-block;
     148}
     149.field-visibility-settings-notoggle,
     150.field-visibility-settings-toggle {  /* visibility settings go in the left column */
     151        margin: 10px 0 10px 200px;
     152        text-align: left;
     153}
     154.field-visibility-settings {  /* visibility settings go in the left column */
    142155        display: none;
    143 }
    144  No newline at end of file
     156        margin-left: 200px;
     157}
     158.field-visibility-settings .button {  /* visibility setting close button */
     159        margin-bottom: 15px;
     160}
     161#normal-sortables .field-visibility-settings legend {  /* id required for css selector weight */
     162        font-size: 16px;
     163        margin-bottom: 10px;
     164}
  • bp-templates/bp-legacy/buddypress/members/register.php

    diff --git a/bp-templates/bp-legacy/buddypress/members/register.php b/bp-templates/bp-legacy/buddypress/members/register.php
    index 8679dc2..6624817 100644
    a b  
    6868
    6969                                                <div class="editfield">
    7070
    71                                                         <?php if ( 'textbox' == bp_get_the_profile_field_type() ) : ?>
     71                                                        <?php
     72                                                        $field_type = bp_xprofile_create_field_type( bp_get_the_profile_field_type() );
     73                                                        $field_type->edit_field_html();
    7274
    73                                                                 <label for="<?php bp_the_profile_field_input_name(); ?>"><?php bp_the_profile_field_name(); ?> <?php if ( bp_get_the_profile_field_is_required() ) : ?><?php _e( '(required)', 'buddypress' ); ?><?php endif; ?></label>
    74                                                                 <?php do_action( bp_get_the_profile_field_errors_action() ); ?>
    75                                                                 <input type="text" name="<?php bp_the_profile_field_input_name(); ?>" id="<?php bp_the_profile_field_input_name(); ?>" value="<?php bp_the_profile_field_edit_value(); ?>" />
     75                                                        do_action( 'bp_custom_profile_edit_fields_pre_visibility' );
    7676
    77                                                         <?php endif; ?>
    78 
    79                                                         <?php if ( 'textarea' == bp_get_the_profile_field_type() ) : ?>
    80 
    81                                                                 <label for="<?php bp_the_profile_field_input_name(); ?>"><?php bp_the_profile_field_name(); ?> <?php if ( bp_get_the_profile_field_is_required() ) : ?><?php _e( '(required)', 'buddypress' ); ?><?php endif; ?></label>
    82                                                                 <?php do_action( bp_get_the_profile_field_errors_action() ); ?>
    83                                                                 <textarea rows="5" cols="40" name="<?php bp_the_profile_field_input_name(); ?>" id="<?php bp_the_profile_field_input_name(); ?>"><?php bp_the_profile_field_edit_value(); ?></textarea>
    84 
    85                                                         <?php endif; ?>
    86 
    87                                                         <?php if ( 'selectbox' == bp_get_the_profile_field_type() ) : ?>
    88 
    89                                                                 <label for="<?php bp_the_profile_field_input_name(); ?>"><?php bp_the_profile_field_name(); ?> <?php if ( bp_get_the_profile_field_is_required() ) : ?><?php _e( '(required)', 'buddypress' ); ?><?php endif; ?></label>
    90                                                                 <?php do_action( bp_get_the_profile_field_errors_action() ); ?>
    91                                                                 <select name="<?php bp_the_profile_field_input_name(); ?>" id="<?php bp_the_profile_field_input_name(); ?>">
    92                                                                         <?php bp_the_profile_field_options(); ?>
    93                                                                 </select>
    94 
    95                                                         <?php endif; ?>
    96 
    97                                                         <?php if ( 'multiselectbox' == bp_get_the_profile_field_type() ) : ?>
    98 
    99                                                                 <label for="<?php bp_the_profile_field_input_name(); ?>"><?php bp_the_profile_field_name(); ?> <?php if ( bp_get_the_profile_field_is_required() ) : ?><?php _e( '(required)', 'buddypress' ); ?><?php endif; ?></label>
    100                                                                 <?php do_action( bp_get_the_profile_field_errors_action() ); ?>
    101                                                                 <select name="<?php bp_the_profile_field_input_name(); ?>" id="<?php bp_the_profile_field_input_name(); ?>" multiple="multiple">
    102                                                                         <?php bp_the_profile_field_options(); ?>
    103                                                                 </select>
    104 
    105                                                         <?php endif; ?>
    106 
    107                                                         <?php if ( 'radio' == bp_get_the_profile_field_type() ) : ?>
    108 
    109                                                                 <div class="radio">
    110                                                                         <span class="label"><?php bp_the_profile_field_name(); ?> <?php if ( bp_get_the_profile_field_is_required() ) : ?><?php _e( '(required)', 'buddypress' ); ?><?php endif; ?></span>
    111 
    112                                                                         <?php do_action( bp_get_the_profile_field_errors_action() ); ?>
    113                                                                         <?php bp_the_profile_field_options(); ?>
    114 
    115                                                                         <?php if ( !bp_get_the_profile_field_is_required() ) : ?>
    116                                                                                 <a class="clear-value" href="javascript:clear( '<?php bp_the_profile_field_input_name(); ?>' );"><?php _e( 'Clear', 'buddypress' ); ?></a>
    117                                                                         <?php endif; ?>
    118                                                                 </div>
    119 
    120                                                         <?php endif; ?>
    121 
    122                                                         <?php if ( 'checkbox' == bp_get_the_profile_field_type() ) : ?>
    123 
    124                                                                 <div class="checkbox">
    125                                                                         <span class="label"><?php bp_the_profile_field_name(); ?> <?php if ( bp_get_the_profile_field_is_required() ) : ?><?php _e( '(required)', 'buddypress' ); ?><?php endif; ?></span>
    126 
    127                                                                         <?php do_action( bp_get_the_profile_field_errors_action() ); ?>
    128                                                                         <?php bp_the_profile_field_options(); ?>
    129                                                                 </div>
    130 
    131                                                         <?php endif; ?>
    132 
    133                                                         <?php if ( 'datebox' == bp_get_the_profile_field_type() ) : ?>
    134 
    135                                                                 <div class="datebox">
    136                                                                         <label for="<?php bp_the_profile_field_input_name(); ?>_day"><?php bp_the_profile_field_name(); ?> <?php if ( bp_get_the_profile_field_is_required() ) : ?><?php _e( '(required)', 'buddypress' ); ?><?php endif; ?></label>
    137                                                                         <?php do_action( bp_get_the_profile_field_errors_action() ); ?>
    138 
    139                                                                         <select name="<?php bp_the_profile_field_input_name(); ?>_day" id="<?php bp_the_profile_field_input_name(); ?>_day">
    140                                                                                 <?php bp_the_profile_field_options( 'type=day' ); ?>
    141                                                                         </select>
    142 
    143                                                                         <select name="<?php bp_the_profile_field_input_name(); ?>_month" id="<?php bp_the_profile_field_input_name(); ?>_month">
    144                                                                                 <?php bp_the_profile_field_options( 'type=month' ); ?>
    145                                                                         </select>
    146 
    147                                                                         <select name="<?php bp_the_profile_field_input_name(); ?>_year" id="<?php bp_the_profile_field_input_name(); ?>_year">
    148                                                                                 <?php bp_the_profile_field_options( 'type=year' ); ?>
    149                                                                         </select>
    150                                                                 </div>
    151 
    152                                                         <?php endif; ?>
    153 
    154                                                         <?php do_action( 'bp_custom_profile_edit_fields_pre_visibility' ); ?>
    155 
    156                                                         <?php if ( bp_current_user_can( 'bp_xprofile_change_field_visibility' ) ) : ?>
     77                                                        if ( bp_current_user_can( 'bp_xprofile_change_field_visibility' ) ) : ?>
    15778                                                                <p class="field-visibility-settings-toggle" id="field-visibility-settings-toggle-<?php bp_the_profile_field_id() ?>">
    15879                                                                        <?php printf( __( 'This field can be seen by: <span class="current-visibility-level">%s</span>', 'buddypress' ), bp_get_the_profile_field_visibility_level_label() ) ?> <a href="#" class="visibility-toggle-link"><?php _ex( 'Change', 'Change profile field visibility level', 'buddypress' ); ?></a>
    15980                                                                </p>
  • bp-templates/bp-legacy/buddypress/members/single/profile/edit.php

    diff --git a/bp-templates/bp-legacy/buddypress/members/single/profile/edit.php b/bp-templates/bp-legacy/buddypress/members/single/profile/edit.php
    index b7b6cc5..a20c079 100644
    a b if ( bp_has_profile( 'profile_group_id=' . bp_get_current_profile_group_id() ) )  
    2121
    2222                        <div<?php bp_field_css_class( 'editfield' ); ?>>
    2323
    24                                 <?php if ( 'textbox' == bp_get_the_profile_field_type() ) : ?>
     24                                <?php
     25                                $field_type = bp_xprofile_create_field_type( bp_get_the_profile_field_type() );
     26                                $field_type->edit_field_html();
    2527
    26                                         <label for="<?php bp_the_profile_field_input_name(); ?>"><?php bp_the_profile_field_name(); ?> <?php if ( bp_get_the_profile_field_is_required() ) : ?><?php _e( '(required)', 'buddypress' ); ?><?php endif; ?></label>
    27                                         <input type="text" name="<?php bp_the_profile_field_input_name(); ?>" id="<?php bp_the_profile_field_input_name(); ?>" value="<?php bp_the_profile_field_edit_value(); ?>" <?php if ( bp_get_the_profile_field_is_required() ) : ?>aria-required="true"<?php endif; ?>/>
    28 
    29                                 <?php endif; ?>
    30 
    31                                 <?php if ( 'textarea' == bp_get_the_profile_field_type() ) : ?>
    32 
    33                                         <label for="<?php bp_the_profile_field_input_name(); ?>"><?php bp_the_profile_field_name(); ?> <?php if ( bp_get_the_profile_field_is_required() ) : ?><?php _e( '(required)', 'buddypress' ); ?><?php endif; ?></label>
    34                                         <textarea rows="5" cols="40" name="<?php bp_the_profile_field_input_name(); ?>" id="<?php bp_the_profile_field_input_name(); ?>" <?php if ( bp_get_the_profile_field_is_required() ) : ?>aria-required="true"<?php endif; ?>><?php bp_the_profile_field_edit_value(); ?></textarea>
    35 
    36                                 <?php endif; ?>
    37 
    38                                 <?php if ( 'selectbox' == bp_get_the_profile_field_type() ) : ?>
    39 
    40                                         <label for="<?php bp_the_profile_field_input_name(); ?>"><?php bp_the_profile_field_name(); ?> <?php if ( bp_get_the_profile_field_is_required() ) : ?><?php _e( '(required)', 'buddypress' ); ?><?php endif; ?></label>
    41                                         <select name="<?php bp_the_profile_field_input_name(); ?>" id="<?php bp_the_profile_field_input_name(); ?>" <?php if ( bp_get_the_profile_field_is_required() ) : ?>aria-required="true"<?php endif; ?>>
    42                                                 <?php bp_the_profile_field_options(); ?>
    43                                         </select>
    44 
    45                                 <?php endif; ?>
    46 
    47                                 <?php if ( 'multiselectbox' == bp_get_the_profile_field_type() ) : ?>
    48 
    49                                         <label for="<?php bp_the_profile_field_input_name(); ?>"><?php bp_the_profile_field_name(); ?> <?php if ( bp_get_the_profile_field_is_required() ) : ?><?php _e( '(required)', 'buddypress' ); ?><?php endif; ?></label>
    50                                         <select name="<?php bp_the_profile_field_input_name(); ?>" id="<?php bp_the_profile_field_input_name(); ?>" multiple="multiple" <?php if ( bp_get_the_profile_field_is_required() ) : ?>aria-required="true"<?php endif; ?>>
    51 
    52                                                 <?php bp_the_profile_field_options(); ?>
    53 
    54                                         </select>
    55 
    56                                         <?php if ( !bp_get_the_profile_field_is_required() ) : ?>
    57 
    58                                                 <a class="clear-value" href="javascript:clear( '<?php bp_the_profile_field_input_name(); ?>' );"><?php _e( 'Clear', 'buddypress' ); ?></a>
    59 
    60                                         <?php endif; ?>
    61 
    62                                 <?php endif; ?>
    63 
    64                                 <?php if ( 'radio' == bp_get_the_profile_field_type() ) : ?>
    65 
    66                                         <div class="radio">
    67                                                 <span class="label"><?php bp_the_profile_field_name(); ?> <?php if ( bp_get_the_profile_field_is_required() ) : ?><?php _e( '(required)', 'buddypress' ); ?><?php endif; ?></span>
    68 
    69                                                 <?php bp_the_profile_field_options(); ?>
    70 
    71                                                 <?php if ( !bp_get_the_profile_field_is_required() ) : ?>
    72 
    73                                                         <a class="clear-value" href="javascript:clear( '<?php bp_the_profile_field_input_name(); ?>' );"><?php _e( 'Clear', 'buddypress' ); ?></a>
    74 
    75                                                 <?php endif; ?>
    76                                         </div>
    77 
    78                                 <?php endif; ?>
    79 
    80                                 <?php if ( 'checkbox' == bp_get_the_profile_field_type() ) : ?>
    81 
    82                                         <div class="checkbox">
    83                                                 <span class="label"><?php bp_the_profile_field_name(); ?> <?php if ( bp_get_the_profile_field_is_required() ) : ?><?php _e( '(required)', 'buddypress' ); ?><?php endif; ?></span>
    84 
    85                                                 <?php bp_the_profile_field_options(); ?>
    86                                         </div>
    87 
    88                                 <?php endif; ?>
    89 
    90                                 <?php if ( 'datebox' == bp_get_the_profile_field_type() ) : ?>
    91 
    92                                         <div class="datebox">
    93                                                 <label for="<?php bp_the_profile_field_input_name(); ?>_day"><?php bp_the_profile_field_name(); ?> <?php if ( bp_get_the_profile_field_is_required() ) : ?><?php _e( '(required)', 'buddypress' ); ?><?php endif; ?></label>
    94 
    95                                                 <select name="<?php bp_the_profile_field_input_name(); ?>_day" id="<?php bp_the_profile_field_input_name(); ?>_day" <?php if ( bp_get_the_profile_field_is_required() ) : ?>aria-required="true"<?php endif; ?>>
    96 
    97                                                         <?php bp_the_profile_field_options( 'type=day' ); ?>
    98 
    99                                                 </select>
    100 
    101                                                 <select name="<?php bp_the_profile_field_input_name(); ?>_month" id="<?php bp_the_profile_field_input_name(); ?>_month" <?php if ( bp_get_the_profile_field_is_required() ) : ?>aria-required="true"<?php endif; ?>>
    102 
    103                                                         <?php bp_the_profile_field_options( 'type=month' ); ?>
    104 
    105                                                 </select>
    106 
    107                                                 <select name="<?php bp_the_profile_field_input_name(); ?>_year" id="<?php bp_the_profile_field_input_name(); ?>_year" <?php if ( bp_get_the_profile_field_is_required() ) : ?>aria-required="true"<?php endif; ?>>
    108 
    109                                                         <?php bp_the_profile_field_options( 'type=year' ); ?>
    110 
    111                                                 </select>
    112                                         </div>
    113 
    114                                 <?php endif; ?>
    115 
    116                                 <?php do_action( 'bp_custom_profile_edit_fields_pre_visibility' ); ?>
     28                                do_action( 'bp_custom_profile_edit_fields_pre_visibility' );
     29                                ?>
    11730
    11831                                <?php if ( bp_current_user_can( 'bp_xprofile_change_field_visibility' ) ) : ?>
    11932                                        <p class="field-visibility-settings-toggle" id="field-visibility-settings-toggle-<?php bp_the_profile_field_id() ?>">
  • bp-templates/bp-legacy/css/buddypress.css

    diff --git a/bp-templates/bp-legacy/css/buddypress.css b/bp-templates/bp-legacy/css/buddypress.css
    index befd22c..773519a 100644
    a b body.activity-permalink #buddypress div.activity-comments div.acomment-content {  
    607607        font-weight: bold;
    608608        margin: 15px 0 5px 0;
    609609}
    610 #buddypress .standard-form div.checkbox label,
    611 #buddypress .standard-form div.radio label {
     610#buddypress .standard-form div.checkbox label:nth-child(n+2),
     611#buddypress .standard-form div.radio div label {
    612612        color: #888;
    613613        font-size: 100%;
    614614        font-weight: normal;
  • bp-xprofile/bp-xprofile-admin.php

    diff --git a/bp-xprofile/bp-xprofile-admin.php b/bp-xprofile/bp-xprofile-admin.php
    index 1c275db..eca6366 100644
    a b function xprofile_admin_field( $admin_field, $admin_group, $class = '' ) {  
    382382                <legend><span><?php bp_the_profile_field_name(); ?> <?php if( !$field->can_delete ) : ?> <?php _e( '(Primary)', 'buddypress' ); endif; ?> <?php if ( bp_get_the_profile_field_is_required() ) : ?><?php _e( '(Required)', 'buddypress' ) ?><?php endif; ?></span></legend>
    383383                <div class="field-wrapper">
    384384
    385                         <?php switch ( $field->type ) : case 'textbox' : ?>
    386 
    387                                 <input type="text" name="<?php bp_the_profile_field_input_name() ?>" id="<?php bp_the_profile_field_input_name() ?>" value="" />
    388 
    389                         <?php break; case 'textarea' : ?>
    390 
    391                                 <textarea rows="5" cols="40" name="<?php bp_the_profile_field_input_name() ?>" id="<?php bp_the_profile_field_input_name() ?>"></textarea>
    392 
    393                         <?php break; case 'selectbox' : ?>
    394 
    395                                 <select name="<?php bp_the_profile_field_input_name() ?>" id="<?php bp_the_profile_field_input_name() ?>">
    396 
    397                                         <?php bp_the_profile_field_options() ?>
    398 
    399                                 </select>
    400 
    401                         <?php break; case 'multiselectbox' : ?>
    402 
    403                                 <select name="<?php bp_the_profile_field_input_name() ?>" id="<?php bp_the_profile_field_input_name() ?>" multiple="multiple">
    404 
    405                                         <?php bp_the_profile_field_options() ?>
    406 
    407                                 </select>
    408 
    409                         <?php break; case 'radio' : ?>
    410 
    411                                 <?php bp_the_profile_field_options() ?>
    412 
    413                                 <?php if ( !bp_get_the_profile_field_is_required() ) : ?>
    414 
    415                                         <a class="clear-value" href="javascript:clear( '<?php bp_the_profile_field_input_name() ?>' );"><?php _e( 'Clear', 'buddypress' ) ?></a>
    416 
    417                                 <?php endif; ?>
    418 
    419                         <?php break; case 'checkbox' : ?>
    420 
    421                                 <?php bp_the_profile_field_options(); ?>
    422 
    423                         <?php break; case 'datebox' : ?>
    424 
    425                                 <select name="<?php bp_the_profile_field_input_name(); ?>_day" id="<?php bp_the_profile_field_input_name(); ?>_day">
    426 
    427                                         <?php bp_the_profile_field_options( 'type=day' ); ?>
    428 
    429                                 </select>
    430 
    431                                 <select name="<?php bp_the_profile_field_input_name(); ?>_month" id="<?php bp_the_profile_field_input_name(); ?>_month">
    432 
    433                                         <?php bp_the_profile_field_options( 'type=month' ); ?>
    434 
    435                                 </select>
    436 
    437                                 <select name="<?php bp_the_profile_field_input_name(); ?>_year" id="<?php bp_the_profile_field_input_name(); ?>_year">
    438 
    439                                         <?php bp_the_profile_field_options( 'type=year' ); ?>
    440 
    441                                 </select>
    442 
    443                         <?php break; default : ?>
    444 
    445                         <?php do_action( 'xprofile_admin_field', $field, 1 ); ?>
     385                        <?php
     386                        $field_type = bp_xprofile_create_field_type( $field->type );
     387                        $field_type->admin_field_html();
    446388
    447                         <?php endswitch; ?>
     389                        do_action( 'xprofile_admin_field', $field, 1 );
     390                        ?>
    448391
    449392                        <?php if ( $field->description ) : ?>
    450393
    … … function xprofile_admin_field( $admin_field, $admin_group, $class = '' ) {  
    467410<?php
    468411}
    469412
     413/**
     414 * Print <option> elements containing the xprofile field types.
     415 *
     416 * @param string $select_field_type The name of the field type that should be selected. Will defaults to "textbox" if NULL is passed.
     417 * @since BuddyPress (2.0.0)
     418 */
     419function bp_xprofile_admin_form_field_types( $select_field_type ) {
     420        $categories = array();
     421
     422        if ( is_null( $select_field_type ) ) {
     423                $select_field_type = 'textbox';
     424        }
     425
     426        // Sort each field type into its category
     427        foreach ( bp_xprofile_get_field_types() as $field_name => $field_class ) {
     428                $field_type_obj = new $field_class;
     429                $the_category   = $field_type_obj->category;
     430
     431                // Fallback to a catch-all if category not set
     432                if ( ! $the_category ) {
     433                        $the_category = _x( 'Other', 'xprofile field type category', 'buddypress' );
     434                }
     435
     436                if ( isset( $categories[$the_category] ) ) {
     437                        $categories[$the_category][] = array( $field_name, $field_type_obj );
     438                } else {
     439                        $categories[$the_category] = array( array( $field_name, $field_type_obj ) );
     440                }
     441        }
     442
     443        // Sort the categories alphabetically. ksort()'s SORT_NATURAL is only in PHP >= 5.4 :((
     444        uksort( $categories, 'strnatcmp' );
     445
     446        // Loop through each category and output form <options>
     447        foreach ( $categories as $category => $fields ) {
     448                printf( '<optgroup label="%1$s">', esc_attr( $category ) );  // Already i18n'd in each profile type class
     449
     450                // Sort these fields types alphabetically
     451                uasort( $fields, create_function( '$a, $b', 'return strnatcmp( $a[1]->name, $b[1]->name );' ) );
     452
     453                foreach ( $fields as $field_type_obj ) {
     454                        $field_name     = $field_type_obj[0];
     455                        $field_type_obj = $field_type_obj[1];
     456
     457                        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 ) );
     458                }
     459
     460                printf( '</optgroup>' );
     461        }
     462}
     463
    470464if ( ! class_exists( 'BP_XProfile_User_Admin' ) ) :
    471465/**
    472466 * Load xProfile Profile admin area.
    … … class BP_XProfile_User_Admin {  
    642636                                // Set the errors var
    643637                                $errors = false;
    644638
    645                                 // Now we've checked for required fields, lets save the values.
     639                                // Now we've checked for required fields, let's save the values.
    646640                                foreach ( (array) $posted_field_ids as $field_id ) {
    647641
    648642                                        // Certain types of fields (checkboxes, multiselects) may come through empty. Save them as an empty array so that they don't get overwritten by the default on the next edit.
    … … class BP_XProfile_User_Admin {  
    702696                }
    703697
    704698                if ( bp_has_profile( $r ) ) :
    705 
    706699                        while ( bp_profile_groups() ) : bp_the_profile_group(); ?>
     700                                <input type="hidden" name="field_ids[]" id="<?php echo esc_attr( 'field_ids_' . bp_get_the_profile_group_slug() ); ?>" value="<?php echo esc_attr( bp_get_the_profile_group_field_ids() ); ?>" />
    707701
    708                                 <p class="description"><?php bp_the_profile_group_description(); ?></p>
    709 
    710                                 <table class="form-table">
    711                                         <tbody>
    712 
    713                                         <?php while ( bp_profile_fields() ) : bp_the_profile_field(); ?>
    714 
    715                                                 <tr>
    716 
    717                                                         <?php if ( 'textbox' === bp_get_the_profile_field_type() ) : ?>
     702                                <?php if ( bp_get_the_profile_group_description() ) : ?>
     703                                        <p class="description"><?php bp_the_profile_group_description(); ?></p>
     704                                <?php
     705                                endif;
    718706
    719                                                                 <th><label for="<?php bp_the_profile_field_input_name(); ?>"><?php bp_the_profile_field_name(); ?> <?php if ( bp_get_the_profile_field_is_required() ) : ?><?php _e( '(required)', 'buddypress' ); ?><?php endif; ?></label></th>
    720                                                                 <td class="admin-field-<?php bp_the_profile_field_type();?>">
    721                                                                         <input type="text" name="<?php bp_the_profile_field_input_name(); ?>" id="<?php bp_the_profile_field_input_name(); ?>" value="<?php bp_the_profile_field_edit_value(); ?>" <?php if ( bp_get_the_profile_field_is_required() ) : ?>aria-required="true"<?php endif; ?>/>
    722                                                                         <span class="description"><?php bp_the_profile_field_description(); ?></span>
    723                                                                 </td>
     707                                while ( bp_profile_fields() ) : bp_the_profile_field(); ?>
    724708
    725                                                         <?php endif; ?>
    726 
    727                                                         <?php if ( 'textarea' === bp_get_the_profile_field_type() ) : ?>
     709                                        <div<?php bp_field_css_class( 'bp-profile-field' ); ?>>
     710                                                <?php
     711                                                $field_type = bp_xprofile_create_field_type( bp_get_the_profile_field_type() );
     712                                                $field_type->edit_field_html( array( 'user_id' => $r['user_id'] ) );
    728713
    729                                                                 <th><label for="<?php bp_the_profile_field_input_name(); ?>"><?php bp_the_profile_field_name(); ?> <?php if ( bp_get_the_profile_field_is_required() ) : ?><?php _e( '(required)', 'buddypress' ); ?><?php endif; ?></label></th>
    730                                                                 <td class="admin-field-<?php bp_the_profile_field_type();?>">
    731                                                                         <textarea rows="5" cols="40" name="<?php bp_the_profile_field_input_name(); ?>" id="<?php bp_the_profile_field_input_name(); ?>" <?php if ( bp_get_the_profile_field_is_required() ) : ?>aria-required="true"<?php endif; ?>><?php bp_the_profile_field_edit_value(); ?></textarea>
    732                                                                         <p class="description"><?php bp_the_profile_field_description(); ?></p>
    733                                                                 </td>
    734 
    735                                                         <?php endif; ?>
     714                                                if ( bp_get_the_profile_field_description() ) : ?>
     715                                                        <p class="description"><?php bp_the_profile_field_description(); ?></p>
     716                                                <?php endif;
    736717
    737                                                         <?php if ( 'selectbox' === bp_get_the_profile_field_type() ) : ?>
     718                                                do_action( 'bp_custom_profile_edit_fields_pre_visibility' );
     719                                                $can_change_visibility = bp_current_user_can( 'bp_xprofile_change_field_visibility' );
     720                                                ?>
    738721
    739                                                                 <th><label for="<?php bp_the_profile_field_input_name(); ?>"><?php bp_the_profile_field_name(); ?> <?php if ( bp_get_the_profile_field_is_required() ) : ?><?php _e( '(required)', 'buddypress' ); ?><?php endif; ?></label></th>
    740                                                                 <td class="admin-field-<?php bp_the_profile_field_type();?>">
    741                                                                         <select name="<?php bp_the_profile_field_input_name(); ?>" id="<?php bp_the_profile_field_input_name(); ?>" <?php if ( bp_get_the_profile_field_is_required() ) : ?>aria-required="true"<?php endif; ?>>
    742                                                                                 <?php bp_the_profile_field_options( array( 'user_id' => $r['user_id'], ) ); ?>
    743                                                                         </select>
    744                                                                         <span class="description"><?php bp_the_profile_field_description(); ?></span>
    745                                                                 </td>
     722                                                <p class="field-visibility-settings-<?php echo $can_change_visibility ? 'toggle' : 'notoggle'; ?>" id="field-visibility-settings-toggle-<?php bp_the_profile_field_id(); ?>">
     723                                                        <?php
     724                                                        printf( __( 'This field can be seen by: <span class="%s">%s</span>', 'buddypress' ), esc_attr( 'current-visibility-level' ), bp_get_the_profile_field_visibility_level_label() );
    746725
     726                                                        if ( $can_change_visibility ) : ?>
     727                                                                 <a href="#" class="button visibility-toggle-link"><?php _e( 'Change', 'buddypress' ); ?></a>
    747728                                                        <?php endif; ?>
     729                                                </p>
     730
     731                                                <?php if ( $can_change_visibility ) : ?>
     732                                                        <div class="field-visibility-settings" id="field-visibility-settings-<?php bp_the_profile_field_id() ?>">
     733                                                                <fieldset>
     734                                                                        <legend><?php _e( 'Who can see this field?', 'buddypress' ); ?></legend>
     735                                                                        <?php bp_profile_visibility_radio_buttons(); ?>
     736                                                                </fieldset>
     737                                                                <a class="button field-visibility-settings-close" href="#"><?php _e( 'Close', 'buddypress' ); ?></a>
     738                                                        </div>
     739                                                <?php endif;
    748740
    749                                                         <?php if ( 'multiselectbox' === bp_get_the_profile_field_type() ) : ?>
    750 
    751                                                                 <th><label for="<?php bp_the_profile_field_input_name(); ?>"><?php bp_the_profile_field_name(); ?> <?php if ( bp_get_the_profile_field_is_required() ) : ?><?php _e( '(required)', 'buddypress' ); ?><?php endif; ?></label></th>
    752                                                                 <td class="admin-field-<?php bp_the_profile_field_type();?>">
    753                                                                         <select name="<?php bp_the_profile_field_input_name(); ?>" id="<?php bp_the_profile_field_input_name(); ?>" multiple="multiple" <?php if ( bp_get_the_profile_field_is_required() ) : ?>aria-required="true"<?php endif; ?>>
    754 
    755                                                                                 <?php bp_the_profile_field_options( array( 'user_id' => $r['user_id'], ) ); ?>
    756 
    757                                                                         </select>
    758 
    759 
    760                                                                         <?php if ( !bp_get_the_profile_field_is_required() ) : ?>
    761 
    762                                                                                 <p><a class="clear-value" href="javascript:clear( '<?php bp_the_profile_field_input_name(); ?>' );"><?php _e( 'Clear', 'buddypress' ); ?></a></p>
    763 
    764                                                                         <?php endif; ?>
    765                                                                         <p class="description"><?php bp_the_profile_field_description(); ?></p>
    766                                                                 </td>
    767 
    768                                                         <?php endif; ?>
    769 
    770                                                         <?php if ( 'radio' === bp_get_the_profile_field_type() ) : ?>
    771 
    772                                                                 <th>
    773                                                                         <span class="label"><?php bp_the_profile_field_name(); ?> <?php if ( bp_get_the_profile_field_is_required() ) : ?><?php _e( '(required)', 'buddypress' ); ?><?php endif; ?></span>
    774                                                                 </th>
    775                                                                 <td class="admin-field-<?php bp_the_profile_field_type();?>">
    776                                                                         <fieldset>
    777                                                                                 <legend class="screen-reader-text"><span><?php bp_the_profile_field_name(); ?></span></legend>
    778                                                                                 <?php bp_the_profile_field_options( array( 'user_id' => $r['user_id'], ) ); ?>
    779                                                                         </fieldset>
    780 
    781                                                                         <?php if ( !bp_get_the_profile_field_is_required() ) : ?>
    782 
    783                                                                                 <p><a class="clear-value" href="javascript:clear( '<?php bp_the_profile_field_input_name(); ?>' );"><?php _e( 'Clear', 'buddypress' ); ?></a></p>
    784 
    785                                                                         <?php endif; ?>
    786                                                                         <p class="description"><?php bp_the_profile_field_description(); ?></p>
    787                                                                 </td>
    788 
    789                                                         <?php endif; ?>
    790 
    791                                                         <?php if ( 'checkbox' === bp_get_the_profile_field_type() ) : ?>
    792 
    793                                                                 <th>
    794                                                                         <span class="label"><?php bp_the_profile_field_name(); ?> <?php if ( bp_get_the_profile_field_is_required() ) : ?><?php _e( '(required)', 'buddypress' ); ?><?php endif; ?></span>
    795                                                                 </th>
    796                                                                 <td class="admin-field-<?php bp_the_profile_field_type();?>">
    797                                                                         <?php bp_the_profile_field_options( array( 'user_id' => $r['user_id'], ) ); ?>
    798                                                                         <p class="description"><?php bp_the_profile_field_description(); ?></p>
    799                                                                 </td>
    800 
    801                                                         <?php endif; ?>
    802 
    803                                                         <?php if ( 'datebox' === bp_get_the_profile_field_type() ) : ?>
    804 
    805                                                                 <th>
    806                                                                         <label for="<?php bp_the_profile_field_input_name(); ?>_day"><?php bp_the_profile_field_name(); ?> <?php if ( bp_get_the_profile_field_is_required() ) : ?><?php _e( '(required)', 'buddypress' ); ?><?php endif; ?></label>
    807                                                                 </th>
    808                                                                 <td class="admin-field-<?php bp_the_profile_field_type();?>">
    809                                                                         <select name="<?php bp_the_profile_field_input_name(); ?>_day" id="<?php bp_the_profile_field_input_name(); ?>_day" <?php if ( bp_get_the_profile_field_is_required() ) : ?>aria-required="true"<?php endif; ?>>
    810 
    811                                                                                 <?php bp_the_profile_field_options( array( 'user_id' => $r['user_id'], 'type' => 'day', ) ); ?>
    812 
    813                                                                         </select>
    814 
    815                                                                         <select name="<?php bp_the_profile_field_input_name(); ?>_month" id="<?php bp_the_profile_field_input_name(); ?>_month" <?php if ( bp_get_the_profile_field_is_required() ) : ?>aria-required="true"<?php endif; ?>>
    816 
    817                                                                                 <?php bp_the_profile_field_options( array( 'user_id' => $r['user_id'], 'type' => 'month', ) ); ?>
    818 
    819                                                                         </select>
    820 
    821                                                                         <select name="<?php bp_the_profile_field_input_name(); ?>_year" id="<?php bp_the_profile_field_input_name(); ?>_year" <?php if ( bp_get_the_profile_field_is_required() ) : ?>aria-required="true"<?php endif; ?>>
    822 
    823                                                                                 <?php bp_the_profile_field_options( array( 'user_id' => $r['user_id'], 'type' => 'year', ) ); ?>
    824 
    825                                                                         </select>
    826                                                                         <p class="description"><?php bp_the_profile_field_description(); ?></p>
    827                                                                 </td>
    828 
    829                                                         <?php endif; ?>
    830 
    831                                                 </tr>
    832 
    833                                                 <tr class="admin-field-visibility-tr">
    834                                                         <td class="admin-field-visibility-td">&nbsp;</td>
    835                                                         <td class="admin-field-visibility-td">
    836 
    837                                                                 <?php do_action( 'bp_custom_profile_edit_fields_pre_visibility' ); ?>
    838 
    839                                                                 <?php if ( bp_current_user_can( 'bp_xprofile_change_field_visibility' ) ) : ?>
    840                                                                         <p class="description field-visibility-settings-toggle" id="field-visibility-settings-toggle-<?php bp_the_profile_field_id() ?>">
    841                                                                                 <?php printf( __( 'This field can be seen by: <span class="current-visibility-level">%s</span>', 'buddypress' ), bp_get_the_profile_field_visibility_level_label() ) ?> <a href="#" class="visibility-toggle-link"><?php _e( 'Change', 'buddypress' ); ?></a>
    842                                                                         </p>
    843 
    844                                                                         <div class="field-visibility-settings" id="field-visibility-settings-<?php bp_the_profile_field_id() ?>">
    845                                                                                 <fieldset>
    846                                                                                         <legend><?php esc_html_e( 'Who can see this field?', 'buddypress' ) ?></legend>
    847 
    848                                                                                         <?php bp_profile_visibility_radio_buttons() ?>
    849 
    850                                                                                 </fieldset>
    851                                                                                 <a class="field-visibility-settings-close" href="#"><?php esc_html_e( 'Close', 'buddypress' ) ?></a>
    852                                                                         </div>
    853                                                                 <?php else : ?>
    854                                                                         <div class="field-visibility-settings-notoggle" id="field-visibility-settings-toggle-<?php bp_the_profile_field_id() ?>">
    855                                                                                 <?php printf( __( 'This field can be seen by: <span class="current-visibility-level">%s</span>', 'buddypress' ), bp_get_the_profile_field_visibility_level_label() ) ?>
    856                                                                         </div>
    857                                                                 <?php endif ?>
    858 
    859                                                         </td>
    860                                                 </tr>
     741                                                do_action( 'bp_custom_profile_edit_fields' ); ?>
     742                                        </div>
    861743
    862                                         <?php endwhile; ?>
    863                                         </tbody>
     744                                <?php
     745                                endwhile; // bp_profile_fields()
    864746
    865                                 </table>
    866                                 <input type="hidden" name="field_ids[]" id="field_ids_<?php bp_the_profile_group_slug(); ?>" value="<?php bp_the_profile_group_field_ids(); ?>" />
    867                         <?php endwhile;
     747                        endwhile; // bp_profile_groups()
    868748                endif;
    869749        }
    870750
  • bp-xprofile/bp-xprofile-classes.php

    diff --git a/bp-xprofile/bp-xprofile-classes.php b/bp-xprofile/bp-xprofile-classes.php
    index 18e7724..4deff29 100644
    a b class BP_XProfile_Field {  
    541541        public $default_visibility = 'public';
    542542        public $allow_custom_visibility = 'allowed';
    543543
     544        /**
     545         * @since BuddyPress (2.0.0)
     546         * @var BP_XProfile_Field_Type Field type object used for validation
     547         */
     548        public $type_obj = null;
     549
    544550        public $data;
    545551        public $message = null;
    546552        public $message_type = 'err';
    547553
    548554        public function __construct( $id = null, $user_id = null, $get_data = true ) {
    549                 if ( !empty( $id ) )
     555                if ( !empty( $id ) ) {
    550556                        $this->populate( $id, $user_id, $get_data );
     557
     558                // Initialise the type obj to prevent fatals when creating new profile fields
     559                } else {
     560                        $this->type_obj            = bp_xprofile_create_field_type( 'textbox' );
     561                        $this->type_obj->field_obj = $this;
     562                }
    551563        }
    552564
    553565        public function populate( $id, $user_id, $get_data ) {
    … … class BP_XProfile_Field {  
    573585                        $this->order_by          = $field->order_by;
    574586                        $this->is_default_option = $field->is_default_option;
    575587
     588                        // Create the field type and store a reference back to this object.
     589                        $this->type_obj            = bp_xprofile_create_field_type( $field->type );
     590                        $this->type_obj->field_obj = $this;
     591
    576592                        if ( $get_data && $user_id ) {
    577593                                $this->data          = $this->get_field_data( $user_id );
    578594                        }
    … … class BP_XProfile_Field {  
    618634                $this->order_by    = apply_filters( 'xprofile_field_order_by_before_save',    $this->order_by,    $this->id );
    619635                $this->field_order = apply_filters( 'xprofile_field_field_order_before_save', $this->field_order, $this->id );
    620636                $this->can_delete  = apply_filters( 'xprofile_field_can_delete_before_save',  $this->can_delete,  $this->id );
     637                $this->type_obj    = bp_xprofile_create_field_type( $this->type );
    621638
    622639                do_action_ref_array( 'xprofile_field_before_save', array( $this ) );
    623640
    … … class BP_XProfile_Field {  
    655672                         * Check to see if this is a field with child options.
    656673                         * We need to add the options to the db, if it is.
    657674                         */
    658                         if ( 'radio' == $this->type || 'selectbox' == $this->type || 'checkbox' == $this->type || 'multiselectbox' == $this->type ) {
     675                        if ( $this->type_obj->supports_options ) {
    659676
    660677                                if ( !empty( $this->id ) ) {
    661678                                        $parent_id = $this->id;
    … … class BP_XProfile_Field {  
    663680                                        $parent_id = $wpdb->insert_id;
    664681                                }
    665682
    666                                 if ( 'radio' == $this->type ) {
    667                                         $post_option  = !empty( $_POST['radio_option']           ) ? $_POST['radio_option']           : '';
    668                                         $post_default = !empty( $_POST['isDefault_radio_option'] ) ? $_POST['isDefault_radio_option'] : '';
    669 
    670                                         $options        = apply_filters( 'xprofile_field_options_before_save', $post_option,  'radio' );
    671                                         $defaults       = apply_filters( 'xprofile_field_default_before_save', $post_default, 'radio' );
    672 
    673                                 } elseif ( 'selectbox' == $this->type ) {
    674                                         $post_option  = !empty( $_POST['selectbox_option']           ) ? $_POST['selectbox_option']           : '';
    675                                         $post_default = !empty( $_POST['isDefault_selectbox_option'] ) ? $_POST['isDefault_selectbox_option'] : '';
    676 
    677                                         $options        = apply_filters( 'xprofile_field_options_before_save', $post_option, 'selectbox' );
    678                                         $defaults       = apply_filters( 'xprofile_field_default_before_save', $post_default, 'selectbox' );
    679 
    680                                 } elseif ( 'multiselectbox' == $this->type ) {
    681                                         $post_option  = !empty( $_POST['multiselectbox_option']           ) ? $_POST['multiselectbox_option']           : '';
    682                                         $post_default = !empty( $_POST['isDefault_multiselectbox_option'] ) ? $_POST['isDefault_multiselectbox_option'] : '';
    683 
    684                                         $options        = apply_filters( 'xprofile_field_options_before_save', $post_option, 'multiselectbox' );
    685                                         $defaults       = apply_filters( 'xprofile_field_default_before_save', $post_default, 'multiselectbox' );
    686 
    687                                 } elseif ( 'checkbox' == $this->type ) {
    688                                         $post_option  = !empty( $_POST['checkbox_option']           ) ? $_POST['checkbox_option']           : '';
    689                                         $post_default = !empty( $_POST['isDefault_checkbox_option'] ) ? $_POST['isDefault_checkbox_option'] : '';
    690 
    691                                         $options        = apply_filters( 'xprofile_field_options_before_save', $post_option, 'checkbox' );
    692                                         $defaults       = apply_filters( 'xprofile_field_default_before_save', $post_default, 'checkbox' );
    693                                 }
     683                                // Allow plugins to filter the field's child options (i.e. the items in a selectbox).
     684                                $post_option  = ! empty( $_POST["{$this->type}_option"] ) ? $_POST["{$this->type}_option"] : '';
     685                                $post_default = ! empty( $_POST["isDefault_{$this->type}_option"] ) ? $_POST["isDefault_{$this->type}_option"] : '';
     686                                $options      = apply_filters( 'xprofile_field_options_before_save', $post_option,  $this->type );
     687                                $defaults     = apply_filters( 'xprofile_field_default_before_save', $post_default, $this->type );
    694688
    695689                                $counter = 1;
    696690                                if ( !empty( $options ) ) {
    … … class BP_XProfile_Field {  
    718712
    719713                        do_action_ref_array( 'xprofile_field_after_save', array( $this ) );
    720714
     715                        // Recreate type_obj in case someone changed $this->type via a filter
     716                        $this->type_obj            = bp_xprofile_create_field_type( $this->type );
     717                        $this->type_obj->field_obj = $this;
     718
    721719                        return $field_id;
    722720                } else {
    723721                        return false;
    … … class BP_XProfile_Field {  
    824822                return false;
    825823        }
    826824
    827         /* ADMIN AREA HTML.
    828         * TODO: Get this out of here and replace with standard template loops
    829         */
    830 
    831         /* This function populates the items for radio buttons checkboxes and drop down boxes */
     825        /**
     826         * This function populates the items for radio buttons checkboxes and drop down boxes
     827         */
    832828        public function render_admin_form_children() {
    833                 $input_types = array( 'checkbox', 'selectbox', 'multiselectbox', 'radio' );
    834 
    835                 foreach ( $input_types as $type ) {
    836                         $default_name = '';
    837 
    838                         if ( ( 'multiselectbox' == $type ) || ( 'checkbox' == $type ) ) {
    839                                 $default_input = 'checkbox';
    840                         } else {
    841                                 $default_input = 'radio';
    842                         }
    843 
    844                         $class = $this->type != $type ? 'display: none;' : '';
    845 
    846                         if ( empty( $this->default_visibility ) ) {
    847                                 $this->default_visibility = 'public';
    848                         }
    849 
    850                         ?>
    851 
    852                         <div id="<?php echo esc_attr( $type ); ?>" class="postbox bp-options-box" style="<?php echo esc_attr( $class ); ?> margin-top: 15px;">
    853                                 <h3><?php _e( 'Please enter options for this Field:', 'buddypress' ); ?></h3>
    854                                 <div class="inside">
    855                                         <p>
    856                                                 <label for="sort_order_<?php echo esc_attr( $type ); ?>"><?php _e( 'Sort Order:', 'buddypress' ); ?></label>
    857                                                 <select name="sort_order_<?php echo esc_attr( $type ); ?>" id="sort_order_<?php echo esc_attr( $type ); ?>" >
    858                                                         <option value="custom" <?php selected( 'custom', $this->order_by ); ?>><?php _e( 'Custom',     'buddypress' ); ?></option>
    859                                                         <option value="asc"    <?php selected( 'asc',    $this->order_by ); ?>><?php _e( 'Ascending',  'buddypress' ); ?></option>
    860                                                         <option value="desc"   <?php selected( 'desc',   $this->order_by ); ?>><?php _e( 'Descending', 'buddypress' ); ?></option>
    861                                                 </select>
    862                                         </p>
    863 
    864                                         <?php if ( !$options = $this->get_children( true ) ) {
    865 
    866                                                 $i = 1;
    867                                                 while ( isset( $_POST[$type . '_option'][$i] ) ) {
    868                                                         (array) $options[] = (object) array(
    869                                                                 'id'                => -1,
    870                                                                 'name'              => $_POST[$type . '_option'][$i],
    871                                                                 'is_default_option' => ( ( 'multiselectbox' != $type ) && ( 'checkbox' != $type ) && ( $_POST["isDefault_{$type}_option"] == $i ) ) ? 1 : $_POST["isDefault_{$type}_option"][$i]
    872                                                         );
    873 
    874                                                         ++$i;
    875                                                 }
    876                                         }
    877 
    878                                         if ( !empty( $options ) ) {
    879                                                 for ( $i = 0, $count = count( $options ); $i < $count; ++$i ) {
    880                                                         $j = $i + 1;
    881 
    882                                                         if ( 'multiselectbox' == $type || 'checkbox' == $type )
    883                                                                 $default_name = '[' . $j . ']'; ?>
    884 
    885                                                         <p class="sortable">
    886                                                                 <span>&nbsp;&Xi;&nbsp;</span>
    887                                                                 <input type="text" name="<?php echo esc_attr( $type ); ?>_option[<?php echo esc_attr( $j ); ?>]" id="<?php echo esc_attr( $type ); ?>_option<?php echo esc_attr( $j ); ?>" value="<?php echo stripslashes( esc_attr( $options[$i]->name ) ); ?>" />
    888                                                                 <input type="<?php echo $default_input; ?>" name="isDefault_<?php echo esc_attr( $type ); ?>_option<?php echo esc_attr( $default_name ); ?>" <?php checked( (int) $options[$i]->is_default_option, true ); ?> value="<?php echo esc_attr( $j ); ?>" />
    889                                                                 <span><?php _e( 'Default Value', 'buddypress' ); ?></span>
    890                                                                 <a href="<?php echo esc_url( 'users.php?page=bp-profile-setup&amp;mode=delete_option&amp;option_id=' . $options[$i]->id ); ?>" class="ajax-option-delete" id="delete-<?php echo esc_attr( $options[$i]->id ); ?>">[x]</a>
    891                                                         </p>
    892 
    893                                                 <?php } /* end for */ ?>
    894 
    895                                                 <input type="hidden" name="<?php echo esc_attr( $type ); ?>_option_number" id="<?php echo esc_attr( $type ); ?>_option_number" value="<?php echo esc_attr( (int) $j + 1 ); ?>" />
    896 
    897                                         <?php } else {
    898 
    899                                                 if ( 'multiselectbox' == $type || 'checkbox' == $type )
    900                                                         $default_name = '[1]'; ?>
    901 
    902                                                 <p class="sortable">
    903                                                         <span>&nbsp;&Xi;&nbsp;</span>
    904                                                         <input type="text" name="<?php echo esc_attr( $type ); ?>_option[1]" id="<?php echo esc_attr( $type ); ?>_option1" />
    905                                                         <input type="<?php echo esc_attr( $default_input ); ?>" name="isDefault_<?php echo esc_attr( $type ); ?>_option<?php echo esc_attr( $default_name ); ?>" id="isDefault_<?php echo esc_attr( $type ); ?>_option" value="1" />
    906                                                         <span><?php _e( 'Default Value', 'buddypress' ); ?></span>
    907                                                         <input type="hidden" name="<?php echo esc_attr( $type ); ?>_option_number" id="<?php echo esc_attr( $type ); ?>_option_number" value="2" />
    908                                                 </p>
    909 
    910                                         <?php } /* end if */ ?>
    911 
    912                                         <div id="<?php echo esc_attr( $type ); ?>_more"></div>
    913                                         <p><a href="javascript:add_option('<?php echo esc_attr( $type ); ?>')"><?php _e( 'Add Another Option', 'buddypress' ); ?></a></p>
    914                                 </div>
    915                         </div>
    916 
    917                 <?php }
     829                foreach ( array_keys( bp_xprofile_get_field_types() ) as $field_type ) {
     830                        $type_obj = bp_xprofile_create_field_type( $field_type );
     831                        $type_obj->admin_new_field_html( $this );
     832                }
    918833        }
    919834
    920835        public function render_admin_form( $message = '' ) {
    … … class BP_XProfile_Field {  
    1041956                                                                        <h3><label for="fieldtype"><?php _e( 'Field Type', 'buddypress'); ?></label></h3>
    1042957                                                                        <div class="inside">
    1043958                                                                                <select name="fieldtype" id="fieldtype" onchange="show_options(this.value)" style="width: 30%">
    1044                                                                                         <optgroup label="<?php esc_attr_e( 'Single Fields', 'buddypress' ); ?>">
    1045                                                                                                 <option value="textbox"        <?php selected( $this->type, 'textbox'        ); ?>><?php _e( 'Text Box',             'buddypress' ); ?></option>
    1046                                                                                                 <option value="textarea"       <?php selected( $this->type, 'textarea'       ); ?>><?php _e( 'Multi-line Text Area', 'buddypress' ); ?></option>
    1047                                                                                                 <option value="datebox"        <?php selected( $this->type, 'datebox'        ); ?>><?php _e( 'Date Selector',        'buddypress' ); ?></option>
    1048                                                                                         </optgroup>
    1049                                                                                         <optgroup label="<?php esc_attr_e( 'Multi Fields', 'buddypress' ); ?>">
    1050                                                                                                 <option value="radio"          <?php selected( $this->type, 'radio'          ); ?>><?php _e( 'Radio Buttons',        'buddypress' ); ?></option>
    1051                                                                                                 <option value="selectbox"      <?php selected( $this->type, 'selectbox'      ); ?>><?php _e( 'Drop Down Select Box', 'buddypress' ); ?></option>
    1052                                                                                                 <option value="multiselectbox" <?php selected( $this->type, 'multiselectbox' ); ?>><?php _e( 'Multi Select Box',     'buddypress' ); ?></option>
    1053                                                                                                 <option value="checkbox"       <?php selected( $this->type, 'checkbox'       ); ?>><?php _e( 'Checkboxes',           'buddypress' ); ?></option>
    1054                                                                                         </optgroup>
     959                                                                                        <?php bp_xprofile_admin_form_field_types( $this->type ); ?>
    1055960                                                                                </select>
    1056961
    1057                                                                                 <?php do_action_ref_array( 'xprofile_field_additional_options', array( $this ) ); ?>
    1058 
    1059                                                                                 <?php $this->render_admin_form_children(); ?>
     962                                                                                <?php
     963                                                                                // Deprecated filter, don't use. Go look at {@link BP_XProfile_Field_Type::admin_new_field_html()}.
     964                                                                                do_action( 'xprofile_field_additional_options', $this );
    1060965
     966                                                                                $this->render_admin_form_children();
     967                                                                                ?>
    1061968                                                                        </div>
    1062969                                                                </div>
    1063970
    … … class BP_XProfile_Field {  
    1086993                if ( '' == $_POST['title'] || '' == $_POST['required'] || '' == $_POST['fieldtype'] ) {
    1087994                        $message = __( 'Please make sure you fill out all required fields.', 'buddypress' );
    1088995                        return false;
    1089                 } else if ( empty( $_POST['field_file'] ) && $_POST['fieldtype'] == 'radio' && empty( $_POST['radio_option'][1] ) ) {
    1090                         $message = __( 'Radio button field types require at least one option. Please add options below.', 'buddypress' );
    1091                         return false;
    1092                 } else if ( empty( $_POST['field_file'] ) && $_POST['fieldtype'] == 'selectbox' && empty( $_POST['selectbox_option'][1] ) ) {
    1093                         $message = __( 'Select box field types require at least one option. Please add options below.', 'buddypress' );
    1094                         return false;
    1095                 } else if ( empty( $_POST['field_file'] ) && $_POST['fieldtype'] == 'multiselectbox' && empty( $_POST['multiselectbox_option'][1] ) ) {
    1096                         $message = __( 'Select box field types require at least one option. Please add options below.', 'buddypress' );
    1097                         return false;
    1098                 } else if ( empty( $_POST['field_file'] ) && $_POST['fieldtype'] == 'checkbox' && empty( $_POST['checkbox_option'][1] ) ) {
    1099                         $message = __( 'Checkbox field types require at least one option. Please add options below.', 'buddypress' );
    1100                         return false;
    1101                 } else {
    1102                         return true;
     996
     997                } elseif ( empty( $_POST['field_file'] ) ) {
     998                        $field_type  = bp_xprofile_create_field_type( $_POST['fieldtype'] );
     999                        $option_name = "{$_POST['fieldtype']}_option";
     1000
     1001                        if ( $field_type->supports_options && isset( $_POST[$option_name] ) && empty( $_POST[$option_name][1] ) ) {
     1002                                $message = __( 'This field type require at least one option. Please add options below.', 'buddypress' );
     1003                                return false;
     1004                        }
    11031005                }
     1006
     1007                return true;
    11041008        }
    11051009}
    11061010
    1107 
    11081011class BP_XProfile_ProfileData {
    11091012        public $id;
    11101013        public $user_id;
    … … class BP_XProfile_ProfileData {  
    15401443                return $data[$field_name];
    15411444        }
    15421445}
     1446
     1447/**
     1448 * Datebox xprofile field type.
     1449 *
     1450 * @since BuddyPress (2.0.0)
     1451 */
     1452class BP_XProfile_Field_Type_Datebox extends BP_XProfile_Field_Type {
     1453
     1454        /**
     1455         * Constructor for the datebox field type
     1456         *
     1457         * @since BuddyPress (2.0.0)
     1458         */
     1459        public function __construct() {
     1460                parent::__construct();
     1461
     1462                $this->category = _x( 'Single Fields', 'xprofile field type category', 'buddypress' );
     1463                $this->name     = _x( 'Date Selector', 'xprofile field type', 'buddypress' );
     1464
     1465                $this->set_format( '/^\d{4}-\d{1,2}-\d{1,2} 00:00:00$/', 'replace' );  // "Y-m-d 00:00:00"
     1466                do_action( 'bp_xprofile_field_type_datebox', $this );
     1467        }
     1468
     1469        /**
     1470         * Output the edit field HTML for this field type.
     1471         *
     1472         * Must be used inside the {@link bp_profile_fields()} template loop.
     1473         *
     1474         * @param array $raw_properties Optional key/value array of {@link http://dev.w3.org/html5/markup/input.html permitted attributes} that you want to add.
     1475         * @since BuddyPress (2.0.0)
     1476         */
     1477        public function edit_field_html( array $raw_properties = array() ) {
     1478                $user_id = bp_displayed_user_id();
     1479
     1480                // user_id is a special optional parameter that we pass to {@link bp_the_profile_field_options()}.
     1481                if ( isset( $raw_properties['user_id'] ) ) {
     1482                        $user_id = (int) $raw_properties['user_id'];
     1483                        unset( $raw_properties['user_id'] );
     1484                }
     1485
     1486                $day_html = $this->get_edit_field_html_elements( array_merge(
     1487                        array(
     1488                                'id'   => bp_get_the_profile_field_input_name() . '_day',
     1489                                'name' => bp_get_the_profile_field_input_name() . '_day',
     1490                        ),
     1491                        $raw_properties
     1492                ) );
     1493
     1494                $month_html = $this->get_edit_field_html_elements( array_merge(
     1495                        array(
     1496                                'id'   => bp_get_the_profile_field_input_name() . '_month',
     1497                                'name' => bp_get_the_profile_field_input_name() . '_month',
     1498                        ),
     1499                        $raw_properties
     1500                ) );
     1501
     1502                $year_html = $this->get_edit_field_html_elements( array_merge(
     1503                        array(
     1504                                'id'   => bp_get_the_profile_field_input_name() . '_year',
     1505                                'name' => bp_get_the_profile_field_input_name() . '_year',
     1506                        ),
     1507                        $raw_properties
     1508                ) );
     1509        ?>
     1510                <div class="datebox">
     1511
     1512                        <label for="<?php bp_the_profile_field_input_name(); ?>_day"><?php bp_the_profile_field_name(); ?> <?php if ( bp_get_the_profile_field_is_required() ) : ?><?php esc_html_e( '(required)', 'buddypress' ); ?><?php endif; ?></label>
     1513
     1514                        <select <?php echo $day_html; ?>>
     1515                                <?php bp_the_profile_field_options( array( 'type' => 'day', 'user_id' => $user_id ) ); ?>
     1516                        </select>
     1517
     1518                        <select <?php echo $month_html; ?>>
     1519                                <?php bp_the_profile_field_options( array( 'type' => 'month', 'user_id' => $user_id ) ); ?>
     1520                        </select>
     1521
     1522                        <select <?php echo $year_html; ?>>
     1523                                <?php bp_the_profile_field_options( array( 'type' => 'year', 'user_id' => $user_id ) ); ?>
     1524                        </select>
     1525
     1526                </div>
     1527        <?php
     1528        }
     1529
     1530        /**
     1531         * Output the edit field options HTML for this field type.
     1532         *
     1533         * BuddyPress considers a field's "options" to be, for example, the items in a selectbox.
     1534         * These are stored separately in the database, and their templating is handled seperately.
     1535         *
     1536         * This templating is separate from {@link BP_XProfile_Field_Type::edit_field_html()} because
     1537         * it's also used in the wp-admin screens when creating new fields, and for backwards compatibility.
     1538         *
     1539         * Must be used inside the {@link bp_profile_fields()} template loop.
     1540         *
     1541         * @param array $args Optional. The arguments passed to {@link bp_the_profile_field_options()}.
     1542         * @since BuddyPress (2.0.0)
     1543         */
     1544        public function edit_field_options_html( array $args = array() ) {
     1545                $options = $this->field_obj->get_children();
     1546                $date    = BP_XProfile_ProfileData::get_value_byid( $this->field_obj->id, $args['user_id'] );
     1547
     1548                $day   = 0;
     1549                $month = 0;
     1550                $year  = 0;
     1551                $html  = '';
     1552
     1553                // Set day, month, year defaults
     1554                if ( ! empty( $date ) ) {
     1555
     1556                        // If Unix timestamp
     1557                        if ( is_numeric( $date ) ) {
     1558                                $day   = date( 'j', $date );
     1559                                $month = date( 'F', $date );
     1560                                $year  = date( 'Y', $date );
     1561
     1562                        // If MySQL timestamp
     1563                        } else {
     1564                                $day   = mysql2date( 'j', $date );
     1565                                $month = mysql2date( 'F', $date, false ); // Not localized, so that selected() works below
     1566                                $year  = mysql2date( 'Y', $date );
     1567                        }
     1568                }
     1569
     1570                // Check for updated posted values, and errors preventing them from being saved first time.
     1571                if ( ! empty( $_POST['field_' . $this->field_obj->id . '_day'] ) ) {
     1572                        $new_day = (int) $_POST['field_' . $this->field_obj->id . '_day'];
     1573                        $day     = ( $day != $new_day ) ? $new_day : $day;
     1574                }
     1575
     1576                if ( ! empty( $_POST['field_' . $this->field_obj->id . '_month'] ) ) {
     1577                        $new_month = (int) $_POST['field_' . $this->field_obj->id . '_month'];
     1578                        $month     = ( $month != $new_month ) ? $new_month : $month;
     1579                }
     1580
     1581                if ( ! empty( $_POST['field_' . $this->field_obj->id . '_year'] ) ) {
     1582                        $new_year = date( 'j', (int) $_POST['field_' . $this->field_obj->id . '_year'] );
     1583                        $year     = ( $year != $new_year ) ? $new_year : $year;
     1584                }
     1585
     1586                // $type will be passed by calling function when needed
     1587                switch ( $args['type'] ) {
     1588                        case 'day':
     1589                                $html = sprintf( '<option value="" %1$s>%2$s</option>', selected( $day, 0, false ), /* translators: no option picked in select box */ __( '----', 'buddypress' ) );
     1590
     1591                                for ( $i = 1; $i < 32; ++$i ) {
     1592                                        $html .= sprintf( '<option value="%1$s" %2$s>%3$s</option>', (int) $i, selected( $day, $i, false ), (int) $i );
     1593                                }
     1594                        break;
     1595
     1596                        case 'month':
     1597                                $eng_months = array( 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December' );
     1598
     1599                                $months = array(
     1600                                        __( 'January', 'buddypress' ),
     1601                                        __( 'February', 'buddypress' ),
     1602                                        __( 'March', 'buddypress' ),
     1603                                        __( 'April', 'buddypress' ),
     1604                                        __( 'May', 'buddypress' ),
     1605                                        __( 'June', 'buddypress' ),
     1606                                        __( 'July', 'buddypress' ),
     1607                                        __( 'August', 'buddypress' ),
     1608                                        __( 'September', 'buddypress' ),
     1609                                        __( 'October', 'buddypress' ),
     1610                                        __( 'November', 'buddypress' ),
     1611                                        __( 'December', 'buddypress' )
     1612                                );
     1613
     1614                                $html = sprintf( '<option value="" %1$s>%2$s</option>', selected( $month, 0, false ), /* translators: no option picked in select box */ __( '----', 'buddypress' ) );
     1615
     1616                                for ( $i = 0; $i < 12; ++$i ) {
     1617                                        $html .= sprintf( '<option value="%1$s" %2$s>%3$s</option>', esc_attr( $eng_months[$i] ), selected( $month, $eng_months[$i], false ), $months[$i] );
     1618                                }
     1619                        break;
     1620
     1621                        case 'year':
     1622                                $html = sprintf( '<option value="" %1$s>%2$s</option>', selected( $year, 0, false ), /* translators: no option picked in select box */ __( '----', 'buddypress' ) );
     1623
     1624                                for ( $i = 2037; $i > 1901; $i-- ) {
     1625                                        $html .= sprintf( '<option value="%1$s" %2$s>%3$s</option>', (int) $i, selected( $year, $i, false ), (int) $i );
     1626                                }
     1627                        break;
     1628                }
     1629
     1630                echo apply_filters( 'bp_get_the_profile_field_datebox', $html, $args['type'], $day, $month, $year, $this->field_obj->id, $date );
     1631        }
     1632
     1633        /**
     1634         * Output HTML for this field type on the wp-admin Profile Fields screen.
     1635         *
     1636         * Must be used inside the {@link bp_profile_fields()} template loop.
     1637         *
     1638         * @param array $raw_properties Optional key/value array of permitted attributes that you want to add.
     1639         * @since BuddyPress (2.0.0)
     1640         */
     1641        public function admin_field_html( array $raw_properties = array() ) {
     1642                $day_html = $this->get_edit_field_html_elements( array_merge(
     1643                        array(
     1644                                'id'   => bp_get_the_profile_field_input_name() . '_day',
     1645                                'name' => bp_get_the_profile_field_input_name() . '_day',
     1646                        ),
     1647                        $raw_properties
     1648                ) );
     1649
     1650                $month_html = $this->get_edit_field_html_elements( array_merge(
     1651                        array(
     1652                                'id'   => bp_get_the_profile_field_input_name() . '_month',
     1653                                'name' => bp_get_the_profile_field_input_name() . '_month',
     1654                        ),
     1655                        $raw_properties
     1656                ) );
     1657
     1658                $year_html = $this->get_edit_field_html_elements( array_merge(
     1659                        array(
     1660                                'id'   => bp_get_the_profile_field_input_name() . '_year',
     1661                                'name' => bp_get_the_profile_field_input_name() . '_year',
     1662                        ),
     1663                        $raw_properties
     1664                ) );
     1665        ?>
     1666                <select <?php echo $day_html; ?>>
     1667                        <?php bp_the_profile_field_options( 'type=day' ); ?>
     1668                </select>
     1669
     1670                <select <?php echo $month_html; ?>>
     1671                        <?php bp_the_profile_field_options( 'type=month' ); ?>
     1672                </select>
     1673
     1674                <select <?php echo $year_html; ?>>
     1675                        <?php bp_the_profile_field_options( 'type=year' ); ?>
     1676                </select>
     1677        <?php
     1678        }
     1679
     1680        /**
     1681         * This method usually outputs HTML for this field type's children options on the wp-admin Profile Fields
     1682         * "Add Field" and "Edit Field" screens, but for this field type, we don't want it, so it's stubbed out.
     1683         *
     1684         * @param BP_XProfile_Field $current_field The current profile field on the add/edit screen.
     1685         * @param string $control_type Optional. HTML input type used to render the current field's child options.
     1686         * @since BuddyPress (2.0.0)
     1687         */
     1688        public function admin_new_field_html( BP_XProfile_Field $current_field, $control_type = '' ) {}
     1689}
     1690
     1691/**
     1692 * Checkbox xprofile field type.
     1693 *
     1694 * @since BuddyPress (2.0.0)
     1695 */
     1696class BP_XProfile_Field_Type_Checkbox extends BP_XProfile_Field_Type {
     1697
     1698        /**
     1699         * Constructor for the checkbox field type
     1700         *
     1701         * @since BuddyPress (2.0.0)
     1702         */
     1703        public function __construct() {
     1704                parent::__construct();
     1705
     1706                $this->category = _x( 'Multi Fields', 'xprofile field type category', 'buddypress' );
     1707                $this->name     = _x( 'Checkboxes', 'xprofile field type', 'buddypress' );
     1708
     1709                $this->supports_multiple_defaults = true;
     1710                $this->accepts_null_value         = true;
     1711                $this->supports_options           = true;
     1712
     1713                $this->set_format( '/^.+$/', 'replace' );
     1714                do_action( 'bp_xprofile_field_type_checkbox', $this );
     1715        }
     1716
     1717        /**
     1718         * Output the edit field HTML for this field type.
     1719         *
     1720         * Must be used inside the {@link bp_profile_fields()} template loop.
     1721         *
     1722         * @param array $raw_properties Optional key/value array of {@link http://dev.w3.org/html5/markup/input.checkbox.html permitted attributes} that you want to add.
     1723         * @since BuddyPress (2.0.0)
     1724         */
     1725        public function edit_field_html( array $raw_properties = array() ) {
     1726                $user_id = bp_displayed_user_id();
     1727
     1728                // user_id is a special optional parameter that we pass to {@link bp_the_profile_field_options()}.
     1729                if ( isset( $raw_properties['user_id'] ) ) {
     1730                        $user_id = (int) $raw_properties['user_id'];
     1731                        unset( $raw_properties['user_id'] );
     1732                }
     1733        ?>
     1734                <div class="checkbox">
     1735
     1736                        <label for="<?php bp_the_profile_field_input_name(); ?>"><?php bp_the_profile_field_name(); ?> <?php if ( bp_get_the_profile_field_is_required() ) : ?><?php esc_html_e( '(required)', 'buddypress' ); ?><?php endif; ?></label>
     1737                        <?php bp_the_profile_field_options( "user_id={$user_id}" ); ?>
     1738
     1739                </div>
     1740                <?php
     1741        }
     1742
     1743        /**
     1744         * Output the edit field options HTML for this field type.
     1745         *
     1746         * BuddyPress considers a field's "options" to be, for example, the items in a selectbox.
     1747         * These are stored separately in the database, and their templating is handled seperately.
     1748         *
     1749         * This templating is separate from {@link BP_XProfile_Field_Type::edit_field_html()} because
     1750         * it's also used in the wp-admin screens when creating new fields, and for backwards compatibility.
     1751         *
     1752         * Must be used inside the {@link bp_profile_fields()} template loop.
     1753         *
     1754         * @param array $args Optional. The arguments passed to {@link bp_the_profile_field_options()}.
     1755         * @since BuddyPress (2.0.0)
     1756         */
     1757        public function edit_field_options_html( array $args = array() ) {
     1758                $options       = $this->field_obj->get_children();
     1759                $option_values = BP_XProfile_ProfileData::get_value_byid( $this->field_obj->id, $args['user_id'] );
     1760                $option_values = (array) maybe_unserialize( $option_values );
     1761
     1762                $html = '';
     1763
     1764                // Check for updated posted values, but errors preventing them from being saved first time
     1765                if ( isset( $_POST['field_' . $this->field_obj->id] ) && $option_values != maybe_serialize( $_POST['field_' . $this->field_obj->id] ) ) {
     1766                        if ( ! empty( $_POST['field_' . $this->field_obj->id] ) ) {
     1767                                $option_values = array_map( 'sanitize_text_field', $_POST['field_' . $this->field_obj->id] );
     1768                        }
     1769                }
     1770
     1771                for ( $k = 0, $count = count( $options ); $k < $count; ++$k ) {
     1772                        $selected = '';
     1773
     1774                        // First, check to see whether the user's saved values match the option
     1775                        for ( $j = 0, $count_values = count( $option_values ); $j < $count_values; ++$j ) {
     1776
     1777                                // Run the allowed option name through the before_save filter, so we'll be sure to get a match
     1778                                $allowed_options = xprofile_sanitize_data_value_before_save( $options[$k]->name, false, false );
     1779
     1780                                if ( $option_values[$j] === $allowed_options || in_array( $allowed_options, $option_values ) ) {
     1781                                        $selected = ' checked="checked"';
     1782                                        break;
     1783                                }
     1784                        }
     1785
     1786                        // If the user has not yet supplied a value for this field, check to see whether there is a default value available
     1787                        if ( ! is_array( $option_values ) && empty( $option_values ) && empty( $selected ) && ! empty( $options[$k]->is_default_option ) ) {
     1788                                $selected = ' checked="checked"';
     1789                        }
     1790
     1791                        $new_html = sprintf( '<label><input %1$s type="checkbox" name="%2$s" id="%3$s" value="%4$s">%5$s</label>',
     1792                                $selected,
     1793                                esc_attr( "field_{$this->field_obj->id}[]" ),
     1794                                esc_attr( "field_{$options[$k]->id}_{$k}" ),
     1795                                esc_attr( stripslashes( $options[$k]->name ) ),
     1796                                esc_html( stripslashes( $options[$k]->name ) )
     1797                        );
     1798                        $html .= apply_filters( 'bp_get_the_profile_field_options_checkbox', $new_html, $options[$k], $this->field_obj->id, $selected, $k );
     1799                }
     1800
     1801                echo $html;
     1802        }
     1803
     1804        /**
     1805         * Output HTML for this field type on the wp-admin Profile Fields screen.
     1806         *
     1807         * Must be used inside the {@link bp_profile_fields()} template loop.
     1808         *
     1809         * @param array $raw_properties Optional key/value array of permitted attributes that you want to add.
     1810         * @since BuddyPress (2.0.0)
     1811         */
     1812        public function admin_field_html( array $raw_properties = array() ) {
     1813                bp_the_profile_field_options();
     1814        }
     1815
     1816        /**
     1817         * Output HTML for this field type's children options on the wp-admin Profile Fields "Add Field" and "Edit Field" screens.
     1818         *
     1819         * Must be used inside the {@link bp_profile_fields()} template loop.
     1820         *
     1821         * @param BP_XProfile_Field $current_field The current profile field on the add/edit screen.
     1822         * @param string $control_type Optional. HTML input type used to render the current field's child options.
     1823         * @since BuddyPress (2.0.0)
     1824         */
     1825        public function admin_new_field_html( BP_XProfile_Field $current_field, $control_type = '' ) {
     1826                parent::admin_new_field_html( $current_field, 'checkbox' );
     1827        }
     1828}
     1829
     1830/**
     1831 * Radio button xprofile field type.
     1832 *
     1833 * @since BuddyPress (2.0.0)
     1834 */
     1835class BP_XProfile_Field_Type_Radiobutton extends BP_XProfile_Field_Type {
     1836
     1837        /**
     1838         * Constructor for the radio button field type
     1839         *
     1840         * @since BuddyPress (2.0.0)
     1841         */
     1842        public function __construct() {
     1843                parent::__construct();
     1844
     1845                $this->category = _x( 'Multi Fields', 'xprofile field type category', 'buddypress' );
     1846                $this->name     = _x( 'Radio Buttons', 'xprofile field type', 'buddypress' );
     1847
     1848                $this->supports_options = true;
     1849
     1850                $this->set_format( '/^.+$/', 'replace' );
     1851                do_action( 'bp_xprofile_field_type_radiobutton', $this );
     1852        }
     1853
     1854        /**
     1855         * Output the edit field HTML for this field type.
     1856         *
     1857         * Must be used inside the {@link bp_profile_fields()} template loop.
     1858         *
     1859         * @param array $raw_properties Optional key/value array of {@link http://dev.w3.org/html5/markup/input.radio.html permitted attributes} that you want to add.
     1860         * @since BuddyPress (2.0.0)
     1861         */
     1862        public function edit_field_html( array $raw_properties = array() ) {
     1863                $user_id = bp_displayed_user_id();
     1864
     1865                // user_id is a special optional parameter that we pass to {@link bp_the_profile_field_options()}.
     1866                if ( isset( $raw_properties['user_id'] ) ) {
     1867                        $user_id = (int) $raw_properties['user_id'];
     1868                        unset( $raw_properties['user_id'] );
     1869                }
     1870        ?>
     1871                <div class="radio">
     1872
     1873                        <label for="<?php bp_the_profile_field_input_name(); ?>"><?php bp_the_profile_field_name(); ?> <?php if ( bp_get_the_profile_field_is_required() ) : ?><?php esc_html_e( '(required)', 'buddypress' ); ?><?php endif; ?></label>
     1874                        <?php bp_the_profile_field_options( "user_id={$user_id}" );
     1875
     1876                        if ( ! bp_get_the_profile_field_is_required() ) : ?>
     1877                                <a class="clear-value" href="javascript:clear( '<?php echo esc_js( bp_get_the_profile_field_input_name() ); ?>' );"><?php esc_html_e( 'Clear', 'buddypress' ); ?></a>
     1878                        <?php endif; ?>
     1879
     1880                </div>
     1881                <?php
     1882        }
     1883
     1884        /**
     1885         * Output the edit field options HTML for this field type.
     1886         *
     1887         * BuddyPress considers a field's "options" to be, for example, the items in a selectbox.
     1888         * These are stored separately in the database, and their templating is handled seperately.
     1889         *
     1890         * This templating is separate from {@link BP_XProfile_Field_Type::edit_field_html()} because
     1891         * it's also used in the wp-admin screens when creating new fields, and for backwards compatibility.
     1892         *
     1893         * Must be used inside the {@link bp_profile_fields()} template loop.
     1894         *
     1895         * @param array $args Optional. The arguments passed to {@link bp_the_profile_field_options()}.
     1896         * @since BuddyPress (2.0.0)
     1897         */
     1898        public function edit_field_options_html( array $args = array() ) {
     1899                $option_value = BP_XProfile_ProfileData::get_value_byid( $this->field_obj->id, $args['user_id'] );
     1900                $options      = $this->field_obj->get_children();
     1901
     1902                $html = sprintf( '<div id="%s">', esc_attr( 'field_' . $this->field_obj->id ) );
     1903
     1904                for ( $k = 0, $count = count( $options ); $k < $count; ++$k ) {
     1905
     1906                        // Check for updated posted values, but errors preventing them from being saved first time
     1907                        if ( isset( $_POST['field_' . $this->field_obj->id] ) && $option_value != $_POST['field_' . $this->field_obj->id] ) {
     1908                                if ( ! empty( $_POST['field_' . $this->field_obj->id] ) ) {
     1909                                        $option_value = sanitize_text_field( $_POST['field_' . $this->field_obj->id] );
     1910                                }
     1911                        }
     1912
     1913                        // Run the allowed option name through the before_save filter, so we'll be sure to get a match
     1914                        $allowed_options = xprofile_sanitize_data_value_before_save( $options[$k]->name, false, false );
     1915                        $selected        = '';
     1916
     1917                        if ( $option_value === $allowed_options || ( empty( $option_value ) && ! empty( $options[$k]->is_default_option ) ) ) {
     1918                                $selected = ' checked="checked"';
     1919                        }
     1920
     1921                        $new_html = sprintf( '<label><input %1$s type="radio" name="%2$s" id="%3$s" value="%4$s">%5$s</label>',
     1922                                $selected,
     1923                                esc_attr( "field_{$this->field_obj->id}" ),
     1924                                esc_attr( "option_{$options[$k]->id}" ),
     1925                                esc_attr( stripslashes( $options[$k]->name ) ),
     1926                                esc_html( stripslashes( $options[$k]->name ) )
     1927                        );
     1928                        $html .= apply_filters( 'bp_get_the_profile_field_options_radio', $new_html, $options[$k], $this->field_obj->id, $selected, $k );
     1929                }
     1930
     1931                echo $html . '</div>';
     1932        }
     1933
     1934        /**
     1935         * Output HTML for this field type on the wp-admin Profile Fields screen.
     1936         *
     1937         * Must be used inside the {@link bp_profile_fields()} template loop.
     1938         *
     1939         * @param array $raw_properties Optional key/value array of permitted attributes that you want to add.
     1940         * @since BuddyPress (2.0.0)
     1941         */
     1942        public function admin_field_html( array $raw_properties = array() ) {
     1943                bp_the_profile_field_options();
     1944
     1945                if ( ! bp_get_the_profile_field_is_required() ) : ?>
     1946                        <a class="clear-value" href="javascript:clear( '<?php echo esc_js( bp_get_the_profile_field_input_name() ); ?>' );"><?php esc_html_e( 'Clear', 'buddypress' ); ?></a>
     1947                <?php endif; ?>
     1948        <?php
     1949        }
     1950
     1951        /**
     1952         * Output HTML for this field type's children options on the wp-admin Profile Fields "Add Field" and "Edit Field" screens.
     1953         *
     1954         * Must be used inside the {@link bp_profile_fields()} template loop.
     1955         *
     1956         * @param BP_XProfile_Field $current_field The current profile field on the add/edit screen.
     1957         * @param string $control_type Optional. HTML input type used to render the current field's child options.
     1958         * @since BuddyPress (2.0.0)
     1959         */
     1960        public function admin_new_field_html( BP_XProfile_Field $current_field, $control_type = '' ) {
     1961                parent::admin_new_field_html( $current_field, 'radio' );
     1962        }
     1963}
     1964
     1965/**
     1966 * Multi-selectbox xprofile field type.
     1967 *
     1968 * @since BuddyPress (2.0.0)
     1969 */
     1970class BP_XProfile_Field_Type_Multiselectbox extends BP_XProfile_Field_Type {
     1971
     1972        /**
     1973         * Constructor for the multi-selectbox field type
     1974         *
     1975         * @since BuddyPress (2.0.0)
     1976         */
     1977        public function __construct() {
     1978                parent::__construct();
     1979
     1980                $this->category = _x( 'Multi Fields', 'xprofile field type category', 'buddypress' );
     1981                $this->name     = _x( 'Multi Select Box', 'xprofile field type', 'buddypress' );
     1982
     1983                $this->supports_multiple_defaults = true;
     1984                $this->accepts_null_value         = true;
     1985                $this->supports_options           = true;
     1986
     1987                $this->set_format( '/^.+$/', 'replace' );
     1988                do_action( 'bp_xprofile_field_type_multiselectbox', $this );
     1989        }
     1990
     1991        /**
     1992         * Output the edit field HTML for this field type.
     1993         *
     1994         * Must be used inside the {@link bp_profile_fields()} template loop.
     1995         *
     1996         * @param array $raw_properties Optional key/value array of {@link http://dev.w3.org/html5/markup/select.html permitted attributes} that you want to add.
     1997         * @since BuddyPress (2.0.0)
     1998         */
     1999        public function edit_field_html( array $raw_properties = array() ) {
     2000                $user_id = bp_displayed_user_id();
     2001
     2002                // user_id is a special optional parameter that we pass to {@link bp_the_profile_field_options()}.
     2003                if ( isset( $raw_properties['user_id'] ) ) {
     2004                        $user_id = (int) $raw_properties['user_id'];
     2005                        unset( $raw_properties['user_id'] );
     2006                }
     2007
     2008                $html = $this->get_edit_field_html_elements( array_merge(
     2009                        array(
     2010                                'multiple' => 'multiple',
     2011                                'id'       => bp_get_the_profile_field_input_name() . '[]',
     2012                                'name'     => bp_get_the_profile_field_input_name() . '[]',
     2013                        ),
     2014                        $raw_properties
     2015                ) );
     2016        ?>
     2017                <label for="<?php bp_the_profile_field_input_name(); ?>[]"><?php bp_the_profile_field_name(); ?> <?php if ( bp_get_the_profile_field_is_required() ) : ?><?php _e( '(required)', 'buddypress' ); ?><?php endif; ?></label>
     2018                <select <?php echo $html; ?>>
     2019                        <?php bp_the_profile_field_options( "user_id={$user_id}" ); ?>
     2020                </select>
     2021
     2022                <?php if ( ! bp_get_the_profile_field_is_required() ) : ?>
     2023                        <a class="clear-value" href="javascript:clear( '<?php echo esc_js( bp_get_the_profile_field_input_name() ); ?>[]' );"><?php esc_html_e( 'Clear', 'buddypress' ); ?></a>
     2024                <?php endif; ?>
     2025        <?php
     2026        }
     2027
     2028        /**
     2029         * Output the edit field options HTML for this field type.
     2030         *
     2031         * BuddyPress considers a field's "options" to be, for example, the items in a selectbox.
     2032         * These are stored separately in the database, and their templating is handled seperately.
     2033         *
     2034         * This templating is separate from {@link BP_XProfile_Field_Type::edit_field_html()} because
     2035         * it's also used in the wp-admin screens when creating new fields, and for backwards compatibility.
     2036         *
     2037         * Must be used inside the {@link bp_profile_fields()} template loop.
     2038         *
     2039         * @param array $args Optional. The arguments passed to {@link bp_the_profile_field_options()}.
     2040         * @since BuddyPress (2.0.0)
     2041         */
     2042        public function edit_field_options_html( array $args = array() ) {
     2043                $original_option_values = maybe_unserialize( BP_XProfile_ProfileData::get_value_byid( $this->field_obj->id, $args['user_id'] ) );
     2044
     2045                $options = $this->field_obj->get_children();
     2046                $html    = '';
     2047
     2048                if ( empty( $original_option_values ) && ! empty( $_POST['field_' . $this->field_obj->id] ) ) {
     2049                        $original_option_values = sanitize_text_field( $_POST['field_' . $this->field_obj->id] );
     2050                }
     2051
     2052                $option_values = (array) $original_option_values;
     2053                for ( $k = 0, $count = count( $options ); $k < $count; ++$k ) {
     2054                        $selected = '';
     2055
     2056                        // Check for updated posted values, but errors preventing them from being saved first time
     2057                        foreach( $option_values as $i => $option_value ) {
     2058                                if ( isset( $_POST['field_' . $this->field_obj->id] ) && $_POST['field_' . $this->field_obj->id][$i] != $option_value ) {
     2059                                        if ( ! empty( $_POST['field_' . $this->field_obj->id][$i] ) ) {
     2060                                                $option_values[] = sanitize_text_field( $_POST['field_' . $this->field_obj->id][$i] );
     2061                                        }
     2062                                }
     2063                        }
     2064
     2065                        // Run the allowed option name through the before_save filter, so we'll be sure to get a match
     2066                        $allowed_options = xprofile_sanitize_data_value_before_save( $options[$k]->name, false, false );
     2067
     2068                        // First, check to see whether the user-entered value matches
     2069                        if ( in_array( $allowed_options, $option_values ) ) {
     2070                                $selected = ' selected="selected"';
     2071                        }
     2072
     2073                        // Then, if the user has not provided a value, check for defaults
     2074                        if ( ! is_array( $original_option_values ) && empty( $option_values ) && ! empty( $options[$k]->is_default_option ) ) {
     2075                                $selected = ' selected="selected"';
     2076                        }
     2077
     2078                        $html .= apply_filters( 'bp_get_the_profile_field_options_multiselect', '<option' . $selected . ' value="' . esc_attr( stripslashes( $options[$k]->name ) ) . '">' . esc_html( stripslashes( $options[$k]->name ) ) . '</option>', $options[$k], $this->field_obj->id, $selected, $k );
     2079                }
     2080
     2081                echo $html;
     2082        }
     2083
     2084        /**
     2085         * Output HTML for this field type on the wp-admin Profile Fields screen.
     2086         *
     2087         * Must be used inside the {@link bp_profile_fields()} template loop.
     2088         *
     2089         * @param array $raw_properties Optional key/value array of permitted attributes that you want to add.
     2090         * @since BuddyPress (2.0.0)
     2091         */
     2092        public function admin_field_html( array $raw_properties = array() ) {
     2093                $html = $this->get_edit_field_html_elements( array_merge(
     2094                        array( 'multiple' => 'multiple' ),
     2095                        $raw_properties
     2096                ) );
     2097        ?>
     2098                <select <?php echo $html; ?>>
     2099                        <?php bp_the_profile_field_options(); ?>
     2100                </select>
     2101        <?php
     2102        }
     2103
     2104        /**
     2105         * Output HTML for this field type's children options on the wp-admin Profile Fields "Add Field" and "Edit Field" screens.
     2106         *
     2107         * Must be used inside the {@link bp_profile_fields()} template loop.
     2108         *
     2109         * @param BP_XProfile_Field $current_field The current profile field on the add/edit screen.
     2110         * @param string $control_type Optional. HTML input type used to render the current field's child options.
     2111         * @since BuddyPress (2.0.0)
     2112         */
     2113        public function admin_new_field_html( BP_XProfile_Field $current_field, $control_type = '' ) {
     2114                parent::admin_new_field_html( $current_field, 'checkbox' );
     2115        }
     2116}
     2117
     2118/**
     2119 * Selectbox xprofile field type.
     2120 *
     2121 * @since BuddyPress (2.0.0)
     2122 */
     2123class BP_XProfile_Field_Type_Selectbox extends BP_XProfile_Field_Type {
     2124
     2125        /**
     2126         * Constructor for the selectbox field type
     2127         *
     2128         * @since BuddyPress (2.0.0)
     2129         */
     2130        public function __construct() {
     2131                parent::__construct();
     2132
     2133                $this->category = _x( 'Multi Fields', 'xprofile field type category', 'buddypress' );
     2134                $this->name     = _x( 'Drop Down Select Box', 'xprofile field type', 'buddypress' );
     2135
     2136                $this->supports_options = true;
     2137
     2138                $this->set_format( '/^.+$/', 'replace' );
     2139                do_action( 'bp_xprofile_field_type_selectbox', $this );
     2140        }
     2141
     2142        /**
     2143         * Output the edit field HTML for this field type.
     2144         *
     2145         * Must be used inside the {@link bp_profile_fields()} template loop.
     2146         *
     2147         * @param array $raw_properties Optional key/value array of {@link http://dev.w3.org/html5/markup/select.html permitted attributes} that you want to add.
     2148         * @since BuddyPress (2.0.0)
     2149         */
     2150        public function edit_field_html( array $raw_properties = array() ) {
     2151                $user_id = bp_displayed_user_id();
     2152
     2153                // user_id is a special optional parameter that we pass to {@link bp_the_profile_field_options()}.
     2154                if ( isset( $raw_properties['user_id'] ) ) {
     2155                        $user_id = (int) $raw_properties['user_id'];
     2156                        unset( $raw_properties['user_id'] );
     2157                }
     2158
     2159                $html = $this->get_edit_field_html_elements( $raw_properties );
     2160        ?>
     2161                <label for="<?php bp_the_profile_field_input_name(); ?>"><?php bp_the_profile_field_name(); ?> <?php if ( bp_get_the_profile_field_is_required() ) : ?><?php esc_html_e( '(required)', 'buddypress' ); ?><?php endif; ?></label>
     2162                <select <?php echo $html; ?>>
     2163                        <?php bp_the_profile_field_options( "user_id={$user_id}" ); ?>
     2164                </select>
     2165        <?php
     2166        }
     2167
     2168        /**
     2169         * Output the edit field options HTML for this field type.
     2170         *
     2171         * BuddyPress considers a field's "options" to be, for example, the items in a selectbox.
     2172         * These are stored separately in the database, and their templating is handled seperately.
     2173         *
     2174         * This templating is separate from {@link BP_XProfile_Field_Type::edit_field_html()} because
     2175         * it's also used in the wp-admin screens when creating new fields, and for backwards compatibility.
     2176         *
     2177         * Must be used inside the {@link bp_profile_fields()} template loop.
     2178         *
     2179         * @param array $args Optional. The arguments passed to {@link bp_the_profile_field_options()}.
     2180         * @since BuddyPress (2.0.0)
     2181         */
     2182        public function edit_field_options_html( array $args = array() ) {
     2183                $original_option_values = maybe_unserialize( BP_XProfile_ProfileData::get_value_byid( $this->field_obj->id, $args['user_id'] ) );
     2184
     2185                $options = $this->field_obj->get_children();
     2186                $html     = '<option value="">' . /* translators: no option picked in select box */ esc_html__( '----', 'buddypress' ) . '</option>';
     2187
     2188                if ( empty( $original_option_values ) && !empty( $_POST['field_' . $this->field_obj->id] ) ) {
     2189                        $original_option_values = sanitize_text_field(  $_POST['field_' . $this->field_obj->id] );
     2190                }
     2191
     2192                $option_values = (array) $original_option_values;
     2193                for ( $k = 0, $count = count( $options ); $k < $count; ++$k ) {
     2194                        $selected = '';
     2195
     2196                        // Check for updated posted values, but errors preventing them from being saved first time
     2197                        foreach( $option_values as $i => $option_value ) {
     2198                                if ( isset( $_POST['field_' . $this->field_obj->id] ) && $_POST['field_' . $this->field_obj->id] != $option_value ) {
     2199                                        if ( ! empty( $_POST['field_' . $this->field_obj->id] ) ) {
     2200                                                $option_values[$i] = sanitize_text_field( $_POST['field_' . $this->field_obj->id] );
     2201                                        }
     2202                                }
     2203                        }
     2204
     2205                        // Run the allowed option name through the before_save filter, so we'll be sure to get a match
     2206                        $allowed_options = xprofile_sanitize_data_value_before_save( $options[$k]->name, false, false );
     2207
     2208                        // First, check to see whether the user-entered value matches
     2209                        if ( in_array( $allowed_options, $option_values ) ) {
     2210                                $selected = ' selected="selected"';
     2211                        }
     2212
     2213                        // Then, if the user has not provided a value, check for defaults
     2214                        if ( ! is_array( $original_option_values ) && empty( $option_values ) && $options[$k]->is_default_option ) {
     2215                                $selected = ' selected="selected"';
     2216                        }
     2217
     2218                        $html .= apply_filters( 'bp_get_the_profile_field_options_select', '<option' . $selected . ' value="' . esc_attr( stripslashes( $options[$k]->name ) ) . '">' . esc_html( stripslashes( $options[$k]->name ) ) . '</option>', $options[$k], $this->field_obj->id, $selected, $k );
     2219                }
     2220
     2221                echo $html;
     2222        }
     2223
     2224        /**
     2225         * Output HTML for this field type on the wp-admin Profile Fields screen.
     2226         *
     2227         * Must be used inside the {@link bp_profile_fields()} template loop.
     2228         *
     2229         * @param array $raw_properties Optional key/value array of permitted attributes that you want to add.
     2230         * @since BuddyPress (2.0.0)
     2231         */
     2232        public function admin_field_html( array $raw_properties = array() ) {
     2233                $html = $this->get_edit_field_html_elements( $raw_properties );
     2234        ?>
     2235                <select <?php echo $html; ?>>
     2236                        <?php bp_the_profile_field_options(); ?>
     2237                </select>
     2238        <?php
     2239        }
     2240
     2241        /**
     2242         * Output HTML for this field type's children options on the wp-admin Profile Fields "Add Field" and "Edit Field" screens.
     2243         *
     2244         * Must be used inside the {@link bp_profile_fields()} template loop.
     2245         *
     2246         * @param BP_XProfile_Field $current_field The current profile field on the add/edit screen.
     2247         * @param string $control_type Optional. HTML input type used to render the current field's child options.
     2248         * @since BuddyPress (2.0.0)
     2249         */
     2250        public function admin_new_field_html( BP_XProfile_Field $current_field, $control_type = '' ) {
     2251                parent::admin_new_field_html( $current_field, 'radio' );
     2252        }
     2253}
     2254
     2255/**
     2256 * Textarea xprofile field type.
     2257 *
     2258 * @since BuddyPress (2.0.0)
     2259 */
     2260class BP_XProfile_Field_Type_Textarea extends BP_XProfile_Field_Type {
     2261
     2262        /**
     2263         * Constructor for the textarea field type
     2264         *
     2265         * @since BuddyPress (2.0.0)
     2266         */
     2267        public function __construct() {
     2268                parent::__construct();
     2269
     2270                $this->category = _x( 'Single Fields', 'xprofile field type category', 'buddypress' );
     2271                $this->name     = _x( 'Multi-line Text Area', 'xprofile field type', 'buddypress' );
     2272
     2273                $this->set_format( '/^.*$/m', 'replace' );
     2274                do_action( 'bp_xprofile_field_type_textarea', $this );
     2275        }
     2276
     2277        /**
     2278         * Output the edit field HTML for this field type.
     2279         *
     2280         * Must be used inside the {@link bp_profile_fields()} template loop.
     2281         *
     2282         * @param array $raw_properties Optional key/value array of {@link http://dev.w3.org/html5/markup/textarea.html permitted attributes} that you want to add.
     2283         * @since BuddyPress (2.0.0)
     2284         */
     2285        public function edit_field_html( array $raw_properties = array() ) {
     2286
     2287                // user_id is a special optional parameter that certain other fields types pass to {@link bp_the_profile_field_options()}.
     2288                if ( isset( $raw_properties['user_id'] ) ) {
     2289                        unset( $raw_properties['user_id'] );
     2290                }
     2291
     2292                $html = $this->get_edit_field_html_elements( array_merge(
     2293                        array(
     2294                                'cols' => 40,
     2295                                'rows' => 5,
     2296                        ),
     2297                        $raw_properties
     2298                ) );
     2299        ?>
     2300                <label for="<?php bp_the_profile_field_input_name(); ?>"><?php bp_the_profile_field_name(); ?> <?php if ( bp_get_the_profile_field_is_required() ) : ?><?php esc_html_e( '(required)', 'buddypress' ); ?><?php endif; ?></label>
     2301                <textarea <?php echo $html; ?>><?php bp_the_profile_field_edit_value(); ?></textarea>
     2302        <?php
     2303        }
     2304
     2305        /**
     2306         * Output HTML for this field type on the wp-admin Profile Fields screen.
     2307         *
     2308         * Must be used inside the {@link bp_profile_fields()} template loop.
     2309         *
     2310         * @param array $raw_properties Optional key/value array of permitted attributes that you want to add.
     2311         * @since BuddyPress (2.0.0)
     2312         */
     2313        public function admin_field_html( array $raw_properties = array() ) {
     2314                $html = $this->get_edit_field_html_elements( array_merge(
     2315                        array(
     2316                                'cols' => 40,
     2317                                'rows' => 5,
     2318                        ),
     2319                        $raw_properties
     2320                ) );
     2321        ?>
     2322                <textarea <?php echo $html; ?>></textarea>
     2323        <?php
     2324        }
     2325
     2326        /**
     2327         * This method usually outputs HTML for this field type's children options on the wp-admin Profile Fields
     2328         * "Add Field" and "Edit Field" screens, but for this field type, we don't want it, so it's stubbed out.
     2329         *
     2330         * @param BP_XProfile_Field $current_field The current profile field on the add/edit screen.
     2331         * @param string $control_type Optional. HTML input type used to render the current field's child options.
     2332         * @since BuddyPress (2.0.0)
     2333         */
     2334        public function admin_new_field_html( BP_XProfile_Field $current_field, $control_type = '' ) {}
     2335}
     2336
     2337/**
     2338 * Textbox xprofile field type.
     2339 *
     2340 * @since BuddyPress (2.0.0)
     2341 */
     2342class BP_XProfile_Field_Type_Textbox extends BP_XProfile_Field_Type {
     2343
     2344        /**
     2345         * Constructor for the textbox field type
     2346         *
     2347         * @since BuddyPress (2.0.0)
     2348         */
     2349        public function __construct() {
     2350                parent::__construct();
     2351
     2352                $this->category = _x( 'Single Fields', 'xprofile field type category', 'buddypress' );
     2353                $this->name     = _x( 'Text Box', 'xprofile field type', 'buddypress' );
     2354
     2355                $this->set_format( '/^.*$/', 'replace' );
     2356                do_action( 'bp_xprofile_field_type_textbox', $this );
     2357        }
     2358
     2359        /**
     2360         * Output the edit field HTML for this field type.
     2361         *
     2362         * Must be used inside the {@link bp_profile_fields()} template loop.
     2363         *
     2364         * @param array $raw_properties Optional key/value array of {@link http://dev.w3.org/html5/markup/input.text.html permitted attributes} that you want to add.
     2365         * @since BuddyPress (2.0.0)
     2366         */
     2367        public function edit_field_html( array $raw_properties = array() ) {
     2368
     2369                // user_id is a special optional parameter that certain other fields types pass to {@link bp_the_profile_field_options()}.
     2370                if ( isset( $raw_properties['user_id'] ) ) {
     2371                        unset( $raw_properties['user_id'] );
     2372                }
     2373
     2374                $html = $this->get_edit_field_html_elements( array_merge(
     2375                        array(
     2376                                'type'  => 'text',
     2377                                'value' => bp_get_the_profile_field_edit_value(),
     2378                        ),
     2379                        $raw_properties
     2380                ) );
     2381        ?>
     2382                <label for="<?php bp_the_profile_field_input_name(); ?>"><?php bp_the_profile_field_name(); ?> <?php if ( bp_get_the_profile_field_is_required() ) : ?><?php esc_html_e( '(required)', 'buddypress' ); ?><?php endif; ?></label>
     2383                <input <?php echo $html; ?>>
     2384        <?php
     2385        }
     2386
     2387        /**
     2388         * Output HTML for this field type on the wp-admin Profile Fields screen.
     2389         *
     2390         * Must be used inside the {@link bp_profile_fields()} template loop.
     2391         *
     2392         * @param array $raw_properties Optional key/value array of permitted attributes that you want to add.
     2393         * @since BuddyPress (2.0.0)
     2394         */
     2395        public function admin_field_html( array $raw_properties = array() ) {
     2396                $html = $this->get_edit_field_html_elements( array_merge(
     2397                        array( 'type' => 'text' ),
     2398                        $raw_properties
     2399                ) );
     2400        ?>
     2401                <input <?php echo $html; ?>>
     2402        <?php
     2403        }
     2404
     2405        /**
     2406         * This method usually outputs HTML for this field type's children options on the wp-admin Profile Fields
     2407         * "Add Field" and "Edit Field" screens, but for this field type, we don't want it, so it's stubbed out.
     2408         *
     2409         * @param BP_XProfile_Field $current_field The current profile field on the add/edit screen.
     2410         * @param string $control_type Optional. HTML input type used to render the current field's child options.
     2411         * @since BuddyPress (2.0.0)
     2412         */
     2413        public function admin_new_field_html( BP_XProfile_Field $current_field, $control_type = '' ) {}
     2414}
     2415
     2416/**
     2417 * Number xprofile field type.
     2418 *
     2419 * @since BuddyPress (2.0.0)
     2420 */
     2421class BP_XProfile_Field_Type_Number extends BP_XProfile_Field_Type {
     2422
     2423        /**
     2424         * Constructor for the number field type
     2425         *
     2426         * @since BuddyPress (2.0.0)
     2427         */
     2428        public function __construct() {
     2429                parent::__construct();
     2430
     2431                $this->category = _x( 'Single Fields', 'xprofile field type category', 'buddypress' );
     2432                $this->name     = _x( 'Number', 'xprofile field type', 'buddypress' );
     2433
     2434                $this->set_format( '/^\d+$/', 'replace' );
     2435                do_action( 'bp_xprofile_field_type_number', $this );
     2436        }
     2437
     2438        /**
     2439         * Output the edit field HTML for this field type.
     2440         *
     2441         * Must be used inside the {@link bp_profile_fields()} template loop.
     2442         *
     2443         * @param array $raw_properties Optional key/value array of {@link http://dev.w3.org/html5/markup/input.number.html permitted attributes} that you want to add.
     2444         * @since BuddyPress (2.0.0)
     2445         */
     2446        public function edit_field_html( array $raw_properties = array() ) {
     2447
     2448                // user_id is a special optional parameter that certain other fields types pass to {@link bp_the_profile_field_options()}.
     2449                if ( isset( $raw_properties['user_id'] ) ) {
     2450                        unset( $raw_properties['user_id'] );
     2451                }
     2452
     2453                $html = $this->get_edit_field_html_elements( array_merge(
     2454                        array(
     2455                                'type'  => 'number',
     2456                                'value' => bp_get_the_profile_field_edit_value(),
     2457                        ),
     2458                        $raw_properties
     2459                ) );
     2460        ?>
     2461                <label for="<?php bp_the_profile_field_input_name(); ?>"><?php bp_the_profile_field_name(); ?> <?php if ( bp_get_the_profile_field_is_required() ) : ?><?php esc_html_e( '(required)', 'buddypress' ); ?><?php endif; ?></label>
     2462                <input <?php echo $html; ?>>
     2463        <?php
     2464        }
     2465
     2466        /**
     2467         * Output HTML for this field type on the wp-admin Profile Fields screen.
     2468         *
     2469         * Must be used inside the {@link bp_profile_fields()} template loop.
     2470         *
     2471         * @param array $raw_properties Optional key/value array of permitted attributes that you want to add.
     2472         * @since BuddyPress (2.0.0)
     2473         */
     2474        public function admin_field_html( array $raw_properties = array() ) {
     2475                $html = $this->get_edit_field_html_elements( array_merge(
     2476                        array( 'type' => 'number' ),
     2477                        $raw_properties
     2478                ) );
     2479        ?>
     2480                <input <?php echo $html; ?>>
     2481        <?php
     2482        }
     2483
     2484        /**
     2485         * This method usually outputs HTML for this field type's children options on the wp-admin Profile Fields
     2486         * "Add Field" and "Edit Field" screens, but for this field type, we don't want it, so it's stubbed out.
     2487         *
     2488         * @param BP_XProfile_Field $current_field The current profile field on the add/edit screen.
     2489         * @param string $control_type Optional. HTML input type used to render the current field's child options.
     2490         * @since BuddyPress (2.0.0)
     2491         */
     2492        public function admin_new_field_html( BP_XProfile_Field $current_field, $control_type = '' ) {}
     2493}
     2494
     2495/**
     2496 * Represents a type of XProfile field and holds meta information about the type of value that it accepts.
     2497 *
     2498 * @since BuddyPress (2.0.0)
     2499 */
     2500abstract class BP_XProfile_Field_Type {
     2501
     2502        /**
     2503         * @since BuddyPress (2.0.0)
     2504         * @var array Field type validation regexes
     2505         */
     2506        protected $validation_regex = array();
     2507
     2508        /**
     2509         * @since BuddyPress (2.0.0)
     2510         * @var array Field type whitelisted values
     2511         */
     2512        protected $validation_whitelist = array();
     2513
     2514        /**
     2515         * @since BuddyPress (2.0.0)
     2516         * @var string The name of this field type
     2517         */
     2518        public $name = '';
     2519
     2520        /**
     2521         * The name of the category that this field type should be grouped with. Used on the [Users > Profile Fields] screen in wp-admin.
     2522         *
     2523         * @since BuddyPress (2.0.0)
     2524         * @var string
     2525         */
     2526        public $category = '';
     2527
     2528        /**
     2529         * @since BuddyPress (2.0.0)
     2530         * @var bool If this is set, allow BP to store null/empty values for this field type.
     2531         */
     2532        public $accepts_null_value = false;
     2533
     2534        /**
     2535         * If this is set, BP will set this field type's validation whitelist from the field's options (e.g checkbox, selectbox).
     2536         *
     2537         * @since BuddyPress (2.0.0)
     2538         * @var bool Does this field support options? e.g. selectbox, radio buttons, etc.
     2539         */
     2540        public $supports_options = false;
     2541
     2542        /**
     2543         * @since BuddyPress (2.0.0)
     2544         * @var bool Does this field type support multiple options being set as default values? e.g. multiselectbox, checkbox.
     2545         */
     2546        public $supports_multiple_defaults = false;
     2547
     2548        /**
     2549         * @since BuddyPress (2.0.0)
     2550         * @var BP_XProfile_Field If this object is created by instantiating a {@link BP_XProfile_Field}, this is a reference back to that object.
     2551         */
     2552        public $field_obj = null;
     2553
     2554        /**
     2555         * Constructor
     2556         *
     2557         * @since BuddyPress (2.0.0)
     2558         */
     2559        public function __construct() {
     2560                do_action( 'bp_xprofile_field_type', $this );
     2561        }
     2562
     2563        /**
     2564         * Set a regex that profile data will be asserted against.
     2565         *
     2566         * You can call this method multiple times to set multiple formats. When validation is performed,
     2567         * it's successful as long as the new value matches any one of the registered formats.
     2568         *
     2569         * @param string $format Regex string
     2570         * @param string $replace_format Optional; if 'replace', replaces the format instead of adding to it. Defaults to 'add'.
     2571         * @return BP_XProfile_Field_Type
     2572         * @since BuddyPress (2.0.0)
     2573         */
     2574        public function set_format( $format, $replace_format = 'add' ) {
     2575
     2576                $format = apply_filters( 'bp_xprofile_field_type_set_format', $format, $replace_format, $this );
     2577
     2578                if ( 'add' === $replace_format ) {
     2579                        $this->validation_regex[] = $format;
     2580                } elseif ( 'replace' === $replace_format ) {
     2581                        $this->validation_regex = array( $format );
     2582                }
     2583
     2584                return $this;
     2585        }
     2586
     2587        /**
     2588         * Add a value to this type's whitelist that that profile data will be asserted against.
     2589         *
     2590         * You can call this method multiple times to set multiple formats. When validation is performed,
     2591         * it's successful as long as the new value matches any one of the registered formats.
     2592         *
     2593         * @param string|array $values
     2594         * @return BP_XProfile_Field_Type
     2595         * @since BuddyPress (2.0.0)
     2596         */
     2597        public function set_whitelist_values( $values ) {
     2598                foreach ( (array) $values as $value ) {
     2599                        $this->validation_whitelist[] = apply_filters( 'bp_xprofile_field_type_set_whitelist_values', $value, $values, $this );
     2600                }
     2601
     2602                return $this;
     2603        }
     2604
     2605        /**
     2606         * Check the given string against the registered formats for this field type.
     2607         *
     2608         * This method doesn't support chaining.
     2609         *
     2610         * @param string|array $values Value to check against the registered formats
     2611         * @return bool True if the value validates
     2612         * @since BuddyPress (2.0.0)
     2613         */
     2614        public function is_valid( $values ) {
     2615                $validated = false;
     2616
     2617                // Some types of field (e.g. multi-selectbox) may have multiple values to check
     2618                foreach ( (array) $values as $value ) {
     2619
     2620                        // Validate the $value against the type's accepted format(s).
     2621                        foreach ( $this->validation_regex as $format ) {
     2622                                if ( 1 === preg_match( $format, $value ) ) {
     2623                                        $validated = true;
     2624                                        continue;
     2625
     2626                                } else {
     2627                                        $validated = false;
     2628                                }
     2629                        }
     2630                }
     2631
     2632                // Handle field types with accepts_null_value set if $values is an empty array
     2633                if ( ! $validated && is_array( $values ) && empty( $values ) && $this->accepts_null_value ) {
     2634                        $validated = true;
     2635                }
     2636
     2637                // If there's a whitelist set, also check the $value.
     2638                if ( $validated && ! empty( $values ) && ! empty( $this->validation_whitelist ) ) {
     2639
     2640                        foreach ( (array) $values as $value ) {
     2641                                $validated = in_array( $value, $this->validation_whitelist, true );
     2642                        }
     2643                }
     2644
     2645                return (bool) apply_filters( 'bp_xprofile_field_type_is_valid', $validated, $values, $this );
     2646        }
     2647
     2648        /**
     2649         * Output the edit field HTML for this field type.
     2650         *
     2651         * Must be used inside the {@link bp_profile_fields()} template loop.
     2652         *
     2653         * @param array $raw_properties Optional key/value array of permitted attributes that you want to add.
     2654         * @since BuddyPress (2.0.0)
     2655         */
     2656        abstract public function edit_field_html( array $raw_properties = array() );
     2657
     2658        /**
     2659         * Output the edit field options HTML for this field type.
     2660         *
     2661         * BuddyPress considers a field's "options" to be, for example, the items in a selectbox.
     2662         * These are stored separately in the database, and their templating is handled separately.
     2663         * Populate this method in a child class if it's required. Otherwise, you can leave it out.
     2664         *
     2665         * This templating is separate from {@link BP_XProfile_Field_Type::edit_field_html()} because
     2666         * it's also used in the wp-admin screens when creating new fields, and for backwards compatibility.
     2667         *
     2668         * Must be used inside the {@link bp_profile_fields()} template loop.
     2669         *
     2670         * @param array $args Optional. The arguments passed to {@link bp_the_profile_field_options()}.
     2671         * @since BuddyPress (2.0.0)
     2672         */
     2673        public function edit_field_options_html( array $args = array() ) {}
     2674
     2675        /**
     2676         * Output HTML for this field type on the wp-admin Profile Fields screen.
     2677         *
     2678         * Must be used inside the {@link bp_profile_fields()} template loop.
     2679         *
     2680         * @param array $raw_properties Optional key/value array of permitted attributes that you want to add.
     2681         * @since BuddyPress (2.0.0)
     2682         */
     2683        abstract public function admin_field_html( array $raw_properties = array() );
     2684
     2685        /**
     2686         * Output HTML for this field type's children options on the wp-admin Profile Fields "Add Field" and "Edit Field" screens.
     2687         *
     2688         * You don't need to implement this method for all field types. It's used in core by the
     2689         * selectbox, multi selectbox, checkbox, and radio button fields, to allow the admin to
     2690         * enter the child option values (e.g. the choices in a select box).
     2691         *
     2692         * Must be used inside the {@link bp_profile_fields()} template loop.
     2693         *
     2694         * @param BP_XProfile_Field $current_field The current profile field on the add/edit screen.
     2695         * @param string $control_type Optional. HTML input type used to render the current field's child options.
     2696         * @since BuddyPress (2.0.0)
     2697         */
     2698        public function admin_new_field_html( BP_XProfile_Field $current_field, $control_type = '' ) {
     2699                $type = array_search( get_class( $this ), bp_xprofile_get_field_types() );
     2700                if ( false === $type ) {
     2701                        return;
     2702                }
     2703
     2704                $class            = $current_field->type != $type ? 'display: none;' : '';
     2705                $current_type_obj = bp_xprofile_create_field_type( $type );
     2706                ?>
     2707
     2708                <div id="<?php echo esc_attr( $type ); ?>" class="postbox bp-options-box" style="<?php echo esc_attr( $class ); ?> margin-top: 15px;">
     2709                        <h3><?php esc_html_e( 'Please enter options for this Field:', 'buddypress' ); ?></h3>
     2710                        <div class="inside">
     2711                                <p>
     2712                                        <label for="sort_order_<?php echo esc_attr( $type ); ?>"><?php esc_html_e( 'Sort Order:', 'buddypress' ); ?></label>
     2713                                        <select name="sort_order_<?php echo esc_attr( $type ); ?>" id="sort_order_<?php echo esc_attr( $type ); ?>" >
     2714                                                <option value="custom" <?php selected( 'custom', $current_field->order_by ); ?>><?php esc_html_e( 'Custom',     'buddypress' ); ?></option>
     2715                                                <option value="asc"    <?php selected( 'asc',    $current_field->order_by ); ?>><?php esc_html_e( 'Ascending',  'buddypress' ); ?></option>
     2716                                                <option value="desc"   <?php selected( 'desc',   $current_field->order_by ); ?>><?php esc_html_e( 'Descending', 'buddypress' ); ?></option>
     2717                                        </select>
     2718                                </p>
     2719
     2720                                <?php
     2721                                $options = $current_field->get_children( true );
     2722
     2723                                // If no children options exists for this field, check in $_POST for a submitted form (e.g. on the "new field" screen).
     2724                                if ( ! $options ) {
     2725
     2726                                        $options = array();
     2727                                        $i       = 1;
     2728
     2729                                        while ( isset( $_POST[$type . '_option'][$i] ) ) {
     2730
     2731                                                // Multiselectbox and checkboxes support MULTIPLE default options; all other core types support only ONE.
     2732                                                if ( $current_type_obj->supports_options && ! $current_type_obj->supports_multiple_defaults && isset( $_POST["isDefault_{$type}_option"][$i] ) && (int) $_POST["isDefault_{$type}_option"] === $i ) {
     2733                                                        $is_default_option = true;
     2734                                                } elseif ( isset( $_POST["isDefault_{$type}_option"][$i] ) ) {
     2735                                                        $is_default_option = (bool) $_POST["isDefault_{$type}_option"][$i];
     2736                                                } else {
     2737                                                        $is_default_option = false;
     2738                                                }
     2739
     2740                                                // Grab the values from $_POST to use as the form's options
     2741                                                $options[] = (object) array(
     2742                                                        'id'                => -1,
     2743                                                        'is_default_option' => $is_default_option,
     2744                                                        'name'              => sanitize_text_field( stripslashes( $_POST[$type . '_option'][$i] ) ),
     2745                                                );
     2746
     2747                                                ++$i;
     2748                                        }
     2749
     2750                                        // If there are still no children options set, this must be the "new field" screen, so add one new/empty option.
     2751                                        if ( ! $options ) {
     2752                                                $options[] = (object) array(
     2753                                                        'id'                => -1,
     2754                                                        'is_default_option' => false,
     2755                                                        'name'              => '',
     2756                                                );
     2757                                        }
     2758                                }
     2759
     2760                                // Render the markup for the children options
     2761                                if ( ! empty( $options ) ) {
     2762                                        $default_name = '';
     2763
     2764                                        for ( $i = 0, $count = count( $options ); $i < $count; ++$i ) :
     2765                                                $j = $i + 1;
     2766
     2767                                                // Multiselectbox and checkboxes support MULTIPLE default options; all other core types support only ONE.
     2768                                                if ( $current_type_obj->supports_options && $current_type_obj->supports_multiple_defaults ) {
     2769                                                        $default_name = '[' . $j . ']';
     2770                                                }
     2771                                                ?>
     2772
     2773                                                <p class="sortable">
     2774                                                        <span>&nbsp;&Xi;&nbsp;</span>
     2775                                                        <input type="text" name="<?php echo esc_attr( "{$type}_option[{$j}]" ); ?>" id="<?php echo esc_attr( "{$type}_option{$j}" ); ?>" value="<?php echo esc_attr( $options[$i]->name ); ?>" />
     2776                                                        <input type="<?php echo esc_attr( $control_type ); ?>" name="<?php echo esc_attr( "isDefault_{$type}_option{$default_name}" ); ?>" <?php checked( $options[$i]->is_default_option, true ); ?> value="<?php echo esc_attr( $j ); ?>" />
     2777                                                        <span><?php _e( 'Default Value', 'buddypress' ); ?></span>
     2778                                                </p>
     2779                                        <?php endfor; ?>
     2780
     2781                                        <input type="hidden" name="<?php echo esc_attr( "{$type}_option_number" ); ?>" id="<?php echo esc_attr( "{$type}_option_number" ); ?>" value="<?php echo esc_attr( $j + 1 ); ?>" />
     2782                                <?php } ?>
     2783
     2784                                <div id="<?php echo esc_attr( "{$type}_more" ); ?>"></div>
     2785                                <p><a href="javascript:add_option('<?php echo esc_js( $type ); ?>')"><?php esc_html_e( 'Add Another Option', 'buddypress' ); ?></a></p>
     2786                        </div>
     2787                </div>
     2788
     2789                <?php
     2790        }
     2791
     2792
     2793        /**
     2794         * Internal protected/private helper methods past this point.
     2795         */
     2796
     2797        /**
     2798         * Get a sanitised and escaped string of the edit field's HTML elements and attributes.
     2799         *
     2800         * Must be used inside the {@link bp_profile_fields()} template loop.
     2801         * This method was intended to be static but couldn't be because php.net/lsb/ requires PHP >= 5.3.
     2802         *
     2803         * @param array $properties Optional key/value array of attributes for this edit field.
     2804         * @return string
     2805         * @since BuddyPress (2.0.0)
     2806         */
     2807        protected function get_edit_field_html_elements( array $properties = array() ) {
     2808
     2809                $properties = array_merge( array(
     2810                        'id'   => bp_get_the_profile_field_input_name(),
     2811                        'name' => bp_get_the_profile_field_input_name(),
     2812                ), $properties );
     2813
     2814                if ( bp_get_the_profile_field_is_required() ) {
     2815                        $properties['aria-required'] = 'true';
     2816                }
     2817
     2818                $html       = '';
     2819                $properties = (array) apply_filters( 'bp_xprofile_field_edit_html_elements', $properties, get_class( $this ) );
     2820
     2821                foreach ( $properties as $name => $value ) {
     2822                        $html .= sprintf( '%s="%s" ', sanitize_key( $name ), esc_attr( $value ) );
     2823                }
     2824
     2825                return $html;
     2826        }
     2827}
  • bp-xprofile/bp-xprofile-functions.php

    diff --git a/bp-xprofile/bp-xprofile-functions.php b/bp-xprofile/bp-xprofile-functions.php
    index 4c508dc..2df82cd 100644
    a b function xprofile_update_field_group_position( $field_group_id, $position ) {  
    6060
    6161/*** Field Management *********************************************************/
    6262
     63/**
     64 * Get details of all xprofile field types.
     65 *
     66 * @return array Key/value pairs (field type => class name).
     67 * @since BuddyPress (2.0.0)
     68 */
     69function bp_xprofile_get_field_types() {
     70        $fields = array(
     71                'checkbox'       => 'BP_XProfile_Field_Type_Checkbox',
     72                'datebox'        => 'BP_XProfile_Field_Type_Datebox',
     73                'multiselectbox' => 'BP_XProfile_Field_Type_Multiselectbox',
     74                'number'         => 'BP_XProfile_Field_Type_Number',
     75                'radio'          => 'BP_XProfile_Field_Type_Radiobutton',
     76                'selectbox'      => 'BP_XProfile_Field_Type_Selectbox',
     77                'textarea'       => 'BP_XProfile_Field_Type_Textarea',
     78                'textbox'        => 'BP_XProfile_Field_Type_Textbox',
     79        );
     80
     81        // If you've added a custom field type in a plugin, register it with this filter.
     82        return apply_filters( 'bp_xprofile_get_field_types', $fields );
     83}
     84
     85/**
     86 * Creates the specified field type object; used for validation and templating.
     87 *
     88 * @param string $type Type of profile field to create. See {@link bp_xprofile_get_field_types()} for default core values.
     89 * @return object If field type unknown, returns BP_XProfile_Field_Type_Textarea. Otherwise returns an instance of the relevant child class of BP_XProfile_Field_Type.
     90 * @since BuddyPress (2.0.0)
     91 */
     92function bp_xprofile_create_field_type( $type ) {
     93
     94        $field = bp_xprofile_get_field_types();
     95        $class = isset( $field[$type] ) ? $field[$type] : '';
     96
     97        /**
     98         * For backpat and to handle (missing) field types introduced by other plugins, fallback to
     99         * textbox if a type is unknown. Textbox validation and display is intentionally low key.
     100         */
     101        if ( $class && class_exists( $class ) ) {
     102                return new $class;
     103        } else {
     104                return new BP_XProfile_Field_Type_Textbox;
     105        }
     106}
     107
    63108function xprofile_insert_field( $args = '' ) {
    64109        global $bp;
    65110
    … … function xprofile_set_field_data( $field, $user_id, $value, $is_required = false  
    214259        if ( $is_required && ( empty( $value ) || !is_array( $value ) && !strlen( trim( $value ) ) ) )
    215260                return false;
    216261
    217         $field = new BP_XProfile_Field( $field_id );
     262        $field          = new BP_XProfile_Field( $field_id );
     263        $field_type_obj = bp_xprofile_create_field_type( BP_XProfile_Field::get_type( $field_id ) );
    218264
    219         // If the value is empty, then delete any field data that exists, unless the field is of a
    220         // type where null values are semantically meaningful
    221         if ( empty( $value ) && 'checkbox' != $field->type && 'multiselectbox' != $field->type ) {
     265        // If the value is empty, then delete any field data that exists, unless the field is of a type where null values are semantically meaningful
     266        if ( empty( $value ) && ! $field_type_obj->accepts_null_value ) {
    222267                xprofile_delete_field_data( $field_id, $user_id );
    223268                return true;
    224269        }
    225270
    226         $possible_values = array();
    227 
    228         // Check the value is an acceptable value
    229         if ( 'checkbox' == $field->type || 'radio' == $field->type || 'selectbox' == $field->type || 'multiselectbox' == $field->type ) {
    230                 $options = $field->get_children();
    231 
    232                 foreach( $options as $option )
    233                         $possible_values[] = $option->name;
    234 
    235                 if ( is_array( $value ) ) {
    236                         foreach( $value as $i => $single ) {
    237                                 if ( !in_array( $single, $possible_values ) ) {
    238                                         unset( $value[$i] );
    239                                 }
    240                         }
     271        // For certain fields, only certain parameters are acceptable, so add them to the whitelist.
     272        if ( $field_type_obj->supports_options ) {
     273                $field_type_obj->set_whitelist_values( wp_list_pluck( $field->get_children(), 'name' ) );
     274        }
    241275
    242                         // Reset the keys by merging with an empty array
    243                         $value = array_merge( array(), $value );
    244                 } else {
    245                         if ( !in_array( $value, $possible_values ) ) {
    246                                 return false;
    247                         }
    248                 }
     276        // Check the value is in an accepted format for this form field.
     277        if ( ! $field_type_obj->is_valid( $value ) ) {
     278                return false;
    249279        }
    250280
    251281        $field           = new BP_XProfile_ProfileData();
  • bp-xprofile/bp-xprofile-loader.php

    diff --git a/bp-xprofile/bp-xprofile-loader.php b/bp-xprofile/bp-xprofile-loader.php
    index 922877c..3477fe1 100644
    a b class BP_XProfile_Component extends BP_Component {  
    9898                }
    9999
    100100                // Set the support field type ids
    101                 $this->field_types = apply_filters( 'xprofile_field_types', array(
    102                         'textbox',
    103                         'textarea',
    104                         'radio',
    105                         'checkbox',
    106                         'selectbox',
    107                         'multiselectbox',
    108                         'datebox'
    109                 ) );
     101                $this->field_types = apply_filters( 'xprofile_field_types', array_keys( bp_xprofile_get_field_types() ) );
    110102
    111103                // Register the visibility levels. See bp_xprofile_get_visibility_levels() to filter
    112104                $this->visibility_levels = array(
  • bp-xprofile/bp-xprofile-template.php

    diff --git a/bp-xprofile/bp-xprofile-template.php b/bp-xprofile/bp-xprofile-template.php
    index ff320d9..aa87a64 100644
    a b function bp_field_css_class( $class = false ) {  
    221221                if ( $profile_template->current_field % 2 == 1 )
    222222                        $css_classes[] = 'alt';
    223223
     224                $css_classes[] = 'field_type_' . sanitize_title( $profile_template->field->type );
    224225                $css_classes = apply_filters_ref_array( 'bp_field_css_classes', array( &$css_classes ) );
    225226
    226227                return apply_filters( 'bp_get_field_css_class', ' class="' . implode( ' ', $css_classes ) . '"' );
    … … function bp_the_profile_field_input_name() {  
    386387        function bp_get_the_profile_field_input_name() {
    387388                global $field;
    388389
    389                 $array_box = false;
    390                 if ( 'multiselectbox' == $field->type )
    391                         $array_box = '[]';
    392 
    393                 return apply_filters( 'bp_get_the_profile_field_input_name', 'field_' . $field->id . $array_box );
     390                return apply_filters( 'bp_get_the_profile_field_input_name', 'field_' . $field->id );
    394391        }
    395392
    396393/**
    … … function bp_get_the_profile_field_errors_action() {  
    423420 *
    424421 * @param array $args Specify type for datebox. Allowed 'day', 'month', 'year'.
    425422 */
    426 function bp_the_profile_field_options( $args = '' ) {
     423function bp_the_profile_field_options( $args = array() ) {
    427424        echo bp_get_the_profile_field_options( $args );
    428425}
    429426        /**
    430427         * bp_get_the_profile_field_options()
    431428         *
    432          * Retrieves field options HTML for field types of 'selectbox', 'multiselectbox',
    433          * 'radio', 'checkbox', and 'datebox'.
     429         * Retrieves field options HTML for field types of 'selectbox', 'multiselectbox', 'radio', 'checkbox', and 'datebox'.
    434430         *
    435431         * @package BuddyPress Xprofile
    436432         * @since BuddyPress (1.1)
    … … function bp_the_profile_field_options( $args = '' ) {  
    446442         *           used when rendering options. Default: displayed user.
    447443         * }
    448444         */
    449         function bp_get_the_profile_field_options( $args = '' ) {
     445        function bp_get_the_profile_field_options( $args = array() ) {
    450446                global $field;
    451447
    452                 $defaults = array(
     448                $args = bp_parse_args( $args, array(
    453449                        'type'    => false,
    454450                        'user_id' => bp_displayed_user_id(),
    455                 );
    456 
    457                 $r = wp_parse_args( $args, $defaults );
    458                 extract( $r, EXTR_SKIP );
     451                ), 'get_the_profile_field_options' );
    459452
    460                 // In some cases, the $field global is not an instantiation of the BP_XProfile_Field
    461                 // class. However, we have to make sure that all data originally in $field gets
    462                 // merged back in, after reinstantiation.
    463                 if ( !method_exists( $field, 'get_children' ) ) {
     453                /**
     454                 * In some cases, the $field global is not an instantiation of the BP_XProfile_Field class.
     455                 * However, we have to make sure that all data originally in $field gets merged back in, after reinstantiation.
     456                 */
     457                if ( ! method_exists( $field, 'get_children' ) ) {
    464458                        $field_obj = new BP_XProfile_Field( $field->id );
    465459
    466                         foreach( $field as $field_prop => $field_prop_value ) {
    467                                 if ( !isset( $field_obj->{$field_prop} ) ) {
     460                        foreach ( $field as $field_prop => $field_prop_value ) {
     461                                if ( ! isset( $field_obj->{$field_prop} ) )
    468462                                        $field_obj->{$field_prop} = $field_prop_value;
    469                                 }
    470463                        }
    471464
    472465                        $field = $field_obj;
    473466                }
    474467
    475                 $options = $field->get_children();
    476 
    477                 // Setup some defaults
    478                 $html     = '';
    479                 $selected = '';
    480 
    481                 switch ( $field->type ) {
    482                         case 'selectbox':
    483 
    484                                 $html .= '<option value="">' . /* translators: no option picked in select box */ __( '----', 'buddypress' ) . '</option>';
    485 
    486                                 $original_option_values = '';
    487                                 $original_option_values = maybe_unserialize( BP_XProfile_ProfileData::get_value_byid( $field->id, $user_id ) );
    488 
    489                                 if ( empty( $original_option_values ) && !empty( $_POST['field_' . $field->id] ) ) {
    490                                         $original_option_values = $_POST['field_' . $field->id];
    491                                 }
    492 
    493                                 $option_values = (array) $original_option_values;
    494 
    495                                 for ( $k = 0, $count = count( $options ); $k < $count; ++$k ) {
    496 
    497                                         // Check for updated posted values, but errors preventing them from being saved first time
    498                                         foreach( $option_values as $i => $option_value ) {
    499                                                 if ( isset( $_POST['field_' . $field->id] ) && $_POST['field_' . $field->id] != $option_value ) {
    500                                                         if ( !empty( $_POST['field_' . $field->id] ) ) {
    501                                                                 $option_values[$i] = $_POST['field_' . $field->id];
    502                                                         }
    503                                                 }
    504                                         }
    505 
    506                                         $selected = '';
    507 
    508                                         // Run the allowed option name through the before_save filter, so we'll be sure to get a match
    509                                         $allowed_options = xprofile_sanitize_data_value_before_save( $options[$k]->name, false, false );
    510 
    511                                         // First, check to see whether the user-entered value matches
    512                                         if ( in_array( $allowed_options, (array) $option_values ) ) {
    513                                                 $selected = ' selected="selected"';
    514                                         }
    515 
    516                                         // Then, if the user has not provided a value, check for defaults
    517                                         if ( !is_array( $original_option_values ) && empty( $option_values ) && $options[$k]->is_default_option ) {
    518                                                 $selected = ' selected="selected"';
    519                                         }
    520 
    521                                         $html .= apply_filters( 'bp_get_the_profile_field_options_select', '<option' . $selected . ' value="' . esc_attr( stripslashes( $options[$k]->name ) ) . '">' . esc_attr( stripslashes( $options[$k]->name ) ) . '</option>', $options[$k], $field->id, $selected, $k );
    522                                 }
    523                                 break;
    524 
    525                         case 'multiselectbox':
    526                                 $original_option_values = '';
    527                                 $original_option_values = maybe_unserialize( BP_XProfile_ProfileData::get_value_byid( $field->id, $user_id ) );
    528 
    529                                 if ( empty( $original_option_values ) && !empty( $_POST['field_' . $field->id] ) ) {
    530                                         $original_option_values = $_POST['field_' . $field->id];
    531                                 }
    532 
    533                                 $option_values = (array) $original_option_values;
    534 
    535                                 for ( $k = 0, $count = count( $options ); $k < $count; ++$k ) {
    536 
    537                                         // Check for updated posted values, but errors preventing them from being saved first time
    538                                         foreach( $option_values as $i => $option_value ) {
    539                                                 if ( isset( $_POST['field_' . $field->id] ) && $_POST['field_' . $field->id][$i] != $option_value ) {
    540                                                         if ( !empty( $_POST['field_' . $field->id][$i] ) ) {
    541                                                                 $option_values[] = $_POST['field_' . $field->id][$i];
    542                                                         }
    543                                                 }
    544                                         }
    545                                         $selected = '';
    546 
    547                                         // Run the allowed option name through the before_save filter, so we'll be sure to get a match
    548                                         $allowed_options = xprofile_sanitize_data_value_before_save( $options[$k]->name, false, false );
    549 
    550                                         // First, check to see whether the user-entered value matches
    551                                         if ( in_array( $allowed_options, (array) $option_values ) ) {
    552                                                 $selected = ' selected="selected"';
    553                                         }
    554 
    555                                         // Then, if the user has not provided a value, check for defaults
    556                                         if ( !is_array( $original_option_values ) && empty( $option_values ) && !empty( $options[$k]->is_default_option ) ) {
    557                                                 $selected = ' selected="selected"';
    558                                         }
    559 
    560                                         $html .= apply_filters( 'bp_get_the_profile_field_options_multiselect', '<option' . $selected . ' value="' . esc_attr( stripslashes( $options[$k]->name ) ) . '">' . esc_attr( stripslashes( $options[$k]->name ) ) . '</option>', $options[$k], $field->id, $selected, $k );
    561                                 }
    562                                 break;
    563 
    564                         case 'radio':
    565                                 $html .= '<div id="field_' . $field->id . '">';
    566                                 $option_value = BP_XProfile_ProfileData::get_value_byid( $field->id, $user_id );
    567 
    568                                 for ( $k = 0, $count = count( $options ); $k < $count; ++$k ) {
    569 
    570                                         // Check for updated posted values, but errors preventing them from being saved first time
    571                                         if ( isset( $_POST['field_' . $field->id] ) && $option_value != $_POST['field_' . $field->id] ) {
    572                                                 if ( !empty( $_POST['field_' . $field->id] ) ) {
    573                                                         $option_value = $_POST['field_' . $field->id];
    574                                                 }
    575                                         }
    576 
    577                                         // Run the allowed option name through the before_save
    578                                         // filter, so we'll be sure to get a match
    579                                         $allowed_options = xprofile_sanitize_data_value_before_save( $options[$k]->name, false, false );
    580                                         $selected        = '';
    581 
    582                                         if ( $option_value == $allowed_options || ( empty( $option_value ) && !empty( $options[$k]->is_default_option ) ) )
    583                                                 $selected = ' checked="checked"';
    584 
    585                                         $html .= apply_filters( 'bp_get_the_profile_field_options_radio', '<label><input' . $selected . ' type="radio" name="field_' . $field->id . '" id="option_' . $options[$k]->id . '" value="' . esc_attr( stripslashes( $options[$k]->name ) ) . '"> ' . esc_attr( stripslashes( $options[$k]->name ) ) . '</label>', $options[$k], $field->id, $selected, $k );
    586                                 }
    587 
    588                                 $html .= '</div>';
    589                                 break;
    590 
    591                         case 'checkbox':
    592                                 $option_values = BP_XProfile_ProfileData::get_value_byid( $field->id, $user_id );
    593                                 $option_values = (array) maybe_unserialize( $option_values );
    594 
    595                                 // Check for updated posted values, but errors preventing them from being saved first time
    596                                 if ( isset( $_POST['field_' . $field->id] ) && $option_values != maybe_serialize( $_POST['field_' . $field->id] ) ) {
    597                                         if ( !empty( $_POST['field_' . $field->id] ) )
    598                                                 $option_values = $_POST['field_' . $field->id];
    599                                 }
    600 
    601                                 for ( $k = 0, $count = count( $options ); $k < $count; ++$k ) {
    602                                         $selected = '';
    603 
    604                                         // First, check to see whether the user's saved values
    605                                         // match the option
    606                                         for ( $j = 0, $count_values = count( $option_values ); $j < $count_values; ++$j ) {
    607 
    608                                                 // Run the allowed option name through the
    609                                                 // before_save filter, so we'll be sure to get a match
    610                                                 $allowed_options = xprofile_sanitize_data_value_before_save( $options[$k]->name, false, false );
    611 
    612                                                 if ( $option_values[$j] == $allowed_options || @in_array( $allowed_options, $option_values ) ) {
    613                                                         $selected = ' checked="checked"';
    614                                                         break;
    615                                                 }
    616                                         }
    617 
    618                                         // If the user has not yet supplied a value for this field,
    619                                         // check to see whether there is a default value available
    620                                         if ( !is_array( $option_values ) && empty( $option_values ) && empty( $selected ) && !empty( $options[$k]->is_default_option ) ) {
    621                                                 $selected = ' checked="checked"';
    622                                         }
    623 
    624                                         $html .= apply_filters( 'bp_get_the_profile_field_options_checkbox', '<label><input' . $selected . ' type="checkbox" name="field_' . $field->id . '[]" id="field_' . $options[$k]->id . '_' . $k . '" value="' . esc_attr( stripslashes( $options[$k]->name ) ) . '"> ' . esc_attr( stripslashes( $options[$k]->name ) ) . '</label>', $options[$k], $field->id, $selected, $k );
    625                                 }
    626                                 break;
    627 
    628                         case 'datebox':
    629                                 $date = BP_XProfile_ProfileData::get_value_byid( $field->id, $user_id );
    630 
    631                                 // Set day, month, year defaults
    632                                 $day   = '';
    633                                 $month = '';
    634                                 $year  = '';
    635 
    636                                 if ( !empty( $date ) ) {
    637 
    638                                         // If Unix timestamp
    639                                         if ( is_numeric( $date ) ) {
    640                                                 $day   = date( 'j', $date );
    641                                                 $month = date( 'F', $date );
    642                                                 $year  = date( 'Y', $date );
    643 
    644                                         // If MySQL timestamp
    645                                         } else {
    646                                                 $day   = mysql2date( 'j', $date );
    647                                                 $month = mysql2date( 'F', $date, false ); // Not localized, so that selected() works below
    648                                                 $year  = mysql2date( 'Y', $date );
    649                                         }
    650                                 }
    651 
    652                                 // Check for updated posted values, and errors preventing
    653                                 // them from being saved first time.
    654                                 if ( !empty( $_POST['field_' . $field->id . '_day'] ) ) {
    655                                         if ( $day != $_POST['field_' . $field->id . '_day'] ) {
    656                                                 $day = $_POST['field_' . $field->id . '_day'];
    657                                         }
    658                                 }
    659 
    660                                 if ( !empty( $_POST['field_' . $field->id . '_month'] ) ) {
    661                                         if ( $month != $_POST['field_' . $field->id . '_month'] ) {
    662                                                 $month = $_POST['field_' . $field->id . '_month'];
    663                                         }
    664                                 }
    665 
    666                                 if ( !empty( $_POST['field_' . $field->id . '_year'] ) ) {
    667                                         if ( $year != date( "j", $_POST['field_' . $field->id . '_year'] ) ) {
    668                                                 $year = $_POST['field_' . $field->id . '_year'];
    669                                         }
    670                                 }
    671 
    672                                 // $type will be passed by calling function when needed
    673                                 switch ( $type ) {
    674                                         case 'day':
    675                                                 $html .= '<option value=""' . selected( $day, '', false ) . '>--</option>';
    676 
    677                                                 for ( $i = 1; $i < 32; ++$i ) {
    678                                                         $html .= '<option value="' . $i .'"' . selected( $day, $i, false ) . '>' . $i . '</option>';
    679                                                 }
    680                                                 break;
    681 
    682                                         case 'month':
    683                                                 $eng_months = array( 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December' );
    684 
    685                                                 $months = array(
    686                                                         __( 'January', 'buddypress' ),
    687                                                         __( 'February', 'buddypress' ),
    688                                                         __( 'March', 'buddypress' ),
    689                                                         __( 'April', 'buddypress' ),
    690                                                         __( 'May', 'buddypress' ),
    691                                                         __( 'June', 'buddypress' ),
    692                                                         __( 'July', 'buddypress' ),
    693                                                         __( 'August', 'buddypress' ),
    694                                                         __( 'September', 'buddypress' ),
    695                                                         __( 'October', 'buddypress' ),
    696                                                         __( 'November', 'buddypress' ),
    697                                                         __( 'December', 'buddypress' )
    698                                                 );
    699 
    700                                                 $html .= '<option value=""' . selected( $month, '', false ) . '>------</option>';
    701 
    702                                                 for ( $i = 0; $i < 12; ++$i ) {
    703                                                         $html .= '<option value="' . $eng_months[$i] . '"' . selected( $month, $eng_months[$i], false ) . '>' . $months[$i] . '</option>';
    704                                                 }
    705                                                 break;
    706 
    707                                         case 'year':
    708                                                 $html .= '<option value=""' . selected( $year, '', false ) . '>----</option>';
    709 
    710                                                 for ( $i = 2037; $i > 1901; $i-- ) {
    711                                                         $html .= '<option value="' . $i .'"' . selected( $year, $i, false ) . '>' . $i . '</option>';
    712                                                 }
    713                                                 break;
    714                                 }
    715 
    716                                 $html = apply_filters( 'bp_get_the_profile_field_datebox', $html, $type, $day, $month, $year, $field->id, $date );
    717 
    718                                 break;
    719                 }
     468                ob_start();
     469                $field->type_obj->edit_field_options_html( $args );
     470                $html = ob_get_contents();
     471                ob_end_clean();
    720472
    721473                return $html;
    722474        }
    … … function bp_xprofile_settings_visibility_select( $args = '' ) {  
    1014766
    1015767                // Output the dropdown list
    1016768                return apply_filters( 'bp_xprofile_settings_visibility_select', ob_get_clean() );
    1017         }
    1018  No newline at end of file
     769        }
  • new file tests/testcases/xprofile/class-bp-xprofile-field-type.php

    diff --git a/tests/testcases/xprofile/class-bp-xprofile-field-type.php b/tests/testcases/xprofile/class-bp-xprofile-field-type.php
    new file mode 100644
    index 0000000..4511262
    - +  
     1<?php
     2/**
     3 * @group xprofile
     4 * @group BP_XProfile_Field_Type
     5 */
     6class BP_Tests_XProfile_Field_Type extends BP_UnitTestCase {
     7        public function setUp() {
     8                parent::setUp();
     9        }
     10
     11        public function tearDown() {
     12                parent::tearDown();
     13        }
     14
     15        public function test_unregistered_field_type_returns_textbox() {
     16                $field = bp_xprofile_create_field_type( 'fakeyfield' );
     17                $this->assertEquals( get_class( $field ), 'BP_XProfile_Field_Type_Textbox' );
     18        }
     19
     20
     21        public function test_textbox_validate_empty_string() {
     22                $field = bp_xprofile_create_field_type( 'textbox' );
     23                $this->assertTrue( $field->is_valid( '' ) );
     24        }
     25
     26        public function test_textbox_validate_string() {
     27                $field = bp_xprofile_create_field_type( 'textbox' );
     28                $this->assertTrue( $field->is_valid( 'my 117th input string!' ) );
     29        }
     30
     31        public function test_textbox_validate_integer() {
     32                $field = bp_xprofile_create_field_type( 'textbox' );
     33                $this->assertTrue( $field->is_valid( 123 ) );
     34        }
     35
     36        public function test_textbox_validate_whitelisted_string() {
     37                $field = bp_xprofile_create_field_type( 'textbox' );
     38
     39                $this->assertTrue( $field->is_valid( 'a string' ) );
     40                $this->assertFalse( $field->set_whitelist_values( 'pizza' )->is_valid( 'pasta' ) );
     41                $this->assertTrue( $field->is_valid( 'pizza' ) );
     42        }
     43
     44
     45        public function test_multiselectbox_validate_whitelisted_array() {
     46                $field = bp_xprofile_create_field_type( 'multiselectbox' );
     47                $field->set_whitelist_values( array( 'cheese', 'pepporoni' ) );
     48
     49                $this->assertTrue( $field->is_valid( array( 'cheese', 'pepporoni' ) ) );
     50                $this->assertTrue( $field->is_valid( array( 'cheese' ) ) );
     51                $this->assertFalse( $field->is_valid( array( 'cheese', 'pepporoni', 'pinapple' ) ) );
     52                $this->assertFalse( $field->is_valid( array( 'pinapple' ) ) );
     53        }
     54
     55        public function test_multiselectbox_validate_null_value() {
     56                $field = bp_xprofile_create_field_type( 'multiselectbox' );
     57                $field->set_whitelist_values( array( 'cheese', 'pepporoni' ) );
     58
     59                $this->assertFalse( $field->is_valid( array( '' ) ) );
     60                $this->assertFalse( $field->is_valid( '' ) );
     61                $this->assertTrue( $field->is_valid( array() ) );
     62        }
     63
     64
     65        public function test_datebox_do_not_validate_string() {
     66                $field = bp_xprofile_create_field_type( 'datebox' );
     67                $this->assertFalse( $field->is_valid( 'datebox fields only accept strings in: Y-m-d 00:00:00' ) );
     68                $this->assertFalse( $field->is_valid( '' ) );
     69        }
     70
     71        public function test_datebox_do_not_validate_integer() {
     72                $field = bp_xprofile_create_field_type( 'datebox' );
     73                $this->assertFalse( $field->is_valid( 221213 ) );
     74        }
     75
     76        public function test_datebox_validate_date() {
     77                $field = bp_xprofile_create_field_type( 'datebox' );
     78                $this->assertTrue( $field->is_valid( '2013-12-22 00:00:00' ) );
     79        }
     80
     81        public function test_datebox_do_not_validate_date_with_timestamp() {
     82                $field = bp_xprofile_create_field_type( 'datebox' );
     83                $this->assertFalse( $field->is_valid( '2013-12-22 19:11:30' ) );
     84                $this->assertFalse( $field->is_valid( '2013-12-22' ) );
     85        }
     86
     87
     88        public function test_number_do_not_validate_string() {
     89                $field = bp_xprofile_create_field_type( 'number' );
     90                $this->assertFalse( $field->is_valid( 'telephone fields only accept integers' ) );
     91                $this->assertFalse( $field->is_valid( '' ) );
     92        }
     93
     94        public function test_number_validate_integer() {
     95                $field = bp_xprofile_create_field_type( 'number' );
     96                $this->assertTrue( $field->is_valid( 12345678901 ) );
     97        }
     98
     99
     100        public function test_radiobutton_validate_whitelisted_array() {
     101                $field = bp_xprofile_create_field_type( 'radio' );
     102                $field->set_whitelist_values( array( 'cheese', 'pepporoni' ) );
     103
     104                $this->assertTrue( $field->is_valid( array( 'cheese', 'pepporoni' ) ) );
     105                $this->assertTrue( $field->is_valid( array( 'cheese' ) ) );
     106                $this->assertFalse( $field->is_valid( array( 'cheese', 'pepporoni', 'pinapple' ) ) );
     107                $this->assertFalse( $field->is_valid( array( 'pinapple' ) ) );
     108                $this->assertFalse( $field->is_valid( '' ) );
     109        }
     110
     111        public function test_radiobutton_do_not_validate_empty_items_in_whitelist() {
     112                $field = bp_xprofile_create_field_type( 'radio' );
     113                $field->set_whitelist_values( array( '' ) );
     114
     115                $this->assertFalse( $field->is_valid( array( '' ) ) );
     116        }
     117
     118
     119        public function test_checkbox_validate_whitelisted_array() {
     120                $field = bp_xprofile_create_field_type( 'checkbox' );
     121                $field->set_whitelist_values( array( 'cheese', 'pepporoni' ) );
     122
     123                $this->assertTrue( $field->is_valid( array( 'cheese', 'pepporoni' ) ) );
     124                $this->assertTrue( $field->is_valid( array( 'cheese' ) ) );
     125                $this->assertFalse( $field->is_valid( array( 'cheese', 'pepporoni', 'pinapple' ) ) );
     126                $this->assertFalse( $field->is_valid( array( 'pinapple' ) ) );
     127                $this->assertFalse( $field->is_valid( '' ) );
     128        }
     129
     130        public function test_checkbox_validate_null_value() {
     131                $field = bp_xprofile_create_field_type( 'checkbox' );
     132                $field->set_whitelist_values( array( 'cheese', 'pepporoni' ) );
     133
     134                $this->assertFalse( $field->is_valid( array( '' ) ) );
     135                $this->assertFalse( $field->is_valid( '' ) );
     136                $this->assertTrue( $field->is_valid( array() ) );
     137        }
     138}