Make WordPress Core


Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/wp-includes/widgets.php

    r6183 r7548  
    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
    1513function register_sidebars($number = 1, $args = array()) {
     14    global $wp_registered_sidebars;
    1615    $number = (int) $number;
    1716
     
    1918        parse_str($args, $args);
    2019
    21     $i = 1;
    22 
    23     while ( $i <= $number ) {
     20    for ( $i=1; $i <= $number; $i++ ) {
    2421        $_args = $args;
     22
    2523        if ( $number > 1 ) {
    26             $_args['name'] = isset($args['name']) ? $args['name'] : sprintf(__('Sidebar %d'), $i);
     24            $_args['name'] = isset($args['name']) ? sprintf($args['name'], $i) : sprintf(__('Sidebar %d'), $i);
    2725        } else {
    2826            $_args['name'] = isset($args['name']) ? $args['name'] : __('Sidebar');
    2927        }
    30         $_args['id'] = isset($args['id']) ? $args['id'] : "sidebar-$i";
     28
     29        if (isset($args['id'])) {
     30            $_args['id'] = $args['id'];
     31        } else {
     32            $n = count($wp_registered_sidebars);
     33            do {
     34                $n++;
     35                $_args['id'] = "sidebar-$n";
     36            } while (isset($wp_registered_sidebars[$_args['id']]));
     37        }
     38
    3139        register_sidebar($_args);
    32         ++$i;
    3340    }
    3441}
     
    8794
    8895function wp_register_sidebar_widget($id, $name, $output_callback, $options = array()) {
    89 
    90     global $wp_registered_widgets, $wp_register_widget_defaults;
    91 
    92     $id = sanitize_title($id);
     96    global $wp_registered_widgets;
    9397
    9498    if ( empty($output_callback) ) {
     
    107111    $widget = array_merge($widget, $options);
    108112
    109     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' ) ) )
    110114        $wp_registered_widgets[$id] = $widget;
     115}
     116
     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'] );
    111125}
    112126
     
    143157}
    144158
     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 multi-widgets (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 */
    145165function wp_register_widget_control($id, $name, $control_callback, $options = array()) {
    146     global $wp_registered_widget_controls, $wp_register_widget_defaults;
    147 
    148     $id = sanitize_title($id);
     166    global $wp_registered_widget_controls;
    149167
    150168    if ( empty($control_callback) ) {
     
    153171    }
    154172
    155     if ( isset($wp_registered_widget_controls[$id]) && $wp_register_widget_defaults )
     173    if ( isset($wp_registered_widget_controls[$id]) && !did_action( 'widgets_init' ) )
    156174        return;
    157175
    158     $defaults = array('width' => 300, 'height' => 200);
     176    $defaults = array('width' => 250, 'height' => 200 ); // height is never used
    159177    $options = wp_parse_args($options, $defaults);
    160178    $options['width'] = (int) $options['width'];
    161179    $options['height'] = (int) $options['height'];
    162     $options['width'] = $options['width'] > 90 ? $options['width'] + 60 : 360;
    163     $options['height'] = $options['height'] > 60 ? $options['height'] + 40 : 240;
    164180
    165181    $widget = array(
     
    199215    $sidebars_widgets = wp_get_sidebars_widgets();
    200216
    201     if ( empty($wp_registered_sidebars[$index]) || !is_array($sidebars_widgets[$index]) || empty($sidebars_widgets[$index]) )
     217    if ( empty($wp_registered_sidebars[$index]) || !array_key_exists($index, $sidebars_widgets) || !is_array($sidebars_widgets[$index]) || empty($sidebars_widgets[$index]) )
    202218        return false;
    203219
     
    206222    $did_one = false;
    207223    foreach ( $sidebars_widgets[$index] as $id ) {
    208         $callback = $wp_registered_widgets[$id]['callback'];
    209 
    210         $params = array_merge(array($sidebar), (array) $wp_registered_widgets[$id]['params']);
     224        $params = array_merge(
     225            array( array_merge( $sidebar, array('widget_id' => $id, 'widget_name' => $wp_registered_widgets[$id]['name']) ) ),
     226            (array) $wp_registered_widgets[$id]['params']
     227        );
    211228
    212229        // Substitute HTML id and class attributes into before_widget
     
    221238        $params[0]['before_widget'] = sprintf($params[0]['before_widget'], $id, $classname_);
    222239
     240        $params = apply_filters( 'dynamic_sidebar_params', $params );
     241
     242        $callback = $wp_registered_widgets[$id]['callback'];
     243
    223244        if ( is_callable($callback) ) {
    224245            call_user_func_array($callback, $params);
     
    230251}
    231252
    232 function is_active_widget($callback) {
     253/* @return mixed false if widget is not active or id of sidebar in which the widget is active
     254 */
     255function is_active_widget($callback, $widget_id = false) {
    233256    global $wp_registered_widgets;
    234257
     
    237260    if ( is_array($sidebars_widgets) ) foreach ( $sidebars_widgets as $sidebar => $widgets )
    238261        if ( is_array($widgets) ) foreach ( $widgets as $widget )
    239             if ( $wp_registered_widgets[$widget]['callback'] == $callback )
    240                 return true;
     262            if ( isset($wp_registered_widgets[$widget]['callback']) && $wp_registered_widgets[$widget]['callback'] == $callback )
     263                if ( !$widget_id || $widget_id == $wp_registered_widgets[$widget]['id'] )
     264                    return $sidebar;
     265
    241266
    242267    return false;
     
    383408    $exclude = attribute_escape( $options['exclude'] );
    384409?>
    385             <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>
    386             <p><label for="pages-sortby"><?php _e( 'Sort by:' ); ?>
    387                 <select name="pages-sortby" id="pages-sortby">
     410        <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>
     411        <p>
     412            <label for="pages-sortby"><?php _e( 'Sort by:' ); ?>
     413                <select name="pages-sortby" id="pages-sortby" class="widefat">
    388414                    <option value="post_title"<?php selected( $options['sortby'], 'post_title' ); ?>><?php _e('Page title'); ?></option>
    389415                    <option value="menu_order"<?php selected( $options['sortby'], 'menu_order' ); ?>><?php _e('Page order'); ?></option>
    390416                    <option value="ID"<?php selected( $options['sortby'], 'ID' ); ?>><?php _e( 'Page ID' ); ?></option>
    391                 </select></label></p>
    392             <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 />
    393             <small><?php _e( 'Page IDs, separated by commas.' ); ?></small></p>
    394             <input type="hidden" id="pages-submit" name="pages-submit" value="1" />
     417                </select>
     418            </label>
     419        </p>
     420        <p>
     421            <label for="pages-exclude"><?php _e( 'Exclude:' ); ?> <input type="text" value="<?php echo $exclude; ?>" name="pages-exclude" id="pages-exclude" class="widefat" /></label>
     422            <br />
     423            <small><?php _e( 'Page IDs, separated by commas.' ); ?></small>
     424        </p>
     425        <input type="hidden" id="pages-submit" name="pages-submit" value="1" />
    395426<?php
    396427}
     
    459490    $title = attribute_escape($options['title']);
    460491?>
    461             <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>
    462             <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>
    463             <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>
     492            <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>
     493            <p>
     494                <label for="archives-count"><input class="checkbox" type="checkbox" <?php echo $count; ?> id="archives-count" name="archives-count" /> <?php _e('Show post counts'); ?></label>
     495                <br />
     496                <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>
     497            </p>
    464498            <input type="hidden" id="archives-submit" name="archives-submit" value="1" />
    465499<?php
     
    495529    $title = attribute_escape($options['title']);
    496530?>
    497             <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>
     531            <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>
    498532            <input type="hidden" id="meta-submit" name="meta-submit" value="1" />
    499533<?php
     
    523557    $title = attribute_escape($options['title']);
    524558?>
    525             <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>
     559            <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>
    526560            <input type="hidden" id="calendar-submit" name="calendar-submit" value="1" />
    527561<?php
    528562}
    529563
    530 function wp_widget_text($args, $number = 1) {
    531     extract($args);
     564// See large comment section at end of this file
     565function wp_widget_text($args, $widget_args = 1) {
     566    extract( $args, EXTR_SKIP );
     567    if ( is_numeric($widget_args) )
     568        $widget_args = array( 'number' => $widget_args );
     569    $widget_args = wp_parse_args( $widget_args, array( 'number' => -1 ) );
     570    extract( $widget_args, EXTR_SKIP );
     571
    532572    $options = get_option('widget_text');
     573    if ( !isset($options[$number]) )
     574        return;
     575
    533576    $title = $options[$number]['title'];
    534577    $text = apply_filters( 'widget_text', $options[$number]['text'] );
     
    541584}
    542585
    543 function wp_widget_text_control($number) {
    544     $options = $newoptions = get_option('widget_text');
     586function wp_widget_text_control($widget_args) {
     587    global $wp_registered_widgets;
     588    static $updated = false;
     589
     590    if ( is_numeric($widget_args) )
     591        $widget_args = array( 'number' => $widget_args );
     592    $widget_args = wp_parse_args( $widget_args, array( 'number' => -1 ) );
     593    extract( $widget_args, EXTR_SKIP );
     594
     595    $options = get_option('widget_text');
    545596    if ( !is_array($options) )
    546         $options = $newoptions = array();
    547     if ( $_POST["text-submit-$number"] ) {
    548         $newoptions[$number]['title'] = strip_tags(stripslashes($_POST["text-title-$number"]));
    549         $newoptions[$number]['text'] = stripslashes($_POST["text-text-$number"]);
    550         if ( !current_user_can('unfiltered_html') )
    551             $newoptions[$number]['text'] = stripslashes(wp_filter_post_kses($newoptions[$number]['text']));
    552     }
    553     if ( $options != $newoptions ) {
    554         $options = $newoptions;
     597        $options = array();
     598
     599    if ( !$updated && !empty($_POST['sidebar']) ) {
     600        $sidebar = (string) $_POST['sidebar'];
     601
     602        $sidebars_widgets = wp_get_sidebars_widgets();
     603        if ( isset($sidebars_widgets[$sidebar]) )
     604            $this_sidebar =& $sidebars_widgets[$sidebar];
     605        else
     606            $this_sidebar = array();
     607
     608        foreach ( $this_sidebar as $_widget_id ) {
     609            if ( 'wp_widget_text' == $wp_registered_widgets[$_widget_id]['callback'] && isset($wp_registered_widgets[$_widget_id]['params'][0]['number']) ) {
     610                $widget_number = $wp_registered_widgets[$_widget_id]['params'][0]['number'];
     611                if ( !in_array( "text-$widget_number", $_POST['widget-id'] ) ) // the widget has been removed.
     612                    unset($options[$widget_number]);
     613            }
     614        }
     615
     616        foreach ( (array) $_POST['widget-text'] as $widget_number => $widget_text ) {
     617            $title = strip_tags(stripslashes($widget_text['title']));
     618            if ( current_user_can('unfiltered_html') )
     619                $text = stripslashes( $widget_text['text'] );
     620            else
     621                $text = stripslashes(wp_filter_post_kses( $widget_text['text'] ));
     622            $options[$widget_number] = compact( 'title', 'text' );
     623        }
     624
    555625        update_option('widget_text', $options);
    556     }
    557     $title = attribute_escape($options[$number]['title']);
    558     $text = format_to_edit($options[$number]['text']);
    559 ?>
    560             <input style="width: 450px;" id="text-title-<?php echo $number; ?>" name="text-title-<?php echo $number; ?>" type="text" value="<?php echo $title; ?>" />
    561             <textarea style="width: 450px; height: 280px;" id="text-text-<?php echo $number; ?>" name="text-text-<?php echo $number; ?>"><?php echo $text; ?></textarea>
    562             <input type="hidden" id="text-submit-<?php echo "$number"; ?>" name="text-submit-<?php echo "$number"; ?>" value="1" />
    563 <?php
    564 }
    565 
    566 function wp_widget_text_setup() {
    567     $options = $newoptions = get_option('widget_text');
    568     if ( isset($_POST['text-number-submit']) ) {
    569         $number = (int) $_POST['text-number'];
    570         if ( $number > 9 ) $number = 9;
    571         if ( $number < 1 ) $number = 1;
    572         $newoptions['number'] = $number;
    573     }
    574     if ( $options != $newoptions ) {
    575         $options = $newoptions;
    576         update_option('widget_text', $options);
    577         wp_widget_text_register($options['number']);
    578     }
    579 }
    580 
    581 function wp_widget_text_page() {
    582     $options = $newoptions = get_option('widget_text');
    583 ?>
    584     <div class="wrap">
    585         <form method="POST">
    586             <h2><?php _e('Text Widgets'); ?></h2>
    587             <p style="line-height: 30px;"><?php _e('How many text widgets would you like?'); ?>
    588             <select id="text-number" name="text-number" value="<?php echo $options['number']; ?>">
    589 <?php for ( $i = 1; $i < 10; ++$i ) echo "<option value='$i' ".($options['number']==$i ? "selected='selected'" : '').">$i</option>"; ?>
    590             </select>
    591             <span class="submit"><input type="submit" name="text-number-submit" id="text-number-submit" value="<?php echo attribute_escape(__('Save')); ?>" /></span></p>
    592         </form>
    593     </div>
     626        $updated = true;
     627    }
     628
     629    if ( -1 == $number ) {
     630        $title = '';
     631        $text = '';
     632        $number = '%i%';
     633    } else {
     634        $title = attribute_escape($options[$number]['title']);
     635        $text = format_to_edit($options[$number]['text']);
     636    }
     637?>
     638        <p>
     639            <input class="widefat" id="text-title-<?php echo $number; ?>" name="widget-text[<?php echo $number; ?>][title]" type="text" value="<?php echo $title; ?>" />
     640            <textarea class="widefat" rows="16" cols="20" id="text-text-<?php echo $number; ?>" name="widget-text[<?php echo $number; ?>][text]"><?php echo $text; ?></textarea>
     641            <input type="hidden" name="widget-text[<?php echo $number; ?>][submit]" value="1" />
     642        </p>
    594643<?php
    595644}
    596645
    597646function wp_widget_text_register() {
    598     $options = get_option('widget_text');
    599     $number = $options['number'];
    600     if ( $number < 1 ) $number = 1;
    601     if ( $number > 9 ) $number = 9;
    602     $dims = array('width' => 460, 'height' => 350);
    603     $class = array('classname' => 'widget_text');
    604     for ($i = 1; $i <= 9; $i++) {
    605         $name = sprintf(__('Text %d'), $i);
    606         $id = "text-$i"; // Never never never translate an id
    607         wp_register_sidebar_widget($id, $name, $i <= $number ? 'wp_widget_text' : /* unregister */ '', $class, $i);
    608         wp_register_widget_control($id, $name, $i <= $number ? 'wp_widget_text_control' : /* unregister */ '', $dims, $i);
    609     }
    610     add_action('sidebar_admin_setup', 'wp_widget_text_setup');
    611     add_action('sidebar_admin_page', 'wp_widget_text_page');
    612 }
    613 
    614 function wp_widget_categories($args, $number = 1) {
    615     extract($args);
     647    if ( !$options = get_option('widget_text') )
     648        $options = array();
     649    $widget_ops = array('classname' => 'widget_text', 'description' => __('Arbitrary text or HTML'));
     650    $control_ops = array('width' => 400, 'height' => 350, 'id_base' => 'text');
     651    $name = __('Text');
     652
     653    $id = false;
     654    foreach ( array_keys($options) as $o ) {
     655        // Old widgets can have null values for some reason
     656        if ( !isset($options[$o]['title']) || !isset($options[$o]['text']) )
     657            continue;
     658        $id = "text-$o"; // Never never never translate an id
     659        wp_register_sidebar_widget($id, $name, 'wp_widget_text', $widget_ops, array( 'number' => $o ));
     660        wp_register_widget_control($id, $name, 'wp_widget_text_control', $control_ops, array( 'number' => $o ));
     661    }
     662
     663    // If there are none, we register the widget's existance with a generic template
     664    if ( !$id ) {
     665        wp_register_sidebar_widget( 'text-1', $name, 'wp_widget_text', $widget_ops, array( 'number' => -1 ) );
     666        wp_register_widget_control( 'text-1', $name, 'wp_widget_text_control', $control_ops, array( 'number' => -1 ) );
     667    }
     668}
     669
     670// See large comment section at end of this file
     671function wp_widget_categories($args, $widget_args = 1) {
     672    extract($args, EXTR_SKIP);
     673    if ( is_numeric($widget_args) )
     674        $widget_args = array( 'number' => $widget_args );
     675    $widget_args = wp_parse_args( $widget_args, array( 'number' => -1 ) );
     676    extract($widget_args, EXTR_SKIP);
     677
    616678    $options = get_option('widget_categories');
     679    if ( !isset($options[$number]) )
     680        return;
    617681
    618682    $c = $options[$number]['count'] ? '1' : '0';
     
    631695?>
    632696
    633 <script lang='javascript'><!--
     697<script type='text/javascript'>
     698/* <![CDATA[ */
    634699    var dropdown = document.getElementById("cat");
    635700    function onCatChange() {
     
    639704    }
    640705    dropdown.onchange = onCatChange;
    641 --></script>
     706/* ]]> */
     707</script>
    642708
    643709<?php
     
    653719}
    654720
    655 function wp_widget_categories_control( $number ) {
    656     $options = $newoptions = get_option('widget_categories');
    657 
    658     if ( !is_array( $options ) ) {
    659         $options = $newoptions = get_option( 'widget_categories' );
    660     }
    661 
    662     if ( $_POST['categories-submit-' . $number] ) {
    663         $newoptions[$number]['count'] = isset($_POST['categories-count-' . $number]);
    664         $newoptions[$number]['hierarchical'] = isset($_POST['categories-hierarchical-' . $number]);
    665         $newoptions[$number]['dropdown'] = isset($_POST['categories-dropdown-' . $number]);
    666         $newoptions[$number]['title'] = strip_tags(stripslashes($_POST['categories-title-' . $number]));
    667     }
    668 
    669     if ( $options != $newoptions ) {
    670         $options = $newoptions;
     721function wp_widget_categories_control( $widget_args ) {
     722    global $wp_registered_widgets;
     723    static $updated = false;
     724
     725    if ( is_numeric($widget_args) )
     726        $widget_args = array( 'number' => $widget_args );
     727    $widget_args = wp_parse_args( $widget_args, array( 'number' => -1 ) );
     728    extract($widget_args, EXTR_SKIP);
     729
     730    $options = get_option('widget_categories');
     731
     732    if ( !is_array( $options ) )
     733        $options = array();
     734
     735    if ( !$updated && !empty($_POST['sidebar']) ) {
     736        $sidebar = (string) $_POST['sidebar'];
     737
     738        $sidebars_widgets = wp_get_sidebars_widgets();
     739        if ( isset($sidebars_widgets[$sidebar]) )
     740            $this_sidebar =& $sidebars_widgets[$sidebar];
     741        else
     742            $this_sidebar = array();
     743
     744        foreach ( $this_sidebar as $_widget_id ) {
     745            if ( 'wp_widget_categories' == $wp_registered_widgets[$_widget_id]['callback'] && isset($wp_registered_widgets[$_widget_id]['params'][0]['number']) ) {
     746                $widget_number = $wp_registered_widgets[$_widget_id]['params'][0]['number'];
     747                if ( !in_array( "categories-$widget_number", $_POST['widget-id'] ) ) // the widget has been removed.
     748                    unset($options[$widget_number]);
     749            }
     750        }
     751
     752        foreach ( (array) $_POST['widget-categories'] as $widget_number => $widget_cat ) {
     753            $title = trim(strip_tags(stripslashes($widget_cat['title'])));
     754            $count = isset($widget_cat['count']);
     755            $hierarchical = isset($widget_cat['hierarchical']);
     756            $dropdown = isset($widget_cat['dropdown']);
     757            $options[$widget_number] = compact( 'title', 'count', 'hierarchical', 'dropdown' );
     758        }
     759
    671760        update_option('widget_categories', $options);
    672     }
    673 
    674     $title = attribute_escape( $options[$number]['title'] );
    675 ?>
    676             <p><label for="categories-title-<?php echo $number; ?>">
    677                 <?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; ?>" />
    678             </label></p>
    679 
    680             <p><label for="categories-dropdown-<?php echo $number; ?>">
    681                 <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' ); ?>
    682             </label></p>
    683 
    684             <p><label for="categories-count-<?php echo $number; ?>">
    685                 <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' ); ?>
    686             </label></p>
    687 
    688             <p><label for="categories-hierarchical-<?php echo $number; ?>">
    689                 <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' ); ?>
    690             </label></p>
    691 
    692             <input type="hidden" id="categories-submit-<?php echo $number; ?>" name="categories-submit-<?php echo $number; ?>" value="1" />
    693 <?php
    694 }
    695 
    696 function wp_widget_categories_setup() {
    697     $options = $newoptions = get_option( 'widget_categories' );
    698 
    699     if ( isset( $_POST['categories-number-submit'] ) ) {
    700         $number = (int) $_POST['categories-number'];
    701 
    702         if ( $number > 9 ) {
    703             $number = 9;
    704         } elseif ( $number < 1 ) {
    705             $number = 1;
    706         }
    707 
    708         $newoptions['number'] = $number;
    709     }
    710 
    711     if ( $newoptions != $options ) {
    712         $options = $newoptions;
    713         update_option( 'widget_categories', $options );
    714         wp_widget_categories_register( $options['number'] );
    715     }
    716 }
    717 
    718 function wp_widget_categories_page() {
    719     $options = get_option( 'widget_categories' );
    720 ?>
    721     <div class="wrap">
    722         <form method="post">
    723             <h2><?php _e( 'Categories Widgets' ); ?></h2>
    724             <p style="line-height: 30px;"><?php _e( 'How many categories widgets would you like?' ); ?>
    725                 <select id="categories-number" name="categories-number" value="<?php echo attribute_escape( $options['number'] ); ?>">
    726                     <?php
    727                         for ( $i = 1; $i < 10; $i++ ) {
    728                             echo '<option value="' . $i . '"' . ( $i == $options['number'] ? ' selected="selected"' : '' ) . '>' . $i . "</option>\n";
    729                         }
    730                     ?>
    731                 </select>
    732                 <span class="submit">
    733                     <input type="submit" value="<?php echo attribute_escape( __( 'Save' ) ); ?>" id="categories-number-submit" name="categories-number-submit" />
    734                 </span>
     761        $updated = true;
     762    }
     763
     764    if ( -1 == $number ) {
     765        $title = '';
     766        $count = false;
     767        $hierarchical = false;
     768        $dropdown = false;
     769        $number = '%i%';
     770    } else {
     771        $title = attribute_escape( $options[$number]['title'] );
     772        $count = (bool) $options[$number]['count'];
     773        $hierarchical = (bool) $options[$number]['hierarchical'];
     774        $dropdown = (bool) $options[$number]['dropdown'];
     775    }
     776?>
     777            <p>
     778                <label for="categories-title-<?php echo $number; ?>">
     779                    <?php _e( 'Title:' ); ?>
     780                    <input class="widefat" id="categories-title-<?php echo $number; ?>" name="widget-categories[<?php echo $number; ?>][title]" type="text" value="<?php echo $title; ?>" />
     781                </label>
    735782            </p>
    736         </form>
    737     </div>
    738 <?php
     783
     784            <p>
     785                <label for="categories-dropdown-<?php echo $number; ?>">
     786                    <input type="checkbox" class="checkbox" id="categories-dropdown-<?php echo $number; ?>" name="widget-categories[<?php echo $number; ?>][dropdown]"<?php checked( $dropdown, true ); ?> />
     787                    <?php _e( 'Show as dropdown' ); ?>
     788                </label>
     789                <br />
     790                <label for="categories-count-<?php echo $number; ?>">
     791                    <input type="checkbox" class="checkbox" id="categories-count-<?php echo $number; ?>" name="widget-categories[<?php echo $number; ?>][count]"<?php checked( $count, true ); ?> />
     792                    <?php _e( 'Show post counts' ); ?>
     793                </label>
     794                <br />
     795                <label for="categories-hierarchical-<?php echo $number; ?>">
     796                    <input type="checkbox" class="checkbox" id="categories-hierarchical-<?php echo $number; ?>" name="widget-categories[<?php echo $number; ?>][hierarchical]"<?php checked( $hierarchical, true ); ?> />
     797                    <?php _e( 'Show hierarchy' ); ?>
     798                </label>
     799            </p>
     800
     801            <input type="hidden" name="widget-categories[<?php echo $number; ?>][submit]" value="1" />
     802<?php
     803}
     804
     805function wp_widget_categories_register() {
     806    if ( !$options = get_option( 'widget_categories' ) )
     807        $options = array();
     808
     809    if ( isset($options['title']) )
     810        $options = wp_widget_categories_upgrade();
     811
     812    $widget_ops = array( 'classname' => 'widget_categories', 'description' => __( "A list or dropdown of categories" ) );
     813
     814    $name = __( 'Categories' );
     815
     816    $id = false;
     817    foreach ( array_keys($options) as $o ) {
     818        // Old widgets can have null values for some reason
     819        if ( !isset($options[$o]['title']) )
     820            continue;
     821        $id = "categories-$o";
     822        wp_register_sidebar_widget( $id, $name, 'wp_widget_categories', $widget_ops, array( 'number' => $o ) );
     823        wp_register_widget_control( $id, $name, 'wp_widget_categories_control', array( 'id_base' => 'categories' ), array( 'number' => $o ) );
     824    }
     825
     826    // If there are none, we register the widget's existance with a generic template
     827    if ( !$id ) {
     828        wp_register_sidebar_widget( 'categories-1', $name, 'wp_widget_categories', $widget_ops, array( 'number' => -1 ) );
     829        wp_register_widget_control( 'categories-1', $name, 'wp_widget_categories_control', array( 'id_base' => 'categories' ), array( 'number' => -1 ) );
     830    }
    739831}
    740832
     
    742834    $options = get_option( 'widget_categories' );
    743835
    744     $newoptions = array( 'number' => 1, 1 => $options );
     836    if ( !isset( $options['title'] ) )
     837        return $options;
     838
     839    $newoptions = array( 1 => $options );
    745840
    746841    update_option( 'widget_categories', $newoptions );
     
    760855    }
    761856
    762     if ( isset( $_POST['categories-submit'] ) ) {
    763         $_POST['categories-submit-1'] = $_POST['categories-submit'];
    764         $_POST['categories-count-1'] = $_POST['categories-count'];
    765         $_POST['categories-hierarchical-1'] = $_POST['categories-hierarchical'];
    766         $_POST['categories-dropdown-1'] = $_POST['categories-dropdown'];
    767         $_POST['categories-title-1'] = $_POST['categories-title'];
    768         foreach ( $_POST as $k => $v )
    769             if ( substr($k, -5) == 'order' )
    770                 $_POST[$k] = str_replace('categories', 'categories-1', $v);
    771     }
    772 
    773857    return $newoptions;
    774858}
    775859
    776 function wp_widget_categories_register() {
    777     $options = get_option( 'widget_categories' );
    778     if ( !isset($options['number']) )
    779         $options = wp_widget_categories_upgrade();
    780     $number = (int) $options['number'];
    781 
    782     if ( $number > 9 ) {
    783         $number = 9;
    784     } elseif ( $number < 1 ) {
    785         $number = 1;
    786     }
    787 
    788     $dims = array( 'width' => 350, 'height' => 170 );
    789     $class = array( 'classname' => 'widget_categories' );
    790 
    791     for ( $i = 1; $i <= 9; $i++ ) {
    792         $name = sprintf( __( 'Categories %d' ), $i );
    793         $id = 'categories-' . $i;
    794 
    795         $widget_callback = ( $i <= $number ) ? 'wp_widget_categories' : '';
    796         $control_callback = ( $i <= $number ) ? 'wp_widget_categories_control' : '';
    797 
    798         wp_register_sidebar_widget( $id, $name, $widget_callback, $class, $i );
    799         wp_register_widget_control( $id, $name, $control_callback, $dims, $i );
    800     }
    801 
    802     add_action( 'sidebar_admin_setup', 'wp_widget_categories_setup' );
    803     add_action( 'sidebar_admin_page', 'wp_widget_categories_page' );
    804 }
    805 
    806860function wp_widget_recent_entries($args) {
    807     if ( $output = wp_cache_get('widget_recent_entries') )
     861    if ( $output = wp_cache_get('widget_recent_entries', 'widget') )
    808862        return print($output);
    809863
     
    831885        <?php echo $after_widget; ?>
    832886<?php
     887        wp_reset_query();  // Restore global post data stomped by the_post().
    833888    endif;
    834     wp_cache_add('widget_recent_entries', ob_get_flush());
     889    wp_cache_add('widget_recent_entries', ob_get_flush(), 'widget');
    835890}
    836891
    837892function wp_flush_widget_recent_entries() {
    838     wp_cache_delete('widget_recent_entries');
     893    wp_cache_delete('widget_recent_entries', 'widget');
    839894}
    840895
    841896add_action('save_post', 'wp_flush_widget_recent_entries');
    842897add_action('deleted_post', 'wp_flush_widget_recent_entries');
     898add_action('switch_theme', 'wp_flush_widget_recent_entries');
    843899
    844900function wp_widget_recent_entries_control() {
     
    857913        $number = 5;
    858914?>
    859             <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>
    860             <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>
     915
     916            <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>
     917            <p>
     918                <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>
     919                <br />
     920                <small><?php _e('(at most 15)'); ?></small>
     921            </p>
    861922            <input type="hidden" id="recent-entries-submit" name="recent-entries-submit" value="1" />
    862923<?php
     
    912973        $number = 5;
    913974?>
    914             <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>
    915             <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>
     975            <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>
     976            <p>
     977                <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>
     978                <br />
     979                <small><?php _e('(at most 15)'); ?></small>
     980            </p>
    916981            <input type="hidden" id="recent-comments-submit" name="recent-comments-submit" value="1" />
    917982<?php
     
    925990
    926991function wp_widget_recent_comments_register() {
    927     $dims = array('width' => 320, 'height' => 90);
    928     $class = array('classname' => 'widget_recent_comments');
    929     wp_register_sidebar_widget('recent-comments', __('Recent Comments'), 'wp_widget_recent_comments', $class);
    930     wp_register_widget_control('recent-comments', __('Recent Comments'), 'wp_widget_recent_comments_control', $dims);
     992    $widget_ops = array('classname' => 'widget_recent_comments', 'description' => __( 'The most recent comments' ) );
     993    wp_register_sidebar_widget('recent-comments', __('Recent Comments'), 'wp_widget_recent_comments', $widget_ops);
     994    wp_register_widget_control('recent-comments', __('Recent Comments'), 'wp_widget_recent_comments_control');
    931995
    932996    if ( is_active_widget('wp_widget_recent_comments') )
     
    934998}
    935999
    936 function wp_widget_rss($args, $number = 1) {
    937     require_once(ABSPATH . WPINC . '/rss.php');
    938     extract($args);
     1000// See large comment section at end of this file
     1001function wp_widget_rss($args, $widget_args = 1) {
     1002    extract($args, EXTR_SKIP);
     1003    if ( is_numeric($widget_args) )
     1004        $widget_args = array( 'number' => $widegt_args );
     1005    $widget_args = wp_parse_args( $widget_args, array( 'number' => -1 ) );
     1006    extract($widget_args, EXTR_SKIP);
     1007
    9391008    $options = get_option('widget_rss');
    940     if ( isset($options['error']) && $options['error'] )
     1009
     1010    if ( !isset($options[$number]) )
    9411011        return;
    942     $num_items = (int) $options[$number]['items'];
    943     $show_summary = $options[$number]['show_summary'];
    944     if ( empty($num_items) || $num_items < 1 || $num_items > 10 ) $num_items = 10;
     1012
     1013    if ( isset($options[$number]['error']) && $options[$number]['error'] )
     1014        return;
     1015
    9451016    $url = $options[$number]['url'];
    9461017    while ( strstr($url, 'http') != $url )
     
    9481019    if ( empty($url) )
    9491020        return;
     1021
     1022    require_once(ABSPATH . WPINC . '/rss.php');
     1023
    9501024    $rss = fetch_rss($url);
    9511025    $link = clean_url(strip_tags($rss->channel['link']));
     
    9661040        $icon = get_option('siteurl').'/wp-includes/images/rss.png';
    9671041    $title = "<a class='rsswidget' href='$url' title='" . attribute_escape(__('Syndicate this content')) ."'><img style='background:orange;color:white;border:none;' width='14' height='14' src='$icon' alt='RSS' /></a> <a class='rsswidget' href='$link' title='$desc'>$title</a>";
    968 ?>
    969         <?php echo $before_widget; ?>
    970             <?php $title ? print($before_title . $title . $after_title) : null; ?>
    971 <?php
     1042
     1043    echo $before_widget;
     1044    echo $before_title . $title . $after_title;
     1045
     1046    wp_widget_rss_output( $rss, $options[$number] );
     1047
     1048    echo $after_widget;
     1049}
     1050
     1051function wp_widget_rss_output( $rss, $args = array() ) {
     1052    if ( is_string( $rss ) ) {
     1053        require_once(ABSPATH . WPINC . '/rss.php');
     1054        if ( !$rss = fetch_rss($rss) )
     1055            return;
     1056    } elseif ( is_array($rss) && isset($rss['url']) ) {
     1057        require_once(ABSPATH . WPINC . '/rss.php');
     1058        $args = $rss;
     1059        if ( !$rss = fetch_rss($rss['url']) )
     1060            return;
     1061    } elseif ( !is_object($rss) ) {
     1062        return;
     1063    }
     1064
     1065    extract( $args, EXTR_SKIP );
     1066
     1067    $items = (int) $items;
     1068    if ( $items < 1 || 20 < $items )
     1069        $items = 10;
     1070    $show_summary  = (int) $show_summary;
     1071    $show_author   = (int) $show_author;
     1072    $show_date     = (int) $show_date;
     1073
    9721074    if ( is_array( $rss->items ) && !empty( $rss->items ) ) {
    973         $rss->items = array_slice($rss->items, 0, $num_items);
     1075        $rss->items = array_slice($rss->items, 0, $items);
    9741076        echo '<ul>';
    9751077        foreach ($rss->items as $item ) {
     
    9811083                $title = __('Untitled');
    9821084            $desc = '';
    983             if ( $show_summary ) {
    984                 $summary = '<div class="rssSummary">' . $item['description'] . '</div>';
    985             } else {
    9861085                if ( isset( $item['description'] ) && is_string( $item['description'] ) )
    9871086                    $desc = str_replace(array("\n", "\r"), ' ', attribute_escape(strip_tags(html_entity_decode($item['description'], ENT_QUOTES))));
     1087                elseif ( isset( $item['summary'] ) && is_string( $item['summary'] ) )
     1088                    $desc = str_replace(array("\n", "\r"), ' ', attribute_escape(strip_tags(html_entity_decode($item['summary'], ENT_QUOTES))));
     1089
     1090            $summary = '';
     1091            if ( isset( $item['description'] ) && is_string( $item['description'] ) )
     1092                $summary = $item['description'];
     1093            elseif ( isset( $item['summary'] ) && is_string( $item['summary'] ) )
     1094                $summary = $item['summary'];
     1095
     1096            $desc = str_replace(array("\n", "\r"), ' ', attribute_escape(strip_tags(html_entity_decode($summary, ENT_QUOTES))));
     1097
     1098            if ( $show_summary ) {
     1099                $desc = '';
     1100                $summary = wp_specialchars( $summary );
     1101                $summary = "<div class='rssSummary'>$summary</div>";
     1102            } else {
    9881103                $summary = '';
    9891104            }
    990             echo "<li><a class='rsswidget' href='$link' title='$desc'>$title</a>$summary</li>";
     1105
     1106            $date = '';
     1107            if ( $show_date ) {
     1108                if ( isset($item['pubdate']) )
     1109                    $date = $item['pubdate'];
     1110                elseif ( isset($item['published']) )
     1111                    $date = $item['published'];
     1112
     1113                if ( $date ) {
     1114                    if ( $date_stamp = strtotime( $date ) )
     1115                        $date = '<span class="rss-date">' . date_i18n( get_option( 'date_format' ), $date_stamp ) . '</span>';
     1116                    else
     1117                        $date = '';
     1118                }
     1119            }
     1120
     1121            $author = '';
     1122            if ( $show_author ) {
     1123                if ( isset($item['dc']['creator']) )
     1124                    $author = ' <cite>' . wp_specialchars( strip_tags( $item['dc']['creator'] ) ) . '</cite>';
     1125                elseif ( isset($item['author_name']) )
     1126                    $author = ' <cite>' . wp_specialchars( strip_tags( $item['author_name'] ) ) . '</cite>';
     1127            }
     1128
     1129            echo "<li><a class='rsswidget' href='$link' title='$desc'>$title</a>{$date}{$summary}{$author}</li>";
    9911130        }
    9921131        echo '</ul>';
     
    9941133        echo '<ul><li>' . __( 'An error has occurred; the feed is probably down. Try again later.' ) . '</li></ul>';
    9951134    }
    996 
    997     echo $after_widget;
    998 }
    999 
    1000 function wp_widget_rss_control($number) {
    1001     $options = $newoptions = get_option('widget_rss');
    1002     if ( $_POST["rss-submit-$number"] ) {
    1003         $newoptions[$number]['items'] = (int) $_POST["rss-items-$number"];
    1004         $url = sanitize_url(strip_tags(stripslashes($_POST["rss-url-$number"])));
    1005         $newoptions[$number]['title'] = trim(strip_tags(stripslashes($_POST["rss-title-$number"])));
    1006         if ( $url !== $options[$number]['url'] ) {
    1007             require_once(ABSPATH . WPINC . '/rss.php');
    1008             $rss = fetch_rss($url);
    1009             if ( is_object($rss) ) {
    1010                 $newoptions[$number]['url'] = $url;
    1011                 $newoptions[$number]['error'] = false;
    1012             } else {
    1013                 $newoptions[$number]['error'] = true;
    1014                 $newoptions[$number]['url'] = wp_specialchars(__('Error: could not find an RSS or ATOM feed at that URL.'), 1);
    1015                 $error = sprintf(__('Error in RSS %1$d: %2$s'), $number, $newoptions[$number]['error']);
     1135}
     1136
     1137function wp_widget_rss_control($widget_args) {
     1138    global $wp_registered_widgets;
     1139    static $updated = false;
     1140
     1141    if ( is_numeric($widget_args) )
     1142        $widget_args = array( 'number' => $widget_args );
     1143    $widget_args = wp_parse_args( $widget_args, array( 'number' => -1 ) );
     1144    extract($widget_args, EXTR_SKIP);
     1145
     1146    $options = get_option('widget_rss');
     1147    if ( !is_array($options) )
     1148        $options = array();
     1149
     1150    $urls = array();
     1151    foreach ( $options as $option )
     1152        if ( isset($option['url']) )
     1153            $urls[$option['url']] = true;
     1154
     1155    if ( !$updated && 'POST' == $_SERVER['REQUEST_METHOD'] && !empty($_POST['sidebar']) ) {
     1156        $sidebar = (string) $_POST['sidebar'];
     1157
     1158        $sidebars_widgets = wp_get_sidebars_widgets();
     1159        if ( isset($sidebars_widgets[$sidebar]) )
     1160            $this_sidebar =& $sidebars_widgets[$sidebar];
     1161        else
     1162            $this_sidebar = array();
     1163
     1164        foreach ( $this_sidebar as $_widget_id ) {
     1165            if ( 'wp_widget_rss' == $wp_registered_widgets[$_widget_id]['callback'] && isset($wp_registered_widgets[$_widget_id]['params'][0]['number']) ) {
     1166                $widget_number = $wp_registered_widgets[$_widget_id]['params'][0]['number'];
     1167                if ( !in_array( "rss-$widget_number", $_POST['widget-id'] ) ) // the widget has been removed.
     1168                    unset($options[$widget_number]);
    10161169            }
    10171170        }
    1018     }
    1019     if ( $options != $newoptions ) {
    1020         $options = $newoptions;
     1171
     1172        foreach( (array) $_POST['widget-rss'] as $widget_number => $widget_rss ) {
     1173            $widget_rss = stripslashes_deep( $widget_rss );
     1174            $url = sanitize_url(strip_tags($widget_rss['url']));
     1175            $options[$widget_number] = wp_widget_rss_process( $widget_rss, !isset($urls[$url]) );
     1176        }
     1177
    10211178        update_option('widget_rss', $options);
    1022     }
    1023     $url = attribute_escape($options[$number]['url']);
    1024     $items = (int) $options[$number]['items'];
    1025     $title = attribute_escape($options[$number]['title']);
    1026     if ( empty($items) || $items < 1 ) $items = 10;
    1027 ?>
    1028             <p style="text-align:center;"><?php _e('Enter the RSS feed URL here:'); ?></p>
    1029             <input style="width: 400px;" id="rss-url-<?php echo "$number"; ?>" name="rss-url-<?php echo "$number"; ?>" type="text" value="<?php echo $url; ?>" />
    1030             <p style="text-align:center;"><?php _e('Give the feed a title (optional):'); ?></p>
    1031             <input style="width: 400px;" id="rss-title-<?php echo "$number"; ?>" name="rss-title-<?php echo "$number"; ?>" type="text" value="<?php echo $title; ?>" />
    1032             <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>
    1033             <input type="hidden" id="rss-submit-<?php echo "$number"; ?>" name="rss-submit-<?php echo "$number"; ?>" value="1" />
    1034 <?php
    1035 }
    1036 
    1037 function wp_widget_rss_setup() {
    1038     $options = $newoptions = get_option('widget_rss');
    1039     if ( isset($_POST['rss-number-submit']) ) {
    1040         $number = (int) $_POST['rss-number'];
    1041         if ( $number > 9 ) $number = 9;
    1042         if ( $number < 1 ) $number = 1;
    1043         $newoptions['number'] = $number;
    1044     }
    1045     if ( $options != $newoptions ) {
    1046         $options = $newoptions;
    1047         update_option('widget_rss', $options);
    1048         wp_widget_rss_register($options['number']);
    1049     }
    1050 }
    1051 
    1052 function wp_widget_rss_page() {
    1053     $options = $newoptions = get_option('widget_rss');
    1054 ?>
    1055     <div class="wrap">
    1056         <form method="POST">
    1057             <h2><?php _e('RSS Feed Widgets'); ?></h2>
    1058             <p style="line-height: 30px;"><?php _e('How many RSS widgets would you like?'); ?>
    1059             <select id="rss-number" name="rss-number" value="<?php echo $options['number']; ?>">
    1060 <?php for ( $i = 1; $i < 10; ++$i ) echo "<option value='$i' ".($options['number']==$i ? "selected='selected'" : '').">$i</option>"; ?>
     1179        $updated = true;
     1180    }
     1181
     1182    if ( -1 == $number ) {
     1183        $title = '';
     1184        $url = '';
     1185        $items = 10;
     1186        $error = false;
     1187        $number = '%i%';
     1188        $show_summary = 0;
     1189        $show_author = 0;
     1190        $show_date = 0;
     1191    } else {
     1192        extract( (array) $options[$number] );
     1193    }
     1194
     1195    wp_widget_rss_form( compact( 'number', 'title', 'url', 'items', 'error', 'show_summary', 'show_author', 'show_date' ) );
     1196}
     1197
     1198function wp_widget_rss_form( $args, $inputs = null ) {
     1199    $default_inputs = array( 'url' => true, 'title' => true, 'items' => true, 'show_summary' => true, 'show_author' => true, 'show_date' => true );
     1200    $inputs = wp_parse_args( $inputs, $default_inputs );
     1201    extract( $args );
     1202    $number = attribute_escape( $number );
     1203    $title  = attribute_escape( $title );
     1204    $url    = attribute_escape( $url );
     1205    $items  = (int) $items;
     1206    if ( $items < 1 || 20 < $items )
     1207        $items  = 10;
     1208    $show_summary   = (int) $show_summary;
     1209    $show_author    = (int) $show_author;
     1210    $show_date      = (int) $show_date;
     1211
     1212    if ( $inputs['url'] ) :
     1213?>
     1214    <p>
     1215        <label for="rss-url-<?php echo $number; ?>"><?php _e('Enter the RSS feed URL here:'); ?>
     1216            <input class="widefat" id="rss-url-<?php echo $number; ?>" name="widget-rss[<?php echo $number; ?>][url]" type="text" value="<?php echo $url; ?>" />
     1217        </label>
     1218    </p>
     1219<?php endif; if ( $inputs['title'] ) : ?>
     1220    <p>
     1221        <label for="rss-title-<?php echo $number; ?>"><?php _e('Give the feed a title (optional):'); ?>
     1222            <input class="widefat" id="rss-title-<?php echo $number; ?>" name="widget-rss[<?php echo $number; ?>][title]" type="text" value="<?php echo $title; ?>" />
     1223        </label>
     1224    </p>
     1225<?php endif; if ( $inputs['items'] ) : ?>
     1226    <p>
     1227        <label for="rss-items-<?php echo $number; ?>"><?php _e('How many items would you like to display?'); ?>
     1228            <select id="rss-items-<?php echo $number; ?>" name="widget-rss[<?php echo $number; ?>][items]">
     1229                <?php
     1230                    for ( $i = 1; $i <= 20; ++$i )
     1231                        echo "<option value='$i' " . ( $items == $i ? "selected='selected'" : '' ) . ">$i</option>";
     1232                ?>
    10611233            </select>
    1062             <span class="submit"><input type="submit" name="rss-number-submit" id="rss-number-submit" value="<?php echo attribute_escape(__('Save')); ?>" /></span></p>
    1063         </form>
    1064     </div>
    1065 <?php
     1234        </label>
     1235    </p>
     1236<?php endif; if ( $inputs['show_summary'] ) : ?>
     1237    <p>
     1238        <label for="rss-show-summary-<?php echo $number; ?>">
     1239            <input id="rss-show-summary-<?php echo $number; ?>" name="widget-rss[<?php echo $number; ?>][show_summary]" type="checkbox" value="1" <?php if ( $show_summary ) echo 'checked="checked"'; ?>/>
     1240            <?php _e('Display item content?'); ?>
     1241        </label>
     1242    </p>
     1243<?php endif; if ( $inputs['show_author'] ) : ?>
     1244    <p>
     1245        <label for="rss-show-author-<?php echo $number; ?>">
     1246            <input id="rss-show-author-<?php echo $number; ?>" name="widget-rss[<?php echo $number; ?>][show_author]" type="checkbox" value="1" <?php if ( $show_author ) echo 'checked="checked"'; ?>/>
     1247            <?php _e('Display item author if available?'); ?>
     1248        </label>
     1249    </p>
     1250<?php endif; if ( $inputs['show_date'] ) : ?>
     1251    <p>
     1252        <label for="rss-show-date-<?php echo $number; ?>">
     1253            <input id="rss-show-date-<?php echo $number; ?>" name="widget-rss[<?php echo $number; ?>][show_date]" type="checkbox" value="1" <?php if ( $show_date ) echo 'checked="checked"'; ?>/>
     1254            <?php _e('Display item date?'); ?>
     1255        </label>
     1256    </p>
     1257    <input type="hidden" name="widget-rss[<?php echo $number; ?>][submit]" value="1" />
     1258<?php
     1259    endif;
     1260    foreach ( array_keys($default_inputs) as $input ) :
     1261        if ( 'hidden' === $inputs[$input] ) :
     1262            $id = str_replace( '_', '-', $input );
     1263?>
     1264    <input type="hidden" id="rss-<?php echo $id; ?>-<?php echo $number; ?>" name="widget-rss[<?php echo $number; ?>][<?php echo $input; ?>]" value="<?php echo $$input; ?>" />
     1265<?php
     1266        endif;
     1267    endforeach;
     1268}
     1269
     1270// Expects unescaped data
     1271function wp_widget_rss_process( $widget_rss, $check_feed = true ) {
     1272    $items = (int) $widget_rss['items'];
     1273    if ( $items < 1 || 20 < $items )
     1274        $items = 10;
     1275    $url           = sanitize_url(strip_tags( $widget_rss['url'] ));
     1276    $title         = trim(strip_tags( $widget_rss['title'] ));
     1277    $show_summary  = (int) $widget_rss['show_summary'];
     1278    $show_author   = (int) $widget_rss['show_author'];
     1279    $show_date     = (int) $widget_rss['show_date'];
     1280
     1281    if ( $check_feed ) {
     1282        require_once(ABSPATH . WPINC . '/rss.php');
     1283        $rss = fetch_rss($url);
     1284        $error = false;
     1285        $link = '';
     1286        if ( !is_object($rss) ) {
     1287            $url = wp_specialchars(__('Error: could not find an RSS or ATOM feed at that URL.'), 1);
     1288            $error = sprintf(__('Error in RSS %1$d'), $widget_number );
     1289        } else {
     1290            $link = clean_url(strip_tags($rss->channel['link']));
     1291            while ( strstr($link, 'http') != $link )
     1292                $link = substr($link, 1);
     1293        }
     1294    }
     1295
     1296    return compact( 'title', 'url', 'link', 'items', 'error', 'show_summary', 'show_author', 'show_date' );
    10661297}
    10671298
    10681299function wp_widget_rss_register() {
    1069     $options = get_option('widget_rss');
    1070     $number = $options['number'];
    1071     if ( $number < 1 ) $number = 1;
    1072     if ( $number > 9 ) $number = 9;
    1073     $dims = array('width' => 410, 'height' => 200);
    1074     $class = array('classname' => 'widget_rss');
    1075     for ($i = 1; $i <= 9; $i++) {
    1076         $name = sprintf(__('RSS %d'), $i);
    1077         $id = "rss-$i"; // Never never never translate an id
    1078         wp_register_sidebar_widget($id, $name, $i <= $number ? 'wp_widget_rss' : /* unregister */ '', $class, $i);
    1079         wp_register_widget_control($id, $name, $i <= $number ? 'wp_widget_rss_control' : /* unregister */ '', $dims, $i);
    1080     }
    1081     add_action('sidebar_admin_setup', 'wp_widget_rss_setup');
    1082     add_action('sidebar_admin_page', 'wp_widget_rss_page');
     1300    if ( !$options = get_option('widget_rss') )
     1301        $options = array();
     1302    $widget_ops = array('classname' => 'widget_rss', 'description' => __( 'Entries from any RSS or Atom feed' ));
     1303    $control_ops = array('width' => 400, 'height' => 200, 'id_base' => 'rss');
     1304    $name = __('RSS');
     1305
     1306    $id = false;
     1307    foreach ( array_keys($options) as $o ) {
     1308        // Old widgets can have null values for some reason
     1309        if ( !isset($options[$o]['url']) || !isset($options[$o]['title']) || !isset($options[$o]['items']) )
     1310            continue;
     1311        $id = "rss-$o"; // Never never never translate an id
     1312        wp_register_sidebar_widget($id, $name, 'wp_widget_rss', $widget_ops, array( 'number' => $o ));
     1313        wp_register_widget_control($id, $name, 'wp_widget_rss_control', $control_ops, array( 'number' => $o ));
     1314    }
     1315
     1316    // If there are none, we register the widget's existance with a generic template
     1317    if ( !$id ) {
     1318        wp_register_sidebar_widget( 'rss-1', $name, 'wp_widget_rss', $widget_ops, array( 'number' => -1 ) );
     1319        wp_register_widget_control( 'rss-1', $name, 'wp_widget_rss_control', $control_ops, array( 'number' => -1 ) );
     1320    }
    10831321}
    10841322
     
    11091347?>
    11101348    <p><label for="tag-cloud-title">
    1111     <?php _e('Title:') ?> <input type="text" style="width:300px" id="tag-cloud-title" name="tag-cloud-title" value="<?php echo $title ?>" /></label>
     1349    <?php _e('Title:') ?> <input type="text" class="widefat" id="tag-cloud-title" name="tag-cloud-title" value="<?php echo $title ?>" /></label>
    11121350    </p>
    11131351    <input type="hidden" name="tag-cloud-submit" id="tag-cloud-submit" value="1" />
     
    11191357        return;
    11201358
    1121     $GLOBALS['wp_register_widget_defaults'] = true;
    1122 
    1123     $dims90 = array( 'height' => 90, 'width' => 300 );
    1124     $dims100 = array( 'height' => 100, 'width' => 300 );
    1125     $dims150 = array( 'height' => 150, 'width' => 300 );
    1126 
    1127     $class = array('classname' => 'widget_pages');
    1128     wp_register_sidebar_widget('pages', __('Pages'), 'wp_widget_pages', $class);
    1129     wp_register_widget_control('pages', __('Pages'), 'wp_widget_pages_control', $dims150);
    1130 
    1131     $class['classname'] = 'widget_calendar';
    1132     wp_register_sidebar_widget('calendar', __('Calendar'), 'wp_widget_calendar', $class);
    1133     wp_register_widget_control('calendar', __('Calendar'), 'wp_widget_calendar_control', $dims90);
    1134 
    1135     $class['classname'] = 'widget_archives';
    1136     wp_register_sidebar_widget('archives', __('Archives'), 'wp_widget_archives', $class);
    1137     wp_register_widget_control('archives', __('Archives'), 'wp_widget_archives_control', $dims100);
    1138 
    1139     $class['classname'] = 'widget_links';
    1140     wp_register_sidebar_widget('links', __('Links'), 'wp_widget_links', $class);
    1141 
    1142     $class['classname'] = 'widget_meta';
    1143     wp_register_sidebar_widget('meta', __('Meta'), 'wp_widget_meta', $class);
    1144     wp_register_widget_control('meta', __('Meta'), 'wp_widget_meta_control', $dims90);
    1145 
    1146     $class['classname'] = 'widget_search';
    1147     wp_register_sidebar_widget('search', __('Search'), 'wp_widget_search', $class);
    1148 
    1149     $class['classname'] = 'widget_recent_entries';
    1150     wp_register_sidebar_widget('recent-posts', __('Recent Posts'), 'wp_widget_recent_entries', $class);
    1151     wp_register_widget_control('recent-posts', __('Recent Posts'), 'wp_widget_recent_entries_control', $dims90);
    1152 
    1153     $class['classname'] = 'widget_tag_cloud';
    1154     wp_register_sidebar_widget('tag_cloud', __('Tag Cloud'), 'wp_widget_tag_cloud', $class);
    1155     wp_register_widget_control('tag_cloud', __('Tag Cloud'), 'wp_widget_tag_cloud_control', 'width=300&height=160');
     1359    $widget_ops = array('classname' => 'widget_pages', 'description' => __( "Your blog's WordPress Pages") );
     1360    wp_register_sidebar_widget('pages', __('Pages'), 'wp_widget_pages', $widget_ops);
     1361    wp_register_widget_control('pages', __('Pages'), 'wp_widget_pages_control' );
     1362
     1363    $widget_ops = array('classname' => 'widget_calendar', 'description' => __( "A calendar of your blog's posts") );
     1364    wp_register_sidebar_widget('calendar', __('Calendar'), 'wp_widget_calendar', $widget_ops);
     1365    wp_register_widget_control('calendar', __('Calendar'), 'wp_widget_calendar_control' );
     1366
     1367    $widget_ops = array('classname' => 'widget_archive', 'description' => __( "A monthly archive of your blog's posts") );
     1368    wp_register_sidebar_widget('archives', __('Archives'), 'wp_widget_archives', $widget_ops);
     1369    wp_register_widget_control('archives', __('Archives'), 'wp_widget_archives_control' );
     1370
     1371    $widget_ops = array('classname' => 'widget_links', 'description' => __( "Your blogroll") );
     1372    wp_register_sidebar_widget('links', __('Links'), 'wp_widget_links', $widget_ops);
     1373
     1374    $widget_ops = array('classname' => 'widget_meta', 'description' => __( "Log in/out, admin, feed and WordPress links") );
     1375    wp_register_sidebar_widget('meta', __('Meta'), 'wp_widget_meta', $widget_ops);
     1376    wp_register_widget_control('meta', __('Meta'), 'wp_widget_meta_control' );
     1377
     1378    $widget_ops = array('classname' => 'widget_search', 'description' => __( "A search form for your blog") );
     1379    wp_register_sidebar_widget('search', __('Search'), 'wp_widget_search', $widget_ops);
     1380
     1381    $widget_ops = array('classname' => 'widget_recent_entries', 'description' => __( "The most recent posts on your blog") );
     1382    wp_register_sidebar_widget('recent-posts', __('Recent Posts'), 'wp_widget_recent_entries', $widget_ops);
     1383    wp_register_widget_control('recent-posts', __('Recent Posts'), 'wp_widget_recent_entries_control' );
     1384
     1385    $widget_ops = array('classname' => 'widget_tag_cloud', 'description' => __( "Your most used tags in cloud format") );
     1386    wp_register_sidebar_widget('tag_cloud', __('Tag Cloud'), 'wp_widget_tag_cloud', $widget_ops);
     1387    wp_register_widget_control('tag_cloud', __('Tag Cloud'), 'wp_widget_tag_cloud_control' );
    11561388
    11571389    wp_widget_categories_register();
     
    11601392    wp_widget_recent_comments_register();
    11611393
    1162     $GLOBALS['wp_register_widget_defaults'] = false;
    1163 
    11641394    do_action('widgets_init');
    11651395}
     
    11671397add_action('init', 'wp_widgets_init', 1);
    11681398
    1169 ?>
     1399/* Pattern for multi-widget (allows multiple instances such as the text widget).
     1400
     1401// Displays widget on blag
     1402// $widget_args: number
     1403//    number: which of the several widgets of this type do we mean
     1404function widget_many( $args, $widget_args = 1 ) {
     1405    extract( $args, EXTR_SKIP );
     1406    if ( is_numeric($widget_args) )
     1407        $widget_args = array( 'number' => $widget_args );
     1408    $widget_args = wp_parse_args( $widget_args, array( 'number' => -1 ) );
     1409    extract( $widget_args, EXTR_SKIP );
     1410
     1411    // Data should be stored as array:  array( number => data for that instance of the widget, ... )
     1412    $options = get_option('widget_many');
     1413    if ( !isset($options[$number]) )
     1414        return;
     1415
     1416    echo $before_widget;
     1417
     1418    // Do stuff for this widget, drawing data from $options[$number]
     1419
     1420    echo $after_widget;
     1421}
     1422
     1423// Displays form for a particular instance of the widget.  Also updates the data after a POST submit
     1424// $widget_args: number
     1425//    number: which of the several widgets of this type do we mean
     1426function widget_many_control( $widget_args = 1 ) {
     1427    global $wp_registered_widgets;
     1428    static $updated = false; // Whether or not we have already updated the data after a POST submit
     1429
     1430    if ( is_numeric($widget_args) )
     1431        $widget_args = array( 'number' => $widget_args );
     1432    $widget_args = wp_parse_args( $widget_args, array( 'number' => -1 ) );
     1433    extract( $widget_args, EXTR_SKIP );
     1434
     1435    // Data should be stored as array:  array( number => data for that instance of the widget, ... )
     1436    $options = get_option('widget_many');
     1437    if ( !is_array($options) )
     1438        $options = array();
     1439
     1440    // We need to update the data
     1441    if ( !$updated && !empty($_POST['sidebar']) ) {
     1442        // Tells us what sidebar to put the data in
     1443        $sidebar = (string) $_POST['sidebar'];
     1444
     1445        $sidebars_widgets = wp_get_sidebars_widgets();
     1446        if ( isset($sidebars_widgets[$sidebar]) )
     1447            $this_sidebar =& $sidebars_widgets[$sidebar];
     1448        else
     1449            $this_sidebar = array();
     1450
     1451        foreach ( $this_sidebar as $_widget_id ) {
     1452            // Remove all widgets of this type from the sidebar.  We'll add the new data in a second.  This makes sure we don't get any duplicate data
     1453            // since widget ids aren't necessarily persistent across multiple updates
     1454            if ( 'widget_many' == $wp_registered_widgets[$_widget_id]['callback'] && isset($wp_registered_widgets[$_widget_id]['params'][0]['number']) ) {
     1455                $widget_number = $wp_registered_widgets[$_widget_id]['params'][0]['number'];
     1456                if ( !in_array( "many-$widget_number", $_POST['widget-id'] ) ) // the widget has been removed. "many-$widget_number" is "{id_base}-{widget_number}
     1457                    unset($options[$widget_number]);
     1458            }
     1459        }
     1460
     1461        foreach ( (array) $_POST['widget-many'] as $widget_number => $widget_many_instance ) {
     1462            // compile data from $widget_many_instance
     1463            $something = wp_specialchars( $widget_many_instance['something'] );
     1464            $options[$widget_number] = array( 'something' => $something );  // Even simple widgets should store stuff in array, rather than in scalar
     1465        }
     1466
     1467        update_option('widget_text', $options);
     1468
     1469        $updated = true; // So that we don't go through this more than once
     1470    }
     1471
     1472
     1473    // Here we echo out the form
     1474    if ( -1 == $number ) { // We echo out a template for a form which can be converted to a specific form later via JS
     1475        $something = '';
     1476        $number = '%i%';
     1477    } else {
     1478        $something = attribute_escape($options[$number]['something']);
     1479    }
     1480
     1481    // The form has inputs with names like widget-many[$number][something] so that all data for that instance of
     1482    // the widget are stored in one $_POST variable: $_POST['widget-many'][$number]
     1483?>
     1484        <p>
     1485            <input class="widefat" id="widget-many-something-<?php echo $number; ?>" name="widget-many[<?php echo $number; ?>][something]" type="text" value="<?php echo $data; ?>" />
     1486            <input type="hidden" id="widget-many-submit-<?php echo $number; ?>" name="widget-many[<?php echo $number; ?>][submit]" value="1" />
     1487        </p>
     1488<?php
     1489}
     1490
     1491// Registers each instance of our widget on startup
     1492function widget_many_register() {
     1493    if ( !$options = get_option('widget_many') )
     1494        $options = array();
     1495
     1496    $widget_ops = array('classname' => 'widget_many', 'description' => __('Widget which allows multiple instances'));
     1497    $control_ops = array('width' => 400, 'height' => 350, 'id_base' => 'many');
     1498    $name = __('Many');
     1499
     1500    $registered = false;
     1501    foreach ( array_keys($options) as $o ) {
     1502        // Old widgets can have null values for some reason
     1503        if ( !isset($options[$o]['something']) ) // we used 'something' above in our exampple.  Replace with with whatever your real data are.
     1504            continue;
     1505
     1506        // $id should look like {$id_base}-{$o}
     1507        $id = "many-$o"; // Never never never translate an id
     1508        $registered = true;
     1509        wp_register_sidebar_widget( $id, $name, 'wp_widget_text', $widget_ops, array( 'number' => $o ) );
     1510        wp_register_widget_control( $id, $name, 'wp_widget_text_control', $control_ops, array( 'number' => $o ) );
     1511    }
     1512
     1513    // If there are none, we register the widget's existance with a generic template
     1514    if ( !$registered ) {
     1515        wp_register_sidebar_widget( 'many-1', $name, 'widget_many', $widget_ops, array( 'number' => -1 ) );
     1516        wp_register_widget_control( 'many-1', $name, 'widget_many_control', $control_ops, array( 'number' => -1 ) );
     1517    }
     1518}
     1519
     1520// This is important
     1521add_action( 'widgets_init', 'widget_many_register' )
     1522
     1523*/
     1524
     1525?>
Note: See TracChangeset for help on using the changeset viewer.