<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[39346] trunk: Theme starter content: Add support for featured images and page templates.</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta" style="font-size: 105%">
<dt style="float: left; width: 6em; font-weight: bold">Revision</dt> <dd><a style="font-weight: bold" href="https://core.trac.wordpress.org/changeset/39346">39346</a><script type="application/ld+json">{"@context":"http://schema.org","@type":"EmailMessage","description":"Review this Commit","action":{"@type":"ViewAction","url":"https://core.trac.wordpress.org/changeset/39346","name":"Review Commit"}}</script></dd>
<dt style="float: left; width: 6em; font-weight: bold">Author</dt> <dd>helen</dd>
<dt style="float: left; width: 6em; font-weight: bold">Date</dt> <dd>2016-11-23 09:52:27 +0000 (Wed, 23 Nov 2016)</dd>
</dl>

<pre style='padding-left: 1em; margin: 2em 0; border-left: 2px solid #ccc; line-height: 1.25; font-size: 105%; font-family: sans-serif'>Theme starter content: Add support for featured images and page templates.

Featured image support means that attachments can now be imported. Media can be sideloaded from within theme or plugin directories. Like other posts, attachments are auto-drafts until customizer changes are published, and are not duplicated when they already exist in the customized state. Attachment IDs can be used for any number of purposes, much like post IDs. Twenty Seventeen now includes 3 images used as featured images to best showcase the multi-section homepage setup.

As featured image IDs are stored in post meta, it also made sense to add support for page templates. Twenty Seventeen does not include any such templates, but the functionality can be quite important for displaying themes to their best effect.

