Ticket #5583: 5583.diff

File 5583.diff, 82.8 kB (added by mdawaffe, 8 months ago)

big

  • wp-includes/widgets.php

    old new  
    22 
    33/* Global Variables */ 
    44 
    5 global $wp_registered_sidebars, $wp_registered_widgets, $wp_registered_widget_controls, $wp_registered_widget_styles, $wp_registered_widget_defaults
     5global $wp_registered_sidebars, $wp_registered_widgets, $wp_registered_widget_controls
    66 
    77$wp_registered_sidebars = array(); 
    88$wp_registered_widgets = array(); 
    99$wp_registered_widget_controls = array(); 
    10 $wp_registered_widget_styles = array(); 
    11 $wp_register_widget_defaults = false; 
    1210 
    1311/* Template tags & API functions */ 
    1412 
     
    9593} 
    9694 
    9795function wp_register_sidebar_widget($id, $name, $output_callback, $options = array()) { 
     96        global $wp_registered_widgets; 
    9897 
    99         global $wp_registered_widgets, $wp_register_widget_defaults; 
    100  
    10198        if ( empty($output_callback) ) { 
    10299                unset($wp_registered_widgets[$id]); 
    103100                return; 
     
    113110        ); 
    114111        $widget = array_merge($widget, $options); 
    115112 
    116         if ( is_callable($output_callback) && ( !isset($wp_registered_widgets[$id]) || !$wp_register_widget_defaults) ) 
     113        if ( is_callable($output_callback) && ( !isset($wp_registered_widgets[$id]) || did_action( 'widgets_init' ) ) ) 
    117114                $wp_registered_widgets[$id] = $widget; 
    118115} 
    119116 
     117function wp_widget_description( $id ) { 
     118        if ( !is_scalar($id) ) 
     119                return; 
     120 
     121        global $wp_registered_widgets; 
     122 
     123        if ( isset($wp_registered_widgets[$id]['description']) ) 
     124                return wp_specialchars( $wp_registered_widgets[$id]['description'] ); 
     125} 
     126 
    120127function unregister_sidebar_widget($id) { 
    121128        return wp_unregister_sidebar_widget($id); 
    122129} 
     
    149156        call_user_func_array('wp_register_widget_control', $args); 
    150157} 
    151158 
     159/* $options: height, width, id_base 
     160 *   height: never used 
     161 *   width:  width of fully expanded control form.  Try hard to use the default width. 
     162 *   id_base: for widgets which allow multiple instances (such as the text widget), an id_base must be provided. 
     163 *            the widget id will ennd up looking like {$id_base}-{$unique_number} 
     164 */ 
    152165function wp_register_widget_control($id, $name, $control_callback, $options = array()) { 
    153         global $wp_registered_widget_controls, $wp_register_widget_defaults
     166        global $wp_registered_widget_controls
    154167 
    155168        if ( empty($control_callback) ) { 
    156169                unset($wp_registered_widget_controls[$id]); 
    157170                return; 
    158171        } 
    159172 
    160         if ( isset($wp_registered_widget_controls[$id]) && $wp_register_widget_defaults
     173        if ( isset($wp_registered_widget_controls[$id]) && !did_action( 'widgets_init' )
    161174                return; 
    162175 
    163         $defaults = array('width' => 300, 'height' => 200); 
     176        $defaults = array('width' => 250, 'height' => 200 ); // height is never used 
    164177        $options = wp_parse_args($options, $defaults); 
    165178        $options['width'] = (int) $options['width']; 
    166179        $options['height'] = (int) $options['height']; 
    167         $options['width'] = $options['width'] > 90 ? $options['width'] + 60 : 360; 
    168         $options['height'] = $options['height'] > 60 ? $options['height'] + 40 : 240; 
    169180 
    170181        $widget = array( 
    171182                'name' => $name, 
     
    234245        return $did_one; 
    235246} 
    236247 
     248/* @return mixed false if widget is not active or id of sidebar in which the widget is active 
     249 */ 
    237250function is_active_widget($callback) { 
    238251        global $wp_registered_widgets; 
    239252 
    240253        $sidebars_widgets = wp_get_sidebars_widgets(false); 
    241254 
    242         if ( is_array($sidebars_widgets) ) foreach ( $sidebars_widgets as $widgets ) 
     255        if ( is_array($sidebars_widgets) ) foreach ( $sidebars_widgets as $sidebar => $widgets ) 
    243256                if ( is_array($widgets) ) foreach ( $widgets as $widget ) 
    244257                        if ( $wp_registered_widgets[$widget]['callback'] == $callback ) 
    245                                 return true
     258                                return $sidebar
    246259 
    247260        return false; 
    248261} 
     
    387400        $title = attribute_escape($options['title']); 
    388401        $exclude = attribute_escape( $options['exclude'] ); 
    389402?> 
    390                         <p><label for="pages-title"><?php _e('Title:'); ?> <input style="width: 250px;" id="pages-title" name="pages-title" type="text" value="<?php echo $title; ?>" /></label></p> 
    391                         <p><label for="pages-sortby"><?php _e( 'Sort by:' ); ?> 
    392                                 <select name="pages-sortby" id="pages-sortby"> 
     403                <p><label for="pages-title"><?php _e('Title:'); ?> <input class="widefat" id="pages-title" name="pages-title" type="text" value="<?php echo $title; ?>" /></label></p> 
     404                <p> 
     405                        <label for="pages-sortby"><?php _e( 'Sort by:' ); ?> 
     406                                <select name="pages-sortby" id="pages-sortby" class="widefat"> 
    393407                                        <option value="post_title"<?php selected( $options['sortby'], 'post_title' ); ?>><?php _e('Page title'); ?></option> 
    394408                                        <option value="menu_order"<?php selected( $options['sortby'], 'menu_order' ); ?>><?php _e('Page order'); ?></option> 
    395409                                        <option value="ID"<?php selected( $options['sortby'], 'ID' ); ?>><?php _e( 'Page ID' ); ?></option> 
    396                                 </select></label></p> 
    397                         <p><label for="pages-exclude"><?php _e( 'Exclude:' ); ?> <input type="text" value="<?php echo $exclude; ?>" name="pages-exclude" id="pages-exclude" style="width: 180px;" /></label><br /> 
    398                         <small><?php _e( 'Page IDs, separated by commas.' ); ?></small></p> 
    399                         <input type="hidden" id="pages-submit" name="pages-submit" value="1" /> 
     410                                </select> 
     411                        </label> 
     412                </p> 
     413                <p> 
     414                        <label for="pages-exclude"><?php _e( 'Exclude:' ); ?> <input type="text" value="<?php echo $exclude; ?>" name="pages-exclude" id="pages-exclude" class="widefat" /></label> 
     415                        <br /> 
     416                        <small><?php _e( 'Page IDs, separated by commas.' ); ?></small> 
     417                </p> 
     418                <input type="hidden" id="pages-submit" name="pages-submit" value="1" /> 
    400419<?php 
    401420} 
    402421 
     
    463482        $dropdown = $options['dropdown'] ? 'checked="checked"' : ''; 
    464483        $title = attribute_escape($options['title']); 
    465484?> 
    466                         <p><label for="archives-title"><?php _e('Title:'); ?> <input style="width: 250px;" id="archives-title" name="archives-title" type="text" value="<?php echo $title; ?>" /></label></p> 
    467                         <p style="text-align:right;margin-right:40px;"><label for="archives-count"><?php _e('Show post counts'); ?> <input class="checkbox" type="checkbox" <?php echo $count; ?> id="archives-count" name="archives-count" /></label></p> 
    468                         <p style="text-align:right;margin-right:40px;"><label for="archives-dropdown"><?php _e('Display as a drop down'); ?> <input class="checkbox" type="checkbox" <?php echo $dropdown; ?> id="archives-dropdown" name="archives-dropdown" /></label></p> 
     485                        <p><label for="archives-title"><?php _e('Title:'); ?> <input class="widefat" id="archives-title" name="archives-title" type="text" value="<?php echo $title; ?>" /></label></p> 
     486                        <p> 
     487                                <label for="archives-count"><input class="checkbox" type="checkbox" <?php echo $count; ?> id="archives-count" name="archives-count" /> <?php _e('Show post counts'); ?></label> 
     488                                <br /> 
     489                                <label for="archives-dropdown"><input class="checkbox" type="checkbox" <?php echo $dropdown; ?> id="archives-dropdown" name="archives-dropdown" /> <?php _e('Display as a drop down'); ?></label> 
     490                        </p> 
    469491                        <input type="hidden" id="archives-submit" name="archives-submit" value="1" /> 
    470492<?php 
    471493} 
     
    499521        } 
    500522        $title = attribute_escape($options['title']); 
    501523?> 
    502                         <p><label for="meta-title"><?php _e('Title:'); ?> <input style="width: 250px;" id="meta-title" name="meta-title" type="text" value="<?php echo $title; ?>" /></label></p> 
     524                        <p><label for="meta-title"><?php _e('Title:'); ?> <input class="widefat" id="meta-title" name="meta-title" type="text" value="<?php echo $title; ?>" /></label></p> 
    503525                        <input type="hidden" id="meta-submit" name="meta-submit" value="1" /> 
    504526<?php 
    505527} 
     
    527549        } 
    528550        $title = attribute_escape($options['title']); 
    529551?> 
    530                         <p><label for="calendar-title"><?php _e('Title:'); ?> <input style="width: 250px;" id="calendar-title" name="calendar-title" type="text" value="<?php echo $title; ?>" /></label></p> 
     552                        <p><label for="calendar-title"><?php _e('Title:'); ?> <input class="widefat" id="calendar-title" name="calendar-title" type="text" value="<?php echo $title; ?>" /></label></p> 
    531553                        <input type="hidden" id="calendar-submit" name="calendar-submit" value="1" /> 
    532554<?php 
    533555} 
    534556 
    535 function wp_widget_text($args, $number = 1) { 
    536         extract($args); 
     557// See large comment section at end of this file 
     558function wp_widget_text($args, $widget_args = 1) { 
     559        extract( $args, EXTR_SKIP ); 
     560        if ( is_numeric($widget_args) ) 
     561                $widget_args = array( 'number' => $widget_args ); 
     562        $widget_args = wp_parse_args( $widget_args, array( 'number' => -1 ) ); 
     563        extract( $widget_args, EXTR_SKIP ); 
     564 
    537565        $options = get_option('widget_text'); 
     566        if ( !isset($options[$number]) ) 
     567                return; 
     568 
    538569        $title = $options[$number]['title']; 
    539570        $text = apply_filters( 'widget_text', $options[$number]['text'] ); 
    540571?> 
     
    545576<?php 
    546577} 
    547578 
    548 function wp_widget_text_control($number) { 
    549         $options = $newoptions = get_option('widget_text'); 
     579function wp_widget_text_control($widget_args) { 
     580        global $wp_registered_widgets; 
     581        static $updated = false; 
     582 
     583        if ( is_numeric($widget_args) ) 
     584                $widget_args = array( 'number' => $widget_args ); 
     585        $widget_args = wp_parse_args( $widget_args, array( 'number' => -1 ) ); 
     586        extract( $widget_args, EXTR_SKIP ); 
     587 
     588        $options = get_option('widget_text'); 
    550589        if ( !is_array($options) ) 
    551                 $options = $newoptions = array(); 
    552         if ( $_POST["text-submit-$number"] ) { 
    553                 $newoptions[$number]['title'] = strip_tags(stripslashes($_POST["text-title-$number"])); 
    554                 $newoptions[$number]['text'] = stripslashes($_POST["text-text-$number"]); 
    555                 if ( !current_user_can('unfiltered_html') ) 
    556                         $newoptions[$number]['text'] = stripslashes(wp_filter_post_kses($newoptions[$number]['text'])); 
    557         } 
    558         if ( $options != $newoptions ) { 
    559                 $options = $newoptions; 
     590                $options = array(); 
     591 
     592        if ( !$updated && !empty($_POST['sidebar']) ) { 
     593                $sidebar = (string) $_POST['sidebar']; 
     594 
     595                $sidebars_widgets = wp_get_sidebars_widgets(); 
     596                if ( isset($sidebars_widgets[$sidebar]) ) 
     597                        $this_sidebar =& $sidebars_widgets[$sidebar]; 
     598                else 
     599                        $this_sidebar = array(); 
     600 
     601                foreach ( $this_sidebar as $_widget_id ) { 
     602                        if ( 'wp_widget_text' == $wp_registered_widgets[$_widget_id]['callback'] && isset($wp_registered_widgets[$_widget_id]['params'][0]['number']) ) { 
     603                                $widget_number = $wp_registered_widgets[$_widget_id]['params'][0]['number']; 
     604                                unset($options[$widget_number]); 
     605                        } 
     606                } 
     607 
     608                foreach ( (array) $_POST['widget-text'] as $widget_number => $widget_text ) { 
     609                        $title = strip_tags(stripslashes($widget_text['title'])); 
     610                        if ( current_user_can('unfiltered_html') ) 
     611                                $text = stripslashes( $widget_text['text'] ); 
     612                        else 
     613                                $text = stripslashes(wp_filter_post_kses( $widget_text['text'] )); 
     614                        $options[$widget_number] = compact( 'title', 'text' ); 
     615                } 
     616 
    560617                update_option('widget_text', $options); 
     618                $updated = true; 
    561619        } 
    562         $title = attribute_escape($options[$number]['title']); 
    563         $text = format_to_edit($options[$number]['text']); 
    564 ?> 
    565                         <input style="width: 450px;" id="text-title-<?php echo $number; ?>" name="text-title-<?php echo $number; ?>" type="text" value="<?php echo $title; ?>" /> 
    566                         <textarea style="width: 450px; height: 280px;" id="text-text-<?php echo $number; ?>" name="text-text-<?php echo $number; ?>"><?php echo $text; ?></textarea> 
    567                         <input type="hidden" id="text-submit-<?php echo "$number"; ?>" name="text-submit-<?php echo "$number"; ?>" value="1" /> 
    568 <?php 
    569 } 
    570620 
    571 function wp_widget_text_setup() { 
    572         $options = $newoptions = get_option('widget_text')
    573         if ( isset($_POST['text-number-submit']) ) { 
    574                 $number = (int) $_POST['text-number']
    575                if ( $number > 9 ) $number = 9; 
    576                 if ( $number < 1 ) $number = 1
    577                 $newoptions['number'] = $number
     621       if ( -1 == $number ) { 
     622               $title = ''
     623               $text = ''; 
     624                $number = '%i%'
     625        } else { 
     626                $title = attribute_escape($options[$number]['title'])
     627                $text = format_to_edit($options[$number]['text'])
    578628        } 
    579         if ( $options != $newoptions ) { 
    580                 $options = $newoptions; 
    581                 update_option('widget_text', $options); 
    582                 wp_widget_text_register($options['number']); 
    583         } 
    584 } 
    585  
    586 function wp_widget_text_page() { 
    587         $options = get_option('widget_text'); 
    588629?> 
    589         <div class="wrap"> 
    590                 <form method="POST"> 
    591                         <h2><?php _e('Text Widgets'); ?></h2> 
    592                         <p style="line-height: 30px;"><?php _e('How many text widgets would you like?'); ?> 
    593                         <select id="text-number" name="text-number" value="<?php echo $options['number']; ?>"> 
    594 <?php for ( $i = 1; $i < 10; ++$i ) echo "<option value='$i' ".($options['number']==$i ? "selected='selected'" : '').">$i</option>"; ?> 
    595                         </select> 
    596                         <span class="submit"><input type="submit" name="text-number-submit" id="text-number-submit" value="<?php echo attribute_escape(__('Save')); ?>" /></span></p> 
    597                 </form> 
    598         </div> 
     630                <p> 
     631                        <input class="widefat" id="text-title-<?php echo $number; ?>" name="widget-text[<?php echo $number; ?>][title]" type="text" value="<?php echo $title; ?>" /> 
     632                        <textarea class="widefat" rows="16" cols="20" id="text-text-<?php echo $number; ?>" name="widget-text[<?php echo $number; ?>][text]"><?php echo $text; ?></textarea> 
     633                        <input type="hidden" id="text-submit-<?php echo $number; ?>" name="text-submit-<?php echo $number; ?>" value="1" /> 
     634                </p> 
    599635<?php 
    600636} 
    601637 
    602638function wp_widget_text_register() { 
    603639        $options = get_option('widget_text'); 
    604         $number = $options['number']; 
    605         if ( $number < 1 ) $number = 1; 
    606         if ( $number > 9 ) $number = 9; 
    607         $dims = array('width' => 460, 'height' => 350); 
    608         $class = array('classname' => 'widget_text'); 
    609         for ($i = 1; $i <= 9; $i++) { 
    610                 $name = sprintf(__('Text %d'), $i); 
    611                 $id = "text-$i"; // Never never never translate an id 
    612                 wp_register_sidebar_widget($id, $name, $i <= $number ? 'wp_widget_text' : /* unregister */ '', $class, $i); 
    613                 wp_register_widget_control($id, $name, $i <= $number ? 'wp_widget_text_control' : /* unregister */ '', $dims, $i); 
     640        $widget_ops = array('classname' => 'widget_text', 'description' => __('Arbitrary text or HTML')); 
     641        $control_ops = array('width' => 460, 'height' => 350, 'id_base' => 'text'); 
     642        $name = __('Text'); 
     643 
     644        // If there are none, we register the widget's existance with a generic template 
     645        if ( !$options ) { 
     646                wp_register_sidebar_widget( 'text-1', $name, 'wp_widget_text', $widget_ops, array( 'number' => -1 ) ); 
     647                wp_register_widget_control( 'text-1', $name, 'wp_widget_text_control', $control_ops, array( 'number' => -1 ) ); 
    614648        } 
    615         add_action('sidebar_admin_setup', 'wp_widget_text_setup'); 
    616         add_action('sidebar_admin_page', 'wp_widget_text_page'); 
     649 
     650        foreach ( array_keys($options) as $o ) { 
     651                // Old widgets can have null values for some reason 
     652                if ( !isset($options[$o]['title']) || !isset($options[$o]['text']) ) 
     653                        continue; 
     654                $id = "text-$o"; // Never never never translate an id 
     655                wp_register_sidebar_widget($id, $name, 'wp_widget_text', $widget_ops, array( 'number' => $o )); 
     656                wp_register_widget_control($id, $name, 'wp_widget_text_control', $control_ops, array( 'number' => $o )); 
     657        } 
    617658} 
    618659 
    619 function wp_widget_categories($args, $number = 1) { 
    620         extract($args); 
     660// See large comment section at end of this file 
     661function wp_widget_categories($args, $widget_args = 1) { 
     662        extract($args, EXTR_SKIP); 
     663        if ( is_numeric($widget_args) ) 
     664                $widget_args = array( 'number' => $widget_args ); 
     665        $widget_args = wp_parse_args( $widget_args, array( 'number' => -1 ) ); 
     666        extract($widget_args, EXTR_SKIP); 
     667 
    621668        $options = get_option('widget_categories'); 
     669        if ( !isset($options[$number]) ) 
     670                return; 
    622671 
    623672        $c = $options[$number]['count'] ? '1' : '0'; 
    624673        $h = $options[$number]['hierarchical'] ? '1' : '0'; 
     
    635684                wp_dropdown_categories($cat_args . '&show_option_none= ' . __('Select Category')); 
    636685?> 
    637686 
    638 <script type='text/javascript'><!-- 
     687<script type='text/javascript'> 
     688/* <![CDATA[ */ 
    639689    var dropdown = document.getElementById("cat"); 
    640690    function onCatChange() { 
    641691                if ( dropdown.options[dropdown.selectedIndex].value > 0 ) { 
     
    643693                } 
    644694    } 
    645695    dropdown.onchange = onCatChange; 
    646 --></script> 
     696/* ]]> */ 
     697</script> 
    647698 
    648699<?php 
    649700        } else { 
     
    657708        echo $after_widget; 
    658709} 
    659710 
    660 function wp_widget_categories_control( $number ) { 
    661         $options = $newoptions = get_option('widget_categories'); 
     711function wp_widget_categories_control( $widget_args ) { 
     712        global $wp_registered_widgets; 
     713        static $updated = false; 
    662714 
    663         if ( !is_array( $options ) ) { 
    664                 $options = $newoptions = get_option( 'widget_categories' ); 
    665         } 
     715        if ( is_numeric($widget_args) ) 
     716                $widget_args = array( 'number' => $widget_args ); 
     717        $widget_args = wp_parse_args( $widget_args, array( 'number' => -1 ) ); 
     718        extract($widget_args, EXTR_SKIP); 
    666719 
    667         if ( $_POST['categories-submit-' . $number] ) { 
    668                 $newoptions[$number]['count'] = isset($_POST['categories-count-' . $number]); 
    669                 $newoptions[$number]['hierarchical'] = isset($_POST['categories-hierarchical-' . $number]); 
    670                 $newoptions[$number]['dropdown'] = isset($_POST['categories-dropdown-' . $number]); 
    671                 $newoptions[$number]['title'] = strip_tags(stripslashes($_POST['categories-title-' . $number])); 
    672         } 
     720        $options = get_option('widget_categories'); 
    673721 
    674         if ( $options != $newoptions ) { 
    675                 $options = $newoptions; 
     722        if ( !is_array( $options ) ) 
     723                $options = array(); 
     724 
     725        if ( !$updated && !empty($_POST['sidebar']) ) { 
     726                $sidebar = (string) $_POST['sidebar']; 
     727                 
     728                $sidebars_widgets = wp_get_sidebars_widgets(); 
     729                if ( isset($sidebars_widgets[$sidebar]) ) 
     730                        $this_sidebar =& $sidebars_widgets[$sidebar]; 
     731                else 
     732                        $this_sidebar = array(); 
     733                 
     734                foreach ( $this_sidebar as $_widget_id ) { 
     735                        if ( 'wp_widget_categories' == $wp_registered_widgets[$_widget_id]['callback'] && isset($wp_registered_widgets[$_widget_id]['params'][0]['number']) ) { 
     736                                $widget_number = $wp_registered_widgets[$_widget_id]['params'][0]['number']; 
     737                                unset($options[$widget_number]); 
     738                        }    
     739                } 
     740 
     741                foreach ( (array) $_POST['widget-categories'] as $widget_number => $widget_cat ) { 
     742                        $title = trim(strip_tags(stripslashes($widget_cat['title']))); 
     743                        $count = isset($widget_cat['count']); 
     744                        $hierarchical = isset($widget_cat['hierarchical']); 
     745                        $dropdown = isset($widget_cat['dropdown']); 
     746                        $options[$widget_number] = compact( 'title', 'count', 'hierarchical', 'dropdown' ); 
     747                } 
     748 
    676749                update_option('widget_categories', $options); 
     750                $updated = true; 
    677751        } 
    678752 
    679         $title = attribute_escape( $options[$number]['title'] ); 
     753        if ( -1 == $number ) { 
     754                $title = ''; 
     755                $count = false; 
     756                $hierarchical = false; 
     757                $dropdown = false; 
     758                $number = '%i%'; 
     759        } else { 
     760                $title = attribute_escape( $options[$number]['title'] ); 
     761                $count = (bool) $options[$number]['count']; 
     762                $hierarchical = (bool) $options[$number]['hierarchical']; 
     763                $dropdown = (bool) $options[$number]['dropdown']; 
     764        } 
    680765?> 
    681                         <p><label for="categories-title-<?php echo $number; ?>"> 
    682                                 <?php _e( 'Title:' ); ?> <input style="width:300px" id="categories-title-<?php echo $number; ?>" name="categories-title-<?php echo $number; ?>" type="text" value="<?php echo $title; ?>" /> 
    683                         </label></p> 
     766                        <p> 
     767                                <label for="categories-title-<?php echo $number; ?>"> 
     768                                        <?php _e( 'Title:' ); ?>  
     769                                        <input class="widefat" id="categories-title-<?php echo $number; ?>" name="widget-categories[<?php echo $number; ?>][title]" type="text" value="<?php echo $title; ?>" /> 
     770                                </label> 
     771                        </p> 
    684772 
    685                         <p><label for="categories-dropdown-<?php echo $number; ?>"> 
    686                                 <input type="checkbox" class="checkbox" id="categories-dropdown-<?php echo $number; ?>" name="categories-dropdown-<?php echo $number; ?>"<?php echo $options[$number]['dropdown'] ? ' checked="checked"' : ''; ?> /> <?php _e( 'Show as dropdown' ); ?> 
    687                         </label></p> 
     773                        <p> 
     774                                <label for="categories-dropdown-<?php echo $number; ?>"> 
     775                                        <input type="checkbox" class="checkbox" id="categories-dropdown-<?php echo $number; ?>" name="widget-categories[<?php echo $number; ?>][dropdown]"<?php checked( $dropdown, true ); ?> /> 
     776                                        <?php _e( 'Show as dropdown' ); ?> 
     777                                </label> 
     778                                <br /> 
     779                                <label for="categories-count-<?php echo $number; ?>"> 
     780                                        <input type="checkbox" class="checkbox" id="categories-count-<?php echo $number; ?>" name="widget-categories[<?php echo $number; ?>][count]"<?php checked( $count, true ); ?> /> 
     781                                        <?php _e( 'Show post counts' ); ?> 
     782                                </label> 
     783                                <br /> 
     784                                <label for="categories-hierarchical-<?php echo $number; ?>"> 
     785                                        <input type="checkbox" class="checkbox" id="categories-hierarchical-<?php echo $number; ?>" name="widget-categories[<?php echo $number; ?>][hierarchical]"<?php checked( $hierarchical, true ); ?> /> 
     786                                        <?php _e( 'Show hierarchy' ); ?> 
     787                                </label> 
     788                        </p> 
    688789 
    689                         <p><label for="categories-count-<?php echo $number; ?>"> 
    690                                 <input type="checkbox" class="checkbox" id="categories-count-<?php echo $number; ?>" name="categories-count-<?php echo $number; ?>"<?php echo $options[$number]['count'] ? ' checked="checked"' : ''; ?> /> <?php _e( 'Show post counts' ); ?> 
    691                         </label></p> 
    692  
    693                         <p><label for="categories-hierarchical-<?php echo $number; ?>"> 
    694                                 <input type="checkbox" class="checkbox" id="categories-hierarchical-<?php echo $number; ?>" name="categories-hierarchical-<?php echo $number; ?>"<?php echo $options[$number]['hierarchical'] ? ' checked="checked"' : ''; ?> /> <?php _e( 'Show hierarchy' ); ?> 
    695                         </label></p> 
    696  
    697790                        <input type="hidden" id="categories-submit-<?php echo $number; ?>" name="categories-submit-<?php echo $number; ?>" value="1" /> 
    698791<?php 
    699792} 
    700793 
    701 function wp_widget_categories_setup() { 
    702         $options = $newoptions = get_option( 'widget_categories' ); 
     794function wp_widget_categories_register() { 
     795        $options = get_option( 'widget_categories' ); 
     796        if ( isset($options['title']) ) 
     797                $options = wp_widget_categories_upgrade(); 
    703798 
    704         if ( isset( $_POST['categories-number-submit'] ) ) { 
    705                 $number = (int) $_POST['categories-number']; 
     799        $widget_ops = array( 'classname' => 'widget_categories', 'description' => __( "A list or dropdown of categories" ) ); 
    706800 
    707                 if ( $number > 9 ) { 
    708                         $number = 9; 
    709                 } elseif ( $number < 1 ) { 
    710                         $number = 1; 
    711                 } 
     801        $name = __( 'Categories' ); 
    712802 
    713                 $newoptions['number'] = $number; 
     803        // If there are none, we register the widget's existance with a generic template 
     804        if ( !$options ) { 
     805                wp_register_sidebar_widget( 'categories-1', $name, 'wp_widget_categories', $widget_ops, array( 'number' => -1 ) ); 
     806                wp_register_widget_control( 'categories-1', $name, 'wp_widget_categories_control', array( 'id_base' => 'categories' ), array( 'number' => -1 ) ); 
    714807        } 
    715808 
    716         if ( $newoptions != $options ) { 
    717                 $options = $newoptions; 
    718                 update_option( 'widget_categories', $options ); 
    719                 wp_widget_categories_register( $options['number'] ); 
     809        foreach ( array_keys($options) as $o ) { 
     810                // Old widgets can have null values for some reason 
     811                if ( !isset($options[$o]['title']) ) 
     812                        continue; 
     813                $id = "categories-$o"; 
     814                wp_register_sidebar_widget( $id, $name, 'wp_widget_categories', $widget_ops, array( 'number' => $o ) ); 
     815                wp_register_widget_control( $id, $name, 'wp_widget_categories_control', array( 'id_base' => 'categories' ), array( 'number' => $o ) ); 
    720816        } 
    721 } 
    722817 
    723 function wp_widget_categories_page() { 
    724         $options = get_option( 'widget_categories' ); 
    725 ?> 
    726         <div class="wrap"> 
    727                 <form method="post"> 
    728                         <h2><?php _e( 'Categories Widgets' ); ?></h2> 
    729                         <p style="line-height: 30px;"><?php _e( 'How many categories widgets would you like?' ); ?> 
    730                                 <select id="categories-number" name="categories-number" value="<?php echo attribute_escape( $options['number'] ); ?>"> 
    731                                         <?php 
    732                                                 for ( $i = 1; $i < 10; $i++ ) { 
    733                                                         echo '<option value="' . $i . '"' . ( $i == $options['number'] ? ' selected="selected"' : '' ) . '>' . $i . "</option>\n"; 
    734                                                 } 
    735                                         ?> 
    736                                 </select> 
    737                                 <span class="submit"> 
    738                                         <input type="submit" value="<?php echo attribute_escape( __( 'Save' ) ); ?>" id="categories-number-submit" name="categories-number-submit" /> 
    739                                 </span> 
    740                         </p> 
    741                 </form> 
    742         </div> 
    743 <?php 
    744818} 
    745819 
    746820function wp_widget_categories_upgrade() { 
    747821        $options = get_option( 'widget_categories' ); 
    748822 
    749         $newoptions = array( 'number' => 1, 1 => $options ); 
     823        if ( !isset( $options['title'] ) ) 
     824                return $options; 
    750825 
     826        $newoptions = array( 1 => $options ); 
     827 
    751828        update_option( 'widget_categories', $newoptions ); 
    752829 
    753830        $sidebars_widgets = get_option( 'sidebars_widgets' ); 
     
    764841                        update_option( 'sidebars_widgets', $new_widgets ); 
    765842        } 
    766843 
    767         if ( isset( $_POST['categories-submit'] ) ) { 
    768                 $_POST['categories-submit-1'] = $_POST['categories-submit']; 
    769                 $_POST['categories-count-1'] = $_POST['categories-count']; 
    770                 $_POST['categories-hierarchical-1'] = $_POST['categories-hierarchical']; 
    771                 $_POST['categories-dropdown-1'] = $_POST['categories-dropdown']; 
    772                 $_POST['categories-title-1'] = $_POST['categories-title']; 
    773                 foreach ( $_POST as $k => $v ) 
    774                         if ( substr($k, -5) == 'order' ) 
    775                                 $_POST[$k] = str_replace('categories', 'categories-1', $v); 
    776         } 
    777  
    778844        return $newoptions; 
    779845} 
    780846 
    781 function wp_widget_categories_register() { 
    782         $options = get_option( 'widget_categories' ); 
    783         if ( !isset($options['number']) ) 
    784                 $options = wp_widget_categories_upgrade(); 
    785         $number = (int) $options['number']; 
    786  
    787         if ( $number > 9 ) { 
    788                 $number = 9; 
    789         } elseif ( $number < 1 ) { 
    790                 $number = 1; 
    791         } 
    792  
    793         $dims = array( 'width' => 350, 'height' => 170 ); 
    794         $class = array( 'classname' => 'widget_categories' ); 
    795  
    796         for ( $i = 1; $i <= 9; $i++ ) { 
    797                 $name = sprintf( __( 'Categories %d' ), $i ); 
    798                 $id = 'categories-' . $i; 
    799  
    800                 $widget_callback = ( $i <= $number ) ? 'wp_widget_categories' : ''; 
    801                 $control_callback = ( $i <= $number ) ? 'wp_widget_categories_control' : ''; 
    802  
    803                 wp_register_sidebar_widget( $id, $name, $widget_callback, $class, $i ); 
    804                 wp_register_widget_control( $id, $name, $control_callback, $dims, $i ); 
    805         } 
    806  
    807         add_action( 'sidebar_admin_setup', 'wp_widget_categories_setup' ); 
    808         add_action( 'sidebar_admin_page', 'wp_widget_categories_page' ); 
    809 } 
    810  
    811847function wp_widget_recent_entries($args) { 
    812848        if ( $output = wp_cache_get('widget_recent_entries') ) 
    813849                return print($output); 
     
    861897        if ( !$number = (int) $options['number'] ) 
    862898                $number = 5; 
    863899?> 
    864                         <p><label for="recent-entries-title"><?php _e('Title:'); ?> <input style="width: 250px;" id="recent-entries-title" name="recent-entries-title" type="text" value="<?php echo $title; ?>" /></label></p> 
    865                         <p><label for="recent-entries-number"><?php _e('Number of posts to show:'); ?> <input style="width: 25px; text-align: center;" id="recent-entries-number" name="recent-entries-number" type="text" value="<?php echo $number; ?>" /></label> <?php _e('(at most 15)'); ?></p> 
     900 
     901                        <p><label for="recent-entries-title"><?php _e('Title:'); ?> <input class="widefat" id="recent-entries-title" name="recent-entries-title" type="text" value="<?php echo $title; ?>" /></label></p> 
     902                        <p> 
     903                                <label for="recent-entries-number"><?php _e('Number of posts to show:'); ?> <input style="width: 25px; text-align: center;" id="recent-entries-number" name="recent-entries-number" type="text" value="<?php echo $number; ?>" /></label> 
     904                                <br /> 
     905                                <small><?php _e('(at most 15)'); ?></small> 
     906                        </p> 
    866907                        <input type="hidden" id="recent-entries-submit" name="recent-entries-submit" value="1" /> 
    867908<?php 
    868909} 
     
    916957        if ( !$number = (int) $options['number'] ) 
    917958                $number = 5; 
    918959?> 
    919                         <p><label for="recent-comments-title"><?php _e('Title:'); ?> <input style="width: 250px;" id="recent-comments-title" name="recent-comments-title" type="text" value="<?php echo $title; ?>" /></label></p> 
    920                         <p><label for="recent-comments-number"><?php _e('Number of comments to show:'); ?> <input style="width: 25px; text-align: center;" id="recent-comments-number" name="recent-comments-number" type="text" value="<?php echo $number; ?>" /></label> <?php _e('(at most 15)'); ?></p> 
     960                        <p><label for="recent-comments-title"><?php _e('Title:'); ?> <input class="widefat" id="recent-comments-title" name="recent-comments-title" type="text" value="<?php echo $title; ?>" /></label></p> 
     961                        <p> 
     962                                <label for="recent-comments-number"><?php _e('Number of comments to show:'); ?> <input style="width: 25px; text-align: center;" id="recent-comments-number" name="recent-comments-number" type="text" value="<?php echo $number; ?>" /></label> 
     963                                <br /> 
     964                                <small><?php _e('(at most 15)'); ?></small> 
     965                        </p> 
    921966                        <input type="hidden" id="recent-comments-submit" name="recent-comments-submit" value="1" /> 
    922967<?php 
    923968} 
     
    929974} 
    930975 
    931976function wp_widget_recent_comments_register() { 
    932         $dims = array('width' => 320, 'height' => 90); 
    933         $class = array('classname' => 'widget_recent_comments'); 
    934         wp_register_sidebar_widget('recent-comments', __('Recent Comments'), 'wp_widget_recent_comments', $class); 
    935         wp_register_widget_control('recent-comments', __('Recent Comments'), 'wp_widget_recent_comments_control', $dims); 
     977        $widget_ops = array('classname' => 'widget_recent_comments', 'description' => __( 'The most recent comments' ) ); 
     978        wp_register_sidebar_widget('recent-comments', __('Recent Comments'), 'wp_widget_recent_comments', $widget_ops); 
     979        wp_register_widget_control('recent-comments', __('Recent Comments'), 'wp_widget_recent_comments_control'); 
    936980 
    937981        if ( is_active_widget('wp_widget_recent_comments') ) 
    938982                add_action('wp_head', 'wp_widget_recent_comments_style'); 
    939983} 
    940984 
    941 function wp_widget_rss($args, $number = 1) { 
    942         require_once(ABSPATH . WPINC . '/rss.php'); 
    943         extract($args); 
     985// See large comment section at end of this file 
     986function wp_widget_rss($args, $widget_args = 1) { 
     987        extract($args, EXTR_SKIP); 
     988        if ( is_numeric($widget_args) ) 
     989                $widget_args = array( 'number' => $widegt_args ); 
     990        $widget_args = wp_parse_args( $widget_args, array( 'number' => -1 ) ); 
     991        extract($widget_args, EXTR_SKIP); 
     992 
    944993        $options = get_option('widget_rss'); 
    945         if ( isset($options['error']) && $options['error'] ) 
     994 
     995        if ( !isset($options[$number]) ) 
    946996                return; 
     997 
     998        if ( isset($options[$number]['error']) && $options[$number]['error'] ) 
     999                return; 
     1000 
    9471001        $num_items = (int) $options[$number]['items']; 
    9481002        $show_summary = $options[$number]['show_summary']; 
    9491003        if ( empty($num_items) || $num_items < 1 || $num_items > 10 ) $num_items = 10; 
     
    9521006                $url = substr($url, 1); 
    9531007        if ( empty($url) ) 
    9541008                return; 
     1009 
     1010        require_once(ABSPATH . WPINC . '/rss.php'); 
     1011 
    9551012        $rss = fetch_rss($url); 
    9561013        $link = clean_url(strip_tags($rss->channel['link'])); 
    9571014        while ( strstr($link, 'http') != $link ) 
     
    10021059        echo $after_widget; 
    10031060} 
    10041061 
    1005 function wp_widget_rss_control($number) { 
    1006         $options = $newoptions = get_option('widget_rss'); 
    1007         if ( $_POST["rss-submit-$number"] ) { 
    1008                 $newoptions[$number]['items'] = (int) $_POST["rss-items-$number"]; 
    1009                 $url = sanitize_url(strip_tags(stripslashes($_POST["rss-url-$number"]))); 
    1010                 $newoptions[$number]['title'] = trim(strip_tags(stripslashes($_POST["rss-title-$number"]))); 
    1011                 if ( $url !== $options[$number]['url'] ) { 
    1012                         require_once(ABSPATH . WPINC . '/rss.php'); 
    1013                         $rss = fetch_rss($url); 
    1014                         if ( is_object($rss) ) { 
    1015                                 $newoptions[$number]['url'] = $url; 
    1016                                 $newoptions[$number]['error'] = false; 
    1017                         } else { 
    1018                                 $newoptions[$number]['error'] = true; 
    1019                                 $newoptions[$number]['url'] = wp_specialchars(__('Error: could not find an RSS or ATOM feed at that URL.'), 1); 
     1062function wp_widget_rss_control($widget_args) { 
     1063        global $wp_registered_widgets; 
     1064        static $updated = false; 
     1065 
     1066        if ( is_numeric($widget_args) ) 
     1067                $widget_args = array( 'number' => $widget_args ); 
     1068        $widget_args = wp_parse_args( $widget_args, array( 'number' => -1 ) ); 
     1069        extract($widget_args, EXTR_SKIP); 
     1070 
     1071        $options = get_option('widget_rss'); 
     1072        if ( !is_array($options) ) 
     1073                $options = array(); 
     1074 
     1075        $urls = array(); 
     1076        foreach ( $options as $option ) 
     1077                if ( isset($option['url']) ) 
     1078                        $urls[$option['url']] = true; 
     1079 
     1080        if ( !$updated && !empty($_POST['sidebar']) ) { 
     1081                $sidebar = (string) $_POST['sidebar']; 
     1082 
     1083                $sidebars_widgets = wp_get_sidebars_widgets(); 
     1084                if ( isset($sidebars_widgets[$sidebar]) ) 
     1085                        $this_sidebar =& $sidebars_widgets[$sidebar]; 
     1086                else 
     1087                        $this_sidebar = array(); 
     1088         
     1089                foreach ( $this_sidebar as $_widget_id ) { 
     1090                        if ( 'wp_widget_rss' == $wp_registered_widgets[$_widget_id]['callback'] && isset($wp_registered_widgets[$_widget_id]['params'][0]['number']) ) { 
     1091                                $widget_number = $wp_registered_widgets[$_widget_id]['params'][0]['number']; 
     1092                                unset($options[$widget_number]); 
    10201093                        } 
    10211094                } 
    1022         } 
    1023         if ( $options != $newoptions ) { 
    1024                 $options = $newoptions; 
     1095 
     1096                foreach( (array) $_POST['widget-rss'] as $widget_number => $widget_rss ) { 
     1097                        $items = (int) $widget_rss['items']; 
     1098                        if ( $items < 1 ) 
     1099                                $items = 10; 
     1100                        $url = sanitize_url(strip_tags(stripslashes($widget_rss['url']))); 
     1101                        $title = trim(strip_tags(stripslashes($widget_rss['title']))); 
     1102 
     1103                        if ( !isset($urls[$url]) ) { 
     1104                                require_once(ABSPATH . WPINC . '/rss.php'); 
     1105                                $rss = fetch_rss($url); 
     1106                                $error = false; 
     1107                                if ( !is_object($rss) ) { 
     1108                                        $url = wp_specialchars(__('Error: could not find an RSS or ATOM feed at that URL.'), 1); 
     1109                                        $error = sprintf(__('Error in RSS %1$d'), $widget_number ); 
     1110                                } 
     1111                        } 
     1112                        $options[$widget_number] = compact( 'title', 'url', 'items', 'error' ); 
     1113                } 
     1114 
    10251115                update_option('widget_rss', $options); 
     1116                $updated = true; 
    10261117        } 
    1027         $url = attribute_escape($options[$number]['url']); 
    1028         $items = (int) $options[$number]['items']; 
    1029         $title = attribute_escape($options[$number]['title']); 
    1030         if ( empty($items) || $items < 1 ) $items = 10; 
    1031 ?> 
    1032                         <p style="text-align:center;"><?php _e('Enter the RSS feed URL here:'); ?></p> 
    1033                         <input style="width: 400px;" id="rss-url-<?php echo "$number"; ?>" name="rss-url-<?php echo "$number"; ?>" type="text" value="<?php echo $url; ?>" /> 
    1034                         <p style="text-align:center;"><?php _e('Give the feed a title (optional):'); ?></p> 
    1035                         <input style="width: 400px;" id="rss-title-<?php echo "$number"; ?>" name="rss-title-<?php echo "$number"; ?>" type="text" value="<?php echo $title; ?>" /> 
    1036                         <p style="text-align:center; line-height: 30px;"><?php _e('How many items would you like to display?'); ?> <select id="rss-items-<?php echo $number; ?>" name="rss-items-<?php echo $number; ?>"><?php for ( $i = 1; $i <= 10; ++$i ) echo "<option value='$i' ".($items==$i ? "selected='selected'" : '').">$i</option>"; ?></select></p> 
    1037                         <input type="hidden" id="rss-submit-<?php echo "$number"; ?>" name="rss-submit-<?php echo $number; ?>" value="1" /> 
    1038 <?php 
    1039 } 
    10401118 
    1041 function wp_widget_rss_setup() { 
    1042         $options = $newoptions = get_option('widget_rss'); 
    1043         if ( isset($_POST['rss-number-submit']) ) { 
    1044                 $number = (int) $_POST['rss-number']; 
    1045                 if ( $number > 9 ) $number = 9; 
    1046                 if ( $number < 1 ) $number = 1; 
    1047                 $newoptions['number'] = $number; 
     1119        if ( -1 == $number ) { 
     1120                $title = ''; 
     1121                $url = ''; 
     1122                $items = 10; 
     1123                $error = false; 
     1124                $number = '%i%'; 
     1125        } else { 
     1126                $title = attribute_escape($options[$number]['title']); 
     1127                $url = attribute_escape($options[$number]['url']); 
     1128