Make WordPress Core


Ignore:
Timestamp:
09/10/2017 06:32:34 AM (8 years ago)
Author:
westonruter
Message:

Widgets: Add shortcode support inside Text widgets.

  • Used now in core to facilitate displaying inserted media. See #40854.
  • The [embed] shortcode is not supported because there is no post context for caching oEmbed responses. This depends on #34115.
  • Add do_shortcode() to the widget_text_content filter in the same way it is added for the_content at priority 11, with shortcode_unautop() called at priority 10 after wpautop().
  • For Text widget in legacy mode, manually apply do_shortcode() (and shortcode_unautop() if auto-paragraph checked) if the core-added widget_text_content filter remains, unless a plugin added do_shortcode() to widget_text to prevent applying shortcodes twice.
  • Ensure that global $post is null while filters apply in the Text widget so shortcode handlers won't run with unexpected contexts.

Props westonruter, nacin, aaroncampbell.
See #40854, #34115.
Fixes #10457.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/widgets/class-wp-widget-text.php

    r41260 r41361  
    184184     * @since 2.8.0
    185185     *
     186     * @global WP_Post $post
     187     *
    186188     * @param array $args     Display arguments including 'before_title', 'after_title',
    187189     *                        'before_widget', and 'after_widget'.
     
    189191     */
    190192    public function widget( $args, $instance ) {
     193        global $post;
    191194
    192195        /** This filter is documented in wp-includes/widgets/class-wp-widget-pages.php */
     
    206209
    207210        /*
    208          * Just-in-time temporarily upgrade Visual Text widget shortcode handling
    209          * (with support added by plugin) from the widget_text filter to
    210          * widget_text_content:11 to prevent wpautop from corrupting HTML output
    211          * added by the shortcode.
     211         * Suspend legacy plugin-supplied do_shortcode() for 'widget_text' filter for the visual Text widget to prevent
     212         * shortcodes being processed twice. Now do_shortcode() is added to the 'widget_text_content' filter in core itself
     213         * and it applies after wpautop() to prevent corrupting HTML output added by the shortcode. When do_shortcode() is
     214         * added to 'widget_text_content' then do_shortcode() will be manually called when in legacy mode as well.
    212215         */
    213216        $widget_text_do_shortcode_priority = has_filter( 'widget_text', 'do_shortcode' );
    214         $should_upgrade_shortcode_handling = ( $is_visual_text_widget && false !== $widget_text_do_shortcode_priority );
    215         if ( $should_upgrade_shortcode_handling ) {
     217        $should_suspend_legacy_shortcode_support = ( $is_visual_text_widget && false !== $widget_text_do_shortcode_priority );
     218        if ( $should_suspend_legacy_shortcode_support ) {
    216219            remove_filter( 'widget_text', 'do_shortcode', $widget_text_do_shortcode_priority );
    217             add_filter( 'widget_text_content', 'do_shortcode', 11 );
     220        }
     221
     222        // Nullify the $post global during widget rendering to prevent shortcodes from running with the unexpected context.
     223        $suspended_post = null;
     224        if ( isset( $post ) ) {
     225            $suspended_post = $post;
     226            $post = null;
    218227        }
    219228
     
    245254             */
    246255            $text = apply_filters( 'widget_text_content', $text, $instance, $this );
    247 
    248         } elseif ( ! empty( $instance['filter'] ) ) {
    249             $text = wpautop( $text ); // Back-compat for instances prior to 4.8.
    250         }
    251 
    252         // Undo temporary upgrade of the plugin-supplied shortcode handling.
    253         if ( $should_upgrade_shortcode_handling ) {
    254             remove_filter( 'widget_text_content', 'do_shortcode', 11 );
     256        } else {
     257            // Now in legacy mode, add paragraphs and line breaks when checkbox is checked.
     258            if ( ! empty( $instance['filter'] ) ) {
     259                $text = wpautop( $text );
     260            }
     261
     262            /*
     263             * Manually do shortcodes on the content when the core-added filter is present. It is added by default
     264             * in core by adding do_shortcode() to the 'widget_text_content' filter to apply after wpautop().
     265             * Since the legacy Text widget runs wpautop() after 'widget_text' filters are applied, the widget in
     266             * legacy mode here manually applies do_shortcode() on the content unless the default
     267             * core filter for 'widget_text_content' has been removed, or if do_shortcode() has already
     268             * been applied via a plugin adding do_shortcode() to 'widget_text' filters.
     269             */
     270            if ( has_filter( 'widget_text_content', 'do_shortcode' ) && ! $widget_text_do_shortcode_priority ) {
     271                if ( ! empty( $instance['filter'] ) ) {
     272                    $text = shortcode_unautop( $text );
     273                }
     274                $text = do_shortcode( $text );
     275            }
     276        }
     277
     278        // Restore post global.
     279        if ( isset( $suspended_post ) ) {
     280            $post = $suspended_post;
     281        }
     282
     283        // Undo suspension of legacy plugin-supplied shortcode handling.
     284        if ( $should_suspend_legacy_shortcode_support ) {
    255285            add_filter( 'widget_text', 'do_shortcode', $widget_text_do_shortcode_priority );
    256286        }
Note: See TracChangeset for help on using the changeset viewer.