Skip to content

Commit 7e3239e

Browse files
committed
Configure site before showing sitekits
- Install dependency plugins - Publish demo content
1 parent f045c62 commit 7e3239e

File tree

5 files changed

+246
-5
lines changed

5 files changed

+246
-5
lines changed

includes/Application.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ public function __construct( Container $container ) {
6969
}
7070

7171
if ( Permissions::is_authorized_admin() || Permissions::rest_is_authorized_admin() ) {
72-
new RestAPI();
72+
new RestApi();
7373
new WP_Admin();
7474
new ExternalRedirectInterceptor();
7575
}

includes/Services/Ai/ContentGeneration/SitekitsContentGeneration.php

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,16 @@
22

33
namespace NewfoldLabs\WP\Module\Onboarding\Services\Ai\ContentGeneration;
44

5+
use NewfoldLabs\WP\Module\Onboarding\RestApi\ParallelRequestsController;
6+
use NewfoldLabs\WP\Module\Onboarding\Services\ParallelRequestsService;
57
use NewfoldLabs\WP\Module\Onboarding\Services\SiteGenService;
8+
use NewfoldLabs\WP\Module\Onboarding\Services\SiteTypes\EcommerceSiteTypeService;
69
use NewfoldLabs\WP\Module\Onboarding\Types\Page;
710
use NewfoldLabs\WP\Module\Onboarding\Types\Pages;
11+
use NewfoldLabs\WP\Module\Onboarding\Types\ParallelRequest;
812
use NewfoldLabs\WP\Module\Onboarding\Types\SiteClassification;
913
use NewfoldLabs\WP\Module\Onboarding\Types\Sitekit;
14+
use WpOrg\Requests\Requests;
1015

