PluginProbe
Elementor Website Builder – more than just a page builder / 3.26.0-dev4
Elementor Website Builder – more than just a page builder v3.26.0-dev4
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.26.0-dev4, at modules/ai/connect/ai.php

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