Wordpress 2.5.1
[autoinstalls/wordpress.git] / wp-admin / includes / dashboard.php
1 <?php
2
3 // Registers dashboard widgets, handles POST data, sets up filters
4 function wp_dashboard_setup() {
5         global $wpdb, $wp_dashboard_sidebars;
6         $update = false;
7         $widget_options = get_option( 'dashboard_widget_options' );
8         if ( !$widget_options || !is_array($widget_options) )
9                 $widget_options = array();
10
11
12         /* Register WP Dashboard Dynamic Sidebar */
13         register_sidebar( array(
14                 'name' => 'WordPress Dashboard',
15                 'id' => 'wp_dashboard',
16                 'before_widget' => "\t<div class='dashboard-widget-holder %2\$s' id='%1\$s'>\n\n\t\t<div class='dashboard-widget'>\n\n",
17                 'after_widget' => "\t\t</div>\n\n\t</div>\n\n",
18                 'before_title' => "\t\t\t<h3 class='dashboard-widget-title'>",
19                 'after_title' => "</h3>\n\n"
20         ) );
21
22
23         /* Register Widgets and Controls */
24
25         // Recent Comments Widget
26         if ( current_user_can( 'moderate_comments' ) && $mod_comments = $wpdb->get_var("SELECT COUNT(*) FROM $wpdb->comments WHERE comment_approved = '0'") ) {
27                 $notice = sprintf( __ngettext( '%d comment awaiting moderation', '%d comments awaiting moderation', $mod_comments ), $mod_comments );
28                 $notice = "<a href='edit-comments.php?comment_status=moderated'>$notice</a>";
29         } else {
30                 $notice = '';
31         }
32         wp_register_sidebar_widget( 'dashboard_recent_comments', __( 'Recent Comments' ), 'wp_dashboard_recent_comments',
33                 array( 'all_link' => 'edit-comments.php', 'notice' => $notice, 'width' => 'half' )
34         );
35
36         // Incoming Links Widget
37         if ( !isset( $widget_options['dashboard_incoming_links'] ) ) {
38                 $update = true;
39                 $widget_options['dashboard_incoming_links'] = array(
40                         'link' => apply_filters( 'dashboard_incoming_links_link', 'http://blogsearch.google.com/blogsearch?hl=en&scoring=d&partner=wordpress&q=link:' . trailingslashit( get_option('home') ) ),
41                         'url' => apply_filters( 'dashboard_incoming_links_feed', 'http://blogsearch.google.com/blogsearch_feeds?hl=en&scoring=d&ie=utf-8&num=10&output=rss&partner=wordpress&q=link:' . trailingslashit( get_option('home') ) ),
42                         'items' => 5,
43                         'show_date' => 0
44                 );
45         }
46         wp_register_sidebar_widget( 'dashboard_incoming_links', __( 'Incoming Links' ), 'wp_dashboard_empty',
47                 array( 'all_link' => $widget_options['dashboard_incoming_links']['link'], 'feed_link' => $widget_options['dashboard_incoming_links']['url'], 'width' => 'half' ),
48                 'wp_dashboard_cached_rss_widget', 'wp_dashboard_incoming_links_output'
49         );
50         wp_register_widget_control( 'dashboard_incoming_links', __( 'Incoming Links' ), 'wp_dashboard_rss_control', array(),
51                 array( 'widget_id' => 'dashboard_incoming_links', 'form_inputs' => array( 'title' => false, 'show_summary' => false, 'show_author' => false ) )
52         );
53
54
55         // WP Plugins Widget
56         wp_register_sidebar_widget( 'dashboard_plugins', __( 'Plugins' ), 'wp_dashboard_empty',
57                 array( 'all_link' => 'http://wordpress.org/extend/plugins/', 'feed_link' => 'http://wordpress.org/extend/plugins/rss/topics/', 'width' => 'half' ),
58                 'wp_dashboard_cached_rss_widget', 'wp_dashboard_plugins_output',
59                 array( 'http://wordpress.org/extend/plugins/rss/browse/popular/', 'http://wordpress.org/extend/plugins/rss/browse/new/', 'http://wordpress.org/extend/plugins/rss/browse/updated/' )
60         );
61
62         // Primary feed (Dev Blog) Widget
63         if ( !isset( $widget_options['dashboard_primary'] ) ) {
64                 $update = true;
65                 $widget_options['dashboard_primary'] = array(
66                         'link' => apply_filters( 'dashboard_primary_link',  __( 'http://wordpress.org/development/' ) ),
67                         'url' => apply_filters( 'dashboard_primary_feed',  __( 'http://wordpress.org/development/feed/' ) ),
68                         'title' => apply_filters( 'dashboard_primary_title', __( 'WordPress Development Blog' ) ),
69                         'items' => 2,
70                         'show_summary' => 1,
71                         'show_author' => 0,
72                         'show_date' => 1
73                 );
74         }
75         wp_register_sidebar_widget( 'dashboard_primary', $widget_options['dashboard_primary']['title'], 'wp_dashboard_empty',
76                 array( 'all_link' => $widget_options['dashboard_primary']['link'], 'feed_link' => $widget_options['dashboard_primary']['url'], 'width' => 'half', 'class' => 'widget_rss' ),
77                 'wp_dashboard_cached_rss_widget', 'wp_dashboard_rss_output'
78         );
79         wp_register_widget_control( 'dashboard_primary', __( 'Primary Feed' ), 'wp_dashboard_rss_control', array(),
80                 array( 'widget_id' => 'dashboard_primary' )
81         );
82
83
84         // Secondary Feed (Planet) Widget
85         if ( !isset( $widget_options['dashboard_secondary'] ) ) {
86                 $update = true;
87                 $widget_options['dashboard_secondary'] = array(
88                         'link' => apply_filters( 'dashboard_secondary_link',  __( 'http://planet.wordpress.org/' ) ),
89                         'url' => apply_filters( 'dashboard_secondary_feed',  __( 'http://planet.wordpress.org/feed/' ) ),
90                         'title' => apply_filters( 'dashboard_secondary_title', __( 'Other WordPress News' ) ),
91                         'items' => 15
92                 );
93         }
94         wp_register_sidebar_widget( 'dashboard_secondary', $widget_options['dashboard_secondary']['title'], 'wp_dashboard_empty',
95                 array( 'all_link' => $widget_options['dashboard_secondary']['link'], 'feed_link' => $widget_options['dashboard_secondary']['url'], 'width' => 'full' ),
96                 'wp_dashboard_cached_rss_widget', 'wp_dashboard_secondary_output'
97         );
98         wp_register_widget_control( 'dashboard_secondary', __( 'Secondary Feed' ), 'wp_dashboard_rss_control', array(),
99                 array( 'widget_id' => 'dashboard_secondary', 'form_inputs' => array( 'show_summary' => false, 'show_author' => false, 'show_date' => false ) )
100         );
101
102
103                 /* Dashboard Widget Template
104                 wp_register_sidebar_widget( $widget_id (unique slug) , $widget_title, $output_callback,
105                         array(
106                                 'all_link'  => full url for "See All" link,
107                                 'feed_link' => full url for "RSS" link,
108                                 'width'     => 'fourth', 'third', 'half', 'full' (defaults to 'half'),
109                                 'height'    => 'single', 'double' (defaults to 'single'),
110                         ),
111                         $wp_dashboard_empty_callback (only needed if using 'wp_dashboard_empty' as your $output_callback),
112                         $arg, $arg, $arg... (further args passed to callbacks)
113                 );
114
115                 // optional: if you want users to be able to edit the settings of your widget, you need to register a widget_control
116                 wp_register_widget_control( $widget_id, $widget_control_title, $control_output_callback,
117                         array(), // leave an empty array here: oddity in widget code
118                         array(
119                                 'widget_id' => $widget_id, // Yes - again.  This is required: oddity in widget code
120                                 'arg'       => an arg to pass to the $control_output_callback,
121                                 'another'   => another arg to pass to the $control_output_callback,
122                                 ...
123                         )
124                 );
125                 */
126
127         // Hook to register new widgets
128         do_action( 'wp_dashboard_setup' );
129
130         // Hard code the sidebar's widgets and order
131         $dashboard_widgets = array();
132         $dashboard_widgets[] = 'dashboard_recent_comments';
133         $dashboard_widgets[] = 'dashboard_incoming_links';
134         $dashboard_widgets[] = 'dashboard_primary';
135         if ( current_user_can( 'activate_plugins' ) )
136                 $dashboard_widgets[] = 'dashboard_plugins';
137         $dashboard_widgets[] = 'dashboard_secondary';
138
139         // Filter widget order
140         $dashboard_widgets = apply_filters( 'wp_dashboard_widgets', $dashboard_widgets );
141
142         $wp_dashboard_sidebars = array( 'wp_dashboard' => $dashboard_widgets, 'array_version' => 3.5 );
143
144         add_filter( 'dynamic_sidebar_params', 'wp_dashboard_dynamic_sidebar_params' );
145
146         if ( 'POST' == $_SERVER['REQUEST_METHOD'] && isset($_POST['widget_id']) ) {
147                 ob_start(); // hack - but the same hack wp-admin/widgets.php uses
148                 wp_dashboard_trigger_widget_control( $_POST['widget_id'] );
149                 ob_end_clean();
150                 wp_redirect( remove_query_arg( 'edit' ) );
151                 exit;
152         }
153
154         if ( $update )
155                 update_option( 'dashboard_widget_options', $widget_options );
156 }
157
158 // Echoes out the dashboard
159 function wp_dashboard() {
160         echo "<div id='dashboard-widgets'>\n\n";
161
162         // We're already filtering dynamic_sidebar_params obove
163         add_filter( 'option_sidebars_widgets', 'wp_dashboard_sidebars_widgets' ); // here there be hackery
164         dynamic_sidebar( 'wp_dashboard' );
165         remove_filter( 'option_sidebars_widgets', 'wp_dashboard_sidebars_widgets' );
166
167         echo "<br class='clear' />\n</div>\n\n\n";
168 }
169
170 // Makes sidebar_widgets option reflect the dashboard settings
171 function wp_dashboard_sidebars_widgets() { // hackery
172         return $GLOBALS['wp_dashboard_sidebars'];
173 }
174
175 // Modifies sidbar params on the fly to set up ids, class names, titles for each widget (called once per widget)
176 // Switches widget to edit mode if $_GET['edit']
177 function wp_dashboard_dynamic_sidebar_params( $params ) {
178         global $wp_registered_widgets, $wp_registered_widget_controls;
179
180         $sidebar_defaults = array('widget_id' => 0, 'before_widget' => '', 'after_widget' => '', 'before_title' => '', 'after_title' => '');
181         extract( $sidebar_defaults, EXTR_PREFIX_ALL, 'sidebar' );
182         extract( $params[0], EXTR_PREFIX_ALL, 'sidebar' );
183
184         if ( !isset($wp_registered_widgets[$sidebar_widget_id]) || !is_array($wp_registered_widgets[$sidebar_widget_id]) ) {
185                 return $params;
186         }
187         $widget_defaults = array('id' => '', 'width' => '', 'height' => '', 'class' => '', 'feed_link' => '', 'all_link' => '', 'notice' => false, 'error' => false);
188         extract( $widget_defaults, EXTR_PREFIX_ALL, 'widget' );
189         extract( $wp_registered_widgets[$sidebar_widget_id], EXTR_PREFIX_ALL, 'widget' );
190
191         $the_classes = array();
192         if ( in_array($widget_width, array( 'third', 'fourth', 'full' ) ) )
193                 $the_classes[] = $widget_width;
194
195         if ( 'double' == $widget_height )
196                 $the_classes[] = 'double';
197
198         if ( $widget_class )
199                 $the_classes[] = $widget_class;
200
201         // Add classes to the widget holder
202         if ( $the_classes )
203                 $sidebar_before_widget = str_replace( "<div class='dashboard-widget-holder ", "<div class='dashboard-widget-holder " . join( ' ', $the_classes ) . ' ', $sidebar_before_widget );
204
205         $links = array();
206         if ( $widget_all_link )
207                 $links[] = '<a href="' . clean_url( $widget_all_link ) . '">' . __( 'See&nbsp;All' ) . '</a>';
208
209         $content_class = 'dashboard-widget-content';
210         if ( current_user_can( 'edit_dashboard' ) && isset($wp_registered_widget_controls[$widget_id]) && is_callable($wp_registered_widget_controls[$widget_id]['callback']) ) {
211                 // Switch this widget to edit mode
212                 if ( isset($_GET['edit']) && $_GET['edit'] == $widget_id ) {
213                         $content_class .= ' dashboard-widget-control';
214                         $wp_registered_widgets[$widget_id]['callback'] = 'wp_dashboard_empty';
215                         $sidebar_widget_name = $wp_registered_widget_controls[$widget_id]['name'];
216                         $params[1] = 'wp_dashboard_trigger_widget_control';
217                         $sidebar_before_widget .= '<form action="' . remove_query_arg( 'edit' )  . '" method="post">';
218                         $sidebar_after_widget   = "<div class='dashboard-widget-submit'><input type='hidden' name='sidebar' value='wp_dashboard' /><input type='hidden' name='widget_id' value='$widget_id' /><input type='submit' value='" . __( 'Save' ) . "' /></div></form>$sidebar_after_widget";
219                         $links[] = '<a href="' . remove_query_arg( 'edit' ) . '">' . __( 'Cancel' ) . '</a>';
220                 } else {
221                         $links[] = '<a href="' . add_query_arg( 'edit', $widget_id ) . "#$widget_id" . '">' . __( 'Edit' ) . '</a>';
222                 }
223         }
224
225         if ( $widget_feed_link )
226                 $links[] = '<img class="rss-icon" src="' . get_option( 'siteurl' ) . '/' . WPINC . '/images/rss.png" alt="' . __( 'rss icon' ) . '" /> <a href="' . clean_url( $widget_feed_link ) . '">' . __( 'RSS' ) . '</a>';
227
228         $links = apply_filters( "wp_dashboard_widget_links_$widget_id", $links );
229
230         // Add links to widget's title bar
231         if ( $links ) {
232                 $sidebar_before_title .= '<span>';
233                 $sidebar_after_title   = '</span><small>' . join( '&nbsp;|&nbsp;', $links ) . "</small><br class='clear' />$sidebar_after_title";
234         }
235
236         // Could have put this in widget-content.  Doesn't really matter
237         if ( $widget_notice )
238                 $sidebar_after_title .= "\t\t\t<div class='dashboard-widget-notice'>$widget_notice</div>\n\n";
239
240         if ( $widget_error )
241                 $sidebar_after_title .= "\t\t\t<div class='dashboard-widget-error'>$widget_error</div>\n\n";
242
243         $sidebar_after_title .= "\t\t\t<div class='$content_class'>\n\n";
244
245         $sidebar_after_widget .= "\t\t\t</div>\n\n";
246
247         foreach( array_keys( $params[0] ) as $key )
248                 $$key = ${'sidebar_' . $key};
249
250         $params[0] = compact( array_keys( $params[0] ) );
251
252         return $params;
253 }
254
255
256 /* Dashboard Widgets */
257
258 function wp_dashboard_recent_comments( $sidebar_args ) {
259         global $comment;
260         extract( $sidebar_args, EXTR_SKIP );
261
262         echo $before_widget;
263
264         echo $before_title;
265         echo $widget_name;
266         echo $after_title;
267
268         $lambda = create_function( '', 'return 5;' );
269         add_filter( 'option_posts_per_rss', $lambda ); // hack - comments query doesn't accept per_page parameter
270         $comments_query = new WP_Query('feed=rss2&withcomments=1');
271         remove_filter( 'option_posts_per_rss', $lambda );
272
273         $is_first = true;
274
275         if ( $comments_query->have_comments() ) {
276                 while ( $comments_query->have_comments() ) { $comments_query->the_comment();
277
278                         $comment_post_url = get_permalink( $comment->comment_post_ID );
279                         $comment_post_title = get_the_title( $comment->comment_post_ID );
280                         $comment_post_link = "<a href='$comment_post_url'>$comment_post_title</a>";
281                         $comment_link = '<a class="comment-link" href="' . get_comment_link() . '">#</a>';
282                         $comment_meta = sprintf( __( 'From <strong>%1$s</strong> on %2$s %3$s' ), get_comment_author(), $comment_post_link, $comment_link );
283
284                         if ( $is_first ) : $is_first = false;
285 ?>
286                                 <blockquote><p>&#8220;<?php comment_excerpt(); ?>&#8221;</p></blockquote>
287                                 <p class='comment-meta'><?php echo $comment_meta; ?></p>
288 <?php
289                                 if ( $comments_query->comment_count > 1 ) : ?>
290                                 <ul id="dashboard-comments-list">
291 <?php
292                                 endif; // comment_count
293                         else : // is_first
294 ?>
295
296                                         <li class='comment-meta'><?php echo $comment_meta; ?></li>
297 <?php
298                         endif; // is_first
299                 }
300
301                 if ( $comments_query->comment_count > 1 ) : ?>
302                                 </ul>
303 <?php
304                 endif; // comment_count;
305
306         }
307
308         echo $after_widget;
309 }
310
311 // $sidebar_args are handled by wp_dashboard_empty()
312 function wp_dashboard_incoming_links_output() {
313         $widgets = get_option( 'dashboard_widget_options' );
314         @extract( @$widgets['dashboard_incoming_links'], EXTR_SKIP );
315         $rss = @fetch_rss( $url );
316         if ( isset($rss->items) && 1 < count($rss->items) )  {// Technorati returns a 1-item feed when it has no results
317
318                 echo "<ul>\n";
319
320                 $rss->items = array_slice($rss->items, 0, $items);
321                 foreach ( $rss->items as $item ) {
322                         $publisher = '';
323                         $site_link = '';
324                         $link = '';
325                         $content = '';
326                         $date = '';
327                         $link = clean_url( strip_tags( $item['link'] ) );
328
329                         if ( isset( $item['author_uri'] ) )
330                                 $site_link = clean_url( strip_tags( $item['author_uri'] ) );
331
332                         if ( !$publisher = wp_specialchars( strip_tags( isset($item['dc']['publisher']) ? $item['dc']['publisher'] : $item['author_name'] ) ) )
333                                 $publisher = __( 'Somebody' );
334                         if ( $site_link )
335                                 $publisher = "<a href='$site_link'>$publisher</a>";
336                         else
337                                 $publisher = "<strong>$publisher</strong>";
338
339                         if ( isset($item['description']) )
340                                 $content = $item['description'];
341                         elseif ( isset($item['summary']) )
342                                 $content = $item['summary'];
343                         elseif ( isset($item['atom_content']) )
344                                 $content = $item['atom_content'];
345                         else
346                                 $content = __( 'something' );
347                         $content = wp_html_excerpt($content, 50) . ' ...';
348                         if ( $link )
349                                 $text = _c( '%1$s linked here <a href="%2$s">saying</a>, "%3$s"|feed_display' );
350                         else
351                                 $text = _c( '%1$s linked here saying, "%3$s"|feed_display' );
352
353                         if ( $show_date ) {
354                                 if ( $show_author || $show_summary )
355                                         $text .= _c( ' on %4$s|feed_display' );
356                                 $date = wp_specialchars( strip_tags( isset($item['pubdate']) ? $item['pubdate'] : $item['published'] ) );
357                                 $date = strtotime( $date );
358                                 $date = gmdate( get_option( 'date_format' ), $date );
359                         }
360
361                         echo "\t<li>" . sprintf( _c( "$text|feed_display" ), $publisher, $link, $content, $date ) . "</li>\n";
362                 }
363
364                 echo "</ul>\n";
365
366         } else {
367                 echo '<p>' . __('This dashboard widget queries <a href="http://blogsearch.google.com/">Google Blog Search</a> so that when another blog links to your site it will show up here. It has found no incoming links&hellip; yet. It&#8217;s okay &#8212; there is no rush.') . "</p>\n";
368         }
369 }
370
371 // $sidebar_args are handled by wp_dashboard_empty()
372 function wp_dashboard_rss_output( $widget_id ) {
373         $widgets = get_option( 'dashboard_widget_options' );
374         wp_widget_rss_output( $widgets[$widget_id] );
375 }
376
377 // $sidebar_args are handled by wp_dashboard_empty()
378 function wp_dashboard_secondary_output() {
379         $widgets = get_option( 'dashboard_widget_options' );
380         @extract( @$widgets['dashboard_secondary'], EXTR_SKIP );
381         $rss = @fetch_rss( $url );
382         if ( !isset($rss->items) || 0 == count($rss->items) )
383                 return false;
384
385         echo "<ul id='planetnews'>\n";
386
387         $rss->items = array_slice($rss->items, 0, $items);
388         foreach ($rss->items as $item ) {
389                 $title = wp_specialchars($item['title']);
390                 $author = preg_replace( '|(.+?):.+|s', '$1', $item['title'] );
391                 $post = preg_replace( '|.+?:(.+)|s', '$1', $item['title'] );
392                 $link = clean_url($item['link']);
393
394                 echo "\t<li><a href='$link'><span class='post'>$post</span><span class='hidden'> - </span><cite>$author</cite></a></li>\n";
395         }
396
397         echo "</ul>\n<br class='clear' />\n";
398 }
399
400 // $sidebar_args are handled by wp_dashboard_empty()
401 function wp_dashboard_plugins_output() {
402         $popular = @fetch_rss( 'http://wordpress.org/extend/plugins/rss/browse/popular/' );
403         $new     = @fetch_rss( 'http://wordpress.org/extend/plugins/rss/browse/new/' );
404         $updated = @fetch_rss( 'http://wordpress.org/extend/plugins/rss/browse/updated/' );
405
406         foreach ( array( 'popular' => __('Most Popular'), 'new' => __('Newest Plugins'), 'updated' => __('Recently Updated') ) as $feed => $label ) {
407                 if ( !isset($$feed->items) || 0 == count($$feed->items) )
408                         continue;
409
410                 $$feed->items = array_slice($$feed->items, 0, 5);
411                 $item_key = array_rand($$feed->items);
412
413                 // Eliminate some common badly formed plugin descriptions
414                 while ( ( null !== $item_key = array_rand($$feed->items) ) && false !== strpos( $$feed->items[$item_key]['description'], 'Plugin Name:' ) )
415                         unset($$feed->items[$item_key]);
416
417                 if ( !isset($$feed->items[$item_key]) )
418                         continue;
419
420                 $item = $$feed->items[$item_key];
421
422                 // current bbPress feed item titles are: user on "topic title"
423                 if ( preg_match( '/"(.*)"/s', $item['title'], $matches ) )
424                         $title = $matches[1];
425                 else // but let's make it forward compatible if things change
426                         $title = $item['title'];
427                 $title = wp_specialchars( $title );
428
429                 $description = wp_specialchars( strip_tags(html_entity_decode($item['description'], ENT_QUOTES)) );
430
431                 list($link, $frag) = explode( '#', $item['link'] );
432
433                 $link = clean_url($link);
434                 $dlink = rtrim($link, '/') . '/download/';
435
436                 echo "<h4>$label</h4>\n";
437                 echo "<h5><a href='$link'>$title</a></h5>&nbsp;<span>(<a href='$dlink'>" . __( 'Download' ) . "</a>)</span>\n";
438                 echo "<p>$description</p>\n";
439         }
440 }
441
442 // Checks to see if all of the feed url in $check_urls are cached.
443 // If $check_urls is empty, look for the rss feed url found in the dashboard widget optios of $widget_id.
444 // If cached, call $callback, a function that echoes out output for this widget.
445 // If not cache, echo a "Loading..." stub which is later replaced by AJAX call (see top of /wp-admin/index.php)
446 function wp_dashboard_cached_rss_widget( $widget_id, $callback, $check_urls = array() ) {
447         $loading = '<p class="widget-loading">' . __( 'Loading&#8230;' ) . '</p>';
448
449         if ( empty($check_urls) ) {
450                 $widgets = get_option( 'dashboard_widget_options' );
451                 if ( empty($widgets[$widget_id]['url']) ) {
452                         echo $loading;
453                         return false;
454                 }
455                 $check_urls = array( $widgets[$widget_id]['url'] );
456         }
457
458
459         require_once( ABSPATH . WPINC . '/rss.php' );
460         init(); // initialize rss constants
461
462         $cache = new RSSCache( MAGPIE_CACHE_DIR, MAGPIE_CACHE_AGE );
463
464         foreach ( $check_urls as $check_url ) {
465                 $status = $cache->check_cache( $check_url );
466                 if ( 'HIT' !== $status ) {
467                         echo $loading;
468                         return false;
469                 }
470         }
471
472         if ( $callback && is_callable( $callback ) ) {
473                 $args = array_slice( func_get_args(), 2 );
474                 array_unshift( $args, $widget_id );
475                 call_user_func_array( $callback, $args );
476         }
477
478         return true;
479 }
480
481 // Empty widget used for JS/AJAX created output.
482 // Callback inserts content between before_widget and after_widget.  Used when widget is in edit mode.  Can also be used for custom widgets.
483 function wp_dashboard_empty( $sidebar_args, $callback = false ) {
484         extract( $sidebar_args, EXTR_SKIP );
485
486         echo $before_widget;
487
488         echo $before_title;
489         echo $widget_name;
490         echo $after_title;
491
492         // When in edit mode, the callback passed to this function is the widget_control callback
493         if ( $callback && is_callable( $callback ) ) {
494                 $args = array_slice( func_get_args(), 2 );
495                 array_unshift( $args, $widget_id );
496                 call_user_func_array( $callback, $args );
497         }
498
499         echo $after_widget;
500 }
501
502 /* Dashboard Widgets Controls. Ssee also wp_dashboard_empty() */
503
504 // Calls widget_control callback
505 function wp_dashboard_trigger_widget_control( $widget_control_id = false ) {
506         global $wp_registered_widget_controls;
507         if ( is_scalar($widget_control_id) && $widget_control_id && isset($wp_registered_widget_controls[$widget_control_id]) && is_callable($wp_registered_widget_controls[$widget_control_id]['callback']) )
508                 call_user_func_array( $wp_registered_widget_controls[$widget_control_id]['callback'], $wp_registered_widget_controls[$widget_control_id]['params'] );
509 }
510
511 // Sets up $args to be used as input to wp_widget_rss_form(), handles POST data from RSS-type widgets
512 function wp_dashboard_rss_control( $args ) {
513         extract( $args );
514         if ( !$widget_id )
515                 return false;
516
517         if ( !$widget_options = get_option( 'dashboard_widget_options' ) )
518                 $widget_options = array();
519
520         if ( !isset($widget_options[$widget_id]) )
521                 $widget_options[$widget_id] = array();
522
523         $number = 1; // Hack to use wp_widget_rss_form()
524         $widget_options[$widget_id]['number'] = $number;
525
526         if ( 'POST' == $_SERVER['REQUEST_METHOD'] && isset($_POST['widget-rss'][$number]) ) {
527                 $_POST['widget-rss'][$number] = stripslashes_deep( $_POST['widget-rss'][$number] );
528                 $widget_options[$widget_id] = wp_widget_rss_process( $_POST['widget-rss'][$number] );
529                 // title is optional.  If black, fill it if possible
530                 if ( !$widget_options[$widget_id]['title'] && isset($_POST['widget-rss'][$number]['title']) ) {
531                         require_once(ABSPATH . WPINC . '/rss.php');
532                         $rss = fetch_rss($widget_options[$widget_id]['url']);
533                         $widget_options[$widget_id]['title'] = htmlentities(strip_tags($rss->channel['title']));
534                 }
535                 update_option( 'dashboard_widget_options', $widget_options );
536         }
537
538         wp_widget_rss_form( $widget_options[$widget_id], $form_inputs );
539 }
540
541 ?>