Skip to:
Content

BuddyPress.org

Changeset 10254


Ignore:
Timestamp:
10/12/2015 05:50:45 PM (11 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.