X-Git-Url: https://scripts.mit.edu/gitweb/autoinstalls/wordpress.git/blobdiff_plain/177fd6fefd2e3d5a0ea6591c71d660cabdb3c1a4..refs/tags/wordpress-3.4:/wp-admin/includes/dashboard.php diff --git a/wp-admin/includes/dashboard.php b/wp-admin/includes/dashboard.php index 9ce9db91..6e7d5f0d 100644 --- a/wp-admin/includes/dashboard.php +++ b/wp-admin/includes/dashboard.php @@ -1,147 +1,134 @@ '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" - ) ); + $response = wp_check_browser_version(); + if ( $response && $response['upgrade'] ) { + add_filter( 'postbox_classes_dashboard_dashboard_browser_nag', 'dashboard_browser_nag_class' ); + if ( $response['insecure'] ) + wp_add_dashboard_widget( 'dashboard_browser_nag', __( 'You are using an insecure browser!' ), 'wp_dashboard_browser_nag' ); + else + wp_add_dashboard_widget( 'dashboard_browser_nag', __( 'Your browser is out of date!' ), 'wp_dashboard_browser_nag' ); + } - /* Register Widgets and Controls */ + // Right Now + if ( is_blog_admin() && current_user_can('edit_posts') ) + wp_add_dashboard_widget( 'dashboard_right_now', __( 'Right Now' ), 'wp_dashboard_right_now' ); + + if ( is_network_admin() ) + wp_add_dashboard_widget( 'network_dashboard_right_now', __( 'Right Now' ), 'wp_network_dashboard_right_now' ); // Recent Comments Widget - if ( current_user_can( 'moderate_comments' ) && $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 = ''; + if ( is_blog_admin() && current_user_can('moderate_comments') ) { + if ( !isset( $widget_options['dashboard_recent_comments'] ) || !isset( $widget_options['dashboard_recent_comments']['items'] ) ) { + $update = true; + $widget_options['dashboard_recent_comments'] = array( + 'items' => 5, + ); + } + $recent_comments_title = __( 'Recent Comments' ); + wp_add_dashboard_widget( 'dashboard_recent_comments', $recent_comments_title, 'wp_dashboard_recent_comments', 'wp_dashboard_recent_comments_control' ); } - 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 - ); + if ( is_blog_admin() && current_user_can('publish_posts') ) { + if ( !isset( $widget_options['dashboard_incoming_links'] ) || !isset( $widget_options['dashboard_incoming_links']['home'] ) || $widget_options['dashboard_incoming_links']['home'] != get_option('home') ) { + $update = true; + $num_items = isset($widget_options['dashboard_incoming_links']['items']) ? $widget_options['dashboard_incoming_links']['items'] : 10; + $widget_options['dashboard_incoming_links'] = array( + 'home' => get_option('home'), + 'link' => apply_filters( 'dashboard_incoming_links_link', 'http://blogsearch.google.com/blogsearch?scoring=d&partner=wordpress&q=link:' . trailingslashit( get_option('home') ) ), + 'url' => isset($widget_options['dashboard_incoming_links']['url']) ? apply_filters( 'dashboard_incoming_links_feed', $widget_options['dashboard_incoming_links']['url'] ) : apply_filters( 'dashboard_incoming_links_feed', 'http://blogsearch.google.com/blogsearch_feeds?scoring=d&ie=utf-8&num=' . $num_items . '&output=rss&partner=wordpress&q=link:' . trailingslashit( get_option('home') ) ), + 'items' => $num_items, + 'show_date' => isset($widget_options['dashboard_incoming_links']['show_date']) ? $widget_options['dashboard_incoming_links']['show_date'] : false + ); + } + wp_add_dashboard_widget( 'dashboard_incoming_links', __( 'Incoming Links' ), 'wp_dashboard_incoming_links', 'wp_dashboard_incoming_links_control' ); } - 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/topics/', '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/' ) - ); + if ( ( ! is_multisite() && is_blog_admin() && current_user_can( 'install_plugins' ) ) || ( is_network_admin() && current_user_can( 'manage_network_plugins' ) && current_user_can( 'install_plugins' ) ) ) + wp_add_dashboard_widget( 'dashboard_plugins', __( 'Plugins' ), 'wp_dashboard_plugins' ); + + // QuickPress Widget + if ( is_blog_admin() && current_user_can('edit_posts') ) + wp_add_dashboard_widget( 'dashboard_quick_press', __( 'QuickPress' ), 'wp_dashboard_quick_press' ); + + // Recent Drafts + if ( is_blog_admin() && current_user_can('edit_posts') ) + wp_add_dashboard_widget( 'dashboard_recent_drafts', __('Recent Drafts'), 'wp_dashboard_recent_drafts' ); // 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' ) ), + 'link' => apply_filters( 'dashboard_primary_link', __( 'http://wordpress.org/news/' ) ), + 'url' => apply_filters( 'dashboard_primary_feed', __( 'http://wordpress.org/news/feed/' ) ), + 'title' => apply_filters( 'dashboard_primary_title', __( 'WordPress Blog' ) ), 'items' => 2, 'show_summary' => 1, 'show_author' => 0, - 'show_date' => 1 + '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' ) - ); - + wp_add_dashboard_widget( 'dashboard_primary', $widget_options['dashboard_primary']['title'], 'wp_dashboard_primary', 'wp_dashboard_primary_control' ); // 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/' ) ), + '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 + 'items' => 5, + 'show_summary' => 0, + 'show_author' => 0, + 'show_date' => 0, ); } - 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, - ... - ) - ); - */ + wp_add_dashboard_widget( 'dashboard_secondary', $widget_options['dashboard_secondary']['title'], 'wp_dashboard_secondary', 'wp_dashboard_secondary_control' ); // Hook to register new widgets - do_action( 'wp_dashboard_setup' ); - - // Hard code the sidebar's widgets and order - $dashboard_widgets = array(); - $dashboard_widgets[] = 'dashboard_recent_comments'; - $dashboard_widgets[] = 'dashboard_incoming_links'; - $dashboard_widgets[] = 'dashboard_primary'; - if ( current_user_can( 'activate_plugins' ) ) - $dashboard_widgets[] = 'dashboard_plugins'; - $dashboard_widgets[] = '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 ); + if ( is_network_admin() ) { + do_action( 'wp_network_dashboard_setup' ); + $dashboard_widgets = apply_filters( 'wp_network_dashboard_widgets', array() ); + } elseif ( is_user_admin() ) { + do_action( 'wp_user_dashboard_setup' ); + $dashboard_widgets = apply_filters( 'wp_user_dashboard_widgets', array() ); + } else { + do_action( 'wp_dashboard_setup' ); + $dashboard_widgets = apply_filters( 'wp_dashboard_widgets', array() ); + } - add_filter( 'dynamic_sidebar_params', 'wp_dashboard_dynamic_sidebar_params' ); + foreach ( $dashboard_widgets as $widget_id ) { + $name = empty( $wp_registered_widgets[$widget_id]['all_link'] ) ? $wp_registered_widgets[$widget_id]['name'] : $wp_registered_widgets[$widget_id]['name'] . " " . __('View all') . ''; + wp_add_dashboard_widget( $widget_id, $name, $wp_registered_widgets[$widget_id]['callback'], $wp_registered_widget_controls[$widget_id]['callback'] ); + } if ( 'POST' == $_SERVER['REQUEST_METHOD'] && isset($_POST['widget_id']) ) { ob_start(); // hack - but the same hack wp-admin/widgets.php uses @@ -153,367 +140,928 @@ function wp_dashboard_setup() { if ( $update ) update_option( 'dashboard_widget_options', $widget_options ); + + do_action('do_meta_boxes', $screen->id, 'normal', ''); + do_action('do_meta_boxes', $screen->id, 'side', ''); } -// Echoes out the dashboard -function wp_dashboard() { - echo "
\n\n"; +function wp_add_dashboard_widget( $widget_id, $widget_name, $callback, $control_callback = null ) { + $screen = get_current_screen(); + global $wp_dashboard_control_callbacks; - // 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' ); + if ( $control_callback && current_user_can( 'edit_dashboard' ) && is_callable( $control_callback ) ) { + $wp_dashboard_control_callbacks[$widget_id] = $control_callback; + if ( isset( $_GET['edit'] ) && $widget_id == $_GET['edit'] ) { + list($url) = explode( '#', add_query_arg( 'edit', false ), 2 ); + $widget_name .= ' ' . __( 'Cancel' ) . ''; + $callback = '_wp_dashboard_control_callback'; + } else { + list($url) = explode( '#', add_query_arg( 'edit', $widget_id ), 2 ); + $widget_name .= ' ' . __( 'Configure' ) . ''; + } + } + + if ( is_blog_admin () ) + $side_widgets = array('dashboard_quick_press', 'dashboard_recent_drafts', 'dashboard_primary', 'dashboard_secondary'); + else if (is_network_admin() ) + $side_widgets = array('dashboard_primary', 'dashboard_secondary'); + else + $side_widgets = array(); - echo "
\n
\n\n\n"; + $location = 'normal'; + if ( in_array($widget_id, $side_widgets) ) + $location = 'side'; + + $priority = 'core'; + if ( 'dashboard_browser_nag' === $widget_id ) + $priority = 'high'; + + add_meta_box( $widget_id, $widget_name, $callback, $screen, $location, $priority ); } -// Makes sidebar_widgets option reflect the dashboard settings -function wp_dashboard_sidebars_widgets() { // hackery - return $GLOBALS['wp_dashboard_sidebars']; +function _wp_dashboard_control_callback( $dashboard, $meta_box ) { + echo '
'; + wp_dashboard_trigger_widget_control( $meta_box['id'] ); + echo ''; + submit_button( __('Submit') ); + echo '
'; } -// 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; - - $sidebar_defaults = array('widget_id' => 0, 'before_widget' => '', 'after_widget' => '', 'before_title' => '', 'after_title' => ''); - extract( $sidebar_defaults, EXTR_PREFIX_ALL, 'sidebar' ); - extract( $params[0], EXTR_PREFIX_ALL, 'sidebar' ); - - if ( !isset($wp_registered_widgets[$sidebar_widget_id]) || !is_array($wp_registered_widgets[$sidebar_widget_id]) ) { - return $params; - } - $widget_defaults = array('id' => '', 'width' => '', 'height' => '', 'class' => '', 'feed_link' => '', 'all_link' => '', 'notice' => false, 'error' => false); - extract( $widget_defaults, EXTR_PREFIX_ALL, 'widget' ); - 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_dashboard_trigger_widget_control'; - $sidebar_before_widget .= '
'; - $sidebar_after_widget = "
$sidebar_after_widget"; - $links[] = '' . __( 'Cancel' ) . ''; - } else { - $links[] = '' . __( 'Edit' ) . ''; - } +/** + * Displays the dashboard. + * + * @since 2.5.0 + */ +function wp_dashboard() { + $screen = get_current_screen(); + $class = 'columns-' . get_current_screen()->get_columns(); + +?> +
+
+ id, 'normal', '' ); ?> +
+
+ id, 'side', '' ); ?> +
+
+ id, 'column3', '' ); ?> +
+
+ id, 'column4', '' ); ?> +
+
+ +'; + echo "\n\t".'

