diff --git a/src/wp-admin/includes/meta-boxes.php b/src/wp-admin/includes/meta-boxes.php index 506b38b3b9af0..835c2404c49aa 100644 --- a/src/wp-admin/includes/meta-boxes.php +++ b/src/wp-admin/includes/meta-boxes.php @@ -1010,6 +1010,7 @@ function page_attributes_meta_box( $post ) { 'show_option_none' => __( '(no parent)' ), 'sort_column' => 'menu_order, post_title', 'echo' => 0, + 'post_status' => array( 'publish', 'draft', 'pending', 'private' ), ); /** diff --git a/src/wp-includes/post.php b/src/wp-includes/post.php index 4382aa003ff62..68e79e5c01151 100644 --- a/src/wp-includes/post.php +++ b/src/wp-includes/post.php @@ -6268,6 +6268,23 @@ function get_page_children( $page_id, $pages ) { } } + if ( 0 === $page_id ) { + $parent_ids = array_keys( $children ); + $page_ids = wp_list_pluck( $pages, 'ID' ); + + foreach ( $parent_ids as $parent_id ) { + if ( 0 !== $parent_id && ! in_array( $parent_id, $page_ids, true ) ) { + foreach ( $children[ $parent_id ] as $orphan ) { + $page_list[] = $orphan; + if ( isset( $children[ $orphan->ID ] ) ) { + $orphan_pages = get_page_children( $orphan->ID, $pages ); + $page_list = array_merge( $page_list, $orphan_pages ); + } + } + } + } + } + return $page_list; } diff --git a/tests/phpunit/tests/post/wpDropdownPages.php b/tests/phpunit/tests/post/wpDropdownPages.php index d838875f1d315..3415cac085eb6 100644 --- a/tests/phpunit/tests/post/wpDropdownPages.php +++ b/tests/phpunit/tests/post/wpDropdownPages.php @@ -219,4 +219,65 @@ public function test_wp_dropdown_pages_should_obey_class_parameter() { $this->assertMatchesRegularExpression( '/]+class=\'bar\'/', $found ); } + + /** + * Test that published child pages remain selectable when parent is trashed. + * + * @ticket 11235 + */ + public function test_child_page_available_when_parent_trashed() { + $parent_id = self::factory()->post->create( + array( + 'post_type' => 'page', + 'post_status' => 'publish', + ) + ); + + $child_id = self::factory()->post->create( + array( + 'post_type' => 'page', + 'post_parent' => $parent_id, + 'post_status' => 'publish', + ) + ); + + wp_trash_post( $parent_id ); + + $output = wp_dropdown_pages( array( 'echo' => 0 ) ); + + $this->assertStringContainsString( 'value="' . $child_id . '"', $output, 'Published child page should remain available even when parent is trashed.' ); + $this->assertStringNotContainsString( 'value="' . $parent_id . '"', $output, 'Trashed parent should not appear in dropdown.' ); + } + + /** + * Test that published child pages remain selectable when parent is draft or pending. + * + * @ticket 11235 + */ + public function test_child_page_available_when_parent_not_published() { + $parent_id = self::factory()->post->create( + array( + 'post_type' => 'page', + 'post_status' => 'publish', + ) + ); + + $child_id = self::factory()->post->create( + array( + 'post_type' => 'page', + 'post_parent' => $parent_id, + 'post_status' => 'publish', + ) + ); + + wp_update_post( + array( + 'ID' => $parent_id, + 'post_status' => 'draft', + ) + ); + + $output = wp_dropdown_pages( array( 'echo' => 0 ) ); + $this->assertStringContainsString( 'value="' . $child_id . '"', $output, 'Published child should be available when parent is draft.' ); + } }