Ticket #37782: 37782.14.diff
File 37782.14.diff, 12.7 KB (added by , 6 years ago) |
---|
-
src/wp-admin/css/nav-menus.css
413 413 margin-top: -4px; 414 414 } 415 415 416 .menu-item-title .post-state { 417 font-weight: 600; 418 } 419 416 420 /* Nav Menu */ 417 421 #menu-container .inside { 418 422 padding-bottom: 10px; -
src/wp-admin/includes/class-walker-nav-menu-checklist.php
94 94 } elseif ( isset( $item->post_type ) ) { 95 95 /** This filter is documented in wp-includes/post-template.php */ 96 96 $title = apply_filters( 'the_title', $item->post_title, $item->ID ); 97 if ( ! empty( $item->front_or_home ) && _x( 'Home', 'nav menu home label' ) !== $title ) {98 /* translators: %s: front page title */99 $title = sprintf( _x( 'Home: %s', 'nav menu front page title' ), $title );100 }101 97 } 102 98 103 99 $output .= isset( $title ) ? esc_html( $title ) : esc_html( $item->title ); 100 101 if ( empty( $item->label ) && isset( $item->post_type ) && 'page' === $item->post_type ) { 102 // Append post states. 103 $output .= _post_states( $item, false ); 104 } 105 104 106 $output .= '</label>'; 105 107 106 108 // Menu item hidden fields -
src/wp-admin/includes/nav-menu.php
354 354 $args = array_merge( $args, (array) $box['args']->_default_query ); 355 355 } 356 356 357 /* 358 * If we're dealing with pages, let's prioritize the Front Page, 359 * Posts Page and Privacy Policy Page at the top of the list. 360 */ 361 $important_pages = array(); 362 if ( 'page' == $post_type_name ) { 363 $suppress_page_ids = array(); 364 365 // Insert Front Page or custom Home link. 366 $front_page = 'page' == get_option( 'show_on_front' ) ? (int) get_option( 'page_on_front' ) : 0; 367 368 $front_page_obj = null; 369 if ( ! empty( $front_page ) ) { 370 $front_page_obj = get_post( $front_page ); 371 $front_page_obj->front_or_home = true; 372 373 $important_pages[] = $front_page_obj; 374 $suppress_page_ids[] = $front_page_obj->ID; 375 } else { 376 $_nav_menu_placeholder = ( 0 > $_nav_menu_placeholder ) ? intval( $_nav_menu_placeholder ) - 1 : -1; 377 $front_page_obj = (object) array( 378 'front_or_home' => true, 379 'ID' => 0, 380 'object_id' => $_nav_menu_placeholder, 381 'post_content' => '', 382 'post_excerpt' => '', 383 'post_parent' => '', 384 'post_title' => _x( 'Home', 'nav menu home label' ), 385 'post_type' => 'nav_menu_item', 386 'type' => 'custom', 387 'url' => home_url( '/' ), 388 ); 389 390 $important_pages[] = $front_page_obj; 391 } 392 393 // Insert Posts Page. 394 $posts_page = 'page' == get_option( 'show_on_front' ) ? (int) get_option( 'page_for_posts' ) : 0; 395 396 if ( ! empty( $posts_page ) ) { 397 $posts_page_obj = get_post( $posts_page ); 398 $posts_page_obj->posts_page = true; 399 400 $important_pages[] = $posts_page_obj; 401 $suppress_page_ids[] = $posts_page_obj->ID; 402 } 403 404 // Insert Privacy Policy Page. 405 $privacy_policy_page_id = (int) get_option( 'wp_page_for_privacy_policy' ); 406 407 if ( ! empty( $privacy_policy_page_id ) ) { 408 $privacy_policy_page = get_post( $privacy_policy_page_id ); 409 if ( $privacy_policy_page instanceof WP_Post && 'publish' === $privacy_policy_page->post_status ) { 410 $privacy_policy_page->privacy_policy_page = true; 411 412 $important_pages[] = $privacy_policy_page; 413 $suppress_page_ids[] = $privacy_policy_page->ID; 414 } 415 } 416 417 // Add suppression array to arguments for WP_Query. 418 if ( ! empty( $suppress_page_ids ) ) { 419 $args['post__not_in'] = $suppress_page_ids; 420 } 421 } 422 357 423 // @todo transient caching of these results with proper invalidation on updating of a post of this type 358 424 $get_posts = new WP_Query; 359 425 $posts = $get_posts->query( $args ); 426 427 // Only suppress and insert when more than just suppression pages available. 360 428 if ( ! $get_posts->post_count ) { 361 echo '<p>' . __( 'No items.' ) . '</p>'; 362 return; 429 if ( ! empty( $suppress_page_ids ) ) { 430 unset( $args['post__not_in'] ); 431 $get_posts = new WP_Query; 432 $posts = $get_posts->query( $args ); 433 } else { 434 echo '<p>' . __( 'No items.' ) . '</p>'; 435 return; 436 } 437 } elseif ( ! empty( $important_pages ) ) { 438 $posts = array_merge( $important_pages, $posts ); 363 439 } 364 440 365 441 $num_pages = $get_posts->max_num_pages; … … 520 596 <?php 521 597 $args['walker'] = $walker; 522 598 523 /*524 * If we're dealing with pages, let's put a checkbox for the front525 * page at the top of the list.526 */527 if ( 'page' == $post_type_name ) {528 $front_page = 'page' == get_option( 'show_on_front' ) ? (int) get_option( 'page_on_front' ) : 0;529 if ( ! empty( $front_page ) ) {530 $front_page_obj = get_post( $front_page );531 $front_page_obj->front_or_home = true;532 array_unshift( $posts, $front_page_obj );533 } else {534 $_nav_menu_placeholder = ( 0 > $_nav_menu_placeholder ) ? intval( $_nav_menu_placeholder ) - 1 : -1;535 array_unshift(536 $posts,537 (object) array(538 'front_or_home' => true,539 'ID' => 0,540 'object_id' => $_nav_menu_placeholder,541 'post_content' => '',542 'post_excerpt' => '',543 'post_parent' => '',544 'post_title' => _x( 'Home', 'nav menu home label' ),545 'post_type' => 'nav_menu_item',546 'type' => 'custom',547 'url' => home_url( '/' ),548 )549 );550 }551 }552 553 599 $post_type = get_post_type_object( $post_type_name ); 554 600 555 601 if ( $post_type->has_archive ) { -
src/wp-admin/includes/template.php
2009 2009 } 2010 2010 2011 2011 /** 2012 * @param WP_Post $post 2012 * Function to echo or return the Post States as HTML. 2013 * 2014 * @since 2.8.0 2015 * 2016 * @param WP_Post $post The post to retrieve states for. 2017 * @param boolean $echo Optional. Whether to echo or return the Post States as an HTML string. Default true for echo. 2018 * 2019 * @return string|void Post States string when echo is false. 2013 2020 */ 2014 function _post_states( $post ) { 2021 function _post_states( $post, $echo = true ) { 2022 $post_states = get_post_states( $post ); 2023 $post_states_string = ''; 2024 2025 if ( ! empty( $post_states ) ) { 2026 $state_count = count( $post_states ); 2027 $i = 0; 2028 2029 $post_states_string .= ' — '; 2030 foreach ( $post_states as $state ) { 2031 ++$i; 2032 ( $i == $state_count ) ? $sep = '' : $sep = ', '; 2033 $post_states_string .= "<span class='post-state'>$state$sep</span>"; 2034 } 2035 } 2036 2037 if ( $echo ) { 2038 echo $post_states_string; 2039 } 2040 2041 return $post_states_string; 2042 } 2043 2044 /** 2045 * Function to retrieve an array of Post States from a Post. 2046 * 2047 * @since 5.2.0 2048 * 2049 * @param WP_Post $post The post to retrieve states for. 2050 * 2051 * @return array $post_states The array of translated post states. 2052 * 2053 */ 2054 function get_post_states( $post ) { 2015 2055 $post_states = array(); 2016 2056 if ( isset( $_REQUEST['post_status'] ) ) { 2017 2057 $post_status = $_REQUEST['post_status']; … … 2022 2062 if ( ! empty( $post->post_password ) ) { 2023 2063 $post_states['protected'] = __( 'Password protected' ); 2024 2064 } 2065 2025 2066 if ( 'private' == $post->post_status && 'private' != $post_status ) { 2026 2067 $post_states['private'] = __( 'Private' ); 2027 2068 } 2069 2028 2070 if ( 'draft' === $post->post_status ) { 2029 2071 if ( get_post_meta( $post->ID, '_customize_changeset_uuid', true ) ) { 2030 2072 $post_states[] = __( 'Customization Draft' ); … … 2034 2076 } elseif ( 'trash' === $post->post_status && get_post_meta( $post->ID, '_customize_changeset_uuid', true ) ) { 2035 2077 $post_states[] = __( 'Customization Draft' ); 2036 2078 } 2079 2037 2080 if ( 'pending' == $post->post_status && 'pending' != $post_status ) { 2038 2081 $post_states['pending'] = _x( 'Pending', 'post status' ); 2039 2082 } 2083 2040 2084 if ( is_sticky( $post->ID ) ) { 2041 2085 $post_states['sticky'] = __( 'Sticky' ); 2042 2086 } … … 2068 2112 * @param string[] $post_states An array of post display states. 2069 2113 * @param WP_Post $post The current post object. 2070 2114 */ 2071 $post_states = apply_filters( 'display_post_states', $post_states, $post ); 2072 2073 if ( ! empty( $post_states ) ) { 2074 $state_count = count( $post_states ); 2075 $i = 0; 2076 echo ' — '; 2077 foreach ( $post_states as $state ) { 2078 ++$i; 2079 ( $i == $state_count ) ? $sep = '' : $sep = ', '; 2080 echo "<span class='post-state'>$state$sep</span>"; 2081 } 2082 } 2083 2115 return apply_filters( 'display_post_states', $post_states, $post ); 2084 2116 } 2085 2117 2086 2118 /** -
tests/phpunit/tests/menu/wpNavMenuItemPostTypeMetaBox.php
1 <?php 2 /** 3 * Test cases for the `wp_nav_menu_item_post_type_meta_box()` function. 4 * 5 * @package WordPress 6 * @subpackage UnitTests 7 * @since 5.2.0 8 */ 9 10 require_once ABSPATH . 'wp-admin/includes/nav-menu.php'; 11 12 /** 13 * Tests_Menu_WpNavMenuItemPostTypeMetaBox class. 14 * 15 * @group navmenus 16 * @covers ::wp_nav_menu_item_post_type_meta_box() 17 * 18 * @since 5.2.0 19 */ 20 class Tests_Menu_WpNavMenuItemPostTypeMetaBox extends WP_UnitTestCase { 21 22 /** 23 * The function should contain no items without pages. 24 * 25 * @ticket 37782 26 */ 27 public function test_should_contain_no_items_without_pages() { 28 29 $item = apply_filters( 'nav_menu_meta_box_object', get_post_type_object( 'page' ) ); 30 31 $box = array( 32 'id' => 'add-' . $item->name, 33 'title' => $item->labels->name, 34 'callback' => 'wp_nav_menu_item_post_type_meta_box', 35 'args' => $item, 36 ); 37 38 $output = get_echo( 'wp_nav_menu_item_post_type_meta_box', array( null, $box ) ); 39 40 $this->assertContains( 'No items', $output ); 41 $this->assertSame( 0, substr_count( $output, '<li>' ) ); 42 } 43 44 /** 45 * The function should include a page only once, when viewing all pages. 46 * 47 * @ticket 37782 48 */ 49 public function test_should_contain_page_only_once_when_viewing_all() { 50 $page = $this->factory()->post->create_and_get( 51 array( 52 'post_title' => 'My Test Page', 53 'post_type' => 'page', 54 ) 55 ); 56 57 $item = apply_filters( 'nav_menu_meta_box_object', get_post_type_object( 'page' ) ); 58 59 $box = array( 60 'id' => 'add-' . $item->name, 61 'title' => $item->labels->name, 62 'callback' => 'wp_nav_menu_item_post_type_meta_box', 63 'args' => $item, 64 ); 65 66 $output = get_echo( 'wp_nav_menu_item_post_type_meta_box', array( null, $box ) ); 67 68 // Clean up. 69 wp_delete_post( $page->ID ); 70 71 // Extract the "View All" part. 72 preg_match( '~<div id="page-all"[^>]*>.*?</div>~i', str_replace( "\n", '', $output ), $matches ); 73 74 $this->assertTrue( isset( $matches[0] ) ); 75 $this->assertSame( 2, substr_count( $matches[0], '<li>' ) ); 76 $this->assertContains( sprintf( '> %s</label>', $page->post_title ), $matches[0] ); 77 $this->assertContains( '> Home</label>', $matches[0] ); 78 } 79 80 /** 81 * The function should include the front page only once, when viewing all pages. 82 * 83 * @ticket 37782 84 */ 85 public function test_should_contain_front_page_only_once_when_viewing_all() { 86 $page = $this->factory()->post->create_and_get( 87 array( 88 'post_title' => 'My Test Page', 89 'post_type' => 'page', 90 ) 91 ); 92 93 $item = apply_filters( 'nav_menu_meta_box_object', get_post_type_object( 'page' ) ); 94 95 $box = array( 96 'id' => 'add-' . $item->name, 97 'title' => $item->labels->name, 98 'callback' => 'wp_nav_menu_item_post_type_meta_box', 99 'args' => $item, 100 ); 101 102 // Front page setup. 103 update_option( 'show_on_front', 'page' ); 104 update_option( 'page_on_front', $page->ID ); 105 106 $output = get_echo( 'wp_nav_menu_item_post_type_meta_box', array( null, $box ) ); 107 108 // Clean up. 109 delete_option( 'show_on_front' ); 110 delete_option( 'page_on_front' ); 111 wp_delete_post( $page->ID ); 112 113 // Extract the "View All" part. 114 preg_match( '~<div id="page-all"[^>]*>.*?</div>~i', str_replace( "\n", '', $output ), $matches ); 115 116 $this->assertTrue( isset( $matches[0] ) ); 117 $this->assertSame( 1, substr_count( $matches[0], '<li>' ) ); 118 $this->assertContains( sprintf( "> %s — <span class='post-state'>Front Page</span></label>", $page->post_title ), $matches[0] ); 119 $this->assertNotContains( sprintf( "> %s</label>", $page->post_title ), $matches[0] ); 120 } 121 }