' . __('Content') . '

'."\n\t".''; + echo "\n\t".''; + + // Posts + $num = number_format_i18n( $num_posts->publish ); + $text = _n( 'Post', 'Posts', intval($num_posts->publish) ); + if ( current_user_can( 'edit_posts' ) ) { + $num = "$num"; + $text = "$text"; } + echo ''; + echo ''; - if ( $widget_feed_link ) - $links[] = '' . __( 'rss icon' ) . '' . __( 'RSS' ) . ''; + echo ''; + /* TODO: Show status breakdown on hover + if ( $can_edit_pages && !empty($num_pages->publish) ) { // how many pages is not exposed in feeds. Don't show if !current_user_can + $post_type_texts[] = ''.sprintf( _n( '%s page', '%s pages', $num_pages->publish ), number_format_i18n( $num_pages->publish ) ).''; + } + if ( $can_edit_posts && !empty($num_posts->draft) ) { + $post_type_texts[] = ''.sprintf( _n( '%s draft', '%s drafts', $num_posts->draft ), number_format_i18n( $num_posts->draft ) ).''; + } + if ( $can_edit_posts && !empty($num_posts->future) ) { + $post_type_texts[] = ''.sprintf( _n( '%s scheduled post', '%s scheduled posts', $num_posts->future ), number_format_i18n( $num_posts->future ) ).''; + } + if ( current_user_can('publish_posts') && !empty($num_posts->pending) ) { + $pending_text = sprintf( _n( 'There is %2$s post pending your review.', 'There are %2$s posts pending your review.', $num_posts->pending ), 'edit.php?post_status=pending', number_format_i18n( $num_posts->pending ) ); + } else { + $pending_text = ''; + } + */ + + // Pages + $num = number_format_i18n( $num_pages->publish ); + $text = _n( 'Page', 'Pages', $num_pages->publish ); + if ( current_user_can( 'edit_pages' ) ) { + $num = "$num"; + $text = "$text"; + } + echo ''; + echo ''; - $links = apply_filters( "wp_dashboard_widget_links_$widget_id", $links ); + echo ''; - // Add links to widget's title bar - if ( $links ) { - $sidebar_before_title .= ''; - $sidebar_after_title = '' . join( ' | ', $links ) . "
$sidebar_after_title"; + // Categories + $num = number_format_i18n( $num_cats ); + $text = _n( 'Category', 'Categories', $num_cats ); + if ( current_user_can( 'manage_categories' ) ) { + $num = "$num"; + $text = "$text"; } + echo ''; + echo ''; - // Could have put this in widget-content. Doesn't really matter - if ( $widget_notice ) - $sidebar_after_title .= "\t\t\t
$widget_notice
\n\n"; + echo ''; - if ( $widget_error ) - $sidebar_after_title .= "\t\t\t
$widget_error
\n\n"; + // Tags + $num = number_format_i18n( $num_tags ); + $text = _n( 'Tag', 'Tags', $num_tags ); + if ( current_user_can( 'manage_categories' ) ) { + $num = "$num"; + $text = "$text"; + } + echo ''; + echo ''; + + echo ""; + do_action('right_now_content_table_end'); + echo "\n\t
' . $num . '' . $text . '
' . $num . '' . $text . '
' . $num . '' . $text . '
' . $num . '' . $text . '
\n\t
"; + + echo "\n\t".'
'; + echo "\n\t".'

