'WordPress Dashboard', 'id' => 'wp_dashboard', 'before_widget' => "\t
\n\n\t\t
\n\n", 'after_widget' => "\t\t
\n\n\t
\n\n", 'before_title' => "\t\t\t

", 'after_title' => "

\n\n" ) ); /* Register Widgets and Controls */ // Recent Comments Widget if ( $mod_comments = $wpdb->get_var("SELECT COUNT(*) FROM $wpdb->comments WHERE comment_approved = '0'") ) { $notice = sprintf( __ngettext( '%d comment awaiting moderation', '%d comments awaiting moderation', $mod_comments ), $mod_comments ); $notice = "$notice"; } else { $notice = ''; } wp_register_sidebar_widget( 'dashboard_recent_comments', __( 'Recent Comments' ), 'wp_dashboard_recent_comments', array( 'all_link' => 'edit-comments.php', 'notice' => $notice, 'width' => 'half' ) ); // Incoming Links Widget if ( !isset( $widget_options['dashboard_incoming_links'] ) ) { $update = true; $widget_options['dashboard_incoming_links'] = array( 'link' => apply_filters( 'dashboard_incoming_links_link', 'http://blogsearch.google.com/blogsearch?hl=en&scoring=d&partner=wordpress&q=link:' . trailingslashit( get_option('home') ) ), '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') ) ), 'items' => 5, 'show_date' => 0 ); } wp_register_sidebar_widget( 'dashboard_incoming_links', __( 'Incoming Links' ), 'wp_dashboard_empty', array( 'all_link' => $widget_options['dashboard_incoming_links']['link'], 'feed_link' => $widget_options['dashboard_incoming_links']['url'], 'width' => 'half' ), 'wp_dashboard_cached_rss_widget', 'wp_dashboard_incoming_links_output' ); wp_register_widget_control( 'dashboard_incoming_links', __( 'Incoming Links' ), 'wp_dashboard_rss_control', array(), array( 'widget_id' => 'dashboard_incoming_links', 'form_inputs' => array( 'title' => false, 'show_summary' => false, 'show_author' => false ) ) ); // WP Plugins Widget wp_register_sidebar_widget( 'dashboard_plugins', __( 'Plugins' ), 'wp_dashboard_empty', array( 'all_link' => 'http://wordpress.org/extend/plugins/', 'feed_link' => 'http://wordpress.org/extend/plugins/rss/', 'width' => 'half' ), 'wp_dashboard_cached_rss_widget', 'wp_dashboard_plugins_output', 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/' ) ); // Primary feed (Dev Blog) Widget if ( !isset( $widget_options['dashboard_primary'] ) ) { $update = true; $widget_options['dashboard_primary'] = array( 'link' => apply_filters( 'dashboard_primary_link', 'http://wordpress.org/development/' ), 'url' => apply_filters( 'dashboard_primary_feed', 'http://wordpress.org/development/feed/' ), 'title' => apply_filters( 'dashboard_primary_title', __( 'WordPress Development Blog' ) ), 'items' => 2, 'show_summary' => 1, 'show_author' => 0, 'show_date' => 1 ); } wp_register_sidebar_widget( 'dashboard_primary', $widget_options['dashboard_primary']['title'], 'wp_dashboard_empty', array( 'all_link' => $widget_options['dashboard_primary']['link'], 'feed_link' => $widget_options['dashboard_primary']['url'], 'width' => 'half', 'class' => 'widget_rss' ), 'wp_dashboard_cached_rss_widget', 'wp_dashboard_rss_output' ); wp_register_widget_control( 'dashboard_primary', __( 'Primary Feed' ), 'wp_dashboard_rss_control', array(), array( 'widget_id' => 'dashboard_primary' ) ); // Secondary Feed (Planet) Widget if ( !isset( $widget_options['dashboard_secondary'] ) ) { $update = true; $widget_options['dashboard_secondary'] = array( 'link' => apply_filters( 'dashboard_secondary_link', 'http://planet.wordpress.org/' ), 'url' => apply_filters( 'dashboard_secondary_feed', 'http://planet.wordpress.org/feed/' ), 'title' => apply_filters( 'dashboard_secondary_title', __( 'Other WordPress News' ) ), 'items' => 15 ); } wp_register_sidebar_widget( 'dashboard_secondary', $widget_options['dashboard_secondary']['title'], 'wp_dashboard_empty', array( 'all_link' => $widget_options['dashboard_secondary']['link'], 'feed_link' => $widget_options['dashboard_secondary']['url'], 'width' => 'full' ), 'wp_dashboard_cached_rss_widget', 'wp_dashboard_secondary_output' ); wp_register_widget_control( 'dashboard_secondary', __( 'Secondary Feed' ), 'wp_dashboard_rss_control', array(), array( 'widget_id' => 'dashboard_secondary', 'form_inputs' => array( 'show_summary' => false, 'show_author' => false, 'show_date' => false ) ) ); /* Dashboard Widget Template wp_register_sidebar_widget( $widget_id (unique slug) , $widget_title, $output_callback, array( 'all_link' => full url for "See All" link, 'feed_link' => full url for "RSS" link, 'width' => 'fourth', 'third', 'half', 'full' (defaults to 'half'), 'height' => 'single', 'double' (defaults to 'single'), ), $wp_dashboard_empty_callback (only needed if using 'wp_dashboard_empty' as your $output_callback), $arg, $arg, $arg... (further args passed to callbacks) ); // optional: if you want users to be able to edit the settings of your widget, you need to register a widget_control wp_register_widget_control( $widget_id, $widget_control_title, $control_output_callback, array(), // leave an empty array here: oddity in widget code array( 'widget_id' => $widget_id, // Yes - again. This is required: oddity in widget code 'arg' => an arg to pass to the $control_output_callback, 'another' => another arg to pass to the $control_output_callback, ... ) ); */ // Hook to register new widgets do_action( 'wp_dashboard_setup' ); // Hard code the sidebar's widgets and order $dashboard_widgets = array( 'dashboard_recent_comments', 'dashboard_incoming_links', 'dashboard_primary', 'dashboard_plugins', 'dashboard_secondary' ); // Filter widget order $dashboard_widgets = apply_filters( 'wp_dashboard_widgets', $dashboard_widgets ); $wp_dashboard_sidebars = array( 'wp_dashboard' => $dashboard_widgets, 'array_version' => 3.5 ); add_filter( 'dynamic_sidebar_params', 'wp_dashboard_dynamic_sidebar_params' ); if ( 'POST' == $_SERVER['REQUEST_METHOD'] && isset($_POST['widget_id']) ) { ob_start(); // hack - but the same hack wp-admin/widgets.php uses wp_dashbaord_trigger_widget_control( $_POST['widget_id'] ); ob_end_clean(); wp_redirect( remove_query_arg( 'edit' ) ); exit; } if ( $update ) update_option( 'dashboard_widget_options', $widget_options ); } // Echoes out the dashboard function wp_dashboard() { echo "
\n\n"; // We're already filtering dynamic_sidebar_params obove add_filter( 'option_sidebars_widgets', 'wp_dashboard_sidebars_widgets' ); // here there be hackery dynamic_sidebar( 'wp_dashboard' ); remove_filter( 'option_sidebars_widgets', 'wp_dashboard_sidebars_widgets' ); echo "
\n
\n\n\n"; } // Makes sidebar_widgets option reflect the dashboard settings function wp_dashboard_sidebars_widgets() { // hackery return $GLOBALS['wp_dashboard_sidebars']; } // Modifies sidbar params on the fly to set up ids, class names, titles for each widget (called once per widget) // Switches widget to edit mode if $_GET['edit'] function wp_dashboard_dynamic_sidebar_params( $params ) { global $wp_registered_widgets, $wp_registered_widget_controls; extract( $params[0], EXTR_PREFIX_ALL, 'sidebar' ); extract( $wp_registered_widgets[$sidebar_widget_id], EXTR_PREFIX_ALL, 'widget' ); $the_classes = array(); if ( in_array($widget_width, array( 'third', 'fourth', 'full' ) ) ) $the_classes[] = $widget_width; if ( 'double' == $widget_height ) $the_classes[] = 'double'; if ( $widget_class ) $the_classes[] = $widget_class; // Add classes to the widget holder if ( $the_classes ) $sidebar_before_widget = str_replace( "
' . __( 'See All' ) . ''; $content_class = 'dashboard-widget-content'; if ( current_user_can( 'edit_dashboard' ) && isset($wp_registered_widget_controls[$widget_id]) && is_callable($wp_registered_widget_controls[$widget_id]['callback']) ) { // Switch this widget to edit mode if ( isset($_GET['edit']) && $_GET['edit'] == $widget_id ) { $content_class .= ' dashboard-widget-control'; $wp_registered_widgets[$widget_id]['callback'] = 'wp_dashboard_empty'; $sidebar_widget_name = $wp_registered_widget_controls[$widget_id]['name']; $params[1] = 'wp_dashbaord_trigger_widget_control'; $sidebar_before_widget .= '
'; $sidebar_after_widget = "
$sidebar_after_widget"; $links[] = '' . __( 'Cancel' ) . ''; } else { $links[] = '' . __( 'Edit' ) . ''; } } if ( $widget_feed_link ) $links[] = '' . __( 'rss icon' ) . ' ' . __( 'RSS' ) . ''; $links = apply_filters( "wp_dashboard_widget_links_$widget_id", $links ); // Add links to widget's title bar if ( $links ) { $sidebar_before_title .= ''; $sidebar_after_title = '' . join( ' | ', $links ) . "
$sidebar_after_title"; } // Could have put this in widget-content. Doesn't really matter if ( $widget_notice ) $sidebar_after_title .= "\t\t\t
$widget_notice
\n\n"; if ( $widget_error ) $sidebar_after_title .= "\t\t\t
$widget_error
\n\n"; $sidebar_after_title .= "\t\t\t
\n\n"; $sidebar_after_widget .= "\t\t\t
\n\n"; foreach( array_keys( $params[0] ) as $key ) $$key = ${'sidebar_' . $key}; $params[0] = compact( array_keys( $params[0] ) ); return $params; } /* Dashboard Widgets */ function wp_dashboard_recent_comments( $sidebar_args ) { global $comment; extract( $sidebar_args, EXTR_SKIP ); echo $before_widget; echo $before_title; echo $widget_name; echo $after_title; $lambda = create_function( '', 'return 5;' ); add_filter( 'option_posts_per_rss', $lambda ); // hack - comments query doesn't accept per_page parameter $comments_query = new WP_Query('feed=rss2&withcomments=1'); remove_filter( 'option_posts_per_rss', $lambda ); $is_first = true; if ( $comments_query->have_comments() ) { while ( $comments_query->have_comments() ) { $comments_query->the_comment(); $comment_post_url = get_permalink( $comment->comment_post_ID ); $comment_post_title = get_the_title( $comment->comment_post_ID ); $comment_post_link = "$comment_post_title"; $comment_link = '#'; $comment_meta = sprintf( __( 'From %s on %s %s' ), get_comment_author(), $comment_post_link, $comment_link ); if ( $is_first ) : $is_first = false; ?>

