diff --git a/wp-admin/includes/widgets.php b/wp-admin/includes/widgets.php index 6c53d843ba..be12a3f7bf 100644 --- a/wp-admin/includes/widgets.php +++ b/wp-admin/includes/widgets.php @@ -2,7 +2,7 @@ // $_search is unsanitized function wp_list_widgets( $show = 'all', $_search = false ) { - global $wp_registered_widgets, $sidebars_widgets; + global $wp_registered_widgets, $sidebars_widgets, $wp_registered_widget_controls; if ( $_search ) { // sanitize $search = preg_replace( '/[^\w\s]/', '', $_search ); @@ -52,17 +52,31 @@ function wp_list_widgets( $show = 'all', $_search = false ) { $widget_control_template = ob_get_contents(); ob_end_clean(); + $widget_id = $widget['id']; // save this for later in case we mess with $widget['id'] + $is_multi = false !== strpos( $widget_control_template, '%i%' ); if ( !$sidebar || $is_multi ) { - if ( $is_multi ) - $already_shown[] = $widget['callback']; // it's a multi-widget. We only need to show it in the list once. - $action = 'add'; - $add_url = wp_nonce_url( add_query_arg( array( + $add_query = array( 'sidebar' => $sidebar, - 'add' => $widget['id'], 'key' => false, 'edit' => false - ) ), "add-widget_$widget[id]" ); + ); + if ( $is_multi ) { + // it's a multi-widget. We only need to show it in the list once. + $already_shown[] = $widget['callback']; + $num = array_pop( explode( '-', $widget['id'] ) ); + $id_base = $wp_registered_widget_controls[$widget['id']]['id_base']; + // so that we always add a new one when clicking "add" + while ( isset($wp_registered_widgets["$id_base-$num"]) ) + $num++; + $widget['id'] = "$id_base-$num"; + $add_query['base'] = $id_base; + $add_query['key'] = $num; + $add_query['sidebar'] = $GLOBALS['sidebar']; + } + $add_query['add'] = $widget['id']; + $action = 'add'; + $add_url = wp_nonce_url( add_query_arg( $add_query ), "add-widget_$widget[id]" ); } else { $action = 'edit'; $edit_url = clean_url( add_query_arg( array( @@ -110,7 +124,7 @@ function wp_list_widgets( $show = 'all', $_search = false ) {
- +

@@ -174,7 +188,7 @@ function wp_widget_control( $sidebar_args ) { $key = $sidebar_id ? array_search( $widget_id, $sidebars_widgets[$sidebar_id] ) : 'no-key'; // position of widget in sidebar - $edit = $edit_widget > 0 && $key && $edit_widget == $key; // (bool) are we currently editing this widget + $edit = -1 < $edit_widget && is_numeric($key) && $edit_widget === $key; // (bool) are we currently editing this widget $id_format = $widget['id']; // We aren't showing a widget control, we're outputing a template for a mult-widget control @@ -240,7 +254,7 @@ function wp_widget_control( $sidebar_args ) { - "> + ">
diff --git a/wp-admin/widgets.php b/wp-admin/widgets.php index 07bfe9aaa1..4a8751d159 100644 --- a/wp-admin/widgets.php +++ b/wp-admin/widgets.php @@ -46,10 +46,11 @@ if ( empty( $sidebars_widgets ) ) if ( empty( $sidebars_widgets[$sidebar] ) ) $sidebars_widgets[$sidebar] = array(); -$http_post = ( 'POST' == $_SERVER['REQUEST_METHOD'] ); +$http_post = 'post' == strtolower($_SERVER['REQUEST_METHOD']); // We're updating a sidebar if ( $http_post && isset($sidebars_widgets[$_POST['sidebar']]) ) { + check_admin_referer( 'edit-sidebar_' . $_POST['sidebar'] ); /* Hack #1 * The widget_control is overloaded. It updates the widget's options AND echoes out the widget's HTML form. @@ -81,7 +82,7 @@ if ( $http_post && isset($sidebars_widgets[$_POST['sidebar']]) ) { if ( !$val ) unset($_POST['widget-id'][$key]); - // Reset the key numbering and stare + // Reset the key numbering and store $new_sidebar = isset( $_POST['widget-id'] ) && is_array( $_POST['widget-id'] ) ? array_values( $_POST['widget-id'] ) : array(); $sidebars_widgets[$_POST['sidebar']] = $new_sidebar; wp_set_sidebars_widgets( $sidebars_widgets ); @@ -96,14 +97,65 @@ if ( $http_post && isset($sidebars_widgets[$_POST['sidebar']]) ) { // What widget (if any) are we editing $edit_widget = -1; -$query_args = array('add', 'remove', 'key', 'edit', '_wpnonce', 'message' ); +$query_args = array('add', 'remove', 'key', 'edit', '_wpnonce', 'message', 'base' ); if ( isset($_GET['add']) && $_GET['add'] ) { // Add to the end of the sidebar + $control_callback; if ( isset($wp_registered_widgets[$_GET['add']]) ) { check_admin_referer( "add-widget_$_GET[add]" ); $sidebars_widgets[$sidebar][] = $_GET['add']; wp_set_sidebars_widgets( $sidebars_widgets ); + } elseif ( isset($_GET['base']) && isset($_GET['key']) ) { // It's a multi-widget + check_admin_referer( "add-widget_$_GET[add]" ); + // Copy minimal info from an existing instance of this widget to a new instance + foreach ( $wp_registered_widget_controls as $control ) { + if ( $_GET['base'] === $control['id_base'] ) { + $control_callback = $control['callback']; + $num = (int) $_GET['key']; + $control['params'][0]['number'] = $num; + $control['id'] = $control['id_base'] . '-' . $num; + $wp_registered_widget_controls[$control['id']] = $control; + $sidebars_widgets[$sidebar][] = $control['id']; + break; + } + } + } + + // it's a multi-widget. The only way to add multi-widgets without JS is to actually submit POST content... + // so here we go + if ( is_callable( $control_callback ) ) { + require_once( 'admin-header.php' ); + ?> +
+

+
+
+ + +
+
+ +

diff --git a/wp-includes/widgets.php b/wp-includes/widgets.php index 750b7b28f2..92c048b205 100644 --- a/wp-includes/widgets.php +++ b/wp-includes/widgets.php @@ -1189,7 +1189,7 @@ function wp_widget_rss_control($widget_args) { $show_author = 0; $show_date = 0; } else { - extract( $options[$number] ); + extract( (array) $options[$number] ); } wp_widget_rss_form( compact( 'number', 'title', 'url', 'items', 'error', 'show_summary', 'show_author', 'show_date' ) );