' . __('Discussion') . '

'."\n\t".''; + echo "\n\t".''; + + // Total Comments + $num = '' . number_format_i18n($num_comm->total_comments) . ''; + $text = _n( 'Comment', 'Comments', $num_comm->total_comments ); + if ( current_user_can( 'moderate_comments' ) ) { + $num = '' . $num . ''; + $text = '' . $text . ''; + } + echo ''; + echo ''; - $sidebar_after_title .= "\t\t\t
\n\n"; + echo '
'; - $sidebar_after_widget .= "\t\t\t\n\n"; + // Approved Comments + $num = '' . number_format_i18n($num_comm->approved) . ''; + $text = _nx( 'Approved', 'Approved', $num_comm->approved, 'Right Now' ); + if ( current_user_can( 'moderate_comments' ) ) { + $num = "$num"; + $text = "$text"; + } + echo ''; + echo ''; - foreach( array_keys( $params[0] ) as $key ) - $$key = ${'sidebar_' . $key}; + echo "\n\t"; - $params[0] = compact( array_keys( $params[0] ) ); + // Pending Comments + $num = '' . number_format_i18n($num_comm->moderated) . ''; + $text = _n( 'Pending', 'Pending', $num_comm->moderated ); + if ( current_user_can( 'moderate_comments' ) ) { + $num = "$num"; + $text = "$text"; + } + echo ''; + echo ''; - return $params; -} + echo "\n\t"; + // Spam Comments + $num = number_format_i18n($num_comm->spam); + $text = _nx( 'Spam', 'Spam', $num_comm->spam, 'comment' ); + if ( current_user_can( 'moderate_comments' ) ) { + $num = "$num"; + $text = "$text"; + } + echo ''; + echo ''; + + echo ""; + do_action('right_now_table_end'); + do_action('right_now_discussion_table_end'); + echo "\n\t
' . $num . '' . $text . '
' . $num . '' . $text . '
' . $num . '' . $text . '
' . $num . '' . $text . '
\n\t
"; + + echo "\n\t".'
'; + $theme = wp_get_theme(); + + echo "\n\t