items) && 1 < count($rss->items) ) {// Technorati returns a 1-item feed when it has no results echo "\n"; } else { echo '

' . __('No incoming links found... yet.') . "

\n"; } } // $sidebar_args are handled by wp_dashboard_empty() function wp_dashboard_rss_output( $widget_id ) { $widgets = get_option( 'dashboard_widget_options' ); wp_widget_rss_output( $widgets[$widget_id] ); } // $sidebar_args are handled by wp_dashboard_empty() function wp_dashboard_secondary_output() { $widgets = get_option( 'dashboard_widget_options' ); @extract( @$widgets['dashboard_secondary'], EXTR_SKIP ); $rss = @fetch_rss( $url ); if ( !isset($rss->items) || 0 == count($rss->items) ) return false; echo "\n
\n"; } // $sidebar_args are handled by wp_dashboard_empty() function wp_dashboard_plugins_output() { $popular = @fetch_rss( 'http://wordpress.org/extend/plugins/rss/browse/popular/' ); $new = @fetch_rss( 'http://wordpress.org/extend/plugins/rss/browse/new/' ); $updated = @fetch_rss( 'http://wordpress.org/extend/plugins/rss/browse/updated/' ); foreach ( array( 'popular' => __('Most Popular'), 'new' => __('Newest Plugins'), 'updated' => __('Recently Updated') ) as $feed => $label ) { if ( !isset($$feed->items) || 0 == count($$feed->items) ) continue; $$feed->items = array_slice($$feed->items, 0, 5); $item_key = array_rand($$feed->items); // Eliminate some common badly formed plugin descriptions while ( ( null !== $item_key = array_rand($$feed->items) ) && false !== strpos( $$feed->items[$item_key]['description'], 'Plugin Name:' ) ) unset($$feed->items[$item_key]); if ( !isset($$feed->items[$item_key]) ) continue; $item = $$feed->items[$item_key]; // current bbPress feed item titles are: user on "topic title" if ( preg_match( '/"(.*)"/s', $item['title'], $matches ) ) $title = $matches[1]; else // but let's make it forward compatible if things change $title = $item['title']; $title = wp_specialchars( $title ); $description = wp_specialchars( strip_tags(html_entity_decode($item['description'], ENT_QUOTES)) ); list($link, $frag) = explode( '#', $item['link'] ); $link = clean_url($link); $dlink = rtrim($link, '/') . '/download/'; echo "

$label

\n"; echo "
$title
(" . __( 'Download' ) . ")\n"; echo "

$description

\n"; } } // Checks to see if all of the feed url in $check_urls are cached. // If $check_urls is empty, look for the rss feed url found in the dashboard widget optios of $widget_id. // If cached, call $callback, a function that echoes out output for this widget. // If not cache, echo a "Loading..." stub which is later replaced by AJAX call (see top of /wp-admin/index.php) function wp_dashboard_cached_rss_widget( $widget_id, $callback, $check_urls = array() ) { $loading = '

' . __( 'Loading…' ) . '

'; if ( empty($check_urls) ) { $widgets = get_option( 'dashboard_widget_options' ); if ( empty($widgets[$widget_id]['url']) ) { echo $loading; return false; } $check_urls = array( $widgets[$widget_id]['url'] ); } require_once( ABSPATH . WPINC . '/rss.php' ); init(); // initialize rss constants $cache = new RSSCache( MAGPIE_CACHE_DIR, MAGPIE_CACHE_AGE ); foreach ( $check_urls as $check_url ) { $status = $cache->check_cache( $check_url ); if ( 'HIT' !== $status ) { echo $loading; return false; } } if ( $callback && is_callable( $callback ) ) { $args = array_slice( func_get_args(), 2 ); array_unshift( $args, $widget_id ); call_user_func_array( $callback, $args ); } return true; } // Empty widget used for JS/AJAX created output. // Callback inserts content between before_widget and after_widget. Used when widget is in edit mode. Can also be used for custom widgets. function wp_dashboard_empty( $sidebar_args, $callback = false ) { extract( $sidebar_args, EXTR_SKIP ); echo $before_widget; echo $before_title; echo $widget_name; echo $after_title; // When in edit mode, the callback passed to this function is the widget_control callback if ( $callback && is_callable( $callback ) ) { $args = array_slice( func_get_args(), 2 ); array_unshift( $args, $widget_id ); call_user_func_array( $callback, $args ); } echo $after_widget; } /* Dashboard Widgets Controls. Ssee also wp_dashboard_empty() */ // Calls widget_control callback function wp_dashbaord_trigger_widget_control( $widget_control_id = false ) { global $wp_registered_widget_controls; 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']) ) call_user_func_array( $wp_registered_widget_controls[$widget_control_id]['callback'], $wp_registered_widget_controls[$widget_control_id]['params'] ); } // Sets up $args to be used as input to wp_widget_rss_form(), handles POST data from RSS-type widgets function wp_dashboard_rss_control( $args ) { extract( $args ); if ( !$widget_id ) return false; if ( !$widget_options = get_option( 'dashboard_widget_options' ) ) $widget_options = array(); if ( !isset($widget_options[$widget_id]) ) $widget_options[$widget_id] = array(); $number = 1; // Hack to use wp_widget_rss_form() $widget_options[$widget_id]['number'] = $number; if ( 'POST' == $_SERVER['REQUEST_METHOD'] && isset($_POST['widget-rss'][$number]) ) { $_POST['widget-rss'][$number] = stripslashes_deep( $_POST['widget-rss'][$number] ); $widget_options[$widget_id] = wp_widget_rss_process( $_POST['widget-rss'][$number] ); // title is optional. If black, fill it if possible if ( !$widget_options[$widget_id]['title'] && isset($_POST['widget-rss'][$number]['title']) ) { require_once(ABSPATH . WPINC . '/rss.php'); $rss = fetch_rss($widget_options[$widget_id]['url']); $widget_options[$widget_id]['title'] = htmlentities(strip_tags($rss->channel['title'])); } update_option( 'dashboard_widget_options', $widget_options ); } wp_widget_rss_form( $widget_options[$widget_id], $form_inputs ); } ?>