PluginProbe
Elementor Website Builder – more than just a page builder / 3.32.1
Elementor Website Builder – more than just a page builder v3.32.1
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 / cloud-kit-library / connect / cloud-kits.php

cloud-kits.php in Elementor Website Builder – more than just a page builder 3.32.1, at modules/cloud-kit-library/connect/cloud-kits.php

196 lines 5.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace Elementor\Modules\CloudKitLibrary\Connect;
3
4 use Elementor\Core\Common\Modules\Connect\Apps\Library;
5 use Elementor\Core\Utils\Exceptions;
6
7 if ( ! defined( 'ABSPATH' ) ) {
8 exit; // Exit if accessed directly.
9 }
10
11 class Cloud_Kits extends Library {
12 const THRESHOLD_UNLIMITED = -1;
13 const FAILED_TO_FETCH_QUOTA_KEY = 'failed-to-fetch-quota';
14 const INSUFFICIENT_QUOTA_KEY = 'insufficient-quota';
15
16 public function get_title() {
17 return esc_html__( 'Cloud Kits', 'elementor' );
18 }
19
20 protected function get_api_url(): string {
21 return 'https://cloud-library.prod.builder.elementor.red/api/v1/cloud-library';
22 }
23
24 /**
25 * @return array|\WP_Error
26 */
27 public function get_all( $args = [] ) {
28 return $this->http_request( 'GET', 'kits', [], [
29 'return_type' => static::HTTP_RETURN_TYPE_ARRAY,
30 ] );
31 }
32
33 /**
34 * @return array|\WP_Error
35 */
36 public function get_quota() {
37 return $this->http_request( 'GET', 'quota/kits', [], [
38 'return_type' => static::HTTP_RETURN_TYPE_ARRAY,
39 ] );
40 }
41
42 public function validate_quota() {
43 $quota = $this->get_quota();
44
45 if ( is_wp_error( $quota ) ) {
46 throw new \Error( static::FAILED_TO_FETCH_QUOTA_KEY ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
47 }
48
49 $is_unlimited = self::THRESHOLD_UNLIMITED === $quota['threshold'];
50 $has_quota = $quota['currentUsage'] < $quota['threshold'];
51
52 if ( ! $is_unlimited && ! $has_quota ) {
53 throw new \Error( static::INSUFFICIENT_QUOTA_KEY ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
54 }
55 }
56
57 public function check_eligibility() {
58 $quota = $this->get_quota();
59
60 if ( is_wp_error( $quota ) ) {
61 return [
62 'is_eligible' => false,
63 'subscription_id' => '',
64 ];
65 }
66
67 return [
68 'is_eligible' => isset( $quota['threshold'] ) && 0 !== $quota['threshold'],
69 'subscription_id' => ! empty( $quota['subscriptionId'] ) ? $quota['subscriptionId'] : '',
70 ];
71 }
72
73 public function create_kit( $title, $description, $content_file_data, $preview_file_data, array $includes ) {
74 $this->validate_quota();
75
76 $endpoint = 'kits';
77
78 $boundary = wp_generate_password( 24, false );
79
80 $headers = [
81 'Content-Type' => 'multipart/form-data; boundary=' . $boundary,
82 ];
83
84 $body = $this->create_multipart_body(
85 [
86 'title' => $title,
87 'description' => $description,
88 'includes' => wp_json_encode( $includes ),
89 ],
90 [
91 'previewFile' => [
92 'filename' => 'preview.png',
93 'content' => $preview_file_data,
94 'content_type' => 'image/png',
95 ],
96 ],
97 $boundary
98 );
99
100 $payload = [
101 'headers' => $headers,
102 'body' => $body,
103 'timeout' => 120,
104 ];
105
106 $response = $this->http_request( 'POST', $endpoint, $payload, [
107 'return_type' => static::HTTP_RETURN_TYPE_ARRAY,
108 ] );
109
110 if ( empty( $response['id'] ) ) {
111 $error_message = esc_html__( 'Failed to create kit: Invalid response', 'elementor' );
112 throw new \Exception( $error_message, Exceptions::INTERNAL_SERVER_ERROR ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
113 }
114
115 if ( empty( $response['uploadUrl'] ) ) {
116 $this->delete_kit( $response['id'] );
117 $error_message = esc_html__( 'Failed to create kit: No upload URL provided', 'elementor' );
118 throw new \Exception( $error_message, Exceptions::INTERNAL_SERVER_ERROR ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
119 }
120
121 $upload_success = $this->upload_content_file( $response['uploadUrl'], $content_file_data );
122
123 if ( ! $upload_success ) {
124 $this->delete_kit( $response['id'] );
125 $error_message = esc_html__( 'Failed to create kit: Content upload failed', 'elementor' );
126 throw new \Exception( $error_message, Exceptions::INTERNAL_SERVER_ERROR ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
127 }
128
129 return $response;
130 }
131
132 private function upload_content_file( $upload_url, $content_file_data ) {
133 $upload_response = wp_remote_request( $upload_url, [
134 'method' => 'PUT',
135 'body' => $content_file_data,
136 'headers' => [
137 'Content-Type' => 'application/zip',
138 'Content-Length' => strlen( $content_file_data ),
139 ],
140 'timeout' => 120,
141 ] );
142
143 if ( is_wp_error( $upload_response ) ) {
144 return false;
145 }
146
147 $response_code = wp_remote_retrieve_response_code( $upload_response );
148
149 return $response_code >= 200 && $response_code < 300;
150 }
151
152 public function get_kit( array $args ) {
153 $args = array_merge_recursive( $args, [
154 'timeout' => 60, // just in case if zip is big
155 ] );
156
157 return $this->http_request( 'GET', 'kits/' . $args['id'], $args, [
158 'return_type' => static::HTTP_RETURN_TYPE_ARRAY,
159 ] );
160 }
161
162 public function delete_kit( int $id ) {
163 return $this->http_request( 'DELETE', 'kits/' . $id, [], [
164 'return_type' => static::HTTP_RETURN_TYPE_ARRAY,
165 ] );
166 }
167
168 private function create_multipart_body( $fields, $files, $boundary ): string {
169 $eol = "\r\n";
170 $body = '';
171
172 foreach ( $fields as $name => $value ) {
173 $body .= "--{$boundary}{$eol}";
174 $body .= "Content-Disposition: form-data; name=\"{$name}\"{$eol}{$eol}";
175 $body .= "{$value}{$eol}";
176 }
177
178 foreach ( $files as $name => $file ) {
179 $filename = basename( $file['filename'] );
180 $content_type = $file['content_type'];
181 $content = $file['content'];
182
183 $body .= "--{$boundary}{$eol}";
184 $body .= "Content-Disposition: form-data; name=\"{$name}\"; filename=\"{$filename}\"{$eol}";
185 $body .= "Content-Type: {$content_type}{$eol}{$eol}";
186 $body .= $content . $eol;
187 }
188
189 $body .= "--{$boundary}--{$eol}";
190
191 return $body;
192 }
193
194 protected function init() {}
195 }
196