"; + + if ( $theme->errors() ) { + if ( ! is_multisite() || is_super_admin() ) + echo '' . __('ERROR: The themes directory is either empty or doesn’t exist. Please check your installation.') . ''; + } elseif ( ! empty($wp_registered_sidebars) ) { + $sidebars_widgets = wp_get_sidebars_widgets(); + $num_widgets = 0; + foreach ( (array) $sidebars_widgets as $k => $v ) { + if ( 'wp_inactive_widgets' == $k || 'orphaned_widgets' == substr( $k, 0, 16 ) ) + continue; + if ( is_array($v) ) + $num_widgets = $num_widgets + count($v); + } + $num = number_format_i18n( $num_widgets ); -/* Dashboard Widgets */ + $switch_themes = $theme->display('Name'); + if ( current_user_can( 'switch_themes') ) + $switch_themes = '' . $switch_themes . ''; + if ( current_user_can( 'edit_theme_options' ) ) { + printf(_n('Theme %1$s with %2$s Widget', 'Theme %1$s with %2$s Widgets', $num_widgets), $switch_themes, $num); + } else { + printf(_n('Theme %1$s with %2$s Widget', 'Theme %1$s with %2$s Widgets', $num_widgets), $switch_themes, $num); + } + } else { + if ( current_user_can( 'switch_themes' ) ) + printf( __('Theme %1$s'), $theme->display('Name') ); + else + printf( __('Theme %1$s'), $theme->display('Name') ); + } + echo '

'; -function wp_dashboard_recent_comments( $sidebar_args ) { - global $comment; - extract( $sidebar_args, EXTR_SKIP ); + // Check if search engines are blocked. + if ( !is_network_admin() && !is_user_admin() && current_user_can('manage_options') && '1' != get_option('blog_public') ) { + $title = apply_filters('privacy_on_link_title', __('Your site is asking search engines not to index its content') ); + $content = apply_filters('privacy_on_link_text', __('Search Engines Blocked') ); - echo $before_widget; + echo "

$content

