diff --git a/wp-content/themes/twentyseventeen/assets/images/coffee.jpg b/wp-content/themes/twentyseventeen/assets/images/coffee.jpg new file mode 100644 index 0000000000..13847cde7c Binary files /dev/null and b/wp-content/themes/twentyseventeen/assets/images/coffee.jpg differ diff --git a/wp-content/themes/twentyseventeen/assets/images/espresso.jpg b/wp-content/themes/twentyseventeen/assets/images/espresso.jpg new file mode 100644 index 0000000000..7514c96bdf Binary files /dev/null and b/wp-content/themes/twentyseventeen/assets/images/espresso.jpg differ diff --git a/wp-content/themes/twentyseventeen/assets/images/sandwich.jpg b/wp-content/themes/twentyseventeen/assets/images/sandwich.jpg new file mode 100644 index 0000000000..6baddbf053 Binary files /dev/null and b/wp-content/themes/twentyseventeen/assets/images/sandwich.jpg differ diff --git a/wp-content/themes/twentyseventeen/functions.php b/wp-content/themes/twentyseventeen/functions.php index 1bcb95fc34..e1c4e06501 100644 --- a/wp-content/themes/twentyseventeen/functions.php +++ b/wp-content/themes/twentyseventeen/functions.php @@ -123,10 +123,33 @@ function twentyseventeen_setup() { 'posts' => array( 'home', - 'about', - 'contact', - 'blog', - 'homepage-section', + 'about' => array( + 'thumbnail' => '{{image-sandwich}}', + ), + 'contact' => array( + 'thumbnail' => '{{image-espresso}}', + ), + 'blog' => array( + 'thumbnail' => '{{image-coffee}}', + ), + 'homepage-section' => array( + 'thumbnail' => '{{image-espresso}}', + ), + ), + + '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', + ), ), 'options' => array( diff --git a/wp-includes/class-wp-customize-manager.php b/wp-includes/class-wp-customize-manager.php index e71787c676..1f5da60f8d 100644 --- a/wp-includes/class-wp-customize-manager.php +++ b/wp-includes/class-wp-customize-manager.php @@ -916,6 +916,7 @@ final class WP_Customize_Manager { } $sidebars_widgets = isset( $starter_content['widgets'] ) && ! empty( $this->widgets ) ? $starter_content['widgets'] : array(); + $attachments = isset( $starter_content['attachments'] ) && ! empty( $this->nav_menus ) ? $starter_content['attachments'] : array(); $posts = isset( $starter_content['posts'] ) && ! empty( $this->nav_menus ) ? $starter_content['posts'] : array(); $options = isset( $starter_content['options'] ) ? $starter_content['options'] : array(); $nav_menus = isset( $starter_content['nav_menus'] ) && ! empty( $this->nav_menus ) ? $starter_content['nav_menus'] : array(); @@ -965,26 +966,126 @@ final class WP_Customize_Manager { } } + $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; + } + } + + // 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; + } + + $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 ) ); + } + } + // 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']; - } - - $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; - } - } - foreach ( array_keys( $posts ) as $post_symbol ) { if ( empty( $posts[ $post_symbol ]['post_type'] ) ) { continue; @@ -999,24 +1100,36 @@ final class WP_Customize_Manager { } // Use existing auto-draft post if one already exists with the same type and name. - if ( isset( $existing_posts[ $post_type . ':' . $post_name ] ) ) { - $posts[ $post_symbol ]['ID'] = $existing_posts[ $post_type . ':' . $post_name ]->ID; + if ( isset( $existing_starter_content_posts[ $post_type . ':' . $post_name ] ) ) { + $posts[ $post_symbol ]['ID'] = $existing_starter_content_posts[ $post_type . ':' . $post_name ]->ID; continue; } + // Translate the featured image symbol. + if ( ! empty( $posts[ $post_symbol ]['thumbnail'] ) + && preg_match( '/^{{(?P.+)}}$/', $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']; + } + $r = $this->nav_menus->insert_auto_draft_post( $posts[ $post_symbol ] ); if ( $r instanceof WP_Post ) { $posts[ $post_symbol ]['ID'] = $r->ID; } } - // The nav_menus_created_posts setting is why nav_menus component is dependency for adding posts. + $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 ) ) { $setting_id = 'nav_menus_created_posts'; - 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; - } + $this->set_post_value( $setting_id, array_unique( array_values( $starter_content_auto_draft_post_ids ) ) ); + $this->pending_starter_content_settings_ids[] = $setting_id; } // Nav menus. diff --git a/wp-includes/class-wp-customize-nav-menus.php b/wp-includes/class-wp-customize-nav-menus.php index 7ce9e18ed3..1305a147e0 100644 --- a/wp-includes/class-wp-customize-nav-menus.php +++ b/wp-includes/class-wp-customize-nav-menus.php @@ -1191,8 +1191,10 @@ final class WP_Customize_Nav_Menus { $post_ids = $setting->post_value(); if ( ! empty( $post_ids ) ) { foreach ( $post_ids as $post_id ) { + $target_status = 'attachment' === get_post_type( $post_id ) ? 'inherit' : 'publish'; + // Note that wp_publish_post() cannot be used because unique slugs need to be assigned. - wp_update_post( array( 'ID' => $post_id, 'post_status' => 'publish' ) ); + wp_update_post( array( 'ID' => $post_id, 'post_status' => $target_status ) ); } } } diff --git a/wp-includes/post.php b/wp-includes/post.php index d3c68ca89b..620d1e4a8f 100644 --- a/wp-includes/post.php +++ b/wp-includes/post.php @@ -3058,7 +3058,7 @@ function wp_insert_post( $postarr, $wp_error = false ) { } $post_status = empty( $postarr['post_status'] ) ? 'draft' : $postarr['post_status']; - if ( 'attachment' === $post_type && ! in_array( $post_status, array( 'inherit', 'private', 'trash' ) ) ) { + if ( 'attachment' === $post_type && ! in_array( $post_status, array( 'inherit', 'private', 'trash', 'auto-draft' ), true ) ) { $post_status = 'inherit'; } diff --git a/wp-includes/theme.php b/wp-includes/theme.php index eea50a50dc..136ec840d7 100644 --- a/wp-includes/theme.php +++ b/wp-includes/theme.php @@ -1986,8 +1986,17 @@ function get_theme_starter_content() { // Widgets are grouped into sidebars. case 'widgets' : foreach ( $config[ $type ] as $sidebar_id => $widgets ) { - foreach ( $widgets as $widget ) { + foreach ( $widgets as $id => $widget ) { if ( is_array( $widget ) ) { + + // 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 ), + ); + } + $content[ $type ][ $sidebar_id ][] = $widget; } elseif ( is_string( $widget ) && ! empty( $core_content[ $type ] ) && ! empty( $core_content[ $type ][ $widget ] ) ) { $content[ $type ][ $sidebar_id ][] = $core_content[ $type ][ $widget ]; @@ -2007,8 +2016,14 @@ function get_theme_starter_content() { $content[ $type ][ $nav_menu_location ]['name'] = $nav_menu['name']; - foreach ( $nav_menu['items'] as $nav_menu_item ) { + foreach ( $nav_menu['items'] as $id => $nav_menu_item ) { if ( is_array( $nav_menu_item ) ) { + + // Item extends core content. + if ( ! empty( $core_content[ $type ][ $id ] ) ) { + $nav_menu_item = array_merge( $core_content[ $type ][ $id ], $nav_menu_item ); + } + $content[ $type ][ $nav_menu_location ]['items'][] = $nav_menu_item; } elseif ( is_string( $nav_menu_item ) && ! empty( $core_content[ $type ] ) && ! empty( $core_content[ $type ][ $nav_menu_item ] ) ) { $content[ $type ][ $nav_menu_location ]['items'][] = $core_content[ $type ][ $nav_menu_item ]; @@ -2017,12 +2032,41 @@ function get_theme_starter_content() { } break; - // Everything else should map at the next level. - default : - foreach( $config[ $type ] as $i => $item ) { + // 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 ) { if ( is_array( $item ) ) { - $content[ $type ][ $i ] = $item; - } elseif ( is_string( $item ) && ! empty( $core_content[ $type ] ) && ! empty( $core_content[ $type ][ $item ] ) ) { + + // 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 ] ) ) { $content[ $type ][ $item ] = $core_content[ $type ][ $item ]; } } diff --git a/wp-includes/version.php b/wp-includes/version.php index 96a4aeb330..4e0487afdb 100644 --- a/wp-includes/version.php +++ b/wp-includes/version.php @@ -4,7 +4,7 @@ * * @global string $wp_version */ -$wp_version = '4.7-beta4-39345'; +$wp_version = '4.7-beta4-39346'; /** * Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.