props westonruter, helen, flixos90.
fixes <a href="https://core.trac.wordpress.org/ticket/38615">#38615</a>.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunksrcwpcontentthemestwentyseventeenfunctionsphp">trunk/src/wp-content/themes/twentyseventeen/functions.php</a></li>
<li><a href="#trunksrcwpincludesclasswpcustomizemanagerphp">trunk/src/wp-includes/class-wp-customize-manager.php</a></li>
<li><a href="#trunksrcwpincludesclasswpcustomizenavmenusphp">trunk/src/wp-includes/class-wp-customize-nav-menus.php</a></li>
<li><a href="#trunksrcwpincludespostphp">trunk/src/wp-includes/post.php</a></li>
<li><a href="#trunksrcwpincludesthemephp">trunk/src/wp-includes/theme.php</a></li>
<li><a href="#trunktestsphpunittestscustomizemanagerphp">trunk/tests/phpunit/tests/customize/manager.php</a></li>
<li><a href="#trunktestsphpunitteststhemegetThemeStarterContentphp">trunk/tests/phpunit/tests/theme/getThemeStarterContent.php</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunksrcwpcontentthemestwentyseventeenassetsimagescoffeejpg">trunk/src/wp-content/themes/twentyseventeen/assets/images/coffee.jpg</a></li>
<li><a href="#trunksrcwpcontentthemestwentyseventeenassetsimagesespressojpg">trunk/src/wp-content/themes/twentyseventeen/assets/images/espresso.jpg</a></li>
<li><a href="#trunksrcwpcontentthemestwentyseventeenassetsimagessandwichjpg">trunk/src/wp-content/themes/twentyseventeen/assets/images/sandwich.jpg</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunksrcwpcontentthemestwentyseventeenassetsimagescoffeejpg"></a>
<div class="binary"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: trunk/src/wp-content/themes/twentyseventeen/assets/images/coffee.jpg</h4>
<pre class="diff"><span>
<span class="cx">(Binary files differ)
</span></span></pre></div>
<span class="cx" style="display: block; padding: 0 10px">Index: trunk/src/wp-content/themes/twentyseventeen/assets/images/coffee.jpg
</span><span class="cx" style="display: block; padding: 0 10px">===================================================================
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">--- trunk/src/wp-content/themes/twentyseventeen/assets/images/coffee.jpg 2016-11-23 06:04:23 UTC (rev 39345)
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+++ trunk/src/wp-content/themes/twentyseventeen/assets/images/coffee.jpg  2016-11-23 09:52:27 UTC (rev 39346)
</ins><span class="cx" style="display: block; padding: 0 10px">Property changes on: trunk/src/wp-content/themes/twentyseventeen/assets/images/coffee.jpg
</span><span class="cx" style="display: block; padding: 0 10px">___________________________________________________________________
</span><a id="svnexecutable"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:executable</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+*
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><a id="svnmimetype"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:mime-type</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+application/octet-stream
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><a id="trunksrcwpcontentthemestwentyseventeenassetsimagesespressojpg"></a>
<div class="binary"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: trunk/src/wp-content/themes/twentyseventeen/assets/images/espresso.jpg</h4>
<pre class="diff"><span>
<span class="cx">(Binary files differ)
</span></span></pre></div>
<span class="cx" style="display: block; padding: 0 10px">Index: trunk/src/wp-content/themes/twentyseventeen/assets/images/espresso.jpg
</span><span class="cx" style="display: block; padding: 0 10px">===================================================================
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">--- trunk/src/wp-content/themes/twentyseventeen/assets/images/espresso.jpg       2016-11-23 06:04:23 UTC (rev 39345)
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+++ trunk/src/wp-content/themes/twentyseventeen/assets/images/espresso.jpg        2016-11-23 09:52:27 UTC (rev 39346)
</ins><span class="cx" style="display: block; padding: 0 10px">Property changes on: trunk/src/wp-content/themes/twentyseventeen/assets/images/espresso.jpg
</span><span class="cx" style="display: block; padding: 0 10px">___________________________________________________________________
</span><a id="svnmimetype"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:mime-type</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+application/octet-stream
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><a id="svnexecutable"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:executable</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+*
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><a id="trunksrcwpcontentthemestwentyseventeenassetsimagessandwichjpg"></a>
<div class="binary"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: trunk/src/wp-content/themes/twentyseventeen/assets/images/sandwich.jpg</h4>
<pre class="diff"><span>
<span class="cx">(Binary files differ)
</span></span></pre></div>
<span class="cx" style="display: block; padding: 0 10px">Index: trunk/src/wp-content/themes/twentyseventeen/assets/images/sandwich.jpg
</span><span class="cx" style="display: block; padding: 0 10px">===================================================================
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">--- trunk/src/wp-content/themes/twentyseventeen/assets/images/sandwich.jpg       2016-11-23 06:04:23 UTC (rev 39345)
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+++ trunk/src/wp-content/themes/twentyseventeen/assets/images/sandwich.jpg        2016-11-23 09:52:27 UTC (rev 39346)
</ins><span class="cx" style="display: block; padding: 0 10px">Property changes on: trunk/src/wp-content/themes/twentyseventeen/assets/images/sandwich.jpg
</span><span class="cx" style="display: block; padding: 0 10px">___________________________________________________________________
</span><a id="svnmimetype"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:mime-type</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+application/octet-stream
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><a id="svnexecutable"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:executable</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+*
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><a id="trunksrcwpcontentthemestwentyseventeenfunctionsphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-content/themes/twentyseventeen/functions.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-content/themes/twentyseventeen/functions.php 2016-11-23 06:04:23 UTC (rev 39345)
+++ trunk/src/wp-content/themes/twentyseventeen/functions.php   2016-11-23 09:52:27 UTC (rev 39346)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -123,12 +123,35 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                'posts' => array(
</span><span class="cx" style="display: block; padding: 0 10px">                        'home',
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        'about',
-                       'contact',
-                       'blog',
-                       'homepage-section',
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 'about' => array(
+                               'thumbnail' => '{{image-sandwich}}',
+                       ),
+                       'contact' => array(
+                               'thumbnail' => '{{image-espresso}}',
+                       ),
+                       'blog' => array(
+                               'thumbnail' => '{{image-coffee}}',
+                       ),
+                       'homepage-section' => array(
+                               'thumbnail' => '{{image-espresso}}',
+                       ),
</ins><span class="cx" style="display: block; padding: 0 10px">                 ),
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                'attachments' => array(
+                       'image-espresso' => array(
+                               'post_title' => _x( 'Espresso', 'Theme starter content' ),
+                               'file' => 'assets/images/espresso.jpg',
+                       ),
+                       'image-sandwich' => array(
+                               'post_title' => _x( 'Sandwich', 'Theme starter content' ),
+                               'file' => 'assets/images/sandwich.jpg',
+                       ),
+                       'image-coffee' => array(
+                               'post_title' => _x( 'Coffee', 'Theme starter content' ),
+                               'file' => 'assets/images/coffee.jpg',
+                       ),
+               ),
+
</ins><span class="cx" style="display: block; padding: 0 10px">                 'options' => array(
</span><span class="cx" style="display: block; padding: 0 10px">                        'show_on_front' => 'page',
</span><span class="cx" style="display: block; padding: 0 10px">                        'page_on_front' => '{{home}}',
</span></span></pre></div>
<a id="trunksrcwpincludesclasswpcustomizemanagerphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/class-wp-customize-manager.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/class-wp-customize-manager.php      2016-11-23 06:04:23 UTC (rev 39345)
+++ trunk/src/wp-includes/class-wp-customize-manager.php        2016-11-23 09:52:27 UTC (rev 39346)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -916,6 +916,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                $sidebars_widgets = isset( $starter_content['widgets'] ) && ! empty( $this->widgets ) ? $starter_content['widgets'] : array();
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                $attachments = isset( $starter_content['attachments'] ) && ! empty( $this->nav_menus ) ? $starter_content['attachments'] : array();
</ins><span class="cx" style="display: block; padding: 0 10px">                 $posts = isset( $starter_content['posts'] ) && ! empty( $this->nav_menus ) ? $starter_content['posts'] : array();
</span><span class="cx" style="display: block; padding: 0 10px">                $options = isset( $starter_content['options'] ) ? $starter_content['options'] : array();
</span><span class="cx" style="display: block; padding: 0 10px">                $nav_menus = isset( $starter_content['nav_menus'] ) && ! empty( $this->nav_menus ) ? $starter_content['nav_menus'] : array();
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -965,26 +966,126 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                // Posts & pages.
-               if ( ! empty( $posts ) ) {
-                       $nav_menus_created_posts = array();
-                       if ( ! empty( $changeset_data['nav_menus_created_posts']['value'] ) ) {
-                               $nav_menus_created_posts = $changeset_data['nav_menus_created_posts']['value'];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $starter_content_auto_draft_post_ids = array();
+               if ( ! empty( $changeset_data['nav_menus_created_posts']['value'] ) ) {
+                       $starter_content_auto_draft_post_ids = array_merge( $starter_content_auto_draft_post_ids, $changeset_data['nav_menus_created_posts']['value'] );
+               }
+
+               $existing_starter_content_posts = array();
+               if ( ! empty( $starter_content_auto_draft_post_ids ) ) {
+                       $existing_posts_query = new WP_Query( array(
+                               'post__in' => $starter_content_auto_draft_post_ids,
+                               'post_status' => 'auto-draft',
+                               'post_type' => 'any',
+                               'number' => -1,
+                       ) );
+                       foreach ( $existing_posts_query->posts as $existing_post ) {
+                               $existing_starter_content_posts[ $existing_post->post_type . ':' . $existing_post->post_name ] = $existing_post;
</ins><span class="cx" style="display: block; padding: 0 10px">                         }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                }
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $existing_posts = array();
-                       if ( ! empty( $nav_menus_created_posts ) ) {
-                               $existing_posts_query = new WP_Query( array(
-                                       'post__in' => $nav_menus_created_posts,
-                                       'post_status' => 'auto-draft',
-                                       'post_type' => 'any',
-                                       'number' => -1,
-                               ) );
-                               foreach ( $existing_posts_query->posts as $existing_post ) {
-                                       $existing_posts[ $existing_post->post_type . ':' . $existing_post->post_name ] = $existing_post;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         // Attachments are technically posts but handled differently.
+               if ( ! empty( $attachments ) ) {
+                       // Such is The WordPress Way.
+                       require_once( ABSPATH . 'wp-admin/includes/file.php' );
+                       require_once( ABSPATH . 'wp-admin/includes/media.php' );
+                       require_once( ABSPATH . 'wp-admin/includes/image.php' );
+
+                       $attachment_ids = array();
+
+                       foreach ( $attachments as $symbol => $attachment ) {
+
+                               // A file is required and URLs to files are not currently allowed.
+                               if ( empty( $attachment['file'] ) || preg_match( '#^https?://$#', $attachment['file'] ) ) {
+                                       continue;
</ins><span class="cx" style="display: block; padding: 0 10px">                                 }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+                               $file_array = array();
+                               $file_path = null;
+                               if ( file_exists( $attachment['file'] ) ) {
+                                       $file_path = $attachment['file']; // Could be absolute path to file in plugin.
+                               } elseif ( is_child_theme() && file_exists( get_stylesheet_directory() . '/' . $attachment['file'] ) ) {
+                                       $file_path = get_stylesheet_directory() . '/' . $attachment['file'];
+                               } elseif ( file_exists( get_template_directory() . '/' . $attachment['file'] ) ) {
+                                       $file_path = get_template_directory() . '/' . $attachment['file'];
+                               } else {
+                                       continue;
+                               }
+                               $file_array['name'] = basename( $attachment['file'] );
+
+                               // Skip file types that are not recognized.
+                               $checked_filetype = wp_check_filetype( $file_array['name'] );
+                               if ( empty( $checked_filetype['type'] ) ) {
+                                       continue;
+                               }
+
+                               // Ensure post_name is set since not automatically derived from post_title for new auto-draft posts.
+                               if ( empty( $attachment['post_name'] ) ) {
+                                       if ( ! empty( $attachment['post_title'] ) ) {
+                                               $attachment['post_name'] = sanitize_title( $attachment['post_title'] );
+                                       } else {
+                                               $attachment['post_name'] = sanitize_title( preg_replace( '/\.\w+$/', '', $file_array['name'] ) );
+                                       }
+                               }
+
+                               $attachment_id = null;
+                               $attached_file = null;
+                               if ( isset( $existing_starter_content_posts[ 'attachment:' . $attachment['post_name'] ] ) ) {
+                                       $attachment_post = $existing_starter_content_posts[ 'attachment:' . $attachment['post_name'] ];
+                                       $attachment_id = $attachment_post->ID;
+                                       $attached_file = get_attached_file( $attachment_id );
+                                       if ( empty( $attached_file ) || ! file_exists( $attached_file ) ) {
+                                               $attachment_id = null;
+                                               $attached_file = null;
+                                       } elseif ( $this->get_stylesheet() !== get_post_meta( $attachment_post->ID, '_starter_content_theme', true ) ) {
+
+                                               // Re-generate attachment metadata since it was previously generated for a different theme.
+                                               $metadata = wp_generate_attachment_metadata( $attachment_post->ID, $attached_file );
+                                               wp_update_attachment_metadata( $attachment_id, $metadata );
+                                               update_post_meta( $attachment_id, '_starter_content_theme', $this->get_stylesheet() );
+                                       }
+                               }
+
+                               // Insert the attachment auto-draft because it doesn't yet exist or the attached file is gone.
+                               if ( ! $attachment_id ) {
+
+                                       // Copy file to temp location so that original file won't get deleted from theme after sideloading.
+                                       $temp_file_name = wp_tempnam( basename( $file_path ) );
+                                       if ( $temp_file_name && copy( $file_path, $temp_file_name ) ) {
+                                               $file_array['tmp_name'] = $temp_file_name;
+                                       }
+                                       if ( empty( $file_array['tmp_name'] ) ) {
+                                               continue;
+                                       }
+
+                                       $attachment_post_data = array_merge(
+                                               wp_array_slice_assoc( $attachment, array( 'post_title', 'post_content', 'post_excerpt', 'post_name' ) ),
+                                               array(
+                                                       'post_status' => 'auto-draft', // So attachment will be garbage collected in a week if changeset is never published.
+                                               )
+                                       );
+
+                                       // In PHP < 5.6 filesize() returns 0 for the temp files unless we clear the file status cache.
+                                       // Technically, PHP < 5.6.0 || < 5.5.13 || < 5.4.29 but no need to be so targeted.
+                                       // See https://bugs.php.net/bug.php?id=65701
+                                       if ( version_compare( PHP_VERSION, '5.6', '<' ) ) {
+                                               clearstatcache();
+                                       }
+
+                                       $attachment_id = media_handle_sideload( $file_array, 0, null, $attachment_post_data );
+                                       if ( is_wp_error( $attachment_id ) ) {
+                                               continue;
+                                       }
+                                       update_post_meta( $attachment_id, '_starter_content_theme', $this->get_stylesheet() );
+                               }
+
+                               $attachment_ids[ $symbol ] = $attachment_id;
+                               $starter_content_auto_draft_post_ids = array_merge( $starter_content_auto_draft_post_ids, array_values( $attachment_ids ) );
</ins><span class="cx" style="display: block; padding: 0 10px">                         }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                }
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                // Posts & pages.
+               if ( ! empty( $posts ) ) {
</ins><span class="cx" style="display: block; padding: 0 10px">                         foreach ( array_keys( $posts ) as $post_symbol ) {
</span><span class="cx" style="display: block; padding: 0 10px">                                if ( empty( $posts[ $post_symbol ]['post_type'] ) ) {
</span><span class="cx" style="display: block; padding: 0 10px">                                        continue;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -999,24 +1100,36 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                // Use existing auto-draft post if one already exists with the same type and name.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                if ( isset( $existing_posts[ $post_type . ':' . $post_name ] ) ) {
-                                       $posts[ $post_symbol ]['ID'] = $existing_posts[ $post_type . ':' . $post_name ]->ID;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         if ( isset( $existing_starter_content_posts[ $post_type . ':' . $post_name ] ) ) {
+                                       $posts[ $post_symbol ]['ID'] = $existing_starter_content_posts[ $post_type . ':' . $post_name ]->ID;
</ins><span class="cx" style="display: block; padding: 0 10px">                                         continue;
</span><span class="cx" style="display: block; padding: 0 10px">                                }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                // Translate the featured image symbol.
+                               if ( ! empty( $posts[ $post_symbol ]['thumbnail'] )
+                                       && preg_match( '/^{{(?P<symbol>.+)}}$/', $posts[ $post_symbol ]['thumbnail'], $matches )
+                                       && isset( $attachment_ids[ $matches['symbol'] ] ) ) {
+                                       $posts[ $post_symbol ]['meta_input']['_thumbnail_id'] = $attachment_ids[ $matches['symbol'] ];
+                               }
+
+                               if ( ! empty( $posts[ $post_symbol ]['template'] ) ) {
+                                       $posts[ $post_symbol ]['meta_input']['_wp_page_template'] = $posts[ $post_symbol ]['template'];
+                               }
+
</ins><span class="cx" style="display: block; padding: 0 10px">                                 $r = $this->nav_menus->insert_auto_draft_post( $posts[ $post_symbol ] );
</span><span class="cx" style="display: block; padding: 0 10px">                                if ( $r instanceof WP_Post ) {
</span><span class="cx" style="display: block; padding: 0 10px">                                        $posts[ $post_symbol ]['ID'] = $r->ID;
</span><span class="cx" style="display: block; padding: 0 10px">                                }
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        // The nav_menus_created_posts setting is why nav_menus component is dependency for adding posts.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $starter_content_auto_draft_post_ids = array_merge( $starter_content_auto_draft_post_ids, wp_list_pluck( $posts, 'ID' ) );
+               }
+
+               // The nav_menus_created_posts setting is why nav_menus component is dependency for adding posts.
+               if ( ! empty( $this->nav_menus ) && ! empty( $starter_content_auto_draft_post_ids ) ) {
</ins><span class="cx" style="display: block; padding: 0 10px">                         $setting_id = 'nav_menus_created_posts';
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        if ( empty( $changeset_data[ $setting_id ] ) || ! empty( $changeset_data[ $setting_id ]['starter_content'] ) ) {
-                               $nav_menus_created_posts = array_unique( array_merge( $nav_menus_created_posts, wp_list_pluck( $posts, 'ID' ) ) );
-                               $this->set_post_value( $setting_id, array_values( $nav_menus_created_posts ) );
-                               $this->pending_starter_content_settings_ids[] = $setting_id;
-                       }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $this->set_post_value( $setting_id, array_unique( array_values( $starter_content_auto_draft_post_ids ) ) );
+                       $this->pending_starter_content_settings_ids[] = $setting_id;
</ins><span class="cx" style="display: block; padding: 0 10px">                 }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                // Nav menus.
</span></span></pre></div>
<a id="trunksrcwpincludesclasswpcustomizenavmenusphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/class-wp-customize-nav-menus.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/class-wp-customize-nav-menus.php    2016-11-23 06:04:23 UTC (rev 39345)
+++ trunk/src/wp-includes/class-wp-customize-nav-menus.php      2016-11-23 09:52:27 UTC (rev 39346)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1191,8 +1191,10 @@
</span><span class="cx" style="display: block; padding: 0 10px">                $post_ids = $setting->post_value();
</span><span class="cx" style="display: block; padding: 0 10px">                if ( ! empty( $post_ids ) ) {
</span><span class="cx" style="display: block; padding: 0 10px">                        foreach ( $post_ids as $post_id ) {
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                $target_status = 'attachment' === get_post_type( $post_id ) ? 'inherit' : 'publish';
+
</ins><span class="cx" style="display: block; padding: 0 10px">                                 // Note that wp_publish_post() cannot be used because unique slugs need to be assigned.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                wp_update_post( array( 'ID' => $post_id, 'post_status' => 'publish' ) );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         wp_update_post( array( 'ID' => $post_id, 'post_status' => $target_status ) );
</ins><span class="cx" style="display: block; padding: 0 10px">                         }
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span></span></pre></div>
<a id="trunksrcwpincludespostphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/post.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/post.php    2016-11-23 06:04:23 UTC (rev 39345)
+++ trunk/src/wp-includes/post.php      2016-11-23 09:52:27 UTC (rev 39346)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -3058,7 +3058,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        $post_status = empty( $postarr['post_status'] ) ? 'draft' : $postarr['post_status'];
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        if ( 'attachment' === $post_type && ! in_array( $post_status, array( 'inherit', 'private', 'trash' ) ) ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( 'attachment' === $post_type && ! in_array( $post_status, array( 'inherit', 'private', 'trash', 'auto-draft' ), true ) ) {
</ins><span class="cx" style="display: block; padding: 0 10px">                 $post_status = 'inherit';
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span></span></pre></div>
<a id="trunksrcwpincludesthemephp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/theme.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/theme.php   2016-11-23 06:04:23 UTC (rev 39345)
+++ trunk/src/wp-includes/theme.php     2016-11-23 09:52:27 UTC (rev 39346)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1986,8 +1986,17 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        // Widgets are grouped into sidebars.
</span><span class="cx" style="display: block; padding: 0 10px">                        case 'widgets' :
</span><span class="cx" style="display: block; padding: 0 10px">                                foreach ( $config[ $type ] as $sidebar_id => $widgets ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        foreach ( $widgets as $widget ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 foreach ( $widgets as $id => $widget ) {
</ins><span class="cx" style="display: block; padding: 0 10px">                                                 if ( is_array( $widget ) ) {
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+                                                       // Item extends core content.
+                                                       if ( ! empty( $core_content[ $type ][ $id ] ) ) {
+                                                               $widget = array(
+                                                                       $core_content[ $type ][ $id ][0],
+                                                                       array_merge( $core_content[ $type ][ $id ][1], $widget ),
+                                                               );
+                                                       }
+
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         $content[ $type ][ $sidebar_id ][] = $widget;
</span><span class="cx" style="display: block; padding: 0 10px">                                                } elseif ( is_string( $widget ) && ! empty( $core_content[ $type ] ) && ! empty( $core_content[ $type ][ $widget ] ) ) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                        $content[ $type ][ $sidebar_id ][] = $core_content[ $type ][ $widget ];
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2007,8 +2016,14 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                        $content[ $type ][ $nav_menu_location ]['name'] = $nav_menu['name'];
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        foreach ( $nav_menu['items'] as $nav_menu_item ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 foreach ( $nav_menu['items'] as $id => $nav_menu_item ) {
</ins><span class="cx" style="display: block; padding: 0 10px">                                                 if ( is_array( $nav_menu_item ) ) {
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+                                                       // Item extends core content.
+                                                       if ( ! empty( $core_content[ $type ][ $id ] ) ) {
+                                                               $nav_menu_item = array_merge( $core_content[ $type ][ $id ], $nav_menu_item );
+                                                       }
+
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         $content[ $type ][ $nav_menu_location ]['items'][] = $nav_menu_item;
</span><span class="cx" style="display: block; padding: 0 10px">                                                } elseif ( is_string( $nav_menu_item ) && ! empty( $core_content[ $type ] ) && ! empty( $core_content[ $type ][ $nav_menu_item ] ) ) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                        $content[ $type ][ $nav_menu_location ]['items'][] = $core_content[ $type ][ $nav_menu_item ];
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2017,12 +2032,41 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                }
</span><span class="cx" style="display: block; padding: 0 10px">                                break;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        // Everything else should map at the next level.
-                       default :
-                               foreach( $config[ $type ] as $i => $item ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 // Attachments are posts but have special treatment.
+                       case 'attachments' :
+                               foreach ( $config[ $type ] as $id => $item ) {
+                                       if ( ! empty( $item['file'] ) ) {
+                                               $content[ $type ][ $id ] = $item;
+                                       }
+                               }
+                               break;
+
+                       // All that's left now are posts (besides attachments). Not a default case for the sake of clarity and future work.
+                       case 'posts' :
+                               foreach ( $config[ $type ] as $id => $item ) {
</ins><span class="cx" style="display: block; padding: 0 10px">                                         if ( is_array( $item ) ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                $content[ $type ][ $i ] = $item;
-                                       } elseif ( is_string( $item ) && ! empty( $core_content[ $type ] ) && ! empty( $core_content[ $type ][ $item ] ) ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+                                               // Item extends core content.
+                                               if ( ! empty( $core_content[ $type ][ $id ] ) ) {
+                                                       $item = array_merge( $core_content[ $type ][ $id ], $item );
+                                               }
+
+                                               // Enforce a subset of fields.
+                                               $content[ $type ][ $id ] = wp_array_slice_assoc(
+                                                       $item,
+                                                       array(
+                                                               'post_type',
+                                                               'post_title',
+                                                               'post_excerpt',
+                                                               'post_name',
+                                                               'post_content',
+                                                               'menu_order',
+                                                               'comment_status',
+                                                               'thumbnail',
+                                                               'template',
+                                                       )
+                                               );
+                                       } elseif ( is_string( $item ) && ! empty( $core_content[ $type ][ $item ] ) ) {
</ins><span class="cx" style="display: block; padding: 0 10px">                                                 $content[ $type ][ $item ] = $core_content[ $type ][ $item ];
</span><span class="cx" style="display: block; padding: 0 10px">                                        }
</span><span class="cx" style="display: block; padding: 0 10px">                                }
</span></span></pre></div>
<a id="trunktestsphpunittestscustomizemanagerphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/phpunit/tests/customize/manager.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/customize/manager.php   2016-11-23 06:04:23 UTC (rev 39345)
+++ trunk/tests/phpunit/tests/customize/manager.php     2016-11-23 09:52:27 UTC (rev 39346)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -313,6 +313,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">         */
</span><span class="cx" style="display: block; padding: 0 10px">        function test_import_theme_starter_content() {
</span><span class="cx" style="display: block; padding: 0 10px">                wp_set_current_user( self::$admin_user_id );
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                register_nav_menu( 'top', 'Top' );
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                global $wp_customize;
</span><span class="cx" style="display: block; padding: 0 10px">                $wp_customize = new WP_Customize_Manager();
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -343,13 +344,24 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        ),
</span><span class="cx" style="display: block; padding: 0 10px">                        'posts' => array(
</span><span class="cx" style="display: block; padding: 0 10px">                                'home',
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                'about',
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         'about' => array(
+                                       'template' => 'sample-page-template.php',
+                               ),
</ins><span class="cx" style="display: block; padding: 0 10px">                                 'blog',
</span><span class="cx" style="display: block; padding: 0 10px">                                'custom' => array(
</span><span class="cx" style="display: block; padding: 0 10px">                                        'post_type' => 'post',
</span><span class="cx" style="display: block; padding: 0 10px">                                        'post_title' => 'Custom',
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                        'thumbnail' => '{{featured-image-logo}}',
</ins><span class="cx" style="display: block; padding: 0 10px">                                 ),
</span><span class="cx" style="display: block; padding: 0 10px">                        ),
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                        'attachments' => array(
+                               'featured-image-logo' => array(
+                                       'post_title' => 'Featured Image',
+                                       'post_content' => 'Attachment Description',
+                                       'post_excerpt' => 'Attachment Caption',
+                                       'file' => DIR_TESTDATA . '/images/waffles.jpg',
+                               ),
+                       ),
</ins><span class="cx" style="display: block; padding: 0 10px">                         'options' => array(
</span><span class="cx" style="display: block; padding: 0 10px">                                'blogname' => 'Starter Content Title',
</span><span class="cx" style="display: block; padding: 0 10px">                                'blogdescription' => 'Starter Content Tagline',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -394,11 +406,22 @@
</span><span class="cx" style="display: block; padding: 0 10px">                $this->assertEquals( array( 'text-2', 'meta-3' ), $changeset_values['sidebars_widgets[sidebar-1]'] );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                $posts_by_name = array();
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                $this->assertCount( 5, $changeset_values['nav_menus_created_posts'] );
</ins><span class="cx" style="display: block; padding: 0 10px">                 foreach ( $changeset_values['nav_menus_created_posts'] as $post_id ) {
</span><span class="cx" style="display: block; padding: 0 10px">                        $post = get_post( $post_id );
</span><span class="cx" style="display: block; padding: 0 10px">                        $this->assertEquals( 'auto-draft', $post->post_status );
</span><span class="cx" style="display: block; padding: 0 10px">                        $posts_by_name[ $post->post_name ] = $post->ID;
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                $this->assertEquals( array( 'featured-image', 'home', 'about', 'blog', 'custom' ), array_keys( $posts_by_name ) );
+               $this->assertEquals( 'Custom', get_post( $posts_by_name['custom'] )->post_title );
+               $this->assertEquals( 'sample-page-template.php', get_page_template_slug( $posts_by_name['about'] ) );
+               $this->assertEquals( '', get_page_template_slug( $posts_by_name['blog'] ) );
+               $this->assertEquals( $posts_by_name['featured-image'], get_post_thumbnail_id( $posts_by_name['custom'] ) );
+               $this->assertEquals( '', get_post_thumbnail_id( $posts_by_name['blog'] ) );
+               $attachment_metadata = wp_get_attachment_metadata( $posts_by_name['featured-image'] );
+               $this->assertEquals( 'Featured Image', get_post( $posts_by_name['featured-image'] )->post_title );
+               $this->assertArrayHasKey( 'file', $attachment_metadata );
+               $this->assertContains( 'waffles', $attachment_metadata['file'] );
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                $this->assertEquals( 'page', $changeset_values['show_on_front'] );
</span><span class="cx" style="display: block; padding: 0 10px">                $this->assertEquals( $posts_by_name['home'], $changeset_values['page_on_front'] );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -418,6 +441,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        $this->assertTrue( $setting_params['starter_content'] );
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                // Ensure that re-importing doesn't cause auto-drafts to balloon.
+               $wp_customize->import_theme_starter_content();
+               $changeset_data = $wp_customize->changeset_data();
+               $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.' );
+
</ins><span class="cx" style="display: block; padding: 0 10px">                 // Test that saving non-starter content on top of the changeset clears the starter_content flag.
</span><span class="cx" style="display: block; padding: 0 10px">                $wp_customize->save_changeset_post( array(
</span><span class="cx" style="display: block; padding: 0 10px">                        'data' => array(
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -442,6 +470,16 @@
</span><span class="cx" style="display: block; padding: 0 10px">                $this->assertArrayNotHasKey( 'starter_content', $changeset_data['blogname'] );
</span><span class="cx" style="display: block; padding: 0 10px">                $this->assertNotEquals( $previous_blogdescription, $changeset_data['blogdescription']['value'] );
</span><span class="cx" style="display: block; padding: 0 10px">                $this->assertArrayHasKey( 'starter_content', $changeset_data['blogdescription'] );
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+               // Publish.
+               $this->assertEquals( 'auto-draft', get_post( $posts_by_name['about'] )->post_status );
+               $this->assertEquals( 'auto-draft', get_post( $posts_by_name['featured-image'] )->post_status );
+               $this->assertNotEquals( $changeset_data['blogname']['value'], get_option( 'blogname' ) );
+               $r = $wp_customize->save_changeset_post( array( 'status' => 'publish' ) );
+               $this->assertInternalType( 'array', $r );
+               $this->assertEquals( 'publish', get_post( $posts_by_name['about'] )->post_status );
+               $this->assertEquals( 'inherit', get_post( $posts_by_name['featured-image'] )->post_status );
+               $this->assertEquals( $changeset_data['blogname']['value'], get_option( 'blogname' ) );
</ins><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span></span></pre></div>
<a id="trunktestsphpunitteststhemegetThemeStarterContentphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/phpunit/tests/theme/getThemeStarterContent.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/theme/getThemeStarterContent.php        2016-11-23 06:04:23 UTC (rev 39345)
+++ trunk/tests/phpunit/tests/theme/getThemeStarterContent.php  2016-11-23 09:52:27 UTC (rev 39346)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -41,7 +41,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        'widgets' => array(
</span><span class="cx" style="display: block; padding: 0 10px">                                'sidebar-1' => array(
</span><span class="cx" style="display: block; padding: 0 10px">                                        'text_business_info',
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        'text_about',
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 'text_about' => array(
+                                               'title' => 'Our Story',
+                                       ),
</ins><span class="cx" style="display: block; padding: 0 10px">                                         'archives',
</span><span class="cx" style="display: block; padding: 0 10px">                                        'calendar',
</span><span class="cx" style="display: block; padding: 0 10px">                                        'categories',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -63,7 +65,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                'page_about',
</span><span class="cx" style="display: block; padding: 0 10px">                                                'page_blog',
</span><span class="cx" style="display: block; padding: 0 10px">                                                'page_news',
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                'page_contact',
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         'page_contact' => array(
+                                                       'title' => 'Email Us',
+                                               ),
</ins><span class="cx" style="display: block; padding: 0 10px">                                                 'link_email',
</span><span class="cx" style="display: block; padding: 0 10px">                                                'link_facebook',
</span><span class="cx" style="display: block; padding: 0 10px">                                                'link_foursquare',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -86,15 +90,30 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                'home',
</span><span class="cx" style="display: block; padding: 0 10px">                                'about',
</span><span class="cx" style="display: block; padding: 0 10px">                                'contact',
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                'blog',
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         'blog' => array(
+                                       'template' => 'blog.php',
+                                       'post_excerpt' => 'Extended',
+                               ),
</ins><span class="cx" style="display: block; padding: 0 10px">                                 'news',
</span><span class="cx" style="display: block; padding: 0 10px">                                'homepage-section',
</span><span class="cx" style="display: block; padding: 0 10px">                                'unknown',
</span><span class="cx" style="display: block; padding: 0 10px">                                'custom' => array(
</span><span class="cx" style="display: block; padding: 0 10px">                                        'post_type' => 'post',
</span><span class="cx" style="display: block; padding: 0 10px">                                        'post_title' => 'Custom',
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                        'thumbnail' => '{{featured-image-logo}}',
</ins><span class="cx" style="display: block; padding: 0 10px">                                 ),
</span><span class="cx" style="display: block; padding: 0 10px">                        ),
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                        'attachments' => array(
+                               'featured-image-logo' => array(
+                                       'post_title' => 'Title',
+                                       'post_content' => 'Description',
+                                       'post_excerpt' => 'Caption',
+                                       'file' => DIR_TESTDATA . '/images/waffles.jpg',
+                               ),
+                               'featured-image-skipped' => array(
+                                       'post_title' => 'Skipped',
+                               ),
+                       ),
</ins><span class="cx" style="display: block; padding: 0 10px">                         'options' => array(
</span><span class="cx" style="display: block; padding: 0 10px">                                'show_on_front' => 'page',
</span><span class="cx" style="display: block; padding: 0 10px">                                'page_on_front' => '{{home}}',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -115,6 +134,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">                $this->assertSame( $hydrated_starter_content['options'], $dehydrated_starter_content['options'] );
</span><span class="cx" style="display: block; padding: 0 10px">                $this->assertCount( 16, $hydrated_starter_content['nav_menus']['top']['items'], 'Unknown should be dropped, custom should be present.' );
</span><span class="cx" style="display: block; padding: 0 10px">                $this->assertCount( 10, $hydrated_starter_content['widgets']['sidebar-1'], 'Unknown should be dropped.' );
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                $this->assertCount( 1, $hydrated_starter_content['attachments'], 'Attachment with missing file is filtered out.' );
+               $this->assertArrayHasKey( 'featured-image-logo', $hydrated_starter_content['attachments'] );
+               $this->assertSame( $dehydrated_starter_content['attachments']['featured-image-logo'], $hydrated_starter_content['attachments']['featured-image-logo'] );
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                foreach ( $hydrated_starter_content['widgets']['sidebar-1'] as $widget ) {
</span><span class="cx" style="display: block; padding: 0 10px">                        $this->assertInternalType( 'array', $widget );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -123,11 +145,14 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        $this->assertInternalType( 'array', $widget[1] );
</span><span class="cx" style="display: block; padding: 0 10px">                        $this->assertArrayHasKey( 'title', $widget[1] );
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                $this->assertEquals( 'text', $hydrated_starter_content['widgets']['sidebar-1'][1][0], 'Core content extended' );
+               $this->assertEquals( 'Our Story', $hydrated_starter_content['widgets']['sidebar-1'][1][1]['title'], 'Core content extended' );
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                foreach ( $hydrated_starter_content['nav_menus']['top']['items'] as $nav_menu_item ) {
</span><span class="cx" style="display: block; padding: 0 10px">                        $this->assertInternalType( 'array', $nav_menu_item );
</span><span class="cx" style="display: block; padding: 0 10px">                        $this->assertTrue( ! empty( $nav_menu_item['object_id'] ) || ! empty( $nav_menu_item['url'] ) );
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                $this->assertEquals( 'Email Us', $hydrated_starter_content['nav_menus']['top']['items'][4]['title'], 'Core content extended' );
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                foreach ( $hydrated_starter_content['posts'] as $key => $post ) {
</span><span class="cx" style="display: block; padding: 0 10px">                        $this->assertInternalType( 'string', $key );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -136,6 +161,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        $this->assertArrayHasKey( 'post_type', $post );
</span><span class="cx" style="display: block; padding: 0 10px">                        $this->assertArrayHasKey( 'post_title', $post );
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                $this->assertEquals( 'Extended', $hydrated_starter_content['posts']['blog']['post_excerpt'], 'Core content extended' );
+               $this->assertEquals( 'blog.php', $hydrated_starter_content['posts']['blog']['template'], 'Core content extended' );
+               $this->assertEquals( '{{featured-image-logo}}', $hydrated_starter_content['posts']['custom']['thumbnail'], 'Core content extended' );
</ins><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span></span></pre>
</div>
</div>

</body>
</html>