"; + } + + update_right_now_message(); - echo $before_title; - echo $widget_name; - echo $after_title; + echo "\n\t".'
'; + do_action( 'rightnow_end' ); + do_action( 'activity_box_end' ); +} - $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 ); +function wp_network_dashboard_right_now() { + $actions = array(); + if ( current_user_can('create_sites') ) + $actions['create-site'] = '' . __( 'Create a New Site' ) . ''; + if ( current_user_can('create_users') ) + $actions['create-user'] = '' . __( 'Create a New User' ) . ''; - $is_first = true; + $c_users = get_user_count(); + $c_blogs = get_blog_count(); - if ( $comments_query->have_comments() ) { - while ( $comments_query->have_comments() ) { $comments_query->the_comment(); + $user_text = sprintf( _n( '%s user', '%s users', $c_users ), number_format_i18n( $c_users ) ); + $blog_text = sprintf( _n( '%s site', '%s sites', $c_blogs ), number_format_i18n( $c_blogs ) ); - $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 %1$s on %2$s %3$s' ), get_comment_author(), $comment_post_link, $comment_link ); + $sentence = sprintf( __( 'You have %1$s and %2$s.' ), $blog_text, $user_text ); - if ( $is_first ) : $is_first = false; + if ( $actions ) { + echo ''; + } ?> -

-

+
+ +

+ + +
+

+ + 'submit_users' ) ); ?> +

+
+ +
+

+ + 'submit_sites' ) ); ?> +

+
comment_count > 1 ) : ?> - +
comment_ID) ) ); ?>> + comment_type || 'comment' == $comment->comment_type ) : ?> + + + +
+

+ ' . get_comment_author_link() . '', $comment_post_link.' '.$comment_link, ' ' . __( '[Pending]' ) . '' ); ?> +

+ + comment_type ) : + case 'pingback' : + $type = __( 'Pingback' ); + break; + case 'trackback' : + $type = __( 'Trackback' ); + break; + default : + $type = ucwords( $comment->comment_type ); + endswitch; + $type = esc_html( $type ); + ?> +
+ +

$type", $comment_post_link." ".$comment_link ); ?>

+

+ + +

+

+
+
'; + echo '

