Wordpress 2.6.2
[autoinstalls/wordpress.git] / wp-includes / widgets.php
1 <?php
2
3 /* Global Variables */
4
5 global $wp_registered_sidebars, $wp_registered_widgets, $wp_registered_widget_controls;
6
7 $wp_registered_sidebars = array();
8 $wp_registered_widgets = array();
9 $wp_registered_widget_controls = array();
10
11 /* Template tags & API functions */
12
13 function register_sidebars($number = 1, $args = array()) {
14         global $wp_registered_sidebars;
15         $number = (int) $number;
16
17         if ( is_string($args) )
18                 parse_str($args, $args);
19
20         for ( $i=1; $i <= $number; $i++ ) {
21                 $_args = $args;
22
23                 if ( $number > 1 ) {
24                         $_args['name'] = isset($args['name']) ? sprintf($args['name'], $i) : sprintf(__('Sidebar %d'), $i);
25                 } else {
26                         $_args['name'] = isset($args['name']) ? $args['name'] : __('Sidebar');
27                 }
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
39                 register_sidebar($_args);
40         }
41 }
42
43 function register_sidebar($args = array()) {
44         global $wp_registered_sidebars;
45
46         if ( is_string($args) )
47                 parse_str($args, $args);
48
49         $i = count($wp_registered_sidebars) + 1;
50
51         $defaults = array(
52                 'name' => sprintf(__('Sidebar %d'), $i ),
53                 'id' => "sidebar-$i",
54                 'before_widget' => '<li id="%1$s" class="widget %2$s">',
55                 'after_widget' => "</li>\n",
56                 'before_title' => '<h2 class="widgettitle">',
57                 'after_title' => "</h2>\n",
58         );
59
60         $sidebar = array_merge($defaults, (array) $args);
61
62         $wp_registered_sidebars[$sidebar['id']] = $sidebar;
63
64         return $sidebar['id'];
65 }
66
67 function unregister_sidebar( $name ) {
68         global $wp_registered_sidebars;
69
70         if ( isset( $wp_registered_sidebars[$name] ) )
71                 unset( $wp_registered_sidebars[$name] );
72 }
73
74 function register_sidebar_widget($name, $output_callback, $classname = '') {
75         // Compat
76         if ( is_array($name) ) {
77                 if ( count($name) == 3 )
78                         $name = sprintf($name[0], $name[2]);
79                 else
80                         $name = $name[0];
81         }
82
83         $id = sanitize_title($name);
84         $options = array();
85         if ( !empty($classname) && is_string($classname) )
86                 $options['classname'] = $classname;
87         $params = array_slice(func_get_args(), 2);
88         $args = array($id, $name, $output_callback, $options);
89         if ( !empty($params) )
90                 $args = array_merge($args, $params);
91
92         call_user_func_array('wp_register_sidebar_widget', $args);
93 }
94
95 function wp_register_sidebar_widget($id, $name, $output_callback, $options = array()) {
96         global $wp_registered_widgets;
97
98         $id = strtolower($id);
99
100         if ( empty($output_callback) ) {
101                 unset($wp_registered_widgets[$id]);
102                 return;
103         }
104
105         $defaults = array('classname' => $output_callback);
106         $options = wp_parse_args($options, $defaults);
107         $widget = array(
108                 'name' => $name,
109                 'id' => $id,
110                 'callback' => $output_callback,
111                 'params' => array_slice(func_get_args(), 4)
112         );
113         $widget = array_merge($widget, $options);
114
115         if ( is_callable($output_callback) && ( !isset($wp_registered_widgets[$id]) || did_action( 'widgets_init' ) ) )
116                 $wp_registered_widgets[$id] = $widget;
117 }
118
119 function wp_widget_description( $id ) {
120         if ( !is_scalar($id) )
121                 return;
122
123         global $wp_registered_widgets;
124
125         if ( isset($wp_registered_widgets[$id]['description']) )
126                 return wp_specialchars( $wp_registered_widgets[$id]['description'] );
127 }
128
129 function unregister_sidebar_widget($id) {
130         return wp_unregister_sidebar_widget($id);
131 }
132
133 function wp_unregister_sidebar_widget($id) {
134         wp_register_sidebar_widget($id, '', '');
135         wp_unregister_widget_control($id);
136 }
137
138 function register_widget_control($name, $control_callback, $width = '', $height = '') {
139         // Compat
140         if ( is_array($name) ) {
141                 if ( count($name) == 3 )
142                         $name = sprintf($name[0], $name[2]);
143                 else
144                         $name = $name[0];
145         }
146
147         $id = sanitize_title($name);
148         $options = array();
149         if ( !empty($width) )
150                 $options['width'] = $width;
151         if ( !empty($height) )
152                 $options['height'] = $height;
153         $params = array_slice(func_get_args(), 4);
154         $args = array($id, $name, $control_callback, $options);
155         if ( !empty($params) )
156                 $args = array_merge($args, $params);
157
158         call_user_func_array('wp_register_widget_control', $args);
159 }
160
161 /* $options: height, width, id_base
162  *   height: never used
163  *   width:  width of fully expanded control form.  Try hard to use the default width.
164  *   id_base: for multi-widgets (widgets which allow multiple instances such as the text widget), an id_base must be provided.
165  *            the widget id will ennd up looking like {$id_base}-{$unique_number}
166  */
167 function wp_register_widget_control($id, $name, $control_callback, $options = array()) {
168         global $wp_registered_widget_controls;
169         
170         $id = strtolower($id);
171
172         if ( empty($control_callback) ) {
173                 unset($wp_registered_widget_controls[$id]);
174                 return;
175         }
176
177         if ( isset($wp_registered_widget_controls[$id]) && !did_action( 'widgets_init' ) )
178                 return;
179
180         $defaults = array('width' => 250, 'height' => 200 ); // height is never used
181         $options = wp_parse_args($options, $defaults);
182         $options['width'] = (int) $options['width'];
183         $options['height'] = (int) $options['height'];
184
185         $widget = array(
186                 'name' => $name,
187                 'id' => $id,
188                 'callback' => $control_callback,
189                 'params' => array_slice(func_get_args(), 4)
190         );
191         $widget = array_merge($widget, $options);
192
193         $wp_registered_widget_controls[$id] = $widget;
194 }
195
196 function unregister_widget_control($id) {
197         return wp_unregister_widget_control($id);
198 }
199
200 function wp_unregister_widget_control($id) {
201         return wp_register_widget_control($id, '', '');
202 }
203
204 function dynamic_sidebar($index = 1) {
205         global $wp_registered_sidebars, $wp_registered_widgets;
206
207         if ( is_int($index) ) {
208                 $index = "sidebar-$index";
209         } else {
210                 $index = sanitize_title($index);
211                 foreach ( $wp_registered_sidebars as $key => $value ) {
212                         if ( sanitize_title($value['name']) == $index ) {
213                                 $index = $key;
214                                 break;
215                         }
216                 }
217         }
218
219         $sidebars_widgets = wp_get_sidebars_widgets();
220
221         if ( empty($wp_registered_sidebars[$index]) || !array_key_exists($index, $sidebars_widgets) || !is_array($sidebars_widgets[$index]) || empty($sidebars_widgets[$index]) )
222                 return false;
223
224         $sidebar = $wp_registered_sidebars[$index];
225
226         $did_one = false;
227         foreach ( $sidebars_widgets[$index] as $id ) {
228                 $params = array_merge(
229                         array( array_merge( $sidebar, array('widget_id' => $id, 'widget_name' => $wp_registered_widgets[$id]['name']) ) ),
230                         (array) $wp_registered_widgets[$id]['params']
231                 );
232
233                 // Substitute HTML id and class attributes into before_widget
234                 $classname_ = '';
235                 foreach ( (array) $wp_registered_widgets[$id]['classname'] as $cn ) {
236                         if ( is_string($cn) )
237                                 $classname_ .= '_' . $cn;
238                         elseif ( is_object($cn) )
239                                 $classname_ .= '_' . get_class($cn);
240                 }
241                 $classname_ = ltrim($classname_, '_');
242                 $params[0]['before_widget'] = sprintf($params[0]['before_widget'], $id, $classname_);
243
244                 $params = apply_filters( 'dynamic_sidebar_params', $params );
245
246                 $callback = $wp_registered_widgets[$id]['callback'];
247
248                 if ( is_callable($callback) ) {
249                         call_user_func_array($callback, $params);
250                         $did_one = true;
251                 }
252         }
253
254         return $did_one;
255 }
256
257 /* @return mixed false if widget is not active or id of sidebar in which the widget is active
258  */
259 function is_active_widget($callback, $widget_id = false) {
260         global $wp_registered_widgets;
261
262         $sidebars_widgets = wp_get_sidebars_widgets(false);
263
264         if ( is_array($sidebars_widgets) ) foreach ( $sidebars_widgets as $sidebar => $widgets )
265                 if ( is_array($widgets) ) foreach ( $widgets as $widget )
266                         if ( isset($wp_registered_widgets[$widget]['callback']) && $wp_registered_widgets[$widget]['callback'] == $callback )
267                                 if ( !$widget_id || $widget_id == $wp_registered_widgets[$widget]['id'] )
268                                         return $sidebar;
269
270
271         return false;
272 }
273
274 function is_dynamic_sidebar() {
275         global $wp_registered_widgets, $wp_registered_sidebars;
276         $sidebars_widgets = get_option('sidebars_widgets');
277         foreach ( $wp_registered_sidebars as $index => $sidebar ) {
278                 if ( count($sidebars_widgets[$index]) ) {
279                         foreach ( $sidebars_widgets[$index] as $widget )
280                                 if ( array_key_exists($widget, $wp_registered_widgets) )
281                                         return true;
282                 }
283         }
284         return false;
285 }
286
287 /* Internal Functions */
288
289 function wp_get_sidebars_widgets($update = true) {
290         global $wp_registered_widgets, $wp_registered_sidebars;
291
292         $sidebars_widgets = get_option('sidebars_widgets');
293         $_sidebars_widgets = array();
294
295         if ( !isset($sidebars_widgets['array_version']) )
296                 $sidebars_widgets['array_version'] = 1;
297
298         switch ( $sidebars_widgets['array_version'] ) {
299                 case 1 :
300                         foreach ( $sidebars_widgets as $index => $sidebar )
301                         if ( is_array($sidebar) )
302                         foreach ( $sidebar as $i => $name ) {
303                                 $id = strtolower($name);
304                                 if ( isset($wp_registered_widgets[$id]) ) {
305                                         $_sidebars_widgets[$index][$i] = $id;
306                                         continue;
307                                 }
308                                 $id = sanitize_title($name);
309                                 if ( isset($wp_registered_widgets[$id]) ) {
310                                         $_sidebars_widgets[$index][$i] = $id;
311                                         continue;
312                                 }
313
314                                 $found = false;
315
316                                 foreach ( $wp_registered_widgets as $widget_id => $widget ) {
317                                         if ( strtolower($widget['name']) == strtolower($name) ) {
318                                                 $_sidebars_widgets[$index][$i] = $widget['id'];
319                                                 $found = true;
320                                                 break;
321                                         } elseif ( sanitize_title($widget['name']) == sanitize_title($name) ) {
322                                                 $_sidebars_widgets[$index][$i] = $widget['id'];
323                                                 $found = true;
324                                                 break;
325                                         }
326                                 }
327
328                                 if ( $found )
329                                         continue;
330
331                                 unset($_sidebars_widgets[$index][$i]);
332                         }
333                         $_sidebars_widgets['array_version'] = 2;
334                         $sidebars_widgets = $_sidebars_widgets;
335                         unset($_sidebars_widgets);
336
337                 case 2 :
338                         $sidebars = array_keys( $wp_registered_sidebars );
339                         if ( !empty( $sidebars ) ) {
340                                 // Move the known-good ones first
341                                 foreach ( $sidebars as $id ) {
342                                         if ( array_key_exists( $id, $sidebars_widgets ) ) {
343                                                 $_sidebars_widgets[$id] = $sidebars_widgets[$id];
344                                                 unset($sidebars_widgets[$id], $sidebars[$id]);
345                                         }
346                                 }
347
348                                 // Assign to each unmatched registered sidebar the first available orphan
349                                 unset( $sidebars_widgets[ 'array_version' ] );
350                                 while ( ( $sidebar = array_shift( $sidebars ) ) && $widgets = array_shift( $sidebars_widgets ) )
351                                         $_sidebars_widgets[ $sidebar ] = $widgets;
352
353                                 $_sidebars_widgets['array_version'] = 3;
354                                 $sidebars_widgets = $_sidebars_widgets;
355                                 unset($_sidebars_widgets);
356                         }
357
358                         if ( $update )
359                                 update_option('sidebars_widgets', $sidebars_widgets);
360         }
361
362         unset($sidebars_widgets['array_version']);
363
364         return $sidebars_widgets;
365 }
366
367 function wp_set_sidebars_widgets( $sidebars_widgets ) {
368         update_option( 'sidebars_widgets', $sidebars_widgets );
369 }
370
371 function wp_get_widget_defaults() {
372         global $wp_registered_sidebars;
373
374         $defaults = array();
375
376         foreach ( $wp_registered_sidebars as $index => $sidebar )
377                 $defaults[$index] = array();
378
379         return $defaults;
380 }
381
382 /* Default Widgets */
383
384 function wp_widget_pages( $args ) {
385         extract( $args );
386         $options = get_option( 'widget_pages' );
387
388         $title = empty( $options['title'] ) ? __( 'Pages' ) : apply_filters('widget_title', $options['title']);
389         $sortby = empty( $options['sortby'] ) ? 'menu_order' : $options['sortby'];
390         $exclude = empty( $options['exclude'] ) ? '' : $options['exclude'];
391
392         if ( $sortby == 'menu_order' ) {
393                 $sortby = 'menu_order, post_title';
394         }
395
396         $out = wp_list_pages( array('title_li' => '', 'echo' => 0, 'sort_column' => $sortby, 'exclude' => $exclude) );
397
398         if ( !empty( $out ) ) {
399 ?>
400         <?php echo $before_widget; ?>
401                 <?php echo $before_title . $title . $after_title; ?>
402                 <ul>
403                         <?php echo $out; ?>
404                 </ul>
405         <?php echo $after_widget; ?>
406 <?php
407         }
408 }
409
410 function wp_widget_pages_control() {
411         $options = $newoptions = get_option('widget_pages');
412         if ( $_POST['pages-submit'] ) {
413                 $newoptions['title'] = strip_tags(stripslashes($_POST['pages-title']));
414
415                 $sortby = stripslashes( $_POST['pages-sortby'] );
416
417                 if ( in_array( $sortby, array( 'post_title', 'menu_order', 'ID' ) ) ) {
418                         $newoptions['sortby'] = $sortby;
419                 } else {
420                         $newoptions['sortby'] = 'menu_order';
421                 }
422
423                 $newoptions['exclude'] = strip_tags( stripslashes( $_POST['pages-exclude'] ) );
424         }
425         if ( $options != $newoptions ) {
426                 $options = $newoptions;
427                 update_option('widget_pages', $options);
428         }
429         $title = attribute_escape($options['title']);
430         $exclude = attribute_escape( $options['exclude'] );
431 ?>
432                 <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>
433                 <p>
434                         <label for="pages-sortby"><?php _e( 'Sort by:' ); ?>
435                                 <select name="pages-sortby" id="pages-sortby" class="widefat">
436                                         <option value="post_title"<?php selected( $options['sortby'], 'post_title' ); ?>><?php _e('Page title'); ?></option>
437                                         <option value="menu_order"<?php selected( $options['sortby'], 'menu_order' ); ?>><?php _e('Page order'); ?></option>
438                                         <option value="ID"<?php selected( $options['sortby'], 'ID' ); ?>><?php _e( 'Page ID' ); ?></option>
439                                 </select>
440                         </label>
441                 </p>
442                 <p>
443                         <label for="pages-exclude"><?php _e( 'Exclude:' ); ?> <input type="text" value="<?php echo $exclude; ?>" name="pages-exclude" id="pages-exclude" class="widefat" /></label>
444                         <br />
445                         <small><?php _e( 'Page IDs, separated by commas.' ); ?></small>
446                 </p>
447                 <input type="hidden" id="pages-submit" name="pages-submit" value="1" />
448 <?php
449 }
450
451 function wp_widget_links($args) {
452         extract($args, EXTR_SKIP);
453
454         $before_widget = preg_replace('/id="[^"]*"/','id="%id"', $before_widget);
455         wp_list_bookmarks(apply_filters('widget_links_args', array(
456                 'title_before' => $before_title, 'title_after' => $after_title,
457                 'category_before' => $before_widget, 'category_after' => $after_widget,
458                 'show_images' => true, 'class' => 'linkcat widget'
459         )));
460 }
461
462 function wp_widget_search($args) {
463         extract($args);
464         $searchform_template = get_template_directory() . '/searchform.php';
465         
466         echo $before_widget;
467         
468         // Use current theme search form if it exists
469         if ( file_exists($searchform_template) ) {
470                 include_once($searchform_template);
471         } else { ?>
472                 <form id="searchform" method="get" action="<?php bloginfo('url'); ?>/"><div>
473                         <label class="hidden" for="s"><?php _e('Search for:'); ?></label>
474                         <input type="text" name="s" id="s" size="15" value="<?php the_search_query(); ?>" />
475                         <input type="submit" value="<?php echo attribute_escape(__('Search')); ?>" />
476                 </div></form>
477         <?php }
478         
479         echo $after_widget;
480 }
481
482 function wp_widget_archives($args) {
483         extract($args);
484         $options = get_option('widget_archives');
485         $c = $options['count'] ? '1' : '0';
486         $d = $options['dropdown'] ? '1' : '0';
487         $title = empty($options['title']) ? __('Archives') : apply_filters('widget_title', $options['title']);
488
489         echo $before_widget;
490         echo $before_title . $title . $after_title;
491
492         if($d) {
493 ?>
494                 <select name="archive-dropdown" onchange='document.location.href=this.options[this.selectedIndex].value;'> <option value=""><?php echo attribute_escape(__('Select Month')); ?></option> <?php wp_get_archives("type=monthly&format=option&show_post_count=$c"); ?> </select>
495 <?php
496         } else {
497 ?>
498                 <ul>
499                 <?php wp_get_archives("type=monthly&show_post_count=$c"); ?>
500                 </ul>
501 <?php
502         }
503
504         echo $after_widget;
505 }
506
507 function wp_widget_archives_control() {
508         $options = $newoptions = get_option('widget_archives');
509         if ( $_POST["archives-submit"] ) {
510                 $newoptions['count'] = isset($_POST['archives-count']);
511                 $newoptions['dropdown'] = isset($_POST['archives-dropdown']);
512                 $newoptions['title'] = strip_tags(stripslashes($_POST["archives-title"]));
513         }
514         if ( $options != $newoptions ) {
515                 $options = $newoptions;
516                 update_option('widget_archives', $options);
517         }
518         $count = $options['count'] ? 'checked="checked"' : '';
519         $dropdown = $options['dropdown'] ? 'checked="checked"' : '';
520         $title = attribute_escape($options['title']);
521 ?>
522                         <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>
523                         <p>
524                                 <label for="archives-count"><input class="checkbox" type="checkbox" <?php echo $count; ?> id="archives-count" name="archives-count" /> <?php _e('Show post counts'); ?></label>
525                                 <br />
526                                 <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>
527                         </p>
528                         <input type="hidden" id="archives-submit" name="archives-submit" value="1" />
529 <?php
530 }
531
532 function wp_widget_meta($args) {
533         extract($args);
534         $options = get_option('widget_meta');
535         $title = empty($options['title']) ? __('Meta') : apply_filters('widget_title', $options['title']);
536 ?>
537                 <?php echo $before_widget; ?>
538                         <?php echo $before_title . $title . $after_title; ?>
539                         <ul>
540                         <?php wp_register(); ?>
541                         <li><?php wp_loginout(); ?></li>
542                         <li><a href="<?php bloginfo('rss2_url'); ?>" title="<?php echo attribute_escape(__('Syndicate this site using RSS 2.0')); ?>"><?php _e('Entries <abbr title="Really Simple Syndication">RSS</abbr>'); ?></a></li>
543                         <li><a href="<?php bloginfo('comments_rss2_url'); ?>" title="<?php echo attribute_escape(__('The latest comments to all posts in RSS')); ?>"><?php _e('Comments <abbr title="Really Simple Syndication">RSS</abbr>'); ?></a></li>
544                         <li><a href="http://wordpress.org/" title="<?php echo attribute_escape(__('Powered by WordPress, state-of-the-art semantic personal publishing platform.')); ?>">WordPress.org</a></li>
545                         <?php wp_meta(); ?>
546                         </ul>
547                 <?php echo $after_widget; ?>
548 <?php
549 }
550 function wp_widget_meta_control() {
551         $options = $newoptions = get_option('widget_meta');
552         if ( $_POST["meta-submit"] ) {
553                 $newoptions['title'] = strip_tags(stripslashes($_POST["meta-title"]));
554         }
555         if ( $options != $newoptions ) {
556                 $options = $newoptions;
557                 update_option('widget_meta', $options);
558         }
559         $title = attribute_escape($options['title']);
560 ?>
561                         <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>
562                         <input type="hidden" id="meta-submit" name="meta-submit" value="1" />
563 <?php
564 }
565
566 function wp_widget_calendar($args) {
567         extract($args);
568         $options = get_option('widget_calendar');
569         $title = apply_filters('widget_title', $options['title']);
570         if ( empty($title) )
571                 $title = '&nbsp;';
572         echo $before_widget . $before_title . $title . $after_title;
573         echo '<div id="calendar_wrap">';
574         get_calendar();
575         echo '</div>';
576         echo $after_widget;
577 }
578 function wp_widget_calendar_control() {
579         $options = $newoptions = get_option('widget_calendar');
580         if ( $_POST["calendar-submit"] ) {
581                 $newoptions['title'] = strip_tags(stripslashes($_POST["calendar-title"]));
582         }
583         if ( $options != $newoptions ) {
584                 $options = $newoptions;
585                 update_option('widget_calendar', $options);
586         }
587         $title = attribute_escape($options['title']);
588 ?>
589                         <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>
590                         <input type="hidden" id="calendar-submit" name="calendar-submit" value="1" />
591 <?php
592 }
593
594 // See large comment section at end of this file
595 function wp_widget_text($args, $widget_args = 1) {
596         extract( $args, EXTR_SKIP );
597         if ( is_numeric($widget_args) )
598                 $widget_args = array( 'number' => $widget_args );
599         $widget_args = wp_parse_args( $widget_args, array( 'number' => -1 ) );
600         extract( $widget_args, EXTR_SKIP );
601
602         $options = get_option('widget_text');
603         if ( !isset($options[$number]) )
604                 return;
605
606         $title = apply_filters('widget_title', $options[$number]['title']);
607         $text = apply_filters( 'widget_text', $options[$number]['text'] );
608 ?>
609                 <?php echo $before_widget; ?>
610                         <?php if ( !empty( $title ) ) { echo $before_title . $title . $after_title; } ?>
611                         <div class="textwidget"><?php echo $text; ?></div>
612                 <?php echo $after_widget; ?>
613 <?php
614 }
615
616 function wp_widget_text_control($widget_args) {
617         global $wp_registered_widgets;
618         static $updated = false;
619
620         if ( is_numeric($widget_args) )
621                 $widget_args = array( 'number' => $widget_args );
622         $widget_args = wp_parse_args( $widget_args, array( 'number' => -1 ) );
623         extract( $widget_args, EXTR_SKIP );
624
625         $options = get_option('widget_text');
626         if ( !is_array($options) )
627                 $options = array();
628
629         if ( !$updated && !empty($_POST['sidebar']) ) {
630                 $sidebar = (string) $_POST['sidebar'];
631
632                 $sidebars_widgets = wp_get_sidebars_widgets();
633                 if ( isset($sidebars_widgets[$sidebar]) )
634                         $this_sidebar =& $sidebars_widgets[$sidebar];
635                 else
636                         $this_sidebar = array();
637
638                 foreach ( $this_sidebar as $_widget_id ) {
639                         if ( 'wp_widget_text' == $wp_registered_widgets[$_widget_id]['callback'] && isset($wp_registered_widgets[$_widget_id]['params'][0]['number']) ) {
640                                 $widget_number = $wp_registered_widgets[$_widget_id]['params'][0]['number'];
641                                 if ( !in_array( "text-$widget_number", $_POST['widget-id'] ) ) // the widget has been removed.
642                                         unset($options[$widget_number]);
643                         }
644                 }
645
646                 foreach ( (array) $_POST['widget-text'] as $widget_number => $widget_text ) {
647                         if ( !isset($widget_text['text']) && isset($options[$widget_number]) ) // user clicked cancel
648                                 continue;
649                         $title = strip_tags(stripslashes($widget_text['title']));
650                         if ( current_user_can('unfiltered_html') )
651                                 $text = stripslashes( $widget_text['text'] );
652                         else
653                                 $text = stripslashes(wp_filter_post_kses( $widget_text['text'] ));
654                         $options[$widget_number] = compact( 'title', 'text' );
655                 }
656
657                 update_option('widget_text', $options);
658                 $updated = true;
659         }
660
661         if ( -1 == $number ) {
662                 $title = '';
663                 $text = '';
664                 $number = '%i%';
665         } else {
666                 $title = attribute_escape($options[$number]['title']);
667                 $text = format_to_edit($options[$number]['text']);
668         }
669 ?>
670                 <p>
671                         <input class="widefat" id="text-title-<?php echo $number; ?>" name="widget-text[<?php echo $number; ?>][title]" type="text" value="<?php echo $title; ?>" />
672                         <textarea class="widefat" rows="16" cols="20" id="text-text-<?php echo $number; ?>" name="widget-text[<?php echo $number; ?>][text]"><?php echo $text; ?></textarea>
673                         <input type="hidden" name="widget-text[<?php echo $number; ?>][submit]" value="1" />
674                 </p>
675 <?php
676 }
677
678 function wp_widget_text_register() {
679         if ( !$options = get_option('widget_text') )
680                 $options = array();
681         $widget_ops = array('classname' => 'widget_text', 'description' => __('Arbitrary text or HTML'));
682         $control_ops = array('width' => 400, 'height' => 350, 'id_base' => 'text');
683         $name = __('Text');
684
685         $id = false;
686         foreach ( array_keys($options) as $o ) {
687                 // Old widgets can have null values for some reason
688                 if ( !isset($options[$o]['title']) || !isset($options[$o]['text']) )
689                         continue;
690                 $id = "text-$o"; // Never never never translate an id
691                 wp_register_sidebar_widget($id, $name, 'wp_widget_text', $widget_ops, array( 'number' => $o ));
692                 wp_register_widget_control($id, $name, 'wp_widget_text_control', $control_ops, array( 'number' => $o ));
693         }
694
695         // If there are none, we register the widget's existance with a generic template
696         if ( !$id ) {
697                 wp_register_sidebar_widget( 'text-1', $name, 'wp_widget_text', $widget_ops, array( 'number' => -1 ) );
698                 wp_register_widget_control( 'text-1', $name, 'wp_widget_text_control', $control_ops, array( 'number' => -1 ) );
699         }
700 }
701
702 // See large comment section at end of this file
703 function wp_widget_categories($args, $widget_args = 1) {
704         extract($args, EXTR_SKIP);
705         if ( is_numeric($widget_args) )
706                 $widget_args = array( 'number' => $widget_args );
707         $widget_args = wp_parse_args( $widget_args, array( 'number' => -1 ) );
708         extract($widget_args, EXTR_SKIP);
709
710         $options = get_option('widget_categories');
711         if ( !isset($options[$number]) )
712                 return;
713
714         $c = $options[$number]['count'] ? '1' : '0';
715         $h = $options[$number]['hierarchical'] ? '1' : '0';
716         $d = $options[$number]['dropdown'] ? '1' : '0';
717
718         $title = empty($options[$number]['title']) ? __('Categories') : apply_filters('widget_title', $options[$number]['title']);
719
720         echo $before_widget;
721         echo $before_title . $title . $after_title;
722
723         $cat_args = array('orderby' => 'name', 'show_count' => $c, 'hierarchical' => $h);
724
725         if ( $d ) {
726                 $cat_args['show_option_none'] = __('Select Category');
727                 wp_dropdown_categories($cat_args);
728 ?>
729
730 <script type='text/javascript'>
731 /* <![CDATA[ */
732     var dropdown = document.getElementById("cat");
733     function onCatChange() {
734                 if ( dropdown.options[dropdown.selectedIndex].value > 0 ) {
735                         location.href = "<?php echo get_option('home'); ?>/?cat="+dropdown.options[dropdown.selectedIndex].value;
736                 }
737     }
738     dropdown.onchange = onCatChange;
739 /* ]]> */
740 </script>
741
742 <?php
743         } else {
744 ?>
745                 <ul>
746                 <?php 
747                         $cat_args['title_li'] = '';
748                         wp_list_categories($cat_args); 
749                 ?>
750                 </ul>
751 <?php
752         }
753
754         echo $after_widget;
755 }
756
757 function wp_widget_categories_control( $widget_args ) {
758         global $wp_registered_widgets;
759         static $updated = false;
760
761         if ( is_numeric($widget_args) )
762                 $widget_args = array( 'number' => $widget_args );
763         $widget_args = wp_parse_args( $widget_args, array( 'number' => -1 ) );
764         extract($widget_args, EXTR_SKIP);
765
766         $options = get_option('widget_categories');
767
768         if ( !is_array( $options ) )
769                 $options = array();
770
771         if ( !$updated && !empty($_POST['sidebar']) ) {
772                 $sidebar = (string) $_POST['sidebar'];
773
774                 $sidebars_widgets = wp_get_sidebars_widgets();
775                 if ( isset($sidebars_widgets[$sidebar]) )
776                         $this_sidebar =& $sidebars_widgets[$sidebar];
777                 else
778                         $this_sidebar = array();
779
780                 foreach ( $this_sidebar as $_widget_id ) {
781                         if ( 'wp_widget_categories' == $wp_registered_widgets[$_widget_id]['callback'] && isset($wp_registered_widgets[$_widget_id]['params'][0]['number']) ) {
782                                 $widget_number = $wp_registered_widgets[$_widget_id]['params'][0]['number'];
783                                 if ( !in_array( "categories-$widget_number", $_POST['widget-id'] ) ) // the widget has been removed.
784                                         unset($options[$widget_number]);
785                         }
786                 }
787
788                 foreach ( (array) $_POST['widget-categories'] as $widget_number => $widget_cat ) {
789                         if ( !isset($widget_cat['title']) && isset($options[$widget_number]) ) // user clicked cancel
790                                 continue;
791                         $title = trim(strip_tags(stripslashes($widget_cat['title'])));
792                         $count = isset($widget_cat['count']);
793                         $hierarchical = isset($widget_cat['hierarchical']);
794                         $dropdown = isset($widget_cat['dropdown']);
795                         $options[$widget_number] = compact( 'title', 'count', 'hierarchical', 'dropdown' );
796                 }
797
798                 update_option('widget_categories', $options);
799                 $updated = true;
800         }
801
802         if ( -1 == $number ) {
803                 $title = '';
804                 $count = false;
805                 $hierarchical = false;
806                 $dropdown = false;
807                 $number = '%i%';
808         } else {
809                 $title = attribute_escape( $options[$number]['title'] );
810                 $count = (bool) $options[$number]['count'];
811                 $hierarchical = (bool) $options[$number]['hierarchical'];
812                 $dropdown = (bool) $options[$number]['dropdown'];
813         }
814 ?>
815                         <p>
816                                 <label for="categories-title-<?php echo $number; ?>">
817                                         <?php _e( 'Title:' ); ?>
818                                         <input class="widefat" id="categories-title-<?php echo $number; ?>" name="widget-categories[<?php echo $number; ?>][title]" type="text" value="<?php echo $title; ?>" />
819                                 </label>
820                         </p>
821
822                         <p>
823                                 <label for="categories-dropdown-<?php echo $number; ?>">
824                                         <input type="checkbox" class="checkbox" id="categories-dropdown-<?php echo $number; ?>" name="widget-categories[<?php echo $number; ?>][dropdown]"<?php checked( $dropdown, true ); ?> />
825                                         <?php _e( 'Show as dropdown' ); ?>
826                                 </label>
827                                 <br />
828                                 <label for="categories-count-<?php echo $number; ?>">
829                                         <input type="checkbox" class="checkbox" id="categories-count-<?php echo $number; ?>" name="widget-categories[<?php echo $number; ?>][count]"<?php checked( $count, true ); ?> />
830                                         <?php _e( 'Show post counts' ); ?>
831                                 </label>
832                                 <br />
833                                 <label for="categories-hierarchical-<?php echo $number; ?>">
834                                         <input type="checkbox" class="checkbox" id="categories-hierarchical-<?php echo $number; ?>" name="widget-categories[<?php echo $number; ?>][hierarchical]"<?php checked( $hierarchical, true ); ?> />
835                                         <?php _e( 'Show hierarchy' ); ?>
836                                 </label>
837                         </p>
838
839                         <input type="hidden" name="widget-categories[<?php echo $number; ?>][submit]" value="1" />
840 <?php
841 }
842
843 function wp_widget_categories_register() {
844         if ( !$options = get_option( 'widget_categories' ) )
845                 $options = array();
846
847         if ( isset($options['title']) )
848                 $options = wp_widget_categories_upgrade();
849
850         $widget_ops = array( 'classname' => 'widget_categories', 'description' => __( "A list or dropdown of categories" ) );
851
852         $name = __( 'Categories' );
853
854         $id = false;
855         foreach ( array_keys($options) as $o ) {
856                 // Old widgets can have null values for some reason
857                 if ( !isset($options[$o]['title']) )
858                         continue;
859                 $id = "categories-$o";
860                 wp_register_sidebar_widget( $id, $name, 'wp_widget_categories', $widget_ops, array( 'number' => $o ) );
861                 wp_register_widget_control( $id, $name, 'wp_widget_categories_control', array( 'id_base' => 'categories' ), array( 'number' => $o ) );
862         }
863
864         // If there are none, we register the widget's existance with a generic template
865         if ( !$id ) {
866                 wp_register_sidebar_widget( 'categories-1', $name, 'wp_widget_categories', $widget_ops, array( 'number' => -1 ) );
867                 wp_register_widget_control( 'categories-1', $name, 'wp_widget_categories_control', array( 'id_base' => 'categories' ), array( 'number' => -1 ) );
868         }
869 }
870
871 function wp_widget_categories_upgrade() {
872         $options = get_option( 'widget_categories' );
873
874         if ( !isset( $options['title'] ) )
875                 return $options;
876
877         $newoptions = array( 1 => $options );
878
879         update_option( 'widget_categories', $newoptions );
880
881         $sidebars_widgets = get_option( 'sidebars_widgets' );
882         if ( is_array( $sidebars_widgets ) ) {
883                 foreach ( $sidebars_widgets as $sidebar => $widgets ) {
884                         if ( is_array( $widgets ) ) {
885                                 foreach ( $widgets as $widget )
886                                         $new_widgets[$sidebar][] = ( $widget == 'categories' ) ? 'categories-1' : $widget;
887                         } else {
888                                 $new_widgets[$sidebar] = $widgets;
889                         }
890                 }
891                 if ( $new_widgets != $sidebars_widgets )
892                         update_option( 'sidebars_widgets', $new_widgets );
893         }
894
895         return $newoptions;
896 }
897
898 function wp_widget_recent_entries($args) {
899         if ( '%BEG_OF_TITLE%' != $args['before_title'] ) {
900                 if ( $output = wp_cache_get('widget_recent_entries', 'widget') )
901                         return print($output);
902                 ob_start();
903         }
904
905         extract($args);
906         $options = get_option('widget_recent_entries');
907         $title = empty($options['title']) ? __('Recent Posts') : apply_filters('widget_title', $options['title']);
908         if ( !$number = (int) $options['number'] )
909                 $number = 10;
910         else if ( $number < 1 )
911                 $number = 1;
912         else if ( $number > 15 )
913                 $number = 15;
914
915         $r = new WP_Query(array('showposts' => $number, 'what_to_show' => 'posts', 'nopaging' => 0, 'post_status' => 'publish'));
916         if ($r->have_posts()) :
917 ?>
918                 <?php echo $before_widget; ?>
919                         <?php echo $before_title . $title . $after_title; ?>
920                         <ul>
921                         <?php  while ($r->have_posts()) : $r->the_post(); ?>
922                         <li><a href="<?php the_permalink() ?>"><?php if ( get_the_title() ) the_title(); else the_ID(); ?> </a></li>
923                         <?php endwhile; ?>
924                         </ul>
925                 <?php echo $after_widget; ?>
926 <?php
927                 wp_reset_query();  // Restore global post data stomped by the_post().
928         endif;
929
930         if ( '%BEG_OF_TITLE%' != $args['before_title'] )
931                 wp_cache_add('widget_recent_entries', ob_get_flush(), 'widget');
932 }
933
934 function wp_flush_widget_recent_entries() {
935         wp_cache_delete('widget_recent_entries', 'widget');
936 }
937
938 add_action('save_post', 'wp_flush_widget_recent_entries');
939 add_action('deleted_post', 'wp_flush_widget_recent_entries');
940 add_action('switch_theme', 'wp_flush_widget_recent_entries');
941
942 function wp_widget_recent_entries_control() {
943         $options = $newoptions = get_option('widget_recent_entries');
944         if ( $_POST["recent-entries-submit"] ) {
945                 $newoptions['title'] = strip_tags(stripslashes($_POST["recent-entries-title"]));
946                 $newoptions['number'] = (int) $_POST["recent-entries-number"];
947         }
948         if ( $options != $newoptions ) {
949                 $options = $newoptions;
950                 update_option('widget_recent_entries', $options);
951                 wp_flush_widget_recent_entries();
952         }
953         $title = attribute_escape($options['title']);
954         if ( !$number = (int) $options['number'] )
955                 $number = 5;
956 ?>
957
958                         <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>
959                         <p>
960                                 <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>
961                                 <br />
962                                 <small><?php _e('(at most 15)'); ?></small>
963                         </p>
964                         <input type="hidden" id="recent-entries-submit" name="recent-entries-submit" value="1" />
965 <?php
966 }
967
968 function wp_widget_recent_comments($args) {
969         global $wpdb, $comments, $comment;
970         extract($args, EXTR_SKIP);
971         $options = get_option('widget_recent_comments');
972         $title = empty($options['title']) ? __('Recent Comments') : apply_filters('widget_title', $options['title']);
973         if ( !$number = (int) $options['number'] )
974                 $number = 5;
975         else if ( $number < 1 )
976                 $number = 1;
977         else if ( $number > 15 )
978                 $number = 15;
979
980         if ( !$comments = wp_cache_get( 'recent_comments', 'widget' ) ) {
981                 $comments = $wpdb->get_results("SELECT comment_author, comment_author_url, comment_ID, comment_post_ID FROM $wpdb->comments WHERE comment_approved = '1' ORDER BY comment_date_gmt DESC LIMIT $number");
982                 wp_cache_add( 'recent_comments', $comments, 'widget' );
983         }
984 ?>
985
986                 <?php echo $before_widget; ?>
987                         <?php echo $before_title . $title . $after_title; ?>
988                         <ul id="recentcomments"><?php
989                         if ( $comments ) : foreach ($comments as $comment) :
990                         echo  '<li class="recentcomments">' . sprintf(__('%1$s on %2$s'), get_comment_author_link(), '<a href="'. get_permalink($comment->comment_post_ID) . '#comment-' . $comment->comment_ID . '">' . get_the_title($comment->comment_post_ID) . '</a>') . '</li>';
991                         endforeach; endif;?></ul>
992                 <?php echo $after_widget; ?>
993 <?php
994 }
995
996 function wp_delete_recent_comments_cache() {
997         wp_cache_delete( 'recent_comments', 'widget' );
998 }
999 add_action( 'comment_post', 'wp_delete_recent_comments_cache' );
1000 add_action( 'wp_set_comment_status', 'wp_delete_recent_comments_cache' );
1001
1002 function wp_widget_recent_comments_control() {
1003         $options = $newoptions = get_option('widget_recent_comments');
1004         if ( $_POST["recent-comments-submit"] ) {
1005                 $newoptions['title'] = strip_tags(stripslashes($_POST["recent-comments-title"]));
1006                 $newoptions['number'] = (int) $_POST["recent-comments-number"];
1007         }
1008         if ( $options != $newoptions ) {
1009                 $options = $newoptions;
1010                 update_option('widget_recent_comments', $options);
1011                 wp_delete_recent_comments_cache();
1012         }
1013         $title = attribute_escape($options['title']);
1014         if ( !$number = (int) $options['number'] )
1015                 $number = 5;
1016 ?>
1017                         <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>
1018                         <p>
1019                                 <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>
1020                                 <br />
1021                                 <small><?php _e('(at most 15)'); ?></small>
1022                         </p>
1023                         <input type="hidden" id="recent-comments-submit" name="recent-comments-submit" value="1" />
1024 <?php
1025 }
1026
1027 function wp_widget_recent_comments_style() {
1028 ?>
1029 <style type="text/css">.recentcomments a{display:inline !important;padding: 0 !important;margin: 0 !important;}</style>
1030 <?php
1031 }
1032
1033 function wp_widget_recent_comments_register() {
1034         $widget_ops = array('classname' => 'widget_recent_comments', 'description' => __( 'The most recent comments' ) );
1035         wp_register_sidebar_widget('recent-comments', __('Recent Comments'), 'wp_widget_recent_comments', $widget_ops);
1036         wp_register_widget_control('recent-comments', __('Recent Comments'), 'wp_widget_recent_comments_control');
1037
1038         if ( is_active_widget('wp_widget_recent_comments') )
1039                 add_action('wp_head', 'wp_widget_recent_comments_style');
1040 }
1041
1042 // See large comment section at end of this file
1043 function wp_widget_rss($args, $widget_args = 1) {
1044         extract($args, EXTR_SKIP);
1045         if ( is_numeric($widget_args) )
1046                 $widget_args = array( 'number' => $widget_args );
1047         $widget_args = wp_parse_args( $widget_args, array( 'number' => -1 ) );
1048         extract($widget_args, EXTR_SKIP);
1049
1050         $options = get_option('widget_rss');
1051
1052         if ( !isset($options[$number]) )
1053                 return;
1054
1055         if ( isset($options[$number]['error']) && $options[$number]['error'] )
1056                 return;
1057
1058         $url = $options[$number]['url'];
1059         while ( strstr($url, 'http') != $url )
1060                 $url = substr($url, 1);
1061         if ( empty($url) )
1062                 return;
1063
1064         require_once(ABSPATH . WPINC . '/rss.php');
1065
1066         $rss = fetch_rss($url);
1067         $link = clean_url(strip_tags($rss->channel['link']));
1068         while ( strstr($link, 'http') != $link )
1069                 $link = substr($link, 1);
1070         $desc = attribute_escape(strip_tags(html_entity_decode($rss->channel['description'], ENT_QUOTES)));
1071         $title = $options[$number]['title'];
1072         if ( empty($title) )
1073                 $title = htmlentities(strip_tags($rss->channel['title']));
1074         if ( empty($title) )
1075                 $title = $desc;
1076         if ( empty($title) )
1077                 $title = __('Unknown Feed');
1078         $title = apply_filters('widget_title', $title );
1079         $url = clean_url(strip_tags($url));
1080         if ( file_exists(dirname(__FILE__) . '/rss.png') )
1081                 $icon = str_replace(ABSPATH, site_url() . '/', dirname(__FILE__)) . '/rss.png';
1082         else
1083                 $icon = includes_url('images/rss.png');
1084         $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>";
1085
1086         echo $before_widget;
1087         echo $before_title . $title . $after_title;
1088
1089         wp_widget_rss_output( $rss, $options[$number] );
1090
1091         echo $after_widget;
1092 }
1093
1094 function wp_widget_rss_output( $rss, $args = array() ) {
1095         if ( is_string( $rss ) ) {
1096                 require_once(ABSPATH . WPINC . '/rss.php');
1097                 if ( !$rss = fetch_rss($rss) )
1098                         return;
1099         } elseif ( is_array($rss) && isset($rss['url']) ) {
1100                 require_once(ABSPATH . WPINC . '/rss.php');
1101                 $args = $rss;
1102                 if ( !$rss = fetch_rss($rss['url']) )
1103                         return;
1104         } elseif ( !is_object($rss) ) {
1105                 return;
1106         }
1107
1108         extract( $args, EXTR_SKIP );
1109
1110         $items = (int) $items;
1111         if ( $items < 1 || 20 < $items )
1112                 $items = 10;
1113         $show_summary  = (int) $show_summary;
1114         $show_author   = (int) $show_author;
1115         $show_date     = (int) $show_date;
1116
1117         if ( is_array( $rss->items ) && !empty( $rss->items ) ) {
1118                 $rss->items = array_slice($rss->items, 0, $items);
1119                 echo '<ul>';
1120                 foreach ($rss->items as $item ) {
1121                         while ( strstr($item['link'], 'http') != $item['link'] )
1122                                 $item['link'] = substr($item['link'], 1);
1123                         $link = clean_url(strip_tags($item['link']));
1124                         $title = attribute_escape(strip_tags($item['title']));
1125                         if ( empty($title) )
1126                                 $title = __('Untitled');
1127                         $desc = '';
1128                         $summary = '';
1129                         if ( isset( $item['description'] ) && is_string( $item['description'] ) )
1130                                 $desc = $summary = str_replace(array("\n", "\r"), ' ', attribute_escape(strip_tags(html_entity_decode($item['description'], ENT_QUOTES))));
1131                         elseif ( isset( $item['summary'] ) && is_string( $item['summary'] ) )
1132                                 $desc = $summary = str_replace(array("\n", "\r"), ' ', attribute_escape(strip_tags(html_entity_decode($item['summary'], ENT_QUOTES))));
1133
1134                         if ( $show_summary ) {
1135                                 $desc = '';
1136                                 $summary = wp_specialchars( $summary );
1137                                 $summary = "<div class='rssSummary'>$summary</div>";
1138                         } else {
1139                                 $summary = '';
1140                         }
1141
1142                         $date = '';
1143                         if ( $show_date ) {
1144                                 if ( isset($item['pubdate']) )
1145                                         $date = $item['pubdate'];
1146                                 elseif ( isset($item['published']) )
1147                                         $date = $item['published'];
1148
1149                                 if ( $date ) {
1150                                         if ( $date_stamp = strtotime( $date ) )
1151                                                 $date = ' <span class="rss-date">' . date_i18n( get_option( 'date_format' ), $date_stamp ) . '</span>';
1152                                         else
1153                                                 $date = '';
1154                                 }
1155                         }
1156
1157                         $author = '';
1158                         if ( $show_author ) {
1159                                 if ( isset($item['dc']['creator']) )
1160                                         $author = ' <cite>' . wp_specialchars( strip_tags( $item['dc']['creator'] ) ) . '</cite>';
1161                                 elseif ( isset($item['author_name']) )
1162                                         $author = ' <cite>' . wp_specialchars( strip_tags( $item['author_name'] ) ) . '</cite>';
1163                         }
1164
1165                         if ( $link == '' ) {
1166                                 echo "<li>$title{$date}{$summary}{$author}</li>"; 
1167                         } else {
1168                                 echo "<li><a class='rsswidget' href='$link' title='$desc'>$title</a>{$date}{$summary}{$author}</li>"; 
1169                         }
1170 }
1171                 echo '</ul>';
1172         } else {
1173                 echo '<ul><li>' . __( 'An error has occurred; the feed is probably down. Try again later.' ) . '</li></ul>';
1174         }
1175 }
1176
1177 function wp_widget_rss_control($widget_args) {
1178         global $wp_registered_widgets;
1179         static $updated = false;
1180
1181         if ( is_numeric($widget_args) )
1182                 $widget_args = array( 'number' => $widget_args );
1183         $widget_args = wp_parse_args( $widget_args, array( 'number' => -1 ) );
1184         extract($widget_args, EXTR_SKIP);
1185
1186         $options = get_option('widget_rss');
1187         if ( !is_array($options) )
1188                 $options = array();
1189
1190         $urls = array();
1191         foreach ( $options as $option )
1192                 if ( isset($option['url']) )
1193                         $urls[$option['url']] = true;
1194
1195         if ( !$updated && 'POST' == $_SERVER['REQUEST_METHOD'] && !empty($_POST['sidebar']) ) {
1196                 $sidebar = (string) $_POST['sidebar'];
1197
1198                 $sidebars_widgets = wp_get_sidebars_widgets();
1199                 if ( isset($sidebars_widgets[$sidebar]) )
1200                         $this_sidebar =& $sidebars_widgets[$sidebar];
1201                 else
1202                         $this_sidebar = array();
1203
1204                 foreach ( $this_sidebar as $_widget_id ) {
1205                         if ( 'wp_widget_rss' == $wp_registered_widgets[$_widget_id]['callback'] && isset($wp_registered_widgets[$_widget_id]['params'][0]['number']) ) {
1206                                 $widget_number = $wp_registered_widgets[$_widget_id]['params'][0]['number'];
1207                                 if ( !in_array( "rss-$widget_number", $_POST['widget-id'] ) ) // the widget has been removed.
1208                                         unset($options[$widget_number]);
1209                         }
1210                 }
1211
1212                 foreach( (array) $_POST['widget-rss'] as $widget_number => $widget_rss ) {
1213                         if ( !isset($widget_rss['url']) && isset($options[$widget_number]) ) // user clicked cancel
1214                                 continue;
1215                         $widget_rss = stripslashes_deep( $widget_rss );
1216                         $url = sanitize_url(strip_tags($widget_rss['url']));
1217                         $options[$widget_number] = wp_widget_rss_process( $widget_rss, !isset($urls[$url]) );
1218                 }
1219
1220                 update_option('widget_rss', $options);
1221                 $updated = true;
1222         }
1223
1224         if ( -1 == $number ) {
1225                 $title = '';
1226                 $url = '';
1227                 $items = 10;
1228                 $error = false;
1229                 $number = '%i%';
1230                 $show_summary = 0;
1231                 $show_author = 0;
1232                 $show_date = 0;
1233         } else {
1234                 extract( (array) $options[$number] );
1235         }
1236
1237         wp_widget_rss_form( compact( 'number', 'title', 'url', 'items', 'error', 'show_summary', 'show_author', 'show_date' ) );
1238 }
1239
1240 function wp_widget_rss_form( $args, $inputs = null ) {
1241         $default_inputs = array( 'url' => true, 'title' => true, 'items' => true, 'show_summary' => true, 'show_author' => true, 'show_date' => true );
1242         $inputs = wp_parse_args( $inputs, $default_inputs );
1243         extract( $args );
1244         $number = attribute_escape( $number );
1245         $title  = attribute_escape( $title );
1246         $url    = attribute_escape( $url );
1247         $items  = (int) $items;
1248         if ( $items < 1 || 20 < $items )
1249                 $items  = 10;
1250         $show_summary   = (int) $show_summary;
1251         $show_author    = (int) $show_author;
1252         $show_date      = (int) $show_date;
1253
1254         if ( $inputs['url'] ) :
1255 ?>
1256         <p>
1257                 <label for="rss-url-<?php echo $number; ?>"><?php _e('Enter the RSS feed URL here:'); ?>
1258                         <input class="widefat" id="rss-url-<?php echo $number; ?>" name="widget-rss[<?php echo $number; ?>][url]" type="text" value="<?php echo $url; ?>" />
1259                 </label>
1260         </p>
1261 <?php endif; if ( $inputs['title'] ) : ?>
1262         <p>
1263                 <label for="rss-title-<?php echo $number; ?>"><?php _e('Give the feed a title (optional):'); ?>
1264                         <input class="widefat" id="rss-title-<?php echo $number; ?>" name="widget-rss[<?php echo $number; ?>][title]" type="text" value="<?php echo $title; ?>" />
1265                 </label>
1266         </p>
1267 <?php endif; if ( $inputs['items'] ) : ?>
1268         <p>
1269                 <label for="rss-items-<?php echo $number; ?>"><?php _e('How many items would you like to display?'); ?>
1270                         <select id="rss-items-<?php echo $number; ?>" name="widget-rss[<?php echo $number; ?>][items]">
1271                                 <?php
1272                                         for ( $i = 1; $i <= 20; ++$i )
1273                                                 echo "<option value='$i' " . ( $items == $i ? "selected='selected'" : '' ) . ">$i</option>";
1274                                 ?>
1275                         </select>
1276                 </label>
1277         </p>
1278 <?php endif; if ( $inputs['show_summary'] ) : ?>
1279         <p>
1280                 <label for="rss-show-summary-<?php echo $number; ?>">
1281                         <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"'; ?>/>
1282                         <?php _e('Display item content?'); ?>
1283                 </label>
1284         </p>
1285 <?php endif; if ( $inputs['show_author'] ) : ?>
1286         <p>
1287                 <label for="rss-show-author-<?php echo $number; ?>">
1288                         <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"'; ?>/>
1289                         <?php _e('Display item author if available?'); ?>
1290                 </label>
1291         </p>
1292 <?php endif; if ( $inputs['show_date'] ) : ?>
1293         <p>
1294                 <label for="rss-show-date-<?php echo $number; ?>">
1295                         <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"'; ?>/>
1296                         <?php _e('Display item date?'); ?>
1297                 </label>
1298         </p>
1299         <input type="hidden" name="widget-rss[<?php echo $number; ?>][submit]" value="1" />
1300 <?php
1301         endif;
1302         foreach ( array_keys($default_inputs) as $input ) :
1303                 if ( 'hidden' === $inputs[$input] ) :
1304                         $id = str_replace( '_', '-', $input );
1305 ?>
1306         <input type="hidden" id="rss-<?php echo $id; ?>-<?php echo $number; ?>" name="widget-rss[<?php echo $number; ?>][<?php echo $input; ?>]" value="<?php echo $$input; ?>" />
1307 <?php
1308                 endif;
1309         endforeach;
1310 }
1311
1312 // Expects unescaped data
1313 function wp_widget_rss_process( $widget_rss, $check_feed = true ) {
1314         $items = (int) $widget_rss['items'];
1315         if ( $items < 1 || 20 < $items )
1316                 $items = 10;
1317         $url           = sanitize_url(strip_tags( $widget_rss['url'] ));
1318         $title         = trim(strip_tags( $widget_rss['title'] ));
1319         $show_summary  = (int) $widget_rss['show_summary'];
1320         $show_author   = (int) $widget_rss['show_author'];
1321         $show_date     = (int) $widget_rss['show_date'];
1322
1323         if ( $check_feed ) {
1324                 require_once(ABSPATH . WPINC . '/rss.php');
1325                 $rss = fetch_rss($url);
1326                 $error = false;
1327                 $link = '';
1328                 if ( !is_object($rss) ) {
1329                         $url = wp_specialchars(__('Error: could not find an RSS or ATOM feed at that URL.'), 1);
1330                         $error = sprintf(__('Error in RSS %1$d'), $widget_number );
1331                 } else {
1332                         $link = clean_url(strip_tags($rss->channel['link']));
1333                         while ( strstr($link, 'http') != $link )
1334                                 $link = substr($link, 1);
1335                 }
1336         }
1337
1338         return compact( 'title', 'url', 'link', 'items', 'error', 'show_summary', 'show_author', 'show_date' );
1339 }
1340
1341 function wp_widget_rss_register() {
1342         if ( !$options = get_option('widget_rss') )
1343                 $options = array();
1344         $widget_ops = array('classname' => 'widget_rss', 'description' => __( 'Entries from any RSS or Atom feed' ));
1345         $control_ops = array('width' => 400, 'height' => 200, 'id_base' => 'rss');
1346         $name = __('RSS');
1347
1348         $id = false;
1349         foreach ( array_keys($options) as $o ) {
1350                 // Old widgets can have null values for some reason
1351                 if ( !isset($options[$o]['url']) || !isset($options[$o]['title']) || !isset($options[$o]['items']) )
1352                         continue;
1353                 $id = "rss-$o"; // Never never never translate an id
1354                 wp_register_sidebar_widget($id, $name, 'wp_widget_rss', $widget_ops, array( 'number' => $o ));
1355                 wp_register_widget_control($id, $name, 'wp_widget_rss_control', $control_ops, array( 'number' => $o ));
1356         }
1357
1358         // If there are none, we register the widget's existance with a generic template
1359         if ( !$id ) {
1360                 wp_register_sidebar_widget( 'rss-1', $name, 'wp_widget_rss', $widget_ops, array( 'number' => -1 ) );
1361                 wp_register_widget_control( 'rss-1', $name, 'wp_widget_rss_control', $control_ops, array( 'number' => -1 ) );
1362         }
1363 }
1364
1365 function wp_widget_tag_cloud($args) {
1366         extract($args);
1367         $options = get_option('widget_tag_cloud');
1368         $title = empty($options['title']) ? __('Tags') : apply_filters('widget_title', $options['title']);
1369
1370         echo $before_widget;
1371         echo $before_title . $title . $after_title;
1372         wp_tag_cloud();
1373         echo $after_widget;
1374 }
1375
1376 function wp_widget_tag_cloud_control() {
1377         $options = $newoptions = get_option('widget_tag_cloud');
1378
1379         if ( $_POST['tag-cloud-submit'] ) {
1380                 $newoptions['title'] = strip_tags(stripslashes($_POST['tag-cloud-title']));
1381         }
1382
1383         if ( $options != $newoptions ) {
1384                 $options = $newoptions;
1385                 update_option('widget_tag_cloud', $options);
1386         }
1387
1388         $title = attribute_escape( $options['title'] );
1389 ?>
1390         <p><label for="tag-cloud-title">
1391         <?php _e('Title:') ?> <input type="text" class="widefat" id="tag-cloud-title" name="tag-cloud-title" value="<?php echo $title ?>" /></label>
1392         </p>
1393         <input type="hidden" name="tag-cloud-submit" id="tag-cloud-submit" value="1" />
1394 <?php
1395 }
1396
1397 function wp_widgets_init() {
1398         if ( !is_blog_installed() )
1399                 return;
1400
1401         $widget_ops = array('classname' => 'widget_pages', 'description' => __( "Your blog's WordPress Pages") );
1402         wp_register_sidebar_widget('pages', __('Pages'), 'wp_widget_pages', $widget_ops);
1403         wp_register_widget_control('pages', __('Pages'), 'wp_widget_pages_control' );
1404
1405         $widget_ops = array('classname' => 'widget_calendar', 'description' => __( "A calendar of your blog's posts") );
1406         wp_register_sidebar_widget('calendar', __('Calendar'), 'wp_widget_calendar', $widget_ops);
1407         wp_register_widget_control('calendar', __('Calendar'), 'wp_widget_calendar_control' );
1408
1409         $widget_ops = array('classname' => 'widget_archive', 'description' => __( "A monthly archive of your blog's posts") );
1410         wp_register_sidebar_widget('archives', __('Archives'), 'wp_widget_archives', $widget_ops);
1411         wp_register_widget_control('archives', __('Archives'), 'wp_widget_archives_control' );
1412
1413         $widget_ops = array('classname' => 'widget_links', 'description' => __( "Your blogroll") );
1414         wp_register_sidebar_widget('links', __('Links'), 'wp_widget_links', $widget_ops);
1415
1416         $widget_ops = array('classname' => 'widget_meta', 'description' => __( "Log in/out, admin, feed and WordPress links") );
1417         wp_register_sidebar_widget('meta', __('Meta'), 'wp_widget_meta', $widget_ops);
1418         wp_register_widget_control('meta', __('Meta'), 'wp_widget_meta_control' );
1419
1420         $widget_ops = array('classname' => 'widget_search', 'description' => __( "A search form for your blog") );
1421         wp_register_sidebar_widget('search', __('Search'), 'wp_widget_search', $widget_ops);
1422
1423         $widget_ops = array('classname' => 'widget_recent_entries', 'description' => __( "The most recent posts on your blog") );
1424         wp_register_sidebar_widget('recent-posts', __('Recent Posts'), 'wp_widget_recent_entries', $widget_ops);
1425         wp_register_widget_control('recent-posts', __('Recent Posts'), 'wp_widget_recent_entries_control' );
1426
1427         $widget_ops = array('classname' => 'widget_tag_cloud', 'description' => __( "Your most used tags in cloud format") );
1428         wp_register_sidebar_widget('tag_cloud', __('Tag Cloud'), 'wp_widget_tag_cloud', $widget_ops);
1429         wp_register_widget_control('tag_cloud', __('Tag Cloud'), 'wp_widget_tag_cloud_control' );
1430
1431         wp_widget_categories_register();
1432         wp_widget_text_register();
1433         wp_widget_rss_register();
1434         wp_widget_recent_comments_register();
1435
1436         do_action('widgets_init');
1437 }
1438
1439 add_action('init', 'wp_widgets_init', 1);
1440
1441 /* Pattern for multi-widget (allows multiple instances such as the text widget).
1442
1443 // Displays widget on blag
1444 // $widget_args: number
1445 //    number: which of the several widgets of this type do we mean
1446 function widget_many( $args, $widget_args = 1 ) {
1447         extract( $args, EXTR_SKIP );
1448         if ( is_numeric($widget_args) )
1449                 $widget_args = array( 'number' => $widget_args );
1450         $widget_args = wp_parse_args( $widget_args, array( 'number' => -1 ) );
1451         extract( $widget_args, EXTR_SKIP );
1452
1453         // Data should be stored as array:  array( number => data for that instance of the widget, ... )
1454         $options = get_option('widget_many');
1455         if ( !isset($options[$number]) )
1456                 return;
1457
1458         echo $before_widget;
1459
1460         // Do stuff for this widget, drawing data from $options[$number]
1461
1462         echo $after_widget;
1463 }
1464
1465 // Displays form for a particular instance of the widget.  Also updates the data after a POST submit
1466 // $widget_args: number
1467 //    number: which of the several widgets of this type do we mean
1468 function widget_many_control( $widget_args = 1 ) {
1469         global $wp_registered_widgets;
1470         static $updated = false; // Whether or not we have already updated the data after a POST submit
1471
1472         if ( is_numeric($widget_args) )
1473                 $widget_args = array( 'number' => $widget_args );
1474         $widget_args = wp_parse_args( $widget_args, array( 'number' => -1 ) );
1475         extract( $widget_args, EXTR_SKIP );
1476
1477         // Data should be stored as array:  array( number => data for that instance of the widget, ... )
1478         $options = get_option('widget_many');
1479         if ( !is_array($options) )
1480                 $options = array();
1481
1482         // We need to update the data
1483         if ( !$updated && !empty($_POST['sidebar']) ) {
1484                 // Tells us what sidebar to put the data in
1485                 $sidebar = (string) $_POST['sidebar'];
1486
1487                 $sidebars_widgets = wp_get_sidebars_widgets();
1488                 if ( isset($sidebars_widgets[$sidebar]) )
1489                         $this_sidebar =& $sidebars_widgets[$sidebar];
1490                 else
1491                         $this_sidebar = array();
1492
1493                 foreach ( $this_sidebar as $_widget_id ) {
1494                         // 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
1495                         // since widget ids aren't necessarily persistent across multiple updates
1496                         if ( 'widget_many' == $wp_registered_widgets[$_widget_id]['callback'] && isset($wp_registered_widgets[$_widget_id]['params'][0]['number']) ) {
1497                                 $widget_number = $wp_registered_widgets[$_widget_id]['params'][0]['number'];
1498                                 if ( !in_array( "many-$widget_number", $_POST['widget-id'] ) ) // the widget has been removed. "many-$widget_number" is "{id_base}-{widget_number}
1499                                         unset($options[$widget_number]);
1500                         }
1501                 }
1502
1503                 foreach ( (array) $_POST['widget-many'] as $widget_number => $widget_many_instance ) {
1504                         // compile data from $widget_many_instance
1505                         if ( !isset($widget_many_instance['something']) && isset($options[$widget_number]) ) // user clicked cancel
1506                                 continue;
1507                         $something = wp_specialchars( $widget_many_instance['something'] );
1508                         $options[$widget_number] = array( 'something' => $something );  // Even simple widgets should store stuff in array, rather than in scalar
1509                 }
1510
1511                 update_option('widget_many', $options);
1512
1513                 $updated = true; // So that we don't go through this more than once
1514         }
1515
1516
1517         // Here we echo out the form
1518         if ( -1 == $number ) { // We echo out a template for a form which can be converted to a specific form later via JS
1519                 $something = '';
1520                 $number = '%i%';
1521         } else {
1522                 $something = attribute_escape($options[$number]['something']);
1523         }
1524
1525         // The form has inputs with names like widget-many[$number][something] so that all data for that instance of
1526         // the widget are stored in one $_POST variable: $_POST['widget-many'][$number]
1527 ?>
1528                 <p>
1529                         <input class="widefat" id="widget-many-something-<?php echo $number; ?>" name="widget-many[<?php echo $number; ?>][something]" type="text" value="<?php echo $data; ?>" />
1530                         <input type="hidden" id="widget-many-submit-<?php echo $number; ?>" name="widget-many[<?php echo $number; ?>][submit]" value="1" />
1531                 </p>
1532 <?php
1533 }
1534
1535 // Registers each instance of our widget on startup
1536 function widget_many_register() {
1537         if ( !$options = get_option('widget_many') )
1538                 $options = array();
1539
1540         $widget_ops = array('classname' => 'widget_many', 'description' => __('Widget which allows multiple instances'));
1541         $control_ops = array('width' => 400, 'height' => 350, 'id_base' => 'many');
1542         $name = __('Many');
1543
1544         $registered = false;
1545         foreach ( array_keys($options) as $o ) {
1546                 // Old widgets can have null values for some reason
1547                 if ( !isset($options[$o]['something']) ) // we used 'something' above in our exampple.  Replace with with whatever your real data are.
1548                         continue;
1549
1550                 // $id should look like {$id_base}-{$o}
1551                 $id = "many-$o"; // Never never never translate an id
1552                 $registered = true;
1553                 wp_register_sidebar_widget( $id, $name, 'widget_many', $widget_ops, array( 'number' => $o ) );
1554                 wp_register_widget_control( $id, $name, 'widget_many_control', $control_ops, array( 'number' => $o ) );
1555         }
1556
1557         // If there are none, we register the widget's existance with a generic template
1558         if ( !$registered ) {
1559                 wp_register_sidebar_widget( 'many-1', $name, 'widget_many', $widget_ops, array( 'number' => -1 ) );
1560                 wp_register_widget_control( 'many-1', $name, 'widget_many_control', $control_ops, array( 'number' => -1 ) );
1561         }
1562 }
1563
1564 // This is important
1565 add_action( 'widgets_init', 'widget_many_register' )
1566
1567 */
1568
1569 ?>