PluginProbe
Elementor Website Builder – more than just a page builder / 3.18.3
Elementor Website Builder – more than just a page builder v3.18.3
4.3.0-beta2 4.3.0-beta1 4.2.4 4.2.3 4.2.2 4.2.1 4.2.0 4.1.5 4.2.0-beta2 4.2.0-dev2 4.2.0-beta1 4.1.4 4.1.3 4.1.2 4.1.1 4.1.0 4.1.0-beta3 4.1.0-dev3 4.0.9 4.1.0-beta2 4.1.0-dev2 4.0.8 4.1.0-beta1 4.1.0-dev1 4.0.7 All 451 releases
← All changes | modules/ai/module.php +166 -788 4.2.23.18.3 View file →
@@ -1,17 +1,14 @@
1 1 <?php
2 2 namespace Elementor\Modules\Ai;
3 3
4 -use Elementor\Controls_Manager;
5 4 use Elementor\Core\Base\Module as BaseModule;
6 5 use Elementor\Core\Common\Modules\Connect\Module as ConnectModule;
7 -use Elementor\Element_Base;
8 -use Elementor\Modules\Ai\Feature_Intro\Product_Image_Unification_Intro;
9 -use Elementor\Plugin;
6 +use Elementor\Core\Experiments\Manager as Experiments_Manager;
10 7 use Elementor\Core\Utils\Collection;
11 8 use Elementor\Modules\Ai\Connect\Ai;
9 +use Elementor\Plugin;
12 10 use Elementor\User;
13 -use Elementor\Utils;
14 11
15 12 if ( ! defined( 'ABSPATH' ) ) {
16 13 exit; // Exit if accessed directly.
17 14 }
@@ -28,10 +25,11 @@
28 25 self::HISTORY_TYPE_CODE,
29 26 self::HISTORY_TYPE_IMAGE,
30 27 self::HISTORY_TYPE_BLOCK,
31 28 ];
32 - const MIN_PAGES_FOR_CREATE_WITH_AI_BANNER = 10;
33 29
30 + const LAYOUT_EXPERIMENT = 'ai-layout';
31 +
34 32 public function get_name() {
35 33 return 'ai';
36 34 }
37 35
@@ -37,21 +35,10 @@
37 35
38 36 public function __construct() {
39 37 parent::__construct();
40 38
41 - ( new SitePlannerConnect\Module() );
39 + $this->register_layout_experiment();
42 40
43 - if ( is_admin() ) {
44 - ( new Preferences() )->register();
45 - add_action( 'elementor/import-export/import-kit/runner/after-run', [ $this, 'handle_kit_install' ] );
46 - }
47 -
48 - if ( ! $this->is_ai_enabled() ) {
49 - return;
50 - }
51 -
52 - add_filter( 'elementor/core/admin/homescreen', [ $this, 'add_create_with_ai_banner_to_homescreen' ] );
53 -
54 41 add_action( 'elementor/connect/apps/register', function ( ConnectModule $connect_module ) {
55 42 $connect_module->register_app( 'ai', Ai::get_class_name() );
56 43 } );
57 44
@@ -58,12 +45,9 @@
58 45 add_action( 'elementor/ajax/register_actions', function( $ajax ) {
59 46 $handlers = [
60 47 'ai_get_user_information' => [ $this, 'ajax_ai_get_user_information' ],
61 48 'ai_get_remote_config' => [ $this, 'ajax_ai_get_remote_config' ],
62 - 'ai_get_remote_frontend_config' => [ $this, 'ajax_ai_get_remote_frontend_config' ],
63 49 'ai_get_completion_text' => [ $this, 'ajax_ai_get_completion_text' ],
64 - 'ai_get_excerpt' => [ $this, 'ajax_ai_get_excerpt' ],
65 - 'ai_get_featured_image' => [ $this, 'ajax_ai_get_featured_image' ],
66 50 'ai_get_edit_text' => [ $this, 'ajax_ai_get_edit_text' ],
67 51 'ai_get_custom_code' => [ $this, 'ajax_ai_get_custom_code' ],
68 52 'ai_get_custom_css' => [ $this, 'ajax_ai_get_custom_css' ],
69 53 'ai_set_get_started' => [ $this, 'ajax_ai_set_get_started' ],
@@ -71,9 +55,8 @@
71 55 'ai_get_image_prompt_enhancer' => [ $this, 'ajax_ai_get_image_prompt_enhancer' ],
72 56 'ai_get_text_to_image' => [ $this, 'ajax_ai_get_text_to_image' ],
73 57 'ai_get_image_to_image' => [ $this, 'ajax_ai_get_image_to_image' ],
74 58 'ai_get_image_to_image_mask' => [ $this, 'ajax_ai_get_image_to_image_mask' ],
75 - 'ai_get_image_to_image_mask_cleanup' => [ $this, 'ajax_ai_get_image_to_image_mask_cleanup' ],
76 59 'ai_get_image_to_image_outpainting' => [ $this, 'ajax_ai_get_image_to_image_outpainting' ],
77 60 'ai_get_image_to_image_upscale' => [ $this, 'ajax_ai_get_image_to_image_upscale' ],
78 61 'ai_get_image_to_image_remove_background' => [ $this, 'ajax_ai_get_image_to_image_remove_background' ],
79 62 'ai_get_image_to_image_replace_background' => [ $this, 'ajax_ai_get_image_to_image_replace_background' ],
@@ -82,11 +65,8 @@
82 65 'ai_get_layout_prompt_enhancer' => [ $this, 'ajax_ai_get_layout_prompt_enhancer' ],
83 66 'ai_get_history' => [ $this, 'ajax_ai_get_history' ],
84 67 'ai_delete_history_item' => [ $this, 'ajax_ai_delete_history_item' ],
85 68 'ai_toggle_favorite_history_item' => [ $this, 'ajax_ai_toggle_favorite_history_item' ],
86 - 'ai_get_product_image_unification' => [ $this, 'ajax_ai_get_product_image_unification' ],
87 - 'ai_get_animation' => [ $this, 'ajax_ai_get_animation' ],
88 - 'ai_get_image_to_image_isolate_objects' => [ $this, 'ajax_ai_get_product_image_unification' ],
89 69 ];
90 70
91 71 foreach ( $handlers as $tag => $callback ) {
92 72 $ajax->register_ajax_action( $tag, $callback );
@@ -94,9 +74,12 @@
94 74 } );
95 75
96 76 add_action( 'elementor/editor/before_enqueue_scripts', function() {
97 77 $this->enqueue_main_script();
98 - $this->enqueue_layout_script();
78 +
79 + if ( $this->is_layout_active() ) {
80 + $this->enqueue_layout_script();
81 + }
99 82 } );
100 83
101 84 add_action( 'elementor/editor/after_enqueue_styles', function() {
102 85 wp_enqueue_style(
@@ -107,352 +90,40 @@
107 90 );
108 91 } );
109 92
110 93 add_action( 'elementor/preview/enqueue_styles', function() {
111 - wp_enqueue_style(
112 - 'elementor-ai-layout-preview',
113 - $this->get_css_assets_url( 'modules/ai/layout-preview' ),
114 - [],
115 - ELEMENTOR_VERSION
116 - );
94 + if ( $this->is_layout_active() ) {
95 + wp_enqueue_style(
96 + 'elementor-ai-layout-preview',
97 + $this->get_css_assets_url( 'modules/ai/layout-preview' ),
98 + [],
99 + ELEMENTOR_VERSION
100 + );
101 + }
117 102 } );
118 103
119 - if ( is_admin() ) {
120 - add_action( 'wp_enqueue_media', [ $this, 'enqueue_ai_media_library' ] );
121 - add_action( 'admin_head', [ $this, 'enqueue_ai_media_library_upload_screen' ] );
122 -
123 - if ( current_user_can( 'edit_products' ) || current_user_can( 'publish_products' ) ) {
124 - add_action( 'admin_init', [ $this, 'enqueue_ai_products_page_scripts' ] );
125 - add_action( 'current_screen', [ $this, 'enqueue_ai_single_product_page_scripts' ] );
126 - add_action( 'wp_ajax_elementor-ai-get-product-images', [ $this, 'get_product_images_ajax' ] );
127 - add_action( 'wp_ajax_elementor-ai-set-product-images', [ $this, 'set_product_images_ajax' ] );
128 - Product_Image_Unification_Intro::add_hooks();
104 + add_filter( 'elementor/document/save/data', function ( $data ) {
105 + if ( $this->is_layout_active() ) {
106 + return $this->remove_temporary_containers( $data );
129 107 }
130 - }
131 108
132 - add_action( 'enqueue_block_editor_assets', function() {
133 - wp_enqueue_script( 'elementor-ai-gutenberg',
134 - $this->get_js_assets_url( 'ai-gutenberg' ),
135 - [
136 - 'jquery',
137 - 'elementor-v2-ui',
138 - 'elementor-v2-icons',
139 - 'wp-blocks',
140 - 'wp-element',
141 - 'wp-editor',
142 - 'wp-data',
143 - 'wp-components',
144 - 'wp-compose',
145 - 'wp-i18n',
146 - 'wp-hooks',
147 - 'elementor-ai-media-library',
148 - ],
149 - ELEMENTOR_VERSION, true );
150 -
151 - wp_localize_script(
152 - 'elementor-ai-gutenberg',
153 - 'ElementorAiConfig',
154 - [
155 - 'is_get_started' => User::get_introduction_meta( 'ai_get_started' ),
156 - 'connect_url' => $this->get_ai_connect_url(),
157 - ]
158 - );
159 -
160 - wp_set_script_translations( 'elementor-ai-gutenberg', 'elementor' );
161 - });
162 -
163 - add_filter( 'elementor/document/save/data', function ( $data ) {
164 - return $this->remove_temporary_containers( $data );
109 + return $data;
165 110 } );
166 -
167 - add_action( 'elementor/element/common/section_effects/after_section_start', [ $this, 'register_ai_motion_effect_control' ], 10, 1 );
168 - add_action( 'elementor/element/container/section_effects/after_section_start', [ $this, 'register_ai_motion_effect_control' ], 10, 1 );
169 - add_action( 'elementor/element/common/_section_transform/after_section_end', [ $this, 'register_ai_hover_effect_control' ], 10, 1 );
170 - add_action( 'elementor/element/container/_section_transform/after_section_end', [ $this, 'register_ai_hover_effect_control' ], 10, 1 );
171 111 }
172 112
173 - public function is_ai_enabled() {
174 - if ( ! Plugin::$instance->experiments->is_feature_active( 'container' ) ) {
175 - return false;
176 - }
177 -
178 - return Preferences::is_ai_enabled( get_current_user_id() );
179 - }
180 -
181 - public function handle_kit_install( $imported_data ) {
182 - if ( ! $this->is_ai_enabled() ) {
183 - return;
184 - }
185 -
186 - if ( ! isset( $imported_data['status'] ) || 'success' !== $imported_data['status'] ) {
187 - return;
188 - }
189 -
190 - if ( ! isset( $imported_data['runner'] ) || 'site-settings' !== $imported_data['runner'] ) {
191 - return;
192 - }
193 -
194 - if ( ! isset( $imported_data['configData']['lastImportedSession']['instance_data']['site_settings']['settings']['ai'] ) ) {
195 - return;
196 - }
197 -
198 - $is_connected = $this->get_ai_app()->is_connected() && User::get_introduction_meta( 'ai_get_started' );
199 -
200 - if ( ! $is_connected ) {
201 - return;
202 - }
203 -
204 - $last_imported_session = $imported_data['configData']['lastImportedSession'];
205 - $imported_ai_data = $last_imported_session['instance_data']['site_settings']['settings']['ai'];
206 -
207 - $this->get_ai_app()->send_event( [
208 - 'name' => 'kit_installed',
209 - 'data' => $imported_ai_data,
210 - 'client' => [
211 - 'name' => 'elementor',
212 - 'version' => ELEMENTOR_VERSION,
213 - 'session_id' => $last_imported_session['session_id'],
113 + private function register_layout_experiment() {
114 + Plugin::$instance->experiments->add_feature( [
115 + 'name' => static::LAYOUT_EXPERIMENT,
116 + 'title' => esc_html__( 'Build with AI', 'elementor' ),
117 + 'description' => esc_html__( 'Tap into the potential of AI to easily create and customize containers to your specifications, right within Elementor. This feature comes packed with handy AI tools, including generation, variations, and URL references.', 'elementor' ),
118 + 'default' => Experiments_Manager::STATE_INACTIVE,
119 + 'status' => Experiments_Manager::RELEASE_STATUS_ALPHA,
120 + 'dependencies' => [
121 + 'container',
214 122 ],
215 123 ] );
216 124 }
217 125
218 - public function register_ai_hover_effect_control( Element_Base $element ) {
219 - if ( ! $element->get_controls( 'ai_hover_animation' ) ) {
220 - $element->add_control(
221 - 'ai_hover_animation',
222 - [
223 - 'tabs_wrapper' => '_tabs_positioning',
224 - 'inner_tab' => '_tab_positioning_hover',
225 - 'label' => esc_html__( 'Animate With AI', 'elementor' ),
226 - 'type' => Controls_Manager::RAW_HTML,
227 - 'raw' => '
228 -<style>
229 - .elementor-control-ai_hover_animation .elementor-control-content {
230 - display: flex;
231 - flex-direction: row;
232 - justify-content: space-between;
233 - align-items: center;
234 - }
235 - .elementor-control-ai_hover_animation .elementor-control-raw-html {
236 - display: none;
237 - }
238 -</style>',
239 - 'render_type' => 'none',
240 - 'ai' => [
241 - 'active' => true,
242 - 'type' => 'hover_animation',
243 - ],
244 - ],
245 - [
246 - 'position' => [
247 - 'of' => '_transform_rotate_popover_hover',
248 - 'type' => 'control',
249 - 'at' => 'before',
250 - ],
251 - ]
252 - );
253 - }
254 - }
255 - public function register_ai_motion_effect_control( $element ) {
256 - if ( Utils::has_pro() && ! $element->get_controls( 'ai_animation' ) ) {
257 - $element->add_control(
258 - 'ai_animation',
259 - [
260 - 'label' => esc_html__( 'Animate With AI', 'elementor' ),
261 - 'type' => Controls_Manager::RAW_HTML,
262 - 'raw' => '
263 - <style>
264 - .elementor-control-ai_animation .elementor-control-content {
265 - display: flex;
266 - flex-direction: row;
267 - justify-content: space-between;
268 - align-items: center;
269 - }
270 - .elementor-control-ai_animation .elementor-control-raw-html {
271 - display: none;
272 - }
273 - </style>',
274 - 'render_type' => 'none',
275 - 'ai' => [
276 - 'active' => true,
277 - 'type' => 'animation',
278 - ],
279 - ]
280 - );
281 - }
282 - }
283 -
284 - private function get_current_screen() {
285 - $is_wc = class_exists( 'WooCommerce' ) && post_type_exists( 'product' );
286 - if ( ! $is_wc ) {
287 - return 'other';
288 - }
289 -
290 - $is_products_page = isset( $_GET['post_type'] ) && 'product' === $_GET['post_type'];
291 - if ( $is_products_page ) {
292 - return 'wc-products';
293 - }
294 -
295 - $screen = get_current_screen();
296 - $is_single_product_page = isset( $screen->post_type ) && ( 'product' === $screen->post_type && 'post' === $screen->base );
297 - if ( $is_single_product_page ) {
298 - return 'wc-single-product';
299 - }
300 -
301 - return 'other';
302 - }
303 -
304 - public function enqueue_ai_products_page_scripts() {
305 - if ( 'wc-products' !== $this->get_current_screen() ) {
306 - return;
307 - }
308 -
309 - $this->add_wc_scripts();
310 - }
311 -
312 - public function enqueue_ai_single_product_page_scripts() {
313 - if ( 'wc-single-product' !== $this->get_current_screen() ) {
314 - return;
315 - }
316 -
317 - $this->add_wc_scripts();
318 - }
319 -
320 - private function add_products_bulk_action( $bulk_actions ) {
321 - $bulk_actions['elementor-ai-unify-product-images'] = __( 'Unify with Elementor AI', 'elementor' );
322 - return $bulk_actions;
323 - }
324 -
325 - public function get_product_images_ajax() {
326 - check_ajax_referer( 'elementor-ai-unify-product-images_nonce', 'nonce' );
327 -
328 - $post_ids = isset( $_POST['post_ids'] ) ? array_map( 'intval', $_POST['post_ids'] ) : [];
329 - $is_galley_only = isset( $_POST['is_galley_only'] ) && sanitize_text_field( wp_unslash( $_POST['is_galley_only'] ) );
330 -
331 - $image_ids = [];
332 -
333 - foreach ( $post_ids as $post_id ) {
334 - if ( $is_galley_only ) {
335 - $product = wc_get_product( $post_id );
336 - $gallery_image_ids = $product->get_gallery_image_ids();
337 - foreach ( $gallery_image_ids as $image_id ) {
338 - $image_ids[] = [
339 - 'productId' => $post_id,
340 - 'id' => $image_id,
341 - 'image_url' => wp_get_attachment_url( $image_id ),
342 - ];
343 - }
344 - continue;
345 - }
346 -
347 - $image_id = get_post_thumbnail_id( $post_id );
348 -
349 - if ( ! $image_id ) {
350 - $product = wc_get_product( $post_id );
351 - $gallery_image_ids = $product->get_gallery_image_ids();
352 - if ( ! empty( $gallery_image_ids ) ) {
353 - $image_id = $gallery_image_ids[0];
354 - }
355 - }
356 -
357 - $image_ids[] = [
358 - 'productId' => $post_id,
359 - 'id' => $image_id ? $image_id : 'No Image',
360 - 'image_url' => $image_id ? wp_get_attachment_url( $image_id ) : 'No Image',
361 - ];
362 - }
363 -
364 - wp_send_json_success( [ 'product_images' => array_slice( $image_ids, 0, 10 ) ] );
365 -
366 - wp_die();
367 - }
368 -
369 - private function get_attachment_id_by_url( $url ) {
370 - $attachments = get_posts( [
371 - 'post_type' => 'attachment',
372 - 'meta_query' => [
373 - [
374 - 'key' => '_wp_attached_file',
375 - 'value' => basename( $url ),
376 - 'compare' => 'LIKE',
377 - ],
378 - ],
379 - 'fields' => 'ids',
380 - 'numberposts' => 1,
381 - ] );
382 -
383 - return ! empty( $attachments ) ? $attachments[0] : null;
384 - }
385 -
386 - public function set_product_images_ajax() {
387 - check_ajax_referer( 'elementor-ai-unify-product-images_nonce', 'nonce' );
388 -
389 - $product_id = isset( $_POST['productId'] ) ? sanitize_text_field( wp_unslash( $_POST['productId'] ) ) : '';
390 - $image_url = isset( $_POST['image_url'] ) ? sanitize_text_field( wp_unslash( $_POST['image_url'] ) ) : '';
391 - $image_to_add = isset( $_POST['image_to_add'] ) ? intval( wp_unslash( $_POST['image_to_add'] ) ) : null;
392 - $image_to_remove = isset( $_POST['image_to_remove'] ) ? intval( wp_unslash( $_POST['image_to_remove'] ) ) : null;
393 - $is_product_gallery = isset( $_POST['is_product_gallery'] ) && sanitize_text_field( wp_unslash( $_POST['is_product_gallery'] ) ) === 'true';
394 -
395 - if ( ! $product_id || ! $image_url ) {
396 - throw new \Exception( 'Product ID and Image URL are required' );
397 - }
398 -
399 - $product = wc_get_product( $product_id );
400 - if ( ! $product ) {
401 - throw new \Exception( 'Product not found' );
402 - }
403 -
404 - $attachment_id = $this->get_attachment_id_by_url( $image_url );
405 - if ( is_wp_error( $attachment_id ) ) {
406 - throw new \Exception( 'Image upload failed' );
407 - }
408 -
409 - if ( $is_product_gallery ) {
410 - $this->update_product_gallery( $product, $image_to_remove, $image_to_add );
411 - } else {
412 - $product->set_image_id( $attachment_id );
413 - $product->save();
414 - }
415 -
416 - wp_send_json_success( [
417 - 'message' => __( 'Image added successfully', 'elementor' ),
418 - ] );
419 - }
420 -
421 - public function enqueue_ai_media_library_upload_screen() {
422 - $screen = get_current_screen();
423 - if ( ! $screen || 'upload' !== $screen->id ) {
424 - return;
425 - }
426 -
427 - $this->enqueue_ai_media_library();
428 - }
429 -
430 - public function enqueue_ai_media_library() {
431 - wp_enqueue_script( 'elementor-ai-media-library',
432 - $this->get_js_assets_url( 'ai-media-library' ),
433 - [
434 - 'jquery',
435 - 'elementor-v2-ui',
436 - 'elementor-v2-icons',
437 - 'media-grid',
438 - ],
439 - ELEMENTOR_VERSION,
440 - true
441 - );
442 -
443 - wp_localize_script(
444 - 'elementor-ai-media-library',
445 - 'ElementorAiConfig',
446 - [
447 - 'is_get_started' => User::get_introduction_meta( 'ai_get_started' ),
448 - 'connect_url' => $this->get_ai_connect_url(),
449 - ]
450 - );
451 -
452 - wp_set_script_translations( 'elementor-ai-media-library', 'elementor' );
453 - }
454 -
455 126 private function enqueue_main_script() {
456 127 wp_enqueue_script(
457 128 'elementor-ai',
458 129 $this->get_js_assets_url( 'ai' ),
@@ -471,17 +142,17 @@
471 142 ELEMENTOR_VERSION,
472 143 true
473 144 );
474 145
475 - $config = [
476 - 'is_get_started' => User::get_introduction_meta( 'ai_get_started' ),
477 - 'connect_url' => $this->get_ai_connect_url(),
478 - ];
479 -
480 146 wp_localize_script(
481 147 'elementor-ai',
482 148 'ElementorAiConfig',
483 - $config
149 + [
150 + 'is_get_started' => User::get_introduction_meta( 'ai_get_started' ),
151 + 'connect_url' => $this->get_ai_connect_url(),
152 + // Use a cached version, don't call the API on every editor load.
153 + 'usage' => $this->get_ai_app()->get_cached_usage(),
154 + ]
484 155 );
485 156
486 157 wp_set_script_translations( 'elementor-ai', 'elementor' );
487 158 }
@@ -507,10 +178,14 @@
507 178
508 179 wp_set_script_translations( 'elementor-ai-layout', 'elementor' );
509 180 }
510 181
182 + private function is_layout_active() {
183 + return Plugin::$instance->experiments->is_feature_active( self::LAYOUT_EXPERIMENT );
184 + }
185 +
511 186 private function remove_temporary_containers( $data ) {
512 - if ( empty( $data['elements'] ) || ! is_array( $data['elements'] ) ) {
187 + if ( empty( $data['elements'] ) ) {
513 188 return $data;
514 189 }
515 190
516 191 // If for some reason the document has been saved during an AI Layout session,
@@ -568,25 +243,8 @@
568 243
569 244 return $app->get_remote_config();
570 245 }
571 246
572 - public function ajax_ai_get_remote_frontend_config( $data ) {
573 - $callback = function () use ( $data ) {
574 - return $this->get_ai_app()->get_remote_frontend_config( $data );
575 - };
576 -
577 - return Utils::get_cached_callback( $callback, 'ai_remote_frontend_config-' . get_current_user_id(), HOUR_IN_SECONDS );
578 - }
579 -
580 - public function verify_upload_permissions( $data ) {
581 - $referer = wp_get_referer();
582 -
583 - if ( str_contains( $referer, 'wp-admin/upload.php' ) && current_user_can( 'upload_files' ) ) {
584 - return;
585 - }
586 - $this->verify_permissions( $data['editor_post_id'] );
587 - }
588 -
589 247 private function verify_permissions( $editor_post_id ) {
590 248 $document = Plugin::$instance->documents->get( $editor_post_id );
591 249
592 250 if ( ! $document ) {
@@ -592,19 +250,15 @@
592 250 if ( ! $document ) {
593 251 throw new \Exception( 'Document not found' );
594 252 }
595 253
596 - if ( $document->is_built_with_elementor() ) {
597 - if ( ! $document->is_editable_by_current_user() ) {
598 - throw new \Exception( 'Access denied' );
599 - }
600 - } elseif ( ! current_user_can( 'edit_post', $editor_post_id ) ) {
601 - throw new \Exception( 'Access denied' );
254 + if ( ! $document->is_built_with_elementor() || ! $document->is_editable_by_current_user() ) {
255 + throw new \Exception( 'Access denied' );
602 256 }
603 257 }
604 258
605 259 public function ajax_ai_get_image_prompt_enhancer( $data ) {
606 - $this->verify_upload_permissions( $data );
260 + $this->verify_permissions( $data['editor_post_id'] );
607 261
608 262 $app = $this->get_ai_app();
609 263
610 264 if ( empty( $data['prompt'] ) ) {
@@ -613,12 +267,13 @@
613 267
614 268 if ( ! $app->is_connected() ) {
615 269 throw new \Exception( 'not_connected' );
616 270 }
617 - $request_ids = $this->get_request_ids( $data['payload'] );
618 271
619 - $result = $app->get_image_prompt_enhanced( $data['prompt'], [], $request_ids );
620 - $this->throw_on_error( $result );
272 + $result = $app->get_image_prompt_enhanced( $data['prompt'] );
273 + if ( is_wp_error( $result ) ) {
274 + throw new \Exception( $result->get_error_message() );
275 + }
621 276
622 277 return [
623 278 'text' => $result['text'],
624 279 'response_id' => $result['responseId'],
@@ -630,9 +285,9 @@
630 285 $this->verify_permissions( $data['editor_post_id'] );
631 286
632 287 $app = $this->get_ai_app();
633 288
634 - if ( empty( $data['payload']['prompt'] ) ) {
289 + if ( empty( $data['prompt'] ) ) {
635 290 throw new \Exception( 'Missing prompt' );
636 291 }
637 292
638 293 if ( ! $app->is_connected() ) {
@@ -640,39 +295,13 @@
640 295 }
641 296
642 297 $context = $this->get_request_context( $data );
643 298
644 - $request_ids = $this->get_request_ids( $data['payload'] );
645 -
646 - $result = $app->get_completion_text( $data['payload']['prompt'], $context, $request_ids );
647 - $this->throw_on_error( $result );
648 -
649 - return [
650 - 'text' => $result['text'],
651 - 'response_id' => $result['responseId'],
652 - 'usage' => $result['usage'],
653 - ];
654 - }
655 -
656 -
657 - public function ajax_ai_get_excerpt( $data ): array {
658 - $app = $this->get_ai_app();
659 -
660 - if ( empty( $data['payload']['content'] ) ) {
661 - throw new \Exception( 'Missing content' );
299 + $result = $app->get_completion_text( $data['prompt'], $context );
300 + if ( is_wp_error( $result ) ) {
301 + throw new \Exception( $result->get_error_message() );
662 302 }
663 303
664 - if ( ! $app->is_connected() ) {
665 - throw new \Exception( 'Not connected' );
666 - }
667 -
668 - $context = $this->get_request_context( $data );
669 -
670 - $request_ids = $this->get_request_ids( $data['payload'] );
671 -
672 - $result = $app->get_excerpt( $data['payload']['content'], $context, $request_ids );
673 - $this->throw_on_error( $result );
674 -
675 304 return [
676 305 'text' => $result['text'],
677 306 'response_id' => $result['responseId'],
678 307 'usage' => $result['usage'],
@@ -678,36 +307,9 @@
678 307 'usage' => $result['usage'],
679 308 ];
680 309 }
681 310
682 - public function ajax_ai_get_featured_image( $data ): array {
683 - $this->verify_upload_permissions( $data );
684 -
685 - if ( empty( $data['payload']['prompt'] ) ) {
686 - throw new \Exception( 'Missing prompt' );
687 - }
688 -
689 - $app = $this->get_ai_app();
690 -
691 - if ( ! $app->is_connected() ) {
692 - throw new \Exception( 'not_connected' );
693 - }
694 -
695 - $context = $this->get_request_context( $data );
696 - $request_ids = $this->get_request_ids( $data['payload'] );
697 -
698 - $result = $app->get_featured_image( $data, $context, $request_ids );
699 -
700 - $this->throw_on_error( $result );
701 -
702 - return [
703 - 'images' => $result['images'],
704 - 'response_id' => $result['responseId'],
705 - 'usage' => $result['usage'],
706 - ];
707 - }
708 -
709 - private function get_ai_app(): Ai {
311 + private function get_ai_app() : Ai {
710 312 return Plugin::$instance->common->get_component( 'connect' )->get_app( 'ai' );
711 313 }
712 314
713 315 private function get_request_context( $data ) {
@@ -717,26 +319,18 @@
717 319
718 320 return $data['context'];
719 321 }
720 322
721 - private function get_request_ids( $data ) {
722 - if ( empty( $data['requestIds'] ) ) {
723 - return new \stdClass();
724 - }
725 -
726 - return $data['requestIds'];
727 - }
728 -
729 323 public function ajax_ai_get_edit_text( $data ) {
730 324 $this->verify_permissions( $data['editor_post_id'] );
731 325
732 326 $app = $this->get_ai_app();
733 327
734 - if ( empty( $data['payload']['input'] ) ) {
328 + if ( empty( $data['input'] ) ) {
735 329 throw new \Exception( 'Missing input' );
736 330 }
737 331
738 - if ( empty( $data['payload']['instruction'] ) ) {
332 + if ( empty( $data['instruction'] ) ) {
739 333 throw new \Exception( 'Missing instruction' );
740 334 }
741 335
742 336 if ( ! $app->is_connected() ) {
@@ -744,13 +338,13 @@
744 338 }
745 339
746 340 $context = $this->get_request_context( $data );
747 341
748 - $request_ids = $this->get_request_ids( $data['payload'] );
342 + $result = $app->get_edit_text( $data['input'], $data['instruction'], $context );
343 + if ( is_wp_error( $result ) ) {
344 + throw new \Exception( $result->get_error_message() );
345 + }
749 346
750 - $result = $app->get_edit_text( $data, $context, $request_ids );
751 - $this->throw_on_error( $result );
752 -
753 347 return [
754 348 'text' => $result['text'],
755 349 'response_id' => $result['responseId'],
756 350 'usage' => $result['usage'],
@@ -759,13 +353,13 @@
759 353
760 354 public function ajax_ai_get_custom_code( $data ) {
761 355 $app = $this->get_ai_app();
762 356
763 - if ( empty( $data['payload']['prompt'] ) ) {
357 + if ( empty( $data['prompt'] ) ) {
764 358 throw new \Exception( 'Missing prompt' );
765 359 }
766 360
767 - if ( empty( $data['payload']['language'] ) ) {
361 + if ( empty( $data['language'] ) ) {
768 362 throw new \Exception( 'Missing language' );
769 363 }
770 364
771 365 if ( ! $app->is_connected() ) {
@@ -773,13 +367,13 @@
773 367 }
774 368
775 369 $context = $this->get_request_context( $data );
776 370
777 - $request_ids = $this->get_request_ids( $data['payload'] );
371 + $result = $app->get_custom_code( $data['prompt'], $data['language'], $context );
372 + if ( is_wp_error( $result ) ) {
373 + throw new \Exception( $result->get_error_message() );
374 + }
778 375
779 - $result = $app->get_custom_code( $data, $context, $request_ids );
780 - $this->throw_on_error( $result );
781 -
782 376 return [
783 377 'text' => $result['text'],
784 378 'response_id' => $result['responseId'],
785 379 'usage' => $result['usage'],
@@ -790,17 +384,17 @@
790 384 $this->verify_permissions( $data['editor_post_id'] );
791 385
792 386 $app = $this->get_ai_app();
793 387
794 - if ( empty( $data['payload']['prompt'] ) ) {
388 + if ( empty( $data['prompt'] ) ) {
795 389 throw new \Exception( 'Missing prompt' );
796 390 }
797 391
798 - if ( empty( $data['payload']['html_markup'] ) ) {
392 + if ( empty( $data['html_markup'] ) ) {
799 393 $data['html_markup'] = '';
800 394 }
801 395
802 - if ( empty( $data['payload']['element_id'] ) ) {
396 + if ( empty( $data['element_id'] ) ) {
803 397 throw new \Exception( 'Missing element_id' );
804 398 }
805 399
806 400 if ( ! $app->is_connected() ) {
@@ -807,12 +401,13 @@
807 401 throw new \Exception( 'not_connected' );
808 402 }
809 403
810 404 $context = $this->get_request_context( $data );
811 - $request_ids = $this->get_request_ids( $data['payload'] );
812 405
813 - $result = $app->get_custom_css( $data, $context, $request_ids );
814 - $this->throw_on_error( $result );
406 + $result = $app->get_custom_css( $data['prompt'], $data['html_markup'], $data['element_id'], $context );
407 + if ( is_wp_error( $result ) ) {
408 + throw new \Exception( $result->get_error_message() );
409 + }
815 410
816 411 return [
817 412 'text' => $result['text'],
818 413 'response_id' => $result['responseId'],
@@ -846,11 +441,11 @@
846 441 return [];
847 442 }
848 443
849 444 public function ajax_ai_get_text_to_image( $data ) {
850 - $this->verify_upload_permissions( $data );
445 + $this->verify_permissions( $data['editor_post_id'] );
851 446
852 - if ( empty( $data['payload']['prompt'] ) ) {
447 + if ( empty( $data['prompt'] ) ) {
853 448 throw new \Exception( 'Missing prompt' );
854 449 }
855 450
856 451 $app = $this->get_ai_app();
@@ -859,13 +454,14 @@
859 454 throw new \Exception( 'not_connected' );
860 455 }
861 456
862 457 $context = $this->get_request_context( $data );
863 - $request_ids = $this->get_request_ids( $data['payload'] );
864 458
865 - $result = $app->get_text_to_image( $data, $context, $request_ids );
459 + $result = $app->get_text_to_image( $data['prompt'], $data['promptSettings'], $context );
866 460
867 - $this->throw_on_error( $result );
461 + if ( is_wp_error( $result ) ) {
462 + throw new \Exception( $result->get_error_message() );
463 + }
868 464
869 465 return [
870 466 'images' => $result['images'],
871 467 'response_id' => $result['responseId'],
@@ -873,17 +469,21 @@
873 469 ];
874 470 }
875 471
876 472 public function ajax_ai_get_image_to_image( $data ) {
877 - $this->verify_upload_permissions( $data );
473 + $this->verify_permissions( $data['editor_post_id'] );
878 474
879 475 $app = $this->get_ai_app();
880 476
881 - if ( empty( $data['payload']['image'] ) || empty( $data['payload']['image']['id'] ) ) {
477 + if ( empty( $data['prompt'] ) ) {
478 + throw new \Exception( 'Missing prompt' );
479 + }
480 +
481 + if ( empty( $data['image'] ) || empty( $data['image']['id'] ) ) {
882 482 throw new \Exception( 'Missing Image' );
883 483 }
884 484
885 - if ( empty( $data['payload']['settings'] ) ) {
485 + if ( empty( $data['promptSettings'] ) ) {
886 486 throw new \Exception( 'Missing prompt settings' );
887 487 }
888 488
889 489 if ( ! $app->is_connected() ) {
@@ -890,17 +490,18 @@
890 490 throw new \Exception( 'not_connected' );
891 491 }
892 492
893 493 $context = $this->get_request_context( $data );
894 - $request_ids = $this->get_request_ids( $data['payload'] );
895 494
896 495 $result = $app->get_image_to_image( [
897 - 'prompt' => $data['payload']['prompt'],
898 - 'promptSettings' => $data['payload']['settings'],
899 - 'attachment_id' => $data['payload']['image']['id'],
900 - ], $context, $request_ids );
496 + 'prompt' => $data['prompt'],
497 + 'promptSettings' => $data['promptSettings'],
498 + 'attachment_id' => $data['image']['id'],
499 + ], $context );
901 500
902 - $this->throw_on_error( $result );
501 + if ( is_wp_error( $result ) ) {
502 + throw new \Exception( $result->get_error_message() );
503 + }
903 504
904 505 return [
905 506 'images' => $result['images'],
906 507 'response_id' => $result['responseId'],
@@ -908,17 +509,17 @@
908 509 ];
909 510 }
910 511
911 512 public function ajax_ai_get_image_to_image_upscale( $data ) {
912 - $this->verify_upload_permissions( $data );
513 + $this->verify_permissions( $data['editor_post_id'] );
913 514
914 515 $app = $this->get_ai_app();
915 516
916 - if ( empty( $data['payload']['image'] ) || empty( $data['payload']['image']['id'] ) ) {
517 + if ( empty( $data['image'] ) || empty( $data['image']['id'] ) ) {
917 518 throw new \Exception( 'Missing Image' );
918 519 }
919 520
920 - if ( empty( $data['payload']['promptSettings'] ) ) {
521 + if ( empty( $data['promptSettings'] ) ) {
921 522 throw new \Exception( 'Missing prompt settings' );
922 523 }
923 524
924 525 if ( ! $app->is_connected() ) {
@@ -925,16 +526,17 @@
925 526 throw new \Exception( 'not_connected' );
926 527 }
927 528
928 529 $context = $this->get_request_context( $data );
929 - $request_ids = $this->get_request_ids( $data['payload'] );
930 530
931 531 $result = $app->get_image_to_image_upscale( [
932 - 'promptSettings' => $data['payload']['promptSettings'],
933 - 'attachment_id' => $data['payload']['image']['id'],
934 - ], $context, $request_ids );
532 + 'promptSettings' => $data['promptSettings'],
533 + 'attachment_id' => $data['image']['id'],
534 + ], $context );
935 535
936 - $this->throw_on_error( $result );
536 + if ( is_wp_error( $result ) ) {
537 + throw new \Exception( $result->get_error_message() );
538 + }
937 539
938 540 return [
939 541 'images' => $result['images'],
940 542 'response_id' => $result['responseId'],
@@ -942,17 +544,17 @@
942 544 ];
943 545 }
944 546
945 547 public function ajax_ai_get_image_to_image_replace_background( $data ) {
946 - $this->verify_upload_permissions( $data );
548 + $this->verify_permissions( $data['editor_post_id'] );
947 549
948 550 $app = $this->get_ai_app();
949 551
950 - if ( empty( $data['payload']['image'] ) || empty( $data['payload']['image']['id'] ) ) {
552 + if ( empty( $data['image'] ) || empty( $data['image']['id'] ) ) {
951 553 throw new \Exception( 'Missing Image' );
952 554 }
953 555
954 - if ( empty( $data['payload']['prompt'] ) ) {
556 + if ( empty( $data['prompt'] ) ) {
955 557 throw new \Exception( 'Prompt Missing' );
956 558 }
957 559
958 560 if ( ! $app->is_connected() ) {
@@ -959,16 +561,17 @@
959 561 throw new \Exception( 'not_connected' );
960 562 }
961 563
962 564 $context = $this->get_request_context( $data );
963 - $request_ids = $this->get_request_ids( $data['payload'] );
964 565
965 566 $result = $app->get_image_to_image_replace_background( [
966 - 'attachment_id' => $data['payload']['image']['id'],
967 - 'prompt' => $data['payload']['prompt'],
968 - ], $context, $request_ids );
567 + 'attachment_id' => $data['image']['id'],
568 + 'prompt' => $data['prompt'],
569 + ], $context );
969 570
970 - $this->throw_on_error( $result );
571 + if ( is_wp_error( $result ) ) {
572 + throw new \Exception( $result->get_error_message() );
573 + }
971 574
972 575 return [
973 576 'images' => $result['images'],
974 577 'response_id' => $result['responseId'],
@@ -976,13 +579,13 @@
976 579 ];
977 580 }
978 581
979 582 public function ajax_ai_get_image_to_image_remove_background( $data ) {
980 - $this->verify_upload_permissions( $data );
583 + $this->verify_permissions( $data['editor_post_id'] );
981 584
982 585 $app = $this->get_ai_app();
983 586
984 - if ( empty( $data['payload']['image'] ) || empty( $data['payload']['image']['id'] ) ) {
587 + if ( empty( $data['image'] ) || empty( $data['image']['id'] ) ) {
985 588 throw new \Exception( 'Missing Image' );
986 589 }
987 590
988 591 if ( ! $app->is_connected() ) {
@@ -989,14 +592,16 @@
989 592 throw new \Exception( 'not_connected' );
990 593 }
991 594
992 595 $context = $this->get_request_context( $data );
993 - $request_ids = $this->get_request_ids( $data['payload'] );
596 +
994 597 $result = $app->get_image_to_image_remove_background( [
995 - 'attachment_id' => $data['payload']['image']['id'],
996 - ], $context, $request_ids );
598 + 'attachment_id' => $data['image']['id'],
599 + ], $context );
997 600
998 - $this->throw_on_error( $result );
601 + if ( is_wp_error( $result ) ) {
602 + throw new \Exception( $result->get_error_message() );
603 + }
999 604
1000 605 return [
1001 606 'images' => $result['images'],
1002 607 'response_id' => $result['responseId'],
@@ -1004,75 +609,44 @@
1004 609 ];
1005 610 }
1006 611
1007 612 public function ajax_ai_get_image_to_image_mask( $data ) {
1008 - $this->verify_upload_permissions( $data );
613 + $this->verify_permissions( $data['editor_post_id'] );
1009 614
1010 615 $app = $this->get_ai_app();
1011 616
1012 - if ( empty( $data['payload']['prompt'] ) ) {
617 + if ( empty( $data['prompt'] ) ) {
1013 618 throw new \Exception( 'Missing prompt' );
1014 619 }
1015 620
1016 - if ( empty( $data['payload']['image'] ) || empty( $data['payload']['image']['id'] ) ) {
621 + if ( empty( $data['image'] ) || empty( $data['image']['id'] ) ) {
1017 622 throw new \Exception( 'Missing Image' );
1018 623 }
1019 624
1020 - if ( empty( $data['payload']['settings'] ) ) {
625 + if ( empty( $data['promptSettings'] ) ) {
1021 626 throw new \Exception( 'Missing prompt settings' );
1022 627 }
1023 628
1024 - if ( empty( $data['payload']['mask'] ) ) {
1025 - throw new \Exception( 'Missing Mask' );
1026 - }
1027 -
1028 - $context = $this->get_request_context( $data );
1029 - $request_ids = $this->get_request_ids( $data['payload'] );
1030 -
1031 - $result = $app->get_image_to_image_mask( [
1032 - 'prompt' => $data['payload']['prompt'],
1033 - 'attachment_id' => $data['payload']['image']['id'],
1034 - 'mask' => $data['payload']['mask'],
1035 - ], $context, $request_ids );
1036 -
1037 - $this->throw_on_error( $result );
1038 -
1039 - return [
1040 - 'images' => $result['images'],
1041 - 'response_id' => $result['responseId'],
1042 - 'usage' => $result['usage'],
1043 - ];
1044 - }
1045 - public function ajax_ai_get_image_to_image_mask_cleanup( $data ) {
1046 - $this->verify_upload_permissions( $data );
1047 -
1048 - $app = $this->get_ai_app();
1049 -
1050 - if ( empty( $data['payload']['image'] ) || empty( $data['payload']['image']['id'] ) ) {
1051 - throw new \Exception( 'Missing Image' );
1052 - }
1053 -
1054 - if ( empty( $data['payload']['settings'] ) ) {
1055 - throw new \Exception( 'Missing prompt settings' );
1056 - }
1057 -
1058 629 if ( ! $app->is_connected() ) {
1059 630 throw new \Exception( 'not_connected' );
1060 631 }
1061 632
1062 - if ( empty( $data['payload']['mask'] ) ) {
633 + if ( empty( $data['mask'] ) ) {
1063 634 throw new \Exception( 'Missing Mask' );
1064 635 }
1065 636
1066 637 $context = $this->get_request_context( $data );
1067 - $request_ids = $this->get_request_ids( $data['payload'] );
1068 638
1069 - $result = $app->get_image_to_image_mask_cleanup( [
1070 - 'attachment_id' => $data['payload']['image']['id'],
1071 - 'mask' => $data['payload']['mask'],
1072 - ], $context, $request_ids );
639 + $result = $app->get_image_to_image_mask( [
640 + 'prompt' => $data['prompt'],
641 + 'promptSettings' => $data['promptSettings'],
642 + 'attachment_id' => $data['image']['id'],
643 + 'mask' => $data['mask'],
644 + ], $context );
1073 645
1074 - $this->throw_on_error( $result );
646 + if ( is_wp_error( $result ) ) {
647 + throw new \Exception( $result->get_error_message() );
648 + }
1075 649
1076 650 return [
1077 651 'images' => $result['images'],
1078 652 'response_id' => $result['responseId'],
@@ -1078,32 +652,35 @@
1078 652 'response_id' => $result['responseId'],
1079 653 'usage' => $result['usage'],
1080 654 ];
1081 655 }
1082 -
1083 656 public function ajax_ai_get_image_to_image_outpainting( $data ) {
1084 - $this->verify_upload_permissions( $data );
657 + $this->verify_permissions( $data['editor_post_id'] );
1085 658
1086 659 $app = $this->get_ai_app();
1087 660
661 + if ( empty( $data['prompt'] ) ) {
662 + throw new \Exception( 'Missing prompt' );
663 + }
664 +
1088 665 if ( ! $app->is_connected() ) {
1089 666 throw new \Exception( 'not_connected' );
1090 667 }
1091 668
1092 - if ( empty( $data['payload']['mask'] ) ) {
669 + if ( empty( $data['mask'] ) ) {
1093 670 throw new \Exception( 'Missing Expended Image' );
1094 671 }
1095 672
1096 673 $context = $this->get_request_context( $data );
1097 - $request_ids = $this->get_request_ids( $data['payload'] );
674 +
1098 675 $result = $app->get_image_to_image_out_painting( [
1099 - 'size' => $data['payload']['size'],
1100 - 'position' => $data['payload']['position'],
1101 - 'mask' => $data['payload']['mask'],
1102 - 'image_base64' => $data['payload']['image_base64'],
1103 - ], $context, $request_ids );
676 + 'prompt' => $data['prompt'],
677 + 'mask' => $data['mask'],
678 + ], $context );
1104 679
1105 - $this->throw_on_error( $result );
680 + if ( is_wp_error( $result ) ) {
681 + throw new \Exception( $result->get_error_message() );
682 + }
1106 683
1107 684 return [
1108 685 'images' => $result['images'],
1109 686 'response_id' => $result['responseId'],
@@ -1111,10 +688,8 @@
1111 688 ];
1112 689 }
1113 690
1114 691 public function ajax_ai_upload_image( $data ) {
1115 - $this->verify_upload_permissions( $data );
1116 -
1117 692 if ( empty( $data['image'] ) ) {
1118 693 throw new \Exception( 'Missing image data' );
1119 694 }
1120 695
@@ -1126,14 +701,14 @@
1126 701
1127 702 $image_data = $this->upload_image( $image['image_url'], $data['prompt'], $data['editor_post_id'] );
1128 703
1129 704 if ( is_wp_error( $image_data ) ) {
1130 - throw new \Exception( esc_html( $image_data->get_error_message() ) );
705 + throw new \Exception( $image_data->get_error_message() );
1131 706 }
1132 707
1133 708 if ( ! empty( $image['use_gallery_image'] ) && ! empty( $image['id'] ) ) {
1134 - $app = $this->get_ai_app();
1135 - $app->set_used_gallery_image( $image['id'] );
709 + $app = $this->get_ai_app();
710 + $app->set_used_gallery_image( $image['id'] );
1136 711 }
1137 712
1138 713 return [
1139 714 'image' => array_merge( $image_data, $data ),
@@ -1154,9 +729,9 @@
1154 729 }
1155 730
1156 731 $result = $app->generate_layout(
1157 732 $data,
1158 - $this->prepare_generate_layout_context( $data )
733 + $this->prepare_generate_layout_context()
1159 734 );
1160 735
1161 736 if ( is_wp_error( $result ) ) {
1162 737 $message = $result->get_error_message();
@@ -1162,12 +737,11 @@
1162 737 $message = $result->get_error_message();
1163 738
1164 739 if ( is_array( $message ) ) {
1165 740 $message = implode( ', ', $message );
1166 - throw new \Exception( esc_html( $message ) );
1167 741 }
1168 742
1169 - $this->throw_on_error( $result );
743 + throw new \Exception( $message );
1170 744 }
1171 745
1172 746 $elements = $result['text']['elements'] ?? [];
1173 747 $base_template_id = $result['baseTemplateId'] ?? null;
@@ -1227,12 +801,14 @@
1227 801
1228 802 $result = $app->get_layout_prompt_enhanced(
1229 803 $data['prompt'],
1230 804 $data['enhance_type'],
1231 - $this->prepare_generate_layout_context( $data )
805 + $this->prepare_generate_layout_context()
1232 806 );
1233 807
1234 - $this->throw_on_error( $result );
808 + if ( is_wp_error( $result ) ) {
809 + throw new \Exception( $result->get_error_message() );
810 + }
1235 811
1236 812 return [
1237 813 'text' => $result['text'] ?? $data['prompt'],
1238 814 'response_id' => $result['responseId'] ?? '',
@@ -1239,14 +815,13 @@
1239 815 'usage' => $result['usage'] ?? '',
1240 816 ];
1241 817 }
1242 818
1243 - private function prepare_generate_layout_context( $data ) {
1244 - $request_context = $this->get_request_context( $data );
819 + private function prepare_generate_layout_context() {
1245 820 $kit = Plugin::$instance->kits_manager->get_active_kit();
1246 821
1247 822 if ( ! $kit ) {
1248 - return $request_context;
823 + return [];
1249 824 }
1250 825
1251 826 $kits_data = Collection::make( $kit->get_data()['settings'] ?? [] );
1252 827
@@ -1299,14 +874,14 @@
1299 874 ],
1300 875 ];
1301 876 } );
1302 877
1303 - $request_context['globals'] = [
1304 - 'colors' => $colors->all(),
1305 - 'typography' => $typography->all(),
878 + return [
879 + 'globals' => [
880 + 'colors' => $colors->all(),
881 + 'typography' => $typography->all(),
882 + ],
1306 883 ];
1307 -
1308 - return $request_context;
1309 884 }
1310 885
1311 886 private function upload_image( $image_url, $image_title, $parent_post_id = 0 ) {
1312 887 if ( ! current_user_can( 'upload_files' ) ) {
@@ -1312,24 +887,10 @@
1312 887 if ( ! current_user_can( 'upload_files' ) ) {
1313 888 throw new \Exception( 'Not Allowed to Upload images' );
1314 889 }
1315 890
1316 - $uploads_manager = new \Elementor\Core\Files\Uploads_Manager();
1317 - if ( $uploads_manager::are_unfiltered_uploads_enabled() ) {
1318 - Plugin::$instance->uploads_manager->set_elementor_upload_state( true );
1319 - add_filter( 'wp_handle_sideload_prefilter', [ Plugin::$instance->uploads_manager, 'handle_elementor_upload' ] );
1320 - add_filter( 'image_sideload_extensions', function( $extensions ) {
1321 - $extensions[] = 'svg';
1322 - return $extensions;
1323 - });
1324 - }
1325 -
1326 891 $attachment_id = media_sideload_image( $image_url, $parent_post_id, $image_title, 'id' );
1327 892
1328 - if ( is_wp_error( $attachment_id ) ) {
1329 - return new \WP_Error( 'upload_error', $attachment_id->get_error_message() );
1330 - }
1331 -
1332 893 if ( ! empty( $attachment_id['error'] ) ) {
1333 894 return new \WP_Error( 'upload_error', $attachment_id['error'] );
1334 895 }
1335 896
@@ -1334,10 +895,10 @@
1334 895 }
1335 896
1336 897 return [
1337 898 'id' => $attachment_id,
1338 - 'url' => esc_url( wp_get_attachment_image_url( $attachment_id, 'full' ) ),
1339 - 'alt' => esc_attr( $image_title ),
899 + 'url' => wp_get_attachment_image_url( $attachment_id, 'full' ),
900 + 'alt' => $image_title,
1340 901 'source' => 'library',
1341 902 ];
1342 903 }
1343 904
@@ -1361,9 +922,9 @@
1361 922
1362 923 $result = $app->get_history_by_type( $type, $page, $limit, $context );
1363 924
1364 925 if ( is_wp_error( $result ) ) {
1365 - throw new \Exception( esc_html( $result->get_error_message() ) );
926 + throw new \Exception( $result->get_error_message() );
1366 927 }
1367 928
1368 929 return $result;
1369 930 }
@@ -1383,9 +944,9 @@
1383 944
1384 945 $result = $app->delete_history_item( $data['id'], $context );
1385 946
1386 947 if ( is_wp_error( $result ) ) {
1387 - throw new \Exception( esc_html( $result->get_error_message() ) );
948 + throw new \Exception( $result->get_error_message() );
1388 949 }
1389 950
1390 951 return [];
1391 952 }
@@ -1405,193 +966,10 @@
1405 966
1406 967 $result = $app->toggle_favorite_history_item( $data['id'], $context );
1407 968
1408 969 if ( is_wp_error( $result ) ) {
1409 - throw new \Exception( esc_html( $result->get_error_message() ) );
970 + throw new \Exception( $result->get_error_message() );
1410 971 }
1411 972
1412 973 return [];
1413 - }
1414 -
1415 - public function ajax_ai_get_product_image_unification( $data ): array {
1416 - if ( ! empty( $data['payload']['postId'] ) ) {
1417 - $data['editor_post_id'] = $data['payload']['postId'];
1418 - }
1419 - $this->verify_upload_permissions( $data );
1420 -
1421 - $app = $this->get_ai_app();
1422 -
1423 - if ( empty( $data['payload']['image'] ) || empty( $data['payload']['image']['id'] ) ) {
1424 - throw new \Exception( 'Missing Image' );
1425 - }
1426 -
1427 - if ( empty( $data['payload']['settings'] ) ) {
1428 - throw new \Exception( 'Missing prompt settings' );
1429 - }
1430 -
1431 - if ( ! $app->is_connected() ) {
1432 - throw new \Exception( 'not_connected' );
1433 - }
1434 -
1435 - $context = $this->get_request_context( $data );
1436 - $request_ids = $this->get_request_ids( $data['payload'] );
1437 -
1438 - $result = $app->get_unify_product_images( [
1439 - 'promptSettings' => $data['payload']['settings'],
1440 - 'attachment_id' => $data['payload']['image']['id'],
1441 - 'featureIdentifier' => $data['payload']['featureIdentifier'] ?? '',
1442 - ], $context, $request_ids );
1443 -
1444 - $this->throw_on_error( $result );
1445 -
1446 - return [
1447 - 'images' => $result['images'],
1448 - 'response_id' => $result['responseId'],
1449 - 'usage' => $result['usage'],
1450 - ];
1451 - }
1452 -
1453 - public function ajax_ai_get_animation( $data ): array {
1454 - $this->verify_upload_permissions( $data );
1455 -
1456 - $app = $this->get_ai_app();
1457 -
1458 - if ( empty( $data['payload']['prompt'] ) ) {
1459 - throw new \Exception( 'Missing prompt' );
1460 - }
1461 -
1462 - if ( empty( $data['payload']['motionEffectType'] ) ) {
1463 - throw new \Exception( 'Missing animation type' );
1464 - }
1465 -
1466 - if ( ! $app->is_connected() ) {
1467 - throw new \Exception( 'not_connected' );
1468 - }
1469 -
1470 - $context = $this->get_request_context( $data );
1471 -
1472 - $request_ids = $this->get_request_ids( $data['payload'] );
1473 -
1474 - $result = $app->get_animation( $data, $context, $request_ids );
1475 - $this->throw_on_error( $result );
1476 -
1477 - return [
1478 - 'text' => $result['text'],
1479 - 'response_id' => $result['responseId'],
1480 - 'usage' => $result['usage'],
1481 - ];
1482 - }
1483 -
1484 - /**
1485 - * @param mixed $result
1486 - */
1487 - private function throw_on_error( $result ): void {
1488 - if ( is_wp_error( $result ) ) {
1489 - wp_send_json_error( [
1490 - 'message' => esc_html( $result->get_error_message() ),
1491 - 'extra_data' => $result->get_error_data(),
1492 - ] );
1493 - }
1494 - }
1495 -
1496 - /**
1497 - * @return void
1498 - */
1499 - public function add_wc_scripts(): void {
1500 - wp_enqueue_script( 'elementor-ai-unify-product-images',
1501 - $this->get_js_assets_url( 'ai-unify-product-images' ),
1502 - [
1503 - 'jquery',
1504 - 'elementor-v2-ui',
1505 - 'elementor-v2-icons',
1506 - 'wp-components',
1507 - 'elementor-common',
1508 - ],
1509 - ELEMENTOR_VERSION,
1510 - true
1511 - );
1512 -
1513 - wp_localize_script(
1514 - 'elementor-ai-unify-product-images',
1515 - 'UnifyProductImagesConfig',
1516 - [
1517 - 'get_product_images_url' => admin_url( 'admin-ajax.php' ),
1518 - 'set_product_images_url' => admin_url( 'admin-ajax.php' ),
1519 - 'nonce' => wp_create_nonce( 'elementor-ai-unify-product-images_nonce' ),
1520 - 'placeholder' => ELEMENTOR_ASSETS_URL . 'images/app/ai/product-image-unification-example.gif?' . ELEMENTOR_VERSION,
1521 - 'is_get_started' => User::get_introduction_meta( 'ai_get_started' ),
1522 - 'connect_url' => $this->get_ai_connect_url(),
1523 - ]
1524 - );
1525 -
1526 - add_filter( 'bulk_actions-edit-product', function ( $data ) {
1527 - return $this->add_products_bulk_action( $data );
1528 - });
1529 -
1530 - wp_set_script_translations( 'elementor-ai-unify-product-images', 'elementor' );
1531 - }
1532 -
1533 - /**
1534 - * @param $product
1535 - * @param int|null $image_to_remove
1536 - * @param int|null $image_to_add
1537 - * @return void
1538 - */
1539 - private function update_product_gallery( $product, ?int $image_to_remove, ?int $image_to_add ): void {
1540 - $gallery_image_ids = $product->get_gallery_image_ids();
1541 -
1542 - $index = array_search( $image_to_remove, $gallery_image_ids, true );
1543 - if ( false !== $index ) {
1544 - unset( $gallery_image_ids[ $index ] );
1545 - }
1546 -
1547 - if ( ! in_array( $image_to_add, $gallery_image_ids, true ) ) {
1548 - $gallery_image_ids[] = $image_to_add;
1549 - }
1550 -
1551 - $product->set_gallery_image_ids( $gallery_image_ids );
1552 - $product->save();
1553 - }
1554 -
1555 - private function should_display_create_with_ai_banner() {
1556 - $elementor_pages = new \WP_Query( [
1557 - 'post_type' => 'page',
1558 - 'post_status' => 'publish',
1559 - 'fields' => 'ids',
1560 - 'posts_per_page' => self::MIN_PAGES_FOR_CREATE_WITH_AI_BANNER + 1,
1561 - ] );
1562 -
1563 - if ( $elementor_pages->post_count > self::MIN_PAGES_FOR_CREATE_WITH_AI_BANNER ) {
1564 - return false;
1565 - }
1566 -
1567 - if ( Utils::is_custom_kit_applied() ) {
1568 - return false;
1569 - }
1570 -
1571 - return true;
1572 - }
1573 -
1574 - private function get_create_with_ai_banner_data() {
1575 - return [
1576 - 'title' => 'Create and launch your site faster with AI',
1577 - 'description' => 'Share your vision with our AI Chat and watch as it becomes a brief, sitemap, and wireframes in minutes:',
1578 - 'input_placeholder' => 'Start describing the site you want to create...',
1579 - 'button_title' => 'Create with AI',
1580 - 'button_cta_url' => 'http://planner.elementor.com/chat.html',
1581 - 'background_image' => ELEMENTOR_ASSETS_URL . 'images/app/ai/ai-site-creator-homepage-bg.svg',
1582 - 'utm_source' => 'editor-home',
1583 - 'utm_medium' => 'wp-dash',
1584 - 'utm_campaign' => 'generate-with-ai',
1585 - ];
1586 - }
1587 -
1588 - public function add_create_with_ai_banner_to_homescreen( $home_screen_data ) {
1589 - if ( $this->should_display_create_with_ai_banner() ) {
1590 - $home_screen_data['create_with_ai'] = $this->get_create_with_ai_banner_data();
1591 - } else {
1592 - $home_screen_data['create_with_ai'] = null;
1593 - }
1594 -
1595 - return $home_screen_data;
1596 974 }
1597 975 }