'; } -// $sidebar_args are handled by wp_dashboard_empty() +function wp_dashboard_incoming_links() { + wp_dashboard_cached_rss_widget( 'dashboard_incoming_links', 'wp_dashboard_incoming_links_output' ); +} + +/** + * Display incoming links dashboard widget content. + * + * @since 2.5.0 + */ function wp_dashboard_incoming_links_output() { $widgets = get_option( 'dashboard_widget_options' ); @extract( @$widgets['dashboard_incoming_links'], EXTR_SKIP ); - $rss = @fetch_rss( $url ); - if ( isset($rss->items) && 1 < count($rss->items) ) {// Technorati returns a 1-item feed when it has no results + $rss = fetch_feed( $url ); - echo "\n"; + $rss->__destruct(); + unset($rss); +} + +function wp_dashboard_incoming_links_control() { + wp_dashboard_rss_control( 'dashboard_incoming_links', array( 'title' => false, 'show_summary' => false, 'show_author' => false ) ); } -// $sidebar_args are handled by wp_dashboard_empty() +function wp_dashboard_primary() { + wp_dashboard_cached_rss_widget( 'dashboard_primary', 'wp_dashboard_rss_output' ); +} + +function wp_dashboard_primary_control() { + wp_dashboard_rss_control( 'dashboard_primary' ); +} + +/** + * {@internal Missing Short Description}} + * + * @since 2.5.0 + * + * @param string $widget_id + */ function wp_dashboard_rss_output( $widget_id ) { $widgets = get_option( 'dashboard_widget_options' ); + echo '
'; wp_widget_rss_output( $widgets[$widget_id] ); + echo "
"; +} + +function wp_dashboard_secondary() { + wp_dashboard_cached_rss_widget( 'dashboard_secondary', 'wp_dashboard_secondary_output' ); +} + +function wp_dashboard_secondary_control() { + wp_dashboard_rss_control( 'dashboard_secondary' ); } -// $sidebar_args are handled by wp_dashboard_empty() +/** + * Display secondary dashboard RSS widget feed. + * + * @since 2.5.0 + * + * @return unknown + */ 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"; +function wp_dashboard_plugins() { + wp_dashboard_cached_rss_widget( 'dashboard_plugins', 'wp_dashboard_plugins_output', array( + 'http://wordpress.org/extend/plugins/rss/browse/popular/', + 'http://wordpress.org/extend/plugins/rss/browse/new/' + ) ); } -// $sidebar_args are handled by wp_dashboard_empty() +/** + * Display plugins most popular, newest plugins, and recently updated widget text. + * + * @since 2.5.0 + */ 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/' ); + $popular = fetch_feed( 'http://wordpress.org/extend/plugins/rss/browse/popular/' ); + $new = fetch_feed( 'http://wordpress.org/extend/plugins/rss/browse/new/' ); + + if ( false === $plugin_slugs = get_transient( 'plugin_slugs' ) ) { + $plugin_slugs = array_keys( get_plugins() ); + set_transient( 'plugin_slugs', $plugin_slugs, 86400 ); + } - foreach ( array( 'popular' => __('Most Popular'), 'new' => __('Newest Plugins'), 'updated' => __('Recently Updated') ) as $feed => $label ) { - if ( !isset($$feed->items) || 0 == count($$feed->items) ) + foreach ( array( 'popular' => __('Most Popular'), 'new' => __('Newest Plugins') ) as $feed => $label ) { + if ( is_wp_error($$feed) || !$$feed->get_item_quantity() ) continue; - $$feed->items = array_slice($$feed->items, 0, 5); - $item_key = array_rand($$feed->items); + $items = $$feed->get_items(0, 5); + + // Pick a random, non-installed plugin + while ( true ) { + // Abort this foreach loop iteration if there's no plugins left of this type + if ( 0 == count($items) ) + continue 2; + + $item_key = array_rand($items); + $item = $items[$item_key]; + + list($link, $frag) = explode( '#', $item->get_link() ); + + $link = esc_url($link); + if ( preg_match( '|/([^/]+?)/?$|', $link, $matches ) ) + $slug = $matches[1]; + else { + unset( $items[$item_key] ); + continue; + } + + // Is this random plugin's slug already installed? If so, try again. + reset( $plugin_slugs ); + foreach ( $plugin_slugs as $plugin_slug ) { + if ( $slug == substr( $plugin_slug, 0, strlen( $slug ) ) ) { + unset( $items[$item_key] ); + continue 2; + } + } + + // If we get to this point, then the random plugin isn't installed and we can stop the while(). + break; + } // 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]); + while ( ( null !== $item_key = array_rand($items) ) && false !== strpos( $items[$item_key]->get_description(), 'Plugin Name:' ) ) + unset($items[$item_key]); - if ( !isset($$feed->items[$item_key]) ) + if ( !isset($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 ) ) + if ( preg_match( '/"(.*)"/s', $item->get_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)) ); + $title = $item->get_title(); + $title = esc_html( $title ); - list($link, $frag) = explode( '#', $item['link'] ); + $description = esc_html( strip_tags(@html_entity_decode($item->get_description(), ENT_QUOTES, get_option('blog_charset'))) ); - $link = clean_url($link); - $dlink = rtrim($link, '/') . '/download/'; + $ilink = wp_nonce_url('plugin-install.php?tab=plugin-information&plugin=' . $slug, 'install-plugin_' . $slug) . + '&TB_iframe=true&width=600&height=800'; echo "

$label

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

$description

\n"; + + $$feed->__destruct(); + unset($$feed); } } -// 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) +/** + * 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 options 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) + * + * @since 2.5.0 + * + * @param string $widget_id + * @param callback $callback + * @param array $check_urls RSS feeds + * @return bool False on failure. True on success. + */ function wp_dashboard_cached_rss_widget( $widget_id, $callback, $check_urls = array() ) { - $loading = '

' . __( 'Loading…' ) . '

'; + $loading = '

' . __( 'Loading…' ) . '

' . __( 'This widget requires JavaScript.' ) . '

