Skip to content
This repository has been archived by the owner on Feb 23, 2024. It is now read-only.

[Store Customization MVP] Add image alts to the ai prompt if available #11101

Merged
merged 9 commits into from
Oct 13, 2023
36 changes: 9 additions & 27 deletions patterns/store-info-alt-image-and-text.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
*/

use Automattic\WooCommerce\Blocks\Patterns\PatternsHelper;
$images = PatternsHelper::get_pattern_images( 'woocommerce-blocks/alt-image-and-text' );
$content = PatternsHelper::get_pattern_content( 'woocommerce-blocks/alt-image-and-text' );
$images = PatternsHelper::get_pattern_images( 'woocommerce-blocks/alt-image-and-text' );

$image1 = PatternsHelper::get_image_url( $images, 0, 'images/pattern-placeholders/crafting-pots.png' );
$image2 = PatternsHelper::get_image_url( $images, 1, 'images/pattern-placeholders/hand-made-pots.png' );
Expand All @@ -29,35 +30,16 @@
<!-- wp:column {"verticalAlignment":"center","width":"50%"} -->
<div class="wp-block-column is-vertically-aligned-center" style="flex-basis:50%">
<!-- wp:paragraph {"placeholder":"Content…","style":{"typography":{"textTransform":"uppercase"}}} -->
<p style="text-transform:uppercase"><?php esc_html_e( 'The goods', 'woo-gutenberg-products-block' ); ?></p>
<p style="text-transform:uppercase"><?php echo esc_html( $content['titles'][0]['default'] ); ?></p>
<!-- /wp:paragraph -->

<!-- wp:heading {"level":3,"style":{"spacing":{"margin":{"top":"0","bottom":"0"}}}} -->
<h3 class="wp-block-heading" style="margin-top:0;margin-bottom:0"><?php esc_html_e( 'Created with love and care in Australia', 'woo-gutenberg-products-block' ); ?></h3>
<h3 class="wp-block-heading" style="margin-top:0;margin-bottom:0"><?php echo esc_html( $content['titles'][1]['default'] ); ?></h3>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p><?php esc_html_e( 'All items are 100% hand-made, using the potter’s wheel or traditional techniques.', 'woo-gutenberg-products-block' ); ?></p>
<p><?php echo esc_html( $content['descriptions'][0]['default'] ); ?></p>
<!-- /wp:paragraph -->

<!-- wp:list -->
<ul><!-- wp:list-item -->
<li><?php esc_html_e( 'Timeless style.', 'woo-gutenberg-products-block' ); ?></li>
<!-- /wp:list-item -->

<!-- wp:list-item -->
<li><?php esc_html_e( 'Earthy, organic feel.', 'woo-gutenberg-products-block' ); ?></li>
<!-- /wp:list-item -->

<!-- wp:list-item -->
<li><?php esc_html_e( 'Enduring quality.', 'woo-gutenberg-products-block' ); ?></li>
<!-- /wp:list-item -->

<!-- wp:list-item -->
<li><?php esc_html_e( 'Unique, one-of-a-kind pieces.', 'woo-gutenberg-products-block' ); ?></li>
<!-- /wp:list-item -->
</ul>
<!-- /wp:list -->
</div>
<!-- /wp:column -->
</div>
Expand All @@ -68,22 +50,22 @@
<!-- wp:column {"verticalAlignment":"center","width":"48%"} -->
<div class="wp-block-column is-vertically-aligned-center" style="flex-basis:48%">
<!-- wp:paragraph {"placeholder":"Content…","style":{"typography":{"textTransform":"uppercase"}}} -->
<p style="text-transform:uppercase"><?php esc_html_e( 'About us', 'woo-gutenberg-products-block' ); ?></p>
<p style="text-transform:uppercase"><?php echo esc_html( $content['titles'][2]['default'] ); ?></p>
<!-- /wp:paragraph -->

