diff --git a/src/wp-admin/css/dashboard.css b/src/wp-admin/css/dashboard.css
index 9901d1c2a2c13..e8ebe1cd7da23 100644
--- a/src/wp-admin/css/dashboard.css
+++ b/src/wp-admin/css/dashboard.css
@@ -409,20 +409,9 @@
#dashboard_right_now .search-engines-info:before,
#dashboard_right_now li a:before,
#dashboard_right_now li > span:before { /* get only the first level span to exclude screen-reader-text in mu-storage */
- content: "\f159" / ''; /* generic icon for items added by CPTs ? */
padding: 0 5px 0 0;
}
-#dashboard_right_now .page-count a:before,
-#dashboard_right_now .page-count span:before {
- content: "\f105" / '';
-}
-
-#dashboard_right_now .post-count a:before,
-#dashboard_right_now .post-count span:before {
- content: "\f109" / '';
-}
-
#dashboard_right_now .comment-count a:before {
content: "\f101" / '';
}
diff --git a/src/wp-admin/includes/dashboard.php b/src/wp-admin/includes/dashboard.php
index cac03b1fe3630..4c2a44c5f4faf 100644
--- a/src/wp-admin/includes/dashboard.php
+++ b/src/wp-admin/includes/dashboard.php
@@ -302,26 +302,45 @@ function wp_dashboard_right_now() {
publish ) {
- if ( 'post' === $post_type ) {
- /* translators: %s: Number of posts. */
- $text = _n( '%s Post', '%s Posts', $num_posts->publish );
+ // At a Glance Post Types.
+ foreach ( get_post_types( array( 'at_a_glance' => true ), 'objects' ) as $post_type_object ) {
+ $post_type = $post_type_object->name;
+ $num_posts = wp_count_posts( $post_type );
+ $num_post_published = intval( $num_posts->publish );
+
+ if ( $num_posts && $num_post_published ) {
+ if ( 1 === $num_post_published ) {
+ $post_label = $post_type_object->labels->singular_name;
} else {
- /* translators: %s: Number of pages. */
- $text = _n( '%s Page', '%s Pages', $num_posts->publish );
+ $post_label = $post_type_object->labels->name;
}
+ $text = number_format_i18n( $num_post_published ) . ' ' . $post_label;
- $text = sprintf( $text, number_format_i18n( $num_posts->publish ) );
- $post_type_object = get_post_type_object( $post_type );
+ $icon_class = '';
- if ( $post_type_object && current_user_can( $post_type_object->cap->edit_posts ) ) {
- printf( '- %2$s
', $post_type, $text );
+ if ( str_starts_with( $post_type_object->menu_icon, 'dashicons' ) ) {
+ $icon_class = $post_type_object->menu_icon;
+ } elseif ( str_starts_with( $post_type_object->menu_icon, 'data:image/svg+xml;base64,' ) ) {
+ printf(
+ '',
+ $post_type,
+ $post_type_object->menu_icon
+ );
+ }
+
+ $class_attr = $icon_class ? sprintf( ' class="%s"', $icon_class ) : '';
+
+ if ( current_user_can( $post_type_object->cap->edit_posts ) ) {
+ printf( '- %2$s
', $post_type, $text, $class_attr );
} else {
- printf( '- %2$s
', $post_type, $text );
+ printf( '- %2$s
', $post_type, $text, $class_attr );
}
}
}
diff --git a/src/wp-includes/class-wp-post-type.php b/src/wp-includes/class-wp-post-type.php
index 8812c21f1b415..75d4187a30ed6 100644
--- a/src/wp-includes/class-wp-post-type.php
+++ b/src/wp-includes/class-wp-post-type.php
@@ -147,6 +147,15 @@ final class WP_Post_Type {
*/
public $show_in_menu = null;
+ /**
+ * Makes this post type visible in the At a Glance dashboard widget.
+ *
+ * Default is the value of $show_in_menu.
+ *
+ * @var bool $at_a_glance
+ */
+ public $at_a_glance = null;
+
/**
* Makes this post type available for selection in navigation menus.
*
@@ -190,7 +199,7 @@ final class WP_Post_Type {
* @since 4.6.0
* @var string $menu_icon
*/
- public $menu_icon = null;
+ public $menu_icon;
/**
* The string to use to build the read, edit, and delete capabilities.
@@ -538,6 +547,7 @@ public function set_props( $args ) {
'show_in_admin_bar' => null,
'menu_position' => null,
'menu_icon' => null,
+ 'at_a_glance' => null,
'capability_type' => 'post',
'capabilities' => array(),
'map_meta_cap' => null,
@@ -591,6 +601,16 @@ public function set_props( $args ) {
$args['show_in_menu'] = $args['show_ui'];
}
+ // If not set, default to the setting for show_in_menu.
+ if ( null === $args['at_a_glance'] ) {
+ $args['at_a_glance'] = (bool) $args['show_in_menu'];
+ }
+
+ // If not set, default to the post icon.
+ if ( null === $args['menu_icon'] ) {
+ $args['menu_icon'] = 'dashicons-admin-post';
+ }
+
// If not set, default to the setting for 'show_in_menu'.
if ( null === $args['show_in_admin_bar'] ) {
$args['show_in_admin_bar'] = (bool) $args['show_in_menu'];
diff --git a/src/wp-includes/post.php b/src/wp-includes/post.php
index a88d1afd57332..a12b692b2a017 100644
--- a/src/wp-includes/post.php
+++ b/src/wp-includes/post.php
@@ -103,6 +103,7 @@ function create_initial_post_types() {
),
'public' => true,
'show_ui' => true,
+ 'at_a_glance' => false,
'_builtin' => true, /* internal use only. don't use this when registering your own post type. */
'_edit_link' => 'post.php?post=%d', /* internal use only. don't use this when registering your own post type. */
'capability_type' => 'post',
@@ -1734,6 +1735,8 @@ function get_post_types( $args = array(), $output = 'names', $operator = 'and' )
* of a Dashicons helper class to use a font icon, e.g.
* 'dashicons-chart-pie'. Pass 'none' to leave div.wp-menu-image empty
* so an icon can be added via CSS. Defaults to use the posts icon.
+ * @type bool $at_a_glance Whether to display this post type in the 'At a Glance' dashboard widget.
+ * Default is value of $show_in_menu.
* @type string|array $capability_type The string to use to build the read, edit, and delete capabilities.
* May be passed as an array to allow for alternative plurals when using
* this argument as a base to construct the capabilities, e.g.
diff --git a/tests/phpunit/tests/post/types.php b/tests/phpunit/tests/post/types.php
index 96519586d6cff..6024fac2858d2 100644
--- a/tests/phpunit/tests/post/types.php
+++ b/tests/phpunit/tests/post/types.php
@@ -676,4 +676,24 @@ public function test_register_post_type_override_is_embeddable() {
);
$this->assertFalse( $post_type->embeddable, 'Post type should not be embeddable even though it is public' );
}
+
+ /**
+ * @ticket 45035
+ * @covers ::register_post_type()
+ */
+ public function test_register_post_type_at_a_glance_should_default_to_value_of_show_in_menu() {
+ /*
+ * 'public' Default is false
+ * 'show_ui' Default is null ('public')
+ * 'show_in_menu' Default is null ('show_ui' > 'public')
+ * 'at_a_glance' Default is null ('show_in_menu' > 'show_ui' > 'public')
+ */
+ $args = register_post_type( $this->post_type, array( 'public' => $public = false ) );
+ // Should fall back to 'show_in_menu'.
+ $this->assertSame( $args->show_in_menu, $args->at_a_glance );
+ // Should fall back to 'show_ui'.
+ $this->assertSame( $args->show_ui, $args->at_a_glance );
+ // Should fall back to 'public'.
+ $this->assertSame( $public, $args->at_a_glance );
+ }
}