diff --git a/.gitignore b/.gitignore index 0390bec..e9010ec 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ vendor/ .idea/ node_modules/ +.vscode/ diff --git a/bootstrap.php b/bootstrap.php index 5a95401..a85a724 100644 --- a/bootstrap.php +++ b/bootstrap.php @@ -17,10 +17,13 @@ function () { if ( ! defined( 'NFD_AI_SERVICE_BASE' ) ) { define( 'NFD_AI_SERVICE_BASE', 'https://hiive.cloud/workers/ai-proxy/v1/' ); + define( 'NFD_AI_BASE', 'https://hiive.cloud/workers/ai-proxy/' ); + define( 'NFD_PATTERNS_BASE', 'https://patterns.hiive.cloud/' ); + define( 'NFD_SITEGEN_OPTION', 'nfd-ai-site-gen' ); } register( - [ + array( 'name' => 'ai', 'label' => __( 'ai', 'newfold-ai-module' ), 'callback' => function ( Container $container ) { @@ -28,9 +31,8 @@ function () { }, 'isActive' => true, 'isHidden' => true, - ] + ) ); - } ); diff --git a/composer.json b/composer.json index f3021b9..4a1d38e 100644 --- a/composer.json +++ b/composer.json @@ -22,7 +22,7 @@ "newfold-labs/wp-module-data": "^2.3.1" }, "require-dev": { - "newfold-labs/wp-php-standards": "@stable" + "newfold-labs/wp-php-standards": "^1.2" }, "autoload": { "psr-4": { diff --git a/composer.lock b/composer.lock index 94fcd85..bed0e09 100644 --- a/composer.lock +++ b/composer.lock @@ -4,24 +4,23 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "4e587178cd800b53c803cbe78539d2d2", + "content-hash": "e0a92498da822db25c9596e13a6ef4f6", "packages": [ { "name": "newfold-labs/wp-module-data", - "version": "2.3.1", + "version": "2.4.11", "source": { "type": "git", "url": "https://github.com/newfold-labs/wp-module-data.git", - "reference": "bbbe8cee60cafee87206fc586c39b7b6238b5ed2" + "reference": "c244dd52e7e07bf0d890e51892e179c62f197bac" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/newfold-labs/wp-module-data/zipball/bbbe8cee60cafee87206fc586c39b7b6238b5ed2", - "reference": "bbbe8cee60cafee87206fc586c39b7b6238b5ed2", + "url": "https://api.github.com/repos/newfold-labs/wp-module-data/zipball/c244dd52e7e07bf0d890e51892e179c62f197bac", + "reference": "c244dd52e7e07bf0d890e51892e179c62f197bac", "shasum": "" }, "require": { - "wp-forge/container": "^2.0", "wp-forge/wp-query-builder": "^1.0", "wp-forge/wp-upgrade-handler": "^1.0", "wpscholar/url": "^1.2" @@ -32,7 +31,7 @@ "type": "library", "autoload": { "psr-4": { - "NewfoldLabs\\WP\\Module\\Data\\": "src/" + "NewfoldLabs\\WP\\Module\\Data\\": "includes/" }, "files": [ "bootstrap.php" @@ -51,99 +50,10 @@ ], "description": "Newfold Data Module", "support": { - "source": "https://github.com/newfold-labs/wp-module-data/tree/2.3.1", + "source": "https://github.com/newfold-labs/wp-module-data/tree/2.4.11", "issues": "https://github.com/newfold-labs/wp-module-data/issues" }, - "time": "2023-04-29T19:38:59+00:00" - }, - { - "name": "psr/container", - "version": "1.1.2", - "source": { - "type": "git", - "url": "https://github.com/php-fig/container.git", - "reference": "513e0666f7216c7459170d56df27dfcefe1689ea" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/513e0666f7216c7459170d56df27dfcefe1689ea", - "reference": "513e0666f7216c7459170d56df27dfcefe1689ea", - "shasum": "" - }, - "require": { - "php": ">=7.4.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Psr\\Container\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common Container Interface (PHP FIG PSR-11)", - "homepage": "https://github.com/php-fig/container", - "keywords": [ - "PSR-11", - "container", - "container-interface", - "container-interop", - "psr" - ], - "support": { - "issues": "https://github.com/php-fig/container/issues", - "source": "https://github.com/php-fig/container/tree/1.1.2" - }, - "time": "2021-11-05T16:50:12+00:00" - }, - { - "name": "wp-forge/container", - "version": "2.0", - "source": { - "type": "git", - "url": "https://github.com/wp-forge/container.git", - "reference": "a4f48079eff2d7e3f31acb09d199d1c1e39de74a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/wp-forge/container/zipball/a4f48079eff2d7e3f31acb09d199d1c1e39de74a", - "reference": "a4f48079eff2d7e3f31acb09d199d1c1e39de74a", - "shasum": "" - }, - "require": { - "php": ">=7.0", - "psr/container": "^1.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "WP_Forge\\Container\\": "includes" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "GPL-2.0-or-later" - ], - "authors": [ - { - "name": "Micah Wood", - "email": "micah@wpscholar.com" - } - ], - "description": "A lightweight, PHP 7.0+ compatible, PSR-11 dependency injection container.", - "support": { - "issues": "https://github.com/wp-forge/container/issues", - "source": "https://github.com/wp-forge/container/tree/2.0" - }, - "time": "2022-08-10T20:22:58+00:00" + "time": "2023-11-13T19:54:44+00:00" }, { "name": "wp-forge/wp-query-builder", @@ -556,6 +466,142 @@ }, "time": "2022-10-24T09:00:36+00:00" }, + { + "name": "phpcsstandards/phpcsextra", + "version": "1.1.2", + "source": { + "type": "git", + "url": "https://github.com/PHPCSStandards/PHPCSExtra.git", + "reference": "746c3190ba8eb2f212087c947ba75f4f5b9a58d5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHPCSStandards/PHPCSExtra/zipball/746c3190ba8eb2f212087c947ba75f4f5b9a58d5", + "reference": "746c3190ba8eb2f212087c947ba75f4f5b9a58d5", + "shasum": "" + }, + "require": { + "php": ">=5.4", + "phpcsstandards/phpcsutils": "^1.0.8", + "squizlabs/php_codesniffer": "^3.7.1" + }, + "require-dev": { + "php-parallel-lint/php-console-highlighter": "^1.0", + "php-parallel-lint/php-parallel-lint": "^1.3.2", + "phpcsstandards/phpcsdevcs": "^1.1.6", + "phpcsstandards/phpcsdevtools": "^1.2.1", + "phpunit/phpunit": "^4.5 || ^5.0 || ^6.0 || ^7.0" + }, + "type": "phpcodesniffer-standard", + "extra": { + "branch-alias": { + "dev-stable": "1.x-dev", + "dev-develop": "1.x-dev" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-3.0-or-later" + ], + "authors": [ + { + "name": "Juliette Reinders Folmer", + "homepage": "https://github.com/jrfnl", + "role": "lead" + }, + { + "name": "Contributors", + "homepage": "https://github.com/PHPCSStandards/PHPCSExtra/graphs/contributors" + } + ], + "description": "A collection of sniffs and standards for use with PHP_CodeSniffer.", + "keywords": [ + "PHP_CodeSniffer", + "phpcbf", + "phpcodesniffer-standard", + "phpcs", + "standards", + "static analysis" + ], + "support": { + "issues": "https://github.com/PHPCSStandards/PHPCSExtra/issues", + "source": "https://github.com/PHPCSStandards/PHPCSExtra" + }, + "time": "2023-09-20T22:06:18+00:00" + }, + { + "name": "phpcsstandards/phpcsutils", + "version": "1.0.8", + "source": { + "type": "git", + "url": "https://github.com/PHPCSStandards/PHPCSUtils.git", + "reference": "69465cab9d12454e5e7767b9041af0cd8cd13be7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHPCSStandards/PHPCSUtils/zipball/69465cab9d12454e5e7767b9041af0cd8cd13be7", + "reference": "69465cab9d12454e5e7767b9041af0cd8cd13be7", + "shasum": "" + }, + "require": { + "dealerdirect/phpcodesniffer-composer-installer": "^0.4.1 || ^0.5 || ^0.6.2 || ^0.7 || ^1.0", + "php": ">=5.4", + "squizlabs/php_codesniffer": "^3.7.1 || 4.0.x-dev@dev" + }, + "require-dev": { + "ext-filter": "*", + "php-parallel-lint/php-console-highlighter": "^1.0", + "php-parallel-lint/php-parallel-lint": "^1.3.2", + "phpcsstandards/phpcsdevcs": "^1.1.6", + "yoast/phpunit-polyfills": "^1.0.5 || ^2.0.0" + }, + "type": "phpcodesniffer-standard", + "extra": { + "branch-alias": { + "dev-stable": "1.x-dev", + "dev-develop": "1.x-dev" + } + }, + "autoload": { + "classmap": [ + "PHPCSUtils/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-3.0-or-later" + ], + "authors": [ + { + "name": "Juliette Reinders Folmer", + "homepage": "https://github.com/jrfnl", + "role": "lead" + }, + { + "name": "Contributors", + "homepage": "https://github.com/PHPCSStandards/PHPCSUtils/graphs/contributors" + } + ], + "description": "A suite of utility functions for use with PHP_CodeSniffer", + "homepage": "https://phpcsutils.com/", + "keywords": [ + "PHP_CodeSniffer", + "phpcbf", + "phpcodesniffer-standard", + "phpcs", + "phpcs3", + "standards", + "static analysis", + "tokens", + "utility" + ], + "support": { + "docs": "https://phpcsutils.com/", + "issues": "https://github.com/PHPCSStandards/PHPCSUtils/issues", + "source": "https://github.com/PHPCSStandards/PHPCSUtils" + }, + "time": "2023-07-16T21:39:41+00:00" + }, { "name": "squizlabs/php_codesniffer", "version": "3.7.2", @@ -615,30 +661,38 @@ }, { "name": "wp-coding-standards/wpcs", - "version": "2.3.0", + "version": "3.0.1", "source": { "type": "git", "url": "https://github.com/WordPress/WordPress-Coding-Standards.git", - "reference": "7da1894633f168fe244afc6de00d141f27517b62" + "reference": "b4caf9689f1a0e4a4c632679a44e638c1c67aff1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/WordPress/WordPress-Coding-Standards/zipball/7da1894633f168fe244afc6de00d141f27517b62", - "reference": "7da1894633f168fe244afc6de00d141f27517b62", + "url": "https://api.github.com/repos/WordPress/WordPress-Coding-Standards/zipball/b4caf9689f1a0e4a4c632679a44e638c1c67aff1", + "reference": "b4caf9689f1a0e4a4c632679a44e638c1c67aff1", "shasum": "" }, "require": { + "ext-filter": "*", + "ext-libxml": "*", + "ext-tokenizer": "*", + "ext-xmlreader": "*", "php": ">=5.4", - "squizlabs/php_codesniffer": "^3.3.1" + "phpcsstandards/phpcsextra": "^1.1.0", + "phpcsstandards/phpcsutils": "^1.0.8", + "squizlabs/php_codesniffer": "^3.7.2" }, "require-dev": { - "dealerdirect/phpcodesniffer-composer-installer": "^0.5 || ^0.6", + "php-parallel-lint/php-console-highlighter": "^1.0.0", + "php-parallel-lint/php-parallel-lint": "^1.3.2", "phpcompatibility/php-compatibility": "^9.0", - "phpcsstandards/phpcsdevtools": "^1.0", + "phpcsstandards/phpcsdevtools": "^1.2.0", "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0" }, "suggest": { - "dealerdirect/phpcodesniffer-composer-installer": "^0.6 || This Composer plugin will sort out the PHPCS 'installed_paths' automatically." + "ext-iconv": "For improved results", + "ext-mbstring": "For improved results" }, "type": "phpcodesniffer-standard", "notification-url": "https://packagist.org/downloads/", @@ -655,6 +709,7 @@ "keywords": [ "phpcs", "standards", + "static analysis", "wordpress" ], "support": { @@ -662,14 +717,18 @@ "source": "https://github.com/WordPress/WordPress-Coding-Standards", "wiki": "https://github.com/WordPress/WordPress-Coding-Standards/wiki" }, - "time": "2020-05-13T23:57:56+00:00" + "funding": [ + { + "url": "https://opencollective.com/thewpcc/contribute/wp-php-63406", + "type": "custom" + } + ], + "time": "2023-09-14T07:06:09+00:00" } ], "aliases": [], "minimum-stability": "stable", - "stability-flags": { - "newfold-labs/wp-php-standards": 0 - }, + "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, "platform": [], diff --git a/includes/RestApi/AISearchController.php b/includes/RestApi/AISearchController.php index 0409534..4120b99 100644 --- a/includes/RestApi/AISearchController.php +++ b/includes/RestApi/AISearchController.php @@ -2,6 +2,7 @@ namespace NewfoldLabs\WP\Module\AI\RestApi; +use NewfoldLabs\WP\Module\AI\SiteGen\SiteGen; use NewfoldLabs\WP\Module\AI\Utils\AISearchUtil; use NewfoldLabs\WP\Module\Data\HiiveConnection; @@ -59,11 +60,92 @@ public function register_routes() { array( array( 'methods' => \WP_REST_Server::CREATABLE, - 'callback' => array($this, 'get_default_search_results'), - 'permission_callback' => array($this, 'check_permission'), + 'callback' => array( $this, 'get_default_search_results' ), + 'permission_callback' => array( $this, 'check_permission' ), ), ) ); + + register_rest_route( + $this->namespace, + '/' . $this->rest_base . '/sitegen', + array( + array( + 'methods' => \WP_REST_Server::CREATABLE, + 'callback' => array( $this, 'sitegen' ), + 'args' => array( + 'site_info' => array( + 'required' => true, + 'type' => 'object', + ), + 'identifier' => array( + 'required' => true, + 'type' => 'string', + ), + ), + 'permission_callback' => array( $this, 'check_permission' ), + ), + ) + ); + + register_rest_route( + $this->namespace, + '/' . $this->rest_base . '/homepages', + array( + array( + 'methods' => \WP_REST_Server::CREATABLE, + 'callback' => array( $this, 'homepages' ), + 'args' => array( + 'site_description' => array( + 'required' => true, + 'type' => 'string', + ), + 'content_style' => array( + 'required' => true, + 'type' => 'object', + ), + 'target_audience' => array( + 'required' => true, + 'type' => 'object', + ), + ), + 'permission_callback' => array( $this, 'check_permission' ), + ), + ) + ); + } + + /** + * Proxy to the AI service to get the responses. + * + * @param \WP_REST_Request $request Request object + * + * @returns \WP_REST_Response|\WP_Error + */ + public function sitegen( \WP_REST_Request $request ) { + $site_info = $request['site_info']; + $identifier = $request['identifier']; + + $response = SiteGen::generate_site_meta( $site_info, $identifier ); + + return new \WP_REST_Response( $response, 200 ); + } + + /** + * Proxy to the AI service to get the responses. + * + * @param \WP_REST_Request $request Request object + * + * @returns \WP_REST_Response|\WP_Error + */ + public function homepages( \WP_REST_Request $request ) { + $site_description = $request['site_description']; + $content_style = $request['content_style']; + $target_audience = $request['target_audience']; + + $response = SiteGen::get_home_pages( $site_description, $content_style, $target_audience ); + + return new \WP_REST_Response( $response, 200 ); } /** @@ -130,7 +212,7 @@ public function get_default_search_results( \WP_REST_Request $request ) { * @return \WP_Error */ public function check_permission() { - if ( ! current_user_can('read') ) { + if ( ! current_user_can( 'read' ) ) { return new \WP_Error( 'rest_forbidden', __( 'You must be authenticated to make this call' ), diff --git a/includes/SiteGen/SiteGen.php b/includes/SiteGen/SiteGen.php new file mode 100644 index 0000000..37798ae --- /dev/null +++ b/includes/SiteGen/SiteGen.php @@ -0,0 +1,361 @@ + array( + 'site_description', + ), + 'targetaudience' => array( + 'site_description', + ), + 'contenttones' => array( + 'site_description', + ), + 'contentstructure' => array( + 'site_description', + ), + 'colorpalette' => array( + 'site_description', + ), + 'sitemap' => array( + 'site_description', + ), + 'pluginrecommendation' => array( + 'site_description', + ), + 'fontpair' => array( + 'site_description', + ), + 'keywords' => array( + 'site_description', + 'content_style', + ), + ); + + /** + * Function to check capabilities + */ + private static function check_capabilities() { + $capability = new SiteCapabilities(); + + $ai_enabled = $capability->get( 'canAccessAI' ); + + return $ai_enabled; + } + + /** + * Function to validate site info + * + * @param array $site_info The main input for forming the prompt + * @param string $identifier The identifier to be used for generating the required meta + */ + private static function validate_site_info( $site_info, $identifier ) { + if ( array_key_exists( $identifier, self::$required_validations ) ) { + $validations = self::$required_validations[ $identifier ]; + foreach ( $validations as $required_key ) { + if ( ! array_key_exists( $required_key, $site_info ) ) { + return false; + } + } + } + return true; + } + + /** + * Function to get the site gen response from cache based on the identifier + * + * @param string $identifier The identifier to be used for generating the required meta + */ + private static function get_sitegen_from_cache( $identifier ) { + $site_gen = get_option( NFD_SITEGEN_OPTION, null ); + if ( ! $site_gen ) { + update_option( NFD_SITEGEN_OPTION, array() ); + } + if ( $site_gen && array_key_exists( $identifier, $site_gen ) ) { + return $site_gen[ $identifier ]; + } + return null; + } + + /** + * Function to cache the response from sitegen API + * + * @param string $identifier The identifier to be used for generating the required meta + * @param array $response The response from the sitegen API. + */ + private static function cache_sitegen_response( $identifier, $response ) { + $site_gen = get_option( NFD_SITEGEN_OPTION, array() ); + $site_gen[ $identifier ] = $response; + update_option( NFD_SITEGEN_OPTION, $site_gen ); + } + + /** + * Function to generate the prompt from the JSON input. + * + * @param array $site_info The JSON input for the sitegen call. + */ + private static function get_prompt_from_info( $site_info ) { + $prompt = ''; + foreach ( $site_info as $key => $value ) { + $prompt = $prompt . $key . ': ' . $value . ', '; + } + return $prompt; + } + + /** + * Get the patterns for a particular category. + * + * @param string $category The category to get patterns for. + */ + private static function get_patterns_for_category( $category ) { + $response = wp_remote_get( + NFD_PATTERNS_BASE . 'patterns?category=' . $category, + array( + 'headers' => array( + 'Content-Type' => 'application/json', + ), + 'timeout' => 60, + ) + ); + + if ( wp_remote_retrieve_response_code( $response ) !== 200 ) { + return array( + 'error' => __( 'We are unable to process the request at this moment' ), + ); + } + + $patterns = json_decode( wp_remote_retrieve_body( $response ), true ); + $processed_patterns = array(); + + foreach ( $patterns['data'] as $pattern ) { + $processed_patterns[ $pattern['slug'] ] = $pattern; + } + + return $processed_patterns; + } + + /** + * Function to generate all possible patterns for the current generation. + * + * @param string $site_description The site description (the user prompt) + * @param array $content_style The generated content style. + * @param array $target_audience The generated target audience. + * @param array $content_structure The content structures generated / cached + * @param boolean $skip_cache If we need to skip cache. + */ + private static function generate_pattern_content( + $site_description, + $content_style, + $target_audience, + $content_structure, + $skip_cache = false + ) { + if ( ! $skip_cache ) { + $generated_patterns = self::get_sitegen_from_cache( 'contentRegenerate' ); + if ( $generated_patterns ) { + return $generated_patterns; + } + } + + $keywords = self::generate_site_meta( + array( + 'site_description' => $site_description, + 'content_style' => $content_style, + ), + 'keywords' + ); + + $unique_categories = array(); + foreach ( $content_structure as $homepage => $structure ) { + foreach ( $structure as $category ) { + if ( ! in_array( $category, $unique_categories, true ) ) { + array_push( $unique_categories, $category ); + } + } + } + + $category_pattern_map = array(); + + // Generate patterns randomly for the unique categories + foreach ( $unique_categories as $category ) { + $patterns_for_category = self::get_patterns_for_category( $category ); + if ( count( $patterns_for_category ) <= 5 ) { + $random_selected_patterns = array_rand( $patterns_for_category, count( $patterns_for_category ) ); + } else { + $random_selected_patterns = array_rand( $patterns_for_category, 5 ); + } + + $category_pattern_map[ $category ] = array(); + foreach ( $random_selected_patterns as $pattern_slug ) { + $pattern = $patterns_for_category[ $pattern_slug ]; + // Generate content for these patterns + $response = wp_remote_post( + NFD_AI_BASE . 'generateSiteMeta', + array( + 'headers' => array( + 'Content-Type' => 'application/json', + ), + 'timeout' => 60, + 'body' => wp_json_encode( + array( + 'hiivetoken' => HiiveConnection::get_auth_token(), + 'prompt' => array( + 'pattern' => $pattern['content'], + 'prompt' => self::get_prompt_from_info( + array( + 'site_description' => $site_description, + 'keywords' => wp_json_encode( $keywords ), + 'content_style' => wp_json_encode( $content_style ), + 'target_audience' => wp_json_encode( $target_audience ), + ) + ), + ), + 'identifier' => 'contentRegenerate', + ) + ), + ) + ); + + $parsed_response = json_decode( wp_remote_retrieve_body( $response ), true ); + $generated_pattern = $parsed_response['content']; + array_push( $category_pattern_map[ $category ], $generated_pattern ); + } + } + + // Store the categories + self::cache_sitegen_response( 'contentRegenerate', $category_pattern_map ); + + return $category_pattern_map; + } + + /** + * Function to generate the site meta according to the arguments passed + * + * @param array $site_info The Site Info object, will be validated for required params. + * @param string $identifier The identifier for generating the site meta + * @param boolean $skip_cache To skip returning the response from cache + */ + public static function generate_site_meta( $site_info, $identifier, $skip_cache = false ) { + if ( ! self::check_capabilities() ) { + return array( + 'error' => __( 'You do not have the permissions to perform this action' ), + ); + } + + if ( ! self::validate_site_info( $site_info, $identifier ) ) { + return array( + 'error' => __( 'Required values not provided' ), + ); + } + + if ( ! $skip_cache ) { + $site_gen_cached = self::get_sitegen_from_cache( $identifier ); + if ( $site_gen_cached ) { + return $site_gen_cached; + } + } + + $response = wp_remote_post( + NFD_AI_BASE . 'generateSiteMeta', + array( + 'headers' => array( + 'Content-Type' => 'application/json', + ), + 'timeout' => 60, + 'body' => wp_json_encode( + array( + 'hiivetoken' => HiiveConnection::get_auth_token(), + 'prompt' => self::get_prompt_from_info( $site_info ), + 'identifier' => $identifier, + ) + ), + ) + ); + + $response_code = wp_remote_retrieve_response_code( $response ); + if ( 200 !== $response_code ) { + if ( 400 === $response_code ) { + $error = json_decode( wp_remote_retrieve_body( $response ), true ); + return array( + 'error' => $error['payload']['reason'], + ); + } + return array( + 'error' => __( 'We are unable to process the request at this moment' ), + ); + } + + $parsed_response = json_decode( wp_remote_retrieve_body( $response ), true ); + + self::cache_sitegen_response( $identifier, $parsed_response ); + + try { + return $parsed_response; + } catch ( \Exception $exception ) { + return array( + 'error' => __( 'We are unable to process the request at this moment' ), + ); + } + } + + /** + * Function to get the home page patterns. Randomly generates the patterns and substitutes with existing content. + * Set regenerate to get new combinations + * + * @param string $site_description The site description (user prompt). + * @param array $content_style Generated from sitegen. + * @param array $target_audience Generated target audience. + * @param boolean $regenerate If we need to regenerate. + */ + public static function get_home_pages( $site_description, $content_style, $target_audience, $regenerate = true ) { + $generated_content_structures = self::generate_site_meta( + array( 'site_description' => $site_description ), + 'contentstructure' + ); + // Check if we have the response in cache already + if ( ! $regenerate ) { + $generated_homepages = self::get_sitegen_from_cache( 'homepages' ); + if ( $generated_homepages ) { + return $generated_homepages; + } + } + $random_homepages = array_rand( $generated_content_structures, 3 ); + $generated_homepages = array(); + $generated_patterns = self::generate_pattern_content( + $site_description, + $content_style, + $target_audience, + $generated_content_structures + ); + + // Choose random categories for the generated patterns and return + foreach ( $random_homepages as $slug ) { + $generated_homepages[ $slug ] = array(); + foreach ( $generated_content_structures[ $slug ] as $pattern_category ) { + if ( ! $generated_patterns[ $pattern_category ] ) { + continue; + } + // Get a random pattern for the category. + $random_pattern = array_rand( $generated_patterns[ $pattern_category ] ); + $random_pattern = $generated_patterns[ $random_pattern ]; + array_push( $generated_homepages[ $slug ], $random_pattern ); + } + } + + self::cache_sitegen_response( 'homepages', $generated_homepages ); + return $generated_homepages; + } +}