PluginProbe
aBlocks – Gutenberg Blocks, User Dashboard Builder, Popup Builder, Form Builder & Animation Builder / 2.14.0
aBlocks – Gutenberg Blocks, User Dashboard Builder, Popup Builder, Form Builder & Animation Builder v2.14.0
2.14.0 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 All 81 releases
ablocks / includes / ajax / demo-import.php

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

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