--- a/wp/wp-includes/widgets.php Tue Dec 15 15:52:01 2020 +0100
+++ b/wp/wp-includes/widgets.php Wed Sep 21 18:19:35 2022 +0200
@@ -219,28 +219,37 @@
* called, it will be automatically enabled through the use of add_theme_support()
*
* @since 2.2.0
+ * @since 5.6.0 Added the `before_sidebar` and `after_sidebar` arguments.
*
* @global array $wp_registered_sidebars Registered sidebars.
*
* @param array|string $args {
* Optional. Array or string of arguments for the sidebar being registered.
*
- * @type string $name The name or title of the sidebar displayed in the Widgets
- * interface. Default 'Sidebar $instance'.
- * @type string $id The unique identifier by which the sidebar will be called.
- * Default 'sidebar-$instance'.
- * @type string $description Description of the sidebar, displayed in the Widgets interface.
- * Default empty string.
- * @type string $class Extra CSS class to assign to the sidebar in the Widgets interface.
- * Default empty.
- * @type string $before_widget HTML content to prepend to each widget's HTML output when
- * assigned to this sidebar. Default is an opening list item element.
- * @type string $after_widget HTML content to append to each widget's HTML output when
- * assigned to this sidebar. Default is a closing list item element.
- * @type string $before_title HTML content to prepend to the sidebar title when displayed.
- * Default is an opening h2 element.
- * @type string $after_title HTML content to append to the sidebar title when displayed.
- * Default is a closing h2 element.
+ * @type string $name The name or title of the sidebar displayed in the Widgets
+ * interface. Default 'Sidebar $instance'.
+ * @type string $id The unique identifier by which the sidebar will be called.
+ * Default 'sidebar-$instance'.
+ * @type string $description Description of the sidebar, displayed in the Widgets interface.
+ * Default empty string.
+ * @type string $class Extra CSS class to assign to the sidebar in the Widgets interface.
+ * Default empty.
+ * @type string $before_widget HTML content to prepend to each widget's HTML output when assigned
+ * to this sidebar. Receives the widget's ID attribute as `%1$s`
+ * and class name as `%2$s`. Default is an opening list item element.
+ * @type string $after_widget HTML content to append to each widget's HTML output when assigned
+ * to this sidebar. Default is a closing list item element.
+ * @type string $before_title HTML content to prepend to the sidebar title when displayed.
+ * Default is an opening h2 element.
+ * @type string $after_title HTML content to append to the sidebar title when displayed.
+ * Default is a closing h2 element.
+ * @type string $before_sidebar HTML content to prepend to the sidebar when displayed.
+ * Receives the `$id` argument as `%1$s` and `$class` as `%2$s`.
+ * Outputs after the {@see 'dynamic_sidebar_before'} action.
+ * Default empty string.
+ * @type string $after_sidebar HTML content to append to the sidebar when displayed.
+ * Outputs before the {@see 'dynamic_sidebar_after'} action.
+ * Default empty string.
* }
* @return string Sidebar ID added to $wp_registered_sidebars global.
*/
@@ -253,14 +262,16 @@
$defaults = array(
/* translators: %d: Sidebar number. */
- 'name' => sprintf( __( 'Sidebar %d' ), $i ),
- 'id' => "sidebar-$i",
- 'description' => '',
- 'class' => '',
- 'before_widget' => '<li id="%1$s" class="widget %2$s">',
- 'after_widget' => "</li>\n",
- 'before_title' => '<h2 class="widgettitle">',
- 'after_title' => "</h2>\n",
+ 'name' => sprintf( __( 'Sidebar %d' ), $i ),
+ 'id' => "sidebar-$i",
+ 'description' => '',
+ 'class' => '',
+ 'before_widget' => '<li id="%1$s" class="widget %2$s">',
+ 'after_widget' => "</li>\n",
+ 'before_title' => '<h2 class="widgettitle">',
+ 'after_title' => "</h2>\n",
+ 'before_sidebar' => '',
+ 'after_sidebar' => '',
);
/**
@@ -346,6 +357,7 @@
* @since 2.2.0
* @since 5.3.0 Formalized the existing and already documented `...$params` parameter
* by adding it to the function signature.
+ * @since 5.8.0 Added show_instance_in_rest option.
*
* @global array $wp_registered_widgets Uses stored registered widgets.
* @global array $wp_registered_widget_controls Stores the registered widget controls (options).
@@ -358,10 +370,12 @@
* @param array $options {
* Optional. An array of supplementary widget options for the instance.
*
- * @type string $classname Class name for the widget's HTML container. Default is a shortened
- * version of the output callback name.
- * @type string $description Widget description for display in the widget administration
- * panel and/or theme.
+ * @type string $classname Class name for the widget's HTML container. Default is a shortened
+ * version of the output callback name.
+ * @type string $description Widget description for display in the widget administration
+ * panel and/or theme.
+ * @type bool $show_instance_in_rest Whether to show the widget's instance settings in the REST API.
+ * Only available for WP_Widget based widgets.
* }
* @param mixed ...$params Optional additional parameters to pass to the callback function when it's called.
*/
@@ -691,6 +705,10 @@
return apply_filters( 'dynamic_sidebar_has_widgets', false, $index );
}
+ $sidebar = $wp_registered_sidebars[ $index ];
+
+ $sidebar['before_sidebar'] = sprintf( $sidebar['before_sidebar'], $sidebar['id'], $sidebar['class'] );
+
/**
* Fires before widgets are rendered in a dynamic sidebar.
*
@@ -704,7 +722,10 @@
* Default true.
*/
do_action( 'dynamic_sidebar_before', $index, true );
- $sidebar = $wp_registered_sidebars[ $index ];
+
+ if ( ! is_admin() && ! empty( $sidebar['before_sidebar'] ) ) {
+ echo $sidebar['before_sidebar'];
+ }
$did_one = false;
foreach ( (array) $sidebars_widgets[ $index ] as $id ) {
@@ -735,8 +756,13 @@
$classname_ .= '_' . get_class( $cn );
}
}
- $classname_ = ltrim( $classname_, '_' );
- $params[0]['before_widget'] = sprintf( $params[0]['before_widget'], $id, $classname_ );
+ $classname_ = ltrim( $classname_, '_' );
+
+ $params[0]['before_widget'] = sprintf(
+ $params[0]['before_widget'],
+ str_replace( '\\', '_', $id ),
+ $classname_
+ );
/**
* Filters the parameters passed to a widget's display callback.
@@ -784,19 +810,19 @@
*
* @since 3.0.0
*
- * @param array $widget_id {
+ * @param array $widget {
* An associative array of widget arguments.
*
* @type string $name Name of the widget.
* @type string $id Widget ID.
- * @type callable $callback When the hook is fired on the front end, $callback is an array
- * containing the widget object. Fired on the back end, $callback
- * is 'wp_widget_control', see $_callback.
+ * @type callable $callback When the hook is fired on the front end, `$callback` is an array
+ * containing the widget object. Fired on the back end, `$callback`
+ * is 'wp_widget_control', see `$_callback`.
* @type array $params An associative array of multi-widget arguments.
* @type string $classname CSS class applied to the widget container.
* @type string $description The widget description.
- * @type array $_callback When the hook is fired on the back end, $_callback is populated
- * with an array containing the widget object, see $callback.
+ * @type array $_callback When the hook is fired on the back end, `$_callback` is populated
+ * with an array containing the widget object, see `$callback`.
* }
*/
do_action( 'dynamic_sidebar', $wp_registered_widgets[ $id ] );
@@ -807,6 +833,10 @@
}
}
+ if ( ! is_admin() && ! empty( $sidebar['after_sidebar'] ) ) {
+ echo $sidebar['after_sidebar'];
+ }
+
/**
* Fires after widgets are rendered in a dynamic sidebar.
*
@@ -857,11 +887,15 @@
*
* @global array $wp_registered_widgets
*
- * @param callable|false $callback Optional, Widget callback to check. Default false.
- * @param int|false $widget_id Optional. Widget ID. Optional, but needed for checking. Default false.
- * @param string|false $id_base Optional. The base ID of a widget created by extending WP_Widget. Default false.
- * @param bool $skip_inactive Optional. Whether to check in 'wp_inactive_widgets'. Default true.
- * @return string|false False if widget is not active or id of sidebar in which the widget is active.
+ * @param callable|false $callback Optional. Widget callback to check. Default false.
+ * @param string|false $widget_id Optional. Widget ID. Optional, but needed for checking.
+ * Default false.
+ * @param string|false $id_base Optional. The base ID of a widget created by extending WP_Widget.
+ * Default false.
+ * @param bool $skip_inactive Optional. Whether to check in 'wp_inactive_widgets'.
+ * Default true.
+ * @return string|false ID of the sidebar in which the widget is active,
+ * false if the widget is not active.
*/
function is_active_widget( $callback = false, $widget_id = false, $id_base = false, $skip_inactive = true ) {
global $wp_registered_widgets;
@@ -1262,7 +1296,7 @@
$sidebars_widgets = wp_map_sidebars_widgets( $sidebars_widgets );
// Find hidden/lost multi-widget instances.
- $shown_widgets = call_user_func_array( 'array_merge', $sidebars_widgets );
+ $shown_widgets = array_merge( ...array_values( $sidebars_widgets ) );
$lost_widgets = array_diff( $registered_widgets_ids, $shown_widgets );
foreach ( $lost_widgets as $key => $widget_id ) {
@@ -1531,7 +1565,7 @@
echo '<ul>';
foreach ( $rss->get_items( 0, $items ) as $item ) {
$link = $item->get_link();
- while ( stristr( $link, 'http' ) !== $link ) {
+ while ( ! empty( $link ) && stristr( $link, 'http' ) !== $link ) {
$link = substr( $link, 1 );
}
$link = esc_url( strip_tags( $link ) );
@@ -1765,6 +1799,8 @@
register_widget( 'WP_Widget_Custom_HTML' );
+ register_widget( 'WP_Widget_Block' );
+
/**
* Fires after all default WordPress widgets have been registered.
*
@@ -1772,3 +1808,243 @@
*/
do_action( 'widgets_init' );
}
+
+/**
+ * Enables the widgets block editor. This is hooked into 'after_setup_theme' so
+ * that the block editor is enabled by default but can be disabled by themes.
+ *
+ * @since 5.8.0
+ *
+ * @access private
+ */
+function wp_setup_widgets_block_editor() {
+ add_theme_support( 'widgets-block-editor' );
+}
+
+/**
+ * Whether or not to use the block editor to manage widgets. Defaults to true
+ * unless a theme has removed support for widgets-block-editor or a plugin has
+ * filtered the return value of this function.
+ *
+ * @since 5.8.0
+ *
+ * @return boolean Whether or not to use the block editor to manage widgets.
+ */
+function wp_use_widgets_block_editor() {
+ /**
+ * Filters whether or not to use the block editor to manage widgets.
+ *
+ * @since 5.8.0
+ *
+ * @param boolean $use_widgets_block_editor Whether or not to use the block editor to manage widgets.
+ */
+ return apply_filters(
+ 'use_widgets_block_editor',
+ get_theme_support( 'widgets-block-editor' )
+ );
+}
+
+/**
+ * Converts a widget ID into its id_base and number components.
+ *
+ * @since 5.8.0
+ *
+ * @param string $id Widget ID.
+ * @return array Array containing a widget's id_base and number components.
+ */
+function wp_parse_widget_id( $id ) {
+ $parsed = array();
+
+ if ( preg_match( '/^(.+)-(\d+)$/', $id, $matches ) ) {
+ $parsed['id_base'] = $matches[1];
+ $parsed['number'] = (int) $matches[2];
+ } else {
+ // Likely an old single widget.
+ $parsed['id_base'] = $id;
+ }
+
+ return $parsed;
+}
+
+/**
+ * Finds the sidebar that a given widget belongs to.
+ *
+ * @since 5.8.0
+ *
+ * @param string $widget_id The widget id to look for.
+ * @return string|null The found sidebar's id, or null if it was not found.
+ */
+function wp_find_widgets_sidebar( $widget_id ) {
+ foreach ( wp_get_sidebars_widgets() as $sidebar_id => $widget_ids ) {
+ foreach ( $widget_ids as $maybe_widget_id ) {
+ if ( $maybe_widget_id === $widget_id ) {
+ return (string) $sidebar_id;
+ }
+ }
+ }
+
+ return null;
+}
+
+/**
+ * Assigns a widget to the given sidebar.
+ *
+ * @since 5.8.0
+ *
+ * @param string $widget_id The widget id to assign.
+ * @param string $sidebar_id The sidebar id to assign to. If empty, the widget won't be added to any sidebar.
+ */
+function wp_assign_widget_to_sidebar( $widget_id, $sidebar_id ) {
+ $sidebars = wp_get_sidebars_widgets();
+
+ foreach ( $sidebars as $maybe_sidebar_id => $widgets ) {
+ foreach ( $widgets as $i => $maybe_widget_id ) {
+ if ( $widget_id === $maybe_widget_id && $sidebar_id !== $maybe_sidebar_id ) {
+ unset( $sidebars[ $maybe_sidebar_id ][ $i ] );
+ // We could technically break 2 here, but continue looping in case the id is duplicated.
+ continue 2;
+ }
+ }
+ }
+
+ if ( $sidebar_id ) {
+ $sidebars[ $sidebar_id ][] = $widget_id;
+ }
+
+ wp_set_sidebars_widgets( $sidebars );
+}
+
+/**
+ * Calls the render callback of a widget and returns the output.
+ *
+ * @since 5.8.0
+ *
+ * @param string $widget_id Widget ID.
+ * @param string $sidebar_id Sidebar ID.
+ * @return string
+ */
+function wp_render_widget( $widget_id, $sidebar_id ) {
+ global $wp_registered_widgets, $wp_registered_sidebars;
+
+ if ( ! isset( $wp_registered_widgets[ $widget_id ] ) ) {
+ return '';
+ }
+
+ if ( isset( $wp_registered_sidebars[ $sidebar_id ] ) ) {
+ $sidebar = $wp_registered_sidebars[ $sidebar_id ];
+ } elseif ( 'wp_inactive_widgets' === $sidebar_id ) {
+ $sidebar = array();
+ } else {
+ return '';
+ }
+
+ $params = array_merge(
+ array(
+ array_merge(
+ $sidebar,
+ array(
+ 'widget_id' => $widget_id,
+ 'widget_name' => $wp_registered_widgets[ $widget_id ]['name'],
+ )
+ ),
+ ),
+ (array) $wp_registered_widgets[ $widget_id ]['params']
+ );
+
+ // Substitute HTML `id` and `class` attributes into `before_widget`.
+ $classname_ = '';
+ foreach ( (array) $wp_registered_widgets[ $widget_id ]['classname'] as $cn ) {
+ if ( is_string( $cn ) ) {
+ $classname_ .= '_' . $cn;
+ } elseif ( is_object( $cn ) ) {
+ $classname_ .= '_' . get_class( $cn );
+ }
+ }
+ $classname_ = ltrim( $classname_, '_' );
+ $params[0]['before_widget'] = sprintf( $params[0]['before_widget'], $widget_id, $classname_ );
+
+ /** This filter is documented in wp-includes/widgets.php */
+ $params = apply_filters( 'dynamic_sidebar_params', $params );
+
+ $callback = $wp_registered_widgets[ $widget_id ]['callback'];
+
+ ob_start();
+
+ /** This filter is documented in wp-includes/widgets.php */
+ do_action( 'dynamic_sidebar', $wp_registered_widgets[ $widget_id ] );
+
+ if ( is_callable( $callback ) ) {
+ call_user_func_array( $callback, $params );
+ }
+
+ return ob_get_clean();
+}
+
+/**
+ * Calls the control callback of a widget and returns the output.
+ *
+ * @since 5.8.0
+ *
+ * @param string $id Widget ID.
+ * @return string|null
+ */
+function wp_render_widget_control( $id ) {
+ global $wp_registered_widget_controls;
+
+ if ( ! isset( $wp_registered_widget_controls[ $id ]['callback'] ) ) {
+ return null;
+ }
+
+ $callback = $wp_registered_widget_controls[ $id ]['callback'];
+ $params = $wp_registered_widget_controls[ $id ]['params'];
+
+ ob_start();
+
+ if ( is_callable( $callback ) ) {
+ call_user_func_array( $callback, $params );
+ }
+
+ return ob_get_clean();
+}
+
+/**
+ * Displays a _doing_it_wrong() message for conflicting widget editor scripts.
+ *
+ * The 'wp-editor' script module is exposed as window.wp.editor. This overrides
+ * the legacy TinyMCE editor module which is required by the widgets editor.
+ * Because of that conflict, these two shouldn't be enqueued together.
+ * See https://core.trac.wordpress.org/ticket/53569.
+ *
+ * There is also another conflict related to styles where the block widgets
+ * editor is hidden if a block enqueues 'wp-edit-post' stylesheet.
+ * See https://core.trac.wordpress.org/ticket/53569.
+ *
+ * @since 5.8.0
+ * @access private
+ *
+ * @global WP_Scripts $wp_scripts
+ * @global WP_Styles $wp_styles
+ */
+function wp_check_widget_editor_deps() {
+ global $wp_scripts, $wp_styles;
+
+ if (
+ $wp_scripts->query( 'wp-edit-widgets', 'enqueued' ) ||
+ $wp_scripts->query( 'wp-customize-widgets', 'enqueued' )
+ ) {
+ if ( $wp_scripts->query( 'wp-editor', 'enqueued' ) ) {
+ _doing_it_wrong(
+ 'wp_enqueue_script()',
+ '"wp-editor" script should not be enqueued together with the new widgets editor (wp-edit-widgets or wp-customize-widgets).',
+ '5.8.0'
+ );
+ }
+ if ( $wp_styles->query( 'wp-edit-post', 'enqueued' ) ) {
+ _doing_it_wrong(
+ 'wp_enqueue_style()',
+ '"wp-edit-post" style should not be enqueued together with the new widgets editor (wp-edit-widgets or wp-customize-widgets).',
+ '5.8.0'
+ );
+ }
+ }
+}