Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 77
0.00% covered (danger)
0.00%
0 / 8
CRAP
0.00% covered (danger)
0.00%
0 / 1
SitekitsContentGeneration
0.00% covered (danger)
0.00%
0 / 77
0.00% covered (danger)
0.00%
0 / 8
342
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
 generate_sitekits
0.00% covered (danger)
0.00%
0 / 31
0.00% covered (danger)
0.00%
0 / 1
42
 get_sitekit_object
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 1
2
 process_sitekit_item
0.00% covered (danger)
0.00%
0 / 14
0.00% covered (danger)
0.00%
0 / 1
6
 get_page_content_from_patterns
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
6
 install_pre_requisites_in_background
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
6
 publish_content
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
12
 site_type_supported
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3namespace NewfoldLabs\WP\Module\Onboarding\Services\Ai\ContentGeneration;
4
5use NewfoldLabs\WP\Module\Onboarding\RestApi\ParallelRequestsController;
6use NewfoldLabs\WP\Module\Onboarding\Services\ParallelRequestsService;
7use NewfoldLabs\WP\Module\Onboarding\Services\SiteGenService;
8use NewfoldLabs\WP\Module\Onboarding\Services\SiteTypes\EcommerceSiteTypeService;
9use NewfoldLabs\WP\Module\Onboarding\Types\Page;
10use NewfoldLabs\WP\Module\Onboarding\Types\Pages;
11use NewfoldLabs\WP\Module\Onboarding\Types\ParallelRequest;
12use NewfoldLabs\WP\Module\Onboarding\Types\SiteClassification;
13use NewfoldLabs\WP\Module\Onboarding\Types\Sitekit;
14use WpOrg\Requests\Requests;
15
16class SitekitsContentGeneration {
17
18    private static $site_types_supported = [
19        'ecommerce',
20    ];
21
22    /**
23     * The site type.
24     *
25     * @var string
26     */
27    private $site_type;
28
29    /**
30     * The locale.
31     *
32     * @var string
33     */
34    private $locale;
35
36    /**
37     * The prompt.
38     *
39     * @var ContentGenerationPrompt
40     */
41    private $prompt;
42
43    /**
44     * The site classification.
45     *
46     * @var SiteClassification
47     */
48    private $site_classification;
49
50    /**
51     * Constructor.
52     *
53     * @param string $site_type The site type.
54     * @param string $locale The locale.
55     * @param ContentGenerationPrompt $prompt The prompt.
56     * @param SiteClassification $site_classification The site classification.
57     */
58    public function __construct( string $site_type, string $locale, ContentGenerationPrompt $prompt, SiteClassification $site_classification ) {
59        $this->site_type           = $site_type;
60        $this->locale              = $locale;
61        $this->prompt              = $prompt;
62        $this->site_classification = $site_classification;
63    }
64
65    /**
66     * Generates the sitekits.
67     *
68     * @param int $count The number of sitekits to generate.
69     * @return array|\WP_Error The sitekits - array of Sitekit objects or WP_Error on failure.
70     */
71    public function generate_sitekits( int $count = 3 ) {
72        $prompt = $this->prompt->get_prompt();
73        $request_body = array(
74            'siteType'      => $this->site_type,
75            'count'         => $count,
76            'prompt'        => $prompt,
77            'locale'        => $this->locale,
78            'primaryType'   => $this->site_classification->get_primary_type(),
79            'secondaryType' => $this->site_classification->get_secondary_type(),
80        );
81
82        // Install sitekits pre-requisites plugins in background.
83        $this->install_pre_requisites_in_background();
84
85        // Generate sitekits.
86        $request = new ContentGenerationServiceRequest( 'sitekits/generate', $request_body );
87        $request->send();
88        // Success.
89        if (
90            $request->is_successful() &&
91            isset( $request->get_response_body()['sitekits'] )
92        ) {
93            $response = array();
94
95            // Process the sitekits.
96            $sitekits = $request->get_response_body()['sitekits'];
97            foreach ( $sitekits as $sitekit ) {
98                $sitekit_object = $this->get_sitekit_object( $sitekit );
99                $response[]     = $sitekit_object;
100            }
101
102            // Publish site content.
103            $posts = $request->get_response_body()['posts'] ?? array();
104            $this->publish_content( $posts );
105
106            return $response;
107        }
108
109        // Error.
110        $response_code = $request->get_response_code();
111        $response_body = $request->get_error_response_body();
112        $error_message = ( $response_body && isset( $response_body['message'] ) ) ? $response_body['message'] : __( 'An unknown error occurred', 'wp-module-onboarding' );
113        $response = new \WP_Error(
114            'sitekits_generation_failed',
115            $error_message,
116            array( 'status' => $response_code )
117        );
118
119        return $response;
120    }
121
122    /**
123     * Gets the sitekit object.
124     *
125     * @param array $sitekit The sitekit.
126     * @return Sitekit The sitekit object.
127     */
128    private function get_sitekit_object( array $sitekit ): Sitekit {
129        $processed_sitekit = $this->process_sitekit_item( $sitekit );
130
131        $sitekit = new Sitekit(
132            $processed_sitekit['slug'],
133            $processed_sitekit['title'],
134            $processed_sitekit['header'],
135            $processed_sitekit['footer'],
136            $processed_sitekit['pages'],
137            $processed_sitekit['color_palette']
138        );
139
140        return $sitekit;
141    }
142
143    /**
144     * Processes and prepares a sitekit item from the response.
145     *
146     * @param array $sitekit_item The sitekit item.
147     * @return array The processed sitekit item — ready to be converted to a Sitekit object.
148     */
149    private function process_sitekit_item( array $sitekit_item ): array {
150        $result           = array();
151        $result['slug']   = $sitekit_item['slug'];
152        $result['title']  = $sitekit_item['title'];
153        $result['header'] = $sitekit_item['header']['patternContent'];
154        $result['footer'] = $sitekit_item['footer']['patternContent'];
155        
156        $pages = array();
157        foreach ( $sitekit_item['pages'] as $page_slug => $page_patterns ) {
158            $page_title    = ucfirst( str_replace( '-', ' ', $page_slug ) );
159            $page_content  = $this->get_page_content_from_patterns( $page_patterns );
160            $is_front_page = $page_slug === 'home';
161            $pages[]       = new Page( $page_title, $page_slug, $page_content, $is_front_page );
162        }
163        $result['pages'] = new Pages( $pages );
164
165        // Attach a color palette to the sitekit.
166        $result['color_palette'] = SiteGenService::get_instance()->get_color_palette();
167
168        return $result;
169    }
170
171    /**
172     * Gets the page content from the response patterns array.
173     *
174     * @param array $page_patterns The page patterns.
175     * @return string The page content.
176     */
177    private function get_page_content_from_patterns( array $page_patterns ): string {
178        $page_content = '';
179        foreach ( $page_patterns as $pattern ) {
180            $page_content .= $pattern['patternContent'];
181        }
182        return $page_content;
183    }
184
185    /**
186     * Installs the pre-requisites in background.
187     *
188     * @return void
189     */
190    private function install_pre_requisites_in_background(): void {
191        if ( $this->site_type === 'ecommerce' ) {
192            EcommerceSiteTypeService::install_ecommerce_plugins();
193        }
194    }
195
196    /**
197     * Publishes the demo content.
198     *
199     * @param array $posts The posts.
200     * @return void
201     */
202    private function publish_content( array $posts = array() ): void {
203        // Publish WooCommerce products.
204        $products = $posts['products'] ?? array();
205        if ( ! empty( $products ) ) {
206            foreach ( $products as $index => $product ) {
207                EcommerceSiteTypeService::publish_woo_product(
208                    $product['name'] ?? 'Product ' . $index + 1,
209                    $product['description'] ?? 'Description for Product ' . $index + 1,
210                    $product['price'] ?? '24.99',
211                    $product['image'] ?? '',
212                    $product['categories'] ?? array()
213                );
214            }
215        }
216    }
217
218    /**
219     * Checks if the site type supports sitekits`.
220     *
221     * @param string $site_type The site type.
222     * @return bool
223     */
224    public static function site_type_supported( string $site_type ): bool {
225        return in_array( $site_type, self::$site_types_supported );
226    }
227}