1116
class SitekitsContentGeneration {
1217

@@ -74,20 +79,30 @@ public function generate_sitekits( int $count = 3 ) {
7479
'secondaryType' => $this->site_classification->get_secondary_type(),
7580
);
7681

82+
// Install sitekits pre-requisites plugins in background.
83+
$this->install_pre_requisites_in_background();
84+
85+
// Generate sitekits.
7786
$request = new ContentGenerationServiceRequest( 'sitekits/generate', $request_body );
7887
$request->send();
79-
8088
// Success.
8189
if (
8290
$request->is_successful() &&
8391
isset( $request->get_response_body()['sitekits'] )
8492
) {
8593
$response = array();
94+
95+
// Process the sitekits.
8696
$sitekits = $request->get_response_body()['sitekits'];
8797
foreach ( $sitekits as $sitekit ) {
88-
$sitekit_type = $this->get_sitekit_object( $sitekit );
89-
$response[] = $sitekit_type;
98+
$sitekit_object = $this->get_sitekit_object( $sitekit );
99+
$response[] = $sitekit_object;
90100
}
101+
102+
// Publish site content.
103+
$posts = $request->get_response_body()['posts'] ?? array();
104+
$this->publish_content( $posts );
105+
91106
return $response;
92107
}
93108

@@ -167,6 +182,39 @@ private function get_page_content_from_patterns( array $page_patterns ): string
167182
return $page_content;
168183
}
169184

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+
170218
/**
171219
* Checks if the site type supports sitekits`.
172220
*
Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
<?php
2+
/**
3+
* Ecommerce site type service.
4+
*
5+
* @package NewfoldLabs\WP\Module\Onboarding\Services\SiteTypes
6+
*/
7+
8+
namespace NewfoldLabs\WP\Module\Onboarding\Services\SiteTypes;
9+
10+
use NewfoldLabs\WP\Module\Installer\Services\PluginInstaller;
11+
use NewfoldLabs\WP\Module\Installer\TaskManagers\PluginActivationTaskManager;
12+
use NewfoldLabs\WP\Module\Installer\TaskManagers\PluginInstallTaskManager;
13+
use NewfoldLabs\WP\Module\Installer\Tasks\PluginActivationTask;
14+
use NewfoldLabs\WP\Module\Installer\Tasks\PluginInstallTask;
15+
use NewfoldLabs\WP\Module\Onboarding\Data\Plugins as LegacyPlugins;
16+
17+
/**
18+
* Ecommerce site type service.
19+
*/
20+
class EcommerceSiteTypeService {
21+
22+
/**
23+
* Publishes a WooCommerce product.
24+
*
25+
* @param array $product The product.
26+
* @return int|WP_Error The product ID.
27+
*/
28+
public static function publish_woo_product( string $name, string $description, mixed $price, string $image_url = '', array $categories = array()) {
29+
// Remove hooks that can slow down the operation.
30+
remove_all_actions('woocommerce_new_product');
31+
remove_all_actions('woocommerce_update_product');
32+
remove_all_actions('wp_insert_post');
33+
remove_all_actions('save_post');
34+
35+
$product_data = array(
36+
'post_title' => $name,
37+
'post_content' => '',
38+
'post_excerpt' => $description,
39+
'post_status' => 'publish',
40+
'post_type' => 'product',
41+
'post_author' => get_current_user_id() ?: 1,
42+
);
43+
// Insert product.
44+
$product_id = wp_insert_post( $product_data );
45+
// Validate product was created successfully.
46+
if ( is_wp_error( $product_id ) || !$product_id ) {
47+
return new \WP_Error( 'error_publishing_woo_product', 'Failed to create product' );
48+
}
49+
// Product meta.
50+
update_post_meta( $product_id, '_regular_price', $price );
51+
update_post_meta( $product_id, '_price', $price );
52+
update_post_meta( $product_id, '_stock_status', 'instock' );
53+
update_post_meta( $product_id, '_manage_stock', 'no' );
54+
// Product categories.
55+
if ( ! empty( $categories ) ) {
56+
$category_ids = array();
57+
foreach ( $categories as $category ) {
58+
$category_ids[] = self::create_or_get_woo_category( $category );
59+
}
60+
wp_set_post_terms( $product_id, $category_ids, 'product_cat' );
61+
}
62+
// Featured image.
63+
if ( ! empty( $image_url ) ) {
64+
self::set_woo_product_featured_image_from_url( $image_url, $product_id );
65+
}
66+
67+
return $product_id;
68+
}
69+
70+
/**
71+
* Sets the featured image for a WooCommerce product.
72+
*
73+
* @param string $image_url The URL of the image.
74+
* @param int $product_id The ID of the product.
75+
* @return void
76+
*/
77+
private static function set_woo_product_featured_image_from_url( string $image_url, int $product_id ): void {
78+
$image_id = self::import_image_from_url( $image_url, $product_id );
79+
if ( $image_id ) {
80+
update_post_meta( $product_id, '_thumbnail_id', $image_id );
81+
}
82+
}
83+
84+
/**
85+
* Imports an image from a URL.
86+
*
87+
* @param string $image_url The URL of the image.
88+
* @param int $product_id The ID of the product.
89+
* @return int The ID of the attachment.
90+
*/
91+
private static function import_image_from_url( string $image_url, int $product_id ): int {
92+
if ( ! function_exists( 'media_handle_sideload' ) ) {
93+
require_once( ABSPATH . 'wp-admin/includes/media.php' );
94+
require_once( ABSPATH . 'wp-admin/includes/file.php' );
95+
require_once( ABSPATH . 'wp-admin/includes/image.php' );
96+
}
97+
98+
// Add an arbitrary extension to the image URL to trick media_sideload_image to download the image.
99+
$image_url = $image_url . '?ext=.jpeg';
100+
$attachment_id = media_sideload_image( $image_url, $product_id, null, 'id' );
101+
if ( is_wp_error( $attachment_id ) ) {
102+
return 0;
103+
}
104+
105+
return $attachment_id;
106+
}
107+
108+
/**
109+
* Creates or gets a WooCommerce category.
110+
*
111+
* @param string $name The name of the category.
112+
* @return int The ID of the category.
113+
*/
114+
public static function create_or_get_woo_category( string $name ): int {
115+
$category_slug = sanitize_title( $name );
116+
$category = get_term_by( 'slug', $category_slug, 'product_cat' );
117+
if ( $category ) {
118+
return $category->term_id;
119+
}
120+
$category = wp_insert_term( $name, 'product_cat' );
121+
if ( is_wp_error( $category ) ) {
122+
return 0;
123+
}
124+
return $category['term_id'];
125+
}
126+
127+
/**
128+
* Gets the ecommerce plugins.
129+
*
130+
* @return array
131+
*/
132+
public static function get_ecommerce_plugins(): array {
133+
return LegacyPlugins::get_ecommerce_plugins();
134+
}
135+
136+
/**
137+
* Installs the ecommerce plugins (background task).
138+
*
139+
* @return void
140+
*/
141+
public static function install_ecommerce_plugins(): void {
142+
$ecommerce_plugins = self::get_ecommerce_plugins();
143+
144+
foreach ( $ecommerce_plugins as $plugin ) {
145+
$plugin_type = PluginInstaller::get_plugin_type( $plugin['slug'] );
146+
$plugin_path = PluginInstaller::get_plugin_path( $plugin['slug'], $plugin_type );
147+
if ( ! $plugin_path ) {
148+
continue;
149+
}
150+
151+
// Checks if a plugin with the given slug and activation criteria already installed.
152+
if ( PluginInstaller::is_plugin_installed( $plugin_path ) ) {
153+
// If the plugin is installed, we'll add it to the activation queue.
154+
PluginActivationTaskManager::add_to_queue(
155+
new PluginActivationTask(
156+
$plugin['slug']
157+
)
158+
);
159+
continue;
160+
}
161+
162+
// If the plugin is not installed, we'll add it to the install/activation queue.
163+
PluginInstallTaskManager::add_to_queue(
164+
new PluginInstallTask(
165+
$plugin['slug'],
166+
true,
167+
isset( $plugin['priority'] ) ? $plugin['priority'] : 0
168+
)
169+
);
170+
}
171+
172+
return;
173+
}
174+
}

