PluginProbe
Elementor Website Builder – more than just a page builder / 3.19.0-beta5
Elementor Website Builder – more than just a page builder v3.19.0-beta5
4.3.4 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 All 457 releases
← All changes | modules/ai/module.php +189 -733 4.3.4 → 3.19.0-beta5 View file →
@@ -1,14 +1,13 @@
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 11 use Elementor\Utils;
13 12
14 13 if ( ! defined( 'ABSPATH' ) ) {
@@ -27,8 +26,11 @@
27 26 self::HISTORY_TYPE_CODE,
28 27 self::HISTORY_TYPE_IMAGE,
29 28 self::HISTORY_TYPE_BLOCK,
30 29 ];
30 +
31 + const LAYOUT_EXPERIMENT = 'ai-layout';
32 +
31 33 public function get_name() {
32 34 return 'ai';
33 35 }
34 36
@@ -34,19 +36,10 @@
34 36
35 37 public function __construct() {
36 38 parent::__construct();
37 39
38 - ( new SitePlannerConnect\Module() );
40 + $this->register_layout_experiment();
39 41
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 42 add_action( 'elementor/connect/apps/register', function ( ConnectModule $connect_module ) {
50 43 $connect_module->register_app( 'ai', Ai::get_class_name() );
51 44 } );
52 45
@@ -53,12 +46,9 @@
53 46 add_action( 'elementor/ajax/register_actions', function( $ajax ) {
54 47 $handlers = [
55 48 'ai_get_user_information' => [ $this, 'ajax_ai_get_user_information' ],
56 49 'ai_get_remote_config' => [ $this, 'ajax_ai_get_remote_config' ],
57 - 'ai_get_remote_frontend_config' => [ $this, 'ajax_ai_get_remote_frontend_config' ],
58 50 '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 51 'ai_get_edit_text' => [ $this, 'ajax_ai_get_edit_text' ],
62 52 'ai_get_custom_code' => [ $this, 'ajax_ai_get_custom_code' ],
63 53 'ai_get_custom_css' => [ $this, 'ajax_ai_get_custom_css' ],
64 54 'ai_set_get_started' => [ $this, 'ajax_ai_set_get_started' ],
@@ -66,9 +56,8 @@
66 56 'ai_get_image_prompt_enhancer' => [ $this, 'ajax_ai_get_image_prompt_enhancer' ],
67 57 'ai_get_text_to_image' => [ $this, 'ajax_ai_get_text_to_image' ],
68 58 'ai_get_image_to_image' => [ $this, 'ajax_ai_get_image_to_image' ],
69 59 '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 60 'ai_get_image_to_image_outpainting' => [ $this, 'ajax_ai_get_image_to_image_outpainting' ],
72 61 'ai_get_image_to_image_upscale' => [ $this, 'ajax_ai_get_image_to_image_upscale' ],
73 62 'ai_get_image_to_image_remove_background' => [ $this, 'ajax_ai_get_image_to_image_remove_background' ],
74 63 'ai_get_image_to_image_replace_background' => [ $this, 'ajax_ai_get_image_to_image_replace_background' ],
@@ -77,11 +66,8 @@
77 66 'ai_get_layout_prompt_enhancer' => [ $this, 'ajax_ai_get_layout_prompt_enhancer' ],
78 67 'ai_get_history' => [ $this, 'ajax_ai_get_history' ],
79 68 'ai_delete_history_item' => [ $this, 'ajax_ai_delete_history_item' ],
80 69 '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 70 ];
85 71
86 72 foreach ( $handlers as $tag => $callback ) {
87 73 $ajax->register_ajax_action( $tag, $callback );
@@ -89,9 +75,12 @@
89 75 } );
90 76
91 77 add_action( 'elementor/editor/before_enqueue_scripts', function() {
92 78 $this->enqueue_main_script();
93 - $this->enqueue_layout_script();
79 +
80 + if ( $this->is_layout_active() ) {
81 + $this->enqueue_layout_script();
82 + }
94 83 } );
95 84
96 85 add_action( 'elementor/editor/after_enqueue_styles', function() {
97 86 wp_enqueue_style(
@@ -102,351 +91,40 @@
102 91 );
103 92 } );
104 93
105 94 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 - );
95 + if ( $this->is_layout_active() ) {
96 + wp_enqueue_style(
97 + 'elementor-ai-layout-preview',
98 + $this->get_css_assets_url( 'modules/ai/layout-preview' ),
99 + [],
100 + ELEMENTOR_VERSION
101 + );
102 + }
112 103 } );
113 104
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' ] );
105 + add_filter( 'elementor/document/save/data', function ( $data ) {
106 + if ( $this->is_layout_active() ) {
107 + return $this->remove_temporary_containers( $data );
123 108 }
124 - }
125 109
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 );
110 + return $data;
159 111 } );
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 112 }
166 113
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'],
114 + private function register_layout_experiment() {
115 + Plugin::$instance->experiments->add_feature( [
116 + 'name' => static::LAYOUT_EXPERIMENT,
117 + 'title' => esc_html__( 'Build with AI', 'elementor' ),
118 + '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' ),
119 + 'default' => Experiments_Manager::STATE_ACTIVE,
120 + 'release_status' => Experiments_Manager::RELEASE_STATUS_BETA,
121 + 'dependencies' => [
122 + 'container',
208 123 ],
209 124 ] );
210 125 }
211 126
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 127 private function enqueue_main_script() {
450 128 wp_enqueue_script(
451 129 'elementor-ai',
452 130 $this->get_js_assets_url( 'ai' ),
@@ -470,8 +148,13 @@
470 148 'is_get_started' => User::get_introduction_meta( 'ai_get_started' ),
471 149 'connect_url' => $this->get_ai_connect_url(),
472 150 ];
473 151
152 + if ( $this->get_ai_app()->is_connected() ) {
153 + // Use a cached version, don't call the API on every editor load.
154 + $config['usage'] = $this->get_ai_app()->get_cached_usage();
155 + }
156 +
474 157 wp_localize_script(
475 158 'elementor-ai',
476 159 'ElementorAiConfig',
477 160 $config
@@ -477,8 +160,31 @@
477 160 $config
478 161 );
479 162
480 163 wp_set_script_translations( 'elementor-ai', 'elementor' );
164 +
165 + if ( $this->get_ai_app()->is_connected() && ! empty( $config['is_get_started'] ) ) {
166 + $remote_config = Utils::get_cached_callback( [ $this->get_ai_app(), 'get_remote_config' ], 'ai_remote_config' );
167 +
168 + if ( ! is_wp_error( $remote_config ) && ! empty( $remote_config['config']['remoteIntegrationUrl'] ) ) {
169 + wp_enqueue_scripts(
170 + 'elementor-ai-integration',
171 + $remote_config['config']['remoteIntegrationUrl'],
172 + [
173 + 'elementor-editor',
174 + ],
175 + ELEMENTOR_VERSION,
176 + true
177 + );
178 + }
179 +
180 + add_filter( 'script_loader_tag', function( $tag, $handle ) {
181 + if ( 'elementor-ai-integration' === $handle ) {
182 + return str_replace( ' src', ' type="module" src', $tag );
183 + }
184 + return $tag;
185 + }, 10, 2 );
186 + }
481 187 }
482 188
483 189 private function enqueue_layout_script() {
484 190 wp_enqueue_script(
@@ -501,10 +207,14 @@
501 207
502 208 wp_set_script_translations( 'elementor-ai-layout', 'elementor' );
503 209 }
504 210
211 + private function is_layout_active() {
212 + return Plugin::$instance->experiments->is_feature_active( self::LAYOUT_EXPERIMENT );
213 + }
214 +
505 215 private function remove_temporary_containers( $data ) {
506 - if ( empty( $data['elements'] ) || ! is_array( $data['elements'] ) ) {
216 + if ( empty( $data['elements'] ) ) {
507 217 return $data;
508 218 }
509 219
510 220 // If for some reason the document has been saved during an AI Layout session,
@@ -562,25 +272,8 @@
562 272
563 273 return $app->get_remote_config();
564 274 }
565 275
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 276 private function verify_permissions( $editor_post_id ) {
584 277 $document = Plugin::$instance->documents->get( $editor_post_id );
585 278
586 279 if ( ! $document ) {
@@ -586,19 +279,15 @@
586 279 if ( ! $document ) {
587 280 throw new \Exception( 'Document not found' );
588 281 }
589 282
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' );
283 + if ( ! $document->is_built_with_elementor() || ! $document->is_editable_by_current_user() ) {
284 + throw new \Exception( 'Access denied' );
596 285 }
597 286 }
598 287
599 288 public function ajax_ai_get_image_prompt_enhancer( $data ) {
600 - $this->verify_upload_permissions( $data );
289 + $this->verify_permissions( $data['editor_post_id'] );
601 290
602 291 $app = $this->get_ai_app();
603 292
604 293 if ( empty( $data['prompt'] ) ) {
@@ -607,12 +296,13 @@
607 296
608 297 if ( ! $app->is_connected() ) {
609 298 throw new \Exception( 'not_connected' );
610 299 }
611 - $request_ids = $this->get_request_ids( $data['payload'] );
612 300
613 - $result = $app->get_image_prompt_enhanced( $data['prompt'], [], $request_ids );
614 - $this->throw_on_error( $result );
301 + $result = $app->get_image_prompt_enhanced( $data['prompt'] );
302 + if ( is_wp_error( $result ) ) {
303 + throw new \Exception( $result->get_error_message() );
304 + }
615 305
616 306 return [
617 307 'text' => $result['text'],
618 308 'response_id' => $result['responseId'],
@@ -624,9 +314,9 @@
624 314 $this->verify_permissions( $data['editor_post_id'] );
625 315
626 316 $app = $this->get_ai_app();
627 317
628 - if ( empty( $data['payload']['prompt'] ) ) {
318 + if ( empty( $data['prompt'] ) ) {
629 319 throw new \Exception( 'Missing prompt' );
630 320 }
631 321
632 322 if ( ! $app->is_connected() ) {
@@ -634,39 +324,13 @@
634 324 }
635 325
636 326 $context = $this->get_request_context( $data );
637 327
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' );
328 + $result = $app->get_completion_text( $data['prompt'], $context );
329 + if ( is_wp_error( $result ) ) {
330 + throw new \Exception( $result->get_error_message() );
656 331 }
657 332
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 333 return [
670 334 'text' => $result['text'],
671 335 'response_id' => $result['responseId'],
672 336 'usage' => $result['usage'],
@@ -672,36 +336,9 @@
672 336 'usage' => $result['usage'],
673 337 ];
674 338 }
675 339
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 {
340 + private function get_ai_app() : Ai {
704 341 return Plugin::$instance->common->get_component( 'connect' )->get_app( 'ai' );
705 342 }
706 343
707 344 private function get_request_context( $data ) {
@@ -711,26 +348,18 @@
711 348
712 349 return $data['context'];
713 350 }
714 351
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 352 public function ajax_ai_get_edit_text( $data ) {
724 353 $this->verify_permissions( $data['editor_post_id'] );
725 354
726 355 $app = $this->get_ai_app();
727 356
728 - if ( empty( $data['payload']['input'] ) ) {
357 + if ( empty( $data['input'] ) ) {
729 358 throw new \Exception( 'Missing input' );
730 359 }
731 360
732 - if ( empty( $data['payload']['instruction'] ) ) {
361 + if ( empty( $data['instruction'] ) ) {
733 362 throw new \Exception( 'Missing instruction' );
734 363 }
735 364
736 365 if ( ! $app->is_connected() ) {
@@ -738,13 +367,13 @@
738 367 }
739 368
740 369 $context = $this->get_request_context( $data );
741 370
742 - $request_ids = $this->get_request_ids( $data['payload'] );
371 + $result = $app->get_edit_text( $data['input'], $data['instruction'], $context );
372 + if ( is_wp_error( $result ) ) {
373 + throw new \Exception( $result->get_error_message() );
374 + }
743 375
744 - $result = $app->get_edit_text( $data, $context, $request_ids );
745 - $this->throw_on_error( $result );
746 -
747 376 return [
748 377 'text' => $result['text'],
749 378 'response_id' => $result['responseId'],
750 379 'usage' => $result['usage'],
@@ -753,13 +382,13 @@
753 382
754 383 public function ajax_ai_get_custom_code( $data ) {
755 384 $app = $this->get_ai_app();
756 385
757 - if ( empty( $data['payload']['prompt'] ) ) {
386 + if ( empty( $data['prompt'] ) ) {
758 387 throw new \Exception( 'Missing prompt' );
759 388 }
760 389
761 - if ( empty( $data['payload']['language'] ) ) {
390 + if ( empty( $data['language'] ) ) {
762 391 throw new \Exception( 'Missing language' );
763 392 }
764 393
765 394 if ( ! $app->is_connected() ) {
@@ -767,13 +396,13 @@
767 396 }
768 397
769 398 $context = $this->get_request_context( $data );
770 399
771 - $request_ids = $this->get_request_ids( $data['payload'] );
400 + $result = $app->get_custom_code( $data['prompt'], $data['language'], $context );
401 + if ( is_wp_error( $result ) ) {
402 + throw new \Exception( $result->get_error_message() );
403 + }
772 404
773 - $result = $app->get_custom_code( $data, $context, $request_ids );
774 - $this->throw_on_error( $result );
775 -
776 405 return [
777 406 'text' => $result['text'],
778 407 'response_id' => $result['responseId'],
779 408 'usage' => $result['usage'],
@@ -784,17 +413,17 @@
784 413 $this->verify_permissions( $data['editor_post_id'] );
785 414
786 415 $app = $this->get_ai_app();
787 416
788 - if ( empty( $data['payload']['prompt'] ) ) {
417 + if ( empty( $data['prompt'] ) ) {
789 418 throw new \Exception( 'Missing prompt' );
790 419 }
791 420
792 - if ( empty( $data['payload']['html_markup'] ) ) {
421 + if ( empty( $data['html_markup'] ) ) {
793 422 $data['html_markup'] = '';
794 423 }
795 424
796 - if ( empty( $data['payload']['element_id'] ) ) {
425 + if ( empty( $data['element_id'] ) ) {
797 426 throw new \Exception( 'Missing element_id' );
798 427 }
799 428
800 429 if ( ! $app->is_connected() ) {
@@ -801,12 +430,13 @@
801 430 throw new \Exception( 'not_connected' );
802 431 }
803 432
804 433 $context = $this->get_request_context( $data );
805 - $request_ids = $this->get_request_ids( $data['payload'] );
806 434
807 - $result = $app->get_custom_css( $data, $context, $request_ids );
808 - $this->throw_on_error( $result );
435 + $result = $app->get_custom_css( $data['prompt'], $data['html_markup'], $data['element_id'], $context );
436 + if ( is_wp_error( $result ) ) {
437 + throw new \Exception( $result->get_error_message() );
438 + }
809 439
810 440 return [
811 441 'text' => $result['text'],
812 442 'response_id' => $result['responseId'],
@@ -840,11 +470,11 @@
840 470 return [];
841 471 }
842 472
843 473 public function ajax_ai_get_text_to_image( $data ) {
844 - $this->verify_upload_permissions( $data );
474 + $this->verify_permissions( $data['editor_post_id'] );
845 475
846 - if ( empty( $data['payload']['prompt'] ) ) {
476 + if ( empty( $data['prompt'] ) ) {
847 477 throw new \Exception( 'Missing prompt' );
848 478 }
849 479
850 480 $app = $this->get_ai_app();
@@ -853,13 +483,14 @@
853 483 throw new \Exception( 'not_connected' );
854 484 }
855 485
856 486 $context = $this->get_request_context( $data );
857 - $request_ids = $this->get_request_ids( $data['payload'] );
858 487
859 - $result = $app->get_text_to_image( $data, $context, $request_ids );
488 + $result = $app->get_text_to_image( $data['prompt'], $data['promptSettings'], $context );
860 489
861 - $this->throw_on_error( $result );
490 + if ( is_wp_error( $result ) ) {
491 + throw new \Exception( $result->get_error_message() );
492 + }
862 493
863 494 return [
864 495 'images' => $result['images'],
865 496 'response_id' => $result['responseId'],
@@ -867,17 +498,21 @@
867 498 ];
868 499 }
869 500
870 501 public function ajax_ai_get_image_to_image( $data ) {
871 - $this->verify_upload_permissions( $data );
502 + $this->verify_permissions( $data['editor_post_id'] );
872 503
873 504 $app = $this->get_ai_app();
874 505
875 - if ( empty( $data['payload']['image'] ) || empty( $data['payload']['image']['id'] ) ) {
506 + if ( empty( $data['prompt'] ) ) {
507 + throw new \Exception( 'Missing prompt' );
508 + }
509 +
510 + if ( empty( $data['image'] ) || empty( $data['image']['id'] ) ) {
876 511 throw new \Exception( 'Missing Image' );
877 512 }
878 513
879 - if ( empty( $data['payload']['settings'] ) ) {
514 + if ( empty( $data['promptSettings'] ) ) {
880 515 throw new \Exception( 'Missing prompt settings' );
881 516 }
882 517
883 518 if ( ! $app->is_connected() ) {
@@ -884,17 +519,18 @@
884 519 throw new \Exception( 'not_connected' );
885 520 }
886 521
887 522 $context = $this->get_request_context( $data );
888 - $request_ids = $this->get_request_ids( $data['payload'] );
889 523
890 524 $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 );
525 + 'prompt' => $data['prompt'],
526 + 'promptSettings' => $data['promptSettings'],
527 + 'attachment_id' => $data['image']['id'],
528 + ], $context );
895 529
896 - $this->throw_on_error( $result );
530 + if ( is_wp_error( $result ) ) {
531 + throw new \Exception( $result->get_error_message() );
532 + }
897 533
898 534 return [
899 535 'images' => $result['images'],
900 536 'response_id' => $result['responseId'],
@@ -902,17 +538,17 @@
902 538 ];
903 539 }
904 540
905 541 public function ajax_ai_get_image_to_image_upscale( $data ) {
906 - $this->verify_upload_permissions( $data );
542 + $this->verify_permissions( $data['editor_post_id'] );
907 543
908 544 $app = $this->get_ai_app();
909 545
910 - if ( empty( $data['payload']['image'] ) || empty( $data['payload']['image']['id'] ) ) {
546 + if ( empty( $data['image'] ) || empty( $data['image']['id'] ) ) {
911 547 throw new \Exception( 'Missing Image' );
912 548 }
913 549
914 - if ( empty( $data['payload']['promptSettings'] ) ) {
550 + if ( empty( $data['promptSettings'] ) ) {
915 551 throw new \Exception( 'Missing prompt settings' );
916 552 }
917 553
918 554 if ( ! $app->is_connected() ) {
@@ -919,16 +555,17 @@
919 555 throw new \Exception( 'not_connected' );
920 556 }
921 557
922 558 $context = $this->get_request_context( $data );
923 - $request_ids = $this->get_request_ids( $data['payload'] );
924 559
925 560 $result = $app->get_image_to_image_upscale( [
926 - 'promptSettings' => $data['payload']['promptSettings'],
927 - 'attachment_id' => $data['payload']['image']['id'],
928 - ], $context, $request_ids );
561 + 'promptSettings' => $data['promptSettings'],
562 + 'attachment_id' => $data['image']['id'],
563 + ], $context );
929 564
930 - $this->throw_on_error( $result );
565 + if ( is_wp_error( $result ) ) {
566 + throw new \Exception( $result->get_error_message() );
567 + }
931 568
932 569 return [
933 570 'images' => $result['images'],
934 571 'response_id' => $result['responseId'],
@@ -936,17 +573,17 @@
936 573 ];
937 574 }
938 575
939 576 public function ajax_ai_get_image_to_image_replace_background( $data ) {
940 - $this->verify_upload_permissions( $data );
577 + $this->verify_permissions( $data['editor_post_id'] );
941 578
942 579 $app = $this->get_ai_app();
943 580
944 - if ( empty( $data['payload']['image'] ) || empty( $data['payload']['image']['id'] ) ) {
581 + if ( empty( $data['image'] ) || empty( $data['image']['id'] ) ) {
945 582 throw new \Exception( 'Missing Image' );
946 583 }
947 584
948 - if ( empty( $data['payload']['prompt'] ) ) {
585 + if ( empty( $data['prompt'] ) ) {
949 586 throw new \Exception( 'Prompt Missing' );
950 587 }
951 588
952 589 if ( ! $app->is_connected() ) {
@@ -953,16 +590,17 @@
953 590 throw new \Exception( 'not_connected' );
954 591 }
955 592
956 593 $context = $this->get_request_context( $data );
957 - $request_ids = $this->get_request_ids( $data['payload'] );
958 594
959 595 $result = $app->get_image_to_image_replace_background( [
960 - 'attachment_id' => $data['payload']['image']['id'],
961 - 'prompt' => $data['payload']['prompt'],
962 - ], $context, $request_ids );
596 + 'attachment_id' => $data['image']['id'],
597 + 'prompt' => $data['prompt'],
598 + ], $context );
963 599
964 - $this->throw_on_error( $result );
600 + if ( is_wp_error( $result ) ) {
601 + throw new \Exception( $result->get_error_message() );
602 + }
965 603
966 604 return [
967 605 'images' => $result['images'],
968 606 'response_id' => $result['responseId'],
@@ -970,13 +608,13 @@
970 608 ];
971 609 }
972 610
973 611 public function ajax_ai_get_image_to_image_remove_background( $data ) {
974 - $this->verify_upload_permissions( $data );
612 + $this->verify_permissions( $data['editor_post_id'] );
975 613
976 614 $app = $this->get_ai_app();
977 615
978 - if ( empty( $data['payload']['image'] ) || empty( $data['payload']['image']['id'] ) ) {
616 + if ( empty( $data['image'] ) || empty( $data['image']['id'] ) ) {
979 617 throw new \Exception( 'Missing Image' );
980 618 }
981 619
982 620 if ( ! $app->is_connected() ) {
@@ -983,14 +621,16 @@
983 621 throw new \Exception( 'not_connected' );
984 622 }
985 623
986 624 $context = $this->get_request_context( $data );
987 - $request_ids = $this->get_request_ids( $data['payload'] );
625 +
988 626 $result = $app->get_image_to_image_remove_background( [
989 - 'attachment_id' => $data['payload']['image']['id'],
990 - ], $context, $request_ids );
627 + 'attachment_id' => $data['image']['id'],
628 + ], $context );
991 629
992 - $this->throw_on_error( $result );
630 + if ( is_wp_error( $result ) ) {
631 + throw new \Exception( $result->get_error_message() );
632 + }
993 633
994 634 return [
995 635 'images' => $result['images'],
996 636 'response_id' => $result['responseId'],
@@ -998,75 +638,44 @@
998 638 ];
999 639 }
1000 640
1001 641 public function ajax_ai_get_image_to_image_mask( $data ) {
1002 - $this->verify_upload_permissions( $data );
642 + $this->verify_permissions( $data['editor_post_id'] );
1003 643
1004 644 $app = $this->get_ai_app();
1005 645
1006 - if ( empty( $data['payload']['prompt'] ) ) {
646 + if ( empty( $data['prompt'] ) ) {
1007 647 throw new \Exception( 'Missing prompt' );
1008 648 }
1009 649
1010 - if ( empty( $data['payload']['image'] ) || empty( $data['payload']['image']['id'] ) ) {
650 + if ( empty( $data['image'] ) || empty( $data['image']['id'] ) ) {
1011 651 throw new \Exception( 'Missing Image' );
1012 652 }
1013 653
1014 - if ( empty( $data['payload']['settings'] ) ) {
654 + if ( empty( $data['promptSettings'] ) ) {
1015 655 throw new \Exception( 'Missing prompt settings' );
1016 656 }
1017 657
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 658 if ( ! $app->is_connected() ) {
1053 659 throw new \Exception( 'not_connected' );
1054 660 }
1055 661
1056 - if ( empty( $data['payload']['mask'] ) ) {
662 + if ( empty( $data['mask'] ) ) {
1057 663 throw new \Exception( 'Missing Mask' );
1058 664 }
1059 665
1060 666 $context = $this->get_request_context( $data );
1061 - $request_ids = $this->get_request_ids( $data['payload'] );
1062 667
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 );
668 + $result = $app->get_image_to_image_mask( [
669 + 'prompt' => $data['prompt'],
670 + 'promptSettings' => $data['promptSettings'],
671 + 'attachment_id' => $data['image']['id'],
672 + 'mask' => $data['mask'],
673 + ], $context );
1067 674
1068 - $this->throw_on_error( $result );
675 + if ( is_wp_error( $result ) ) {
676 + throw new \Exception( $result->get_error_message() );
677 + }
1069 678
1070 679 return [
1071 680 'images' => $result['images'],
1072 681 'response_id' => $result['responseId'],
@@ -1072,32 +681,35 @@
1072 681 'response_id' => $result['responseId'],
1073 682 'usage' => $result['usage'],
1074 683 ];
1075 684 }
1076 -
1077 685 public function ajax_ai_get_image_to_image_outpainting( $data ) {
1078 - $this->verify_upload_permissions( $data );
686 + $this->verify_permissions( $data['editor_post_id'] );
1079 687
1080 688 $app = $this->get_ai_app();
1081 689
690 + if ( empty( $data['prompt'] ) ) {
691 + throw new \Exception( 'Missing prompt' );
692 + }
693 +
1082 694 if ( ! $app->is_connected() ) {
1083 695 throw new \Exception( 'not_connected' );
1084 696 }
1085 697
1086 - if ( empty( $data['payload']['mask'] ) ) {
698 + if ( empty( $data['mask'] ) ) {
1087 699 throw new \Exception( 'Missing Expended Image' );
1088 700 }
1089 701
1090 702 $context = $this->get_request_context( $data );
1091 - $request_ids = $this->get_request_ids( $data['payload'] );
703 +
1092 704 $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 );
705 + 'prompt' => $data['prompt'],
706 + 'mask' => $data['mask'],
707 + ], $context );
1098 708
1099 - $this->throw_on_error( $result );
709 + if ( is_wp_error( $result ) ) {
710 + throw new \Exception( $result->get_error_message() );
711 + }
1100 712
1101 713 return [
1102 714 'images' => $result['images'],
1103 715 'response_id' => $result['responseId'],
@@ -1105,10 +717,8 @@
1105 717 ];
1106 718 }
1107 719
1108 720 public function ajax_ai_upload_image( $data ) {
1109 - $this->verify_upload_permissions( $data );
1110 -
1111 721 if ( empty( $data['image'] ) ) {
1112 722 throw new \Exception( 'Missing image data' );
1113 723 }
1114 724
@@ -1120,14 +730,14 @@
1120 730
1121 731 $image_data = $this->upload_image( $image['image_url'], $data['prompt'], $data['editor_post_id'] );
1122 732
1123 733 if ( is_wp_error( $image_data ) ) {
1124 - throw new \Exception( esc_html( $image_data->get_error_message() ) );
734 + throw new \Exception( $image_data->get_error_message() );
1125 735 }
1126 736
1127 737 if ( ! empty( $image['use_gallery_image'] ) && ! empty( $image['id'] ) ) {
1128 - $app = $this->get_ai_app();
1129 - $app->set_used_gallery_image( $image['id'] );
738 + $app = $this->get_ai_app();
739 + $app->set_used_gallery_image( $image['id'] );
1130 740 }
1131 741
1132 742 return [
1133 743 'image' => array_merge( $image_data, $data ),
@@ -1148,9 +758,9 @@
1148 758 }
1149 759
1150 760 $result = $app->generate_layout(
1151 761 $data,
1152 - $this->prepare_generate_layout_context( $data )
762 + $this->prepare_generate_layout_context()
1153 763 );
1154 764
1155 765 if ( is_wp_error( $result ) ) {
1156 766 $message = $result->get_error_message();
@@ -1156,12 +766,11 @@
1156 766 $message = $result->get_error_message();
1157 767
1158 768 if ( is_array( $message ) ) {
1159 769 $message = implode( ', ', $message );
1160 - throw new \Exception( esc_html( $message ) );
1161 770 }
1162 771
1163 - $this->throw_on_error( $result );
772 + throw new \Exception( $message );
1164 773 }
1165 774
1166 775 $elements = $result['text']['elements'] ?? [];
1167 776 $base_template_id = $result['baseTemplateId'] ?? null;
@@ -1221,12 +830,14 @@
1221 830
1222 831 $result = $app->get_layout_prompt_enhanced(
1223 832 $data['prompt'],
1224 833 $data['enhance_type'],
1225 - $this->prepare_generate_layout_context( $data )
834 + $this->prepare_generate_layout_context()
1226 835 );
1227 836
1228 - $this->throw_on_error( $result );
837 + if ( is_wp_error( $result ) ) {
838 + throw new \Exception( $result->get_error_message() );
839 + }
1229 840
1230 841 return [
1231 842 'text' => $result['text'] ?? $data['prompt'],
1232 843 'response_id' => $result['responseId'] ?? '',
@@ -1233,14 +844,13 @@
1233 844 'usage' => $result['usage'] ?? '',
1234 845 ];
1235 846 }
1236 847
1237 - private function prepare_generate_layout_context( $data ) {
1238 - $request_context = $this->get_request_context( $data );
848 + private function prepare_generate_layout_context() {
1239 849 $kit = Plugin::$instance->kits_manager->get_active_kit();
1240 850
1241 851 if ( ! $kit ) {
1242 - return $request_context;
852 + return [];
1243 853 }
1244 854
1245 855 $kits_data = Collection::make( $kit->get_data()['settings'] ?? [] );
1246 856
@@ -1293,14 +903,14 @@
1293 903 ],
1294 904 ];
1295 905 } );
1296 906
1297 - $request_context['globals'] = [
1298 - 'colors' => $colors->all(),
1299 - 'typography' => $typography->all(),
907 + return [
908 + 'globals' => [
909 + 'colors' => $colors->all(),
910 + 'typography' => $typography->all(),
911 + ],
1300 912 ];
1301 -
1302 - return $request_context;
1303 913 }
1304 914
1305 915 private function upload_image( $image_url, $image_title, $parent_post_id = 0 ) {
1306 916 if ( ! current_user_can( 'upload_files' ) ) {
@@ -1306,24 +916,10 @@
1306 916 if ( ! current_user_can( 'upload_files' ) ) {
1307 917 throw new \Exception( 'Not Allowed to Upload images' );
1308 918 }
1309 919
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 920 $attachment_id = media_sideload_image( $image_url, $parent_post_id, $image_title, 'id' );
1321 921
1322 - if ( is_wp_error( $attachment_id ) ) {
1323 - return new \WP_Error( 'upload_error', $attachment_id->get_error_message() );
1324 - }
1325 -
1326 922 if ( ! empty( $attachment_id['error'] ) ) {
1327 923 return new \WP_Error( 'upload_error', $attachment_id['error'] );
1328 924 }
1329 925
@@ -1328,10 +924,10 @@
1328 924 }
1329 925
1330 926 return [
1331 927 'id' => $attachment_id,
1332 - 'url' => esc_url( wp_get_attachment_image_url( $attachment_id, 'full' ) ),
1333 - 'alt' => esc_attr( $image_title ),
928 + 'url' => wp_get_attachment_image_url( $attachment_id, 'full' ),
929 + 'alt' => $image_title,
1334 930 'source' => 'library',
1335 931 ];
1336 932 }
1337 933
@@ -1355,9 +951,9 @@
1355 951
1356 952 $result = $app->get_history_by_type( $type, $page, $limit, $context );
1357 953
1358 954 if ( is_wp_error( $result ) ) {
1359 - throw new \Exception( esc_html( $result->get_error_message() ) );
955 + throw new \Exception( $result->get_error_message() );
1360 956 }
1361 957
1362 958 return $result;
1363 959 }
@@ -1377,9 +973,9 @@
1377 973
1378 974 $result = $app->delete_history_item( $data['id'], $context );
1379 975
1380 976 if ( is_wp_error( $result ) ) {
1381 - throw new \Exception( esc_html( $result->get_error_message() ) );
977 + throw new \Exception( $result->get_error_message() );
1382 978 }
1383 979
1384 980 return [];
1385 981 }
@@ -1399,150 +995,10 @@
1399 995
1400 996 $result = $app->toggle_favorite_history_item( $data['id'], $context );
1401 997
1402 998 if ( is_wp_error( $result ) ) {
1403 - throw new \Exception( esc_html( $result->get_error_message() ) );
999 + throw new \Exception( $result->get_error_message() );
1404 1000 }
1405 1001
1406 1002 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 1003 }
1548 1004 }