PluginProbe
Elementor Website Builder – more than just a page builder / 4.3.0-beta3
Elementor Website Builder – more than just a page builder v4.3.0-beta3
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
elementor / modules / cloud-kit-library / connect / cloud-kits.php

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

244 lines 6.6 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
15 const FAILED_TO_UPLOAD_KIT = 'cloud-upload-failed';
16
17 const INSUFFICIENT_QUOTA_KEY = 'insufficient-quota';
18
19 const INSUFFICIENT_STORAGE_QUOTA = 'insufficient-storage-quota';
20
21 public function get_title() {
22 return esc_html__( 'Cloud Kits', 'elementor' );
23 }
24
25 protected function get_api_url(): string {
26 return 'https://cloud-library.prod.builder.elementor.red/api/v1/cloud-library';
27 }
28
29 /**
30 * @return array|\WP_Error
31 */
32 public function get_all( $args = [] ) {
33 return $this->http_request( 'GET', 'kits', [], [
34 'return_type' => static::HTTP_RETURN_TYPE_ARRAY,
35 ] );
36 }
37
38 /**
39 * @return array|\WP_Error
40 */
41 public function get_quota() {
42 if ( ! $this->is_connected() ) {
43 return new \WP_Error( 'not_connected', esc_html__( 'Not connected', 'elementor' ) );
44 }
45
46 return $this->http_request( 'GET', 'quota/kits', [], [
47 'return_type' => static::HTTP_RETURN_TYPE_ARRAY,
48 'with_error_data' => true,
49 ] );
50 }
51
52 public function validate_quota( $quota ) {
53 if ( is_wp_error( $quota ) ) {
54 throw new \Error( static::FAILED_TO_FETCH_QUOTA_KEY ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
55 }
56
57 $is_unlimited = self::THRESHOLD_UNLIMITED === $quota['threshold'];
58 $has_quota = $quota['currentUsage'] < $quota['threshold'];
59
60 if ( ! $is_unlimited && ! $has_quota ) {
61 throw new \Error( static::INSUFFICIENT_QUOTA_KEY ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
62 }
63 }
64
65 public function validate_storage_quota( $intended_usage, $quota ) {
66 if ( is_wp_error( $quota ) ) {
67 throw new \Error( static::FAILED_TO_FETCH_QUOTA_KEY ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
68 }
69
70 if ( empty( $quota['storage']['currentUsage'] ) ) {
71 return;
72 }
73
74 $has_quota = $quota['storage']['currentUsage'] + $intended_usage < $quota['storage']['threshold'];
75
76 if ( ! $has_quota ) {
77 throw new \Error( static::INSUFFICIENT_STORAGE_QUOTA ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
78 }
79 }
80
81 public function check_eligibility() {
82 $quota = $this->get_quota();
83
84 if ( is_wp_error( $quota ) ) {
85 return [
86 'is_eligible' => false,
87 'subscription_id' => '',
88 ];
89 }
90
91 return [
92 'is_eligible' => isset( $quota['threshold'] ) && 0 !== $quota['threshold'],
93 'subscription_id' => ! empty( $quota['subscriptionId'] ) ? $quota['subscriptionId'] : '',
94 ];
95 }
96
97 public function create_kit( $title, $description, $content_file_data, $preview_file_data, array $includes, string $media_format = 'link', $file_size = 0 ) {
98 $quota = $this->get_quota();
99 $this->validate_quota( $quota );
100 $this->validate_storage_quota( $file_size, $quota );
101
102 $endpoint = 'kits';
103
104 $boundary = wp_generate_password( 24, false );
105
106 $headers = [
107 'Content-Type' => 'multipart/form-data; boundary=' . $boundary,
108 ];
109
110 $body = $this->create_multipart_body(
111 [
112 'title' => $title,
113 'description' => $description,
114 'includes' => wp_json_encode( $includes ),
115 'mediaFormat' => $media_format,
116 ],
117 [
118 'previewFile' => [
119 'filename' => 'preview.png',
120 'content' => $preview_file_data,
121 'content_type' => 'image/png',
122 ],
123 ],
124 $boundary
125 );
126
127 $payload = [
128 'headers' => $headers,
129 'body' => $body,
130 'timeout' => 120,
131 ];
132
133 $response = $this->http_request( 'POST', $endpoint, $payload, [
134 'return_type' => static::HTTP_RETURN_TYPE_ARRAY,
135 ] );
136
137 if ( is_wp_error( $response ) || empty( $response['id'] ) ) {
138 throw new \Exception( static::FAILED_TO_UPLOAD_KIT, Exceptions::INTERNAL_SERVER_ERROR ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
139 }
140
141 if ( empty( $response['uploadUrl'] ) ) {
142 $this->delete_kit( $response['id'] );
143 throw new \Exception( static::FAILED_TO_UPLOAD_KIT, Exceptions::INTERNAL_SERVER_ERROR ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
144 }
145
146 $upload_success = $this->upload_content_file( $response['uploadUrl'], $content_file_data );
147
148 if ( ! $upload_success ) {
149 $this->delete_kit( $response['id'] );
150 throw new \Exception( static::FAILED_TO_UPLOAD_KIT, Exceptions::INTERNAL_SERVER_ERROR ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
151 }
152
153 return $response;
154 }
155
156 public function upload_content_file( $upload_url, $content_file_data ) {
157 $upload_response = wp_remote_request( $upload_url, [
158 'method' => 'PUT',
159 'body' => $content_file_data,
160 'headers' => [
161 'Content-Type' => 'application/zip',
162 'Content-Length' => strlen( $content_file_data ),
163 ],
164 'timeout' => 120,
165 ] );
166
167 if ( is_wp_error( $upload_response ) ) {
168 return false;
169 }
170
171 $response_code = wp_remote_retrieve_response_code( $upload_response );
172
173 return $response_code >= 200 && $response_code < 300;
174 }
175
176 public function get_kit( array $args ) {
177 $args = array_merge_recursive( $args, [
178 'timeout' => 60, // just in case if zip is big
179 ] );
180
181 return $this->http_request( 'GET', 'kits/' . $args['id'], $args, [
182 'return_type' => static::HTTP_RETURN_TYPE_ARRAY,
183 ] );
184 }
185
186 public function delete_kit( int $id ) {
187 return $this->http_request( 'DELETE', 'kits/' . $id, [], [
188 'return_type' => static::HTTP_RETURN_TYPE_ARRAY,
189 ] );
190 }
191
192 private function create_multipart_body( $fields, $files, $boundary ): string {
193 $eol = "\r\n";
194 $body = '';
195
196 foreach ( $fields as $name => $value ) {
197 $body .= "--{$boundary}{$eol}";
198 $body .= "Content-Disposition: form-data; name=\"{$name}\"{$eol}{$eol}";
199 $body .= "{$value}{$eol}";
200 }
201
202 foreach ( $files as $name => $file ) {
203 $filename = basename( $file['filename'] );
204 $content_type = $file['content_type'];
205 $content = $file['content'];
206
207 $body .= "--{$boundary}{$eol}";
208 $body .= "Content-Disposition: form-data; name=\"{$name}\"; filename=\"{$filename}\"{$eol}";
209 $body .= "Content-Type: {$content_type}{$eol}{$eol}";
210 $body .= $content . $eol;
211 }
212
213 $body .= "--{$boundary}--{$eol}";
214
215 return $body;
216 }
217
218 public function update_kit( $id, array $kit_data ) {
219 $endpoint = 'kits/' . $id;
220
221 $request = $this->http_request(
222 'PATCH',
223 $endpoint,
224 [
225 'body' => wp_json_encode( $kit_data ),
226 'headers' => [
227 'Content-Type' => 'application/json',
228 ],
229 ],
230 [
231 'return_type' => static::HTTP_RETURN_TYPE_ARRAY,
232 ],
233 );
234
235 if ( is_wp_error( $request ) ) {
236 return false;
237 }
238
239 return true;
240 }
241
242 protected function init() {}
243 }
244