PluginProbe
aBlocks – Gutenberg Blocks, User Dashboard Builder, Popup Builder, Form Builder & Animation Builder / 2.11.1
aBlocks – Gutenberg Blocks, User Dashboard Builder, Popup Builder, Form Builder & Animation Builder v2.11.1
2.13.0 2.13.1 2.12.0 2.11.1 2.11.0 2.10.0 2.9.0 2.7.4 2.7.5 2.7.6 2.7.7 2.8.0 2.8.1 2.9.1 trunk 1.0 1.0-beta1 1.0-beta2 1.0-beta3 1.0.1 1.0.2 1.0.3 1.1.0 1.1.1 1.1.2 All 80 releases
ablocks / includes / ajax / demo-import.php

demo-import.php in aBlocks – Gutenberg Blocks, User Dashboard Builder, Popup Builder, Form Builder & Animation Builder 2.11.1, at includes/ajax/demo-import.php

442 lines 13.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace ABlocks\Ajax;
4
5 if ( ! defined( 'ABSPATH' ) ) {
6 exit;
7 }
8
9 use ABlocks\Classes\AbstractAjaxHandler;
10 use ABlocks\Classes\Sanitizer;
11 use ABlocks\Helper;
12 use ABlocks\import\CustomizerImporter;
13 use ABlocks\import\ThemeOptions\CodeStar;
14 use ABlocks\import\ThemeOptions\Redux;
15 use ABlocks\import\WidgetImporter;
16 use ABlocksThemeBuilder\Database;
17
18 class DemoImport extends AbstractAjaxHandler {
19
20 public function __construct() {
21 $this->actions = array(
22 'get_demo_list' => array(
23 'callback' => array( $this, 'get_demo_list' ),
24 'capability' => 'manage_options',
25 'fields' => array(
26 'type' => 'string',
27 'cost_type' => 'string',
28 'page' => 'integer',
29 'per_page' => 'integer',
30 'category' => 'string',
31 'dev' => 'string',
32 'q' => 'string',
33 )
34 ),
35 'get_single_demo' => array(
36 'callback' => array( $this, 'get_single_demo' ),
37 'capability' => 'manage_options',
38 'fields' => array(
39 'id' => 'integer',
40 'with_images' => 'string',
41 )
42 ),
43 'get_demo_categories' => array(
44 'callback' => array( $this, 'get_demo_categories' ),
45 'capability' => 'manage_options',
46 'fields' => array(
47 'type' => 'string',
48 )
49 ),
50 'get_theme_demos' => array(
51 'callback' => array( $this, 'get_theme_demos' ),
52 'capability' => 'manage_options',
53 ),
54 'check_dependencies' => array(
55 'callback' => array( $this, 'check_dependencies' ),
56 'capability' => 'manage_options',
57 'fields' => array(
58 'dependencies' => 'array|string',
59 )
60 ),
61 'install_and_active' => array(
62 'callback' => array( $this, 'install_and_active' ),
63 'capability' => 'manage_options',
64 'fields' => array(
65 'dependency' => 'array|string',
66 )
67 ),
68 'import_template' => array(
69 'callback' => array( $this, 'import_template' ),
70 'capability' => 'manage_options',
71 'fields' => array(
72 'file_url' => 'string',
73 'customizer_file_url' => 'string',
74 'widget_file_url' => 'string',
75 'codestar_file_url' => 'string',
76 'redux_options' => 'json',
77 'with_images' => 'boolean',
78 )
79 ),
80 );
81 }
82
83 /**
84 * Get demo list data from database, if not exists, then get & store data from API.
85 *
86 * @param array $data Query Data for API.
87 *
88 * @return void
89 */
90 public function get_demo_list( array $data ) {
91 $args = [
92 'type' => $data['type'] ?? 'pattern',
93 'cost_type' => $data['cost_type'] ?? 'all',
94 'page' => $data['page'] ?? 1,
95 ];
96
97 if ( isset( $data['category'] ) ) {
98 $args['category'] = $data['category'];
99 }
100
101 if ( isset( $data['dev'] ) ) {
102 $args['dev'] = $data['dev'];
103 }
104
105 if ( isset( $data['q'] ) ) {
106 $args['q'] = $data['q'];
107 }
108
109 if ( isset( $data['per_page'] ) ) {
110 $args['per_page'] = $data['per_page'];
111 }
112
113 $hash = md5( wp_json_encode( $args ) );
114 $key = "ablocks_demo_$hash";
115 $has_response = get_transient( $key );
116 if ( $has_response ) {
117 wp_send_json_success( $has_response );
118 }
119
120 $url = 'https://' . ABLOCKS_TEMPLATE_LIB_HOST . '/wp-json/ablocks_server/v1/ablocks';
121 $url = add_query_arg( $args, $url );
122 $this->handle_list_response( $url, $key );
123 }
124
125 /**
126 * Get single demo data from database, if not exists, then get & store data from API.
127 *
128 * @param array $data inside data `id` is required.
129 *
130 * @return void
131 */
132 public function get_single_demo( array $data ) {
133 if ( ! $data['id'] ) {
134 wp_send_json_error( __( 'id is required.', 'ablocks' ) );
135 }
136 $id = absint( $data['id'] );
137 $with_images = isset( $data['with_images'] ) && true === (bool) $data['with_images'];
138
139 $key = 'ablocks_demo_item_' . $id;
140 $has_response = get_transient( $key );
141 if ( $has_response ) {
142 if ( $with_images && ! isset( $has_response['remote_images_parsed'] ) ) {
143 $has_response['content'] = Helper::parse_remote_images( $has_response['content'] );
144 $has_response['remote_images_parsed'] = true;
145 set_transient( $key, $has_response, WEEK_IN_SECONDS );
146 }
147 unset( $has_response['remote_images_parsed'] );
148 wp_send_json_success( $has_response );
149 }
150
151 $url = 'https://' . ABLOCKS_TEMPLATE_LIB_HOST . '/wp-json/ablocks_server/v1/ablocks/' . $id;
152 $response = wp_safe_remote_get( $url );
153 if ( is_wp_error( $response ) ) {
154 wp_send_json_error( $response->get_error_message() );
155 }
156
157 $response_code = wp_remote_retrieve_response_code( $response );
158 $response = wp_remote_retrieve_body( $response );
159 $response = json_decode( $response, true );
160 if ( $response_code !== 200 ) {
161 wp_send_json_error( $response );
162 }
163
164 $response = $response['data'];
165 if ( $with_images ) {
166 $content = $response['content'] ?? null;
167 if ( $content ) {
168 $response['content'] = Helper::parse_remote_images( wp_unslash( $content ) );
169 $response['remote_images_parsed'] = true;
170 }
171 }
172 set_transient( $key, $response, WEEK_IN_SECONDS );
173 unset( $response['remote_images_parsed'] );
174 wp_send_json_success( $response );
175 }
176
177 /**
178 * Get demo category list data from database, if not exists, then get & store data from API.
179 *
180 * @param array $data Query Data for Category list API.
181 *
182 * @return void
183 */
184 public function get_demo_categories( array $data ) {
185 $type = $data['type'] ?? 'pattern';
186 $key = "ablocks_demo_categories_$type";
187 $has_response = get_transient( $key );
188 if ( $has_response ) {
189 wp_send_json_success( $has_response );
190 }
191
192 $url = 'https://' . ABLOCKS_TEMPLATE_LIB_HOST . '/wp-json/ablocks_server/v1/categories';
193 $url = add_query_arg( 'type', $type, $url );
194 $this->handle_list_response( $url, $key );
195 }
196
197 /**
198 * Get theme demos.
199 *
200 * @return void
201 */
202 public function get_theme_demos() {
203 $demo_config = Helper::get_theme_demo_config();
204 if ( ! $demo_config ) {
205 wp_send_json_error( [
206 'message' => 'Current theme demo isn\'t configured.',
207 ] );
208 }
209
210 $demos = $demo_config['demos'];
211 $categories = [];
212 foreach ( $demos as &$demo ) {
213 $demo_categories = [];
214 foreach ( $demo['categories'] as $category ) {
215 if ( is_array( $category ) ) {
216 $categories[] = $category;
217 $demo_categories[] = $category;
218 } else {
219 $demo_category = [
220 'label' => ucfirst( $category ),
221 'slug' => str_replace( ' ', '-', trim( $category ) ),
222 ];
223 $categories[] = $demo_category;
224 $demo_categories[] = $demo_category;
225 }
226 }
227 $demo['categories'] = $demo_categories;
228 }
229
230 $preloaded_categories = array_map( fn( $category ) => is_array( $category ) ? $category : [
231 'label' => ucfirst( $category ),
232 'slug' => str_replace( ' ', '-', trim( $category ) ),
233 ], $demo_config['preloaded_demo_category'] );
234
235 $categories_slugs = array_map( fn( $category ) => $category['slug'], $categories );
236 foreach ( $preloaded_categories as $preloaded_category ) {
237 if ( ! in_array( $preloaded_category['slug'], $categories_slugs, true ) ) {
238 $categories[] = $preloaded_category;
239 }
240 }
241
242 wp_send_json_success( array(
243 'categories' => $categories,
244 'preloaded_demo' => $demo_config['preloaded_demo'],
245 'preloaded_demo_categories' => $preloaded_categories,
246 'demos' => $demos,
247 ) );
248 }
249
250 /**
251 * Check dependencies before importing pattern/page/template.
252 *
253 * @param array $data Dependency Data.
254 *
255 * @return void
256 */
257 public function check_dependencies( array $data ) {
258 if ( ! isset( $data['dependencies'] ) ) {
259 return;
260 }
261
262 $dependencies = Sanitizer::sanitize_array_field( $data['dependencies'] );
263 foreach ( $dependencies as $index => $dependency ) {
264 $type = 'check_' . ( $dependency['type'] ?? 'plugin' );
265 $status = Helper::$type( $dependency['slug'] );
266 $dependencies[ $index ]['status'] = $status;
267 if ( isset( $dependency['id'] ) ) {
268 $dependencies[ $index ]['id'] = (int) $dependency['id'];
269 }
270 }
271
272 wp_send_json_success( $dependencies );
273 }
274
275 /**
276 * Install and active theme/plugin from ajax request.
277 *
278 * @param array $data post-data.
279 *
280 * @return void
281 */
282 public function install_and_active( array $data ) {
283 if ( ! isset( $data['dependency'] ) ) {
284 return;
285 }
286 $dependency = Sanitizer::sanitize_array_field( $data['dependency'] );
287 $method = 'install_and_active_' . ( $dependency['type'] ?? 'plugin' );
288 $activated = Helper::$method( $dependency['slug'] );
289 if ( is_wp_error( $activated ) ) {
290 wp_send_json_error( array(
291 'message' => $activated->get_error_message(),
292 ) );
293 }
294
295 wp_send_json_success();
296 }
297
298 /**
299 * Import template from file url.
300 *
301 * @param array $data Import data.
302 *
303 * @return void
304 */
305 public function import_template( array $data ) {
306 if ( ! isset( $data['file_url'] ) ) {
307 return;
308 }
309
310 $file_url = $data['file_url'];
311 $content_file_path = Helper::remote_to_tmp_file( $file_url );
312
313 $customizer_file_url = $data['customizer_file_url'] ?? '';
314 $customizer_file_path = Helper::remote_to_tmp_file( $customizer_file_url );
315 $widget_file_url = $data['widget_file_url'] ?? '';
316 $widget_file_path = Helper::remote_to_tmp_file( $widget_file_url );
317 $codestar_file_url = $data['codestar_file_url'] ?? '';
318 $codestar_file_path = Helper::remote_to_tmp_file( $codestar_file_url );
319 $with_images = isset( $data['with_images'] ) && true === $data['with_images'];
320
321 // Start the event stream.
322 header( 'Content-Type: text/event-stream, charset=UTF-8' );
323 header( 'Cache-Control: no-store' );
324 header( 'Connection: keep-alive' );
325
326 // Turn off PHP output compression.
327 // phpcs:disable WordPress.PHP.IniSet.Risky
328 ini_set( 'output_buffering', 'off' );
329 ini_set( 'zlib.output_compression', false );
330 // phpcs:enable WordPress.PHP.IniSet.Risky
331
332 if ( $GLOBALS['is_nginx'] ) {
333 // Setting this header instructs Nginx to disable fast-cgi buffering
334 // and disable gzip for this request.
335 header( 'X-Accel-Buffering: no' );
336 header( 'Content-Encoding: none' );
337 }
338
339 echo esc_html( ':' . str_repeat( ' ', 2048 ) . "\n\n" ); // 2KB padding for IE.
340
341 set_time_limit( 0 );
342
343 // Ensure we're not buffered.
344 wp_ob_end_flush_all();
345 flush();
346
347 if ( is_wp_error( $content_file_path ) ) {
348 Helper::emit_sse_message( [
349 'action' => 'complete',
350 'error' => is_string( $codestar_file_path->get_error_message() ) && ! empty( $codestar_file_path->get_error_message() ) ? $codestar_file_path->get_error_code() : __( 'Invalid content path.', 'ablocks' ),
351 ] );
352 exit;
353 }
354
355 do_action( 'ablocks/import/before_template_import_start', $data );
356
357 if ( ! Helper::get_addon_active_status( 'theme-builder' ) && ! Helper::is_fse_theme() ) {
358 $saved_addons = json_decode( get_option( ABLOCKS_ADDONS_SETTINGS_NAME, '{}' ), true );
359 if ( ! is_array( $saved_addons ) ) {
360 $saved_addons = [];
361 }
362
363 $addon_slug = 'theme-builder';
364 $saved_addons[ $addon_slug ] = true;
365 do_action( "ablocks/addons/activated_$addon_slug" );
366
367 update_option( ABLOCKS_ADDONS_SETTINGS_NAME, wp_json_encode( $saved_addons ) );
368 ( new Database() )->create_ablocks_tb_post_type();
369 ( new Database() )->register_ablocks_tb_meta();
370 }
371
372 $template_import = Helper::import_template( $content_file_path, $with_images );
373 if ( ! is_wp_error( $template_import ) ) {
374 if ( ! empty( $customizer_file_path ) && ! is_wp_error( $customizer_file_path ) ) {
375 CustomizerImporter::import( $customizer_file_path );
376 }
377 if ( ! empty( $widget_file_path ) && ! is_wp_error( $widget_file_path ) ) {
378 WidgetImporter::import( $widget_file_path );
379 }
380 if ( ! empty( $codestar_file_path ) ) {
381 CodeStar::import( $codestar_file_path );
382 }
383 if ( isset( $data['redux_options'] ) && is_array( $data['redux_options'] ) && count( $data['redux_options'] ) > 0 ) {
384 Redux::import( $data['redux_options'] );
385 }
386 }
387 do_action( 'ablocks/import/template_import_finished', $data );
388
389 // Let the browser know we're done.
390 $complete = [
391 'action' => 'complete',
392 'error' => false,
393 ];
394 if ( is_wp_error( $template_import ) ) {
395 $complete['error'] = $template_import->get_error_message();
396 }
397 Helper::emit_sse_message( $complete );
398 exit;
399 }
400
401 /**
402 * Handle common list response.
403 *
404 * @param string $url URL.
405 * @param string $key Transient key.
406 *
407 * @return void
408 */
409 private function handle_list_response( string $url, string $key ): void {
410 global $wp_version;
411 $response = wp_safe_remote_get( $url, array(
412 'headers' => array(
413 'Accept' => 'application/json',
414 'user-agent' => sprintf(
415 'aBlocks/%1$s (%2$s; WordPress/%3$s) %4$s',
416 ABLOCKS_VERSION,
417 get_option( 'blogname' ),
418 $wp_version,
419 home_url()
420 ),
421 ),
422 ) );
423 if ( is_wp_error( $response ) ) {
424 wp_send_json_error( [
425 'message' => $response->get_error_message()
426 ] );
427 }
428
429 $response_code = wp_remote_retrieve_response_code( $response );
430 $response = wp_remote_retrieve_body( $response );
431 $response = json_decode( $response, true );
432 if ( $response_code !== 200 || isset( $response['message'] ) ) {
433 wp_send_json_error( [
434 'message' => $response['message']
435 ] );
436 }
437
438 set_transient( $key, $response, WEEK_IN_SECONDS );
439 wp_send_json_success( $response );
440 }
441 }
442