Skip to content

Commit 0cfe1b9

Browse files
committed
Widgets: Rename Text widget's legacy mode to non-visual mode, restore boolean filter prop, and improve compatibility for widget_text filters applied in Custom HTML widget.
Props westonruter, obenland, timmydcrawford for testing. Amends [41050]. See #35243, #40951, #40907. Fixes #41394. git-svn-id: https://develop.svn.wordpress.org/trunk@41132 602fd350-edb4-49c9-b593-d223f7449a82
1 parent 0fdf7fd commit 0cfe1b9

5 files changed

Lines changed: 340 additions & 89 deletions

File tree

src/wp-admin/js/widgets/text-widgets.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -368,7 +368,7 @@ wp.textWidgets = ( function( $ ) {
368368
}
369369

370370
// Bypass using TinyMCE when widget is in legacy mode.
371-
if ( widgetForm.find( '.legacy' ).length > 0 ) {
371+
if ( ! widgetForm.find( '.visual' ).val() ) {
372372
return;
373373
}
374374

@@ -429,7 +429,7 @@ wp.textWidgets = ( function( $ ) {
429429
}
430430

431431
// Bypass using TinyMCE when widget is in legacy mode.
432-
if ( widgetForm.find( '.legacy' ).length > 0 ) {
432+
if ( ! widgetForm.find( '.visual' ).val() ) {
433433
return;
434434
}
435435

src/wp-includes/widgets/class-wp-widget-custom-html.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,16 @@ public function widget( $args, $instance ) {
6161
/** This filter is documented in wp-includes/widgets/class-wp-widget-pages.php */
6262
$title = apply_filters( 'widget_title', $instance['title'], $instance, $this->id_base );
6363

64+
// Prepare instance data that looks like a normal Text widget.
65+
$simulated_text_widget_instance = array_merge( $instance, array(
66+
'text' => isset( $instance['content'] ) ? $instance['content'] : '',
67+
'filter' => false, // Because wpautop is not applied.
68+
'visual' => false, // Because it wasn't created in TinyMCE.
69+
) );
70+
unset( $simulated_text_widget_instance['content'] ); // Was moved to 'text' prop.
71+
6472
/** This filter is documented in wp-includes/widgets/class-wp-widget-text.php */
65-
$content = apply_filters( 'widget_text', $instance['content'], $instance, $this );
73+
$content = apply_filters( 'widget_text', $instance['content'], $simulated_text_widget_instance, $this );
6674

6775
/**
6876
* Filters the content of the Custom HTML widget.

src/wp-includes/widgets/class-wp-widget-text.php

Lines changed: 59 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -79,12 +79,12 @@ public function _register_one( $number = -1 ) {
7979
*/
8080
public function is_legacy_instance( $instance ) {
8181

82-
// If the widget has been updated while in legacy mode, it stays in legacy mode.
83-
if ( ! empty( $instance['legacy'] ) ) {
84-
return true;
82+
// Legacy mode when not in visual mode.
83+
if ( isset( $instance['visual'] ) ) {
84+
return ! $instance['visual'];
8585
}
8686

87-
// If the widget has been added/updated in 4.8 then filter prop is 'content' and it is no longer legacy.
87+
// Or, the widget has been added/updated in 4.8.0 then filter prop is 'content' and it is no longer legacy.
8888
if ( isset( $instance['filter'] ) && 'content' === $instance['filter'] ) {
8989
return false;
9090
}
@@ -193,7 +193,16 @@ public function widget( $args, $instance ) {
193193
$title = apply_filters( 'widget_title', empty( $instance['title'] ) ? '' : $instance['title'], $instance, $this->id_base );
194194

195195
$text = ! empty( $instance['text'] ) ? $instance['text'] : '';
196-
$is_visual_text_widget = ( isset( $instance['filter'] ) && 'content' === $instance['filter'] );
196+
$is_visual_text_widget = ( ! empty( $instance['visual'] ) && ! empty( $instance['filter'] ) );
197+
198+
// In 4.8.0 only, visual Text widgets get filter=content, without visual prop; upgrade instance props just-in-time.
199+
if ( ! $is_visual_text_widget ) {
200+
$is_visual_text_widget = ( isset( $instance['filter'] ) && 'content' === $instance['filter'] );
201+
}
202+
if ( $is_visual_text_widget ) {
203+
$instance['filter'] = true;
204+
$instance['visual'] = true;
205+
}
197206

198207
/*
199208
* Just-in-time temporarily upgrade Visual Text widget shortcode handling
@@ -221,25 +230,23 @@ public function widget( $args, $instance ) {
221230
*/
222231
$text = apply_filters( 'widget_text', $text, $instance, $this );
223232

224-
if ( isset( $instance['filter'] ) ) {
225-
if ( 'content' === $instance['filter'] ) {
226-
227-
/**
228-
* Filters the content of the Text widget to apply changes expected from the visual (TinyMCE) editor.
229-
*
230-
* By default a subset of the_content filters are applied, including wpautop and wptexturize.
231-
*
232-
* @since 4.8.0
233-
*
234-
* @param string $text The widget content.
235-
* @param array $instance Array of settings for the current widget.
236-
* @param WP_Widget_Text $this Current Text widget instance.
237-
*/
238-
$text = apply_filters( 'widget_text_content', $text, $instance, $this );
239-
240-
} elseif ( $instance['filter'] ) {
241-
$text = wpautop( $text ); // Back-compat for instances prior to 4.8.
242-
}
233+
if ( $is_visual_text_widget ) {
234+
235+
/**
236+
* Filters the content of the Text widget to apply changes expected from the visual (TinyMCE) editor.
237+
*
238+
* By default a subset of the_content filters are applied, including wpautop and wptexturize.
239+
*
240+
* @since 4.8.0
241+
*
242+
* @param string $text The widget content.
243+
* @param array $instance Array of settings for the current widget.
244+
* @param WP_Widget_Text $this Current Text widget instance.
245+
*/
246+
$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.
243250
}
244251

245252
// Undo temporary upgrade of the plugin-supplied shortcode handling.
@@ -271,28 +278,39 @@ public function widget( $args, $instance ) {
271278
* @return array Settings to save or bool false to cancel saving.
272279
*/
273280
public function update( $new_instance, $old_instance ) {
281+
$new_instance = wp_parse_args( $new_instance, array(
282+
'title' => '',
283+
'text' => '',
284+
'filter' => false, // For back-compat.
285+
'visual' => null, // Must be explicitly defined.
286+
) );
287+
274288
$instance = $old_instance;
289+
275290
$instance['title'] = sanitize_text_field( $new_instance['title'] );
276291
if ( current_user_can( 'unfiltered_html' ) ) {
277292
$instance['text'] = $new_instance['text'];
278293
} else {
279294
$instance['text'] = wp_kses_post( $new_instance['text'] );
280295
}
281296

282-
/*
283-
* If the Text widget is in legacy mode, then a hidden input will indicate this
284-
* and the new content value for the filter prop will by bypassed. Otherwise,
285-
* re-use legacy 'filter' (wpautop) property to now indicate content filters will always apply.
286-
* Prior to 4.8, this is a boolean value used to indicate whether or not wpautop should be
287-
* applied. By re-using this property, downgrading WordPress from 4.8 to 4.7 will ensure
288-
* that the content for Text widgets created with TinyMCE will continue to get wpautop.
289-
*/
290-
if ( isset( $new_instance['legacy'] ) || isset( $old_instance['legacy'] ) || ( isset( $new_instance['filter'] ) && 'content' !== $new_instance['filter'] ) ) {
291-
$instance['filter'] = ! empty( $new_instance['filter'] );
292-
$instance['legacy'] = true;
293-
} else {
294-
$instance['filter'] = 'content';
295-
unset( $instance['legacy'] );
297+
$instance['filter'] = ! empty( $new_instance['filter'] );
298+
299+
// Upgrade 4.8.0 format.
300+
if ( isset( $old_instance['filter'] ) && 'content' === $old_instance['filter'] ) {
301+
$instance['visual'] = true;
302+
}
303+
if ( 'content' === $new_instance['filter'] ) {
304+
$instance['visual'] = true;
305+
}
306+
307+
if ( isset( $new_instance['visual'] ) ) {
308+
$instance['visual'] = ! empty( $new_instance['visual'] );
309+
}
310+
311+
// Filter is always true in visual mode.
312+
if ( ! empty( $instance['visual'] ) ) {
313+
$instance['filter'] = true;
296314
}
297315

298316
return $instance;
@@ -333,8 +351,10 @@ public function form( $instance ) {
333351
<?php if ( ! $this->is_legacy_instance( $instance ) ) : ?>
334352
<input id="<?php echo $this->get_field_id( 'title' ); ?>" name="<?php echo $this->get_field_name( 'title' ); ?>" class="title" type="hidden" value="<?php echo esc_attr( $instance['title'] ); ?>">
335353
<input id="<?php echo $this->get_field_id( 'text' ); ?>" name="<?php echo $this->get_field_name( 'text' ); ?>" class="text" type="hidden" value="<?php echo esc_attr( $instance['text'] ); ?>">
354+
<input id="<?php echo $this->get_field_id( 'filter' ); ?>" name="<?php echo $this->get_field_name( 'filter' ); ?>" class="filter" type="hidden" value="on">
355+
<input id="<?php echo $this->get_field_id( 'visual' ); ?>" name="<?php echo $this->get_field_name( 'visual' ); ?>" class="visual" type="hidden" value="on">
336356
<?php else : ?>
337-
<input name="<?php echo $this->get_field_name( 'legacy' ); ?>" type="hidden" class="legacy" value="true">
357+
<input id="<?php echo $this->get_field_id( 'visual' ); ?>" name="<?php echo $this->get_field_name( 'visual' ); ?>" class="visual" type="hidden" value="">
338358
<p>
339359
<label for="<?php echo $this->get_field_id( 'title' ); ?>"><?php _e( 'Title:' ); ?></label>
340360
<input class="widefat" id="<?php echo $this->get_field_id( 'title' ); ?>" name="<?php echo $this->get_field_name( 'title' ); ?>" type="text" value="<?php echo esc_attr( $instance['title'] ); ?>"/>

tests/phpunit/tests/widgets/custom-html-widget.php

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,14 @@ function test_widget() {
5959
'content' => $content,
6060
);
6161

62+
// Convert Custom HTML widget instance into Text widget instance data.
63+
$text_widget_instance = array_merge( $instance, array(
64+
'text' => $instance['content'],
65+
'filter' => false,
66+
'visual' => false,
67+
) );
68+
unset( $text_widget_instance['content'] );
69+
6270
update_option( 'use_balanceTags', 0 );
6371
add_filter( 'widget_custom_html_content', array( $this, 'filter_widget_custom_html_content' ), 5, 3 );
6472
add_filter( 'widget_text', array( $this, 'filter_widget_text' ), 10, 3 );
@@ -75,11 +83,11 @@ function test_widget() {
7583
$this->assertNotContains( '<p>', $output );
7684
$this->assertNotContains( '<br>', $output );
7785
$this->assertNotContains( '</u>', $output );
78-
$this->assertEquals( $instance, $this->widget_text_args[1] );
86+
$this->assertEquals( $text_widget_instance, $this->widget_text_args[1] );
7987
$this->assertEquals( $instance, $this->widget_custom_html_content_args[1] );
8088
$this->assertSame( $widget, $this->widget_text_args[2] );
8189
$this->assertSame( $widget, $this->widget_custom_html_content_args[2] );
82-
remove_filter( 'widget_custom_html_content', array( $this, 'filter_widget_custom_html_content' ), 5, 3 );
90+
remove_filter( 'widget_custom_html_content', array( $this, 'filter_widget_custom_html_content' ), 5 );
8391
remove_filter( 'widget_text', array( $this, 'filter_widget_text' ), 10 );
8492

8593
update_option( 'use_balanceTags', 1 );

0 commit comments

Comments
 (0)