src/app/utils/api/onboarding.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import apiFetch from '@wordpress/api-fetch';
22
import { wpRestURL } from '@/data/constants';
33
import { resolve } from '@/utils/helpers';
4+
import { fireWpCron } from './';
45

56
export const onboardingRestRoute = 'newfold-onboarding/v1';
67
export const onboardingRestBase = `${ wpRestURL }/${ onboardingRestRoute }`;
@@ -35,7 +36,14 @@ export const updateOnboardingSiteGenSlice = async ( data ) => {
3536
);
3637
};
3738

39+
export const continuouslyFireWpCron = () => {
40+
setInterval( () => {
41+
fireWpCron();
42+
}, 30000 );
43+
};
44+
3845
export const startOnboarding = async ( data = {} ) => {
46+
continuouslyFireWpCron();
3947
return await resolve(
4048
apiFetch( {
4149
url: onboardingRestURL( 'app/start' ),

src/app/utils/api/wp.js

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import apiFetch from '@wordpress/api-fetch';
2-
import { wpRestURL as wpRestApiURL } from '@/data/constants';
2+
import { wpRestURL as wpRestApiURL, wpSiteUrl } from '@/data/constants';
33
import { resolve } from '@/utils/helpers';
44

55
export const wpRestRoute = 'wp/v2';
@@ -16,3 +16,14 @@ export async function getWpSettings() {
1616
} ).then()
1717
);
1818
}
19+
20+
export const fireWpCron = () => {
21+
apiFetch( {
22+
url: `${ wpSiteUrl }/wp-cron.php`,
23+
method: 'GET',
24+
parse: false,
25+
} ).catch( ( error ) => {
26+
// eslint-disable-next-line no-console
27+
console.error( error );
28+
} );
29+
};

0 commit comments

Comments
 (0)