<!-- wp:heading {"level":3,"style":{"spacing":{"margin":{"top":"0","bottom":"0"}}}} -->
<h3 class="wp-block-heading" style="margin-top:0;margin-bottom:0"><?php esc_html_e( 'Marl is an independent studio and artisanal gallery', 'woo-gutenberg-products-block' ); ?></h3>
<h3 class="wp-block-heading" style="margin-top:0;margin-bottom:0"><?php echo esc_html( $content['titles'][3]['default'] ); ?></h3>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p><?php esc_html_e( 'We specialize in limited collections of handmade tableware. We collaborate with restaurants and cafes to create unique items that complement the menu perfectly. Please get in touch if you want to know more about our process and pricing.', 'woo-gutenberg-products-block' ); ?></p>
<p><?php echo esc_html( $content['descriptions'][1]['default'] ); ?></p>
<!-- /wp:paragraph -->

<!-- wp:buttons {"style":{"spacing":{"blockGap":"0"}},"fontSize":"small"} -->
<div class="wp-block-buttons has-custom-font-size has-small-font-size">
<!-- wp:button {"className":"is-style-outline"} -->
<div class="wp-block-button is-style-outline">
<a class="wp-block-button__link wp-element-button"><?php esc_html_e( 'Learn more', 'woo-gutenberg-products-block' ); ?></a>
<a class="wp-block-button__link wp-element-button"><?php echo esc_html( $content['buttons'][0]['default'] ); ?></a>
</div>
<!-- /wp:button -->
</div>
Expand Down
4 changes: 3 additions & 1 deletion src/BlockPatterns.php
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,8 @@ public function update_patterns_content( $value ) {
return $vertical_id;
}

return ( new PatternUpdater() )->create_patterns_content( $vertical_id, new Client() );
$business_description = get_option( VerticalsSelector::STORE_DESCRIPTION_OPTION_KEY );

