Skip to:
Content

BuddyPress.org

Changeset 10254


Ignore:
Timestamp:
10/12/2015 05:50:45 PM (4 years ago)
Author:
boonebgorges
Message:

Enable richtext editing for xProfile textarea fields.

Profile fields of the 'textarea' type are now edited using wp_editor().
Output escaping has been modified to whitelist all tags permitted by the
"teeny" version of the wp_editor() interface.

Richtext is enabled for all and only 'textarea' fields:

  • To enable richtext editing for a custom field type, set the supports_richtext property of your BP_XProfile_Field_Type class to true. In these cases, you'll need to provide your own editing markup as well; see the edit_field_html() and admin_field_html() methods of BP_XProfile_Field_Type_Textarea for inspiration.
  • To disable richtext editing for specific 'textarea' fields, filter bp_xprofile_is_richtext_enabled_for_field.

Props needle, boonebgorges.
Fixes #5625.

Location:
trunk
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/bp-templates/bp-legacy/css/buddypress.css

    r10237 r10254  
    841841#buddypress .wp-editor-wrap input[type=button],
    842842#buddypress .wp-editor-wrap input[type=reset] {
    843     padding: 0 10px 1px;
     843    padding: 0 8px 1px;
    844844}
    845845
     
    15851585    margin: 0;
    15861586}
     1587#buddypress .wp-editor-container {
     1588    border: 1px solid #dedede;
     1589}
     1590#buddypress .html-active button.switch-html {
     1591    border-bottom-color: transparent;
     1592    border-bottom-left-radius: 0;
     1593    border-bottom-right-radius: 0;
     1594    background: #f5f5f5;
     1595}
     1596#buddypress .tmce-active button.switch-tmce {
     1597    border-bottom-color: transparent;
     1598    border-bottom-left-radius: 0;
     1599    border-bottom-right-radius: 0;
     1600    background: #f5f5f5;
     1601}
     1602#buddypress .standard-form .wp-editor-container textarea {
     1603    width: 100%;
     1604    padding-top: 0;
     1605    padding-bottom: 0;
     1606}
    15871607
    15881608/*--------------------------------------------------------------
  • trunk/src/bp-templates/bp-legacy/css/twentyfifteen.css

    r10162 r10254  
    17091709}
    17101710
     1711#buddypress .wp-editor-wrap a.button,
     1712#buddypress .wp-editor-wrap button,
     1713#buddypress .wp-editor-wrap input[type=submit],
     1714#buddypress .wp-editor-wrap input[type=button],
     1715#buddypress .wp-editor-wrap input[type=reset] {
     1716    padding: 0 5px 1px;
     1717}
     1718
    17111719#buddypress .standard-form li,
    17121720#buddypress .group-create-form li {
  • trunk/src/bp-templates/bp-legacy/css/twentyfifteen.scss

    r10162 r10254  
    20412041    select {border: 1px solid rgba($border-color, 0.5);}
    20422042
     2043    // Overrides for embedded WP editors.
     2044    .wp-editor-wrap {
     2045        a.button,
     2046        button,
     2047        input[type=submit],
     2048        input[type=button],
     2049        input[type=reset] {
     2050            padding: 0 5px 1px;
     2051        }
     2052    }
     2053
    20432054} // close #buddypress
    20442055
  • trunk/src/bp-xprofile/bp-xprofile-filters.php

    r10239 r10254  
    2424add_filter( 'bp_get_the_profile_field_value',           'force_balance_tags' );
    2525add_filter( 'bp_get_the_profile_field_value',           'make_clickable'     );
    26 add_filter( 'bp_get_the_profile_field_value',           'esc_html',        8 );
     26add_filter( 'bp_get_the_profile_field_value',           'bp_xprofile_escape_field_data', 8, 3 );
    2727add_filter( 'bp_get_the_profile_field_value',           'convert_smilies', 9 );
    2828add_filter( 'bp_get_the_profile_field_value',           'xprofile_filter_format_field_value',         1, 2 );
     
    3131
    3232add_filter( 'bp_get_the_profile_field_edit_value',      'force_balance_tags' );
    33 add_filter( 'bp_get_the_profile_field_edit_value',      'esc_html'          );
     33add_filter( 'bp_get_the_profile_field_edit_value',      'bp_xprofile_escape_field_data', 10, 3 );
    3434
    3535add_filter( 'bp_get_the_profile_group_name',            'stripslashes' );
     
    4040add_filter( 'bp_get_the_profile_field_description',     'stripslashes' );
    4141
    42 add_filter( 'xprofile_get_field_data',                  'wp_filter_kses', 1 );
     42add_filter( 'xprofile_get_field_data',                  'xprofile_filter_kses', 1 );
    4343add_filter( 'xprofile_field_name_before_save',          'wp_filter_kses', 1 );
    4444add_filter( 'xprofile_field_description_before_save',   'wp_filter_kses', 1 );
     
    124124    $xprofile_allowedtags             = $allowedtags;
    125125    $xprofile_allowedtags['a']['rel'] = array();
     126
     127    // If the field supports rich text, we must allow tags that appear in wp_editor().
     128    if ( $data_obj instanceof BP_XProfile_ProfileData && bp_xprofile_is_richtext_enabled_for_field( $data_obj->field_id ) ) {
     129        $richtext_tags = array(
     130            'img'  => array( 'id' => 1, 'class' => 1, 'src' => 1, 'alt' => 1, 'width' => 1, 'height' => 1 ),
     131            'ul'   => array( 'id' => 1, 'class' => 1 ),
     132            'ol'   => array( 'id' => 1, 'class' => 1 ),
     133            'li'   => array( 'id' => 1, 'class' => 1 ),
     134            'span' => array( 'style' => 1 ),
     135            'p'    => array( 'style' => 1 ),
     136        );
     137
     138        $xprofile_allowedtags = array_merge( $allowedtags, $richtext_tags );
     139    }
    126140
    127141    /**
     
    275289    if ( method_exists( $field_type_obj, 'pre_validate_filter' ) ) {
    276290        $value = call_user_func( array( $field_type_obj, 'pre_validate_filter' ), $value );
     291    }
     292
     293    return $value;
     294}
     295
     296/**
     297 * Escape field value for display.
     298 *
     299 * Most field values are simply run through esc_html(). Those that support rich text (by default, `textarea` only)
     300 * are sanitized using kses, which allows a whitelist of HTML tags.
     301 *
     302 * @since 2.4.0
     303 *
     304 * @param string $value      Field value.
     305 * @param string $field_type Field type.
     306 * @param int    $field_id   Field ID.
     307 * @return string
     308 */
     309function bp_xprofile_escape_field_data( $value, $field_type, $field_id ) {
     310    if ( bp_xprofile_is_richtext_enabled_for_field( $field_id ) ) {
     311        // xprofile_filter_kses() expects a BP_XProfile_ProfileData object.
     312        $data_obj = null;
     313        if ( bp_is_user() ) {
     314            $data_obj = new BP_XProfile_ProfileData( $field_id, bp_displayed_user_id() );
     315        }
     316
     317        $value = xprofile_filter_kses( $value, $data_obj );
     318    } else {
     319        $value = esc_html( $value );
    277320    }
    278321
  • trunk/src/bp-xprofile/bp-xprofile-functions.php

    r10233 r10254  
    10211021
    10221022/**
     1023 * Is rich text enabled for this profile field?
     1024 *
     1025 * By default, rich text is enabled for textarea fields and disabled for all other field types.
     1026 *
     1027 * @since 2.4.0
     1028 *
     1029 * @param int $field_id Optional. Default current field ID.
     1030 * @return bool
     1031 */
     1032function bp_xprofile_is_richtext_enabled_for_field( $field_id = null ) {
     1033    if ( ! $field_id ) {
     1034        $field_id = bp_get_the_profile_field_id();
     1035    }
     1036
     1037    $field = xprofile_get_field( $field_id );
     1038
     1039    $enabled = false;
     1040    if ( $field instanceof BP_XProfile_Field ) {
     1041        $enabled = (bool) $field->type_obj->supports_richtext;
     1042    }
     1043
     1044    /**
     1045     * Filters whether richtext is enabled for the given field.
     1046     *
     1047     * @since 2.4.0
     1048     *
     1049     * @param bool $enabled  True if richtext is enabled for the field, otherwise false.
     1050     * @param int  $field_id ID of the field.
     1051     */
     1052    return apply_filters( 'bp_xprofile_is_richtext_enabled_for_field', $enabled, $field_id );
     1053}
     1054
     1055/**
    10231056 * Get visibility levels out of the $bp global.
    10241057 *
  • trunk/src/bp-xprofile/classes/class-bp-xprofile-field-type-textarea.php

    r10179 r10254  
    2727        $this->category = _x( 'Single Fields', 'xprofile field type category', 'buddypress' );
    2828        $this->name     = _x( 'Multi-line Text Area', 'xprofile field type', 'buddypress' );
     29        $this->supports_richtext = true;
    2930
    3031        $this->set_format( '/^.*$/m', 'replace' );
     
    6061        }
    6162
    62         $r = bp_parse_args( $raw_properties, array(
    63             'cols' => 40,
    64             'rows' => 5,
    65         ) ); ?>
     63        $richtext_enabled = bp_xprofile_is_richtext_enabled_for_field(); ?>
    6664
    6765        <label for="<?php bp_the_profile_field_input_name(); ?>">
     
    7371
    7472        /** This action is documented in bp-xprofile/bp-xprofile-classes */
    75         do_action( bp_get_the_profile_field_errors_action() ); ?>
     73        do_action( bp_get_the_profile_field_errors_action() );
    7674
    77         <textarea <?php echo $this->get_edit_field_html_elements( $r ); ?>><?php bp_the_profile_field_edit_value(); ?></textarea>
     75        if ( ! $richtext_enabled ) {
     76            $r = wp_parse_args( $raw_properties, array(
     77                'cols' => 40,
     78                'rows' => 5,
     79            ) );
    7880
    79         <?php
     81            ?>
     82
     83            <textarea <?php echo $this->get_edit_field_html_elements( $r ); ?>><?php bp_the_profile_field_edit_value(); ?></textarea>
     84
     85            <?php
     86
     87        } else {
     88
     89            /**
     90             * Filters the arguments passed to `wp_editor()` in richtext xprofile fields.
     91             *
     92             * @since 2.4.0
     93             *
     94             * @param array $args {
     95             *     Array of optional arguments. See `wp_editor()`.
     96             *     @type bool $teeny         Whether to use the teeny version of TinyMCE. Default true.
     97             *     @type bool $media_buttons Whether to show media buttons. Default false.
     98             *     @type bool $quicktags     Whether to show the quicktags buttons. Default true.
     99             * }
     100             */
     101            $editor_args = apply_filters( 'bp_xprofile_field_type_textarea_editor_args', array(
     102                'teeny'         => true,
     103                'media_buttons' => false,
     104                'quicktags'     => true,
     105            ) );
     106
     107            wp_editor(
     108                bp_get_the_profile_field_edit_value(),
     109                bp_get_the_profile_field_input_name(),
     110                $editor_args
     111            );
     112        }
    80113    }
    81114
     
    90123     */
    91124    public function admin_field_html( array $raw_properties = array() ) {
    92         $r = bp_parse_args( $raw_properties, array(
    93             'cols' => 40,
    94             'rows' => 5,
    95         ) ); ?>
     125        $richtext_enabled = bp_xprofile_is_richtext_enabled_for_field();
    96126
    97         <textarea <?php echo $this->get_edit_field_html_elements( $r ); ?>></textarea>
     127        if ( ! $richtext_enabled ) {
    98128
    99         <?php
     129            $r = bp_parse_args( $raw_properties, array(
     130                'cols' => 40,
     131                'rows' => 5,
     132            ) ); ?>
     133
     134            <textarea <?php echo $this->get_edit_field_html_elements( $r ); ?>></textarea>
     135
     136            <?php
     137        } else {
     138
     139            /** This filter is documented in bp-xprofile/classes/class-bp-xprofile-field-type-textarea.php */
     140            $editor_args = apply_filters( 'bp_xprofile_field_type_textarea_editor_args', array(
     141                'teeny'         => true,
     142                'media_buttons' => false,
     143                'quicktags'     => true,
     144            ) );
     145
     146            wp_editor(
     147                '',
     148                'xprofile_textarea_' . bp_get_the_profile_field_id(),
     149                $editor_args
     150            );
     151        }
    100152    }
    101153
  • trunk/src/bp-xprofile/classes/class-bp-xprofile-field-type.php

    r10203 r10254  
    7272     */
    7373    public $supports_multiple_defaults = false;
     74
     75    /**
     76     * If the field type supports rich text by default.
     77     *
     78     * @since 2.4.0
     79     * @var bool
     80     */
     81    public $supports_richtext = false;
    7482
    7583    /**
  • trunk/tests/phpunit/testcases/xprofile/functions.php

    r10198 r10254  
    914914        $this->assertSame( $num_queries, $wpdb->num_queries );
    915915    }
     916
     917    /**
     918     * @ticket BP5625
     919     */
     920    public function test_bp_xprofie_is_richtext_enabled_for_field_should_default_to_true_for_textareas() {
     921        $g = $this->factory->xprofile_group->create();
     922        $f = $this->factory->xprofile_field->create( array(
     923            'field_group_id' => $g,
     924            'type' => 'textarea',
     925        ) );
     926
     927        $this->assertTrue( bp_xprofile_is_richtext_enabled_for_field( $f ) );
     928    }
     929
     930    /**
     931     * @ticket BP5625
     932     */
     933    public function test_bp_xprofie_is_richtext_enabled_for_field_should_default_to_false_for_non_textareas() {
     934        $g = $this->factory->xprofile_group->create();
     935        $f = $this->factory->xprofile_field->create( array(
     936            'field_group_id' => $g,
     937            'type' => 'radio',
     938        ) );
     939
     940        $this->assertFalse( bp_xprofile_is_richtext_enabled_for_field( $f ) );
     941    }
    916942}
Note: See TracChangeset for help on using the changeset viewer.