From 589617a41d93daa069d90b7c27a89d2139d77223 Mon Sep 17 00:00:00 2001 From: Patricia Hillebrandt Date: Wed, 27 Dec 2023 08:33:37 -0300 Subject: [PATCH] CYS > Update AI-generated site title, image optimizations and updated directory structure (#43086) * Remove the last business description check to allow repetition. * Create the new AIContent directory and update the structure and name of the classes. * Ensure the store title is updated with new AI-generated content if the previous title was also AI-generated. * Return if the images result in error. * Update the name of the option for fetching the AI generated site title. * Introduce the new adjust_image_size method for shared usage between products and patterns. * Increase the quality of images used in patterns * Introduce the ContentImageProcessor class. * Undo PatternsHelper rename * Add changefile(s) from automation for the following project(s): woocommerce * Address lint errors * Ask AI to summarize the business description if the number of characters provided by the user is bigger than 150 characters. * Rename the ContentImageProcessor class to ContentProcessor and introduce the new summarize_business_description method. --------- Co-authored-by: github-actions --- .../43086-enhance-ai-content-generation | 4 + plugins/woocommerce/patterns/banner.php | 2 +- .../patterns/discount-banner-with-image.php | 2 +- .../featured-category-cover-image.php | 2 +- .../patterns/featured-category-focus.php | 2 +- .../patterns/featured-category-triple.php | 2 +- .../featured-products-fresh-and-tasty.php | 2 +- .../patterns/hero-product-3-split.php | 2 +- .../patterns/hero-product-chessboard.php | 2 +- .../patterns/hero-product-split.php | 2 +- .../patterns/just-arrived-full-hero.php | 2 +- .../patterns/product-collection-4-columns.php | 1 - .../patterns/product-collection-5-columns.php | 1 - .../patterns/product-collection-banner.php | 2 +- ...collection-featured-products-5-columns.php | 2 - ...roduct-collections-featured-collection.php | 2 - ...oduct-collections-featured-collections.php | 2 +- .../product-collections-newest-arrivals.php | 2 - .../patterns/product-featured-2-columns.php | 1 - .../patterns/product-hero-2-col-2-row.php | 2 +- .../woocommerce/patterns/shop-by-price.php | 2 - .../small-discount-banner-with-image.php | 2 +- .../social-follow-us-in-social-media.php | 2 +- .../store-info-alt-image-and-text.php | 2 +- .../patterns/testimonials-3-columns.php | 2 - .../patterns/testimonials-single.php | 2 +- .../src/Blocks/AIContent/ContentProcessor.php | 95 +++++++++++++++++++ .../PatternsHelper.php | 8 +- .../UpdatePatterns.php} | 42 ++------ .../UpdateProducts.php} | 67 +++---------- .../{Patterns => AIContent}/dictionary.json | 0 .../woocommerce/src/Blocks/BlockPatterns.php | 10 +- .../woocommerce/src/Blocks/Images/Pexels.php | 12 ++- .../src/StoreApi/Routes/V1/AI/Patterns.php | 13 +-- .../src/StoreApi/Routes/V1/AI/Product.php | 4 +- .../src/StoreApi/Routes/V1/AI/Products.php | 6 +- .../src/StoreApi/Routes/V1/AI/StoreInfo.php | 6 +- .../src/StoreApi/Routes/V1/AI/StoreTitle.php | 7 +- 38 files changed, 175 insertions(+), 146 deletions(-) create mode 100644 plugins/woocommerce/changelog/43086-enhance-ai-content-generation create mode 100644 plugins/woocommerce/src/Blocks/AIContent/ContentProcessor.php rename plugins/woocommerce/src/Blocks/{Patterns => AIContent}/PatternsHelper.php (94%) rename plugins/woocommerce/src/Blocks/{Patterns/PatternUpdater.php => AIContent/UpdatePatterns.php} (91%) rename plugins/woocommerce/src/Blocks/{Patterns/ProductUpdater.php => AIContent/UpdateProducts.php} (89%) rename plugins/woocommerce/src/Blocks/{Patterns => AIContent}/dictionary.json (100%) diff --git a/plugins/woocommerce/changelog/43086-enhance-ai-content-generation b/plugins/woocommerce/changelog/43086-enhance-ai-content-generation new file mode 100644 index 00000000000..0bc85c456b0 --- /dev/null +++ b/plugins/woocommerce/changelog/43086-enhance-ai-content-generation @@ -0,0 +1,4 @@ +Significance: minor +Type: update + +Ensure the site title can be updated by AI if the owner doesn't change it. Update the size of the images assigned to products and patterns for optimal performance. Allow usage of the same business description on multiple attempts of AI content generation. \ No newline at end of file diff --git a/plugins/woocommerce/patterns/banner.php b/plugins/woocommerce/patterns/banner.php index c664adb8f01..858d497fd23 100644 --- a/plugins/woocommerce/patterns/banner.php +++ b/plugins/woocommerce/patterns/banner.php @@ -5,7 +5,7 @@ * Categories: WooCommerce */ -use Automattic\WooCommerce\Blocks\Patterns\PatternsHelper; +use Automattic\WooCommerce\Blocks\AIContent\PatternsHelper; $banner_title = $content['titles'][0]['default'] ?? ''; $banner_button = $content['buttons'][0]['default'] ?? ''; diff --git a/plugins/woocommerce/patterns/discount-banner-with-image.php b/plugins/woocommerce/patterns/discount-banner-with-image.php index 7b25e1a1207..51bf2f08137 100644 --- a/plugins/woocommerce/patterns/discount-banner-with-image.php +++ b/plugins/woocommerce/patterns/discount-banner-with-image.php @@ -5,7 +5,7 @@ * Categories: WooCommerce */ -use Automattic\WooCommerce\Blocks\Patterns\PatternsHelper; +use Automattic\WooCommerce\Blocks\AIContent\PatternsHelper; $description = $content['descriptions'][0]['default'] ?? ''; ?> diff --git a/plugins/woocommerce/patterns/featured-category-cover-image.php b/plugins/woocommerce/patterns/featured-category-cover-image.php index 95fd8d7819c..52af622b848 100644 --- a/plugins/woocommerce/patterns/featured-category-cover-image.php +++ b/plugins/woocommerce/patterns/featured-category-cover-image.php @@ -5,7 +5,7 @@ * Categories: WooCommerce */ -use Automattic\WooCommerce\Blocks\Patterns\PatternsHelper; +use Automattic\WooCommerce\Blocks\AIContent\PatternsHelper; $image1 = PatternsHelper::get_image_url( $images, 0, 'assets/images/pattern-placeholders/table-wood-house-chair-floor-window.jpg' ); diff --git a/plugins/woocommerce/patterns/featured-category-focus.php b/plugins/woocommerce/patterns/featured-category-focus.php index 2a57971fa43..d70de4f36bd 100644 --- a/plugins/woocommerce/patterns/featured-category-focus.php +++ b/plugins/woocommerce/patterns/featured-category-focus.php @@ -5,7 +5,7 @@ * Categories: WooCommerce */ -use Automattic\WooCommerce\Blocks\Patterns\PatternsHelper; +use Automattic\WooCommerce\Blocks\AIContent\PatternsHelper; $category_title = $content['titles'][0]['default'] ?? ''; diff --git a/plugins/woocommerce/patterns/featured-category-triple.php b/plugins/woocommerce/patterns/featured-category-triple.php index aa991b8c3f5..c8036181865 100644 --- a/plugins/woocommerce/patterns/featured-category-triple.php +++ b/plugins/woocommerce/patterns/featured-category-triple.php @@ -5,7 +5,7 @@ * Categories: WooCommerce */ -use Automattic\WooCommerce\Blocks\Patterns\PatternsHelper; +use Automattic\WooCommerce\Blocks\AIContent\PatternsHelper; $image1 = PatternsHelper::get_image_url( $images, 0, 'assets/images/pattern-placeholders/tree-branch-plant-wood-leaf-flower.jpg' ); $image2 = PatternsHelper::get_image_url( $images, 1, 'assets/images/pattern-placeholders/watch-hand-brand-jewellery-strap-platinum.jpg' ); diff --git a/plugins/woocommerce/patterns/featured-products-fresh-and-tasty.php b/plugins/woocommerce/patterns/featured-products-fresh-and-tasty.php index 4d931819e07..3c848f8152b 100644 --- a/plugins/woocommerce/patterns/featured-products-fresh-and-tasty.php +++ b/plugins/woocommerce/patterns/featured-products-fresh-and-tasty.php @@ -5,7 +5,7 @@ * Categories: WooCommerce */ -use Automattic\WooCommerce\Blocks\Patterns\PatternsHelper; +use Automattic\WooCommerce\Blocks\AIContent\PatternsHelper; $image1 = PatternsHelper::get_image_url( $images, 0, 'assets/images/pattern-placeholders/sweet-organic-lemons.png' ); $image2 = PatternsHelper::get_image_url( $images, 1, 'assets/images/pattern-placeholders/fresh-organic-tomatoes.png' ); diff --git a/plugins/woocommerce/patterns/hero-product-3-split.php b/plugins/woocommerce/patterns/hero-product-3-split.php index 663553fb03d..0cb32f34fd9 100644 --- a/plugins/woocommerce/patterns/hero-product-3-split.php +++ b/plugins/woocommerce/patterns/hero-product-3-split.php @@ -5,7 +5,7 @@ * Categories: WooCommerce */ -use Automattic\WooCommerce\Blocks\Patterns\PatternsHelper; +use Automattic\WooCommerce\Blocks\AIContent\PatternsHelper; $main_title = $content['titles'][3]['default'] ?? ''; $first_title = $content['titles'][0]['default'] ?? ''; diff --git a/plugins/woocommerce/patterns/hero-product-chessboard.php b/plugins/woocommerce/patterns/hero-product-chessboard.php index 6f0ec0eedf7..289949df00e 100644 --- a/plugins/woocommerce/patterns/hero-product-chessboard.php +++ b/plugins/woocommerce/patterns/hero-product-chessboard.php @@ -5,7 +5,7 @@ * Categories: WooCommerce */ -use Automattic\WooCommerce\Blocks\Patterns\PatternsHelper; +use Automattic\WooCommerce\Blocks\AIContent\PatternsHelper; $image1 = PatternsHelper::get_image_url( $images, 0, 'assets/images/pattern-placeholders/plant-white-leaf-flower-vase-green.jpg' ); $image2 = PatternsHelper::get_image_url( $images, 1, 'assets/images/pattern-placeholders/table-wood-house-chair-floor-window.jpg' ); diff --git a/plugins/woocommerce/patterns/hero-product-split.php b/plugins/woocommerce/patterns/hero-product-split.php index 2c0e62361a3..c518cee260d 100644 --- a/plugins/woocommerce/patterns/hero-product-split.php +++ b/plugins/woocommerce/patterns/hero-product-split.php @@ -5,7 +5,7 @@ * Categories: WooCommerce */ -use Automattic\WooCommerce\Blocks\Patterns\PatternsHelper; +use Automattic\WooCommerce\Blocks\AIContent\PatternsHelper; $hero_title = $content['titles'][0]['default'] ?? ''; ?> diff --git a/plugins/woocommerce/patterns/just-arrived-full-hero.php b/plugins/woocommerce/patterns/just-arrived-full-hero.php index f4d27f11711..ae2cb09ff2a 100644 --- a/plugins/woocommerce/patterns/just-arrived-full-hero.php +++ b/plugins/woocommerce/patterns/just-arrived-full-hero.php @@ -5,7 +5,7 @@ * Categories: WooCommerce */ -use Automattic\WooCommerce\Blocks\Patterns\PatternsHelper; +use Automattic\WooCommerce\Blocks\AIContent\PatternsHelper; $pattern_title = $content['titles'][0]['default'] ?? ''; $pattern_description = $content['descriptions'][0]['default'] ?? ''; diff --git a/plugins/woocommerce/patterns/product-collection-4-columns.php b/plugins/woocommerce/patterns/product-collection-4-columns.php index 9f94c1bde19..f7da0e3afde 100644 --- a/plugins/woocommerce/patterns/product-collection-4-columns.php +++ b/plugins/woocommerce/patterns/product-collection-4-columns.php @@ -4,7 +4,6 @@ * Slug: woocommerce-blocks/product-collection-4-columns * Categories: WooCommerce */ -use Automattic\WooCommerce\Blocks\Patterns\PatternsHelper; $products_title = $content['titles'][0]['default'] ?? ''; ?> diff --git a/plugins/woocommerce/patterns/product-collection-5-columns.php b/plugins/woocommerce/patterns/product-collection-5-columns.php index afba5ece5c1..de5098ec772 100644 --- a/plugins/woocommerce/patterns/product-collection-5-columns.php +++ b/plugins/woocommerce/patterns/product-collection-5-columns.php @@ -4,7 +4,6 @@ * Slug: woocommerce-blocks/product-collection-5-columns * Categories: WooCommerce */ -use Automattic\WooCommerce\Blocks\Patterns\PatternsHelper; $products_title = $content['titles'][0]['default'] ?? ''; ?> diff --git a/plugins/woocommerce/patterns/product-collection-banner.php b/plugins/woocommerce/patterns/product-collection-banner.php index ace27ec3a8d..c58540fbf31 100644 --- a/plugins/woocommerce/patterns/product-collection-banner.php +++ b/plugins/woocommerce/patterns/product-collection-banner.php @@ -5,7 +5,7 @@ * Categories: WooCommerce */ -use Automattic\WooCommerce\Blocks\Patterns\PatternsHelper; +use Automattic\WooCommerce\Blocks\AIContent\PatternsHelper; $image = PatternsHelper::get_image_url( $images, 0, 'assets/images/pattern-placeholders/beach-landscape-sea-coast-nature-person.jpg' ); diff --git a/plugins/woocommerce/patterns/product-collection-featured-products-5-columns.php b/plugins/woocommerce/patterns/product-collection-featured-products-5-columns.php index 280c84e5ad8..4e7780f8c53 100644 --- a/plugins/woocommerce/patterns/product-collection-featured-products-5-columns.php +++ b/plugins/woocommerce/patterns/product-collection-featured-products-5-columns.php @@ -5,8 +5,6 @@ * Categories: WooCommerce */ -use Automattic\WooCommerce\Blocks\Patterns\PatternsHelper; - $collection_title = $content['titles'][0]['default'] ?? ''; ?> diff --git a/plugins/woocommerce/patterns/product-collections-featured-collection.php b/plugins/woocommerce/patterns/product-collections-featured-collection.php index faa71c85638..b9ff060406d 100644 --- a/plugins/woocommerce/patterns/product-collections-featured-collection.php +++ b/plugins/woocommerce/patterns/product-collections-featured-collection.php @@ -6,8 +6,6 @@ * Block Types: core/query/woocommerce/product-query */ -use Automattic\WooCommerce\Blocks\Patterns\PatternsHelper; - $collection_title = $content['titles'][0]['default'] ?? ''; ?> diff --git a/plugins/woocommerce/patterns/product-collections-featured-collections.php b/plugins/woocommerce/patterns/product-collections-featured-collections.php index ecaee30fd87..e51e44961d1 100644 --- a/plugins/woocommerce/patterns/product-collections-featured-collections.php +++ b/plugins/woocommerce/patterns/product-collections-featured-collections.php @@ -5,7 +5,7 @@ * Categories: WooCommerce */ -use Automattic\WooCommerce\Blocks\Patterns\PatternsHelper; +use Automattic\WooCommerce\Blocks\AIContent\PatternsHelper; $image1 = PatternsHelper::get_image_url( $images, 0, 'assets/images/pattern-placeholders/technology-white-camera-photography-vintage-photographer.png' ); $image2 = PatternsHelper::get_image_url( $images, 1, 'assets/images/pattern-placeholders/leather-guitar-typewriter-red-gadget-sofa.png' ); diff --git a/plugins/woocommerce/patterns/product-collections-newest-arrivals.php b/plugins/woocommerce/patterns/product-collections-newest-arrivals.php index 3af39dd4c3a..6606b5edce5 100644 --- a/plugins/woocommerce/patterns/product-collections-newest-arrivals.php +++ b/plugins/woocommerce/patterns/product-collections-newest-arrivals.php @@ -6,8 +6,6 @@ * Block Types: core/query/woocommerce/product-query */ -use Automattic\WooCommerce\Blocks\Patterns\PatternsHelper; - $first_title = $content['titles'][0]['default'] ?? ''; $first_button = $content['buttons'][0]['default'] ?? ''; ?> diff --git a/plugins/woocommerce/patterns/product-featured-2-columns.php b/plugins/woocommerce/patterns/product-featured-2-columns.php index 2b6b291516c..fad2036cd6c 100644 --- a/plugins/woocommerce/patterns/product-featured-2-columns.php +++ b/plugins/woocommerce/patterns/product-featured-2-columns.php @@ -4,7 +4,6 @@ * Slug: woocommerce-blocks/featured-products-2-cols * Categories: WooCommerce */ -use Automattic\WooCommerce\Blocks\Patterns\PatternsHelper; $first_title = $content['titles'][0]['default'] ?? ''; $first_description = $content['descriptions'][0]['default'] ?? ''; diff --git a/plugins/woocommerce/patterns/product-hero-2-col-2-row.php b/plugins/woocommerce/patterns/product-hero-2-col-2-row.php index 0379841cebc..af7307ff8b9 100644 --- a/plugins/woocommerce/patterns/product-hero-2-col-2-row.php +++ b/plugins/woocommerce/patterns/product-hero-2-col-2-row.php @@ -5,7 +5,7 @@ * Categories: WooCommerce */ -use Automattic\WooCommerce\Blocks\Patterns\PatternsHelper; +use Automattic\WooCommerce\Blocks\AIContent\PatternsHelper; $image1 = PatternsHelper::get_image_url( $images, 0, 'assets/images/pattern-placeholders/man-person-winter-photography-guy-statue.jpg' ); $image2 = PatternsHelper::get_image_url( $images, 1, 'assets/images/pattern-placeholders/pattern-fashion-clothing-outerwear-wool-scarf.png' ); diff --git a/plugins/woocommerce/patterns/shop-by-price.php b/plugins/woocommerce/patterns/shop-by-price.php index 3968595527a..ee3a7f31e86 100644 --- a/plugins/woocommerce/patterns/shop-by-price.php +++ b/plugins/woocommerce/patterns/shop-by-price.php @@ -5,8 +5,6 @@ * Categories: WooCommerce */ -use Automattic\WooCommerce\Blocks\Patterns\PatternsHelper; - $first_title = $content['titles'][0]['default'] ?? ''; $second_title = $content['titles'][1]['default'] ?? ''; $third_title = $content['titles'][2]['default'] ?? ''; diff --git a/plugins/woocommerce/patterns/small-discount-banner-with-image.php b/plugins/woocommerce/patterns/small-discount-banner-with-image.php index ac959253286..e0dfc1c9d25 100644 --- a/plugins/woocommerce/patterns/small-discount-banner-with-image.php +++ b/plugins/woocommerce/patterns/small-discount-banner-with-image.php @@ -5,7 +5,7 @@ * Categories: WooCommerce */ -use Automattic\WooCommerce\Blocks\Patterns\PatternsHelper; +use Automattic\WooCommerce\Blocks\AIContent\PatternsHelper; $banner_title = $content['titles'][0]['default'] ?? ''; ?> diff --git a/plugins/woocommerce/patterns/social-follow-us-in-social-media.php b/plugins/woocommerce/patterns/social-follow-us-in-social-media.php index f7c5b42a098..b2da6b03793 100644 --- a/plugins/woocommerce/patterns/social-follow-us-in-social-media.php +++ b/plugins/woocommerce/patterns/social-follow-us-in-social-media.php @@ -5,7 +5,7 @@ * Categories: WooCommerce */ -use Automattic\WooCommerce\Blocks\Patterns\PatternsHelper; +use Automattic\WooCommerce\Blocks\AIContent\PatternsHelper; $image1 = PatternsHelper::get_image_url( $images, 0, 'assets/images/pattern-placeholders/drinkware-liquid-tableware-dishware-bottle-fluid.jpg' ); $image2 = PatternsHelper::get_image_url( $images, 1, 'assets/images/pattern-placeholders/watch-hand-brand-jewellery-strap-platinum.jpg' ); diff --git a/plugins/woocommerce/patterns/store-info-alt-image-and-text.php b/plugins/woocommerce/patterns/store-info-alt-image-and-text.php index edcc7b26458..62c27ce641a 100644 --- a/plugins/woocommerce/patterns/store-info-alt-image-and-text.php +++ b/plugins/woocommerce/patterns/store-info-alt-image-and-text.php @@ -5,7 +5,7 @@ * Categories: WooCommerce */ -use Automattic\WooCommerce\Blocks\Patterns\PatternsHelper; +use Automattic\WooCommerce\Blocks\AIContent\PatternsHelper; $image1 = PatternsHelper::get_image_url( $images, 0, 'assets/images/pattern-placeholders/tea-leaf-meal-food-herb-produce.jpg' ); $image2 = PatternsHelper::get_image_url( $images, 1, 'assets/images/pattern-placeholders/drinkware-liquid-tableware-dishware-bottle-fluid.jpg' ); diff --git a/plugins/woocommerce/patterns/testimonials-3-columns.php b/plugins/woocommerce/patterns/testimonials-3-columns.php index 843f83c552d..caed496cf60 100644 --- a/plugins/woocommerce/patterns/testimonials-3-columns.php +++ b/plugins/woocommerce/patterns/testimonials-3-columns.php @@ -5,8 +5,6 @@ * Categories: WooCommerce */ -use Automattic\WooCommerce\Blocks\Patterns\PatternsHelper; - $main_header = $content['titles'][3]['default'] ?? ''; $first_review = $content['titles'][0]['default'] ?? ''; $second_review = $content['titles'][1]['default'] ?? ''; diff --git a/plugins/woocommerce/patterns/testimonials-single.php b/plugins/woocommerce/patterns/testimonials-single.php index f008d5cb6e3..2a02b866eb0 100644 --- a/plugins/woocommerce/patterns/testimonials-single.php +++ b/plugins/woocommerce/patterns/testimonials-single.php @@ -5,7 +5,7 @@ * Categories: WooCommerce */ -use Automattic\WooCommerce\Blocks\Patterns\PatternsHelper; +use Automattic\WooCommerce\Blocks\AIContent\PatternsHelper; $testimonials_title = $content['titles'][0]['default'] ?? ''; $description = $content['descriptions'][0]['default'] ?? ''; diff --git a/plugins/woocommerce/src/Blocks/AIContent/ContentProcessor.php b/plugins/woocommerce/src/Blocks/AIContent/ContentProcessor.php new file mode 100644 index 00000000000..999c90c5f87 --- /dev/null +++ b/plugins/woocommerce/src/Blocks/AIContent/ContentProcessor.php @@ -0,0 +1,95 @@ + $character_limit ) { + $prompt = sprintf( 'You are a professional writer. Read the following business description and write a text with less than %s characters to summarize the products the business is selling: "%s". Make sure you do not add double quotes in your response. Do not add any explanations in the response', $character_limit, $business_description ); + + $response = $ai_connection->fetch_ai_response( $token, $prompt, 30 ); + + $business_description = $response['completion'] ?? $business_description; + } + + return $business_description; + } + + /** + * Ensure that images are provided for assignment to products and patterns. + * + * @param array|WP_Error $images The array of images. + * @param Connection $ai_connection The AI connection. + * @param string $token The JWT token. + * @param string $business_description The business description. + * + * @return array|int|mixed|string|WP_Error + */ + public static function verify_images( $images, $ai_connection, $token, $business_description ) { + if ( ! is_wp_error( $images ) && ! empty( $images['images'] ) && ! empty( $images['search_term'] ) ) { + return $images; + } + + $images = ( new Pexels() )->get_images( $ai_connection, $token, $business_description ); + + if ( is_wp_error( $images ) ) { + return $images; + } + + if ( empty( $images['images'] ) || empty( $images['search_term'] ) ) { + return new WP_Error( 'images_not_found', __( 'No images provided for generating AI content.', 'woocommerce' ) ); + } + + return $images; + } + + /** + * Adjust the size of images for optimal performance on products and patterns. + * + * @param string $image_url The image URL. + * @param string $usage_type The usage type of the image. Either 'products' or 'patterns'. + * + * @return string + */ + public static function adjust_image_size( $image_url, $usage_type ) { + $parsed_url = wp_parse_url( $image_url ); + + if ( ! isset( $parsed_url['query'] ) ) { + return $image_url; + } + + $width = 'products' === $usage_type ? 250 : 500; + + parse_str( $parsed_url['query'], $query_params ); + + unset( $query_params['h'], $query_params['w'] ); + $query_params['w'] = $width; + $url = $parsed_url['scheme'] . '://' . $parsed_url['host'] . $parsed_url['path']; + + return add_query_arg( $query_params, $url ); + } +} diff --git a/plugins/woocommerce/src/Blocks/Patterns/PatternsHelper.php b/plugins/woocommerce/src/Blocks/AIContent/PatternsHelper.php similarity index 94% rename from plugins/woocommerce/src/Blocks/Patterns/PatternsHelper.php rename to plugins/woocommerce/src/Blocks/AIContent/PatternsHelper.php index 9a532210f5b..f50d61b7a7f 100644 --- a/plugins/woocommerce/src/Blocks/Patterns/PatternsHelper.php +++ b/plugins/woocommerce/src/Blocks/AIContent/PatternsHelper.php @@ -1,15 +1,15 @@ array(), - ); - } else { - return new \WP_Error( 'business_description_not_found', __( 'No business description provided for generating AI content.', 'woocommerce' ) ); - } - } - $dummy_products_to_update = $this->fetch_dummy_products_to_update(); if ( is_wp_error( $dummy_products_to_update ) ) { @@ -351,30 +330,6 @@ class ProductUpdater { return $product_image_id; } - /** - * Reduce the size of the image for the product to improve performance and - * avoid memory exhaustion errors when uploading them to the media library. - * - * @param string $image_url The image URL. - * - * @return string - */ - private function adjust_image_size_for_products( $image_url ) { - $parsed_url = wp_parse_url( $image_url ); - - if ( ! isset( $parsed_url['query'] ) ) { - return $image_url; - } - - parse_str( $parsed_url['query'], $query_params ); - - unset( $query_params['h'], $query_params['w'] ); - $query_params['w'] = 300; - $new_query_string = http_build_query( $query_params ); - - return $parsed_url['scheme'] . '://' . $parsed_url['host'] . $parsed_url['path'] . '?' . $new_query_string; - } - /** * Assigns the default content for the products. * @@ -390,7 +345,7 @@ class ProductUpdater { $image_src = $ai_selected_images[ $i ]['URL'] ?? ''; if ( wc_is_valid_url( $image_src ) ) { - $image_src = $this->adjust_image_size_for_products( $ai_selected_images[ $i ]['URL'] ); + $image_src = ContentProcessor::adjust_image_size( $image_src, 'products' ); } $image_alt = $ai_selected_images[ $i ]['title'] ?? ''; @@ -400,8 +355,8 @@ class ProductUpdater { 'description' => 'A product description', 'price' => 'The product price', 'image' => [ - 'src' => esc_url( $image_src ), - 'alt' => esc_attr( $image_alt ), + 'src' => $image_src, + 'alt' => $image_alt, ], 'product_id' => $dummy_products_to_update[ $i ]->get_id(), ]; @@ -422,8 +377,10 @@ class ProductUpdater { * @return array|int|string|\WP_Error */ public function assign_ai_generated_content_to_dummy_products( $ai_connection, $token, $products_information_list, $business_description, $search_term ) { - if ( empty( $business_description ) ) { - return new \WP_Error( 'missing_store_description', __( 'The store description is required to generate content for your site.', 'woocommerce' ) ); + $business_description = ContentProcessor::summarize_business_description( $business_description, $ai_connection, $token, 100 ); + + if ( is_wp_error( $business_description ) ) { + return $business_description; } $prompts = []; diff --git a/plugins/woocommerce/src/Blocks/Patterns/dictionary.json b/plugins/woocommerce/src/Blocks/AIContent/dictionary.json similarity index 100% rename from plugins/woocommerce/src/Blocks/Patterns/dictionary.json rename to plugins/woocommerce/src/Blocks/AIContent/dictionary.json diff --git a/plugins/woocommerce/src/Blocks/BlockPatterns.php b/plugins/woocommerce/src/Blocks/BlockPatterns.php index e01d30f54cd..294f33363e1 100644 --- a/plugins/woocommerce/src/Blocks/BlockPatterns.php +++ b/plugins/woocommerce/src/Blocks/BlockPatterns.php @@ -4,9 +4,9 @@ namespace Automattic\WooCommerce\Blocks; use Automattic\WooCommerce\Blocks\AI\Connection; use Automattic\WooCommerce\Blocks\Images\Pexels; use Automattic\WooCommerce\Blocks\Domain\Package; -use Automattic\WooCommerce\Blocks\Patterns\PatternsHelper; -use Automattic\WooCommerce\Blocks\Patterns\PatternUpdater; -use Automattic\WooCommerce\Blocks\Patterns\ProductUpdater; +use Automattic\WooCommerce\Blocks\AIContent\PatternsHelper; +use Automattic\WooCommerce\Blocks\AIContent\UpdatePatterns; +use Automattic\WooCommerce\Blocks\AIContent\UpdateProducts; /** * Registers patterns under the `./patterns/` directory and updates their content. @@ -366,13 +366,13 @@ class BlockPatterns { return $images->get_error_message(); } - $populate_patterns = ( new PatternUpdater() )->generate_content( $ai_connection, $token, $images, $business_description ); + $populate_patterns = ( new UpdatePatterns() )->generate_content( $ai_connection, $token, $images, $business_description ); if ( is_wp_error( $populate_patterns ) ) { return $populate_patterns->get_error_message(); } - $populate_products = ( new ProductUpdater() )->generate_content( $ai_connection, $token, $images, $business_description ); + $populate_products = ( new UpdateProducts() )->generate_content( $ai_connection, $token, $images, $business_description ); if ( is_wp_error( $populate_products ) ) { return $populate_products->get_error_message(); diff --git a/plugins/woocommerce/src/Blocks/Images/Pexels.php b/plugins/woocommerce/src/Blocks/Images/Pexels.php index b5a659df87f..5d18b713f5f 100644 --- a/plugins/woocommerce/src/Blocks/Images/Pexels.php +++ b/plugins/woocommerce/src/Blocks/Images/Pexels.php @@ -3,7 +3,8 @@ namespace Automattic\WooCommerce\Blocks\Images; use Automattic\WooCommerce\Blocks\AI\Connection; -use Automattic\WooCommerce\Blocks\Patterns\PatternUpdater; +use Automattic\WooCommerce\Blocks\AIContent\ContentProcessor; +use Automattic\WooCommerce\Blocks\AIContent\UpdatePatterns; /** * Pexels API client. @@ -27,6 +28,8 @@ class Pexels { * @return array|\WP_Error Array of images, or WP_Error if the request failed. */ public function get_images( $ai_connection, $token, $business_description ) { + $business_description = ContentProcessor::summarize_business_description( $business_description, $ai_connection, $token ); + if ( str_word_count( $business_description ) === 1 ) { $search_term = $business_description; } else { @@ -111,6 +114,7 @@ class Pexels { * @return mixed|\WP_Error */ private function define_search_term( $ai_connection, $token, $business_description ) { + $prompt = sprintf( 'You are a teacher. Based on the following business description, \'%s\', describe to a child exactly what this store is selling in one or two words and be as precise as you can possibly be. Do not reply with generic words that could cause confusion and be associated with other businesses as a response. Make sure you do not add double quotes in your response. Do not add any explanations in the response', $business_description ); $response = $ai_connection->fetch_ai_response( $token, $prompt, 30 ); @@ -119,6 +123,10 @@ class Pexels { return $response; } + if ( isset( $response['code'] ) && 'completion_error' === $response['code'] ) { + return new \WP_Error( 'search_term_definition_failed', __( 'The search term definition failed.', 'woocommerce' ) ); + } + if ( ! isset( $response['completion'] ) ) { return new \WP_Error( 'search_term_definition_failed', __( 'The search term definition failed.', 'woocommerce' ) ); } @@ -222,7 +230,7 @@ class Pexels { * @return array|\WP_Error The total number of required images, or WP_Error if the request failed. */ private function total_number_required_images() { - $patterns_dictionary = PatternUpdater::get_patterns_dictionary(); + $patterns_dictionary = UpdatePatterns::get_patterns_dictionary(); if ( is_wp_error( $patterns_dictionary ) ) { return $patterns_dictionary; diff --git a/plugins/woocommerce/src/StoreApi/Routes/V1/AI/Patterns.php b/plugins/woocommerce/src/StoreApi/Routes/V1/AI/Patterns.php index d97d8393644..5d54e1623e8 100644 --- a/plugins/woocommerce/src/StoreApi/Routes/V1/AI/Patterns.php +++ b/plugins/woocommerce/src/StoreApi/Routes/V1/AI/Patterns.php @@ -3,9 +3,10 @@ namespace Automattic\WooCommerce\StoreApi\Routes\V1\AI; use Automattic\WooCommerce\Blocks\AI\Connection; -use Automattic\WooCommerce\Blocks\Patterns\PatternsHelper; -use Automattic\WooCommerce\Blocks\Patterns\PatternUpdater; +use Automattic\WooCommerce\Blocks\AIContent\PatternsHelper; +use Automattic\WooCommerce\Blocks\AIContent\UpdatePatterns; use Automattic\WooCommerce\StoreApi\Routes\V1\AbstractRoute; +use WP_Error; /** * Patterns class. @@ -73,7 +74,7 @@ class Patterns extends AbstractRoute { * * @param \WP_REST_Request $request Request object. * - * @return bool|string|\WP_Error|\WP_REST_Response + * @return WP_Error|\WP_HTTP_Response|\WP_REST_Response */ protected function get_route_post_response( \WP_REST_Request $request ) { $business_description = sanitize_text_field( wp_unslash( $request['business_description'] ) ); @@ -91,9 +92,9 @@ class Patterns extends AbstractRoute { $images = $request['images']; try { - ( new PatternUpdater() )->generate_content( $ai_connection, $token, $images, $business_description ); + ( new UpdatePatterns() )->generate_content( $ai_connection, $token, $images, $business_description ); return rest_ensure_response( array( 'ai_content_generated' => true ) ); - } catch ( \WP_Error $e ) { + } catch ( WP_Error $e ) { return $this->error_to_response( $e ); } } @@ -103,7 +104,7 @@ class Patterns extends AbstractRoute { * * @param \WP_REST_Request $request Request object. * - * @return bool|string|\WP_Error|\WP_REST_Response + * @return bool|string|WP_Error|\WP_REST_Response */ protected function get_route_delete_response( \WP_REST_Request $request ) { PatternsHelper::delete_patterns_ai_data_post(); diff --git a/plugins/woocommerce/src/StoreApi/Routes/V1/AI/Product.php b/plugins/woocommerce/src/StoreApi/Routes/V1/AI/Product.php index ec062f215d7..fa6b1807972 100644 --- a/plugins/woocommerce/src/StoreApi/Routes/V1/AI/Product.php +++ b/plugins/woocommerce/src/StoreApi/Routes/V1/AI/Product.php @@ -2,7 +2,7 @@ namespace Automattic\WooCommerce\StoreApi\Routes\V1\AI; -use Automattic\WooCommerce\Blocks\Patterns\ProductUpdater; +use Automattic\WooCommerce\Blocks\AIContent\UpdateProducts; use Automattic\WooCommerce\StoreApi\Routes\V1\AbstractRoute; /** @@ -69,7 +69,7 @@ class Product extends AbstractRoute { * @return bool|string|\WP_Error|\WP_REST_Response */ protected function get_route_post_response( \WP_REST_Request $request ) { - $product_updater = new ProductUpdater(); + $product_updater = new UpdateProducts(); $product_information = $request['products_information'] ?? array(); if ( empty( $product_information ) ) { diff --git a/plugins/woocommerce/src/StoreApi/Routes/V1/AI/Products.php b/plugins/woocommerce/src/StoreApi/Routes/V1/AI/Products.php index 41848b8774d..7acb735fda6 100644 --- a/plugins/woocommerce/src/StoreApi/Routes/V1/AI/Products.php +++ b/plugins/woocommerce/src/StoreApi/Routes/V1/AI/Products.php @@ -3,7 +3,7 @@ namespace Automattic\WooCommerce\StoreApi\Routes\V1\AI; use Automattic\WooCommerce\Blocks\AI\Connection; -use Automattic\WooCommerce\Blocks\Patterns\ProductUpdater; +use Automattic\WooCommerce\Blocks\AIContent\UpdateProducts; use Automattic\WooCommerce\StoreApi\Routes\V1\AbstractRoute; /** @@ -110,7 +110,7 @@ class Products extends AbstractRoute { $images = $request['images']; - $populate_products = ( new ProductUpdater() )->generate_content( $ai_connection, $token, $images, $business_description ); + $populate_products = ( new UpdateProducts() )->generate_content( $ai_connection, $token, $images, $business_description ); if ( is_wp_error( $populate_products ) ) { return $this->error_to_response( $populate_products ); @@ -138,7 +138,7 @@ class Products extends AbstractRoute { * @return bool|string|\WP_Error|\WP_REST_Response */ protected function get_route_delete_response( \WP_REST_Request $request ) { - ( new ProductUpdater() )->reset_products_content(); + ( new UpdateProducts() )->reset_products_content(); return rest_ensure_response( array( 'removed' => true ) ); } } diff --git a/plugins/woocommerce/src/StoreApi/Routes/V1/AI/StoreInfo.php b/plugins/woocommerce/src/StoreApi/Routes/V1/AI/StoreInfo.php index 27c66476d95..2dc358f477b 100644 --- a/plugins/woocommerce/src/StoreApi/Routes/V1/AI/StoreInfo.php +++ b/plugins/woocommerce/src/StoreApi/Routes/V1/AI/StoreInfo.php @@ -2,8 +2,8 @@ namespace Automattic\WooCommerce\StoreApi\Routes\V1\AI; -use Automattic\WooCommerce\Blocks\Patterns\PatternsHelper; -use Automattic\WooCommerce\Blocks\Patterns\ProductUpdater; +use Automattic\WooCommerce\Blocks\AIContent\PatternsHelper; +use Automattic\WooCommerce\Blocks\AIContent\UpdateProducts; use Automattic\WooCommerce\StoreApi\Routes\V1\AbstractRoute; /** @@ -60,7 +60,7 @@ class StoreInfo extends AbstractRoute { * @return bool|string|\WP_Error|\WP_REST_Response */ protected function get_route_response( \WP_REST_Request $request ) { - $product_updater = new ProductUpdater(); + $product_updater = new UpdateProducts(); $patterns = PatternsHelper::get_patterns_ai_data_post(); $products = $product_updater->fetch_product_ids( 'dummy' ); diff --git a/plugins/woocommerce/src/StoreApi/Routes/V1/AI/StoreTitle.php b/plugins/woocommerce/src/StoreApi/Routes/V1/AI/StoreTitle.php index 147b51e1c9f..4c1648c3f47 100644 --- a/plugins/woocommerce/src/StoreApi/Routes/V1/AI/StoreTitle.php +++ b/plugins/woocommerce/src/StoreApi/Routes/V1/AI/StoreTitle.php @@ -91,8 +91,10 @@ class StoreTitle extends AbstractRoute { ); } - $store_title = get_option( 'blogname' ); - if ( ! ( empty( $store_title ) || self::DEFAULT_TITLE === $store_title ) ) { + $store_title = get_option( 'blogname' ); + $previous_ai_generated_title = get_option( 'ai_generated_site_title' ); + + if ( self::DEFAULT_TITLE === $store_title || ( ! empty( $store_title ) && $previous_ai_generated_title !== $store_title ) ) { return rest_ensure_response( array( 'ai_content_generated' => false ) ); } @@ -101,6 +103,7 @@ class StoreTitle extends AbstractRoute { return $this->error_to_response( $ai_generated_title ); } + update_option( 'ai_generated_site_title', $ai_generated_title ); update_option( self::STORE_TITLE_OPTION_NAME, $ai_generated_title ); return rest_ensure_response(