wp/wp-includes/class-wp-customize-widgets.php
changeset 18 be944660c56a
parent 16 a86126ab1dd4
child 19 3d72ae0968f4
equal deleted inserted replaced
17:34716fd837a4 18:be944660c56a
   116 		add_action( 'customize_controls_print_scripts', array( $this, 'print_scripts' ) );
   116 		add_action( 'customize_controls_print_scripts', array( $this, 'print_scripts' ) );
   117 		add_action( 'customize_controls_print_footer_scripts', array( $this, 'print_footer_scripts' ) );
   117 		add_action( 'customize_controls_print_footer_scripts', array( $this, 'print_footer_scripts' ) );
   118 		add_action( 'customize_controls_print_footer_scripts', array( $this, 'output_widget_control_templates' ) );
   118 		add_action( 'customize_controls_print_footer_scripts', array( $this, 'output_widget_control_templates' ) );
   119 		add_action( 'customize_preview_init', array( $this, 'customize_preview_init' ) );
   119 		add_action( 'customize_preview_init', array( $this, 'customize_preview_init' ) );
   120 		add_filter( 'customize_refresh_nonces', array( $this, 'refresh_nonces' ) );
   120 		add_filter( 'customize_refresh_nonces', array( $this, 'refresh_nonces' ) );
       
   121 		add_filter( 'should_load_block_editor_scripts_and_styles', array( $this, 'should_load_block_editor_scripts_and_styles' ) );
   121 
   122 
   122 		add_action( 'dynamic_sidebar', array( $this, 'tally_rendered_widgets' ) );
   123 		add_action( 'dynamic_sidebar', array( $this, 'tally_rendered_widgets' ) );
   123 		add_filter( 'is_active_sidebar', array( $this, 'tally_sidebars_via_is_active_sidebar_calls' ), 10, 2 );
   124 		add_filter( 'is_active_sidebar', array( $this, 'tally_sidebars_via_is_active_sidebar_calls' ), 10, 2 );
   124 		add_filter( 'dynamic_sidebar_has_widgets', array( $this, 'tally_sidebars_via_dynamic_sidebar_calls' ), 10, 2 );
   125 		add_filter( 'dynamic_sidebar_has_widgets', array( $this, 'tally_sidebars_via_dynamic_sidebar_calls' ), 10, 2 );
   125 
   126 
   365 	 * @global array $wp_registered_widget_controls
   366 	 * @global array $wp_registered_widget_controls
   366 	 * @global array $wp_registered_sidebars
   367 	 * @global array $wp_registered_sidebars
   367 	 */
   368 	 */
   368 	public function customize_register() {
   369 	public function customize_register() {
   369 		global $wp_registered_widgets, $wp_registered_widget_controls, $wp_registered_sidebars;
   370 		global $wp_registered_widgets, $wp_registered_widget_controls, $wp_registered_sidebars;
       
   371 
       
   372 		$use_widgets_block_editor = wp_use_widgets_block_editor();
   370 
   373 
   371 		add_filter( 'sidebars_widgets', array( $this, 'preview_sidebars_widgets' ), 1 );
   374 		add_filter( 'sidebars_widgets', array( $this, 'preview_sidebars_widgets' ), 1 );
   372 
   375 
   373 		$sidebars_widgets = array_merge(
   376 		$sidebars_widgets = array_merge(
   374 			array( 'wp_inactive_widgets' => array() ),
   377 			array( 'wp_inactive_widgets' => array() ),
   444 				// Add section to contain controls.
   447 				// Add section to contain controls.
   445 				$section_id = sprintf( 'sidebar-widgets-%s', $sidebar_id );
   448 				$section_id = sprintf( 'sidebar-widgets-%s', $sidebar_id );
   446 				if ( $is_active_sidebar ) {
   449 				if ( $is_active_sidebar ) {
   447 
   450 
   448 					$section_args = array(
   451 					$section_args = array(
   449 						'title'       => $wp_registered_sidebars[ $sidebar_id ]['name'],
   452 						'title'      => $wp_registered_sidebars[ $sidebar_id ]['name'],
   450 						'description' => $wp_registered_sidebars[ $sidebar_id ]['description'],
   453 						'priority'   => array_search( $sidebar_id, array_keys( $wp_registered_sidebars ), true ),
   451 						'priority'    => array_search( $sidebar_id, array_keys( $wp_registered_sidebars ), true ),
   454 						'panel'      => 'widgets',
   452 						'panel'       => 'widgets',
   455 						'sidebar_id' => $sidebar_id,
   453 						'sidebar_id'  => $sidebar_id,
       
   454 					);
   456 					);
       
   457 
       
   458 					if ( $use_widgets_block_editor ) {
       
   459 						$section_args['description'] = '';
       
   460 					} else {
       
   461 						$section_args['description'] = $wp_registered_sidebars[ $sidebar_id ]['description'];
       
   462 					}
   455 
   463 
   456 					/**
   464 					/**
   457 					 * Filters Customizer widget section arguments for a given sidebar.
   465 					 * Filters Customizer widget section arguments for a given sidebar.
   458 					 *
   466 					 *
   459 					 * @since 3.9.0
   467 					 * @since 3.9.0
   465 					$section_args = apply_filters( 'customizer_widgets_section_args', $section_args, $section_id, $sidebar_id );
   473 					$section_args = apply_filters( 'customizer_widgets_section_args', $section_args, $section_id, $sidebar_id );
   466 
   474 
   467 					$section = new WP_Customize_Sidebar_Section( $this->manager, $section_id, $section_args );
   475 					$section = new WP_Customize_Sidebar_Section( $this->manager, $section_id, $section_args );
   468 					$this->manager->add_section( $section );
   476 					$this->manager->add_section( $section );
   469 
   477 
   470 					$control           = new WP_Widget_Area_Customize_Control(
   478 					if ( $use_widgets_block_editor ) {
       
   479 						$control = new WP_Sidebar_Block_Editor_Control(
       
   480 							$this->manager,
       
   481 							$setting_id,
       
   482 							array(
       
   483 								'section'     => $section_id,
       
   484 								'sidebar_id'  => $sidebar_id,
       
   485 								'label'       => $section_args['title'],
       
   486 								'description' => $section_args['description'],
       
   487 							)
       
   488 						);
       
   489 					} else {
       
   490 						$control = new WP_Widget_Area_Customize_Control(
       
   491 							$this->manager,
       
   492 							$setting_id,
       
   493 							array(
       
   494 								'section'    => $section_id,
       
   495 								'sidebar_id' => $sidebar_id,
       
   496 								'priority'   => count( $sidebar_widget_ids ), // place 'Add Widget' and 'Reorder' buttons at end.
       
   497 							)
       
   498 						);
       
   499 					}
       
   500 
       
   501 					$this->manager->add_control( $control );
       
   502 
       
   503 					$new_setting_ids[] = $setting_id;
       
   504 				}
       
   505 			}
       
   506 
       
   507 			if ( ! $use_widgets_block_editor ) {
       
   508 				// Add a control for each active widget (located in a sidebar).
       
   509 				foreach ( $sidebar_widget_ids as $i => $widget_id ) {
       
   510 
       
   511 					// Skip widgets that may have gone away due to a plugin being deactivated.
       
   512 					if ( ! $is_active_sidebar || ! isset( $wp_registered_widgets[ $widget_id ] ) ) {
       
   513 						continue;
       
   514 					}
       
   515 
       
   516 					$registered_widget = $wp_registered_widgets[ $widget_id ];
       
   517 					$setting_id        = $this->get_setting_id( $widget_id );
       
   518 					$id_base           = $wp_registered_widget_controls[ $widget_id ]['id_base'];
       
   519 
       
   520 					$control = new WP_Widget_Form_Customize_Control(
   471 						$this->manager,
   521 						$this->manager,
   472 						$setting_id,
   522 						$setting_id,
   473 						array(
   523 						array(
   474 							'section'    => $section_id,
   524 							'label'          => $registered_widget['name'],
   475 							'sidebar_id' => $sidebar_id,
   525 							'section'        => $section_id,
   476 							'priority'   => count( $sidebar_widget_ids ), // place 'Add Widget' and 'Reorder' buttons at end.
   526 							'sidebar_id'     => $sidebar_id,
       
   527 							'widget_id'      => $widget_id,
       
   528 							'widget_id_base' => $id_base,
       
   529 							'priority'       => $i,
       
   530 							'width'          => $wp_registered_widget_controls[ $widget_id ]['width'],
       
   531 							'height'         => $wp_registered_widget_controls[ $widget_id ]['height'],
       
   532 							'is_wide'        => $this->is_wide_widget( $widget_id ),
   477 						)
   533 						)
   478 					);
   534 					);
   479 					$new_setting_ids[] = $setting_id;
       
   480 
       
   481 					$this->manager->add_control( $control );
   535 					$this->manager->add_control( $control );
   482 				}
   536 				}
   483 			}
       
   484 
       
   485 			// Add a control for each active widget (located in a sidebar).
       
   486 			foreach ( $sidebar_widget_ids as $i => $widget_id ) {
       
   487 
       
   488 				// Skip widgets that may have gone away due to a plugin being deactivated.
       
   489 				if ( ! $is_active_sidebar || ! isset( $wp_registered_widgets[ $widget_id ] ) ) {
       
   490 					continue;
       
   491 				}
       
   492 
       
   493 				$registered_widget = $wp_registered_widgets[ $widget_id ];
       
   494 				$setting_id        = $this->get_setting_id( $widget_id );
       
   495 				$id_base           = $wp_registered_widget_controls[ $widget_id ]['id_base'];
       
   496 
       
   497 				$control = new WP_Widget_Form_Customize_Control(
       
   498 					$this->manager,
       
   499 					$setting_id,
       
   500 					array(
       
   501 						'label'          => $registered_widget['name'],
       
   502 						'section'        => $section_id,
       
   503 						'sidebar_id'     => $sidebar_id,
       
   504 						'widget_id'      => $widget_id,
       
   505 						'widget_id_base' => $id_base,
       
   506 						'priority'       => $i,
       
   507 						'width'          => $wp_registered_widget_controls[ $widget_id ]['width'],
       
   508 						'height'         => $wp_registered_widget_controls[ $widget_id ]['height'],
       
   509 						'is_wide'        => $this->is_wide_widget( $widget_id ),
       
   510 					)
       
   511 				);
       
   512 				$this->manager->add_control( $control );
       
   513 			}
   537 			}
   514 		}
   538 		}
   515 
   539 
   516 		if ( $this->manager->settings_previewed() ) {
   540 		if ( $this->manager->settings_previewed() ) {
   517 			foreach ( $new_setting_ids as $new_setting_id ) {
   541 			foreach ( $new_setting_ids as $new_setting_id ) {
   603 			'id_base' => null,
   627 			'id_base' => null,
   604 		);
   628 		);
   605 
   629 
   606 		if ( preg_match( '/^(.+)-(\d+)$/', $widget_id, $matches ) ) {
   630 		if ( preg_match( '/^(.+)-(\d+)$/', $widget_id, $matches ) ) {
   607 			$parsed['id_base'] = $matches[1];
   631 			$parsed['id_base'] = $matches[1];
   608 			$parsed['number']  = intval( $matches[2] );
   632 			$parsed['number']  = (int) $matches[2];
   609 		} else {
   633 		} else {
   610 			// Likely an old single widget.
   634 			// Likely an old single widget.
   611 			$parsed['id_base'] = $widget_id;
   635 			$parsed['id_base'] = $widget_id;
   612 		}
   636 		}
   613 		return $parsed;
   637 		return $parsed;
   626 		if ( ! preg_match( '/^(widget_(.+?))(?:\[(\d+)\])?$/', $setting_id, $matches ) ) {
   650 		if ( ! preg_match( '/^(widget_(.+?))(?:\[(\d+)\])?$/', $setting_id, $matches ) ) {
   627 			return new WP_Error( 'widget_setting_invalid_id' );
   651 			return new WP_Error( 'widget_setting_invalid_id' );
   628 		}
   652 		}
   629 
   653 
   630 		$id_base = $matches[2];
   654 		$id_base = $matches[2];
   631 		$number  = isset( $matches[3] ) ? intval( $matches[3] ) : null;
   655 		$number  = isset( $matches[3] ) ? (int) $matches[3] : null;
   632 
   656 
   633 		return compact( 'id_base', 'number' );
   657 		return compact( 'id_base', 'number' );
   634 	}
   658 	}
   635 
   659 
   636 	/**
   660 	/**
   803 		$wp_scripts->add_data(
   827 		$wp_scripts->add_data(
   804 			'customize-widgets',
   828 			'customize-widgets',
   805 			'data',
   829 			'data',
   806 			sprintf( 'var _wpCustomizeWidgetsSettings = %s;', wp_json_encode( $settings ) )
   830 			sprintf( 'var _wpCustomizeWidgetsSettings = %s;', wp_json_encode( $settings ) )
   807 		);
   831 		);
       
   832 
       
   833 		/*
       
   834 		 * TODO: Update 'wp-customize-widgets' to not rely so much on things in
       
   835 		 * 'customize-widgets'. This will let us skip most of the above and not
       
   836 		 * enqueue 'customize-widgets' which saves bytes.
       
   837 		 */
       
   838 
       
   839 		if ( wp_use_widgets_block_editor() ) {
       
   840 			$block_editor_context = new WP_Block_Editor_Context();
       
   841 
       
   842 			$editor_settings = get_block_editor_settings(
       
   843 				get_legacy_widget_block_editor_settings(),
       
   844 				$block_editor_context
       
   845 			);
       
   846 
       
   847 			wp_add_inline_script(
       
   848 				'wp-customize-widgets',
       
   849 				sprintf(
       
   850 					'wp.domReady( function() {
       
   851 					   wp.customizeWidgets.initialize( "widgets-customizer", %s );
       
   852 					} );',
       
   853 					wp_json_encode( $editor_settings )
       
   854 				)
       
   855 			);
       
   856 
       
   857 			// Preload server-registered block schemas.
       
   858 			wp_add_inline_script(
       
   859 				'wp-blocks',
       
   860 				'wp.blocks.unstable__bootstrapServerSideBlockDefinitions(' . wp_json_encode( get_block_editor_server_block_settings() ) . ');'
       
   861 			);
       
   862 
       
   863 			wp_add_inline_script(
       
   864 				'wp-blocks',
       
   865 				sprintf( 'wp.blocks.setCategories( %s );', wp_json_encode( get_block_categories( $block_editor_context ) ) ),
       
   866 				'after'
       
   867 			);
       
   868 
       
   869 			wp_enqueue_script( 'wp-customize-widgets' );
       
   870 			wp_enqueue_style( 'wp-customize-widgets' );
       
   871 
       
   872 			/** This action is documented in edit-form-blocks.php */
       
   873 			do_action( 'enqueue_block_editor_assets' );
       
   874 		}
   808 	}
   875 	}
   809 
   876 
   810 	/**
   877 	/**
   811 	 * Renders the widget form control templates into the DOM.
   878 	 * Renders the widget form control templates into the DOM.
   812 	 *
   879 	 *
   886 		if ( preg_match( $this->setting_id_patterns['sidebar_widgets'], $id, $matches ) ) {
   953 		if ( preg_match( $this->setting_id_patterns['sidebar_widgets'], $id, $matches ) ) {
   887 			$args['sanitize_callback']    = array( $this, 'sanitize_sidebar_widgets' );
   954 			$args['sanitize_callback']    = array( $this, 'sanitize_sidebar_widgets' );
   888 			$args['sanitize_js_callback'] = array( $this, 'sanitize_sidebar_widgets_js_instance' );
   955 			$args['sanitize_js_callback'] = array( $this, 'sanitize_sidebar_widgets_js_instance' );
   889 			$args['transport']            = current_theme_supports( 'customize-selective-refresh-widgets' ) ? 'postMessage' : 'refresh';
   956 			$args['transport']            = current_theme_supports( 'customize-selective-refresh-widgets' ) ? 'postMessage' : 'refresh';
   890 		} elseif ( preg_match( $this->setting_id_patterns['widget_instance'], $id, $matches ) ) {
   957 		} elseif ( preg_match( $this->setting_id_patterns['widget_instance'], $id, $matches ) ) {
   891 			$args['sanitize_callback']    = array( $this, 'sanitize_widget_instance' );
   958 			$id_base                      = $matches['id_base'];
   892 			$args['sanitize_js_callback'] = array( $this, 'sanitize_widget_js_instance' );
   959 			$args['sanitize_callback']    = function( $value ) use ( $id_base ) {
       
   960 				return $this->sanitize_widget_instance( $value, $id_base );
       
   961 			};
       
   962 			$args['sanitize_js_callback'] = function( $value ) use ( $id_base ) {
       
   963 				return $this->sanitize_widget_js_instance( $value, $id_base );
       
   964 			};
   893 			$args['transport']            = $this->is_widget_selective_refreshable( $matches['id_base'] ) ? 'postMessage' : 'refresh';
   965 			$args['transport']            = $this->is_widget_selective_refreshable( $matches['id_base'] ) ? 'postMessage' : 'refresh';
   894 		}
   966 		}
   895 
   967 
   896 		$args = array_merge( $args, $overrides );
   968 		$args = array_merge( $args, $overrides );
   897 
   969 
  1107 		$nonces['update-widget'] = wp_create_nonce( 'update-widget' );
  1179 		$nonces['update-widget'] = wp_create_nonce( 'update-widget' );
  1108 		return $nonces;
  1180 		return $nonces;
  1109 	}
  1181 	}
  1110 
  1182 
  1111 	/**
  1183 	/**
       
  1184 	 * Tells the script loader to load the scripts and styles of custom blocks
       
  1185 	 * if the widgets block editor is enabled.
       
  1186 	 *
       
  1187 	 * @since 5.8.0
       
  1188 	 *
       
  1189 	 * @param bool $is_block_editor_screen Current decision about loading block assets.
       
  1190 	 * @return bool Filtered decision about loading block assets.
       
  1191 	 */
       
  1192 	public function should_load_block_editor_scripts_and_styles( $is_block_editor_screen ) {
       
  1193 		if ( wp_use_widgets_block_editor() ) {
       
  1194 			return true;
       
  1195 		}
       
  1196 
       
  1197 		return $is_block_editor_screen;
       
  1198 	}
       
  1199 
       
  1200 	/**
  1112 	 * When previewing, ensures the proper previewing widgets are used.
  1201 	 * When previewing, ensures the proper previewing widgets are used.
  1113 	 *
  1202 	 *
  1114 	 * Because wp_get_sidebars_widgets() gets called early at {@see 'init' } (via
  1203 	 * Because wp_get_sidebars_widgets() gets called early at {@see 'init' } (via
  1115 	 * wp_convert_widget_settings()) and can set global variable `$_wp_sidebars_widgets`
  1204 	 * wp_convert_widget_settings()) and can set global variable `$_wp_sidebars_widgets`
  1116 	 * to the value of `get_option( 'sidebars_widgets' )` before the Customizer preview
  1205 	 * to the value of `get_option( 'sidebars_widgets' )` before the Customizer preview
  1310 	 *
  1399 	 *
  1311 	 * Unserialize the JS-instance for storing in the options. It's important that this filter
  1400 	 * Unserialize the JS-instance for storing in the options. It's important that this filter
  1312 	 * only get applied to an instance *once*.
  1401 	 * only get applied to an instance *once*.
  1313 	 *
  1402 	 *
  1314 	 * @since 3.9.0
  1403 	 * @since 3.9.0
  1315 	 *
  1404 	 * @since 5.8.0 Added the `$id_base` parameter.
  1316 	 * @param array $value Widget instance to sanitize.
  1405 	 *
       
  1406 	 * @global WP_Widget_Factory $wp_widget_factory
       
  1407 	 *
       
  1408 	 * @param array  $value   Widget instance to sanitize.
       
  1409 	 * @param string $id_base Optional. Base of the ID of the widget being sanitized. Default null.
  1317 	 * @return array|void Sanitized widget instance.
  1410 	 * @return array|void Sanitized widget instance.
  1318 	 */
  1411 	 */
  1319 	public function sanitize_widget_instance( $value ) {
  1412 	public function sanitize_widget_instance( $value, $id_base = null ) {
       
  1413 		global $wp_widget_factory;
       
  1414 
  1320 		if ( array() === $value ) {
  1415 		if ( array() === $value ) {
  1321 			return $value;
  1416 			return $value;
  1322 		}
  1417 		}
  1323 
  1418 
  1324 		if ( empty( $value['is_widget_customizer_js_value'] )
  1419 		if ( isset( $value['raw_instance'] ) && $id_base && wp_use_widgets_block_editor() ) {
  1325 			|| empty( $value['instance_hash_key'] )
  1420 			$widget_object = $wp_widget_factory->get_widget_object( $id_base );
  1326 			|| empty( $value['encoded_serialized_instance'] ) ) {
  1421 			if ( ! empty( $widget_object->widget_options['show_instance_in_rest'] ) ) {
       
  1422 				if ( 'block' === $id_base && ! current_user_can( 'unfiltered_html' ) ) {
       
  1423 					/*
       
  1424 					 * The content of the 'block' widget is not filtered on the
       
  1425 					 * fly while editing. Filter the content here to prevent
       
  1426 					 * vulnerabilities.
       
  1427 					 */
       
  1428 					$value['raw_instance']['content'] = wp_kses_post( $value['raw_instance']['content'] );
       
  1429 				}
       
  1430 
       
  1431 				return $value['raw_instance'];
       
  1432 			}
       
  1433 		}
       
  1434 
       
  1435 		if (
       
  1436 			empty( $value['is_widget_customizer_js_value'] ) ||
       
  1437 			empty( $value['instance_hash_key'] ) ||
       
  1438 			empty( $value['encoded_serialized_instance'] )
       
  1439 		) {
  1327 			return;
  1440 			return;
  1328 		}
  1441 		}
  1329 
  1442 
  1330 		$decoded = base64_decode( $value['encoded_serialized_instance'], true );
  1443 		$decoded = base64_decode( $value['encoded_serialized_instance'], true );
  1331 		if ( false === $decoded ) {
  1444 		if ( false === $decoded ) {
  1346 
  1459 
  1347 	/**
  1460 	/**
  1348 	 * Converts a widget instance into JSON-representable format.
  1461 	 * Converts a widget instance into JSON-representable format.
  1349 	 *
  1462 	 *
  1350 	 * @since 3.9.0
  1463 	 * @since 3.9.0
  1351 	 *
  1464 	 * @since 5.8.0 Added the `$id_base` parameter.
  1352 	 * @param array $value Widget instance to convert to JSON.
  1465 	 *
       
  1466 	 * @global WP_Widget_Factory $wp_widget_factory
       
  1467 	 *
       
  1468 	 * @param array  $value   Widget instance to convert to JSON.
       
  1469 	 * @param string $id_base Optional. Base of the ID of the widget being sanitized. Default null.
  1353 	 * @return array JSON-converted widget instance.
  1470 	 * @return array JSON-converted widget instance.
  1354 	 */
  1471 	 */
  1355 	public function sanitize_widget_js_instance( $value ) {
  1472 	public function sanitize_widget_js_instance( $value, $id_base = null ) {
       
  1473 		global $wp_widget_factory;
       
  1474 
  1356 		if ( empty( $value['is_widget_customizer_js_value'] ) ) {
  1475 		if ( empty( $value['is_widget_customizer_js_value'] ) ) {
  1357 			$serialized = serialize( $value );
  1476 			$serialized = serialize( $value );
  1358 
  1477 
  1359 			$value = array(
  1478 			$js_value = array(
  1360 				'encoded_serialized_instance'   => base64_encode( $serialized ),
  1479 				'encoded_serialized_instance'   => base64_encode( $serialized ),
  1361 				'title'                         => empty( $value['title'] ) ? '' : $value['title'],
  1480 				'title'                         => empty( $value['title'] ) ? '' : $value['title'],
  1362 				'is_widget_customizer_js_value' => true,
  1481 				'is_widget_customizer_js_value' => true,
  1363 				'instance_hash_key'             => $this->get_instance_hash_key( $serialized ),
  1482 				'instance_hash_key'             => $this->get_instance_hash_key( $serialized ),
  1364 			);
  1483 			);
  1365 		}
  1484 
       
  1485 			if ( $id_base && wp_use_widgets_block_editor() ) {
       
  1486 				$widget_object = $wp_widget_factory->get_widget_object( $id_base );
       
  1487 				if ( ! empty( $widget_object->widget_options['show_instance_in_rest'] ) ) {
       
  1488 					$js_value['raw_instance'] = (object) $value;
       
  1489 				}
       
  1490 			}
       
  1491 
       
  1492 			return $js_value;
       
  1493 		}
       
  1494 
  1366 		return $value;
  1495 		return $value;
  1367 	}
  1496 	}
  1368 
  1497 
  1369 	/**
  1498 	/**
  1370 	 * Strips out widget IDs for widgets which are no longer registered.
  1499 	 * Strips out widget IDs for widgets which are no longer registered.
  1430 			if ( false === $sanitized_widget_setting ) {
  1559 			if ( false === $sanitized_widget_setting ) {
  1431 				$this->stop_capturing_option_updates();
  1560 				$this->stop_capturing_option_updates();
  1432 				return new WP_Error( 'widget_setting_malformed' );
  1561 				return new WP_Error( 'widget_setting_malformed' );
  1433 			}
  1562 			}
  1434 
  1563 
  1435 			$instance = $this->sanitize_widget_instance( $sanitized_widget_setting );
  1564 			$instance = $this->sanitize_widget_instance( $sanitized_widget_setting, $parsed_id['id_base'] );
  1436 			if ( is_null( $instance ) ) {
  1565 			if ( is_null( $instance ) ) {
  1437 				$this->stop_capturing_option_updates();
  1566 				$this->stop_capturing_option_updates();
  1438 				return new WP_Error( 'widget_setting_unsanitized' );
  1567 				return new WP_Error( 'widget_setting_unsanitized' );
  1439 			}
  1568 			}
  1440 
  1569 
  1496 		 * Override the incoming $_POST['customized'] for a newly-created widget's
  1625 		 * Override the incoming $_POST['customized'] for a newly-created widget's
  1497 		 * setting with the new $instance so that the preview filter currently
  1626 		 * setting with the new $instance so that the preview filter currently
  1498 		 * in place from WP_Customize_Setting::preview() will use this value
  1627 		 * in place from WP_Customize_Setting::preview() will use this value
  1499 		 * instead of the default widget instance value (an empty array).
  1628 		 * instead of the default widget instance value (an empty array).
  1500 		 */
  1629 		 */
  1501 		$this->manager->set_post_value( $setting_id, $this->sanitize_widget_js_instance( $instance ) );
  1630 		$this->manager->set_post_value( $setting_id, $this->sanitize_widget_js_instance( $instance, $parsed_id['id_base'] ) );
  1502 
  1631 
  1503 		// Obtain the widget control with the updated instance in place.
  1632 		// Obtain the widget control with the updated instance in place.
  1504 		ob_start();
  1633 		ob_start();
  1505 		$form = $wp_registered_widget_controls[ $widget_id ];
  1634 		$form = $wp_registered_widget_controls[ $widget_id ];
  1506 		if ( $form ) {
  1635 		if ( $form ) {
  1569 		if ( is_wp_error( $updated_widget ) ) {
  1698 		if ( is_wp_error( $updated_widget ) ) {
  1570 			wp_send_json_error( $updated_widget->get_error_code() );
  1699 			wp_send_json_error( $updated_widget->get_error_code() );
  1571 		}
  1700 		}
  1572 
  1701 
  1573 		$form     = $updated_widget['form'];
  1702 		$form     = $updated_widget['form'];
  1574 		$instance = $this->sanitize_widget_js_instance( $updated_widget['instance'] );
  1703 		$instance = $this->sanitize_widget_js_instance( $updated_widget['instance'], $id_base );
  1575 
  1704 
  1576 		wp_send_json_success( compact( 'form', 'instance' ) );
  1705 		wp_send_json_success( compact( 'form', 'instance' ) );
  1577 	}
  1706 	}
  1578 
  1707 
  1579 	/*
  1708 	/*
  1770 		if ( ! isset( $this->sidebar_instance_count[ $index ] ) ) {
  1899 		if ( ! isset( $this->sidebar_instance_count[ $index ] ) ) {
  1771 			$this->sidebar_instance_count[ $index ] = 0;
  1900 			$this->sidebar_instance_count[ $index ] = 0;
  1772 		}
  1901 		}
  1773 		$this->sidebar_instance_count[ $index ] += 1;
  1902 		$this->sidebar_instance_count[ $index ] += 1;
  1774 		if ( ! $this->manager->selective_refresh->is_render_partials_request() ) {
  1903 		if ( ! $this->manager->selective_refresh->is_render_partials_request() ) {
  1775 			printf( "\n<!--dynamic_sidebar_before:%s:%d-->\n", esc_html( $index ), intval( $this->sidebar_instance_count[ $index ] ) );
  1904 			printf( "\n<!--dynamic_sidebar_before:%s:%d-->\n", esc_html( $index ), (int) $this->sidebar_instance_count[ $index ] );
  1776 		}
  1905 		}
  1777 	}
  1906 	}
  1778 
  1907 
  1779 	/**
  1908 	/**
  1780 	 * Finishes keeping track of the current sidebar being rendered.
  1909 	 * Finishes keeping track of the current sidebar being rendered.
  1786 	 * @param int|string $index Index, name, or ID of the dynamic sidebar.
  1915 	 * @param int|string $index Index, name, or ID of the dynamic sidebar.
  1787 	 */
  1916 	 */
  1788 	public function end_dynamic_sidebar( $index ) {
  1917 	public function end_dynamic_sidebar( $index ) {
  1789 		array_shift( $this->current_dynamic_sidebar_id_stack );
  1918 		array_shift( $this->current_dynamic_sidebar_id_stack );
  1790 		if ( ! $this->manager->selective_refresh->is_render_partials_request() ) {
  1919 		if ( ! $this->manager->selective_refresh->is_render_partials_request() ) {
  1791 			printf( "\n<!--dynamic_sidebar_after:%s:%d-->\n", esc_html( $index ), intval( $this->sidebar_instance_count[ $index ] ) );
  1920 			printf( "\n<!--dynamic_sidebar_after:%s:%d-->\n", esc_html( $index ), (int) $this->sidebar_instance_count[ $index ] );
  1792 		}
  1921 		}
  1793 	}
  1922 	}
  1794 
  1923 
  1795 	/**
  1924 	/**
  1796 	 * Current sidebar being rendered.
  1925 	 * Current sidebar being rendered.
  1849 		}
  1978 		}
  1850 
  1979 
  1851 		$this->rendering_sidebar_id = $context['sidebar_id'];
  1980 		$this->rendering_sidebar_id = $context['sidebar_id'];
  1852 
  1981 
  1853 		if ( isset( $context['sidebar_instance_number'] ) ) {
  1982 		if ( isset( $context['sidebar_instance_number'] ) ) {
  1854 			$this->context_sidebar_instance_number = intval( $context['sidebar_instance_number'] );
  1983 			$this->context_sidebar_instance_number = (int) $context['sidebar_instance_number'];
  1855 		}
  1984 		}
  1856 
  1985 
  1857 		// Filter sidebars_widgets so that only the queried widget is in the sidebar.
  1986 		// Filter sidebars_widgets so that only the queried widget is in the sidebar.
  1858 		$this->rendering_widget_id = $widget_id;
  1987 		$this->rendering_widget_id = $widget_id;
  1859 
  1988