PluginProbe
Elementor Website Builder – more than just a page builder / 3.13.2
Elementor Website Builder – more than just a page builder v3.13.2
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 4.1.0-dev2 4.0.8 4.1.0-beta1 4.1.0-dev1 All 452 releases
← All changes | modules/ai/connect/ai.php +18 -800 4.1.0-dev23.13.2 View file →
@@ -1,29 +1,16 @@
1 1 <?php
2 2 namespace Elementor\Modules\Ai\Connect;
3 3
4 4 use Elementor\Core\Common\Modules\Connect\Apps\Library;
5 -use Elementor\Modules\Ai\Module;
6 -use Elementor\Utils as ElementorUtils;
7 -use Elementor\Plugin;
8 5
9 6 if ( ! defined( 'ABSPATH' ) ) {
10 - exit; // Exit if accessed directly.
7 + exit; // Exit if accessed directly
11 8 }
12 9
13 10 class Ai extends Library {
14 11 const API_URL = 'https://my.elementor.com/api/v2/ai/';
15 12
16 - const STYLE_PRESET = 'style_preset';
17 - const IMAGE_TYPE = 'image_type';
18 - const IMAGE_STRENGTH = 'image_strength';
19 - const ASPECT_RATIO = 'ratio';
20 - const IMAGE_RESOLUTION = 'image_resolution';
21 -
22 - const IMAGE_BACKGROUND_COLOR = 'background_color';
23 -
24 - const PROMPT = 'prompt';
25 -
26 13 public function get_title() {
27 14 return esc_html__( 'AI', 'elementor' );
28 15 }
29 16
@@ -41,146 +28,21 @@
41 28 ]
42 29 );
43 30 }
44 31
45 - public function get_remote_config() {
46 - return $this->ai_request(
47 - 'GET',
48 - 'remote-config/config',
49 - [
50 - 'api_version' => ELEMENTOR_VERSION,
51 - 'site_lang' => get_bloginfo( 'language' ),
52 - ]
53 - );
54 - }
55 -
56 - public function get_remote_frontend_config( $data ) {
57 - return $this->ai_request(
58 - 'POST',
59 - 'remote-config/frontend-config',
60 - [
61 - 'client_name' => $data['payload']['client_name'],
62 - 'client_version' => $data['payload']['client_version'],
63 - 'client_session_id' => $data['payload']['client_session_id'],
64 -
65 - 'api_version' => ELEMENTOR_VERSION,
66 - 'site_lang' => get_bloginfo( 'language' ),
67 - ],
68 - false,
69 - '',
70 - 'json'
71 - );
72 - }
73 -
74 - /**
75 - * @param array $event_data {
76 - * @type string $name
77 - * @type array $data
78 - * @type array $client {
79 - * @type string $name
80 - * @type string $version
81 - * @type string $session_id
82 - * }
83 - * }
84 - */
85 - public function send_event( array $event_data ): void {
86 - $this->ai_request(
87 - 'POST',
88 - 'client-events/events',
89 - [
90 - 'payload' => $event_data,
91 - 'api_version' => ELEMENTOR_VERSION,
92 - 'site_lang' => get_bloginfo( 'language' ),
93 - ],
94 - false,
95 - '',
96 - 'json'
97 - );
98 - }
99 -
100 - /**
101 - * Get file upload get_file_payload
102 - *
103 - * @param $filename
104 - * @param $file_type
105 - * @param $file_path
106 - * @param $boundary
107 - *
108 - * @return string
109 - */
110 - private function get_file_payload( $filename, $file_type, $file_path, $boundary ) {
111 - $name = $filename ?? basename( $file_path );
112 - $mine_type = 'image' === $file_type ? image_type_to_mime_type( exif_imagetype( $file_path ) ) : $file_type;
113 - $payload = '';
114 - // Upload the file
115 - $payload .= '--' . $boundary;
116 - $payload .= "\r\n";
117 - $payload .= 'Content-Disposition: form-data; name="' . esc_attr( $name ) . '"; filename="' . esc_attr( $name ) . '"' . "\r\n";
118 - $payload .= 'Content-Type: ' . $mine_type . "\r\n";
119 - $payload .= "\r\n";
120 - $payload .= file_get_contents( $file_path );
121 - $payload .= "\r\n";
122 -
123 - return $payload;
124 - }
125 -
126 - private function get_upload_request_body( $body, $file, $boundary, $file_name = '' ) {
127 - $payload = '';
128 - // add all body fields as standard POST fields:
129 - foreach ( $body as $name => $value ) {
130 - $payload .= '--' . $boundary;
131 - $payload .= "\r\n";
132 - $payload .= 'Content-Disposition: form-data; name="' . esc_attr( $name ) . '"' . "\r\n\r\n";
133 - $payload .= $value;
134 - $payload .= "\r\n";
135 - }
136 -
137 - if ( is_array( $file ) ) {
138 - foreach ( $file as $key => $file_data ) {
139 - $payload .= $this->get_file_payload( $file_data['name'], $file_data['type'], $file_data['path'], $boundary );
140 - }
141 - } else {
142 - $image_mime = image_type_to_mime_type( exif_imagetype( $file ) );
143 - // @todo: add validation for supported image types
144 -
145 - if ( empty( $file_name ) ) {
146 - $file_name = basename( $file );
147 - }
148 - $payload .= $this->get_file_payload( $file_name, $image_mime, $file, $boundary );
149 - }
150 -
151 - $payload .= '--' . $boundary . '--';
152 -
153 - return $payload;
154 - }
155 -
156 - private function ai_request( $method, $endpoint, $body, $file = false, $file_name = '', $format = 'default' ) {
157 - $headers = [
158 - 'x-elementor-ai-version' => '2',
159 - ];
160 -
161 - if ( $file ) {
162 - $boundary = wp_generate_password( 24, false );
163 - $body = $this->get_upload_request_body( $body, $file, $boundary, $file_name );
164 - // add content type header
165 - $headers['Content-Type'] = 'multipart/form-data; boundary=' . $boundary;
166 - } elseif ( 'json' === $format ) {
167 - $headers['Content-Type'] = 'application/json';
168 - $body = wp_json_encode( $body );
169 - }
170 -
32 + private function ai_request( $method, $endpoint, $body ) {
171 33 return $this->http_request(
172 34 $method,
173 35 $endpoint,
174 36 [
175 - 'timeout' => 100,
176 - 'headers' => $headers,
37 + 'timeout' => 25,
38 + 'headers' => [
39 + 'x-elementor-ai-version' => '2',
40 + ],
177 41 'body' => $body,
178 -
179 42 ],
180 43 [
181 44 'return_type' => static::HTTP_RETURN_TYPE_ARRAY,
182 - 'with_error_data' => true,
183 45 ]
184 46 );
185 47 }
186 48
@@ -205,701 +67,57 @@
205 67 ]
206 68 );
207 69 }
208 70
209 - public function set_used_gallery_image( $image_id ) {
71 + public function get_completion_text( $prompt ) {
210 72 return $this->ai_request(
211 73 'POST',
212 - 'status/used-gallery-image/' . $image_id,
213 - [
214 - 'api_version' => ELEMENTOR_VERSION,
215 - 'site_lang' => get_bloginfo( 'language' ),
216 - ]
217 - );
218 - }
219 -
220 - public function get_completion_text( $prompt, $context, $request_ids ) {
221 - return $this->ai_request(
222 - 'POST',
223 74 'text/completion',
224 75 [
225 76 'prompt' => $prompt,
226 - 'context' => wp_json_encode( $context ),
227 - 'ids' => $request_ids,
228 77 'api_version' => ELEMENTOR_VERSION,
229 78 'site_lang' => get_bloginfo( 'language' ),
230 - ],
231 - false,
232 - '',
233 - 'json'
234 - );
235 - }
236 -
237 - public function get_excerpt( $prompt, $context, $request_ids ) {
238 - $excerpt_length = apply_filters( 'excerpt_length', 55 );
239 - return $this->ai_request(
240 - 'POST',
241 - 'text/get-excerpt',
242 - [
243 - 'content' => $prompt,
244 - 'maxLength' => $excerpt_length,
245 - 'context' => wp_json_encode( $context ),
246 - 'ids' => $request_ids,
247 - 'api_version' => ELEMENTOR_VERSION,
248 - 'site_lang' => get_bloginfo( 'language' ),
249 - ],
250 - false,
251 - '',
252 - 'json'
253 - );
254 - }
255 -
256 - /**
257 - * Get Image Prompt Enhanced get_image_prompt_enhanced
258 - *
259 - * @param $prompt
260 - *
261 - * @return mixed|\WP_Error
262 - */
263 - public function get_image_prompt_enhanced( $prompt, $context, $request_ids ) {
264 - return $this->ai_request(
265 - 'POST',
266 - 'text/enhance-image-prompt',
267 - [
268 - 'prompt' => $prompt,
269 - 'context' => wp_json_encode( $context ),
270 - 'ids' => $request_ids,
271 - 'api_version' => ELEMENTOR_VERSION,
272 - 'site_lang' => get_bloginfo( 'language' ),
273 79 ]
274 80 );
275 81 }
276 82
277 - public function get_edit_text( $data, $context, $request_ids ) {
83 + public function get_edit_text( $input, $instruction ) {
278 84 return $this->ai_request(
279 85 'POST',
280 86 'text/edit',
281 87 [
282 - 'input' => $data['payload']['input'],
283 - 'instruction' => $data['payload']['instruction'],
284 - 'context' => wp_json_encode( $context ),
285 - 'ids' => $request_ids,
88 + 'input' => $input,
89 + 'instruction' => $instruction,
286 90 'api_version' => ELEMENTOR_VERSION,
287 91 'site_lang' => get_bloginfo( 'language' ),
288 - ],
289 - false,
290 - '',
291 - 'json'
92 + ]
292 93 );
293 94 }
294 95
295 - public function get_custom_code( $data, $context, $request_ids ) {
96 + public function get_custom_code( $prompt, $language ) {
296 97 return $this->ai_request(
297 98 'POST',
298 99 'text/custom-code',
299 100 [
300 - 'prompt' => $data['payload']['prompt'],
301 - 'language' => $data['payload']['language'],
302 - 'context' => wp_json_encode( $context ),
303 - 'ids' => $request_ids,
101 + 'prompt' => $prompt,
102 + 'language' => $language,
304 103 'api_version' => ELEMENTOR_VERSION,
305 104 'site_lang' => get_bloginfo( 'language' ),
306 - ],
307 - false,
308 - '',
309 - 'json'
105 + ]
310 106 );
311 107 }
312 108
313 - public function get_custom_css( $data, $context, $request_ids ) {
109 + public function get_custom_css( $prompt, $html_markup, $element_id ) {
314 110 return $this->ai_request(
315 111 'POST',
316 112 'text/custom-css',
317 113 [
318 - 'prompt' => $data['payload']['prompt'],
319 - 'html_markup' => $data['payload']['html_markup'],
320 - 'element_id' => $data['payload']['element_id'],
321 - 'context' => wp_json_encode( $context ),
322 - 'ids' => $request_ids,
323 - 'api_version' => ELEMENTOR_VERSION,
324 - 'site_lang' => get_bloginfo( 'language' ),
325 - ],
326 - false,
327 - '',
328 - 'json'
329 - );
330 - }
331 -
332 - /**
333 - * Get text to image get_text_to_image
334 - *
335 - * @param $prompt
336 - * @param $prompt_settings
337 - *
338 - * @return mixed|\WP_Error
339 - */
340 - public function get_text_to_image( $data, $context, $request_ids ) {
341 - return $this->ai_request(
342 - 'POST',
343 - 'image/text-to-image',
344 - [
345 - self::PROMPT => $data['payload']['prompt'],
346 - self::IMAGE_TYPE => $data['payload']['settings'][ self::IMAGE_TYPE ] . '/' . $data['payload']['settings'][ self::STYLE_PRESET ],
347 - self::ASPECT_RATIO => $data['payload']['settings'][ self::ASPECT_RATIO ],
348 - 'context' => wp_json_encode( $context ),
349 - 'ids' => $request_ids,
350 - 'api_version' => ELEMENTOR_VERSION,
351 - 'site_lang' => get_bloginfo( 'language' ),
352 - ],
353 - false,
354 - '',
355 - 'json'
356 - );
357 - }
358 -
359 - /**
360 - * Get_Featured_Image get_featured_image
361 - *
362 - * @param $data
363 - * @param $context
364 - * @param $request_ids
365 - * @return mixed|\WP_Error
366 - */
367 - public function get_featured_image( $data, $context, $request_ids ) {
368 - return $this->ai_request(
369 - 'POST',
370 - 'image/text-to-image/featured-image',
371 - [
372 - self::PROMPT => $data['payload']['prompt'],
373 - self::IMAGE_TYPE => $data['payload']['settings'][ self::IMAGE_TYPE ] . '/' . $data['payload']['settings'][ self::STYLE_PRESET ],
374 - self::ASPECT_RATIO => $data['payload']['settings'][ self::ASPECT_RATIO ],
375 - 'context' => wp_json_encode( $context ),
376 - 'ids' => $request_ids,
377 - 'api_version' => ELEMENTOR_VERSION,
378 - 'site_lang' => get_bloginfo( 'language' ),
379 - ],
380 - false,
381 - '',
382 - 'json'
383 - );
384 - }
385 -
386 - /**
387 - * Get Image To Image get_image_to_image
388 - *
389 - * @param $image_data
390 - * @param $context
391 - * @param $request_ids
392 - * @return mixed|\WP_Error
393 - * @throws \Exception If image file not found.
394 - */
395 - public function get_image_to_image( $image_data, $context, $request_ids ) {
396 - $image_file = get_attached_file( $image_data['attachment_id'] );
397 -
398 - if ( ! $image_file ) {
399 - throw new \Exception( 'Image file not found' );
400 - }
401 -
402 - $result = $this->ai_request(
403 - 'POST',
404 - 'image/image-to-image',
405 - [
406 - self::PROMPT => $image_data[ self::PROMPT ],
407 - self::IMAGE_TYPE => $image_data['promptSettings'][ self::IMAGE_TYPE ] . '/' . $image_data['promptSettings'][ self::STYLE_PRESET ],
408 - self::IMAGE_STRENGTH => $image_data['promptSettings'][ self::IMAGE_STRENGTH ],
409 - self::ASPECT_RATIO => $image_data['promptSettings'][ self::ASPECT_RATIO ],
410 - 'context' => wp_json_encode( $context ),
411 - 'ids' => $request_ids,
412 - 'api_version' => ELEMENTOR_VERSION,
413 - 'site_lang' => get_bloginfo( 'language' ),
414 - ],
415 - $image_file,
416 - 'image'
417 - );
418 -
419 - return $result;
420 - }
421 -
422 -
423 - private function resizeImageIfNeeded( $original_url ) {
424 - try {
425 - $max_file_size = 4194304;
426 - $current_size = filesize( $original_url );
427 -
428 - if ( $current_size <= $max_file_size ) {
429 - return $original_url;
430 - }
431 -
432 - $image_editor = wp_get_image_editor( $original_url );
433 -
434 - if ( is_wp_error( $image_editor ) ) {
435 - return $original_url;
436 - }
437 -
438 - $dimensions = $image_editor->get_size();
439 - $original_width = $dimensions['width'];
440 - $original_height = $dimensions['height'];
441 -
442 - $scaling_factor = sqrt( $max_file_size / $current_size );
443 -
444 - $new_width = (int) ( $original_width * $scaling_factor );
445 - $new_height = (int) ( $original_height * $scaling_factor );
446 -
447 - $image_editor->resize( $new_width, $new_height, true );
448 -
449 - $file_extension = pathinfo( $original_url, PATHINFO_EXTENSION );
450 - $temp_image = tempnam( sys_get_temp_dir(), 'resized_' ) . '.' . $file_extension;
451 -
452 - $image_editor->save( $temp_image );
453 - return $temp_image;
454 - } catch ( \Exception $e ) {
455 - return $original_url;
456 - }
457 - }
458 -
459 - public function get_unify_product_images( $image_data, $context, $request_ids ) {
460 - $image_file = get_attached_file( $image_data['attachment_id'] );
461 -
462 - if ( ! $image_file ) {
463 - throw new \Exception( 'Image file not found' );
464 - }
465 -
466 - $final_path = $this->resizeImageIfNeeded( $image_file );
467 -
468 - $result = $this->ai_request(
469 - 'POST',
470 - 'image/image-to-image/unify-product-images',
471 - [
472 - 'aspectRatio' => $image_data['promptSettings'][ self::ASPECT_RATIO ],
473 - 'backgroundColor' => $image_data['promptSettings'][ self::IMAGE_BACKGROUND_COLOR ],
474 - 'featureIdentifier' => $image_data['featureIdentifier'],
475 - 'context' => wp_json_encode( $context ),
476 - 'ids' => $request_ids,
477 - 'api_version' => ELEMENTOR_VERSION,
478 - 'site_lang' => get_bloginfo( 'language' ),
479 - ],
480 - $final_path,
481 - 'image'
482 - );
483 -
484 - if ( $image_file !== $final_path ) {
485 - unlink( $final_path );
486 - }
487 -
488 - return $result;
489 - }
490 -
491 - /**
492 - * Get Image To Image Upscale get_image_to_image_upscale
493 - *
494 - * @param $image_data
495 - * @param $context
496 - * @param $request_ids
497 - * @return mixed|\WP_Error
498 - * @throws \Exception If image file not found.
499 - */
500 - public function get_image_to_image_upscale( $image_data, $context, $request_ids ) {
501 - $image_file = get_attached_file( $image_data['attachment_id'] );
502 -
503 - if ( ! $image_file ) {
504 - throw new \Exception( 'Image file not found' );
505 - }
506 -
507 - $result = $this->ai_request(
508 - 'POST',
509 - 'image/image-to-image/upscale',
510 - [
511 - self::IMAGE_RESOLUTION => $image_data['promptSettings']['upscale_to'],
512 - 'context' => wp_json_encode( $context ),
513 - 'ids' => $request_ids,
514 - 'api_version' => ELEMENTOR_VERSION,
515 - 'site_lang' => get_bloginfo( 'language' ),
516 - ],
517 - $image_file,
518 - 'image'
519 - );
520 -
521 - return $result;
522 - }
523 -
524 - /**
525 - * Get Image To Image Remove Background get_image_to_image_remove_background
526 - *
527 - * @param $image_data
528 - * @param $context
529 - * @param $request_ids
530 - * @return mixed|\WP_Error
531 - * @throws \Exception If image file not found.
532 - */
533 - public function get_image_to_image_remove_background( $image_data, $context, $request_ids ) {
534 - $image_file = get_attached_file( $image_data['attachment_id'] );
535 -
536 - if ( ! $image_file ) {
537 - throw new \Exception( 'Image file not found' );
538 - }
539 -
540 - $result = $this->ai_request(
541 - 'POST',
542 - 'image/image-to-image/remove-background',
543 - [
544 - 'context' => wp_json_encode( $context ),
545 - 'ids' => $request_ids,
546 - 'api_version' => ELEMENTOR_VERSION,
547 - 'site_lang' => get_bloginfo( 'language' ),
548 - ],
549 - $image_file,
550 - 'image'
551 - );
552 -
553 - return $result;
554 - }
555 -
556 - /**
557 - * Get Image To Image Remove Text get_image_to_image_remove_text
558 - *
559 - * @param $image_data
560 - * @param $context
561 - * @param $request_ids
562 - * @return mixed|\WP_Error
563 - * @throws \Exception If image file not found.
564 - */
565 - public function get_image_to_image_replace_background( $image_data, $context, $request_ids ) {
566 - $image_file = get_attached_file( $image_data['attachment_id'] );
567 -
568 - if ( ! $image_file ) {
569 - throw new \Exception( 'Image file not found' );
570 - }
571 -
572 - $result = $this->ai_request(
573 - 'POST',
574 - 'image/image-to-image/replace-background',
575 - [
576 - self::PROMPT => $image_data[ self::PROMPT ],
577 - 'context' => wp_json_encode( $context ),
578 - 'ids' => $request_ids,
579 - 'api_version' => ELEMENTOR_VERSION,
580 - 'site_lang' => get_bloginfo( 'language' ),
581 - ],
582 - $image_file,
583 - 'image'
584 - );
585 -
586 - return $result;
587 - }
588 -
589 - /**
590 - * Store Temp File store_temp_file
591 - * used to store a temp file for the AI request and deletes it once the request is done
592 - *
593 - * @param $file_content
594 - * @param $file_ext
595 - *
596 - * @return string
597 - */
598 - private function store_temp_file( $file_content, $file_ext = '' ) {
599 - $temp_file = str_replace( '.tmp', '', wp_tempnam() . $file_ext );
600 - file_put_contents( $temp_file, $file_content );
601 - // make sure the temp file is deleted on shutdown
602 - register_shutdown_function( function () use ( $temp_file ) {
603 - if ( file_exists( $temp_file ) ) {
604 - unlink( $temp_file );
605 - }
606 - } );
607 - return $temp_file;
608 - }
609 -
610 - /**
611 - * Get Image To Image Out Painting get_image_to_image_out_painting
612 - *
613 - * @param $image_data
614 - * @param $context
615 - * @param $request_ids
616 - * @return mixed|\WP_Error
617 - * @throws \Exception If image file not found.
618 - */
619 - public function get_image_to_image_out_painting( $image_data, $context, $request_ids ) {
620 - $img_content = str_replace( ' ', '+', $image_data['mask'] );
621 - $img_content = substr( $img_content, strpos( $img_content, ',' ) + 1 );
622 - $img_content = base64_decode( $img_content );
623 - $mask_file = $this->store_temp_file( $img_content, '.png' );
624 -
625 - if ( ! $mask_file ) {
626 - throw new \Exception( 'Expended Image file not found' );
627 - }
628 -
629 - $result = $this->ai_request(
630 - 'POST',
631 - 'image/image-to-image/outpainting',
632 - [
633 - 'context' => wp_json_encode( $context ),
634 - 'ids' => $request_ids,
635 - 'api_version' => ELEMENTOR_VERSION,
636 - 'site_lang' => get_bloginfo( 'language' ),
637 - 'size' => wp_json_encode( $image_data['size'] ),
638 - 'position' => wp_json_encode( $image_data['position'] ),
639 - 'image_base64' => $image_data['image_base64'],
640 - $image_data['image'],
641 - ],
642 - [
643 - [
644 - 'name' => 'image',
645 - 'type' => 'image',
646 - 'path' => $mask_file,
647 - ],
648 - ]
649 - );
650 -
651 - return $result;
652 - }
653 -
654 - /**
655 - * Get Image To Image Mask get_image_to_image_mask
656 - *
657 - * @param $image_data
658 - * @param $context
659 - * @param $request_ids
660 - * @return mixed|\WP_Error
661 - * @throws \Exception If image file not found.
662 - */
663 - public function get_image_to_image_mask( $image_data, $context, $request_ids ) {
664 - $image_file = get_attached_file( $image_data['attachment_id'] );
665 - $mask_file = $this->store_temp_file( $image_data['mask'], '.svg' );
666 -
667 - if ( ! $image_file ) {
668 - throw new \Exception( 'Image file not found' );
669 - }
670 -
671 - if ( ! $mask_file ) {
672 - throw new \Exception( 'Mask file not found' );
673 - }
674 -
675 - $result = $this->ai_request(
676 - 'POST',
677 - 'image/image-to-image/inpainting',
678 - [
679 - self::PROMPT => $image_data[ self::PROMPT ],
680 - 'context' => wp_json_encode( $context ),
681 - 'ids' => $request_ids,
682 - 'api_version' => ELEMENTOR_VERSION,
683 - 'site_lang' => get_bloginfo( 'language' ),
684 - 'image_base64' => $image_data['image_base64'],
685 - ],
686 - [
687 - [
688 - 'name' => 'image',
689 - 'type' => 'image',
690 - 'path' => $image_file,
691 - ],
692 - [
693 - 'name' => 'mask_image',
694 - 'type' => 'image/svg+xml',
695 - 'path' => $mask_file,
696 - ],
697 - ]
698 - );
699 -
700 - return $result;
701 - }
702 - public function get_image_to_image_mask_cleanup( $image_data, $context, $request_ids ) {
703 - $image_file = get_attached_file( $image_data['attachment_id'] );
704 - $mask_file = $this->store_temp_file( $image_data['mask'], '.svg' );
705 -
706 - if ( ! $image_file ) {
707 - throw new \Exception( 'Image file not found' );
708 - }
709 -
710 - if ( ! $mask_file ) {
711 - throw new \Exception( 'Mask file not found' );
712 - }
713 -
714 - $result = $this->ai_request(
715 - 'POST',
716 - 'image/image-to-image/cleanup',
717 - [
718 - self::PROMPT => $image_data[ self::PROMPT ],
719 - 'context' => wp_json_encode( $context ),
720 - 'ids' => $request_ids,
721 - 'api_version' => ELEMENTOR_VERSION,
722 - 'site_lang' => get_bloginfo( 'language' ),
723 - 'image_base64' => $image_data['image_base64'],
724 - ],
725 - [
726 - [
727 - 'name' => 'image',
728 - 'type' => 'image',
729 - 'path' => $image_file,
730 - ],
731 - [
732 - 'name' => 'mask_image',
733 - 'type' => 'image/svg+xml',
734 - 'path' => $mask_file,
735 - ],
736 - ]
737 - );
738 -
739 - return $result;
740 - }
741 -
742 - public function generate_layout( $data, $context ) {
743 - $endpoint = 'generate/layout';
744 -
745 - $body = [
746 - 'prompt' => $data['prompt'],
747 - 'variationType' => (int) $data['variationType'],
748 - 'ids' => $data['ids'],
749 - ];
750 -
751 - if ( ! empty( $data['prevGeneratedIds'] ) ) {
752 - $body['generatedBaseTemplatesIds'] = $data['prevGeneratedIds'];
753 - }
754 -
755 - if ( ! empty( $data['attachments'] ) ) {
756 - $attachment = $data['attachments'][0];
757 -
758 - switch ( $attachment['type'] ) {
759 - case 'json':
760 - $endpoint = 'generate/generate-json-variation';
761 -
762 - $body['json'] = [
763 - 'type' => 'elementor',
764 - 'elements' => [ $attachment['content'] ],
765 - 'label' => $attachment['label'],
766 - 'source' => $attachment['source'],
767 - ];
768 - break;
769 - case 'url':
770 - $endpoint = 'generate/html-to-elementor';
771 -
772 - $html = wp_json_encode( $attachment['content'] );
773 -
774 - $body['html'] = $html;
775 - $body['htmlFetchedUrl'] = $attachment['label'];
776 -
777 - break;
778 - }
779 - }
780 -
781 - $context['currentContext'] = $data['currentContext'];
782 - $context['features'] = [
783 - 'supportedFeatures' => [ 'Taxonomy' ],
784 - ];
785 -
786 - if ( ElementorUtils::has_pro() ) {
787 - $context['features']['subscriptions'] = [ 'Pro' ];
788 - }
789 -
790 - if ( Plugin::instance()->experiments->get_active_features()['nested-elements'] ) {
791 - $context['features']['supportedFeatures'][] = 'Nested';
792 - }
793 -
794 - if ( Plugin::instance()->experiments->get_active_features()['mega-menu'] ) {
795 - $context['features']['supportedFeatures'][] = 'MegaMenu';
796 - }
797 -
798 - if ( class_exists( 'WC' ) ) {
799 - $context['features']['supportedFeatures'][] = 'WooCommerce';
800 - }
801 -
802 - $metadata = [
803 - 'context' => $context,
804 - 'api_version' => ELEMENTOR_VERSION,
805 - 'site_lang' => get_bloginfo( 'language' ),
806 - 'config' => [
807 - 'generate' => [
808 - 'all' => true,
809 - ],
810 - ],
811 - ];
812 -
813 - $body = array_merge( $body, $metadata );
814 -
815 - // Temp hack for platforms that filters the http_request_args, and it breaks JSON requests.
816 - remove_all_filters( 'http_request_args' );
817 -
818 - return $this->ai_request(
819 - 'POST',
820 - $endpoint,
821 - $body,
822 - false,
823 - '',
824 - 'json'
825 - );
826 - }
827 -
828 - public function get_layout_prompt_enhanced( $prompt, $enhance_type, $context ) {
829 - return $this->ai_request(
830 - 'POST',
831 - 'generate/enhance-prompt',
832 - [
833 114 'prompt' => $prompt,
834 - 'enhance_type' => $enhance_type,
835 - 'context' => wp_json_encode( $context ),
115 + 'html_markup' => $html_markup,
116 + 'element_id' => $element_id,
836 117 'api_version' => ELEMENTOR_VERSION,
837 118 'site_lang' => get_bloginfo( 'language' ),
838 - ],
839 - false,
840 - '',
841 - 'json'
842 - );
843 - }
844 -
845 - public function get_history_by_type( $type, $page, $limit, $context = [] ) {
846 - $endpoint = Module::HISTORY_TYPE_ALL === $type
847 - ? 'history'
848 - : add_query_arg( [
849 - 'page' => $page,
850 - 'limit' => $limit,
851 - ], "history/{$type}" );
852 -
853 - return $this->ai_request(
854 - 'POST',
855 - $endpoint,
856 - [
857 - 'context' => wp_json_encode( $context ),
858 - 'api_version' => ELEMENTOR_VERSION,
859 - 'site_lang' => get_bloginfo( 'language' ),
860 119 ]
861 - );
862 - }
863 -
864 - public function delete_history_item( $id, $context = [] ) {
865 - return $this->ai_request(
866 - 'DELETE', 'history/' . $id,
867 - [
868 - 'context' => wp_json_encode( $context ),
869 - 'api_version' => ELEMENTOR_VERSION,
870 - 'site_lang' => get_bloginfo( 'language' ),
871 - ]
872 - );
873 - }
874 -
875 - public function toggle_favorite_history_item( $id, $context = [] ) {
876 - $sanitized_id = str_replace( '%', '%%', $id );
877 - return $this->ai_request(
878 - 'POST', sprintf( 'history/%s/favorite', $sanitized_id ),
879 - [
880 - 'context' => wp_json_encode( $context ),
881 - 'api_version' => ELEMENTOR_VERSION,
882 - 'site_lang' => get_bloginfo( 'language' ),
883 - ]
884 - );
885 - }
886 -
887 - public function get_animation( $data, $context, $request_ids ) {
888 - return $this->ai_request(
889 - 'POST',
890 - 'text/get-motion-effect',
891 - [
892 - 'prompt' => $data['payload']['prompt'],
893 - 'motionEffectType' => $data['payload']['motionEffectType'],
894 - 'context' => wp_json_encode( $context ),
895 - 'ids' => $request_ids,
896 - 'api_version' => ELEMENTOR_VERSION,
897 - 'site_lang' => get_bloginfo( 'language' ),
898 - ],
899 - false,
900 - '',
901 - 'json'
902 120 );
903 121 }
904 122
905 123 protected function init() {}