WordPress.org

Make WordPress Core

Ticket #38615: 38615.15.diff

File 38615.15.diff, 22.8 KB (added by helen, 3 years ago)

Δ https://github.com/xwp/wordpress-develop/pull/201/files/a3dd024..da2d931

  • src/wp-content/themes/twentyseventeen/functions.php

     
    123123
    124124                'posts' => array(
    125125                        'home',
    126                         'about',
    127                         'contact',
    128                         'blog',
    129                         'homepage-section',
     126                        'about' => array(
     127                                'thumbnail' => '{{image-sandwich}}',
     128                        ),
     129                        'contact' => array(
     130                                'thumbnail' => '{{image-espresso}}',
     131                        ),
     132                        'blog' => array(
     133                                'thumbnail' => '{{image-coffee}}',
     134                        ),
     135                        'homepage-section' => array(
     136                                'thumbnail' => '{{image-espresso}}',
     137                        ),
    130138                ),
    131139
     140                'attachments' => array(
     141                        'image-espresso' => array(
     142                                'post_title' => _x( 'Espresso', 'Theme starter content' ),
     143                                'file' => 'assets/images/espresso.jpg',
     144                        ),
     145                        'image-sandwich' => array(
     146                                'post_title' => _x( 'Sandwich', 'Theme starter content' ),
     147                                'file' => 'assets/images/sandwich.jpg',
     148                        ),
     149                        'image-coffee' => array(
     150                                'post_title' => _x( 'Coffee', 'Theme starter content' ),
     151                                'file' => 'assets/images/coffee.jpg',
     152                        ),
     153                ),
     154
    132155                'options' => array(
    133156                        'show_on_front' => 'page',
    134157                        'page_on_front' => '{{home}}',
  • src/wp-includes/class-wp-customize-manager.php

     
    916916                }
    917917
    918918                $sidebars_widgets = isset( $starter_content['widgets'] ) && ! empty( $this->widgets ) ? $starter_content['widgets'] : array();
     919                $attachments = isset( $starter_content['attachments'] ) && ! empty( $this->nav_menus ) ? $starter_content['attachments'] : array();
    919920                $posts = isset( $starter_content['posts'] ) && ! empty( $this->nav_menus ) ? $starter_content['posts'] : array();
    920921                $options = isset( $starter_content['options'] ) ? $starter_content['options'] : array();
    921922                $nav_menus = isset( $starter_content['nav_menus'] ) && ! empty( $this->nav_menus ) ? $starter_content['nav_menus'] : array();
     
    965966                        }
    966967                }
    967968
    968                 // Posts & pages.
    969                 if ( ! empty( $posts ) ) {
    970                         $nav_menus_created_posts = array();
    971                         if ( ! empty( $changeset_data['nav_menus_created_posts']['value'] ) ) {
    972                                 $nav_menus_created_posts = $changeset_data['nav_menus_created_posts']['value'];
     969                $starter_content_auto_draft_post_ids = array();
     970                if ( ! empty( $changeset_data['nav_menus_created_posts']['value'] ) ) {
     971                        $starter_content_auto_draft_post_ids = array_merge( $starter_content_auto_draft_post_ids, $changeset_data['nav_menus_created_posts']['value'] );
     972                }
     973
     974                $existing_starter_content_posts = array();
     975                if ( ! empty( $starter_content_auto_draft_post_ids ) ) {
     976                        $existing_posts_query = new WP_Query( array(
     977                                'post__in' => $starter_content_auto_draft_post_ids,
     978                                'post_status' => 'auto-draft',
     979                                'post_type' => 'any',
     980                                'number' => -1,
     981                        ) );
     982                        foreach ( $existing_posts_query->posts as $existing_post ) {
     983                                $existing_starter_content_posts[ $existing_post->post_type . ':' . $existing_post->post_name ] = $existing_post;
    973984                        }
     985                }
    974986
    975                         $existing_posts = array();
    976                         if ( ! empty( $nav_menus_created_posts ) ) {
    977                                 $existing_posts_query = new WP_Query( array(
    978                                         'post__in' => $nav_menus_created_posts,
    979                                         'post_status' => 'auto-draft',
    980                                         'post_type' => 'any',
    981                                         'number' => -1,
    982                                 ) );
    983                                 foreach ( $existing_posts_query->posts as $existing_post ) {
    984                                         $existing_posts[ $existing_post->post_type . ':' . $existing_post->post_name ] = $existing_post;
     987                // Attachments are technically posts but handled differently.
     988                if ( ! empty( $attachments ) ) {
     989                        // Such is The WordPress Way.
     990                        require_once( ABSPATH . 'wp-admin/includes/file.php' );
     991                        require_once( ABSPATH . 'wp-admin/includes/media.php' );
     992                        require_once( ABSPATH . 'wp-admin/includes/image.php' );
     993
     994                        $attachment_ids = array();
     995
     996                        foreach ( $attachments as $symbol => $attachment ) {
     997
     998                                // A file is required and URLs to files are not currently allowed.
     999                                if ( empty( $attachment['file'] ) || preg_match( '#^https?://$#', $attachment['file'] ) ) {
     1000                                        continue;
    9851001                                }
     1002
     1003                                $file_array = array();
     1004                                $file_path = null;
     1005                                if ( file_exists( $attachment['file'] ) ) {
     1006                                        $file_path = $attachment['file']; // Could be absolute path to file in plugin.
     1007                                } elseif ( is_child_theme() && file_exists( get_stylesheet_directory() . '/' . $attachment['file'] ) ) {
     1008                                        $file_path = get_stylesheet_directory() . '/' . $attachment['file'];
     1009                                } elseif ( file_exists( get_template_directory() . '/' . $attachment['file'] ) ) {
     1010                                        $file_path = get_template_directory() . '/' . $attachment['file'];
     1011                                } else {
     1012                                        continue;
     1013                                }
     1014                                $file_array['name'] = basename( $attachment['file'] );
     1015
     1016                                // Skip file types that are not recognized.
     1017                                $checked_filetype = wp_check_filetype( $file_array['name'] );
     1018                                if ( empty( $checked_filetype['type'] ) ) {
     1019                                        continue;
     1020                                }
     1021
     1022                                // Ensure post_name is set since not automatically derived from post_title for new auto-draft posts.
     1023                                if ( empty( $attachment['post_name'] ) ) {
     1024                                        if ( ! empty( $attachment['post_title'] ) ) {
     1025                                                $attachment['post_name'] = sanitize_title( $attachment['post_title'] );
     1026                                        } else {
     1027                                                $attachment['post_name'] = sanitize_title( preg_replace( '/\.\w+$/', '', $file_array['name'] ) );
     1028                                        }
     1029                                }
     1030
     1031                                $attachment_id = null;
     1032                                $attached_file = null;
     1033                                if ( isset( $existing_starter_content_posts[ 'attachment:' . $attachment['post_name'] ] ) ) {
     1034                                        $attachment_post = $existing_starter_content_posts[ 'attachment:' . $attachment['post_name'] ];
     1035                                        $attachment_id = $attachment_post->ID;
     1036                                        $attached_file = get_attached_file( $attachment_id );
     1037                                        if ( empty( $attached_file ) || ! file_exists( $attached_file ) ) {
     1038                                                $attachment_id = null;
     1039                                                $attached_file = null;
     1040                                        } elseif ( $this->get_stylesheet() !== get_post_meta( $attachment_post->ID, '_starter_content_theme', true ) ) {
     1041
     1042                                                // Re-generate attachment metadata since it was previously generated for a different theme.
     1043                                                $metadata = wp_generate_attachment_metadata( $attachment_post->ID, $attached_file );
     1044                                                wp_update_attachment_metadata( $attachment_id, $metadata );
     1045                                                update_post_meta( $attachment_id, '_starter_content_theme', $this->get_stylesheet() );
     1046                                        }
     1047                                }
     1048
     1049                                // Insert the attachment auto-draft because it doesn't yet exist or the attached file is gone.
     1050                                if ( ! $attachment_id ) {
     1051
     1052                                        // Copy file to temp location so that original file won't get deleted from theme after sideloading.
     1053                                        $temp_file_name = wp_tempnam( basename( $file_path ) );
     1054                                        if ( $temp_file_name && copy( $file_path, $temp_file_name ) ) {
     1055                                                $file_array['tmp_name'] = $temp_file_name;
     1056                                        }
     1057                                        if ( empty( $file_array['tmp_name'] ) ) {
     1058                                                continue;
     1059                                        }
     1060
     1061                                        $attachment_post_data = array_merge(
     1062                                                wp_array_slice_assoc( $attachment, array( 'post_title', 'post_content', 'post_excerpt', 'post_name' ) ),
     1063                                                array(
     1064                                                        'post_status' => 'auto-draft', // So attachment will be garbage collected in a week if changeset is never published.
     1065                                                )
     1066                                        );
     1067
     1068                                        // In PHP < 5.6 filesize() returns 0 for the temp files unless we clear the file status cache.
     1069                                        // Technically, PHP < 5.6.0 || < 5.5.13 || < 5.4.29 but no need to be so targeted.
     1070                                        // See https://bugs.php.net/bug.php?id=65701
     1071                                        if ( version_compare( PHP_VERSION, '5.6', '<' ) ) {
     1072                                                clearstatcache();
     1073                                        }
     1074
     1075                                        $attachment_id = media_handle_sideload( $file_array, 0, null, $attachment_post_data );
     1076                                        if ( is_wp_error( $attachment_id ) ) {
     1077                                                continue;
     1078                                        }
     1079                                        update_post_meta( $attachment_id, '_starter_content_theme', $this->get_stylesheet() );
     1080                                }
     1081
     1082                                $attachment_ids[ $symbol ] = $attachment_id;
     1083                                $starter_content_auto_draft_post_ids = array_merge( $starter_content_auto_draft_post_ids, array_values( $attachment_ids ) );
    9861084                        }
     1085                }
    9871086
     1087                // Posts & pages.
     1088                if ( ! empty( $posts ) ) {
    9881089                        foreach ( array_keys( $posts ) as $post_symbol ) {
    9891090                                if ( empty( $posts[ $post_symbol ]['post_type'] ) ) {
    9901091                                        continue;
     
    9991100                                }
    10001101
    10011102                                // Use existing auto-draft post if one already exists with the same type and name.
    1002                                 if ( isset( $existing_posts[ $post_type . ':' . $post_name ] ) ) {
    1003                                         $posts[ $post_symbol ]['ID'] = $existing_posts[ $post_type . ':' . $post_name ]->ID;
     1103                                if ( isset( $existing_starter_content_posts[ $post_type . ':' . $post_name ] ) ) {
     1104                                        $posts[ $post_symbol ]['ID'] = $existing_starter_content_posts[ $post_type . ':' . $post_name ]->ID;
    10041105                                        continue;
    10051106                                }
    10061107
     1108                                // Translate the featured image symbol.
     1109                                if ( ! empty( $posts[ $post_symbol ]['thumbnail'] )
     1110                                        && preg_match( '/^{{(?P<symbol>.+)}}$/', $posts[ $post_symbol ]['thumbnail'], $matches )
     1111                                        && isset( $attachment_ids[ $matches['symbol'] ] ) ) {
     1112                                        $posts[ $post_symbol ]['meta_input']['_thumbnail_id'] = $attachment_ids[ $matches['symbol'] ];
     1113                                }
     1114
     1115                                if ( ! empty( $posts[ $post_symbol ]['template'] ) ) {
     1116                                        $posts[ $post_symbol ]['meta_input']['_wp_page_template'] = $posts[ $post_symbol ]['template'];
     1117                                }
     1118
    10071119                                $r = $this->nav_menus->insert_auto_draft_post( $posts[ $post_symbol ] );
    10081120                                if ( $r instanceof WP_Post ) {
    10091121                                        $posts[ $post_symbol ]['ID'] = $r->ID;
     
    10101122                                }
    10111123                        }
    10121124
    1013                         // The nav_menus_created_posts setting is why nav_menus component is dependency for adding posts.
     1125                        $starter_content_auto_draft_post_ids = array_merge( $starter_content_auto_draft_post_ids, wp_list_pluck( $posts, 'ID' ) );
     1126                }
     1127
     1128                // The nav_menus_created_posts setting is why nav_menus component is dependency for adding posts.
     1129                if ( ! empty( $this->nav_menus ) && ! empty( $starter_content_auto_draft_post_ids ) ) {
    10141130                        $setting_id = 'nav_menus_created_posts';
    1015                         if ( empty( $changeset_data[ $setting_id ] ) || ! empty( $changeset_data[ $setting_id ]['starter_content'] ) ) {
    1016                                 $nav_menus_created_posts = array_unique( array_merge( $nav_menus_created_posts, wp_list_pluck( $posts, 'ID' ) ) );
    1017                                 $this->set_post_value( $setting_id, array_values( $nav_menus_created_posts ) );
    1018                                 $this->pending_starter_content_settings_ids[] = $setting_id;
    1019                         }
     1131                        $this->set_post_value( $setting_id, array_unique( array_values( $starter_content_auto_draft_post_ids ) ) );
     1132                        $this->pending_starter_content_settings_ids[] = $setting_id;
    10201133                }
    10211134
    10221135                // Nav menus.
  • src/wp-includes/class-wp-customize-nav-menus.php

     
    11911191                $post_ids = $setting->post_value();
    11921192                if ( ! empty( $post_ids ) ) {
    11931193                        foreach ( $post_ids as $post_id ) {
     1194                                $target_status = 'attachment' === get_post_type( $post_id ) ? 'inherit' : 'publish';
     1195
    11941196                                // Note that wp_publish_post() cannot be used because unique slugs need to be assigned.
    1195                                 wp_update_post( array( 'ID' => $post_id, 'post_status' => 'publish' ) );
     1197                                wp_update_post( array( 'ID' => $post_id, 'post_status' => $target_status ) );
    11961198                        }
    11971199                }
    11981200        }
  • src/wp-includes/post.php

     
    30583058        }
    30593059
    30603060        $post_status = empty( $postarr['post_status'] ) ? 'draft' : $postarr['post_status'];
    3061         if ( 'attachment' === $post_type && ! in_array( $post_status, array( 'inherit', 'private', 'trash' ) ) ) {
     3061        if ( 'attachment' === $post_type && ! in_array( $post_status, array( 'inherit', 'private', 'trash', 'auto-draft' ), true ) ) {
    30623062                $post_status = 'inherit';
    30633063        }
    30643064
  • src/wp-includes/theme.php

     
    19861986                        // Widgets are grouped into sidebars.
    19871987                        case 'widgets' :
    19881988                                foreach ( $config[ $type ] as $sidebar_id => $widgets ) {
    1989                                         foreach ( $widgets as $widget ) {
     1989                                        foreach ( $widgets as $id => $widget ) {
    19901990                                                if ( is_array( $widget ) ) {
     1991
     1992                                                        // Item extends core content.
     1993                                                        if ( ! empty( $core_content[ $type ][ $id ] ) ) {
     1994                                                                $widget = array(
     1995                                                                        $core_content[ $type ][ $id ][0],
     1996                                                                        array_merge( $core_content[ $type ][ $id ][1], $widget ),
     1997                                                                );
     1998                                                        }
     1999
    19912000                                                        $content[ $type ][ $sidebar_id ][] = $widget;
    19922001                                                } elseif ( is_string( $widget ) && ! empty( $core_content[ $type ] ) && ! empty( $core_content[ $type ][ $widget ] ) ) {
    19932002                                                        $content[ $type ][ $sidebar_id ][] = $core_content[ $type ][ $widget ];
     
    20072016
    20082017                                        $content[ $type ][ $nav_menu_location ]['name'] = $nav_menu['name'];
    20092018
    2010                                         foreach ( $nav_menu['items'] as $nav_menu_item ) {
     2019                                        foreach ( $nav_menu['items'] as $id => $nav_menu_item ) {
    20112020                                                if ( is_array( $nav_menu_item ) ) {
     2021
     2022                                                        // Item extends core content.
     2023                                                        if ( ! empty( $core_content[ $type ][ $id ] ) ) {
     2024                                                                $nav_menu_item = array_merge( $core_content[ $type ][ $id ], $nav_menu_item );
     2025                                                        }
     2026
    20122027                                                        $content[ $type ][ $nav_menu_location ]['items'][] = $nav_menu_item;
    20132028                                                } elseif ( is_string( $nav_menu_item ) && ! empty( $core_content[ $type ] ) && ! empty( $core_content[ $type ][ $nav_menu_item ] ) ) {
    20142029                                                        $content[ $type ][ $nav_menu_location ]['items'][] = $core_content[ $type ][ $nav_menu_item ];
     
    20172032                                }
    20182033                                break;
    20192034
    2020                         // Everything else should map at the next level.
    2021                         default :
    2022                                 foreach( $config[ $type ] as $i => $item ) {
     2035                        // Attachments are posts but have special treatment.
     2036                        case 'attachments' :
     2037                                foreach ( $config[ $type ] as $id => $item ) {
     2038                                        if ( ! empty( $item['file'] ) ) {
     2039                                                $content[ $type ][ $id ] = $item;
     2040                                        }
     2041                                }
     2042                                break;
     2043
     2044                        // All that's left now are posts (besides attachments). Not a default case for the sake of clarity and future work.
     2045                        case 'posts' :
     2046                                foreach ( $config[ $type ] as $id => $item ) {
    20232047                                        if ( is_array( $item ) ) {
    2024                                                 $content[ $type ][ $i ] = $item;
    2025                                         } elseif ( is_string( $item ) && ! empty( $core_content[ $type ] ) && ! empty( $core_content[ $type ][ $item ] ) ) {
     2048
     2049                                                // Item extends core content.
     2050                                                if ( ! empty( $core_content[ $type ][ $id ] ) ) {
     2051                                                        $item = array_merge( $core_content[ $type ][ $id ], $item );
     2052                                                }
     2053
     2054                                                // Enforce a subset of fields.
     2055                                                $content[ $type ][ $id ] = wp_array_slice_assoc(
     2056                                                        $item,
     2057                                                        array(
     2058                                                                'post_type',
     2059                                                                'post_title',
     2060                                                                'post_excerpt',
     2061                                                                'post_name',
     2062                                                                'post_content',
     2063                                                                'menu_order',
     2064                                                                'comment_status',
     2065                                                                'thumbnail',
     2066                                                                'template',
     2067                                                        )
     2068                                                );
     2069                                        } elseif ( is_string( $item ) && ! empty( $core_content[ $type ][ $item ] ) ) {
    20262070                                                $content[ $type ][ $item ] = $core_content[ $type ][ $item ];
    20272071                                        }
    20282072                                }
  • tests/phpunit/tests/customize/manager.php

     
    313313         */
    314314        function test_import_theme_starter_content() {
    315315                wp_set_current_user( self::$admin_user_id );
     316                register_nav_menu( 'top', 'Top' );
    316317
    317318                global $wp_customize;
    318319                $wp_customize = new WP_Customize_Manager();
     
    343344                        ),
    344345                        'posts' => array(
    345346                                'home',
    346                                 'about',
     347                                'about' => array(
     348                                        'template' => 'sample-page-template.php',
     349                                ),
    347350                                'blog',
    348351                                'custom' => array(
    349352                                        'post_type' => 'post',
    350353                                        'post_title' => 'Custom',
     354                                        'thumbnail' => '{{featured-image-logo}}',
    351355                                ),
    352356                        ),
     357                        'attachments' => array(
     358                                'featured-image-logo' => array(
     359                                        'post_title' => 'Featured Image',
     360                                        'post_content' => 'Attachment Description',
     361                                        'post_excerpt' => 'Attachment Caption',
     362                                        'file' => DIR_TESTDATA . '/images/waffles.jpg',
     363                                ),
     364                        ),
    353365                        'options' => array(
    354366                                'blogname' => 'Starter Content Title',
    355367                                'blogdescription' => 'Starter Content Tagline',
     
    394406                $this->assertEquals( array( 'text-2', 'meta-3' ), $changeset_values['sidebars_widgets[sidebar-1]'] );
    395407
    396408                $posts_by_name = array();
     409                $this->assertCount( 5, $changeset_values['nav_menus_created_posts'] );
    397410                foreach ( $changeset_values['nav_menus_created_posts'] as $post_id ) {
    398411                        $post = get_post( $post_id );
    399412                        $this->assertEquals( 'auto-draft', $post->post_status );
    400413                        $posts_by_name[ $post->post_name ] = $post->ID;
    401414                }
     415                $this->assertEquals( array( 'featured-image', 'home', 'about', 'blog', 'custom' ), array_keys( $posts_by_name ) );
     416                $this->assertEquals( 'Custom', get_post( $posts_by_name['custom'] )->post_title );
     417                $this->assertEquals( 'sample-page-template.php', get_page_template_slug( $posts_by_name['about'] ) );
     418                $this->assertEquals( '', get_page_template_slug( $posts_by_name['blog'] ) );
     419                $this->assertEquals( $posts_by_name['featured-image'], get_post_thumbnail_id( $posts_by_name['custom'] ) );
     420                $this->assertEquals( '', get_post_thumbnail_id( $posts_by_name['blog'] ) );
     421                $attachment_metadata = wp_get_attachment_metadata( $posts_by_name['featured-image'] );
     422                $this->assertEquals( 'Featured Image', get_post( $posts_by_name['featured-image'] )->post_title );
     423                $this->assertArrayHasKey( 'file', $attachment_metadata );
     424                $this->assertContains( 'waffles', $attachment_metadata['file'] );
    402425
    403426                $this->assertEquals( 'page', $changeset_values['show_on_front'] );
    404427                $this->assertEquals( $posts_by_name['home'], $changeset_values['page_on_front'] );
     
    418441                        $this->assertTrue( $setting_params['starter_content'] );
    419442                }
    420443
     444                // Ensure that re-importing doesn't cause auto-drafts to balloon.
     445                $wp_customize->import_theme_starter_content();
     446                $changeset_data = $wp_customize->changeset_data();
     447                $this->assertEqualSets( array_values( $posts_by_name ), $changeset_data['nav_menus_created_posts']['value'], 'Auto-drafts should not get re-created and amended with each import.' );
     448
    421449                // Test that saving non-starter content on top of the changeset clears the starter_content flag.
    422450                $wp_customize->save_changeset_post( array(
    423451                        'data' => array(
     
    442470                $this->assertArrayNotHasKey( 'starter_content', $changeset_data['blogname'] );
    443471                $this->assertNotEquals( $previous_blogdescription, $changeset_data['blogdescription']['value'] );
    444472                $this->assertArrayHasKey( 'starter_content', $changeset_data['blogdescription'] );
     473
     474                // Publish.
     475                $this->assertEquals( 'auto-draft', get_post( $posts_by_name['about'] )->post_status );
     476                $this->assertEquals( 'auto-draft', get_post( $posts_by_name['featured-image'] )->post_status );
     477                $this->assertNotEquals( $changeset_data['blogname']['value'], get_option( 'blogname' ) );
     478                $r = $wp_customize->save_changeset_post( array( 'status' => 'publish' ) );
     479                $this->assertInternalType( 'array', $r );
     480                $this->assertEquals( 'publish', get_post( $posts_by_name['about'] )->post_status );
     481                $this->assertEquals( 'inherit', get_post( $posts_by_name['featured-image'] )->post_status );
     482                $this->assertEquals( $changeset_data['blogname']['value'], get_option( 'blogname' ) );
    445483        }
    446484
    447485        /**
  • tests/phpunit/tests/theme/getThemeStarterContent.php

     
    4141                        'widgets' => array(
    4242                                'sidebar-1' => array(
    4343                                        'text_business_info',
    44                                         'text_about',
     44                                        'text_about' => array(
     45                                                'title' => 'Our Story',
     46                                        ),
    4547                                        'archives',
    4648                                        'calendar',
    4749                                        'categories',
     
    6365                                                'page_about',
    6466                                                'page_blog',
    6567                                                'page_news',
    66                                                 'page_contact',
     68                                                'page_contact' => array(
     69                                                        'title' => 'Email Us',
     70                                                ),
    6771                                                'link_email',
    6872                                                'link_facebook',
    6973                                                'link_foursquare',
     
    8690                                'home',
    8791                                'about',
    8892                                'contact',
    89                                 'blog',
     93                                'blog' => array(
     94                                        'template' => 'blog.php',
     95                                        'post_excerpt' => 'Extended',
     96                                ),
    9097                                'news',
    9198                                'homepage-section',
    9299                                'unknown',
     
    93100                                'custom' => array(
    94101                                        'post_type' => 'post',
    95102                                        'post_title' => 'Custom',
     103                                        'thumbnail' => '{{featured-image-logo}}',
    96104                                ),
    97105                        ),
     106                        'attachments' => array(
     107                                'featured-image-logo' => array(
     108                                        'post_title' => 'Title',
     109                                        'post_content' => 'Description',
     110                                        'post_excerpt' => 'Caption',
     111                                        'file' => DIR_TESTDATA . '/images/waffles.jpg',
     112                                ),
     113                                'featured-image-skipped' => array(
     114                                        'post_title' => 'Skipped',
     115                                ),
     116                        ),
    98117                        'options' => array(
    99118                                'show_on_front' => 'page',
    100119                                'page_on_front' => '{{home}}',
     
    115134                $this->assertSame( $hydrated_starter_content['options'], $dehydrated_starter_content['options'] );
    116135                $this->assertCount( 16, $hydrated_starter_content['nav_menus']['top']['items'], 'Unknown should be dropped, custom should be present.' );
    117136                $this->assertCount( 10, $hydrated_starter_content['widgets']['sidebar-1'], 'Unknown should be dropped.' );
     137                $this->assertCount( 1, $hydrated_starter_content['attachments'], 'Attachment with missing file is filtered out.' );
     138                $this->assertArrayHasKey( 'featured-image-logo', $hydrated_starter_content['attachments'] );
     139                $this->assertSame( $dehydrated_starter_content['attachments']['featured-image-logo'], $hydrated_starter_content['attachments']['featured-image-logo'] );
    118140
    119141                foreach ( $hydrated_starter_content['widgets']['sidebar-1'] as $widget ) {
    120142                        $this->assertInternalType( 'array', $widget );
     
    123145                        $this->assertInternalType( 'array', $widget[1] );
    124146                        $this->assertArrayHasKey( 'title', $widget[1] );
    125147                }
     148                $this->assertEquals( 'text', $hydrated_starter_content['widgets']['sidebar-1'][1][0], 'Core content extended' );
     149                $this->assertEquals( 'Our Story', $hydrated_starter_content['widgets']['sidebar-1'][1][1]['title'], 'Core content extended' );
    126150
    127151                foreach ( $hydrated_starter_content['nav_menus']['top']['items'] as $nav_menu_item ) {
    128152                        $this->assertInternalType( 'array', $nav_menu_item );
    129153                        $this->assertTrue( ! empty( $nav_menu_item['object_id'] ) || ! empty( $nav_menu_item['url'] ) );
    130154                }
     155                $this->assertEquals( 'Email Us', $hydrated_starter_content['nav_menus']['top']['items'][4]['title'], 'Core content extended' );
    131156
    132157                foreach ( $hydrated_starter_content['posts'] as $key => $post ) {
    133158                        $this->assertInternalType( 'string', $key );
     
    136161                        $this->assertArrayHasKey( 'post_type', $post );
    137162                        $this->assertArrayHasKey( 'post_title', $post );
    138163                }
     164                $this->assertEquals( 'Extended', $hydrated_starter_content['posts']['blog']['post_excerpt'], 'Core content extended' );
     165                $this->assertEquals( 'blog.php', $hydrated_starter_content['posts']['blog']['template'], 'Core content extended' );
     166                $this->assertEquals( '{{featured-image-logo}}', $hydrated_starter_content['posts']['custom']['thumbnail'], 'Core content extended' );
    139167        }
    140168
    141169        /**