return ( new PatternUpdater() )->create_patterns_content( $vertical_id, new Client(), $business_description );
}
}
40 changes: 27 additions & 13 deletions src/Patterns/PatternUpdater.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,13 @@ public function __construct() {
/**
* Creates the patterns content for the given vertical.
*
* @param int $vertical_id The vertical id.
* @param Client $verticals_api_client The verticals API client.
* @param int $vertical_id The vertical id.
* @param Client $verticals_api_client The verticals API client.
* @param string $business_description The business description.
*
* @return bool|WP_Error
*/
public function create_patterns_content( $vertical_id, $verticals_api_client ) {
public function create_patterns_content( $vertical_id, $verticals_api_client, $business_description = '' ) {
if ( ! is_int( $vertical_id ) ) {
return new WP_Error( 'invalid_vertical_id', __( 'The vertical id is invalid.', 'woo-gutenberg-products-block' ) );
}
Expand All @@ -55,7 +56,7 @@ public function create_patterns_content( $vertical_id, $verticals_api_client ) {
return new WP_Error( 'failed_to_set_pattern_images', __( 'Failed to set the pattern images.', 'woo-gutenberg-products-block' ) );
}

$patterns_with_images_and_content = $this->get_patterns_with_content( $patterns_with_images );
$patterns_with_images_and_content = $this->get_patterns_with_content( $patterns_with_images, $business_description );

if ( is_wp_error( $patterns_with_images_and_content ) ) {
return new WP_Error( 'failed_to_set_pattern_content', __( 'Failed to set the pattern content.', 'woo-gutenberg-products-block' ) );
Expand Down Expand Up @@ -96,13 +97,23 @@ private function get_patterns_with_images( $vertical_images ) {
continue;
}

$images = $this->get_images_for_pattern( $pattern, $vertical_images );
list($images, $alts) = $this->get_images_for_pattern( $pattern, $vertical_images );
if ( empty( $images ) ) {
$patterns_with_images[] = $pattern;
continue;
}

$pattern['images'] = $images;
$pattern['images'] = $images;

$string = wp_json_encode( $pattern );

foreach ( $alts as $i => $alt ) {
$alt = empty( $alt ) ? 'the text should be related to the store description but generic enough to adapt to any image' : $alt;
$string = str_replace( "{image.$i}", $alt, $string );
}

$pattern = json_decode( $string, true );

$patterns_with_images[] = $pattern;
}

Expand All @@ -112,11 +123,12 @@ private function get_patterns_with_images( $vertical_images ) {
/**
* Returns the patterns with AI generated content.
*
* @param array $patterns The array of patterns.
* @param array $patterns The array of patterns.
* @param string $business_description The business description.
*
* @return array|WP_Error The patterns with AI generated content.
*/
public function get_patterns_with_content( array $patterns ) {
private function get_patterns_with_content( array $patterns, string $business_description ) {
$site_id = $this->ai_connection->get_site_id();

if ( is_wp_error( $site_id ) ) {
Expand All @@ -132,8 +144,8 @@ public function get_patterns_with_content( array $patterns ) {
$patterns_with_content = $patterns;

$prompts = array();
foreach ( $patterns_with_content as $key => $pattern ) {
$prompt = sprintf( 'Given the following store description: "%s", and the following JSON file representing the content of the "%s" pattern: %s.\n', get_option( VerticalsSelector::STORE_DESCRIPTION_OPTION_KEY ), $pattern['name'], wp_json_encode( $pattern['content'] ) );
foreach ( $patterns_with_content as $pattern ) {
$prompt = sprintf( 'Given the following store description: "%s", and the following JSON file representing the content of the "%s" pattern: %s.\n', $business_description, $pattern['name'], wp_json_encode( $pattern['content'] ) );
$prompt .= "Replace the titles, descriptions and button texts in each 'default' key using the prompt in the corresponding 'ai_prompt' key by a text that is related to the previous store description (but not the exact text) and matches the 'ai_prompt', the length of each replacement should be similar to the 'default' text length. The response should be only a JSON string, with absolutely no intro or explanations.";

$prompts[] = $prompt;
Expand Down Expand Up @@ -192,21 +204,23 @@ private function pattern_has_images( array $pattern ): bool {
* @param array $pattern The array representing the pattern.
* @param array $vertical_images The array of vertical images.
*
* @return string[]
* @return array An array containing an array of the images in the first position and their alts in the second.
*/
private function get_images_for_pattern( array $pattern, array $vertical_images ): array {
$alts = array();
$images = array();
if ( count( $vertical_images ) < $pattern['images_total'] ) {
return $images;
return array( $images, $alts );
}

foreach ( $vertical_images as $vertical_image ) {
if ( $pattern['images_format'] === $this->get_image_format( $vertical_image ) ) {
$images[] = str_replace( 'http://', 'https://', $vertical_image['guid'] );
$alts[] = $vertical_image['meta']['pexels_object']['alt'] ?? '';
}
}

return $images;
return array( $images, $alts );
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/Patterns/PatternsHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public static function get_pattern_images( string $pattern_slug ): array {
return array();
}

return self::get_random_images( $pattern['images'], $pattern['images_total'] );
return $pattern['images'];
}

/**
Expand Down
38 changes: 19 additions & 19 deletions src/Patterns/dictionary.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@
"titles": [
{
"default": "Announcing our newest collection",
"ai_prompt": "The title of the featured category"
"ai_prompt": "The title of the featured category: {image.0}"
}
]
}
Expand All @@ -78,15 +78,15 @@
"titles": [
{
"default": "Cupcakes",
"ai_prompt": "The title of the first featured category"
"ai_prompt": "The title of the first featured category: {image.0}"
},
{
"default": "Sweet Danish",
"ai_prompt": "The title of the second featured category"
"ai_prompt": "The title of the second featured category: {image.1}"
},
{
"default": "Warm Bread",
"ai_prompt": "The title of the third featured category"
"ai_prompt": "The title of the third featured category: {image.2}"
}
]
}
Expand Down Expand Up @@ -118,19 +118,19 @@
"descriptions": [
{
"default": "Sweet Organic Lemons",
"ai_prompt": "The description of the first featured products"
"ai_prompt": "The description of the first featured products: {image.0}"
},
{
"default": "Fresh Organic Tomatoes",
"ai_prompt": "The description of the second featured products"
"ai_prompt": "The description of the second featured products: {image.1}"
},
{
"default": "Fresh Lettuce (Washed)",
"ai_prompt": "The description of the third featured products"
"ai_prompt": "The description of the third featured products: {image.2}"
},
{
"default": "Russet Organic Potatoes",
"ai_prompt": "The description of the fourth featured products"
"ai_prompt": "The description of the fourth featured products: {image.3}"
}
]
}
Expand All @@ -144,7 +144,7 @@
"titles": [
{
"default": "Endless Tee's",
"ai_prompt": "An impact phrase that advertises the displayed product"
"ai_prompt": "An impact phrase that advertises the displayed product: {image.0}"
},
{
"default": "Waterproof Membrane",
Expand Down Expand Up @@ -196,7 +196,7 @@
"titles": [
{
"default": "The Fall Collection",
"ai_prompt": "An impact phrase that advertises the displayed product"
"ai_prompt": "An impact phrase that advertises the displayed product: {image.0}"
},
{
"default": "Quality Materials",
Expand Down Expand Up @@ -248,7 +248,7 @@
"titles": [
{
"default": "Get cozy this fall with knit sweaters",
"ai_prompt": "An impact phrase that advertises the displayed product"
"ai_prompt": "An impact phrase that advertises the displayed product: {image.0}"
}
]
}
Expand Down Expand Up @@ -286,7 +286,7 @@
"titles": [
{
"default": "Brand New for the Holidays",
"ai_prompt": "An impact phrase that advertises the displayed product collection"
"ai_prompt": "An impact phrase that advertises the displayed product collection: {image.0}"
}
],
"descriptions": [
Expand Down Expand Up @@ -318,11 +318,11 @@
"titles": [
{
"default": "Tech gifts under $100",
"ai_prompt": "An impact phrase that advertises the first product collection"
"ai_prompt": "An impact phrase that advertises the first product collection: {image.0}, {image.1}"
},
{
"default": "For the gamers",
"ai_prompt": "An impact phrase that advertises the second product collection"
"ai_prompt": "An impact phrase that advertises the second product collection: {image.2}, {image.3}"
}
],
"buttons": [
Expand Down Expand Up @@ -436,7 +436,7 @@
"titles": [
{
"default": "The Eden Jacket",
"ai_prompt": "An title that advertises the displayed product"
"ai_prompt": "An title that advertises the displayed product: {image.0}"
},
{
"default": "100% Woolen",
Expand All @@ -458,7 +458,7 @@
"descriptions": [
{
"default": "Perfect for any look featuring a mid-rise, relax fitting silhouette.",
"ai_prompt": "A description of the displayed product"
"ai_prompt": "A description of the displayed product: {image.0}"
},
{
"default": "Reflect your fashionable style.",
Expand Down Expand Up @@ -518,7 +518,7 @@
"titles": [
{
"default": "Chairs",
"ai_prompt": "An impact phrase that advertises a products"
"ai_prompt": "An impact phrase that advertises a products: {image.0}"
}
]
}
Expand Down Expand Up @@ -550,14 +550,14 @@
},
{
"default": "Created with love and care in Australia",
"ai_prompt": "An impact phrase that advertises the products"
"ai_prompt": "An impact phrase that advertises the products: {image.0}"
},
{
"default": "About us",
"ai_prompt": "An impact phrase that advertises the brand"
},
{
"default": "Marl is an independent studio and artisanal gallery",
"default": "Marl is an independent studio and artisanal gallery: {image.1}",
"ai_prompt": "An impact phrase that advertises the brand"
}
],
Expand Down
2 changes: 1 addition & 1 deletion src/StoreApi/Routes/V1/Patterns.php
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ protected function get_route_post_response( \WP_REST_Request $request ) {
if ( is_wp_error( $vertical_id ) ) {
$response = $this->error_to_response( $vertical_id );
} else {
$populate_images = ( new PatternUpdater() )->create_patterns_content( $vertical_id, new Client() );
$populate_images = ( new PatternUpdater() )->create_patterns_content( $vertical_id, new Client(), $business_description );

if ( is_wp_error( $populate_images ) ) {
$response = $this->error_to_response( $populate_images );
Expand Down