Make WordPress Core

Changeset 6556


Ignore:
Timestamp:
01/04/2008 11:34:33 PM (17 years ago)
Author:
ryan
Message:

Widget admin redesign from mdawaffe. see #5583

Location:
trunk
Files:
1 added
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/wp-admin/admin-ajax.php

    r6542 r6556  
    11<?php
     2define('DOING_AJAX', true);
     3
    24require_once('../wp-config.php');
    35require_once('includes/admin.php');
    4 
    5 define('DOING_AJAX', true);
    66
    77if ( !is_user_logged_in() )
  • trunk/wp-admin/includes/admin.php

    r5892 r6556  
    1414require_once(ABSPATH . 'wp-admin/includes/user.php');
    1515require_once(ABSPATH . 'wp-admin/includes/update.php');
     16require_once(ABSPATH . 'wp-admin/includes/widgets.php');
    1617
    1718require_once(ABSPATH . WPINC . '/registration.php');
  • trunk/wp-admin/widgets.php

    r6026 r6556  
    11<?php
    22
    3 require_once 'admin.php';
     3require_once( 'admin.php' );
    44
    55if ( ! current_user_can('switch_themes') )
    66    wp_die( __( 'Cheatin&#8217; uh?' ));
    77
    8 wp_enqueue_script('interface');
    9 
    10 function wp_widgets_admin_head() {
    11     global $wp_registered_sidebars, $wp_registered_widgets, $wp_registered_widget_controls;
    12 ?>
    13     <?php wp_admin_css( 'css/widgets' ); ?>
    14     <!--[if IE 7]>
    15     <style type="text/css">
    16         #palette { float: <?php echo ( get_bloginfo( 'text_direction' ) == 'rtl' ) ? 'right' : 'left'; ?>; }
    17     </style>
    18     <![endif]-->
    19 <?php
    20 
    21     $cols = array();
    22     foreach ( $wp_registered_sidebars as $index => $sidebar ) {
    23         $cols[] = '\'' . $index . '\'';
    24     }
    25     $cols = implode( ', ', $cols );
    26 
    27     $widgets = array();
    28     foreach ( $wp_registered_widgets as $name => $widget ) {
    29         $widgets[] = '\'' . $widget['id'] . '\'';
    30     }
    31     $widgets = implode( ', ', $widgets );
    32 ?>
    33 <script type="text/javascript">
    34 // <![CDATA[
    35     var cols = [<?php echo $cols; ?>];
    36     var widgets = [<?php echo $widgets; ?>];
    37     var controldims = new Array;
    38     <?php foreach ( $wp_registered_widget_controls as $name => $widget ) : ?>
    39         controldims['#<?php echo $widget['id']; ?>control'] = new Array;
    40         controldims['#<?php echo $widget['id']; ?>control']['width'] = <?php echo (int) $widget['width']; ?>;
    41         controldims['#<?php echo $widget['id']; ?>control']['height'] = <?php echo (int) $widget['height']; ?>;
    42     <?php endforeach; ?>
    43     function initWidgets() {
    44     <?php foreach ( $wp_registered_widget_controls as $name => $widget ) : ?>
    45         jQuery('#<?php echo $widget['id']; ?>popper').click(function() {popControl('#<?php echo $widget['id']; ?>control');});
    46         jQuery('#<?php echo $widget['id']; ?>closer').click(function() {unpopControl('#<?php echo $widget['id']; ?>control');});
    47         jQuery('#<?php echo $widget['id']; ?>control').Draggable({handle: '.controlhandle', zIndex: 1000});
    48         if ( true && window.opera )
    49             jQuery('#<?php echo $widget['id']; ?>control').css('border','1px solid #bbb');
    50     <?php endforeach; ?>
    51         jQuery('#shadow').css('opacity','0');
    52         jQuery(widgets).each(function(o) {o='#widgetprefix-'+o; jQuery(o).css('position','relative');} );
    53     }
    54     function resetDroppableHeights() {
    55         var max = 6;
    56         jQuery.map(cols, function(o) {
    57             var c = jQuery('#' + o + ' li').length;
    58             if ( c > max ) max = c;
    59         });
    60         var maxheight = 35 * ( max + 1);
    61         jQuery.map(cols, function(o) {
    62             height = 0 == jQuery('#' + o + ' li').length ? maxheight - jQuery('#' + o + 'placemat').height() : maxheight;
    63             jQuery('#' + o).height(height);
    64         });
    65     }
    66     function maxHeight(elm) {
    67         htmlheight = document.body.parentNode.clientHeight;
    68         bodyheight = document.body.clientHeight;
    69         var height = htmlheight > bodyheight ? htmlheight : bodyheight;
    70         jQuery(elm).height(height);
    71     }
    72     function getViewportDims() {
    73         var x,y;
    74         if (self.innerHeight) { // all except Explorer
    75             x = self.innerWidth;
    76             y = self.innerHeight;
    77         } else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode
    78             x = document.documentElement.clientWidth;
    79             y = document.documentElement.clientHeight;
    80         } else if (document.body) { // other Explorers
    81             x = document.body.clientWidth;
    82             y = document.body.clientHeight;
    83         }
    84         return new Array(x,y);
    85     }
    86     function dragChange(o) {
    87         var p = getViewportDims();
    88         var screenWidth = p[0];
    89         var screenHeight = p[1];
    90         var elWidth = parseInt( jQuery(o).css('width') );
    91         var elHeight = parseInt( jQuery(o).css('height') );
    92         var elLeft = parseInt( jQuery(o).css('left') );
    93         var elTop = parseInt( jQuery(o).css('top') );
    94         if ( screenWidth < ( parseInt(elLeft) + parseInt(elWidth) ) )
    95             jQuery(o).css('left', ( screenWidth - elWidth ) + 'px' );
    96         if ( screenHeight < ( parseInt(elTop) + parseInt(elHeight) ) )
    97             jQuery(o).css('top', ( screenHeight - elHeight ) + 'px' );
    98         if ( elLeft < 1 )
    99             jQuery(o).css('left', '1px');
    100         if ( elTop < 1 )
    101             jQuery(o).css('top', '1px');
    102     }
    103     function popControl(elm) {
    104         var x = ( document.body.clientWidth - controldims[elm]['width'] ) / 2;
    105         var y = ( document.body.parentNode.clientHeight - controldims[elm]['height'] ) / 2;
    106         jQuery(elm).css({display: 'block', width: controldims[elm]['width'] + 'px', height: controldims[elm]['height'] + 'px', position: 'absolute', right: x + 'px', top: y + 'px', zIndex: '1000' });
    107         jQuery(elm).attr('class','control');
    108         jQuery('#shadow').click(function() {unpopControl(elm);});
    109         window.onresize = function(){maxHeight('#shadow');dragChange(elm);};
    110         popShadow();
    111     }
    112     function popShadow() {
    113         maxHeight('#shadow');
    114         jQuery('#shadow').css({zIndex: '999', display: 'block'});
    115         jQuery('#shadow').fadeTo('fast', 0.2);
    116     }
    117     function unpopShadow() {
    118         jQuery('#shadow').fadeOut('fast', function() {jQuery('#shadow').hide()});
    119     }
    120     function unpopControl(el) {
    121         jQuery(el).attr('class','hidden');
    122         jQuery(el).hide();
    123         unpopShadow();
    124     }
    125     function serializeAll() {
    126     <?php $i = 0; foreach ( $wp_registered_sidebars as $index => $sidebar ) : $i++; ?>
    127         var serial<?php echo $i ?> = jQuery.SortSerialize('<?php echo $index ?>');
    128         jQuery('#<?php echo $index ?>order').attr('value',serial<?php echo $i ?>.hash.replace(/widgetprefix-/g, ''));
    129     <?php endforeach; ?>
    130     }
    131     function updateAll() {
    132         jQuery.map(cols, function(o) {
    133             if ( jQuery('#' + o + ' li').length )
    134                 jQuery('#'+o+'placemat span.handle').hide();
    135             else
    136                 jQuery('#'+o+'placemat span.handle').show();
    137         });
    138         resetDroppableHeights();
    139     }
    140     jQuery(document).ready( function() {
    141         updateAll();
    142         initWidgets();
    143     });
    144 // ]]>
    145 </script>
    146 <?php
    147 }
    148 add_action( 'admin_head', 'wp_widgets_admin_head' );
     8wp_enqueue_script( array( 'wp-lists', 'admin-widgets' ) );
     9
    14910do_action( 'sidebar_admin_setup' );
    150 
    151 function wp_widget_draggable( $name ) {
    152     global $wp_registered_widgets, $wp_registered_widget_controls;
    153 
    154     if ( !isset( $wp_registered_widgets[$name] ) ) {
    155         return;
    156     }
    157 
    158     $sanitized_name = sanitize_title( $wp_registered_widgets[$name]['id'] );
    159     $link_title = __( 'Configure' );
    160     $popper = ( isset( $wp_registered_widget_controls[$name] ) )
    161         ? ' <div class="popper" id="' . $sanitized_name . 'popper" title="' . $link_title . '">&#8801;</div>'
    162         : '';
    163 
    164     $output = '<li class="module" id="widgetprefix-%1$s"><span class="handle">%2$s</span></li>';
    165 
    166     printf( $output, $sanitized_name, $wp_registered_widgets[$name]['name'] . $popper );
    167 }
    16811
    16912$title = __( 'Widgets' );
    17013$parent_file = 'themes.php';
    17114
    172 require_once 'admin-header.php';
    173 
    174 if ( count( $wp_registered_sidebars ) < 1 ) {
     15// $sidebar = What sidebar are we editing?
     16if ( isset($_GET['sidebar']) && isset($wp_registered_sidebars[$_GET['sidebar']]) ) {
     17    $sidebar = attribute_escape( $_GET['sidebar'] );
     18} elseif ( is_array($wp_registered_sidebars) && !empty($wp_registered_sidebars) ) {
     19    // By default we look at the first defined sidebar
     20    $sidebar = array_shift( array_keys($wp_registered_sidebars) );
     21} else {
     22    // If no sidebars, die.
     23    require_once( 'admin-header.php' );
    17524?>
    176     <div class="wrap">
    177         <h2><?php _e( 'No Sidebars Defined' ); ?></h2>
    178 
     25
     26    <div class="error">
     27        <p><?php _e( 'No Sidebars Defined' ); ?></p>
     28    </div>
     29
     30    <div class="wrap">
    17931        <p><?php _e( 'You are seeing this message because the theme you are currently using isn&#8217;t widget-aware, meaning that it has no sidebars that you are able to change. For information on making your theme widget-aware, please <a href="http://automattic.com/code/widgets/themes/">follow these instructions</a>.' ); /* TODO: article on codex */; ?></p>
    18032    </div>
     33
    18134<?php
    182 
    183     require_once 'admin-footer.php';
     35    require_once( 'admin-footer.php' );
    18436    exit;
    18537}
    18638
     39// These are the widgets grouped by sidebar
    18740$sidebars_widgets = wp_get_sidebars_widgets();
    188 
    189 if ( empty( $sidebars_widgets ) ) {
     41if ( empty( $sidebars_widgets ) )
    19042    $sidebars_widgets = wp_get_widget_defaults();
     43
     44// for the sake of PHP warnings
     45if ( empty( $sidebars_widgets[$sidebar] ) )
     46    $sidebars_widgets[$sidebar] = array();
     47
     48$http_post = ( 'POST' == $_SERVER['REQUEST_METHOD'] );
     49
     50// We're updating a sidebar
     51if ( $http_post && isset($sidebars_widgets[$_POST['sidebar']]) ) {
     52
     53    /* Hack #1
     54     * The widget_control is overloaded.  It updates the widget's options AND echoes out the widget's HTML form.
     55     * Since we want to update before sending out any headers, we have to catchi it with an output buffer
     56     */
     57    ob_start();
     58        /* There can be multiple widgets of the same type, but the widget_control for that
     59         * widget type needs only be called once.
     60         */
     61        $already_done = array();
     62
     63        foreach ( $wp_registered_widget_controls as $name => $control ) {
     64            if ( in_array( $control['callback'], $already_done ) )
     65                continue;
     66
     67            if ( is_callable( $control['callback'] ) )
     68                call_user_func_array( $control['callback'], $control['params'] );
     69        }
     70    ob_end_clean();
     71
     72    // Prophylactic.  Take out empty ids.
     73    foreach ( (array) $_POST['widget-id'] as $key => $val )
     74        if ( !$val )
     75            unset($_POST['widget-id'][$key]);
     76
     77    // Reset the key numbering and stare
     78    $new_sidebar = array_values( $_POST['widget-id'] );
     79    $sidebars_widgets[$_POST['sidebar']] = $new_sidebar;
     80    wp_set_sidebars_widgets( $sidebars_widgets );
     81
     82    // Re-register just in case
     83    wp_widgets_init();
     84
     85    wp_redirect( add_query_arg( 'message', 'updated' ) );
     86    exit;
    19187}
    19288
    193 if ( isset( $_POST['action'] ) ) {
    194     check_admin_referer( 'widgets-save-widget-order' );
    195 
    196     switch ( $_POST['action'] ) {
    197         case 'default' :
    198             $sidebars_widgets = wp_get_widget_defaults();
    199             wp_set_sidebars_widgets( $sidebars_widgets );
    200         break;
    201 
    202         case 'save_widget_order' :
    203             $sidebars_widgets = array();
    204 
    205             foreach ( $wp_registered_sidebars as $index => $sidebar ) {
    206                 $postindex = $index . 'order';
    207 
    208                 parse_str( $_POST[$postindex], $order );
    209 
    210                 $new_order = $order[$index];
    211 
    212                 if ( is_array( $new_order ) ) {
    213                     foreach ( $new_order as $sanitized_name ) {
    214                         foreach ( $wp_registered_widgets as $name => $widget ) {
    215                             if ( $sanitized_name == $widget['id'] ) {
    216                                 $sidebars_widgets[$index][] = $name;
    217                             }
    218                         }
    219                     }
    220                 }
    221             }
    222 
    223             wp_set_sidebars_widgets( $sidebars_widgets );
    224         break;
     89
     90
     91
     92// What widget (if any) are we editing
     93$edit_widget = -1;
     94
     95$query_args = array('add', 'remove', 'key', 'edit', '_wpnonce', 'message' );
     96
     97if ( isset($_GET['add']) && $_GET['add'] ) {
     98    // Add to the end of the sidebar
     99    if ( isset($wp_registered_widgets[$_GET['add']]) ) {
     100        check_admin_referer( "add-widget_$_GET[add]" );
     101        $sidebars_widgets[$sidebar][] = $_GET['add'];
     102        wp_set_sidebars_widgets( $sidebars_widgets );
    225103    }
     104    wp_redirect( remove_query_arg( $query_args ) );
     105    exit;
     106} elseif ( isset($_GET['remove']) && $_GET['remove'] && isset($_GET['key']) && is_numeric($_GET['key']) ) {
     107    // Remove from sidebar the widget of type $_GET['remove'] and in position $_GET['key']
     108    $key = (int) $_GET['key'];
     109    if ( -1 < $key && ( $keys = array_keys($sidebars_widgets[$sidebar], $_GET['remove']) ) && in_array($key, $keys) ) {
     110        check_admin_referer( "remove-widget_$_GET[remove]" );
     111        unset($sidebars_widgets[$sidebar][$key]);
     112        $sidebars_widgets[$sidebar] = array_values($sidebars_widgets[$sidebar]);
     113        wp_set_sidebars_widgets( $sidebars_widgets );
     114    }
     115    wp_redirect( remove_query_arg( $query_args ) );
     116    exit;
     117} elseif ( isset($_GET['edit']) && $_GET['edit'] && isset($_GET['key']) && is_numeric($_GET['key']) ) {
     118    // Edit widget of type $_GET['edit'] and position $_GET['key']
     119    $key = (int) $_GET['key'];
     120    if ( -1 < $key && ( $keys = array_keys($sidebars_widgets[$sidebar], $_GET['edit']) ) && in_array($key, $keys) )
     121        $edit_widget = $key;
    226122}
    227123
    228 ksort( $wp_registered_widgets );
    229 
    230 $inactive_widgets = array();
    231 
    232 foreach ( $wp_registered_widgets as $name => $widget ) {
    233     $is_active = false;
    234 
    235     foreach ( $wp_registered_sidebars as $index => $sidebar ) {
    236         if ( is_array( $sidebars_widgets[$index] ) && in_array( $name, $sidebars_widgets[$index] ) ) {
    237             $is_active = true;
    238             break;
    239         }
    240     }
    241 
    242     if ( !$is_active ) {
    243         $inactive_widgets[] = $name;
    244     }
    245 }
    246 
    247 $containers = array( 'palette' );
    248 
    249 foreach ( $wp_registered_sidebars as $index => $sidebar ) {
    250     $containers[] = $index;
    251 }
    252 
    253 $c_string = '';
    254 
    255 foreach ( $containers as $container ) {
    256     $c_string .= '"' . $container . '",';
    257 }
    258 
    259 $c_string = substr( $c_string, 0, -1 );
    260 
    261 if ( isset( $_POST['action'] ) ) {
    262 ?>
    263     <div class="fade updated" id="message">
    264         <p><?php printf( __( 'Sidebar updated. <a href="%s">View site &raquo;</a>' ), get_bloginfo( 'url' ) . '/' ); ?></p>
    265     </div>
    266 <?php
    267 }
    268 ?>
    269     <div class="wrap">
    270         <h2><?php _e( 'Sidebar Arrangement' ); ?></h2>
    271 
    272         <p><?php _e( 'You can drag and drop widgets onto your sidebar below.' ); ?></p>
    273 
    274         <form id="sbadmin" method="post" onsubmit="serializeAll();">
    275             <p class="submit">
    276                 <input type="submit" value="<?php _e( 'Save Changes &raquo;' ); ?>" />
     124// Total number of registered sidebars
     125$sidebar_widget_count = count($sidebars_widgets[$sidebar]);
     126
     127// This is sort of lame since "widget" won't be converted to "widgets" in the JS
     128if ( 1 < $sidebars_count = count($wp_registered_sidebars) )
     129    $sidebar_info_text = __ngettext( 'You are using %1$s widget in the "%2$s" sidebar.', 'You are using %1$s widgets in the "%2$s" sidebar.', $sidebar_widget_count );
     130else
     131    $sidebar_info_text = __ngettext( 'You are using %1$s widget in the sidebar.', 'You are using %1$s widgets in the sidebar.', $sidebar_widget_count );
     132
     133
     134$sidebar_info_text = sprintf( wp_specialchars( $sidebar_info_text ), "<span id='widget-count'>$sidebar_widget_count</span>", $wp_registered_sidebars[$sidebar]['name'] );
     135
     136$page = isset($_GET['apage']) ? abs( (int) $_GET['apage'] ) : 1;
     137
     138/* TODO: Paginate widgets list
     139$page_links = paginate_links( array(
     140    'base'    => add_query_arg( 'apage', '%#%' ),
     141    'format'  => '',
     142    'total'   => ceil(($total = 105 )/ 10),
     143    'current' => $page
     144));
     145*/
     146$page_links = false;
     147
     148// Unsanitized!
     149$widget_search = isset($_GET['s']) ? $_GET['s'] : false;
     150
     151// Not entirely sure what all should be here
     152$show_values = array(
     153    ''       => $widget_search ? __( 'Show any widgets' ) : __( 'Show all widgets' ),
     154    'unused' => __( 'Show unused widgets' ),
     155    'used'   => __( 'Show used widgets' )
     156);
     157
     158$show = isset($_GET['show']) && isset($show_values[$_GET['show']]) ? attribute_escape( $_GET['show'] ) : false;
     159
     160
     161$messages = array(
     162    'updated' => __('Changes saved.')
     163);
     164
     165require_once( 'admin-header.php' );
     166
     167if ( isset($_GET['message']) && isset($messages[$_GET['message']]) ) : ?>
     168
     169<div id="message" class="updated fade"><p><?php echo $messages[$_GET['message']]; ?></p></div>
     170
     171<?php endif; ?>
     172
     173<div class="wrap">
     174
     175    <form id="widgets-filter" action="" method="get">
     176
     177    <h2><?php _e( 'Widgets' ); ?></h2>
     178    <p id="widget-search">
     179        <input type="text" id="widget-search-input" name="s" value="<?php echo attribute_escape( $widget_search ); ?>" />
     180        <input type="submit" value="<?php _e( 'Search Widgets' ); ?>" />
     181    </p>
     182
     183    <div class="widget-liquid-left-holder">
     184    <div id="available-widgets-filter" class="widget-liquid-left">
     185        <h3><?php printf( __('Available Widgets %s'), '<a href="#help:avaliable-widgets" class="wp-context-help">?</a>' ); ?></h3>
     186        <p>
     187            <select name="show">
     188<?php foreach ( $show_values as $show_value => $show_text ) : $show_value = attribute_escape( $show_value ); ?>
     189                <option value='<?php echo $show_value; ?>'<?php selected( $show_value, $show ); ?>><?php echo wp_specialchars( $show_text ); ?></option>
     190<?php endforeach; ?>
     191            </select>
     192            <input type="submit" value="<?php _e('Show' ); ?>" />
     193        </p>
     194<?php if ( $page_links ) : ?>
     195        <p class="pagenav">
     196            <?php echo $page_links; ?>
     197
     198        </p>
     199<?php endif; ?>
     200    </div>
     201    </div>
     202
     203    <div id="available-sidebars" class="widget-liquid-right">
     204        <h3><?php printf( __('Current Widgets %s'), '<a href="#help:current-widgets" class="wp-context-help">?</a>' ); ?></h3>
     205
     206<?php if ( 1 < $sidebars_count ) : ?>
     207
     208        <p>
     209            <select id="sidebar-selector" name="sidebar">
     210<?php foreach ( $wp_registered_sidebars as $sidebar_id => $registered_sidebar ) : $sidebar_id = attribute_escape( $sidebar_id ); ?>
     211                <option value='<?php echo $sidebar_id; ?>'<?php selected( $sidebar_id, $sidebar ); ?>><?php echo wp_specialchars( $registered_sidebar['name'] ); ?></option>
     212<?php endforeach; ?>
     213            </select>
     214            <input type="submit" value="<?php _e('Go' ); ?>" />
     215        </p>
     216
     217<?php endif; ?>
     218
     219    </div>
     220
     221    </form>
     222
     223    <div id="widget-content" class="widget-liquid-left-holder">
     224
     225        <div id="available-widgets" class="widget-liquid-left">
     226
     227            <?php wp_list_widgets( $show, $widget_search ); // This lists all the widgets for the query ( $show, $search ) ?>
     228
     229<?php if ( $page_links ) : ?>
     230            <p class="pagenav">
     231                <?php echo $page_links; ?>
     232
    277233            </p>
    278             <div id="zones">
    279             <?php
    280                 foreach ( $wp_registered_sidebars as $index => $sidebar ) {
    281             ?>
    282                 <input type="hidden" id="<?php echo $index; ?>order" name="<?php echo $index; ?>order" value="" />
    283 
    284                 <div class="dropzone">
    285                     <h3><?php echo $sidebar['name']; ?></h3>
    286 
    287                     <div id="<?php echo $index; ?>placemat" class="placemat">
    288                         <span class="handle">
    289                             <h4><?php _e( 'Default Sidebar' ); ?></h4>
    290                             <?php _e( 'Your theme will display its usual sidebar when this box is empty. Dragging widgets into this box will replace the usual sidebar with your customized sidebar.' ); ?>
    291                         </span>
    292                     </div>
    293 
    294                     <ul id="<?php echo $index; ?>">
    295                     <?php
    296                         if ( is_array( $sidebars_widgets[$index] ) ) {
    297                             foreach ( $sidebars_widgets[$index] as $name ) {
    298                                 wp_widget_draggable( $name );
    299                             }
    300                         }
    301                     ?>
    302                     </ul>
    303                 </div>
    304             <?php
    305                 }
    306             ?>
    307 
    308             </div>
    309 
    310             <div id="palettediv">
    311                 <h3><?php _e( 'Available Widgets' ); ?></h3>
    312 
    313                 <ul id="palette">
    314                 <?php
    315                     foreach ( $inactive_widgets as $name ) {
    316                         wp_widget_draggable( $name );
    317                     }
    318                 ?>
    319                 </ul>
    320             </div>
    321 
    322             <script type="text/javascript">
    323             // <![CDATA[
    324                 jQuery(document).ready(function(){
    325             <?php foreach ( $containers as $container ) { ?>
    326                     jQuery('ul#<?php echo $container; ?>').Sortable({
    327                         accept: 'module', activeclass: 'activeDraggable', opacity: 0.8, revert: true, onStop: updateAll
    328                     });
    329             <?php } ?>
    330                 });
    331             // ]]>
    332             </script>
    333 
    334             <p class="submit">
    335             <?php wp_nonce_field( 'widgets-save-widget-order' ); ?>
    336                 <input type="hidden" name="action" id="action" value="save_widget_order" />
    337                 <input type="submit" value="<?php _e( 'Save Changes &raquo;' ); ?>" />
    338             </p>
    339 
    340             <div id="controls">
    341             <?php foreach ( $wp_registered_widget_controls as $name => $widget ) { ?>
    342                 <div class="hidden" id="<?php echo $widget['id']; ?>control">
    343                     <span class="controlhandle"><?php echo $widget['name']; ?></span>
    344                     <span id="<?php echo $widget['id']; ?>closer" class="controlcloser">&#215;</span>
    345                     <div class="controlform">
    346                     <?php call_user_func_array( $widget['callback'], $widget['params'] ); ?>
    347                     </div>
    348                 </div>
    349             <?php } ?>
    350             </div>
    351         </form>
    352 
    353         <br class="clear" />
    354     </div>
    355 
    356     <div id="shadow"> </div>
    357 
    358     <?php do_action( 'sidebar_admin_page' ); ?>
    359 
    360 <?php require_once 'admin-footer.php'; ?>
     234<?php endif; ?>
     235
     236        </div>
     237    </div>
     238
     239    <form id="widget-controls" action="" method="post">
     240
     241    <div id="current-widgets-head" class="widget-liquid-right">
     242
     243        <div id="sidebar-info">
     244            <p><?php echo $sidebar_info_text; ?></p>
     245            <p><?php _e( 'Add more from the Available Widgets section.' ); ?></p>
     246        </div>
     247
     248    </div>
     249
     250    <div id="current-widgets" class="widget-liquid-right">
     251        <input type="hidden" id='sidebar' name='sidebar' value="<?php echo $sidebar; ?>" />
     252
     253        <div id="current-sidebar">
     254
     255            <?php wp_list_widget_controls( $sidebars_widgets[$sidebar], $edit_widget ); // Show the control forms for each of the widgets in this sidebar ?>
     256
     257        </div>
     258    </div>
     259
     260    <p class="submit">
     261        <input type="hidden" id="generated-time" name="generated-time" value="<?php echo time(); ?>" />
     262        <input type="submit" name="save-widgets" value="<?php _e( 'Save Changes' ); ?>" />
     263    </p>
     264
     265    </form>
     266
     267</div>
     268
     269<?php do_action( 'sidebar_admin_page' ); ?>
     270
     271<?php require_once( 'admin-footer.php' ); ?>
     272
  • trunk/wp-includes/script-loader.php

    r6547 r6556  
    8080        $this->add( 'jquery', '/wp-includes/js/jquery/jquery.js', false, '1.1.4');
    8181        $this->add( 'jquery-form', '/wp-includes/js/jquery/jquery.form.js', array('jquery'), '1.0.3');
    82         $this->add( 'interface', '/wp-includes/js/jquery/interface.js', array('jquery'), '1.2');
     82        $this->add( 'interface', '/wp-includes/js/jquery/interface.js', array('jquery'), '1.2' );
    8383        $this->add( 'dimensions', '/wp-includes/js/jquery/jquery.dimensions.min.js', array('jquery'), '1.1.2');
    8484        $this->add( 'suggest', '/wp-includes/js/jquery/suggest.js', array('dimensions'), '1.1');
     
    144144                'confirmText' => __("Are you sure you want to delete the file '%title%'?\nClick ok to delete or cancel to go back.")
    145145            ) );
     146            $this->add( 'admin-widgets', '/wp-admin/js/widgets.js', array( 'interface' ), mt_rand() );
    146147        }
    147148    }
  • trunk/wp-includes/widgets.php

    r6436 r6556  
    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 */
     
    9694
    9795function wp_register_sidebar_widget($id, $name, $output_callback, $options = array()) {
    98 
    99     global $wp_registered_widgets, $wp_register_widget_defaults;
     96    global $wp_registered_widgets;
    10097
    10198    if ( empty($output_callback) ) {
     
    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;
     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'] );
    118125}
    119126
     
    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) ) {
     
    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(
     
    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;
     
    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;
     
    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}
     
    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
     
    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
     
    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'] );
     
    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);
    561     }
    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 }
    570 
    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;
    578     }
    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');
    588 ?>
    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>
     618        $updated = true;
     619    }
     620
     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']);
     628    }
     629?>
     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}
     
    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);
    614     }
    615     add_action('sidebar_admin_setup', 'wp_widget_text_setup');
    616     add_action('sidebar_admin_page', 'wp_widget_text_page');
    617 }
    618 
    619 function wp_widget_categories($args, $number = 1) {
    620     extract($args);
     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 ) );
     648    }
     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    }
     658}
     659
     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';
     
    636685?>
    637686
    638 <script type='text/javascript'><!--
     687<script type='text/javascript'>
     688/* <![CDATA[ */
    639689    var dropdown = document.getElementById("cat");
    640690    function onCatChange() {
     
    644694    }
    645695    dropdown.onchange = onCatChange;
    646 --></script>
     696/* ]]> */
     697</script>
    647698
    648699<?php
     
    658709}
    659710
    660 function wp_widget_categories_control( $number ) {
    661     $options = $newoptions = get_option('widget_categories');
    662 
    663     if ( !is_array( $options ) ) {
    664         $options = $newoptions = get_option( 'widget_categories' );
    665     }
    666 
    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     }
    673 
    674     if ( $options != $newoptions ) {
    675         $options = $newoptions;
     711function wp_widget_categories_control( $widget_args ) {
     712    global $wp_registered_widgets;
     713    static $updated = false;
     714
     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);
     719
     720    $options = get_option('widget_categories');
     721
     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);
    677     }
    678 
    679     $title = attribute_escape( $options[$number]['title'] );
    680 ?>
    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>
    684 
    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>
    688 
    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>
     750        $updated = true;
     751    }
     752
     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    }
     765?>
     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>
     772
     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>
    696789
    697790            <input type="hidden" id="categories-submit-<?php echo $number; ?>" name="categories-submit-<?php echo $number; ?>" value="1" />
     
    699792}
    700793
    701 function wp_widget_categories_setup() {
    702     $options = $newoptions = get_option( 'widget_categories' );
    703 
    704     if ( isset( $_POST['categories-number-submit'] ) ) {
    705         $number = (int) $_POST['categories-number'];
    706 
    707         if ( $number > 9 ) {
    708             $number = 9;
    709         } elseif ( $number < 1 ) {
    710             $number = 1;
    711         }
    712 
    713         $newoptions['number'] = $number;
    714     }
    715 
    716     if ( $newoptions != $options ) {
    717         $options = $newoptions;
    718         update_option( 'widget_categories', $options );
    719         wp_widget_categories_register( $options['number'] );
    720     }
    721 }
    722 
    723 function wp_widget_categories_page() {
     794function wp_widget_categories_register() {
    724795    $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
     796    if ( isset($options['title']) )
     797        $options = wp_widget_categories_upgrade();
     798
     799    $widget_ops = array( 'classname' => 'widget_categories', 'description' => __( "A list or dropdown of categories" ) );
     800
     801    $name = __( 'Categories' );
     802
     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 ) );
     807    }
     808
     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 ) );
     816    }
     817
    744818}
    745819
     
    747821    $options = get_option( 'widget_categories' );
    748822
    749     $newoptions = array( 'number' => 1, 1 => $options );
     823    if ( !isset( $options['title'] ) )
     824        return $options;
     825
     826    $newoptions = array( 1 => $options );
    750827
    751828    update_option( 'widget_categories', $newoptions );
     
    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;
    779 }
    780 
    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' );
    809845}
    810846
     
    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
     
    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
     
    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') )
     
    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'];
     
    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']));
     
    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);
    1026     }
    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 }
    1040 
    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;
    1048     }
    1049     if ( $options != $newoptions ) {
    1050         $options = $newoptions;
    1051         update_option('widget_rss', $options);
    1052         wp_widget_rss_register($options['number']);
    1053     }
    1054 }
    1055 
    1056 function wp_widget_rss_page() {
    1057     $options = get_option('widget_rss');
    1058 ?>
    1059     <div class="wrap">
    1060         <form method="POST">
    1061             <h2><?php _e('RSS Feed Widgets'); ?></h2>
    1062             <p style="line-height: 30px;"><?php _e('How many RSS widgets would you like?'); ?>
    1063             <select id="rss-number" name="rss-number" value="<?php echo $options['number']; ?>">
    1064 <?php for ( $i = 1; $i < 10; ++$i ) echo "<option value='$i' ".($options['number']==$i ? "selected='selected'" : '').">$i</option>"; ?>
    1065             </select>
    1066             <span class="submit"><input type="submit" name="rss-number-submit" id="rss-number-submit" value="<?php echo attribute_escape(__('Save')); ?>" /></span></p>
    1067         </form>
    1068     </div>
     1116        $updated = true;
     1117    }
     1118
     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        $items = (int) $options[$number]['items'];
     1129        if ( $items < 1 )
     1130            $items = 10;
     1131        $error = $options[$number]['error'];
     1132    }
     1133
     1134?>
     1135            <p>
     1136                <label for="rss-url-<?php echo $number; ?>"><?php _e('Enter the RSS feed URL here:'); ?>
     1137                    <input class="widefat" id="rss-url-<?php echo $number; ?>" name="widget-rss[<?php echo $number; ?>][url]" type="text" value="<?php echo $url; ?>" />
     1138                </label>
     1139            </p>
     1140            <p>
     1141                <label for="rss-title-<?php echo $number; ?>"><?php _e('Give the feed a title (optional):'); ?>
     1142                    <input class="widefat" id="rss-title-<?php echo $number; ?>" name="widget-rss[<?php echo $number; ?>][title]" type="text" value="<?php echo $title; ?>" />
     1143                </label>
     1144            </p>
     1145            <p>
     1146                <label for="rss-items-<?php echo $number; ?>"><?php _e('How many items would you like to display?'); ?>
     1147                    <select id="rss-items-<?php echo $number; ?>" name="widget-rss[<?php echo $number; ?>][items]">
     1148                        <?php
     1149                            for ( $i = 1; $i <= 10; ++$i )
     1150                                echo "<option value='$i' " . ( $items == $i ? "selected='selected'" : '' ) . ">$i</option>";
     1151                        ?>
     1152                    </select>
     1153                </label>
     1154            </p>
     1155            <input type="hidden" id="rss-submit-<?php echo $number; ?>" name="rss-submit-<?php echo $number; ?>" value="1" />
    10691156<?php
    10701157}
     
    10721159function wp_widget_rss_register() {
    10731160    $options = get_option('widget_rss');
    1074     $number = $options['number'];
    1075     if ( $number < 1 ) $number = 1;
    1076     if ( $number > 9 ) $number = 9;
    1077     $dims = array('width' => 410, 'height' => 200);
    1078     $class = array('classname' => 'widget_rss');
    1079     for ($i = 1; $i <= 9; $i++) {
    1080         $name = sprintf(__('RSS %d'), $i);
    1081         $id = "rss-$i"; // Never never never translate an id
    1082         wp_register_sidebar_widget($id, $name, $i <= $number ? 'wp_widget_rss' : /* unregister */ '', $class, $i);
    1083         wp_register_widget_control($id, $name, $i <= $number ? 'wp_widget_rss_control' : /* unregister */ '', $dims, $i);
    1084     }
    1085     add_action('sidebar_admin_setup', 'wp_widget_rss_setup');
    1086     add_action('sidebar_admin_page', 'wp_widget_rss_page');
     1161    $widget_ops = array('classname' => 'widget_rss', 'description' => __( 'Entries from any RSS or Atom feed' ));
     1162    $control_ops = array('width' => 410, 'height' => 200, 'id_base' => 'rss');
     1163    $name = __('RSS');
     1164
     1165    // If there are none, we register the widget's existance with a generic template
     1166    if ( !$options ) {
     1167        wp_register_sidebar_widget( 'rss-1', $name, 'wp_widget_rss', $widget_ops, array( 'number' => -1 ) );
     1168        wp_register_widget_control( 'rss-1', $name, 'wp_widget_rss_control', $control_ops, array( 'number' => -1 ) );
     1169    }
     1170
     1171    foreach ( array_keys($options) as $o ) {
     1172        // Old widgets can have null values for some reason
     1173        if ( !isset($options[$o]['url']) || !isset($options[$o]['title']) || !isset($options[$o]['items']) )
     1174            contine;
     1175        $id = "rss-$o"; // Never never never translate an id
     1176        wp_register_sidebar_widget($id, $name, 'wp_widget_rss', $widget_ops, array( 'number' => $o ));
     1177        wp_register_widget_control($id, $name, 'wp_widget_rss_control', $control_ops, array( 'number' => $o ));
     1178    }
    10871179}
    10881180
     
    11131205?>
    11141206    <p><label for="tag-cloud-title">
    1115     <?php _e('Title:') ?> <input type="text" style="width:300px" id="tag-cloud-title" name="tag-cloud-title" value="<?php echo $title ?>" /></label>
     1207    <?php _e('Title:') ?> <input type="text" class="widefat" id="tag-cloud-title" name="tag-cloud-title" value="<?php echo $title ?>" /></label>
    11161208    </p>
    11171209    <input type="hidden" name="tag-cloud-submit" id="tag-cloud-submit" value="1" />
     
    11231215        return;
    11241216
    1125     $GLOBALS['wp_register_widget_defaults'] = true;
    1126 
    1127     $dims90 = array( 'height' => 90, 'width' => 300 );
    1128     $dims100 = array( 'height' => 100, 'width' => 300 );
    1129     $dims150 = array( 'height' => 150, 'width' => 300 );
    1130 
    1131     $class = array('classname' => 'widget_pages');
    1132     wp_register_sidebar_widget('pages', __('Pages'), 'wp_widget_pages', $class);
    1133     wp_register_widget_control('pages', __('Pages'), 'wp_widget_pages_control', $dims150);
    1134 
    1135     $class['classname'] = 'widget_calendar';
    1136     wp_register_sidebar_widget('calendar', __('Calendar'), 'wp_widget_calendar', $class);
    1137     wp_register_widget_control('calendar', __('Calendar'), 'wp_widget_calendar_control', $dims90);
    1138 
    1139     $class['classname'] = 'widget_archives';
    1140     wp_register_sidebar_widget('archives', __('Archives'), 'wp_widget_archives', $class);
    1141     wp_register_widget_control('archives', __('Archives'), 'wp_widget_archives_control', $dims100);
    1142 
    1143     $class['classname'] = 'widget_links';
    1144     wp_register_sidebar_widget('links', __('Links'), 'wp_widget_links', $class);
    1145 
    1146     $class['classname'] = 'widget_meta';
    1147     wp_register_sidebar_widget('meta', __('Meta'), 'wp_widget_meta', $class);
    1148     wp_register_widget_control('meta', __('Meta'), 'wp_widget_meta_control', $dims90);
    1149 
    1150     $class['classname'] = 'widget_search';
    1151     wp_register_sidebar_widget('search', __('Search'), 'wp_widget_search', $class);
    1152 
    1153     $class['classname'] = 'widget_recent_entries';
    1154     wp_register_sidebar_widget('recent-posts', __('Recent Posts'), 'wp_widget_recent_entries', $class);
    1155     wp_register_widget_control('recent-posts', __('Recent Posts'), 'wp_widget_recent_entries_control', $dims90);
    1156 
    1157     $class['classname'] = 'widget_tag_cloud';
    1158     wp_register_sidebar_widget('tag_cloud', __('Tag Cloud'), 'wp_widget_tag_cloud', $class);
    1159     wp_register_widget_control('tag_cloud', __('Tag Cloud'), 'wp_widget_tag_cloud_control', 'width=300&height=160');
     1217    $widget_ops = array('classname' => 'widget_pages', 'description' => __( "Your blog's WordPress Pages") );
     1218    wp_register_sidebar_widget('pages', __('Pages'), 'wp_widget_pages', $widget_ops);
     1219    wp_register_widget_control('pages', __('Pages'), 'wp_widget_pages_control' );
     1220
     1221    $widget_ops = array('classname' => 'widget_calendar', 'description' => __( "A calendar of your blog's posts") );
     1222    wp_register_sidebar_widget('calendar', __('Calendar'), 'wp_widget_calendar', $widget_ops);
     1223    wp_register_widget_control('calendar', __('Calendar'), 'wp_widget_calendar_control' );
     1224
     1225    $widget_ops = array('classname' => 'widget_archive', 'description' => __( "A monthly archive of your blog's posts") );
     1226    wp_register_sidebar_widget('archives', __('Archives'), 'wp_widget_archives', $widget_ops);
     1227    wp_register_widget_control('archives', __('Archives'), 'wp_widget_archives_control' );
     1228
     1229    $widget_ops = array('classname' => 'widget_links', 'description' => __( "Your blogroll") );
     1230    wp_register_sidebar_widget('links', __('Links'), 'wp_widget_links', $widget_ops);
     1231
     1232    $widget_ops = array('classname' => 'widget_meta', 'description' => __( "Log in/out, admin, feed and WordPress links") );
     1233    wp_register_sidebar_widget('meta', __('Meta'), 'wp_widget_meta', $widget_ops);
     1234    wp_register_widget_control('meta', __('Meta'), 'wp_widget_meta_control' );
     1235
     1236    $widget_ops = array('classname' => 'widget_search', 'description' => __( "A search form for your blog") );
     1237    wp_register_sidebar_widget('search', __('Search'), 'wp_widget_search', $widget_ops);
     1238
     1239    $widget_ops = array('classname' => 'widget_recent_entries', 'description' => __( "The most recent posts on your blog") );
     1240    wp_register_sidebar_widget('recent-posts', __('Recent Posts'), 'wp_widget_recent_entries', $widget_ops);
     1241    wp_register_widget_control('recent-posts', __('Recent Posts'), 'wp_widget_recent_entries_control' );
     1242
     1243    $widget_ops = array('classname' => 'widget_tag_cloud', 'description' => __( "Your most used tags in cloud format") );
     1244    wp_register_sidebar_widget('tag_cloud', __('Tag Cloud'), 'wp_widget_tag_cloud', $widget_ops);
     1245    wp_register_widget_control('tag_cloud', __('Tag Cloud'), 'wp_widget_tag_cloud_control' );
    11601246
    11611247    wp_widget_categories_register();
     
    11641250    wp_widget_recent_comments_register();
    11651251
    1166     $GLOBALS['wp_register_widget_defaults'] = false;
    1167 
    11681252    do_action('widgets_init');
    11691253}
     
    11711255add_action('init', 'wp_widgets_init', 1);
    11721256
    1173 ?>
     1257/* Pattern for widget which allows multiple instances (such as the text widget)
     1258
     1259// Displays widget on blag
     1260// $widget_args: number
     1261//    number: which of the several widgets of this type do we mean
     1262function widget_many( $args, $widget_args = 1 ) {
     1263    extract( $args, EXTR_SKIP );
     1264    if ( is_numeric($widget_args) )
     1265        $widget_args = array( 'number' => $widget_args );
     1266    $widget_args = wp_parse_args( $widget_args, array( 'number' => -1 ) );
     1267    extract( $widget_args, EXTR_SKIP );
     1268   
     1269    // Data should be stored as array:  array( number => data for that instance of the widget, ... )
     1270    $options = get_option('widget_many');
     1271    if ( !isset($options[$number]) )
     1272        return;
     1273
     1274    echo $before_widget;
     1275
     1276    // Do stuff for this widget, drawing data from $options[$number]
     1277
     1278    echo $after_widget;
     1279}
     1280
     1281// Displays form for a particular instance of the widget.  Also updates the data after a POST submit
     1282// $widget_args: number
     1283//    number: which of the several widgets of this type do we mean
     1284function widget_many_control( $widget_args = 1 ) {
     1285    global $wp_registered_widgets;
     1286    static $updated = false; // Whether or not we have already updated the data after a POST submit
     1287
     1288    if ( is_numeric($widget_args) )
     1289        $widget_args = array( 'number' => $widget_args );
     1290    $widget_args = wp_parse_args( $widget_args, array( 'number' => -1 ) );
     1291    extract( $widget_args, EXTR_SKIP );
     1292
     1293    // Data should be stored as array:  array( number => data for that instance of the widget, ... )
     1294    $options = get_option('widget_many');
     1295    if ( !is_array($options) )
     1296        $options = array();
     1297
     1298    // We need to update the data
     1299    if ( !$updated && !empty($_POST['sidebar']) ) {
     1300        // Tells us what sidebar to put the data in
     1301        $sidebar = (string) $_POST['sidebar'];
     1302
     1303        $sidebars_widgets = wp_get_sidebars_widgets();
     1304        if ( isset($sidebars_widgets[$sidebar]) )
     1305            $this_sidebar =& $sidebars_widgets[$sidebar];
     1306        else
     1307            $this_sidebar = array();
     1308
     1309        foreach ( $this_sidebar as $_widget_id ) {
     1310            // 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
     1311            // since widget ids aren't necessarily persistent across multiple updates
     1312            if ( 'widget_many' == $wp_registered_widgets[$_widget_id]['callback'] && isset($wp_registered_widgets[$_widget_id]['params'][0]['number']) ) {
     1313                $widget_number = $wp_registered_widgets[$_widget_id]['params'][0]['number'];
     1314                unset($options[$widget_number]);
     1315            }
     1316        }
     1317
     1318        foreach ( (array) $_POST['widget-many'] as $widget_number => $widget_many_instance ) {
     1319            // compile data from $widget_many_instance
     1320            $something = wp_specialchars( $widget_many_instance['something'] );
     1321            $options[$widget_number] = array( 'something' => $something );  // Even simple widgets should store stuff in array, rather than in scalar
     1322        }
     1323
     1324        update_option('widget_text', $options);
     1325
     1326        $updated = true; // So that we don't go through this more than once
     1327    }
     1328
     1329
     1330    // Here we echo out the form
     1331    if ( -1 == $number ) { // We echo out a template for a form which can be converted to a specific form later via JS
     1332        $something = '';
     1333        $number = '%i%';
     1334    } else {
     1335        $something = attribute_escape($options[$number]['something']);
     1336    }
     1337
     1338    // The form has inputs with names like widget-many[$number][something] so that all data for that instance of
     1339    // the widget are stored in one $_POST variable: $_POST['widget-many'][$number]
     1340?>
     1341        <p>
     1342            <input class="widefat" id="widget-many-something-<?php echo $number; ?>" name="widget-many[<?php echo $number; ?>][something]" type="text" value="<?php echo $data; ?>" />
     1343            <input type="hidden" id="widget-many-submit-<?php echo $number; ?>" name="widget-many-<?php echo $number; ?>" value="1" />
     1344        </p>
     1345<?php
     1346}
     1347
     1348// Registers each instance of our widget on startup
     1349function widget_many_register() {
     1350    $options = get_option('widget_many');
     1351    $widget_ops = array('classname' => 'widget_many', 'description' => __('Widget which allows multiple instances'));
     1352    $control_ops = array('width' => 400, 'height' => 350, 'id_base' => 'many');
     1353    $name = __('Many');
     1354
     1355    // If there are none, we register the widget's existance with a generic template
     1356    if ( !$options ) {
     1357        wp_register_sidebar_widget( 'many-1', $name, 'widget_many', $widget_ops, array( 'number' => -1 ) );
     1358        wp_register_widget_control( 'many-1', $name, 'widget_many_control', $control_ops, array( 'number' => -1 ) );
     1359    }
     1360
     1361    foreach ( array_keys($options) as $o ) {
     1362        // Old widgets can have null values for some reason
     1363        if ( !isset($options[$o]['something']) ) // we used 'something' above in our exampple.  Replace with with whatever your real data are.
     1364            continue;
     1365
     1366        // $id should look like {$id_base}-{$o}
     1367        $id = "many-$o"; // Never never never translate an id
     1368        wp_register_sidebar_widget( $id, $name, 'wp_widget_text', $widget_ops, array( 'number' => $o ) );
     1369        wp_register_widget_control( $id, $name, 'wp_widget_text_control', $control_ops, array( 'number' => $o ) );
     1370    }
     1371}
     1372
     1373// This is important
     1374add_action( 'widgets_init', 'widget_many_register' )
     1375
     1376*/
     1377
     1378?>
Note: See TracChangeset for help on using the changeset viewer.