PluginProbe
Elementor Website Builder – more than just a page builder / 3.27.3
Elementor Website Builder – more than just a page builder v3.27.3
4.3.0-beta2 4.3.0-beta1 4.2.4 4.2.3 4.2.2 4.2.1 4.2.0 4.1.5 4.2.0-beta2 4.2.0-dev2 4.2.0-beta1 4.1.4 4.1.3 4.1.2 4.1.1 4.1.0 4.1.0-beta3 4.1.0-dev3 4.0.9 4.1.0-beta2 4.1.0-dev2 4.0.8 4.1.0-beta1 4.1.0-dev1 4.0.7 All 451 releases
elementor / modules / ai / connect / ai.php

ai.php in Elementor Website Builder – more than just a page builder 3.27.3, at modules/ai/connect/ai.php

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