'; + $doing_ajax = ( defined('DOING_AJAX') && DOING_AJAX ); if ( empty($check_urls) ) { $widgets = get_option( 'dashboard_widget_options' ); - if ( empty($widgets[$widget_id]['url']) ) { + if ( empty($widgets[$widget_id]['url']) && ! $doing_ajax ) { 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; - } + $cache_key = 'dash_' . md5( $widget_id ); + if ( false !== ( $output = get_transient( $cache_key ) ) ) { + echo $output; + return true; } - if ( $callback && is_callable( $callback ) ) { - $args = array_slice( func_get_args(), 2 ); - array_unshift( $args, $widget_id ); - call_user_func_array( $callback, $args ); + if ( ! $doing_ajax ) { + echo $loading; + return false; } - 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 ); + ob_start(); call_user_func_array( $callback, $args ); + set_transient( $cache_key, ob_get_flush(), 43200); // Default lifetime in cache of 12 hours (same as the feeds) } - echo $after_widget; + return true; } -/* Dashboard Widgets Controls. Ssee also wp_dashboard_empty() */ +/* Dashboard Widgets Controls */ // Calls widget_control callback +/** + * Calls widget control callback. + * + * @since 2.5.0 + * + * @param int $widget_control_id Registered Widget ID. + */ function wp_dashboard_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'] ); -} + global $wp_dashboard_control_callbacks; -// 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 ( is_scalar($widget_control_id) && $widget_control_id && isset($wp_dashboard_control_callbacks[$widget_control_id]) && is_callable($wp_dashboard_control_callbacks[$widget_control_id]) ) { + call_user_func( $wp_dashboard_control_callbacks[$widget_control_id], '', array( 'id' => $widget_control_id, 'callback' => $wp_dashboard_control_callbacks[$widget_control_id] ) ); + } +} +/** + * The RSS dashboard widget control. + * + * Sets up $args to be used as input to wp_widget_rss_form(). Handles POST data + * from RSS-type widgets. + * + * @since 2.5.0 + * + * @param string $widget_id + * @param array $form_inputs + */ +function wp_dashboard_rss_control( $widget_id, $form_inputs = array() ) { if ( !$widget_options = get_option( 'dashboard_widget_options' ) ) $widget_options = array(); @@ -526,16 +1074,253 @@ function wp_dashboard_rss_control( $args ) { 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 + // 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'])); + $rss = fetch_feed($widget_options[$widget_id]['url']); + if ( is_wp_error($rss) ) { + $widget_options[$widget_id]['title'] = htmlentities(__('Unknown Feed')); + } else { + $widget_options[$widget_id]['title'] = htmlentities(strip_tags($rss->get_title())); + $rss->__destruct(); + unset($rss); + } } update_option( 'dashboard_widget_options', $widget_options ); + $cache_key = 'dash_' . md5( $widget_id ); + delete_transient( $cache_key ); } wp_widget_rss_form( $widget_options[$widget_id], $form_inputs ); } -?> +// Display File upload quota on dashboard +function wp_dashboard_quota() { + if ( !is_multisite() || !current_user_can('upload_files') || get_site_option( 'upload_space_check_disabled' ) ) + return true; + + $quota = get_space_allowed(); + $used = get_dirsize( BLOGUPLOADDIR ) / 1024 / 1024; + + if ( $used > $quota ) + $percentused = '100'; + else + $percentused = ( $used / $quota ) * 100; + $used_color = ( $percentused >= 70 ) ? ' spam' : ''; + $used = round( $used, 2 ); + $percentused = number_format( $percentused ); + + ?> +

+
+ + + + + +
%2$sMB' ), esc_url( admin_url( 'upload.php' ) ), $quota ); ?>
+
+
+ + + + + +
%2$sMB (%3$s%%)' ), esc_url( admin_url( 'upload.php' ) ), $used, $percentused ); ?>
+
+
+ %s. Using an outdated browser makes your computer unsafe. For the best WordPress experience, please update your browser." ), esc_attr( $response['update_url'] ), esc_html( $response['name'] ) ); + } else { + $msg = sprintf( __( "It looks like you're using an old version of %s. For the best WordPress experience, please update your browser." ), esc_attr( $response['update_url'] ), esc_html( $response['name'] ) ); + } + + $browser_nag_class = ''; + if ( !empty( $response['img_src'] ) ) { + $img_src = ( is_ssl() && ! empty( $response['img_src_ssl'] ) )? $response['img_src_ssl'] : $response['img_src']; + + $notice .= '
'; + $browser_nag_class = ' has-browser-icon'; + } + $notice .= "

{$msg}

"; + + $browsehappy = 'http://browsehappy.com/'; + $locale = get_locale(); + if ( 'en_US' !== $locale ) + $browsehappy = add_query_arg( 'locale', $locale, $browsehappy ); + + $notice .= '

' . sprintf( __( 'Update %2$s or learn how to browse happy' ), esc_attr( $response['update_url'] ), esc_html( $response['name'] ), esc_url( $browsehappy ) ) . '

'; + $notice .= '

' . __( 'Dismiss' ) . '

