Ticket #33901: 33901.2.diff
File 33901.2.diff, 16.5 KB (added by , 10 years ago) |
---|
-
src/wp-admin/includes/widgets.php
diff --git src/wp-admin/includes/widgets.php src/wp-admin/includes/widgets.php index 356970f..19fd390 100644
function wp_widget_control( $sidebar_args ) { 181 181 $multi_number = isset($sidebar_args['_multi_num']) ? $sidebar_args['_multi_num'] : ''; 182 182 $add_new = isset($sidebar_args['_add']) ? $sidebar_args['_add'] : ''; 183 183 184 $before_form = isset( $sidebar_args['before_form'] ) ? $sidebar_args['before_form'] : '<form method="post">'; 185 $after_form = isset( $sidebar_args['after_form'] ) ? $sidebar_args['after_form'] : '</form>'; 186 $before_widget_content = isset( $sidebar_args['before_widget_content'] ) ? $sidebar_args['before_widget_content'] : '<div class="widget-content">'; 187 $after_widget_content = isset( $sidebar_args['after_widget_content'] ) ? $sidebar_args['after_widget_content'] : '</div>'; 188 184 189 $query_arg = array( 'editwidget' => $widget['id'] ); 185 190 if ( $add_new ) { 186 191 $query_arg['addnew'] = 1; … … function wp_widget_control( $sidebar_args ) { 225 230 </div> 226 231 227 232 <div class="widget-inside"> 228 < form method="post">229 < div class="widget-content">230 <?php231 if ( isset( $control['callback']) )233 <?php echo $before_form; ?> 234 <?php echo $before_widget_content; ?> 235 <?php 236 if ( isset( $control['callback'] ) ) { 232 237 $has_form = call_user_func_array( $control['callback'], $control['params'] ); 233 else 234 echo "\t\t<p>" . __('There are no options for this widget.') . "</p>\n"; ?> 235 </div> 238 } else { 239 echo "\t\t<p>" . __('There are no options for this widget.') . "</p>\n"; 240 } 241 ?> 242 <?php echo $after_widget_content; ?> 236 243 <input type="hidden" name="widget-id" class="widget-id" value="<?php echo esc_attr($id_format); ?>" /> 237 244 <input type="hidden" name="id_base" class="id_base" value="<?php echo esc_attr($id_base); ?>" /> 238 245 <input type="hidden" name="widget-width" class="widget-width" value="<?php if (isset( $control['width'] )) echo esc_attr($control['width']); ?>" /> … … function wp_widget_control( $sidebar_args ) { 252 259 </div> 253 260 <br class="clear" /> 254 261 </div> 255 < /form>262 <?php echo $after_form; ?> 256 263 </div> 257 264 258 265 <div class="widget-description"> -
src/wp-admin/js/customize-widgets.js
diff --git src/wp-admin/js/customize-widgets.js src/wp-admin/js/customize-widgets.js index 6a640e0..8edc02c 100644
417 417 /** 418 418 * @since 4.1.0 419 419 */ 420 initialize: function 420 initialize: function( id, options ) { 421 421 var control = this; 422 api.Control.prototype.initialize.call( control, id, options ); 423 control.expanded = new api.Value(); 422 423 control.widgetControlEmbedded = false; 424 control.widgetContentEmbedded = false; 425 control.expanded = new api.Value( false ); 424 426 control.expandedArgumentsQueue = []; 425 control.expanded.bind( function 427 control.expanded.bind( function( expanded ) { 426 428 var args = control.expandedArgumentsQueue.shift(); 427 429 args = $.extend( {}, control.defaultExpandedArguments, args ); 428 430 control.onChangeExpanded( expanded, args ); 429 431 }); 430 control.expanded.set( false ); 432 433 api.Control.prototype.initialize.call( control, id, options ); 431 434 }, 432 435 433 436 /** 434 * Set up the control 437 * Set up the control. 438 * 439 * @since 3.9.0 435 440 */ 436 441 ready: function() { 437 this._setupModel(); 438 this._setupWideWidget(); 439 this._setupControlToggle(); 440 this._setupWidgetTitle(); 441 this._setupReorderUI(); 442 this._setupHighlightEffects(); 443 this._setupUpdateUI(); 444 this._setupRemoveUI(); 442 var control = this; 443 444 /* 445 * Embed a placeholder once the section is expanded. The full widget 446 * form content will be embedded once the control itself is expanded, 447 * and at this point the widget-added event will be triggered. 448 */ 449 if ( ! control.section() ) { 450 control.embedWidgetControl(); 451 } else { 452 api.section( control.section(), function( section ) { 453 var onExpanded = function( isExpanded ) { 454 if ( isExpanded ) { 455 control.embedWidgetControl(); 456 section.expanded.unbind( onExpanded ); 457 } 458 }; 459 if ( section.expanded() ) { 460 onExpanded( true ); 461 } else { 462 section.expanded.bind( onExpanded ); 463 } 464 } ); 465 } 466 }, 467 468 /** 469 * Embed the .widget element inside the li container. 470 * 471 * @since 4.4.0 472 */ 473 embedWidgetControl: function() { 474 var control = this, widgetControl; 475 476 if ( control.widgetControlEmbedded ) { 477 return; 478 } 479 control.widgetControlEmbedded = true; 480 481 widgetControl = $( control.params.widget_control ); 482 control.container.append( widgetControl ); 483 484 control._setupModel(); 485 control._setupWideWidget(); 486 control._setupControlToggle(); 487 488 control._setupWidgetTitle(); 489 control._setupReorderUI(); 490 control._setupHighlightEffects(); 491 control._setupUpdateUI(); 492 control._setupRemoveUI(); 493 }, 494 495 /** 496 * Embed the actual widget form inside of .widget-content and finally trigger the widget-added event. 497 * 498 * @since 4.4.0 499 */ 500 embedWidgetContent: function() { 501 var control = this, widgetContent; 502 503 control.embedWidgetControl(); 504 if ( control.widgetContentEmbedded ) { 505 return; 506 } 507 control.widgetContentEmbedded = true; 508 509 widgetContent = $( control.params.widget_content ); 510 control.container.find( '.widget-content:first' ).append( widgetContent ); 445 511 446 512 /* 447 513 * Trigger widget-added event so that plugins can attach any event 448 514 * listeners and dynamic UI elements. 449 515 */ 450 $( document ).trigger( 'widget-added', [ this.container.find( '.widget:first' ) ] ); 516 $( document ).trigger( 'widget-added', [ control.container.find( '.widget:first' ) ] ); 517 451 518 }, 452 519 453 520 /** … … 1008 1075 var self = this, instanceOverride, completeCallback, $widgetRoot, $widgetContent, 1009 1076 updateNumber, params, data, $inputs, processing, jqxhr, isChanged; 1010 1077 1078 // The updateWidget logic requires that the form fields to be fully present. 1079 self.embedWidgetContent(); 1080 1011 1081 args = $.extend( { 1012 1082 instance: null, 1013 1083 complete: null, … … 1255 1325 onChangeExpanded: function ( expanded, args ) { 1256 1326 var self = this, $widget, $inside, complete, prevComplete; 1257 1327 1328 self.embedWidgetControl(); // Make sure the outer form is embedded so that the expanded state can be set in the UI. 1329 if ( expanded ) { 1330 self.embedWidgetContent(); 1331 } 1332 1258 1333 // If the expanded state is unchanged only manipulate container expanded states 1259 1334 if ( args.unchanged ) { 1260 1335 if ( expanded ) { -
src/wp-includes/class-wp-customize-control.php
diff --git src/wp-includes/class-wp-customize-control.php src/wp-includes/class-wp-customize-control.php index f105ab1..b6ffa1a 100644
class WP_Widget_Form_Customize_Control extends WP_Customize_Control { 1487 1487 public $height; 1488 1488 public $is_wide = false; 1489 1489 1490 /** 1491 * Gather control params for exporting to JavaScript. 1492 * 1493 * @global array $wp_registered_widgets 1494 */ 1490 1495 public function to_json() { 1496 global $wp_registered_widgets; 1497 1491 1498 parent::to_json(); 1492 1499 $exported_properties = array( 'widget_id', 'widget_id_base', 'sidebar_id', 'width', 'height', 'is_wide' ); 1493 1500 foreach ( $exported_properties as $key ) { 1494 1501 $this->json[ $key ] = $this->$key; 1495 1502 } 1496 }1497 1503 1498 /** 1499 * 1500 * @global array $wp_registered_widgets 1501 */ 1502 public function render_content() { 1503 global $wp_registered_widgets; 1504 // Get the widget_control and widget_content. 1504 1505 require_once ABSPATH . '/wp-admin/includes/widgets.php'; 1505 1506 1506 1507 $widget = $wp_registered_widgets[ $this->widget_id ]; … … class WP_Widget_Form_Customize_Control extends WP_Customize_Control { 1514 1515 ); 1515 1516 1516 1517 $args = wp_list_widget_controls_dynamic_sidebar( array( 0 => $args, 1 => $widget['params'][0] ) ); 1517 echo $this->manager->widgets->get_widget_control( $args ); 1518 $widget_control_parts = $this->manager->widgets->get_widget_control_parts( $args ); 1519 1520 $this->json['widget_control'] = $widget_control_parts['control']; 1521 $this->json['widget_content'] = $widget_control_parts['content']; 1518 1522 } 1519 1523 1520 1524 /** 1525 * Override render_content to be no-op since content is exported via to_json for deferred embedding. 1526 */ 1527 public function render_content() {} 1528 1529 /** 1521 1530 * Whether the current widget is rendered on the page. 1522 1531 * 1523 1532 * @since 4.0.0 -
src/wp-includes/class-wp-customize-widgets.php
diff --git src/wp-includes/class-wp-customize-widgets.php src/wp-includes/class-wp-customize-widgets.php index 8569228..a003393 100644
final class WP_Customize_Widgets { 898 898 * @return string Widget control form HTML markup. 899 899 */ 900 900 public function get_widget_control( $args ) { 901 $args[0]['before_form'] = '<div class="form">'; 902 $args[0]['after_form'] = '</div><!-- .form -->'; 903 $args[0]['before_widget_content'] = '<div class="widget-content">'; 904 $args[0]['after_widget_content'] = '</div><!-- .widget-content -->'; 901 905 ob_start(); 902 903 906 call_user_func_array( 'wp_widget_control', $args ); 904 $replacements = array(905 '<form method="post">' => '<div class="form">',906 '</form>' => '</div><!-- .form -->',907 );908 909 907 $control_tpl = ob_get_clean(); 908 return $control_tpl; 909 } 910 910 911 $control_tpl = str_replace( array_keys( $replacements ), array_values( $replacements ), $control_tpl ); 911 /** 912 * Get the widget control markup parts. 913 * 914 * @since 4.4.0 915 * @access public 916 * 917 * @param array $args Widget control arguments. 918 * @return array { 919 * @type string $control Markup for widget control wrapping form. 920 * @type string $content The contents of the widget form itself. 921 * } 922 */ 923 public function get_widget_control_parts( $args ) { 924 $args[0]['before_widget_content'] = '<div class="widget-content">'; 925 $args[0]['after_widget_content'] = '</div><!-- .widget-content -->'; 926 $control_markup = $this->get_widget_control( $args ); 927 928 $content_start_pos = strpos( $control_markup, $args[0]['before_widget_content'] ); 929 $content_end_pos = strrpos( $control_markup, $args[0]['after_widget_content'] ); 930 931 $control = substr( $control_markup, 0, $content_start_pos + strlen( $args[0]['before_widget_content'] ) ); 932 $control .= substr( $control_markup, $content_end_pos ); 933 $content = trim( substr( 934 $control_markup, 935 $content_start_pos + strlen( $args[0]['before_widget_content'] ), 936 $content_end_pos - $content_start_pos - strlen( $args[0]['before_widget_content'] ) 937 ) ); 912 938 913 return $control_tpl;939 return compact( 'control', 'content' ); 914 940 } 915 941 916 942 /** -
tests/phpunit/tests/customize/widgets.php
diff --git tests/phpunit/tests/customize/widgets.php tests/phpunit/tests/customize/widgets.php index 9f30b94..50aab18 100644
class Tests_WP_Customize_Widgets extends WP_UnitTestCase { 195 195 $unsanitized_from_js = $this->manager->widgets->sanitize_widget_instance( $sanitized_for_js ); 196 196 $this->assertEquals( $unsanitized_from_js, $new_categories_instance ); 197 197 } 198 199 /** 200 * Get the widget control args for tests. 201 * 202 * @return array 203 */ 204 function get_test_widget_control_args() { 205 global $wp_registered_widgets; 206 require_once ABSPATH . '/wp-admin/includes/widgets.php'; 207 $widget_id = 'search-2'; 208 $widget = $wp_registered_widgets[ $widget_id ]; 209 $args = array( 210 'widget_id' => $widget['id'], 211 'widget_name' => $widget['name'], 212 ); 213 $args = wp_list_widget_controls_dynamic_sidebar( array( 0 => $args, 1 => $widget['params'][0] ) ); 214 return $args; 215 } 216 217 /** 218 * @see WP_Customize_Widgets::get_widget_control() 219 */ 220 function test_get_widget_control() { 221 $this->do_customize_boot_actions(); 222 $widget_control = $this->manager->widgets->get_widget_control( $this->get_test_widget_control_args() ); 223 224 $this->assertContains( '<div class="form">', $widget_control ); 225 $this->assertContains( '<div class="widget-content">', $widget_control ); 226 $this->assertContains( '<input type="hidden" name="id_base" class="id_base" value="search"', $widget_control ); 227 $this->assertContains( '<input class="widefat"', $widget_control ); 228 } 229 230 /** 231 * @see WP_Customize_Widgets::get_widget_control_parts() 232 */ 233 function test_get_widget_control_parts() { 234 $this->do_customize_boot_actions(); 235 $widget_control_parts = $this->manager->widgets->get_widget_control_parts( $this->get_test_widget_control_args() ); 236 $this->assertArrayHasKey( 'content', $widget_control_parts ); 237 $this->assertArrayHasKey( 'control', $widget_control_parts ); 238 239 $this->assertContains( '<div class="form">', $widget_control_parts['control'] ); 240 $this->assertContains( '<div class="widget-content">', $widget_control_parts['control'] ); 241 $this->assertContains( '<input type="hidden" name="id_base" class="id_base" value="search"', $widget_control_parts['control'] ); 242 $this->assertNotContains( '<input class="widefat"', $widget_control_parts['control'] ); 243 $this->assertContains( '<input class="widefat"', $widget_control_parts['content'] ); 244 } 245 246 /** 247 * @see WP_Widget_Form_Customize_Control::json() 248 */ 249 function test_wp_widget_form_customize_control_json() { 250 $this->do_customize_boot_actions(); 251 $control = $this->manager->get_control( 'widget_search[2]' ); 252 $params = $control->json(); 253 254 $this->assertEquals( 'widget_form', $params['type'] ); 255 $this->assertRegExp( '#^<li[^>]+>\s+</li>$#', $params['content'] ); 256 $this->assertRegExp( '#^<div[^>]*class=\'widget\'[^>]*#s', $params['widget_control'] ); 257 $this->assertContains( '<div class="widget-content"></div>', $params['widget_control'] ); 258 $this->assertNotContains( '<input class="widefat"', $params['widget_control'] ); 259 $this->assertContains( '<input class="widefat"', $params['widget_content'] ); 260 $this->assertEquals( 'search-2', $params['widget_id'] ); 261 $this->assertEquals( 'search', $params['widget_id_base'] ); 262 $this->assertArrayHasKey( 'sidebar_id', $params ); 263 $this->assertArrayHasKey( 'width', $params ); 264 $this->assertArrayHasKey( 'height', $params ); 265 $this->assertInternalType( 'bool', $params['is_wide'] ); 266 267 } 198 268 } -
tests/phpunit/tests/widgets.php
diff --git tests/phpunit/tests/widgets.php tests/phpunit/tests/widgets.php index 443d3f3..c0dfe08 100644
class Tests_Widgets extends WP_UnitTestCase { 293 293 $this->assertArrayNotHasKey( 2, $option_value ); 294 294 } 295 295 296 /** 297 * @see wp_widget_control() 298 */ 299 function test_wp_widget_control() { 300 global $wp_registered_widgets; 301 302 wp_widgets_init(); 303 require_once ABSPATH . '/wp-admin/includes/widgets.php'; 304 $widget_id = 'search-2'; 305 $widget = $wp_registered_widgets[ $widget_id ]; 306 $params = array( 307 'widget_id' => $widget['id'], 308 'widget_name' => $widget['name'], 309 ); 310 $args = wp_list_widget_controls_dynamic_sidebar( array( 0 => $params, 1 => $widget['params'][0] ) ); 311 312 ob_start(); 313 call_user_func_array( 'wp_widget_control', $args ); 314 $control = ob_get_clean(); 315 $this->assertNotEmpty( $control ); 316 317 $this->assertContains( '<div class="widget-top">', $control ); 318 $this->assertContains( '<div class="widget-title-action">', $control ); 319 $this->assertContains( '<div class="widget-title">', $control ); 320 $this->assertContains( '<form method="post">', $control ); 321 $this->assertContains( '<div class="widget-content">', $control ); 322 $this->assertContains( '<input class="widefat"', $control ); 323 $this->assertContains( '<input type="hidden" name="id_base" class="id_base" value="search"', $control ); 324 $this->assertContains( '<div class="widget-control-actions">', $control ); 325 $this->assertContains( '<div class="alignleft">', $control ); 326 $this->assertContains( 'widget-control-remove', $control ); 327 $this->assertContains( 'widget-control-close', $control ); 328 $this->assertContains( '<div class="alignright">', $control ); 329 $this->assertContains( '<input type="submit" name="savewidget"', $control ); 330 331 $param_overrides = array( 332 'before_form' => '<!-- before_form -->', 333 'after_form' => '<!-- after_form -->', 334 'before_widget_content' => '<!-- before_widget_content -->', 335 'after_widget_content' => '<!-- after_widget_content -->', 336 ); 337 $params = array_merge( $params, $param_overrides ); 338 $args = wp_list_widget_controls_dynamic_sidebar( array( 0 => $params, 1 => $widget['params'][0] ) ); 339 340 ob_start(); 341 call_user_func_array( 'wp_widget_control', $args ); 342 $control = ob_get_clean(); 343 $this->assertNotEmpty( $control ); 344 $this->assertNotContains( '<form method="post">', $control ); 345 $this->assertNotContains( '<div class="widget-content">', $control ); 346 347 foreach ( $param_overrides as $contained ) { 348 $this->assertContains( $contained, $control ); 349 } 350 } 351 296 352 }