diff --git a/src/wp-admin/css/nav-menus.css b/src/wp-admin/css/nav-menus.css index 15d238d169..8b68ac5400 100644 --- a/src/wp-admin/css/nav-menus.css +++ b/src/wp-admin/css/nav-menus.css @@ -413,6 +413,10 @@ ul.add-menu-item-tabs li { margin-top: -4px; } +.menu-item-title .post-state { + font-weight: 600; +} + /* Nav Menu */ #menu-container .inside { padding-bottom: 10px; diff --git a/src/wp-admin/includes/class-walker-nav-menu-checklist.php b/src/wp-admin/includes/class-walker-nav-menu-checklist.php index 61da6cdc83..d518280f34 100644 --- a/src/wp-admin/includes/class-walker-nav-menu-checklist.php +++ b/src/wp-admin/includes/class-walker-nav-menu-checklist.php @@ -94,13 +94,15 @@ class Walker_Nav_Menu_Checklist extends Walker_Nav_Menu { } elseif ( isset( $item->post_type ) ) { /** This filter is documented in wp-includes/post-template.php */ $title = apply_filters( 'the_title', $item->post_title, $item->ID ); - if ( ! empty( $item->front_or_home ) && _x( 'Home', 'nav menu home label' ) !== $title ) { - /* translators: %s: Front page title. */ - $title = sprintf( _x( 'Home: %s', 'nav menu front page title' ), $title ); - } } $output .= isset( $title ) ? esc_html( $title ) : esc_html( $item->title ); + + if ( empty( $item->label ) && isset( $item->post_type ) && 'page' === $item->post_type ) { + // Append post states. + $output .= _post_states( $item, false ); + } + $output .= ''; // Menu item hidden fields diff --git a/src/wp-admin/includes/nav-menu.php b/src/wp-admin/includes/nav-menu.php index 11e8c7f92f..274ee89d47 100644 --- a/src/wp-admin/includes/nav-menu.php +++ b/src/wp-admin/includes/nav-menu.php @@ -354,12 +354,88 @@ function wp_nav_menu_item_post_type_meta_box( $object, $box ) { $args = array_merge( $args, (array) $box['args']->_default_query ); } + /* + * If we're dealing with pages, let's prioritize the Front Page, + * Posts Page and Privacy Policy Page at the top of the list. + */ + $important_pages = array(); + if ( 'page' == $post_type_name ) { + $suppress_page_ids = array(); + + // Insert Front Page or custom Home link. + $front_page = 'page' == get_option( 'show_on_front' ) ? (int) get_option( 'page_on_front' ) : 0; + + $front_page_obj = null; + if ( ! empty( $front_page ) ) { + $front_page_obj = get_post( $front_page ); + $front_page_obj->front_or_home = true; + + $important_pages[] = $front_page_obj; + $suppress_page_ids[] = $front_page_obj->ID; + } else { + $_nav_menu_placeholder = ( 0 > $_nav_menu_placeholder ) ? intval( $_nav_menu_placeholder ) - 1 : -1; + $front_page_obj = (object) array( + 'front_or_home' => true, + 'ID' => 0, + 'object_id' => $_nav_menu_placeholder, + 'post_content' => '', + 'post_excerpt' => '', + 'post_parent' => '', + 'post_title' => _x( 'Home', 'nav menu home label' ), + 'post_type' => 'nav_menu_item', + 'type' => 'custom', + 'url' => home_url( '/' ), + ); + + $important_pages[] = $front_page_obj; + } + + // Insert Posts Page. + $posts_page = 'page' == get_option( 'show_on_front' ) ? (int) get_option( 'page_for_posts' ) : 0; + + if ( ! empty( $posts_page ) ) { + $posts_page_obj = get_post( $posts_page ); + $posts_page_obj->posts_page = true; + + $important_pages[] = $posts_page_obj; + $suppress_page_ids[] = $posts_page_obj->ID; + } + + // Insert Privacy Policy Page. + $privacy_policy_page_id = (int) get_option( 'wp_page_for_privacy_policy' ); + + if ( ! empty( $privacy_policy_page_id ) ) { + $privacy_policy_page = get_post( $privacy_policy_page_id ); + if ( $privacy_policy_page instanceof WP_Post && 'publish' === $privacy_policy_page->post_status ) { + $privacy_policy_page->privacy_policy_page = true; + + $important_pages[] = $privacy_policy_page; + $suppress_page_ids[] = $privacy_policy_page->ID; + } + } + + // Add suppression array to arguments for WP_Query. + if ( ! empty( $suppress_page_ids ) ) { + $args['post__not_in'] = $suppress_page_ids; + } + } + // @todo transient caching of these results with proper invalidation on updating of a post of this type $get_posts = new WP_Query; $posts = $get_posts->query( $args ); + + // Only suppress and insert when more than just suppression pages available. if ( ! $get_posts->post_count ) { - echo '
' . __( 'No items.' ) . '
'; - return; + if ( ! empty( $suppress_page_ids ) ) { + unset( $args['post__not_in'] ); + $get_posts = new WP_Query; + $posts = $get_posts->query( $args ); + } else { + echo '' . __( 'No items.' ) . '
'; + return; + } + } elseif ( ! empty( $important_pages ) ) { + $posts = array_merge( $important_pages, $posts ); } $num_pages = $get_posts->max_num_pages; @@ -522,36 +598,6 @@ function wp_nav_menu_item_post_type_meta_box( $object, $box ) { front_or_home = true; - array_unshift( $posts, $front_page_obj ); - } else { - $_nav_menu_placeholder = ( 0 > $_nav_menu_placeholder ) ? intval( $_nav_menu_placeholder ) - 1 : -1; - array_unshift( - $posts, - (object) array( - 'front_or_home' => true, - 'ID' => 0, - 'object_id' => $_nav_menu_placeholder, - 'post_content' => '', - 'post_excerpt' => '', - 'post_parent' => '', - 'post_title' => _x( 'Home', 'nav menu home label' ), - 'post_type' => 'nav_menu_item', - 'type' => 'custom', - 'url' => home_url( '/' ), - ) - ); - } - } - $post_type = get_post_type_object( $post_type_name ); if ( $post_type->has_archive ) { diff --git a/src/wp-admin/includes/template.php b/src/wp-admin/includes/template.php index d746575225..8777aba514 100644 --- a/src/wp-admin/includes/template.php +++ b/src/wp-admin/includes/template.php @@ -2062,9 +2062,50 @@ function iframe_footer() { } /** - * @param WP_Post $post + * Function to echo or return the Post States as HTML. + * + * @since 2.7.0 + * @since 5.3.0 Adopted use of get_post_states + * + * @param WP_Post $post The post to retrieve states for. + * @param boolean $echo Optional. Whether to echo or return the Post States as an HTML string. Default true for echo. + * + * @return string|void Post States string when echo is false. */ -function _post_states( $post ) { +function _post_states( $post, $echo = true ) { + $post_states = get_post_states( $post ); + $post_states_string = ''; + + if ( ! empty( $post_states ) ) { + $state_count = count( $post_states ); + $i = 0; + + $post_states_string .= ' — '; + foreach ( $post_states as $state ) { + ++$i; + ( $i == $state_count ) ? $sep = '' : $sep = ', '; + $post_states_string .= "$state$sep"; + } + } + + if ( $echo ) { + echo $post_states_string; + } + + return $post_states_string; +} + +/** + * Function to retrieve an array of Post States from a Post. + * + * @since 5.3.0 + * + * @param WP_Post $post The post to retrieve states for. + * + * @return array $post_states The array of translated post states. + * + */ +function get_post_states( $post ) { $post_states = array(); if ( isset( $_REQUEST['post_status'] ) ) { $post_status = $_REQUEST['post_status']; @@ -2073,43 +2114,47 @@ function _post_states( $post ) { } if ( ! empty( $post->post_password ) ) { - $post_states['protected'] = __( 'Password protected' ); + $post_states['protected'] = _x( 'Password protected', 'post status' ); } + if ( 'private' == $post->post_status && 'private' != $post_status ) { - $post_states['private'] = __( 'Private' ); + $post_states['private'] = _x( 'Private', 'post status' ); } + if ( 'draft' === $post->post_status ) { if ( get_post_meta( $post->ID, '_customize_changeset_uuid', true ) ) { $post_states[] = __( 'Customization Draft' ); } elseif ( 'draft' !== $post_status ) { - $post_states['draft'] = __( 'Draft' ); + $post_states['draft'] = _x( 'Draft', 'post status' ); } } elseif ( 'trash' === $post->post_status && get_post_meta( $post->ID, '_customize_changeset_uuid', true ) ) { - $post_states[] = __( 'Customization Draft' ); + $post_states[] = _x( 'Customization Draft', 'post status' ); } + if ( 'pending' == $post->post_status && 'pending' != $post_status ) { $post_states['pending'] = _x( 'Pending', 'post status' ); } + if ( is_sticky( $post->ID ) ) { - $post_states['sticky'] = __( 'Sticky' ); + $post_states['sticky'] = _x( 'Sticky', 'post status' ); } if ( 'future' === $post->post_status ) { - $post_states['scheduled'] = __( 'Scheduled' ); + $post_states['scheduled'] = _x( 'Scheduled', 'post status' ); } if ( 'page' === get_option( 'show_on_front' ) ) { if ( intval( get_option( 'page_on_front' ) ) === $post->ID ) { - $post_states['page_on_front'] = __( 'Front Page' ); + $post_states['page_on_front'] = _x( 'Front Page', 'page label' ); } if ( intval( get_option( 'page_for_posts' ) ) === $post->ID ) { - $post_states['page_for_posts'] = __( 'Posts Page' ); + $post_states['page_for_posts'] = _x( 'Posts Page', 'page label' ); } } if ( intval( get_option( 'wp_page_for_privacy_policy' ) ) === $post->ID ) { - $post_states['page_for_privacy_policy'] = __( 'Privacy Policy Page' ); + $post_states['page_for_privacy_policy'] = _x( 'Privacy Policy Page', 'page label' ); } /** @@ -2121,19 +2166,7 @@ function _post_states( $post ) { * @param string[] $post_states An array of post display states. * @param WP_Post $post The current post object. */ - $post_states = apply_filters( 'display_post_states', $post_states, $post ); - - if ( ! empty( $post_states ) ) { - $state_count = count( $post_states ); - $i = 0; - echo ' — '; - foreach ( $post_states as $state ) { - ++$i; - ( $i == $state_count ) ? $sep = '' : $sep = ', '; - echo "$state$sep"; - } - } - + return apply_filters( 'display_post_states', $post_states, $post ); } /**