'; + $notice .= '
'; + } + + echo apply_filters( 'browse-happy-notice', $notice, $response ); +} + +function dashboard_browser_nag_class( $classes ) { + $response = wp_check_browser_version(); + + if ( $response && $response['insecure'] ) + $classes[] = 'browser-insecure'; + + return $classes; +} + +/** + * Check if the user needs a browser update + * + * @since 3.2.0 + * + * @return array|bool False on failure, array of browser data on success. + */ +function wp_check_browser_version() { + if ( empty( $_SERVER['HTTP_USER_AGENT'] ) ) + return false; + + $key = md5( $_SERVER['HTTP_USER_AGENT'] ); + + if ( false === ($response = get_site_transient('browser_' . $key) ) ) { + global $wp_version; + + $options = array( + 'body' => array( 'useragent' => $_SERVER['HTTP_USER_AGENT'] ), + 'user-agent' => 'WordPress/' . $wp_version . '; ' . home_url() + ); + + $response = wp_remote_post( 'http://api.wordpress.org/core/browse-happy/1.0/', $options ); + + if ( is_wp_error( $response ) || 200 != wp_remote_retrieve_response_code( $response ) ) + return false; + + /** + * Response should be an array with: + * 'name' - string - A user friendly browser name + * 'version' - string - The most recent version of the browser + * 'current_version' - string - The version of the browser the user is using + * 'upgrade' - boolean - Whether the browser needs an upgrade + * 'insecure' - boolean - Whether the browser is deemed insecure + * 'upgrade_url' - string - The url to visit to upgrade + * 'img_src' - string - An image representing the browser + * 'img_src_ssl' - string - An image (over SSL) representing the browser + */ + $response = maybe_unserialize( wp_remote_retrieve_body( $response ) ); + + if ( ! is_array( $response ) ) + return false; + + set_site_transient( 'browser_' . $key, $response, 604800 ); // cache for 1 week + } + + return $response; +} + +/** + * Empty function usable by plugins to output empty dashboard widget (to be populated later by JS). + */ +function wp_dashboard_empty() {} + +/** + * Displays a welcome panel to introduce users to WordPress. + * + * @since 3.3.0 + */ +function wp_welcome_panel() { + global $wp_version; + + if ( ! current_user_can( 'edit_theme_options' ) ) + return; + + $classes = 'welcome-panel'; + + $option = get_user_meta( get_current_user_id(), 'show_welcome_panel', true ); + // 0 = hide, 1 = toggled to show or single site creator, 2 = multisite site owner + $hide = 0 == $option || ( 2 == $option && wp_get_current_user()->user_email != get_option( 'admin_email' ) ); + if ( $hide ) + $classes .= ' hidden'; + + list( $display_version ) = explode( '-', $wp_version ); + ?> +
+ + +
+ +
+

+

First Steps with WordPress. If you’d rather dive right in, here are a few things most people do first when they set up a new WordPress site. If you need help, use the Help tabs in the upper right corner to get information on how to use your current screen and where to go for more assistance.' ); ?>

+
+
+

+

+
    +
  • Choose your privacy setting' ), esc_url( admin_url('options-privacy.php') ) ); ?>
  • +
  • Select your tagline and time zone' ), esc_url( admin_url('options-general.php') ) ); ?>
  • +
  • Turn comments on or off' ), esc_url( admin_url('options-discussion.php') ) ); ?>
  • +
  • Fill in your profile' ), esc_url( admin_url('profile.php') ) ); ?>
  • +
+
+
+

+

+
    +
  • sample page and post' ), esc_url( get_permalink( 2 ) ), esc_url( get_permalink( 1 ) ) ); ?>
  • +
  • sample page and post' ), esc_url( admin_url('edit.php?post_type=page') ), esc_url( admin_url('edit.php') ) ); ?>
  • +
  • Create an About Me page' ), esc_url( admin_url('edit.php?post_type=page') ) ); ?>
  • +
  • Write your first post' ), esc_url( admin_url('post-new.php') ) ); ?>
  • +
+
+
+

+ errors() ) : + echo '

'; + printf( __( 'Install a theme to get started customizing your site.' ), esc_url( admin_url( 'themes.php' ) ) ); + echo '

'; + else: + $customize_links = array(); + if ( 'twentyeleven' == $theme->get_stylesheet() ) + $customize_links[] = sprintf( __( 'Choose light or dark' ), esc_url( admin_url( 'themes.php?page=theme_options' ) ) ); + + if ( current_theme_supports( 'custom-background' ) ) + $customize_links[] = sprintf( __( 'Set a background color' ), esc_url( admin_url( 'themes.php?page=custom-background' ) ) ); + + if ( current_theme_supports( 'custom-header' ) ) + $customize_links[] = sprintf( __( 'Select a new header image' ), esc_url( admin_url( 'themes.php?page=custom-header' ) ) ); + + if ( current_theme_supports( 'widgets' ) ) + $customize_links[] = sprintf( __( 'Add some widgets' ), esc_url( admin_url( 'widgets.php' ) ) ); + + if ( ! empty( $customize_links ) ) { + echo '

'; + printf( __( 'Use the current theme — %1$s — or choose a new one. If you stick with %1$s, here are a few ways to make your site look unique.' ), $theme->display('Name'), esc_url( admin_url( 'themes.php' ) ) ); + echo '

'; + ?> +
    + +
  • + +
+ '; + printf( __( 'Use the current theme — %1$s — or choose a new one.' ), $theme->display('Name'), esc_url( admin_url( 'themes.php' ) ) ); + echo '

'; + } + endif; ?> +
+
+

Dismiss this message.' ), esc_url( admin_url( '?welcome=0' ) ) ); ?>

+
+
+