wp/wp-admin/includes/dashboard.php
changeset 7 cf61fcea0001
parent 5 5e2f62d02dcd
child 9 177826044cd9
equal deleted inserted replaced
6:490d5cc509ed 7:cf61fcea0001
    10  * Registers dashboard widgets.
    10  * Registers dashboard widgets.
    11  *
    11  *
    12  * Handles POST data, sets up filters.
    12  * Handles POST data, sets up filters.
    13  *
    13  *
    14  * @since 2.5.0
    14  * @since 2.5.0
       
    15  *
       
    16  * @global array $wp_registered_widgets
       
    17  * @global array $wp_registered_widget_controls
       
    18  * @global array $wp_dashboard_control_callbacks
    15  */
    19  */
    16 function wp_dashboard_setup() {
    20 function wp_dashboard_setup() {
    17 	global $wp_registered_widgets, $wp_registered_widget_controls, $wp_dashboard_control_callbacks;
    21 	global $wp_registered_widgets, $wp_registered_widget_controls, $wp_dashboard_control_callbacks;
    18 	$wp_dashboard_control_callbacks = array();
    22 	$wp_dashboard_control_callbacks = array();
    19 	$screen = get_current_screen();
    23 	$screen = get_current_screen();
    20 
    24 
    21 	/* Register Widgets and Controls */
    25 	/* Register Widgets and Controls */
       
    26 
       
    27 	// Try Gutenberg
       
    28 
       
    29 	// If Gutenberg isn't activated, only show the panel to users who can install and activate it.
       
    30 	$plugins = get_plugins();
       
    31 	if ( is_plugin_inactive( 'gutenberg/gutenberg.php' ) && ! current_user_can( 'install_plugins' ) ) {
       
    32 		remove_action( 'try_gutenberg_panel', 'wp_try_gutenberg_panel' );
       
    33 	}
       
    34 	// If Gutenberg is activated, only show it to users who can use it.
       
    35 	if ( is_plugin_active( 'gutenberg/gutenberg.php' ) && ! current_user_can( 'edit_posts' ) ) {
       
    36 		remove_action( 'try_gutenberg_panel', 'wp_try_gutenberg_panel' );
       
    37 	}
    22 
    38 
    23 	$response = wp_check_browser_version();
    39 	$response = wp_check_browser_version();
    24 
    40 
    25 	if ( $response && $response['upgrade'] ) {
    41 	if ( $response && $response['upgrade'] ) {
    26 		add_filter( 'postbox_classes_dashboard_dashboard_browser_nag', 'dashboard_browser_nag_class' );
    42 		add_filter( 'postbox_classes_dashboard_dashboard_browser_nag', 'dashboard_browser_nag_class' );
    41 	if ( is_blog_admin() ) {
    57 	if ( is_blog_admin() ) {
    42 		wp_add_dashboard_widget( 'dashboard_activity', __( 'Activity' ), 'wp_dashboard_site_activity' );
    58 		wp_add_dashboard_widget( 'dashboard_activity', __( 'Activity' ), 'wp_dashboard_site_activity' );
    43 	}
    59 	}
    44 
    60 
    45 	// QuickPress Widget
    61 	// QuickPress Widget
    46 	if ( is_blog_admin() && current_user_can( 'edit_posts' ) ) {
    62 	if ( is_blog_admin() && current_user_can( get_post_type_object( 'post' )->cap->create_posts ) ) {
    47 		$quick_draft_title = sprintf( '<span class="hide-if-no-js">%1$s</span> <span class="hide-if-js">%2$s</span>', __( 'Quick Draft' ), __( 'Drafts' ) );
    63 		$quick_draft_title = sprintf( '<span class="hide-if-no-js">%1$s</span> <span class="hide-if-js">%2$s</span>', __( 'Quick Draft' ), __( 'Your Recent Drafts' ) );
    48 		wp_add_dashboard_widget( 'dashboard_quick_press', $quick_draft_title, 'wp_dashboard_quick_press' );
    64 		wp_add_dashboard_widget( 'dashboard_quick_press', $quick_draft_title, 'wp_dashboard_quick_press' );
    49 	}
    65 	}
    50 
    66 
    51 	// WordPress News
    67 	// WordPress Events and News
    52 	wp_add_dashboard_widget( 'dashboard_primary', __( 'WordPress News' ), 'wp_dashboard_primary' );
    68 	wp_add_dashboard_widget( 'dashboard_primary', __( 'WordPress Events and News' ), 'wp_dashboard_events_news' );
    53 
    69 
    54 	if ( is_network_admin() ) {
    70 	if ( is_network_admin() ) {
    55 
    71 
    56 		/**
    72 		/**
    57 		 * Fires after core widgets for the Network Admin dashboard have been registered.
    73 		 * Fires after core widgets for the Network Admin dashboard have been registered.
    59 		 * @since 3.1.0
    75 		 * @since 3.1.0
    60 		 */
    76 		 */
    61 		do_action( 'wp_network_dashboard_setup' );
    77 		do_action( 'wp_network_dashboard_setup' );
    62 
    78 
    63 		/**
    79 		/**
    64 		 * Filter the list of widgets to load for the Network Admin dashboard.
    80 		 * Filters the list of widgets to load for the Network Admin dashboard.
    65 		 *
    81 		 *
    66 		 * @since 3.1.0
    82 		 * @since 3.1.0
    67 		 *
    83 		 *
    68 		 * @param array $dashboard_widgets An array of dashboard widgets.
    84 		 * @param array $dashboard_widgets An array of dashboard widgets.
    69 		 */
    85 		 */
    76 		 * @since 3.1.0
    92 		 * @since 3.1.0
    77 		 */
    93 		 */
    78 		do_action( 'wp_user_dashboard_setup' );
    94 		do_action( 'wp_user_dashboard_setup' );
    79 
    95 
    80 		/**
    96 		/**
    81 		 * Filter the list of widgets to load for the User Admin dashboard.
    97 		 * Filters the list of widgets to load for the User Admin dashboard.
    82 		 *
    98 		 *
    83 		 * @since 3.1.0
    99 		 * @since 3.1.0
    84 		 *
   100 		 *
    85 		 * @param array $dashboard_widgets An array of dashboard widgets.
   101 		 * @param array $dashboard_widgets An array of dashboard widgets.
    86 		 */
   102 		 */
    93 		 * @since 2.5.0
   109 		 * @since 2.5.0
    94 		 */
   110 		 */
    95 		do_action( 'wp_dashboard_setup' );
   111 		do_action( 'wp_dashboard_setup' );
    96 
   112 
    97 		/**
   113 		/**
    98 		 * Filter the list of widgets to load for the admin dashboard.
   114 		 * Filters the list of widgets to load for the admin dashboard.
    99 		 *
   115 		 *
   100 		 * @since 2.5.0
   116 		 * @since 2.5.0
   101 		 *
   117 		 *
   102 		 * @param array $dashboard_widgets An array of dashboard widgets.
   118 		 * @param array $dashboard_widgets An array of dashboard widgets.
   103 		 */
   119 		 */
   123 
   139 
   124 	/** This action is documented in wp-admin/edit-form-advanced.php */
   140 	/** This action is documented in wp-admin/edit-form-advanced.php */
   125 	do_action( 'do_meta_boxes', $screen->id, 'side', '' );
   141 	do_action( 'do_meta_boxes', $screen->id, 'side', '' );
   126 }
   142 }
   127 
   143 
       
   144 /**
       
   145  * Adds a new dashboard widget.
       
   146  *
       
   147  * @since 2.7.0
       
   148  *
       
   149  * @global array $wp_dashboard_control_callbacks
       
   150  *
       
   151  * @param string   $widget_id        Widget ID  (used in the 'id' attribute for the widget).
       
   152  * @param string   $widget_name      Title of the widget.
       
   153  * @param callable $callback         Function that fills the widget with the desired content.
       
   154  *                                   The function should echo its output.
       
   155  * @param callable $control_callback Optional. Function that outputs controls for the widget. Default null.
       
   156  * @param array    $callback_args    Optional. Data that should be set as the $args property of the widget array
       
   157  *                                   (which is the second parameter passed to your callback). Default null.
       
   158  */
   128 function wp_add_dashboard_widget( $widget_id, $widget_name, $callback, $control_callback = null, $callback_args = null ) {
   159 function wp_add_dashboard_widget( $widget_id, $widget_name, $callback, $control_callback = null, $callback_args = null ) {
   129 	$screen = get_current_screen();
   160 	$screen = get_current_screen();
   130 	global $wp_dashboard_control_callbacks;
   161 	global $wp_dashboard_control_callbacks;
       
   162 
       
   163 	$private_callback_args = array( '__widget_basename' => $widget_name );
       
   164 
       
   165 	if ( is_null( $callback_args ) ) {
       
   166 		$callback_args = $private_callback_args;
       
   167 	} else if ( is_array( $callback_args ) ) {
       
   168 		$callback_args = array_merge( $callback_args, $private_callback_args );
       
   169 	}
   131 
   170 
   132 	if ( $control_callback && current_user_can( 'edit_dashboard' ) && is_callable( $control_callback ) ) {
   171 	if ( $control_callback && current_user_can( 'edit_dashboard' ) && is_callable( $control_callback ) ) {
   133 		$wp_dashboard_control_callbacks[$widget_id] = $control_callback;
   172 		$wp_dashboard_control_callbacks[$widget_id] = $control_callback;
   134 		if ( isset( $_GET['edit'] ) && $widget_id == $_GET['edit'] ) {
   173 		if ( isset( $_GET['edit'] ) && $widget_id == $_GET['edit'] ) {
   135 			list($url) = explode( '#', add_query_arg( 'edit', false ), 2 );
   174 			list($url) = explode( '#', add_query_arg( 'edit', false ), 2 );
   152 		$priority = 'high';
   191 		$priority = 'high';
   153 
   192 
   154 	add_meta_box( $widget_id, $widget_name, $callback, $screen, $location, $priority, $callback_args );
   193 	add_meta_box( $widget_id, $widget_name, $callback, $screen, $location, $priority, $callback_args );
   155 }
   194 }
   156 
   195 
       
   196 /**
       
   197  * Outputs controls for the current dashboard widget.
       
   198  *
       
   199  * @access private
       
   200  * @since 2.7.0
       
   201  *
       
   202  * @param mixed $dashboard
       
   203  * @param array $meta_box
       
   204  */
   157 function _wp_dashboard_control_callback( $dashboard, $meta_box ) {
   205 function _wp_dashboard_control_callback( $dashboard, $meta_box ) {
   158 	echo '<form method="post" class="dashboard-widget-control-form">';
   206 	echo '<form method="post" class="dashboard-widget-control-form wp-clearfix">';
   159 	wp_dashboard_trigger_widget_control( $meta_box['id'] );
   207 	wp_dashboard_trigger_widget_control( $meta_box['id'] );
   160 	wp_nonce_field( 'edit-dashboard-widget_' . $meta_box['id'], 'dashboard-widget-nonce' );
   208 	wp_nonce_field( 'edit-dashboard-widget_' . $meta_box['id'], 'dashboard-widget-nonce' );
   161 	echo '<input type="hidden" name="widget_id" value="' . esc_attr($meta_box['id']) . '" />';
   209 	echo '<input type="hidden" name="widget_id" value="' . esc_attr($meta_box['id']) . '" />';
   162 	submit_button( __('Submit') );
   210 	submit_button( __('Submit') );
   163 	echo '</form>';
   211 	echo '</form>';
   233 
   281 
   234 		}
   282 		}
   235 	}
   283 	}
   236 	// Comments
   284 	// Comments
   237 	$num_comm = wp_count_comments();
   285 	$num_comm = wp_count_comments();
   238 	if ( $num_comm && $num_comm->approved ) {
   286 	if ( $num_comm && ( $num_comm->approved || $num_comm->moderated ) ) {
   239 		$text = sprintf( _n( '%s Comment', '%s Comments', $num_comm->approved ), number_format_i18n( $num_comm->approved ) );
   287 		$text = sprintf( _n( '%s Comment', '%s Comments', $num_comm->approved ), number_format_i18n( $num_comm->approved ) );
   240 		?>
   288 		?>
   241 		<li class="comment-count"><a href="edit-comments.php"><?php echo $text; ?></a></li>
   289 		<li class="comment-count"><a href="edit-comments.php"><?php echo $text; ?></a></li>
   242 		<?php
   290 		<?php
   243 		if ( $num_comm->moderated ) {
   291 		$moderated_comments_count_i18n = number_format_i18n( $num_comm->moderated );
   244 			/* translators: Number of comments in moderation */
   292 		/* translators: %s: number of comments in moderation */
   245 			$text = sprintf( _nx( '%s in moderation', '%s in moderation', $num_comm->moderated, 'comments' ), number_format_i18n( $num_comm->moderated ) );
   293 		$text = sprintf( _nx( '%s in moderation', '%s in moderation', $num_comm->moderated, 'comments' ), $moderated_comments_count_i18n );
   246 			?>
   294 		/* translators: %s: number of comments in moderation */
   247 			<li class="comment-mod-count"><a href="edit-comments.php?comment_status=moderated"><?php echo $text; ?></a></li>
   295 		$aria_label = sprintf( _nx( '%s comment in moderation', '%s comments in moderation', $num_comm->moderated, 'comments' ), $moderated_comments_count_i18n );
   248 			<?php
   296 		?>
   249 		}
   297 		<li class="comment-mod-count<?php
       
   298 			if ( ! $num_comm->moderated ) {
       
   299 				echo ' hidden';
       
   300 			}
       
   301 		?>"><a href="edit-comments.php?comment_status=moderated" aria-label="<?php esc_attr_e( $aria_label ); ?>"><?php echo $text; ?></a></li>
       
   302 		<?php
   250 	}
   303 	}
   251 
   304 
   252 	/**
   305 	/**
   253 	 * Filter the array of extra elements to list in the 'At a Glance'
   306 	 * Filters the array of extra elements to list in the 'At a Glance'
   254 	 * dashboard widget.
   307 	 * dashboard widget.
   255 	 *
   308 	 *
   256 	 * Prior to 3.8.0, the widget was named 'Right Now'. Each element
   309 	 * Prior to 3.8.0, the widget was named 'Right Now'. Each element
   257 	 * is wrapped in list-item tags on output.
   310 	 * is wrapped in list-item tags on output.
   258 	 *
   311 	 *
   270 	</ul>
   323 	</ul>
   271 	<?php
   324 	<?php
   272 	update_right_now_message();
   325 	update_right_now_message();
   273 
   326 
   274 	// Check if search engines are asked not to index this site.
   327 	// Check if search engines are asked not to index this site.
   275 	if ( ! is_network_admin() && ! is_user_admin() && current_user_can( 'manage_options' ) && '1' != get_option( 'blog_public' ) ) {
   328 	if ( ! is_network_admin() && ! is_user_admin() && current_user_can( 'manage_options' ) && '0' == get_option( 'blog_public' ) ) {
   276 
   329 
   277 		/**
   330 		/**
   278 		 * Filter the link title attribute for the 'Search Engines Discouraged'
   331 		 * Filters the link title attribute for the 'Search Engines Discouraged'
   279 		 * message displayed in the 'At a Glance' dashboard widget.
   332 		 * message displayed in the 'At a Glance' dashboard widget.
   280 		 *
   333 		 *
   281 		 * Prior to 3.8.0, the widget was named 'Right Now'.
   334 		 * Prior to 3.8.0, the widget was named 'Right Now'.
   282 		 *
   335 		 *
   283 		 * @since 3.0.0
   336 		 * @since 3.0.0
       
   337 		 * @since 4.5.0 The default for `$title` was updated to an empty string.
   284 		 *
   338 		 *
   285 		 * @param string $title Default attribute text.
   339 		 * @param string $title Default attribute text.
   286 		 */
   340 		 */
   287 		$title = apply_filters( 'privacy_on_link_title', __( 'Your site is asking search engines not to index its content' ) );
   341 		$title = apply_filters( 'privacy_on_link_title', '' );
   288 
   342 
   289 		/**
   343 		/**
   290 		 * Filter the link label for the 'Search Engines Discouraged' message
   344 		 * Filters the link label for the 'Search Engines Discouraged' message
   291 		 * displayed in the 'At a Glance' dashboard widget.
   345 		 * displayed in the 'At a Glance' dashboard widget.
   292 		 *
   346 		 *
   293 		 * Prior to 3.8.0, the widget was named 'Right Now'.
   347 		 * Prior to 3.8.0, the widget was named 'Right Now'.
   294 		 *
   348 		 *
   295 		 * @since 3.0.0
   349 		 * @since 3.0.0
   296 		 *
   350 		 *
   297 		 * @param string $content Default text.
   351 		 * @param string $content Default text.
   298 		 */
   352 		 */
   299 		$content = apply_filters( 'privacy_on_link_text' , __( 'Search Engines Discouraged' ) );
   353 		$content = apply_filters( 'privacy_on_link_text' , __( 'Search Engines Discouraged' ) );
   300 
   354 		$title_attr = '' === $title ? '' : " title='$title'";
   301 		echo "<p><a href='options-reading.php' title='$title'>$content</a></p>";
   355 
       
   356 		echo "<p><a href='options-reading.php'$title_attr>$content</a></p>";
   302 	}
   357 	}
   303 	?>
   358 	?>
   304 	</div>
   359 	</div>
   305 	<?php
   360 	<?php
   306 	/*
   361 	/*
   334 		<?php echo $actions; ?>
   389 		<?php echo $actions; ?>
   335 	</div>
   390 	</div>
   336 	<?php endif;
   391 	<?php endif;
   337 }
   392 }
   338 
   393 
       
   394 /**
       
   395  * @since 3.1.0
       
   396  */
   339 function wp_network_dashboard_right_now() {
   397 function wp_network_dashboard_right_now() {
   340 	$actions = array();
   398 	$actions = array();
   341 	if ( current_user_can('create_sites') )
   399 	if ( current_user_can('create_sites') )
   342 		$actions['create-site'] = '<a href="' . network_admin_url('site-new.php') . '">' . __( 'Create a New Site' ) . '</a>';
   400 		$actions['create-site'] = '<a href="' . network_admin_url('site-new.php') . '">' . __( 'Create a New Site' ) . '</a>';
   343 	if ( current_user_can('create_users') )
   401 	if ( current_user_can('create_users') )
   344 		$actions['create-user'] = '<a href="' . network_admin_url('user-new.php') . '">' . __( 'Create a New User' ) . '</a>';
   402 		$actions['create-user'] = '<a href="' . network_admin_url('user-new.php') . '">' . __( 'Create a New User' ) . '</a>';
   345 
   403 
   346 	$c_users = get_user_count();
   404 	$c_users = get_user_count();
   347 	$c_blogs = get_blog_count();
   405 	$c_blogs = get_blog_count();
   348 
   406 
       
   407 	/* translators: %s: number of users on the network */
   349 	$user_text = sprintf( _n( '%s user', '%s users', $c_users ), number_format_i18n( $c_users ) );
   408 	$user_text = sprintf( _n( '%s user', '%s users', $c_users ), number_format_i18n( $c_users ) );
       
   409 	/* translators: %s: number of sites on the network */
   350 	$blog_text = sprintf( _n( '%s site', '%s sites', $c_blogs ), number_format_i18n( $c_blogs ) );
   410 	$blog_text = sprintf( _n( '%s site', '%s sites', $c_blogs ), number_format_i18n( $c_blogs ) );
   351 
   411 
       
   412 	/* translators: 1: text indicating the number of sites on the network, 2: text indicating the number of users on the network */
   352 	$sentence = sprintf( __( 'You have %1$s and %2$s.' ), $blog_text, $user_text );
   413 	$sentence = sprintf( __( 'You have %1$s and %2$s.' ), $blog_text, $user_text );
   353 
   414 
   354 	if ( $actions ) {
   415 	if ( $actions ) {
   355 		echo '<ul class="subsubsub">';
   416 		echo '<ul class="subsubsub">';
   356 		foreach ( $actions as $class => $action ) {
   417 		foreach ( $actions as $class => $action ) {
   368 	<?php
   429 	<?php
   369 		/**
   430 		/**
   370 		 * Fires in the Network Admin 'Right Now' dashboard widget
   431 		 * Fires in the Network Admin 'Right Now' dashboard widget
   371 		 * just before the user and site search form fields.
   432 		 * just before the user and site search form fields.
   372 		 *
   433 		 *
   373 		 * @since MU
   434 		 * @since MU (3.0.0)
   374 		 *
   435 		 *
   375 		 * @param null $unused
   436 		 * @param null $unused
   376 		 */
   437 		 */
   377 		do_action( 'wpmuadminresult', '' );
   438 		do_action( 'wpmuadminresult', '' );
   378 	?>
   439 	?>
   379 
   440 
   380 	<form action="<?php echo network_admin_url('users.php'); ?>" method="get">
   441 	<form action="<?php echo network_admin_url('users.php'); ?>" method="get">
   381 		<p>
   442 		<p>
   382 			<label class="screen-reader-text" for="search-users"><?php _e( 'Search Users' ); ?></label>
   443 			<label class="screen-reader-text" for="search-users"><?php _e( 'Search Users' ); ?></label>
   383 			<input type="search" name="s" value="" size="30" autocomplete="off" id="search-users"/>
   444 			<input type="search" name="s" value="" size="30" autocomplete="off" id="search-users"/>
   384 			<?php submit_button( __( 'Search Users' ), 'button', 'submit', false, array( 'id' => 'submit_users' ) ); ?>
   445 			<?php submit_button( __( 'Search Users' ), '', false, false, array( 'id' => 'submit_users' ) ); ?>
   385 		</p>
   446 		</p>
   386 	</form>
   447 	</form>
   387 
   448 
   388 	<form action="<?php echo network_admin_url('sites.php'); ?>" method="get">
   449 	<form action="<?php echo network_admin_url('sites.php'); ?>" method="get">
   389 		<p>
   450 		<p>
   390 			<label class="screen-reader-text" for="search-sites"><?php _e( 'Search Sites' ); ?></label>
   451 			<label class="screen-reader-text" for="search-sites"><?php _e( 'Search Sites' ); ?></label>
   391 			<input type="search" name="s" value="" size="30" autocomplete="off" id="search-sites"/>
   452 			<input type="search" name="s" value="" size="30" autocomplete="off" id="search-sites"/>
   392 			<?php submit_button( __( 'Search Sites' ), 'button', 'submit', false, array( 'id' => 'submit_sites' ) ); ?>
   453 			<?php submit_button( __( 'Search Sites' ), '', false, false, array( 'id' => 'submit_sites' ) ); ?>
   393 		</p>
   454 		</p>
   394 	</form>
   455 	</form>
   395 <?php
   456 <?php
   396 	/**
   457 	/**
   397 	 * Fires at the end of the 'Right Now' widget in the Network Admin dashboard.
   458 	 * Fires at the end of the 'Right Now' widget in the Network Admin dashboard.
   398 	 *
   459 	 *
   399 	 * @since MU
   460 	 * @since MU (3.0.0)
   400 	 */
   461 	 */
   401 	do_action( 'mu_rightnow_end' );
   462 	do_action( 'mu_rightnow_end' );
   402 
   463 
   403 	/**
   464 	/**
   404 	 * Fires at the end of the 'Right Now' widget in the Network Admin dashboard.
   465 	 * Fires at the end of the 'Right Now' widget in the Network Admin dashboard.
   405 	 *
   466 	 *
   406 	 * @since MU
   467 	 * @since MU (3.0.0)
   407 	 */
   468 	 */
   408 	do_action( 'mu_activity_box_end' );
   469 	do_action( 'mu_activity_box_end' );
   409 }
   470 }
   410 
   471 
   411 /**
   472 /**
   412  * The Quick Draft widget display and creation of drafts.
   473  * The Quick Draft widget display and creation of drafts.
   413  *
   474  *
   414  * @since 3.8.0
   475  * @since 3.8.0
   415  *
   476  *
       
   477  * @global int $post_ID
       
   478  *
   416  * @param string $error_msg Optional. Error message. Default false.
   479  * @param string $error_msg Optional. Error message. Default false.
   417  */
   480  */
   418 function wp_dashboard_quick_press( $error_msg = false ) {
   481 function wp_dashboard_quick_press( $error_msg = false ) {
   419 	global $post_ID;
   482 	global $post_ID;
       
   483 
       
   484 	if ( ! current_user_can( 'edit_posts' ) ) {
       
   485 		return;
       
   486 	}
   420 
   487 
   421 	/* Check if a new auto-draft (= no new post_ID) is needed or if the old can be used */
   488 	/* Check if a new auto-draft (= no new post_ID) is needed or if the old can be used */
   422 	$last_post_id = (int) get_user_option( 'dashboard_quick_press_last_post_id' ); // Get the last post_ID
   489 	$last_post_id = (int) get_user_option( 'dashboard_quick_press_last_post_id' ); // Get the last post_ID
   423 	if ( $last_post_id ) {
   490 	if ( $last_post_id ) {
   424 		$post = get_post( $last_post_id );
   491 		$post = get_post( $last_post_id );
   430 		}
   497 		}
   431 	} else {
   498 	} else {
   432 		$post = get_default_post_to_edit( 'post' , true);
   499 		$post = get_default_post_to_edit( 'post' , true);
   433 		$user_id = get_current_user_id();
   500 		$user_id = get_current_user_id();
   434 		// Don't create an option if this is a super admin who does not belong to this site.
   501 		// Don't create an option if this is a super admin who does not belong to this site.
   435 		if ( ! ( is_super_admin( $user_id ) && ! in_array( get_current_blog_id(), array_keys( get_blogs_of_user( $user_id ) ) ) ) )
   502 		if ( in_array( get_current_blog_id(), array_keys( get_blogs_of_user( $user_id ) ) ) )
   436 			update_user_option( $user_id, 'dashboard_quick_press_last_post_id', (int) $post->ID ); // Save post_ID
   503 			update_user_option( $user_id, 'dashboard_quick_press_last_post_id', (int) $post->ID ); // Save post_ID
   437 	}
   504 	}
   438 
   505 
   439 	$post_ID = (int) $post->ID;
   506 	$post_ID = (int) $post->ID;
   440 ?>
   507 ?>
   477 
   544 
   478 /**
   545 /**
   479  * Show recent drafts of the user on the dashboard.
   546  * Show recent drafts of the user on the dashboard.
   480  *
   547  *
   481  * @since 2.7.0
   548  * @since 2.7.0
       
   549  *
       
   550  * @param array $drafts
   482  */
   551  */
   483 function wp_dashboard_recent_drafts( $drafts = false ) {
   552 function wp_dashboard_recent_drafts( $drafts = false ) {
   484 	if ( ! $drafts ) {
   553 	if ( ! $drafts ) {
   485 		$query_args = array(
   554 		$query_args = array(
   486 			'post_type'      => 'post',
   555 			'post_type'      => 'post',
   488 			'author'         => get_current_user_id(),
   557 			'author'         => get_current_user_id(),
   489 			'posts_per_page' => 4,
   558 			'posts_per_page' => 4,
   490 			'orderby'        => 'modified',
   559 			'orderby'        => 'modified',
   491 			'order'          => 'DESC'
   560 			'order'          => 'DESC'
   492 		);
   561 		);
       
   562 
       
   563 		/**
       
   564 		 * Filters the post query arguments for the 'Recent Drafts' dashboard widget.
       
   565 		 *
       
   566 		 * @since 4.4.0
       
   567 		 *
       
   568 		 * @param array $query_args The query arguments for the 'Recent Drafts' dashboard widget.
       
   569 		 */
       
   570 		$query_args = apply_filters( 'dashboard_recent_drafts_query_args', $query_args );
       
   571 
   493 		$drafts = get_posts( $query_args );
   572 		$drafts = get_posts( $query_args );
   494 		if ( ! $drafts ) {
   573 		if ( ! $drafts ) {
   495 			return;
   574 			return;
   496  		}
   575  		}
   497  	}
   576  	}
   498 
   577 
   499 	echo '<div class="drafts">';
   578 	echo '<div class="drafts">';
   500 	if ( count( $drafts ) > 3 ) {
   579 	if ( count( $drafts ) > 3 ) {
   501 		echo '<p class="view-all"><a href="' . esc_url( admin_url( 'edit.php?post_status=draft' ) ) . '">' . _x( 'View all', 'drafts' ) . "</a></p>\n";
   580 		echo '<p class="view-all"><a href="' . esc_url( admin_url( 'edit.php?post_status=draft' ) ) . '">' . __( 'View all drafts' ) . "</a></p>\n";
   502  	}
   581  	}
   503 	echo '<h4 class="hide-if-no-js">' . __( 'Drafts' ) . "</h4>\n<ul>";
   582 	echo '<h2 class="hide-if-no-js">' . __( 'Your Recent Drafts' ) . "</h2>\n<ul>";
   504 
   583 
   505 	$drafts = array_slice( $drafts, 0, 3 );
   584 	$drafts = array_slice( $drafts, 0, 3 );
   506 	foreach ( $drafts as $draft ) {
   585 	foreach ( $drafts as $draft ) {
   507 		$url = get_edit_post_link( $draft->ID );
   586 		$url = get_edit_post_link( $draft->ID );
   508 		$title = _draft_or_post_title( $draft->ID );
   587 		$title = _draft_or_post_title( $draft->ID );
   509 		echo "<li>\n";
   588 		echo "<li>\n";
   510 		echo '<div class="draft-title"><a href="' . esc_url( $url ) . '" title="' . esc_attr( sprintf( __( 'Edit &#8220;%s&#8221;' ), $title ) ) . '">' . esc_html( $title ) . '</a>';
   589 		/* translators: %s: post title */
   511 		echo '<time datetime="' . get_the_time( 'c', $draft ) . '">' . get_the_time( get_option( 'date_format' ), $draft ) . '</time></div>';
   590 		echo '<div class="draft-title"><a href="' . esc_url( $url ) . '" aria-label="' . esc_attr( sprintf( __( 'Edit &#8220;%s&#8221;' ), $title ) ) . '">' . esc_html( $title ) . '</a>';
       
   591 		echo '<time datetime="' . get_the_time( 'c', $draft ) . '">' . get_the_time( __( 'F j, Y' ), $draft ) . '</time></div>';
   512 		if ( $the_content = wp_trim_words( $draft->post_content, 10 ) ) {
   592 		if ( $the_content = wp_trim_words( $draft->post_content, 10 ) ) {
   513 			echo '<p>' . $the_content . '</p>';
   593 			echo '<p>' . $the_content . '</p>';
   514  		}
   594  		}
   515 		echo "</li>\n";
   595 		echo "</li>\n";
   516  	}
   596  	}
   517 	echo "</ul>\n</div>";
   597 	echo "</ul>\n</div>";
   518 }
   598 }
   519 
   599 
       
   600 /**
       
   601  * Outputs a row for the Recent Comments widget.
       
   602  *
       
   603  * @access private
       
   604  * @since 2.7.0
       
   605  *
       
   606  * @global WP_Comment $comment
       
   607  *
       
   608  * @param WP_Comment $comment   The current comment.
       
   609  * @param bool       $show_date Optional. Whether to display the date.
       
   610  */
   520 function _wp_dashboard_recent_comments_row( &$comment, $show_date = true ) {
   611 function _wp_dashboard_recent_comments_row( &$comment, $show_date = true ) {
   521 	$GLOBALS['comment'] =& $comment;
   612 	$GLOBALS['comment'] = clone $comment;
   522 
   613 
   523 	$comment_post_title = _draft_or_post_title( $comment->comment_post_ID );
   614 	if ( $comment->comment_post_ID > 0 ) {
   524 
   615 
   525 	if ( current_user_can( 'edit_post', $comment->comment_post_ID ) ) {
   616 		$comment_post_title = _draft_or_post_title( $comment->comment_post_ID );
   526 		$comment_post_url = get_edit_post_link( $comment->comment_post_ID );
   617 		$comment_post_url = get_the_permalink( $comment->comment_post_ID );
   527 		$comment_post_link = "<a href='$comment_post_url'>$comment_post_title</a>";
   618 		$comment_post_link = "<a href='$comment_post_url'>$comment_post_title</a>";
   528 	} else {
   619 	} else {
   529 		$comment_post_link = $comment_post_title;
   620 		$comment_post_link = '';
   530 	}
   621 	}
   531 
       
   532 	$comment_link = '<a class="comment-link" href="' . esc_url(get_comment_link()) . '">#</a>';
       
   533 
   622 
   534 	$actions_string = '';
   623 	$actions_string = '';
   535 	if ( current_user_can( 'edit_comment', $comment->comment_ID ) ) {
   624 	if ( current_user_can( 'edit_comment', $comment->comment_ID ) ) {
   536 		// Pre-order it: Approve | Reply | Edit | Spam | Trash.
   625 		// Pre-order it: Approve | Reply | Edit | Spam | Trash.
   537 		$actions = array(
   626 		$actions = array(
   538 			'approve' => '', 'unapprove' => '',
   627 			'approve' => '', 'unapprove' => '',
   539 			'reply' => '',
   628 			'reply' => '',
   540 			'edit' => '',
   629 			'edit' => '',
   541 			'spam' => '',
   630 			'spam' => '',
   542 			'trash' => '', 'delete' => ''
   631 			'trash' => '', 'delete' => '',
       
   632 			'view' => '',
   543 		);
   633 		);
   544 
   634 
   545 		$del_nonce = esc_html( '_wpnonce=' . wp_create_nonce( "delete-comment_$comment->comment_ID" ) );
   635 		$del_nonce = esc_html( '_wpnonce=' . wp_create_nonce( "delete-comment_$comment->comment_ID" ) );
   546 		$approve_nonce = esc_html( '_wpnonce=' . wp_create_nonce( "approve-comment_$comment->comment_ID" ) );
   636 		$approve_nonce = esc_html( '_wpnonce=' . wp_create_nonce( "approve-comment_$comment->comment_ID" ) );
   547 
   637 
   549 		$unapprove_url = esc_url( "comment.php?action=unapprovecomment&p=$comment->comment_post_ID&c=$comment->comment_ID&$approve_nonce" );
   639 		$unapprove_url = esc_url( "comment.php?action=unapprovecomment&p=$comment->comment_post_ID&c=$comment->comment_ID&$approve_nonce" );
   550 		$spam_url = esc_url( "comment.php?action=spamcomment&p=$comment->comment_post_ID&c=$comment->comment_ID&$del_nonce" );
   640 		$spam_url = esc_url( "comment.php?action=spamcomment&p=$comment->comment_post_ID&c=$comment->comment_ID&$del_nonce" );
   551 		$trash_url = esc_url( "comment.php?action=trashcomment&p=$comment->comment_post_ID&c=$comment->comment_ID&$del_nonce" );
   641 		$trash_url = esc_url( "comment.php?action=trashcomment&p=$comment->comment_post_ID&c=$comment->comment_ID&$del_nonce" );
   552 		$delete_url = esc_url( "comment.php?action=deletecomment&p=$comment->comment_post_ID&c=$comment->comment_ID&$del_nonce" );
   642 		$delete_url = esc_url( "comment.php?action=deletecomment&p=$comment->comment_post_ID&c=$comment->comment_ID&$del_nonce" );
   553 
   643 
   554 		$actions['approve'] = "<a href='$approve_url' data-wp-lists='dim:the-comment-list:comment-$comment->comment_ID:unapproved:e7e7d3:e7e7d3:new=approved' class='vim-a' title='" . esc_attr__( 'Approve this comment' ) . "'>" . __( 'Approve' ) . '</a>';
   644 		$actions['approve'] = "<a href='$approve_url' data-wp-lists='dim:the-comment-list:comment-$comment->comment_ID:unapproved:e7e7d3:e7e7d3:new=approved' class='vim-a' aria-label='" . esc_attr__( 'Approve this comment' ) . "'>" . __( 'Approve' ) . '</a>';
   555 		$actions['unapprove'] = "<a href='$unapprove_url' data-wp-lists='dim:the-comment-list:comment-$comment->comment_ID:unapproved:e7e7d3:e7e7d3:new=unapproved' class='vim-u' title='" . esc_attr__( 'Unapprove this comment' ) . "'>" . __( 'Unapprove' ) . '</a>';
   645 		$actions['unapprove'] = "<a href='$unapprove_url' data-wp-lists='dim:the-comment-list:comment-$comment->comment_ID:unapproved:e7e7d3:e7e7d3:new=unapproved' class='vim-u' aria-label='" . esc_attr__( 'Unapprove this comment' ) . "'>" . __( 'Unapprove' ) . '</a>';
   556 		$actions['edit'] = "<a href='comment.php?action=editcomment&amp;c={$comment->comment_ID}' title='" . esc_attr__('Edit comment') . "'>". __('Edit') . '</a>';
   646 		$actions['edit'] = "<a href='comment.php?action=editcomment&amp;c={$comment->comment_ID}' aria-label='" . esc_attr__( 'Edit this comment' ) . "'>". __( 'Edit' ) . '</a>';
   557 		$actions['reply'] = '<a onclick="window.commentReply && commentReply.open(\''.$comment->comment_ID.'\',\''.$comment->comment_post_ID.'\');return false;" class="vim-r hide-if-no-js" title="'.esc_attr__('Reply to this comment').'" href="#">' . __('Reply') . '</a>';
   647 		$actions['reply'] = '<a onclick="window.commentReply && commentReply.open(\'' . $comment->comment_ID . '\',\''.$comment->comment_post_ID.'\');return false;" class="vim-r hide-if-no-js" aria-label="' . esc_attr__( 'Reply to this comment' ) . '" href="#">' . __( 'Reply' ) . '</a>';
   558 		$actions['spam'] = "<a href='$spam_url' data-wp-lists='delete:the-comment-list:comment-$comment->comment_ID::spam=1' class='vim-s vim-destructive' title='" . esc_attr__( 'Mark this comment as spam' ) . "'>" . /* translators: mark as spam link */ _x( 'Spam', 'verb' ) . '</a>';
   648 		$actions['spam'] = "<a href='$spam_url' data-wp-lists='delete:the-comment-list:comment-$comment->comment_ID::spam=1' class='vim-s vim-destructive' aria-label='" . esc_attr__( 'Mark this comment as spam' ) . "'>" . /* translators: mark as spam link */ _x( 'Spam', 'verb' ) . '</a>';
   559 		if ( !EMPTY_TRASH_DAYS )
   649 
   560 			$actions['delete'] = "<a href='$delete_url' data-wp-lists='delete:the-comment-list:comment-$comment->comment_ID::trash=1' class='delete vim-d vim-destructive'>" . __('Delete Permanently') . '</a>';
   650 		if ( ! EMPTY_TRASH_DAYS ) {
   561 		else
   651 			$actions['delete'] = "<a href='$delete_url' data-wp-lists='delete:the-comment-list:comment-$comment->comment_ID::trash=1' class='delete vim-d vim-destructive' aria-label='" . esc_attr__( 'Delete this comment permanently' ) . "'>" . __( 'Delete Permanently' ) . '</a>';
   562 			$actions['trash'] = "<a href='$trash_url' data-wp-lists='delete:the-comment-list:comment-$comment->comment_ID::trash=1' class='delete vim-d vim-destructive' title='" . esc_attr__( 'Move this comment to the trash' ) . "'>" . _x('Trash', 'verb') . '</a>';
   652 		} else {
       
   653 			$actions['trash'] = "<a href='$trash_url' data-wp-lists='delete:the-comment-list:comment-$comment->comment_ID::trash=1' class='delete vim-d vim-destructive' aria-label='" . esc_attr__( 'Move this comment to the Trash' ) . "'>" . _x( 'Trash', 'verb' ) . '</a>';
       
   654 		}
       
   655 
       
   656 		$actions['view'] = '<a class="comment-link" href="' . esc_url( get_comment_link( $comment ) ) . '" aria-label="' . esc_attr__( 'View this comment' ) . '">' . __( 'View' ) . '</a>';
   563 
   657 
   564 		/**
   658 		/**
   565 		 * Filter the action links displayed for each comment in the 'Recent Comments'
   659 		 * Filters the action links displayed for each comment in the 'Recent Comments'
   566 		 * dashboard widget.
   660 		 * dashboard widget.
   567 		 *
   661 		 *
   568 		 * @since 2.6.0
   662 		 * @since 2.6.0
   569 		 *
   663 		 *
   570 		 * @param array  $actions An array of comment actions. Default actions include:
   664 		 * @param array      $actions An array of comment actions. Default actions include:
   571 		 *                        'Approve', 'Unapprove', 'Edit', 'Reply', 'Spam',
   665 		 *                            'Approve', 'Unapprove', 'Edit', 'Reply', 'Spam',
   572 		 *                        'Delete', and 'Trash'.
   666 		 *                            'Delete', and 'Trash'.
   573 		 * @param object $comment The comment object.
   667 		 * @param WP_Comment $comment The comment object.
   574 		 */
   668 		 */
   575 		$actions = apply_filters( 'comment_row_actions', array_filter($actions), $comment );
   669 		$actions = apply_filters( 'comment_row_actions', array_filter($actions), $comment );
   576 
   670 
   577 		$i = 0;
   671 		$i = 0;
   578 		foreach ( $actions as $action => $link ) {
   672 		foreach ( $actions as $action => $link ) {
   579 			++$i;
   673 			++$i;
   580 			( ( ('approve' == $action || 'unapprove' == $action) && 2 === $i ) || 1 === $i ) ? $sep = '' : $sep = ' | ';
   674 			( ( ('approve' == $action || 'unapprove' == $action) && 2 === $i ) || 1 === $i ) ? $sep = '' : $sep = ' | ';
   581 
   675 
   582 			// Reply and quickedit need a hide-if-no-js span
   676 			// Reply and quickedit need a hide-if-no-js span
   583 			if ( 'reply' == $action || 'quickedit' == $action )
   677 			if ( 'reply' == $action || 'quickedit' == $action ) {
   584 				$action .= ' hide-if-no-js';
   678 				$action .= ' hide-if-no-js';
   585 
   679 			}
       
   680 
       
   681 			if ( 'view' === $action && '1' !== $comment->comment_approved ) {
       
   682 				$action .= ' hidden';
       
   683 			}
   586 			$actions_string .= "<span class='$action'>$sep$link</span>";
   684 			$actions_string .= "<span class='$action'>$sep$link</span>";
   587 		}
   685 		}
   588 	}
   686 	}
   589 
       
   590 ?>
   687 ?>
   591 
   688 
   592 		<div id="comment-<?php echo $comment->comment_ID; ?>" <?php comment_class( array( 'comment-item', wp_get_comment_status($comment->comment_ID) ) ); ?>>
   689 		<li id="comment-<?php echo $comment->comment_ID; ?>" <?php comment_class( array( 'comment-item', wp_get_comment_status( $comment ) ), $comment ); ?>>
   593 
   690 
   594 			<?php echo get_avatar( $comment, 50, 'mystery' ); ?>
   691 			<?php echo get_avatar( $comment, 50, 'mystery' ); ?>
   595 
   692 
   596 			<?php if ( !$comment->comment_type || 'comment' == $comment->comment_type ) : ?>
   693 			<?php if ( !$comment->comment_type || 'comment' == $comment->comment_type ) : ?>
   597 
   694 
   598 			<div class="dashboard-comment-wrap">
   695 			<div class="dashboard-comment-wrap has-row-actions">
   599 			<h4 class="comment-meta">
   696 			<p class="comment-meta">
   600 				<?php printf( /* translators: 1: comment author, 2: post link, 3: notification if the comment is pending */__( 'From %1$s on %2$s%3$s' ),
   697 			<?php
   601 					'<cite class="comment-author">' . get_comment_author_link() . '</cite>', $comment_post_link.' '.$comment_link, ' <span class="approve">' . __( '[Pending]' ) . '</span>' ); ?>
   698 				// Comments might not have a post they relate to, e.g. programmatically created ones.
   602 			</h4>
   699 				if ( $comment_post_link ) {
       
   700 					printf(
       
   701 						/* translators: 1: comment author, 2: post link, 3: notification if the comment is pending */
       
   702 						__( 'From %1$s on %2$s %3$s' ),
       
   703 						'<cite class="comment-author">' . get_comment_author_link( $comment ) . '</cite>',
       
   704 						$comment_post_link,
       
   705 						'<span class="approve">' . __( '[Pending]' ) . '</span>'
       
   706 					);
       
   707 				} else {
       
   708 					printf(
       
   709 						/* translators: 1: comment author, 2: notification if the comment is pending */
       
   710 						__( 'From %1$s %2$s' ),
       
   711 						'<cite class="comment-author">' . get_comment_author_link( $comment ) . '</cite>',
       
   712 						'<span class="approve">' . __( '[Pending]' ) . '</span>'
       
   713 					);
       
   714 				}
       
   715 			?>
       
   716 			</p>
   603 
   717 
   604 			<?php
   718 			<?php
   605 			else :
   719 			else :
   606 				switch ( $comment->comment_type ) {
   720 				switch ( $comment->comment_type ) {
   607 					case 'pingback' :
   721 					case 'pingback' :
   613 					default :
   727 					default :
   614 						$type = ucwords( $comment->comment_type );
   728 						$type = ucwords( $comment->comment_type );
   615 				}
   729 				}
   616 				$type = esc_html( $type );
   730 				$type = esc_html( $type );
   617 			?>
   731 			?>
   618 			<div class="dashboard-comment-wrap">
   732 			<div class="dashboard-comment-wrap has-row-actions">
   619 			<?php /* translators: %1$s is type of comment, %2$s is link to the post */ ?>
   733 			<p class="comment-meta">
   620 			<h4 class="comment-meta"><?php printf( _x( '%1$s on %2$s', 'dashboard' ), "<strong>$type</strong>", $comment_post_link." ".$comment_link ); ?></h4>
   734 			<?php
   621 			<p class="comment-author"><?php comment_author_link(); ?></p>
   735 				// Pingbacks, Trackbacks or custom comment types might not have a post they relate to, e.g. programmatically created ones.
       
   736 				if ( $comment_post_link ) {
       
   737 					printf(
       
   738 						/* translators: 1: type of comment, 2: post link, 3: notification if the comment is pending */
       
   739 						_x( '%1$s on %2$s %3$s', 'dashboard' ),
       
   740 						"<strong>$type</strong>",
       
   741 						$comment_post_link,
       
   742 						'<span class="approve">' . __( '[Pending]' ) . '</span>'
       
   743 					);
       
   744 				} else {
       
   745 					printf(
       
   746 						/* translators: 1: type of comment, 2: notification if the comment is pending */
       
   747 						_x( '%1$s %2$s', 'dashboard' ),
       
   748 						"<strong>$type</strong>",
       
   749 						'<span class="approve">' . __( '[Pending]' ) . '</span>'
       
   750 					);
       
   751 				}
       
   752 			?>
       
   753 			</p>
       
   754 			<p class="comment-author"><?php comment_author_link( $comment ); ?></p>
   622 
   755 
   623 			<?php endif; // comment_type ?>
   756 			<?php endif; // comment_type ?>
   624 			<blockquote><p><?php comment_excerpt(); ?></p></blockquote>
   757 			<blockquote><p><?php comment_excerpt( $comment ); ?></p></blockquote>
       
   758 			<?php if ( $actions_string ) : ?>
   625 			<p class="row-actions"><?php echo $actions_string; ?></p>
   759 			<p class="row-actions"><?php echo $actions_string; ?></p>
       
   760 			<?php endif; ?>
   626 			</div>
   761 			</div>
   627 		</div>
   762 		</li>
   628 <?php
   763 <?php
       
   764 	$GLOBALS['comment'] = null;
   629 }
   765 }
   630 
   766 
   631 /**
   767 /**
   632  * Callback function for Activity widget.
   768  * Callback function for Activity widget.
   633  *
   769  *
   654 
   790 
   655 	$recent_comments = wp_dashboard_recent_comments();
   791 	$recent_comments = wp_dashboard_recent_comments();
   656 
   792 
   657 	if ( !$future_posts && !$recent_posts && !$recent_comments ) {
   793 	if ( !$future_posts && !$recent_posts && !$recent_comments ) {
   658 		echo '<div class="no-activity">';
   794 		echo '<div class="no-activity">';
   659 		echo '<p class="smiley"></p>';
   795 		echo '<p class="smiley" aria-hidden="true"></p>';
   660 		echo '<p>' . __( 'No activity yet!' ) . '</p>';
   796 		echo '<p>' . __( 'No activity yet!' ) . '</p>';
   661 		echo '</div>';
   797 		echo '</div>';
   662 	}
   798 	}
   663 
   799 
   664 	echo '</div>';
   800 	echo '</div>';
   691 		'cache_results'  => false,
   827 		'cache_results'  => false,
   692 		'perm'           => ( 'future' === $args['status'] ) ? 'editable' : 'readable',
   828 		'perm'           => ( 'future' === $args['status'] ) ? 'editable' : 'readable',
   693 	);
   829 	);
   694 
   830 
   695 	/**
   831 	/**
   696 	 * Filter the query arguments used for the Recent Posts widget.
   832 	 * Filters the query arguments used for the Recent Posts widget.
   697 	 *
   833 	 *
   698 	 * @since 4.2.0
   834 	 * @since 4.2.0
   699 	 *
   835 	 *
   700 	 * @param array $query_args The arguments passed to WP_Query to produce the list of posts.
   836 	 * @param array $query_args The arguments passed to WP_Query to produce the list of posts.
   701 	 */
   837 	 */
   704 
   840 
   705 	if ( $posts->have_posts() ) {
   841 	if ( $posts->have_posts() ) {
   706 
   842 
   707 		echo '<div id="' . $args['id'] . '" class="activity-block">';
   843 		echo '<div id="' . $args['id'] . '" class="activity-block">';
   708 
   844 
   709 		echo '<h4>' . $args['title'] . '</h4>';
   845 		echo '<h3>' . $args['title'] . '</h3>';
   710 
   846 
   711 		echo '<ul>';
   847 		echo '<ul>';
   712 
   848 
   713 		$today    = date( 'Y-m-d', current_time( 'timestamp' ) );
   849 		$today    = date( 'Y-m-d', current_time( 'timestamp' ) );
   714 		$tomorrow = date( 'Y-m-d', strtotime( '+1 day', current_time( 'timestamp' ) ) );
   850 		$tomorrow = date( 'Y-m-d', strtotime( '+1 day', current_time( 'timestamp' ) ) );
   719 			$time = get_the_time( 'U' );
   855 			$time = get_the_time( 'U' );
   720 			if ( date( 'Y-m-d', $time ) == $today ) {
   856 			if ( date( 'Y-m-d', $time ) == $today ) {
   721 				$relative = __( 'Today' );
   857 				$relative = __( 'Today' );
   722 			} elseif ( date( 'Y-m-d', $time ) == $tomorrow ) {
   858 			} elseif ( date( 'Y-m-d', $time ) == $tomorrow ) {
   723 				$relative = __( 'Tomorrow' );
   859 				$relative = __( 'Tomorrow' );
       
   860 			} elseif ( date( 'Y', $time ) !== date( 'Y', current_time( 'timestamp' ) ) ) {
       
   861 				/* translators: date and time format for recent posts on the dashboard, from a different calendar year, see https://secure.php.net/date */
       
   862 				$relative = date_i18n( __( 'M jS Y' ), $time );
   724 			} else {
   863 			} else {
   725 				/* translators: date and time format for recent posts on the dashboard, see http://php.net/date */
   864 				/* translators: date and time format for recent posts on the dashboard, see https://secure.php.net/date */
   726 				$relative = date_i18n( __( 'M jS' ), $time );
   865 				$relative = date_i18n( __( 'M jS' ), $time );
   727 			}
   866 			}
   728 
   867 
   729 			// Use the post edit link for those who can edit, the permalink otherwise.
   868 			// Use the post edit link for those who can edit, the permalink otherwise.
   730 			$recent_post_link = current_user_can( 'edit_post', get_the_ID() ) ? get_edit_post_link() : get_permalink();
   869 			$recent_post_link = current_user_can( 'edit_post', get_the_ID() ) ? get_edit_post_link() : get_permalink();
   731 
   870 
   732 			/* translators: 1: relative date, 2: time, 3: post edit link or permalink, 4: post title */
   871 			$draft_or_post_title = _draft_or_post_title();
   733 			$format = __( '<span>%1$s, %2$s</span> <a href="%3$s">%4$s</a>' );
   872 			printf(
   734 			printf( "<li>$format</li>", $relative, get_the_time(), $recent_post_link, _draft_or_post_title() );
   873 				'<li><span>%1$s</span> <a href="%2$s" aria-label="%3$s">%4$s</a></li>',
       
   874 				/* translators: 1: relative date, 2: time */
       
   875 				sprintf( _x( '%1$s, %2$s', 'dashboard' ), $relative, get_the_time() ),
       
   876 				$recent_post_link,
       
   877 				/* translators: %s: post title */
       
   878 				esc_attr( sprintf( __( 'Edit &#8220;%s&#8221;' ), $draft_or_post_title ) ),
       
   879 				$draft_or_post_title
       
   880 			);
   735 		}
   881 		}
   736 
   882 
   737 		echo '</ul>';
   883 		echo '</ul>';
   738 		echo '</div>';
   884 		echo '</div>';
   739 
   885 
   764 	);
   910 	);
   765 	if ( ! current_user_can( 'edit_posts' ) )
   911 	if ( ! current_user_can( 'edit_posts' ) )
   766 		$comments_query['status'] = 'approve';
   912 		$comments_query['status'] = 'approve';
   767 
   913 
   768 	while ( count( $comments ) < $total_items && $possible = get_comments( $comments_query ) ) {
   914 	while ( count( $comments ) < $total_items && $possible = get_comments( $comments_query ) ) {
       
   915 		if ( ! is_array( $possible ) ) {
       
   916 			break;
       
   917 		}
   769 		foreach ( $possible as $comment ) {
   918 		foreach ( $possible as $comment ) {
   770 			if ( ! current_user_can( 'read_post', $comment->comment_post_ID ) )
   919 			if ( ! current_user_can( 'read_post', $comment->comment_post_ID ) )
   771 				continue;
   920 				continue;
   772 			$comments[] = $comment;
   921 			$comments[] = $comment;
   773 			if ( count( $comments ) == $total_items )
   922 			if ( count( $comments ) == $total_items )
   777 		$comments_query['number'] = $total_items * 10;
   926 		$comments_query['number'] = $total_items * 10;
   778 	}
   927 	}
   779 
   928 
   780 	if ( $comments ) {
   929 	if ( $comments ) {
   781 		echo '<div id="latest-comments" class="activity-block">';
   930 		echo '<div id="latest-comments" class="activity-block">';
   782 		echo '<h4>' . __( 'Comments' ) . '</h4>';
   931 		echo '<h3>' . __( 'Recent Comments' ) . '</h3>';
   783 
   932 
   784 		echo '<div id="the-comment-list" data-wp-lists="list:comment">';
   933 		echo '<ul id="the-comment-list" data-wp-lists="list:comment">';
   785 		foreach ( $comments as $comment )
   934 		foreach ( $comments as $comment )
   786 			_wp_dashboard_recent_comments_row( $comment );
   935 			_wp_dashboard_recent_comments_row( $comment );
   787 		echo '</div>';
   936 		echo '</ul>';
   788 
   937 
   789 		if ( current_user_can('edit_posts') )
   938 		if ( current_user_can( 'edit_posts' ) ) {
   790 			_get_list_table('WP_Comments_List_Table')->views();
   939 			echo '<h3 class="screen-reader-text">' . __( 'View more comments' ) . '</h3>';
       
   940 			_get_list_table( 'WP_Comments_List_Table' )->views();
       
   941 		}
   791 
   942 
   792 		wp_comment_reply( -1, false, 'dashboard', false );
   943 		wp_comment_reply( -1, false, 'dashboard', false );
   793 		wp_comment_trashnotice();
   944 		wp_comment_trashnotice();
   794 
   945 
   795 		echo '</div>';
   946 		echo '</div>';
   817  * Checks to see if all of the feed url in $check_urls are cached.
   968  * Checks to see if all of the feed url in $check_urls are cached.
   818  *
   969  *
   819  * If $check_urls is empty, look for the rss feed url found in the dashboard
   970  * If $check_urls is empty, look for the rss feed url found in the dashboard
   820  * widget options of $widget_id. If cached, call $callback, a function that
   971  * widget options of $widget_id. If cached, call $callback, a function that
   821  * echoes out output for this widget. If not cache, echo a "Loading..." stub
   972  * echoes out output for this widget. If not cache, echo a "Loading..." stub
   822  * which is later replaced by AJAX call (see top of /wp-admin/index.php)
   973  * which is later replaced by Ajax call (see top of /wp-admin/index.php)
   823  *
   974  *
   824  * @since 2.5.0
   975  * @since 2.5.0
   825  *
   976  *
   826  * @param string $widget_id
   977  * @param string $widget_id
   827  * @param callback $callback
   978  * @param callable $callback
   828  * @param array $check_urls RSS feeds
   979  * @param array $check_urls RSS feeds
   829  * @return bool False on failure. True on success.
   980  * @return bool False on failure. True on success.
   830  */
   981  */
   831 function wp_dashboard_cached_rss_widget( $widget_id, $callback, $check_urls = array() ) {
   982 function wp_dashboard_cached_rss_widget( $widget_id, $callback, $check_urls = array() ) {
   832 	$loading = '<p class="widget-loading hide-if-no-js">' . __( 'Loading&#8230;' ) . '</p><p class="hide-if-js">' . __( 'This widget requires JavaScript.' ) . '</p>';
   983 	$loading = '<p class="widget-loading hide-if-no-js">' . __( 'Loading&#8230;' ) . '</p><div class="hide-if-js notice notice-error inline"><p>' . __( 'This widget requires JavaScript.' ) . '</p></div>';
   833 	$doing_ajax = ( defined('DOING_AJAX') && DOING_AJAX );
   984 	$doing_ajax = wp_doing_ajax();
   834 
   985 
   835 	if ( empty($check_urls) ) {
   986 	if ( empty($check_urls) ) {
   836 		$widgets = get_option( 'dashboard_widget_options' );
   987 		$widgets = get_option( 'dashboard_widget_options' );
   837 		if ( empty($widgets[$widget_id]['url']) && ! $doing_ajax ) {
   988 		if ( empty($widgets[$widget_id]['url']) && ! $doing_ajax ) {
   838 			echo $loading;
   989 			echo $loading;
   839 			return false;
   990 			return false;
   840 		}
   991 		}
   841 		$check_urls = array( $widgets[$widget_id]['url'] );
   992 		$check_urls = array( $widgets[$widget_id]['url'] );
   842 	}
   993 	}
   843 
   994 
   844 	$cache_key = 'dash_' . md5( $widget_id );
   995 	$locale = get_user_locale();
       
   996 	$cache_key = 'dash_v2_' . md5( $widget_id . '_' . $locale );
   845 	if ( false !== ( $output = get_transient( $cache_key ) ) ) {
   997 	if ( false !== ( $output = get_transient( $cache_key ) ) ) {
   846 		echo $output;
   998 		echo $output;
   847 		return true;
   999 		return true;
   848 	}
  1000 	}
   849 
  1001 
   861 	}
  1013 	}
   862 
  1014 
   863 	return true;
  1015 	return true;
   864 }
  1016 }
   865 
  1017 
   866 /* Dashboard Widgets Controls */
  1018 //
   867 
  1019 // Dashboard Widgets Controls
   868 // Calls widget_control callback
  1020 //
       
  1021 
   869 /**
  1022 /**
   870  * Calls widget control callback.
  1023  * Calls widget control callback.
   871  *
  1024  *
   872  * @since 2.5.0
  1025  * @since 2.5.0
       
  1026  *
       
  1027  * @global array $wp_dashboard_control_callbacks
   873  *
  1028  *
   874  * @param int $widget_control_id Registered Widget ID.
  1029  * @param int $widget_control_id Registered Widget ID.
   875  */
  1030  */
   876 function wp_dashboard_trigger_widget_control( $widget_control_id = false ) {
  1031 function wp_dashboard_trigger_widget_control( $widget_control_id = false ) {
   877 	global $wp_dashboard_control_callbacks;
  1032 	global $wp_dashboard_control_callbacks;
   917 				$rss->__destruct();
  1072 				$rss->__destruct();
   918 				unset($rss);
  1073 				unset($rss);
   919 			}
  1074 			}
   920 		}
  1075 		}
   921 		update_option( 'dashboard_widget_options', $widget_options );
  1076 		update_option( 'dashboard_widget_options', $widget_options );
   922 		$cache_key = 'dash_' . md5( $widget_id );
  1077 		$locale = get_user_locale();
       
  1078 		$cache_key = 'dash_v2_' . md5( $widget_id . '_' . $locale );
   923 		delete_transient( $cache_key );
  1079 		delete_transient( $cache_key );
   924 	}
  1080 	}
   925 
  1081 
   926 	wp_widget_rss_form( $widget_options[$widget_id], $form_inputs );
  1082 	wp_widget_rss_form( $widget_options[$widget_id], $form_inputs );
   927 }
  1083 }
   928 
  1084 
       
  1085 
       
  1086 /**
       
  1087  * Renders the Events and News dashboard widget.
       
  1088  *
       
  1089  * @since 4.8.0
       
  1090  */
       
  1091 function wp_dashboard_events_news() {
       
  1092 	wp_print_community_events_markup();
       
  1093 
       
  1094 	?>
       
  1095 
       
  1096 	<div class="wordpress-news hide-if-no-js">
       
  1097 		<?php wp_dashboard_primary(); ?>
       
  1098 	</div>
       
  1099 
       
  1100 	<p class="community-events-footer">
       
  1101 		<?php
       
  1102 			printf(
       
  1103 				'<a href="%1$s" target="_blank">%2$s <span class="screen-reader-text">%3$s</span><span aria-hidden="true" class="dashicons dashicons-external"></span></a>',
       
  1104 				'https://make.wordpress.org/community/meetups-landing-page',
       
  1105 				__( 'Meetups' ),
       
  1106 				/* translators: accessibility text */
       
  1107 				__( '(opens in a new window)' )
       
  1108 			);
       
  1109 		?>
       
  1110 
       
  1111 		|
       
  1112 
       
  1113 		<?php
       
  1114 			printf(
       
  1115 				'<a href="%1$s" target="_blank">%2$s <span class="screen-reader-text">%3$s</span><span aria-hidden="true" class="dashicons dashicons-external"></span></a>',
       
  1116 				'https://central.wordcamp.org/schedule/',
       
  1117 				__( 'WordCamps' ),
       
  1118 				/* translators: accessibility text */
       
  1119 				__( '(opens in a new window)' )
       
  1120 			);
       
  1121 		?>
       
  1122 
       
  1123 		|
       
  1124 
       
  1125 		<?php
       
  1126 			printf(
       
  1127 				'<a href="%1$s" target="_blank">%2$s <span class="screen-reader-text">%3$s</span><span aria-hidden="true" class="dashicons dashicons-external"></span></a>',
       
  1128 				/* translators: If a Rosetta site exists (e.g. https://es.wordpress.org/news/), then use that. Otherwise, leave untranslated. */
       
  1129 				esc_url( _x( 'https://wordpress.org/news/', 'Events and News dashboard widget' ) ),
       
  1130 				__( 'News' ),
       
  1131 				/* translators: accessibility text */
       
  1132 				__( '(opens in a new window)' )
       
  1133 			);
       
  1134 		?>
       
  1135 	</p>
       
  1136 
       
  1137 	<?php
       
  1138 }
       
  1139 
       
  1140 /**
       
  1141  * Prints the markup for the Community Events section of the Events and News Dashboard widget.
       
  1142  *
       
  1143  * @since 4.8.0
       
  1144  */
       
  1145 function wp_print_community_events_markup() {
       
  1146 	?>
       
  1147 
       
  1148 	<div class="community-events-errors notice notice-error inline hide-if-js">
       
  1149 		<p class="hide-if-js">
       
  1150 			<?php _e( 'This widget requires JavaScript.' ); ?>
       
  1151 		</p>
       
  1152 
       
  1153 		<p class="community-events-error-occurred" aria-hidden="true">
       
  1154 			<?php _e( 'An error occurred. Please try again.' ); ?>
       
  1155 		</p>
       
  1156 
       
  1157 		<p class="community-events-could-not-locate" aria-hidden="true"></p>
       
  1158 	</div>
       
  1159 
       
  1160 	<div class="community-events-loading hide-if-no-js">
       
  1161 		<?php _e( 'Loading&hellip;' ); ?>
       
  1162 	</div>
       
  1163 
       
  1164 	<?php
       
  1165 	/*
       
  1166 	 * Hide the main element when the page first loads, because the content
       
  1167 	 * won't be ready until wp.communityEvents.renderEventsTemplate() has run.
       
  1168 	 */
       
  1169 	?>
       
  1170 	<div id="community-events" class="community-events" aria-hidden="true">
       
  1171 		<div class="activity-block">
       
  1172 			<p>
       
  1173 				<span id="community-events-location-message"></span>
       
  1174 
       
  1175 				<button class="button-link community-events-toggle-location" aria-label="<?php esc_attr_e( 'Edit city' ); ?>" aria-expanded="false">
       
  1176 					<span class="dashicons dashicons-edit"></span>
       
  1177 				</button>
       
  1178 			</p>
       
  1179 
       
  1180 			<form class="community-events-form" aria-hidden="true" action="<?php echo esc_url( admin_url( 'admin-ajax.php' ) ); ?>" method="post">
       
  1181 				<label for="community-events-location">
       
  1182 					<?php _e( 'City:' ); ?>
       
  1183 				</label>
       
  1184 				<?php
       
  1185 				/* translators: Replace with a city related to your locale.
       
  1186 				 * Test that it matches the expected location and has upcoming
       
  1187 				 * events before including it. If no cities related to your
       
  1188 				 * locale have events, then use a city related to your locale
       
  1189 				 * that would be recognizable to most users. Use only the city
       
  1190 				 * name itself, without any region or country. Use the endonym
       
  1191 				 * (native locale name) instead of the English name if possible.
       
  1192 				 */
       
  1193 				?>
       
  1194 				<input id="community-events-location" class="regular-text" type="text" name="community-events-location" placeholder="<?php esc_attr_e( 'Cincinnati' ); ?>" />
       
  1195 
       
  1196 				<?php submit_button( __( 'Submit' ), 'secondary', 'community-events-submit', false ); ?>
       
  1197 
       
  1198 				<button class="community-events-cancel button-link" type="button" aria-expanded="false">
       
  1199 					<?php _e( 'Cancel' ); ?>
       
  1200 				</button>
       
  1201 
       
  1202 				<span class="spinner"></span>
       
  1203 			</form>
       
  1204 		</div>
       
  1205 
       
  1206 		<ul class="community-events-results activity-block last"></ul>
       
  1207 	</div>
       
  1208 
       
  1209 	<?php
       
  1210 }
       
  1211 
       
  1212 /**
       
  1213  * Renders the events templates for the Event and News widget.
       
  1214  *
       
  1215  * @since 4.8.0
       
  1216  */
       
  1217 function wp_print_community_events_templates() {
       
  1218 	?>
       
  1219 
       
  1220 	<script id="tmpl-community-events-attend-event-near" type="text/template">
       
  1221 		<?php printf(
       
  1222 			/* translators: %s: the name of a city */
       
  1223 			__( 'Attend an upcoming event near %s.' ),
       
  1224 			'<strong>{{ data.location.description }}</strong>'
       
  1225 		); ?>
       
  1226 	</script>
       
  1227 
       
  1228 	<script id="tmpl-community-events-could-not-locate" type="text/template">
       
  1229 		<?php printf(
       
  1230 			/* translators: %s is the name of the city we couldn't locate.
       
  1231 			 * Replace the examples with cities in your locale, but test
       
  1232 			 * that they match the expected location before including them.
       
  1233 			 * Use endonyms (native locale names) whenever possible.
       
  1234 			 */
       
  1235 			__( 'We couldn&#8217;t locate %s. Please try another nearby city. For example: Kansas City; Springfield; Portland.' ),
       
  1236 			'<em>{{data.unknownCity}}</em>'
       
  1237 		); ?>
       
  1238 	</script>
       
  1239 
       
  1240 	<script id="tmpl-community-events-event-list" type="text/template">
       
  1241 		<# _.each( data.events, function( event ) { #>
       
  1242 			<li class="event event-{{ event.type }} wp-clearfix">
       
  1243 				<div class="event-info">
       
  1244 					<div class="dashicons event-icon" aria-hidden="true"></div>
       
  1245 					<div class="event-info-inner">
       
  1246 						<a class="event-title" href="{{ event.url }}">{{ event.title }}</a>
       
  1247 						<span class="event-city">{{ event.location.location }}</span>
       
  1248 					</div>
       
  1249 				</div>
       
  1250 
       
  1251 				<div class="event-date-time">
       
  1252 					<span class="event-date">{{ event.formatted_date }}</span>
       
  1253 					<# if ( 'meetup' === event.type ) { #>
       
  1254 						<span class="event-time">{{ event.formatted_time }}</span>
       
  1255 					<# } #>
       
  1256 				</div>
       
  1257 			</li>
       
  1258 		<# } ) #>
       
  1259 	</script>
       
  1260 
       
  1261 	<script id="tmpl-community-events-no-upcoming-events" type="text/template">
       
  1262 		<li class="event-none">
       
  1263 			<# if ( data.location.description ) { #>
       
  1264 				<?php printf(
       
  1265 					/* translators: 1: the city the user searched for, 2: meetup organization documentation URL */
       
  1266 					__( 'There aren&#8217;t any events scheduled near %1$s at the moment. Would you like to <a href="%2$s">organize one</a>?' ),
       
  1267 					'{{ data.location.description }}',
       
  1268 					__( 'https://make.wordpress.org/community/handbook/meetup-organizer/welcome/' )
       
  1269 				); ?>
       
  1270 
       
  1271 			<# } else { #>
       
  1272 				<?php printf(
       
  1273 					/* translators: %s: meetup organization documentation URL */
       
  1274 					__( 'There aren&#8217;t any events scheduled near you at the moment. Would you like to <a href="%s">organize one</a>?' ),
       
  1275 					__( 'https://make.wordpress.org/community/handbook/meetup-organizer/welcome/' )
       
  1276 				); ?>
       
  1277 			<# } #>
       
  1278 		</li>
       
  1279 	</script>
       
  1280 	<?php
       
  1281 }
       
  1282 
   929 /**
  1283 /**
   930  * WordPress News dashboard widget.
  1284  * WordPress News dashboard widget.
   931  *
  1285  *
   932  * @since 2.7.0
  1286  * @since 2.7.0
       
  1287  * @since 4.8.0 Removed popular plugins feed.
   933  */
  1288  */
   934 function wp_dashboard_primary() {
  1289 function wp_dashboard_primary() {
   935 	$feeds = array(
  1290 	$feeds = array(
   936 		'news' => array(
  1291 		'news' => array(
   937 
  1292 
   938 			/**
  1293 			/**
   939 			 * Filter the primary link URL for the 'WordPress News' dashboard widget.
  1294 			 * Filters the primary link URL for the 'WordPress News' dashboard widget.
   940 			 *
  1295 			 *
   941 			 * @since 2.5.0
  1296 			 * @since 2.5.0
   942 			 *
  1297 			 *
   943 			 * @param string $link The widget's primary link URL.
  1298 			 * @param string $link The widget's primary link URL.
   944 			 */
  1299 			 */
   945 			'link' => apply_filters( 'dashboard_primary_link', __( 'http://wordpress.org/news/' ) ),
  1300 			'link' => apply_filters( 'dashboard_primary_link', __( 'https://wordpress.org/news/' ) ),
   946 
  1301 
   947 			/**
  1302 			/**
   948 			 * Filter the primary feed URL for the 'WordPress News' dashboard widget.
  1303 			 * Filters the primary feed URL for the 'WordPress News' dashboard widget.
   949 			 *
  1304 			 *
   950 			 * @since 2.3.0
  1305 			 * @since 2.3.0
   951 			 *
  1306 			 *
   952 			 * @param string $url The widget's primary feed URL.
  1307 			 * @param string $url The widget's primary feed URL.
   953 			 */
  1308 			 */
   954 			'url' => apply_filters( 'dashboard_primary_feed', __( 'http://wordpress.org/news/feed/' ) ),
  1309 			'url' => apply_filters( 'dashboard_primary_feed', __( 'http://wordpress.org/news/feed/' ) ),
   955 
  1310 
   956 			/**
  1311 			/**
   957 			 * Filter the primary link title for the 'WordPress News' dashboard widget.
  1312 			 * Filters the primary link title for the 'WordPress News' dashboard widget.
   958 			 *
  1313 			 *
   959 			 * @since 2.3.0
  1314 			 * @since 2.3.0
   960 			 *
  1315 			 *
   961 			 * @param string $title Title attribute for the widget's primary link.
  1316 			 * @param string $title Title attribute for the widget's primary link.
   962 			 */
  1317 			 */
   963 			'title'        => apply_filters( 'dashboard_primary_title', __( 'WordPress Blog' ) ),
  1318 			'title'        => apply_filters( 'dashboard_primary_title', __( 'WordPress Blog' ) ),
   964 			'items'        => 1,
  1319 			'items'        => 1,
   965 			'show_summary' => 1,
  1320 			'show_summary' => 0,
   966 			'show_author'  => 0,
  1321 			'show_author'  => 0,
   967 			'show_date'    => 1,
  1322 			'show_date'    => 0,
   968 		),
  1323 		),
   969 		'planet' => array(
  1324 		'planet' => array(
   970 
  1325 
   971 			/**
  1326 			/**
   972 			 * Filter the secondary link URL for the 'WordPress News' dashboard widget.
  1327 			 * Filters the secondary link URL for the 'WordPress News' dashboard widget.
   973 			 *
  1328 			 *
   974 			 * @since 2.3.0
  1329 			 * @since 2.3.0
   975 			 *
  1330 			 *
   976 			 * @param string $link The widget's secondary link URL.
  1331 			 * @param string $link The widget's secondary link URL.
   977 			 */
  1332 			 */
   978 			'link' => apply_filters( 'dashboard_secondary_link', __( 'https://planet.wordpress.org/' ) ),
  1333 			'link' => apply_filters( 'dashboard_secondary_link', __( 'https://planet.wordpress.org/' ) ),
   979 
  1334 
   980 			/**
  1335 			/**
   981 			 * Filter the secondary feed URL for the 'WordPress News' dashboard widget.
  1336 			 * Filters the secondary feed URL for the 'WordPress News' dashboard widget.
   982 			 *
  1337 			 *
   983 			 * @since 2.3.0
  1338 			 * @since 2.3.0
   984 			 *
  1339 			 *
   985 			 * @param string $url The widget's secondary feed URL.
  1340 			 * @param string $url The widget's secondary feed URL.
   986 			 */
  1341 			 */
   987 			'url' => apply_filters( 'dashboard_secondary_feed', __( 'https://planet.wordpress.org/feed/' ) ),
  1342 			'url' => apply_filters( 'dashboard_secondary_feed', __( 'https://planet.wordpress.org/feed/' ) ),
   988 
  1343 
   989 			/**
  1344 			/**
   990 			 * Filter the secondary link title for the 'WordPress News' dashboard widget.
  1345 			 * Filters the secondary link title for the 'WordPress News' dashboard widget.
   991 			 *
  1346 			 *
   992 			 * @since 2.3.0
  1347 			 * @since 2.3.0
   993 			 *
  1348 			 *
   994 			 * @param string $title Title attribute for the widget's secondary link.
  1349 			 * @param string $title Title attribute for the widget's secondary link.
   995 			 */
  1350 			 */
   996 			'title'        => apply_filters( 'dashboard_secondary_title', __( 'Other WordPress News' ) ),
  1351 			'title'        => apply_filters( 'dashboard_secondary_title', __( 'Other WordPress News' ) ),
   997 			'items'        => 3,
  1352 
       
  1353 			/**
       
  1354 			 * Filters the number of secondary link items for the 'WordPress News' dashboard widget.
       
  1355 			 *
       
  1356 			 * @since 4.4.0
       
  1357 			 *
       
  1358 			 * @param string $items How many items to show in the secondary feed.
       
  1359 			 */
       
  1360 			'items'        => apply_filters( 'dashboard_secondary_items', 3 ),
   998 			'show_summary' => 0,
  1361 			'show_summary' => 0,
   999 			'show_author'  => 0,
  1362 			'show_author'  => 0,
  1000 			'show_date'    => 0,
  1363 			'show_date'    => 0,
  1001 		)
  1364 		)
  1002 	);
  1365 	);
  1003 
  1366 
  1004 	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' ) ) ) {
       
  1005 		$feeds['plugins'] = array(
       
  1006 			'link'         => '',
       
  1007 			'url'          => array(
       
  1008 				'popular' => 'http://wordpress.org/plugins/rss/browse/popular/',
       
  1009 			),
       
  1010 			'title'        => '',
       
  1011 			'items'        => 1,
       
  1012 			'show_summary' => 0,
       
  1013 			'show_author'  => 0,
       
  1014 			'show_date'    => 0,
       
  1015 		);
       
  1016 	}
       
  1017 
       
  1018 	wp_dashboard_cached_rss_widget( 'dashboard_primary', 'wp_dashboard_primary_output', $feeds );
  1367 	wp_dashboard_cached_rss_widget( 'dashboard_primary', 'wp_dashboard_primary_output', $feeds );
  1019 }
  1368 }
  1020 
  1369 
  1021 /**
  1370 /**
  1022  * Display the WordPress news feeds.
  1371  * Display the WordPress news feeds.
  1023  *
  1372  *
  1024  * @since 3.8.0
  1373  * @since 3.8.0
       
  1374  * @since 4.8.0 Removed popular plugins feed.
  1025  *
  1375  *
  1026  * @param string $widget_id Widget ID.
  1376  * @param string $widget_id Widget ID.
  1027  * @param array  $feeds     Array of RSS feeds.
  1377  * @param array  $feeds     Array of RSS feeds.
  1028  */
  1378  */
  1029 function wp_dashboard_primary_output( $widget_id, $feeds ) {
  1379 function wp_dashboard_primary_output( $widget_id, $feeds ) {
  1030 	foreach( $feeds as $type => $args ) {
  1380 	foreach ( $feeds as $type => $args ) {
  1031 		$args['type'] = $type;
  1381 		$args['type'] = $type;
  1032 		echo '<div class="rss-widget">';
  1382 		echo '<div class="rss-widget">';
  1033 		if ( $type === 'plugins' ) {
       
  1034 			wp_dashboard_plugins_output( $args['url'], $args );
       
  1035 		} else {
       
  1036 			wp_widget_rss_output( $args['url'], $args );
  1383 			wp_widget_rss_output( $args['url'], $args );
  1037 		}
       
  1038 		echo "</div>";
  1384 		echo "</div>";
  1039 	}
  1385 	}
  1040 }
  1386 }
  1041 
  1387 
  1042 /**
  1388 /**
  1043  * Display plugins text for the WordPress news widget.
       
  1044  *
       
  1045  * @since 2.5.0
       
  1046  */
       
  1047 function wp_dashboard_plugins_output( $rss, $args = array() ) {
       
  1048 	// Plugin feeds plus link to install them
       
  1049 	$popular = fetch_feed( $args['url']['popular'] );
       
  1050 
       
  1051 	if ( false === $plugin_slugs = get_transient( 'plugin_slugs' ) ) {
       
  1052 		$plugin_slugs = array_keys( get_plugins() );
       
  1053 		set_transient( 'plugin_slugs', $plugin_slugs, DAY_IN_SECONDS );
       
  1054 	}
       
  1055 
       
  1056 	echo '<ul>';
       
  1057 
       
  1058 	foreach ( array( $popular ) as $feed ) {
       
  1059 		if ( is_wp_error( $feed ) || ! $feed->get_item_quantity() )
       
  1060 			continue;
       
  1061 
       
  1062 		$items = $feed->get_items(0, 5);
       
  1063 
       
  1064 		// Pick a random, non-installed plugin
       
  1065 		while ( true ) {
       
  1066 			// Abort this foreach loop iteration if there's no plugins left of this type
       
  1067 			if ( 0 == count($items) )
       
  1068 				continue 2;
       
  1069 
       
  1070 			$item_key = array_rand($items);
       
  1071 			$item = $items[$item_key];
       
  1072 
       
  1073 			list($link, $frag) = explode( '#', $item->get_link() );
       
  1074 
       
  1075 			$link = esc_url($link);
       
  1076 			if ( preg_match( '|/([^/]+?)/?$|', $link, $matches ) )
       
  1077 				$slug = $matches[1];
       
  1078 			else {
       
  1079 				unset( $items[$item_key] );
       
  1080 				continue;
       
  1081 			}
       
  1082 
       
  1083 			// Is this random plugin's slug already installed? If so, try again.
       
  1084 			reset( $plugin_slugs );
       
  1085 			foreach ( $plugin_slugs as $plugin_slug ) {
       
  1086 				if ( $slug == substr( $plugin_slug, 0, strlen( $slug ) ) ) {
       
  1087 					unset( $items[$item_key] );
       
  1088 					continue 2;
       
  1089 				}
       
  1090 			}
       
  1091 
       
  1092 			// If we get to this point, then the random plugin isn't installed and we can stop the while().
       
  1093 			break;
       
  1094 		}
       
  1095 
       
  1096 		// Eliminate some common badly formed plugin descriptions
       
  1097 		while ( ( null !== $item_key = array_rand($items) ) && false !== strpos( $items[$item_key]->get_description(), 'Plugin Name:' ) )
       
  1098 			unset($items[$item_key]);
       
  1099 
       
  1100 		if ( !isset($items[$item_key]) )
       
  1101 			continue;
       
  1102 
       
  1103 		$title = esc_html( $item->get_title() );
       
  1104 
       
  1105 		$ilink = wp_nonce_url('plugin-install.php?tab=plugin-information&plugin=' . $slug, 'install-plugin_' . $slug) . '&amp;TB_iframe=true&amp;width=600&amp;height=800';
       
  1106 		echo "<li class='dashboard-news-plugin'><span>" . __( 'Popular Plugin' ) . ":</span> <a href='$link' class='dashboard-news-plugin-link'>$title</a>&nbsp;<span>(<a href='$ilink' class='thickbox' title='$title'>" . __( 'Install' ) . "</a>)</span></li>";
       
  1107 
       
  1108 		$feed->__destruct();
       
  1109 		unset( $feed );
       
  1110 	}
       
  1111 
       
  1112 	echo '</ul>';
       
  1113 }
       
  1114 
       
  1115 /**
       
  1116  * Display file upload quota on dashboard.
  1389  * Display file upload quota on dashboard.
  1117  *
  1390  *
  1118  * Runs on the activity_box_end hook in wp_dashboard_right_now().
  1391  * Runs on the {@see 'activity_box_end'} hook in wp_dashboard_right_now().
  1119  *
  1392  *
  1120  * @since 3.0.0
  1393  * @since 3.0.0
  1121  *
  1394  *
  1122  * @return bool|null True if not multisite, user can't upload files, or the space check option is disabled.
  1395  * @return bool|null True if not multisite, user can't upload files, or the space check option is disabled.
  1123 */
  1396  */
  1124 function wp_dashboard_quota() {
  1397 function wp_dashboard_quota() {
  1125 	if ( !is_multisite() || !current_user_can( 'upload_files' ) || get_site_option( 'upload_space_check_disabled' ) )
  1398 	if ( !is_multisite() || !current_user_can( 'upload_files' ) || get_site_option( 'upload_space_check_disabled' ) )
  1126 		return true;
  1399 		return true;
  1127 
  1400 
  1128 	$quota = get_space_allowed();
  1401 	$quota = get_space_allowed();
  1135 	$used_class = ( $percentused >= 70 ) ? ' warning' : '';
  1408 	$used_class = ( $percentused >= 70 ) ? ' warning' : '';
  1136 	$used = round( $used, 2 );
  1409 	$used = round( $used, 2 );
  1137 	$percentused = number_format( $percentused );
  1410 	$percentused = number_format( $percentused );
  1138 
  1411 
  1139 	?>
  1412 	?>
  1140 	<h4 class="mu-storage"><?php _e( 'Storage Space' ); ?></h4>
  1413 	<h3 class="mu-storage"><?php _e( 'Storage Space' ); ?></h3>
  1141 	<div class="mu-storage">
  1414 	<div class="mu-storage">
  1142 	<ul>
  1415 	<ul>
  1143 		<li class="storage-count">
  1416 		<li class="storage-count">
  1144 			<?php $text = sprintf(
  1417 			<?php $text = sprintf(
  1145 				/* translators: number of megabytes */
  1418 				/* translators: %s: number of megabytes */
  1146 				__( '%s MB Space Allowed' ),
  1419 				__( '%s MB Space Allowed' ),
  1147 				number_format_i18n( $quota )
  1420 				number_format_i18n( $quota )
  1148 			);
  1421 			);
  1149 			printf(
  1422 			printf(
  1150 				'<a href="%1$s" title="%2$s">%3$s</a>',
  1423 				'<a href="%1$s">%2$s <span class="screen-reader-text">(%3$s)</span></a>',
  1151 				esc_url( admin_url( 'upload.php' ) ),
  1424 				esc_url( admin_url( 'upload.php' ) ),
  1152 				__( 'Manage Uploads' ),
  1425 				$text,
  1153 				$text
  1426 				__( 'Manage Uploads' )
  1154 			); ?>
  1427 			); ?>
  1155 		</li><li class="storage-count <?php echo $used_class; ?>">
  1428 		</li><li class="storage-count <?php echo $used_class; ?>">
  1156 			<?php $text = sprintf(
  1429 			<?php $text = sprintf(
  1157 				/* translators: 1: number of megabytes, 2: percentage */
  1430 				/* translators: 1: number of megabytes, 2: percentage */
  1158 				__( '%1$s MB (%2$s%%) Space Used' ),
  1431 				__( '%1$s MB (%2$s%%) Space Used' ),
  1159 				number_format_i18n( $used, 2 ),
  1432 				number_format_i18n( $used, 2 ),
  1160 				$percentused
  1433 				$percentused
  1161 			);
  1434 			);
  1162 			printf(
  1435 			printf(
  1163 				'<a href="%1$s" title="%2$s" class="musublink">%3$s</a>',
  1436 				'<a href="%1$s" class="musublink">%2$s <span class="screen-reader-text">(%3$s)</span></a>',
  1164 				esc_url( admin_url( 'upload.php' ) ),
  1437 				esc_url( admin_url( 'upload.php' ) ),
  1165 				__( 'Manage Uploads' ),
  1438 				$text,
  1166 				$text
  1439 				__( 'Manage Uploads' )
  1167 			); ?>
  1440 			); ?>
  1168 		</li>
  1441 		</li>
  1169 	</ul>
  1442 	</ul>
  1170 	</div>
  1443 	</div>
  1171 	<?php
  1444 	<?php
  1172 }
  1445 }
  1173 add_action( 'activity_box_end', 'wp_dashboard_quota' );
       
  1174 
  1446 
  1175 // Display Browser Nag Meta Box
  1447 // Display Browser Nag Meta Box
  1176 function wp_dashboard_browser_nag() {
  1448 function wp_dashboard_browser_nag() {
  1177 	$notice = '';
  1449 	$notice = '';
  1178 	$response = wp_check_browser_version();
  1450 	$response = wp_check_browser_version();
  1179 
  1451 
  1180 	if ( $response ) {
  1452 	if ( $response ) {
  1181 		if ( $response['insecure'] ) {
  1453 		if ( $response['insecure'] ) {
  1182 			$msg = sprintf( __( "It looks like you're using an insecure version of <a href='%s'>%s</a>. 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'] ) );
  1454 			/* translators: %s: browser name and link */
       
  1455 			$msg = sprintf( __( "It looks like you're using an insecure version of %s. Using an outdated browser makes your computer unsafe. For the best WordPress experience, please update your browser." ),
       
  1456 				sprintf( '<a href="%s">%s</a>', esc_url( $response['update_url'] ), esc_html( $response['name'] ) )
       
  1457 			);
  1183 		} else {
  1458 		} else {
  1184 			$msg = sprintf( __( "It looks like you're using an old version of <a href='%s'>%s</a>. For the best WordPress experience, please update your browser." ), esc_attr( $response['update_url'] ), esc_html( $response['name'] ) );
  1459 			/* translators: %s: browser name and link */
       
  1460 			$msg = sprintf( __( "It looks like you're using an old version of %s. For the best WordPress experience, please update your browser." ),
       
  1461 				sprintf( '<a href="%s">%s</a>', esc_url( $response['update_url'] ), esc_html( $response['name'] ) )
       
  1462 			);
  1185 		}
  1463 		}
  1186 
  1464 
  1187 		$browser_nag_class = '';
  1465 		$browser_nag_class = '';
  1188 		if ( !empty( $response['img_src'] ) ) {
  1466 		if ( !empty( $response['img_src'] ) ) {
  1189 			$img_src = ( is_ssl() && ! empty( $response['img_src_ssl'] ) )? $response['img_src_ssl'] : $response['img_src'];
  1467 			$img_src = ( is_ssl() && ! empty( $response['img_src_ssl'] ) )? $response['img_src_ssl'] : $response['img_src'];
  1191 			$notice .= '<div class="alignright browser-icon"><a href="' . esc_attr($response['update_url']) . '"><img src="' . esc_attr( $img_src ) . '" alt="" /></a></div>';
  1469 			$notice .= '<div class="alignright browser-icon"><a href="' . esc_attr($response['update_url']) . '"><img src="' . esc_attr( $img_src ) . '" alt="" /></a></div>';
  1192 			$browser_nag_class = ' has-browser-icon';
  1470 			$browser_nag_class = ' has-browser-icon';
  1193 		}
  1471 		}
  1194 		$notice .= "<p class='browser-update-nag{$browser_nag_class}'>{$msg}</p>";
  1472 		$notice .= "<p class='browser-update-nag{$browser_nag_class}'>{$msg}</p>";
  1195 
  1473 
  1196 		$browsehappy = 'http://browsehappy.com/';
  1474 		$browsehappy = 'https://browsehappy.com/';
  1197 		$locale = get_locale();
  1475 		$locale = get_user_locale();
  1198 		if ( 'en_US' !== $locale )
  1476 		if ( 'en_US' !== $locale )
  1199 			$browsehappy = add_query_arg( 'locale', $locale, $browsehappy );
  1477 			$browsehappy = add_query_arg( 'locale', $locale, $browsehappy );
  1200 
  1478 
  1201 		$notice .= '<p>' . sprintf( __( '<a href="%1$s" class="update-browser-link">Update %2$s</a> or learn how to <a href="%3$s" class="browse-happy-link">browse happy</a>' ), esc_attr( $response['update_url'] ), esc_html( $response['name'] ), esc_url( $browsehappy ) ) . '</p>';
  1479 		$notice .= '<p>' . sprintf( __( '<a href="%1$s" class="update-browser-link">Update %2$s</a> or learn how to <a href="%3$s" class="browse-happy-link">browse happy</a>' ), esc_attr( $response['update_url'] ), esc_html( $response['name'] ), esc_url( $browsehappy ) ) . '</p>';
  1202 		$notice .= '<p class="hide-if-no-js"><a href="" class="dismiss">' . __( 'Dismiss' ) . '</a></p>';
  1480 		$notice .= '<p class="hide-if-no-js"><a href="" class="dismiss" aria-label="' . esc_attr__( 'Dismiss the browser warning panel' ) . '">' . __( 'Dismiss' ) . '</a></p>';
  1203 		$notice .= '<div class="clear"></div>';
  1481 		$notice .= '<div class="clear"></div>';
  1204 	}
  1482 	}
  1205 
  1483 
  1206 	/**
  1484 	/**
  1207 	* Filter the notice output for the 'Browse Happy' nag meta box.
  1485 	* Filters the notice output for the 'Browse Happy' nag meta box.
  1208 	*
  1486 	*
  1209 	* @since 3.2.0
  1487 	* @since 3.2.0
  1210 	*
  1488 	*
  1211 	* @param string $notice   The notice content.
  1489 	* @param string $notice   The notice content.
  1212 	* @param array  $response An array containing web browser information.
  1490 	* @param array  $response An array containing web browser information.
  1213 	*/
  1491 	*/
  1214 	echo apply_filters( 'browse-happy-notice', $notice, $response );
  1492 	echo apply_filters( 'browse-happy-notice', $notice, $response );
  1215 }
  1493 }
  1216 
  1494 
       
  1495 /**
       
  1496  * @since 3.2.0
       
  1497  *
       
  1498  * @param array $classes
       
  1499  * @return array
       
  1500  */
  1217 function dashboard_browser_nag_class( $classes ) {
  1501 function dashboard_browser_nag_class( $classes ) {
  1218 	$response = wp_check_browser_version();
  1502 	$response = wp_check_browser_version();
  1219 
  1503 
  1220 	if ( $response && $response['insecure'] )
  1504 	if ( $response && $response['insecure'] )
  1221 		$classes[] = 'browser-insecure';
  1505 		$classes[] = 'browser-insecure';
  1235 		return false;
  1519 		return false;
  1236 
  1520 
  1237 	$key = md5( $_SERVER['HTTP_USER_AGENT'] );
  1521 	$key = md5( $_SERVER['HTTP_USER_AGENT'] );
  1238 
  1522 
  1239 	if ( false === ($response = get_site_transient('browser_' . $key) ) ) {
  1523 	if ( false === ($response = get_site_transient('browser_' . $key) ) ) {
  1240 		global $wp_version;
  1524 		// include an unmodified $wp_version
  1241 
  1525 		include( ABSPATH . WPINC . '/version.php' );
       
  1526 
       
  1527 		$url = 'http://api.wordpress.org/core/browse-happy/1.1/';
  1242 		$options = array(
  1528 		$options = array(
  1243 			'body'			=> array( 'useragent' => $_SERVER['HTTP_USER_AGENT'] ),
  1529 			'body'       => array( 'useragent' => $_SERVER['HTTP_USER_AGENT'] ),
  1244 			'user-agent'	=> 'WordPress/' . $wp_version . '; ' . home_url()
  1530 			'user-agent' => 'WordPress/' . $wp_version . '; ' . home_url( '/' )
  1245 		);
  1531 		);
  1246 
  1532 
  1247 		$response = wp_remote_post( 'http://api.wordpress.org/core/browse-happy/1.1/', $options );
  1533 		if ( wp_http_supports( array( 'ssl' ) ) ) {
       
  1534 			$url = set_url_scheme( $url, 'https' );
       
  1535 		}
       
  1536 
       
  1537 		$response = wp_remote_post( $url, $options );
  1248 
  1538 
  1249 		if ( is_wp_error( $response ) || 200 != wp_remote_retrieve_response_code( $response ) )
  1539 		if ( is_wp_error( $response ) || 200 != wp_remote_retrieve_response_code( $response ) )
  1250 			return false;
  1540 			return false;
  1251 
  1541 
  1252 		/**
  1542 		/**
  1253 		 * Response should be an array with:
  1543 		 * Response should be an array with:
  1254 		 *  'name' - string - A user friendly browser name
  1544 		 *  'platform' - string - A user-friendly platform name, if it can be determined
  1255 		 *  'version' - string - The most recent version of the browser
  1545 		 *  'name' - string - A user-friendly browser name
  1256 		 *  'current_version' - string - The version of the browser the user is using
  1546 		 *  'version' - string - The version of the browser the user is using
       
  1547 		 *  'current_version' - string - The most recent version of the browser
  1257 		 *  'upgrade' - boolean - Whether the browser needs an upgrade
  1548 		 *  'upgrade' - boolean - Whether the browser needs an upgrade
  1258 		 *  'insecure' - boolean - Whether the browser is deemed insecure
  1549 		 *  'insecure' - boolean - Whether the browser is deemed insecure
  1259 		 *  'upgrade_url' - string - The url to visit to upgrade
  1550 		 *  'update_url' - string - The url to visit to upgrade
  1260 		 *  'img_src' - string - An image representing the browser
  1551 		 *  'img_src' - string - An image representing the browser
  1261 		 *  'img_src_ssl' - string - An image (over SSL) representing the browser
  1552 		 *  'img_src_ssl' - string - An image (over SSL) representing the browser
  1262 		 */
  1553 		 */
  1263 		$response = json_decode( wp_remote_retrieve_body( $response ), true );
  1554 		$response = json_decode( wp_remote_retrieve_body( $response ), true );
  1264 
  1555 
  1282  * @since 3.3.0
  1573  * @since 3.3.0
  1283  */
  1574  */
  1284 function wp_welcome_panel() {
  1575 function wp_welcome_panel() {
  1285 	?>
  1576 	?>
  1286 	<div class="welcome-panel-content">
  1577 	<div class="welcome-panel-content">
  1287 	<h3><?php _e( 'Welcome to WordPress!' ); ?></h3>
  1578 	<h2><?php _e( 'Welcome to WordPress!' ); ?></h2>
  1288 	<p class="about-description"><?php _e( 'We&#8217;ve assembled some links to get you started:' ); ?></p>
  1579 	<p class="about-description"><?php _e( 'We&#8217;ve assembled some links to get you started:' ); ?></p>
  1289 	<div class="welcome-panel-column-container">
  1580 	<div class="welcome-panel-column-container">
  1290 	<div class="welcome-panel-column">
  1581 	<div class="welcome-panel-column">
  1291 		<?php if ( current_user_can( 'customize' ) ): ?>
  1582 		<?php if ( current_user_can( 'customize' ) ) : ?>
  1292 			<h4><?php _e( 'Get Started' ); ?></h4>
  1583 			<h3><?php _e( 'Get Started' ); ?></h3>
  1293 			<a class="button button-primary button-hero load-customize hide-if-no-customize" href="<?php echo wp_customize_url(); ?>"><?php _e( 'Customize Your Site' ); ?></a>
  1584 			<a class="button button-primary button-hero load-customize hide-if-no-customize" href="<?php echo wp_customize_url(); ?>"><?php _e( 'Customize Your Site' ); ?></a>
  1294 		<?php endif; ?>
  1585 		<?php endif; ?>
  1295 		<a class="button button-primary button-hero hide-if-customize" href="<?php echo admin_url( 'themes.php' ); ?>"><?php _e( 'Customize Your Site' ); ?></a>
  1586 		<a class="button button-primary button-hero hide-if-customize" href="<?php echo admin_url( 'themes.php' ); ?>"><?php _e( 'Customize Your Site' ); ?></a>
  1296 		<?php if ( current_user_can( 'install_themes' ) || ( current_user_can( 'switch_themes' ) && count( wp_get_themes( array( 'allowed' => true ) ) ) > 1 ) ) : ?>
  1587 		<?php if ( current_user_can( 'install_themes' ) || ( current_user_can( 'switch_themes' ) && count( wp_get_themes( array( 'allowed' => true ) ) ) > 1 ) ) : ?>
  1297 			<p class="hide-if-no-customize"><?php printf( __( 'or, <a href="%s">change your theme completely</a>' ), admin_url( 'themes.php' ) ); ?></p>
  1588 			<?php $themes_link = current_user_can( 'customize' ) ? add_query_arg( 'autofocus[panel]', 'themes', admin_url( 'customize.php' ) ) : admin_url( 'themes.php' ); ?>
       
  1589 			<p class="hide-if-no-customize"><?php printf( __( 'or, <a href="%s">change your theme completely</a>' ), $themes_link ); ?></p>
  1298 		<?php endif; ?>
  1590 		<?php endif; ?>
  1299 	</div>
  1591 	</div>
  1300 	<div class="welcome-panel-column">
  1592 	<div class="welcome-panel-column">
  1301 		<h4><?php _e( 'Next Steps' ); ?></h4>
  1593 		<h3><?php _e( 'Next Steps' ); ?></h3>
  1302 		<ul>
  1594 		<ul>
  1303 		<?php if ( 'page' == get_option( 'show_on_front' ) && ! get_option( 'page_for_posts' ) ) : ?>
  1595 		<?php if ( 'page' == get_option( 'show_on_front' ) && ! get_option( 'page_for_posts' ) ) : ?>
  1304 			<li><?php printf( '<a href="%s" class="welcome-icon welcome-edit-page">' . __( 'Edit your front page' ) . '</a>', get_edit_post_link( get_option( 'page_on_front' ) ) ); ?></li>
  1596 			<li><?php printf( '<a href="%s" class="welcome-icon welcome-edit-page">' . __( 'Edit your front page' ) . '</a>', get_edit_post_link( get_option( 'page_on_front' ) ) ); ?></li>
  1305 			<li><?php printf( '<a href="%s" class="welcome-icon welcome-add-page">' . __( 'Add additional pages' ) . '</a>', admin_url( 'post-new.php?post_type=page' ) ); ?></li>
  1597 			<li><?php printf( '<a href="%s" class="welcome-icon welcome-add-page">' . __( 'Add additional pages' ) . '</a>', admin_url( 'post-new.php?post_type=page' ) ); ?></li>
  1306 		<?php elseif ( 'page' == get_option( 'show_on_front' ) ) : ?>
  1598 		<?php elseif ( 'page' == get_option( 'show_on_front' ) ) : ?>
  1313 		<?php endif; ?>
  1605 		<?php endif; ?>
  1314 			<li><?php printf( '<a href="%s" class="welcome-icon welcome-view-site">' . __( 'View your site' ) . '</a>', home_url( '/' ) ); ?></li>
  1606 			<li><?php printf( '<a href="%s" class="welcome-icon welcome-view-site">' . __( 'View your site' ) . '</a>', home_url( '/' ) ); ?></li>
  1315 		</ul>
  1607 		</ul>
  1316 	</div>
  1608 	</div>
  1317 	<div class="welcome-panel-column welcome-panel-last">
  1609 	<div class="welcome-panel-column welcome-panel-last">
  1318 		<h4><?php _e( 'More Actions' ); ?></h4>
  1610 		<h3><?php _e( 'More Actions' ); ?></h3>
  1319 		<ul>
  1611 		<ul>
  1320 		<?php if ( current_theme_supports( 'widgets' ) || current_theme_supports( 'menus' ) ) : ?>
  1612 		<?php if ( current_theme_supports( 'widgets' ) || current_theme_supports( 'menus' ) ) : ?>
  1321 			<li><div class="welcome-icon welcome-widgets-menus"><?php
  1613 			<li><div class="welcome-icon welcome-widgets-menus"><?php
  1322 				if ( current_theme_supports( 'widgets' ) && current_theme_supports( 'menus' ) ) {
  1614 				if ( current_theme_supports( 'widgets' ) && current_theme_supports( 'menus' ) ) {
  1323 					printf( __( 'Manage <a href="%1$s">widgets</a> or <a href="%2$s">menus</a>' ),
  1615 					printf( __( 'Manage <a href="%1$s">widgets</a> or <a href="%2$s">menus</a>' ),
  1337 	</div>
  1629 	</div>
  1338 	</div>
  1630 	</div>
  1339 	</div>
  1631 	</div>
  1340 	<?php
  1632 	<?php
  1341 }
  1633 }
       
  1634 
       
  1635 /**
       
  1636  * Displays a Try Gutenberg Panel, to introduce people to Gutenberg
       
  1637  *
       
  1638  * @since 4.9.8
       
  1639  */
       
  1640 function wp_try_gutenberg_panel() {
       
  1641 	$plugins = get_plugins();
       
  1642 	$action = $url = $classes = '';
       
  1643 	$classic_action = $classic_url = $classic_classes = '';
       
  1644 
       
  1645 	if ( current_user_can( 'install_plugins' ) ) {
       
  1646 		if ( empty( $plugins['gutenberg/gutenberg.php'] ) ) {
       
  1647 			if ( get_filesystem_method( array(), WP_PLUGIN_DIR ) === 'direct' ) {
       
  1648 				$action = __( 'Install Gutenberg' );
       
  1649 				$url = wp_nonce_url( self_admin_url( 'update.php?action=install-plugin&plugin=gutenberg' ), 'install-plugin_gutenberg' );
       
  1650 				$classes = ' install-now';
       
  1651 			}
       
  1652 		} else if ( is_plugin_inactive( 'gutenberg/gutenberg.php' ) ) {
       
  1653 			$action = __( 'Activate Gutenberg' );
       
  1654 			$url = wp_nonce_url( self_admin_url( 'plugins.php?action=activate&plugin=gutenberg/gutenberg.php&from=try-gutenberg' ), 'activate-plugin_gutenberg/gutenberg.php' );
       
  1655 			$classes = ' activate-now';
       
  1656 		}
       
  1657 
       
  1658 		if ( empty( $plugins['classic-editor/classic-editor.php'] ) ) {
       
  1659 			if ( get_filesystem_method( array(), WP_PLUGIN_DIR ) === 'direct' ) {
       
  1660 				$classic_action = __( 'Install the Classic Editor' );
       
  1661 				$classic_url = wp_nonce_url( self_admin_url( 'update.php?action=install-plugin&plugin=classic-editor' ), 'install-plugin_classic-editor' );
       
  1662 				$classic_classes = ' install-now';
       
  1663 			}
       
  1664 		} else if ( is_plugin_inactive( 'classic-editor/classic-editor.php' ) ) {
       
  1665 			$classic_action = __( 'Activate the Classic Editor' );
       
  1666 			$classic_url = wp_nonce_url( self_admin_url( 'plugins.php?action=activate&plugin=classic-editor/classic-editor.php&from=try-gutenberg' ), 'activate-plugin_classic-editor/classic-editor.php' );
       
  1667 			$classic_classes = ' activate-now';
       
  1668 		} else {
       
  1669 			$classic_action = __( 'The Classic Editor is activated' );
       
  1670 			$classic_url = wp_nonce_url( self_admin_url( 'plugins.php?action=activate&plugin=classic-editor/classic-editor.php&from=try-gutenberg' ), 'activate-plugin_classic-editor/classic-editor.php' );;
       
  1671 			$classic_classes = ' button-disabled install-now updated-message';
       
  1672 		}
       
  1673 	}
       
  1674 
       
  1675 	if ( current_user_can( 'edit_posts' ) && is_plugin_active( 'gutenberg/gutenberg.php' ) ) {
       
  1676 		$action = __( 'Try Gutenberg' );
       
  1677 		$url = admin_url( 'admin.php?page=gutenberg' );
       
  1678 	}
       
  1679 
       
  1680 	?>
       
  1681 	<div class="try-gutenberg-panel-content">
       
  1682 		<h2><?php _e( 'A new, modern publishing experience is coming soon.' ); ?></h2>
       
  1683 
       
  1684 		<p class="about-description"><?php _e( "Take your words, media, and layout in new directions with Gutenberg, the WordPress editor we're currently building." ); ?></p>
       
  1685 
       
  1686 		<hr />
       
  1687 
       
  1688 		<div class="try-gutenberg-panel-column-container">
       
  1689 			<div class="try-gutenberg-panel-column try-gutenberg-panel-image-column">
       
  1690 				<picture>
       
  1691 					<source srcset="about:blank" media="(max-width: 1024px)">
       
  1692 					<img src="https://s.w.org/images/core/gutenberg-screenshot.png?<?php echo date( 'Ymd' ); ?>" alt="<?php esc_attr_e( 'Screenshot from the Gutenberg interface' ); ?>" />
       
  1693 				</picture>
       
  1694 			</div>
       
  1695 			<div class="try-gutenberg-panel-column plugin-card-gutenberg">
       
  1696 
       
  1697 				<div>
       
  1698 					<h3><?php _e( 'Test the new editor today.' ); ?></h3>
       
  1699 
       
  1700 					<p>
       
  1701 						<?php _e( "You can take Gutenberg for a spin (and share your feedback, if you’d like) before we officially release it, by installing it as a plugin." ); ?>
       
  1702 						<?php
       
  1703 							printf(
       
  1704 								/* translators: 1: Gutenberg call for testing handbook link, 2: Gutenberg GitHub repository issues link, 3: Gutenberg GitHub repository CONTRIBUTING.md link */
       
  1705 								__( 'You can help by <a href="%1$s">testing</a>, <a href="%2$s">filing bugs</a>, or contributing on the <a href="%3$s">GitHub repository</a>.' ),
       
  1706 								'https://make.wordpress.org/test/handbook/call-for-testing/gutenberg-testing/',
       
  1707 								'https://github.com/WordPress/gutenberg/issues',
       
  1708 								'https://github.com/WordPress/gutenberg/blob/master/CONTRIBUTING.md'
       
  1709 							);
       
  1710 						?>
       
  1711 					</p>
       
  1712 				</div>
       
  1713 
       
  1714 				<div class="try-gutenberg-action">
       
  1715 					<?php if ( $action ) { ?>
       
  1716 						<p><a class="button button-primary button-hero<?php echo $classes; ?>" href="<?php echo esc_url( $url ); ?>" data-name="<?php esc_attr_e( 'Gutenberg' ); ?>" data-slug="gutenberg"><?php echo $action; ?></a></p>
       
  1717 					<?php } ?>
       
  1718 
       
  1719 					<p>
       
  1720 						<?php
       
  1721 							$learnmore = sprintf(
       
  1722 								/* translators: Link to https://wordpress.org/gutenberg/ */
       
  1723 								__( '<a href="%s">Learn more about Gutenberg</a>' ),
       
  1724 								__( 'https://wordpress.org/gutenberg/' )
       
  1725 							);
       
  1726 
       
  1727 							/**
       
  1728 							 * Filters the "Learn more" link in the Try Gutenberg panel.
       
  1729 							 *
       
  1730 							 * It allows hosts or site owners to change the link, to provide extra
       
  1731 							 * information about Gutenberg, specific to their service.
       
  1732 							 *
       
  1733 							 * WARNING: This filter will only exist in the 4.9.x series, it will not be
       
  1734 							 * added to WordPress 5.0 and later.
       
  1735 							 *
       
  1736 							 * @since 4.9.8
       
  1737 							 */
       
  1738 							echo apply_filters( 'try_gutenberg_learn_more_link', $learnmore );
       
  1739 						?>
       
  1740 					</p>
       
  1741 				</div>
       
  1742 			</div>
       
  1743 
       
  1744 			<div class="try-gutenberg-panel-column plugin-card-classic-editor">
       
  1745 
       
  1746 				<div>
       
  1747 					<h3><?php _e( 'Not quite ready?' ); ?></h3>
       
  1748 
       
  1749 					<p>
       
  1750 						<?php _e( 'The new editor will be enabled by default in the next major release of WordPress. If you’re not sure how compatible your current themes and plugins are, we’ve got you covered.' ); ?>
       
  1751 						<?php
       
  1752 							printf(
       
  1753 								/* translators: Link to the Classic Editor plugin page */
       
  1754 								__( 'Install the <a href="%s">Classic Editor plugin</a> to keep using the current editor until you’re ready to make the switch.' ),
       
  1755 								__( 'https://wordpress.org/plugins/classic-editor' )
       
  1756 							);
       
  1757 						?>
       
  1758 					</p>
       
  1759 				</div>
       
  1760 
       
  1761 				<?php if ( $classic_action ) { ?>
       
  1762 					<div class="try-gutenberg-action">
       
  1763 						<p><a class="button button-secondary button-hero<?php echo $classic_classes; ?>" href="<?php echo esc_url( $classic_url ); ?>" data-name="<?php esc_attr_e( 'Classic Editor' ); ?>" data-slug="classic-editor"><?php echo $classic_action; ?></a></p>
       
  1764 					</div>
       
  1765 				<?php } ?>
       
  1766 			</div>
       
  1767 		</div>
       
  1768 	</div>
       
  1769 	<?php
       
  1770 }