Add images to homepage template and a new layout for sites with more than 4 products (https://github.com/woocommerce/woocommerce-admin/pull/3140)

* Switch templates for sites with more than 4 products

* Update homepage template depending on number of products, and add industry images to templates.

* Slight refactor of the update post template logic
This commit is contained in:
Justin Shreve 2019-11-01 08:49:04 -04:00 committed by GitHub
parent a3224ce65a
commit d04b8a0fc1
8 changed files with 207 additions and 2 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 721 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 533 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 796 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 468 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 390 KiB

View File

@ -162,6 +162,205 @@ class OnboardingTasks extends \WC_REST_Data_Controller {
return '/' . str_replace( array( '%d', '%s' ), '(.*)', trim( quotemeta( $value ) ) ) . '/';
}
/**
* Returns a valid cover block with an image, if one exists, or background as a fallback.
*
* @param array $image Image to use for the cover block. Should contain a media ID and image URL.
* @return string Block content.
*/
private static function get_homepage_cover_block( $image ) {
if ( ! empty ( $image['url'] ) && ! empty( $image['id'] ) ) {
return '<!-- wp:cover {"url":"' . esc_url( $image['url'] ) .'","id":' . intval( $image['id'] ) . '} -->
<div class="wp-block-cover has-background-dim" style="background-image:url(' . esc_url( $image['url'] ) . ')"><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"' . __( 'Write title…', 'woocommerce-admin' ) . '","fontSize":"large"} -->
<p class="has-text-align-center has-large-font-size">' . __( 'Welcome to the store', 'woocommerce-admin' ) . '</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph {"align":"center"} -->
<p class="has-text-align-center">' . __( 'Write a short welcome message here', 'woocommerce-admin' ) . '</p>
<!-- /wp:paragraph -->
<!-- wp:button {"align":"center"} -->
<div class="wp-block-button aligncenter"><a class="wp-block-button__link">' . __( 'Go shopping', 'woocommerce-admin' ) . '</a></div>
<!-- /wp:button --></div></div>
<!-- /wp:cover -->';
}
return '<!-- wp:cover {"overlayColor":"very-dark-gray"} -->
<div class="wp-block-cover has-very-dark-gray-background-color has-background-dim"><div class="wp-block-cover__inner-container"><!-- wp:paragraph {"align":"center","placeholder":"' . __( 'Write title…', 'woocommerce-admin' ) . '","fontSize":"large"} -->
<p class="has-text-align-center has-large-font-size">' . __( 'Welcome to the store', 'woocommerce-admin' ) . '</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph {"align":"center"} -->
<p class="has-text-align-center">' . __( 'Write a short welcome message here', 'woocommerce-admin' ) . '</p>
<!-- /wp:paragraph -->
<!-- wp:button {"align":"center"} -->
<div class="wp-block-button aligncenter"><a class="wp-block-button__link">' . __( 'Go shopping', 'woocommerce-admin' ) . '</a></div>
<!-- /wp:button --></div></div>
<!-- /wp:cover -->';
}
/**
* Returns a valid media block with an image, if one exists, or a uninitialized media block the user can set.
*
* @param array $image Image to use for the cover block. Should contain a media ID and image URL.
* @param string $align If the image should be aligned to the left or right.
* @return string Block content.
*/
private static function get_homepage_media_block( $image, $align = 'left' ) {
$media_position = 'right' === $align ? '"mediaPosition":"right",' : '';
$css_class = 'right' === $align ? ' has-media-on-the-right' : '';
if ( ! empty ( $image['url'] ) && ! empty( $image['id'] ) ) {
return '<!-- wp:media-text {' . $media_position . '"mediaId":' . intval( $image['id'] ) . ',"mediaType":"image"} -->
<div class="wp-block-media-text alignwide' . $css_class . '""><figure class="wp-block-media-text__media"><img src="' . esc_url( $image['url'] ) . '" alt="" class="wp-image-' . intval( $image['id'] ) . '"/></figure><div class="wp-block-media-text__content"><!-- wp:paragraph {"placeholder":"' . __( 'Content…', 'woocommerce-admin' ) . '","fontSize":"large"} -->
<p class="has-large-font-size"></p>
<!-- /wp:paragraph --></div></div>
<!-- /wp:media-text -->';
}
return '<!-- wp:media-text {' . $media_position . '} -->
<div class="wp-block-media-text alignwide' . $css_class . '"><figure class="wp-block-media-text__media"></figure><div class="wp-block-media-text__content"><!-- wp:paragraph {"placeholder":"' . __( 'Content…' , 'woocommerce-admin' ) . '","fontSize":"large"} -->
<p class="has-large-font-size"></p>
<!-- /wp:paragraph --></div></div>
<!-- /wp:media-text -->';
}
/**
* Returns a homepage template to be inserted into a post. A different template will be used depending on the number of products.
*
* @param int $post_id ID of the homepage template.
* @return string Template contents.
*/
private static function get_homepage_template( $post_id ) {
$products = wp_count_posts( 'product' );
if ( $products->publish >= 4 ) {
$images = self::sideload_homepage_images( $post_id, 1 );
$image_1 = ! empty( $images[0] ) ? $images[0] : '';
$cover = self::get_homepage_cover_block( $image_1 );
return $cover . '
<!-- wp:heading {"align":"center"} -->
<h2 style="text-align:center">' . __( 'Shop by Category', 'woocommerce-admin' ) . '</h2>
<!-- /wp:heading -->
<!-- wp:shortcode -->
[product_categories limit="3" columns="3" orderby="menu_order"]
<!-- /wp:shortcode -->
<!-- wp:heading {"align":"center"} -->
<h2 style="text-align:center">' . __( 'New In', 'woocommerce-admin' ) . '</h2>
<!-- /wp:heading -->
<!-- wp:woocommerce/product-new {"columns":4} -->
<div class="wp-block-woocommerce-product-new">[products limit="4" columns="4" orderby="date" order="DESC"]</div>
<!-- /wp:woocommerce/product-new -->
<!-- wp:heading {"align":"center"} -->
<h2 style="text-align:center">' . __( 'Fan Favorites', 'woocommerce-admin' ) . '</h2>
<!-- /wp:heading -->
<!-- wp:woocommerce/product-top-rated {"columns":4} -->
<div class="wp-block-woocommerce-product-top-rated">[products limit="4" columns="4" orderby="rating"]</div>
<!-- /wp:woocommerce/product-top-rated -->
<!-- wp:heading {"align":"center"} -->
<h2 style="text-align:center">' . __( 'On Sale', 'woocommerce-admin' ) . '</h2>
<!-- /wp:heading -->
<!-- wp:woocommerce/product-on-sale {"columns":4} -->
<div class="wp-block-woocommerce-product-on-sale">[products limit="4" columns="4" orderby="date" order="DESC" on_sale="1"]</div>
<!-- /wp:woocommerce/product-on-sale -->
<!-- wp:heading {"align":"center"} -->
<h2 style="text-align:center">' . __( 'Best Sellers', 'woocommerce-admin' ) . '</h2>
<!-- /wp:heading -->
<!-- wp:woocommerce/product-best-sellers {"columns":4} -->
<div class="wp-block-woocommerce-product-best-sellers">[products limit="4" columns="4" best_selling="1"]</div>
<!-- /wp:woocommerce/product-best-sellers -->
';
}
$images = self::sideload_homepage_images( $post_id, 3 );
$image_1 = ! empty( $images[0] ) ? $images[0] : '';
$image_2 = ! empty( $images[1] ) ? $images[1] : '';
$image_3 = ! empty( $images[2] ) ? $images[2] : '';
$cover = self::get_homepage_cover_block( $image_1 );
return $cover . '
<!-- wp:heading {"align":"center"} -->
<h2 class="has-text-align-center">' . __( 'New products', 'woocommerce-admin' ). '</h2>
<!-- /wp:heading -->
<!-- wp:woocommerce/product-new /--> ' .
self::get_homepage_media_block( $image_1, 'right' ) .
self::get_homepage_media_block( $image_2, 'left' ) .
self::get_homepage_media_block( $image_3, 'right' ) . '
<!-- wp:woocommerce/featured-product /-->';
}
/**
* Gets the possible industry images from the plugin folder for sideloading. If an image doesn't exist, other.jpg is used a fallback.
*
* @return array An array of images by industry.
*/
private static function get_available_homepage_images() {
$industry_images = array();
$industries = Onboarding::get_allowed_industries();
foreach ( $industries as $industry_slug => $label ) {
$file_path = WC_ADMIN_ABSPATH . 'images/onboarding/' . $industry_slug . '.jpg';
if ( 'other' === $industry_slug || ! file_exists( $file_path ) ) {
$industry_images[ $industry_slug ] = apply_filters( 'woocommerce_admin_onboarding_industry_image', plugins_url( 'images/onboarding/other.jpg', WC_ADMIN_PLUGIN_FILE ), $industry_slug );
continue;
}
$industry_images[ $industry_slug ] = apply_filters( 'woocommerce_admin_onboarding_industry_image', plugins_url( 'images/onboarding/' . $industry_slug .'.jpg', WC_ADMIN_PLUGIN_FILE ), $industry_slug );
}
return $industry_images;
}
/**
* Uploads a number of images to a homepage template, depending on the selected industry from the profile wizard.
*
* @param int $post_id ID of the homepage template.
* @param int $number_of_images The number of images that should be sideloaded (depending on how many media slots are in the template).
* @return array An array of images that have been attached to the post.
*/
private static function sideload_homepage_images( $post_id, $number_of_images ) {
$profile = get_option( 'wc_onboarding_profile', array() );
$images_to_sideload = array();
$available_images = self::get_available_homepage_images();
require_once ABSPATH . 'wp-admin/includes/image.php';
require_once ABSPATH . 'wp-admin/includes/file.php';
require_once ABSPATH . 'wp-admin/includes/media.php';
if ( ! empty( $profile['industry'] ) ) {
foreach( $profile['industry'] as $selected_industry ) {
$images_to_sideload[] = ! empty ( $available_images[ $selected_industry ] ) ? $available_images[ $selected_industry ] : $available_images[ 'other' ];
}
}
// Make sure we have at least {$number_of_images} images.
if ( count( $images_to_sideload ) < $number_of_images ) {
for ( $i = count( $images_to_sideload ); $i < $number_of_images; $i++ ) {
$images_to_sideload[] = ! empty( $profile['industry'] ) && ! empty ( $available_images[ $profile['industry'][0] ] ) ? $available_images[ $profile['industry'][ 0 ] ] : $available_images[ 'other' ];
}
}
$already_sideloaded = array();
$images_for_post = array();
foreach ( $images_to_sideload as $image ) {
// Avoid uploading two of the same image, if an image is repeated.
if ( ! empty( $already_sideloaded[ $image ] ) ) {
$images_for_post[] = $already_sideloaded[ $image ];
continue;
}
$sideload_id = \media_sideload_image( $image, $post_id, null, 'id' );
if ( ! is_wp_error( $sideload_id ) ) {
$sideload_url = wp_get_attachment_url( $sideload_id );
$already_sideloaded[ $image ] = array( 'id' => $sideload_id, 'url' => $sideload_url );
$images_for_post[] = $already_sideloaded[ $image ];
}
}
return $images_for_post;
}
/**
* Create a homepage from a template.
*/
@ -171,12 +370,18 @@ class OnboardingTasks extends \WC_REST_Data_Controller {
'post_title' => __( 'Homepage', 'woocommerce-admin' ),
'post_type' => 'page',
'post_status' => 'draft',
// @todo The images in this content should be replaced with working external links or imported.
'post_content' => "<!-- wp:cover {\"url\":\"https://local.wordpress.test/wp-content/uploads/2019/05/parallax.jpeg\",\"id\":3624} -->\n<div class=\"wp-block-cover has-background-dim\" style=\"background-image:url(https://local.wordpress.test/wp-content/uploads/2019/05/parallax.jpeg)\"><div class=\"wp-block-cover__inner-container\"><!-- wp:paragraph {\"align\":\"center\",\"placeholder\":\"Write title…\",\"fontSize\":\"large\"} -->\n<p style=\"text-align:center\" class=\"has-large-font-size\">Welcome to the store</p>\n<!-- /wp:paragraph -->\n\n<!-- wp:paragraph {\"align\":\"center\"} -->\n<p style=\"text-align:center\">Write a short welcome message here</p>\n<!-- /wp:paragraph -->\n\n<!-- wp:button {\"align\":\"center\"} -->\n<div class=\"wp-block-button aligncenter\"><a class=\"wp-block-button__link\">Go shopping</a></div>\n<!-- /wp:button --></div></div>\n<!-- /wp:cover -->\n\n<!-- wp:heading {\"align\":\"center\"} -->\n<h2 style=\"text-align:center\">New products</h2>\n<!-- /wp:heading -->\n\n<!-- wp:woocommerce/product-new /-->\n\n<!-- wp:media-text {\"align\":\"\",\"backgroundColor\":\"light-gray\",\"mediaPosition\":\"right\",\"mediaId\":1257,\"mediaType\":\"image\"} -->\n<div class=\"wp-block-media-text has-media-on-the-right has-light-gray-background-color\"><figure class=\"wp-block-media-text__media\"><img src=\"https://local.wordpress.test/wp-content/uploads/2017/05/brady-bellini-191086-1024x616.jpg\" alt=\"\" class=\"wp-image-1257\"/></figure><div class=\"wp-block-media-text__content\"><!-- wp:paragraph {\"align\":\"center\",\"placeholder\":\"Content…\",\"fontSize\":\"large\"} -->\n<p style=\"text-align:center\" class=\"has-large-font-size\">Here's a business goal</p>\n<!-- /wp:paragraph -->\n\n<!-- wp:paragraph {\"align\":\"center\"} -->\n<p style=\"text-align:center\">Describe your business aspiration here.</p>\n<!-- /wp:paragraph --></div></div>\n<!-- /wp:media-text -->\n\n<!-- wp:media-text {\"align\":\"\",\"backgroundColor\":\"light-gray\",\"mediaId\":1257,\"mediaType\":\"image\"} -->\n<div class=\"wp-block-media-text has-light-gray-background-color\"><figure class=\"wp-block-media-text__media\"><img src=\"https://local.wordpress.test/wp-content/uploads/2017/05/brady-bellini-191086-1024x616.jpg\" alt=\"\" class=\"wp-image-1257\"/></figure><div class=\"wp-block-media-text__content\"><!-- wp:paragraph {\"align\":\"center\",\"placeholder\":\"Content…\",\"fontSize\":\"large\"} -->\n<p style=\"text-align:center\" class=\"has-large-font-size\">Another business goal</p>\n<!-- /wp:paragraph -->\n\n<!-- wp:paragraph {\"align\":\"center\"} -->\n<p style=\"text-align:center\">Describe your business aspiration here.</p>\n<!-- /wp:paragraph --></div></div>\n<!-- /wp:media-text -->\n\n<!-- wp:media-text {\"align\":\"\",\"backgroundColor\":\"light-gray\",\"mediaPosition\":\"right\",\"mediaId\":1257,\"mediaType\":\"image\"} -->\n<div class=\"wp-block-media-text has-media-on-the-right has-light-gray-background-color\"><figure class=\"wp-block-media-text__media\"><img src=\"https://local.wordpress.test/wp-content/uploads/2017/05/brady-bellini-191086-1024x616.jpg\" alt=\"\" class=\"wp-image-1257\"/></figure><div class=\"wp-block-media-text__content\"><!-- wp:paragraph {\"align\":\"center\",\"placeholder\":\"Content…\",\"fontSize\":\"large\"} -->\n<p style=\"text-align:center\" class=\"has-large-font-size\">A final business goal</p>\n<!-- /wp:paragraph -->\n\n<!-- wp:paragraph {\"align\":\"center\"} -->\n<p style=\"text-align:center\">Describe your business aspiration here.</p>\n<!-- /wp:paragraph --></div></div>\n<!-- /wp:media-text -->\n\n<!-- wp:woocommerce/featured-product {\"editMode\":false,\"productId\":2567} -->\n<!-- wp:button {\"align\":\"center\"} -->\n<div class=\"wp-block-button aligncenter\"><a class=\"wp-block-button__link\" href=\"https://local.wordpress.test/shop/decor/wordpress-pennant\">Shop now</a></div>\n<!-- /wp:button -->\n<!-- /wp:woocommerce/featured-product -->"
'post_content' => '', // Template content is updated below, so images can be attached to the post.
)
);
if ( ! is_wp_error( $post_id ) ) {
$template = self::get_homepage_template( $post_id );
wp_update_post( array(
'ID' => $post_id,
'post_content' => $template,
) );
update_option( 'woocommerce_onboarding_homepage_post_id', $post_id );
return array(