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