PluginProbe
Gutenify – Visual Site Builder Blocks & Starter Templates / 1.8.0
Gutenify – Visual Site Builder Blocks & Starter Templates v1.8.0
1.9.0 1.8.0 1.7.0 1.6.6 1.6.5 1.6.4 trunk 0.0.1 0.0.2 0.0.3 1.0.0 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 All 74 releases
gutenify / core / inc / rest-api / class-rest.php

class-rest.php in Gutenify – Visual Site Builder Blocks & Starter Templates 1.8.0, at core/inc/rest-api/class-rest.php

649 lines 18.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Rest API functions.
4 *
5 * @package Gutenify
6 */
7
8 if ( ! defined( 'ABSPATH' ) ) {
9 exit;
10 }
11
12 /**
13 * Class Gutenify_Rest
14 */
15 class Gutenify_Rest extends WP_REST_Controller {
16 /**
17 * Namespace.
18 *
19 * @var string
20 */
21 protected $namespace = 'gutenify/v';
22
23 /**
24 * Version.
25 *
26 * @var string
27 */
28 protected $version = '1';
29
30 /**
31 * Gutenify_Rest constructor.
32 */
33 public function __construct() {
34 add_action( 'rest_api_init', array( $this, 'register_routes' ) );
35 }
36
37 /**
38 * Register rest routes.
39 */
40 public function register_routes() {
41 $namespace = $this->namespace . $this->version;
42
43 // Get Templates.
44 register_rest_route(
45 $namespace,
46 '/get_templates/',
47 array(
48 'methods' => WP_REST_Server::READABLE,
49 'callback' => array( $this, 'get_templates' ),
50 'permission_callback' => array( $this, 'update_settings_permission' ),
51 )
52 );
53
54 // Get template data.
55 register_rest_route(
56 $namespace,
57 '/get_template_data/',
58 array(
59 'methods' => WP_REST_Server::READABLE,
60 'callback' => array( $this, 'get_template_data' ),
61 'permission_callback' => array( $this, 'update_settings_permission' ),
62 )
63 );
64
65 // Get settings data.
66 register_rest_route(
67 $namespace,
68 '/get_settings/',
69 array(
70 'methods' => WP_REST_Server::READABLE,
71 'callback' => array( $this, 'get_settings' ),
72 'permission_callback' => array( $this, 'update_settings_permission' ),
73 )
74 );
75
76 // Update Settings.
77 register_rest_route(
78 $namespace,
79 '/update_settings/',
80 array(
81 'methods' => WP_REST_Server::EDITABLE,
82 'callback' => array( $this, 'update_settings' ),
83 'permission_callback' => array( $this, 'update_settings_permission' ),
84 )
85 );
86
87 // Get Templates.
88 register_rest_route(
89 $namespace,
90 '/get_site_options/',
91 array(
92 'methods' => WP_REST_Server::READABLE,
93 'callback' => array( $this, 'get_site_options' ),
94 'permission_callback' => array( $this, 'update_settings_permission' ),
95 )
96 );
97
98 // Update Site Optoins
99 register_rest_route(
100 $namespace,
101 '/update_site_options/',
102 array(
103 'methods' => WP_REST_Server::EDITABLE,
104 'callback' => array( $this, 'update_site_options' ),
105 'permission_callback' => array( $this, 'update_settings_permission' ),
106 )
107 );
108
109 // Update Site Optoins
110 register_rest_route(
111 $namespace,
112 '/update_global_styles/',
113 array(
114 'methods' => WP_REST_Server::EDITABLE,
115 'callback' => array( $this, 'update_global_styles' ),
116 'permission_callback' => array( $this, 'update_settings_permission' ),
117 )
118 );
119
120 // Get get_demo_categories.
121 register_rest_route(
122 $namespace,
123 '/get_demo_categories/',
124 array(
125 'methods' => WP_REST_Server::READABLE,
126 'callback' => array( $this, 'get_demo_categories' ),
127 'permission_callback' => array( $this, 'update_settings_permission' ),
128 )
129 );
130
131 }
132
133 /**
134 * Get templates.
135 *
136 * @return mixed
137 */
138 public function get_templates( WP_REST_Request $request ) {
139 $constants = \gutenify\Helpers::plugin_constants();
140 $plugin_main_slug = $constants['plugin_main_slug'];
141 $plugin_main_function_prefix = $constants['plugin_main_function_prefix'];
142 $plugin_main_base_url = $constants['plugin_main_base_url'];
143 $plugin_main_version = $constants['plugin_main_version'];
144 $plugin_main_post_type_prefix = $constants['plugin_main_post_type_prefix'];
145
146 $api_site = defined( 'GUTENIFY_API_URL' ) ? GUTENIFY_API_URL : 'https://demo.gutenify.com/';
147 $url = $api_site . 'wp-json/gutenify-library/v1/get_library/';
148 $templates = get_transient( 'gutenify_remote_templates', false );
149
150 $data = $request->get_params();
151
152 if ( ! empty( $data['reset'] ) && 'true' === $data['reset'] ) {
153 $templates = array();
154 }
155
156 /*
157 * Get remote templates.
158 */
159 if ( ! $templates ) {
160 $requested_templates = wp_remote_get(
161 add_query_arg(
162 array(
163 'gutenify_version' => '2.19.3',
164 'gutenify_pro' => false,
165 'gutenify_pro_version' => null,
166 ),
167 $url
168 )
169 );
170
171 if ( ! is_wp_error( $requested_templates ) ) {
172 $new_templates = wp_remote_retrieve_body( $requested_templates );
173 $new_templates = json_decode( $new_templates, true );
174
175 if ( $new_templates && isset( $new_templates['response'] ) && is_array( $new_templates['response'] ) ) {
176 $templates = $new_templates['response'];
177 set_transient( 'gutenify_remote_templates', $templates, DAY_IN_SECONDS );
178 }
179 }
180 }
181
182 // Remove Pro templates from array, cause for now there is no way to check if pro addon is activated.
183 if ( $templates ) {
184 foreach ( $templates as $k => $template ) {
185 $is_pro = false;
186
187 if ( isset( $template['types'] ) && is_array( $template['types'] ) ) {
188 foreach ( $template['types'] as $type ) {
189 $is_pro = $is_pro || 'pro' === $type['slug'];
190 }
191 }
192
193 if ( $is_pro ) {
194 unset( $templates[ $k ] );
195 }
196 }
197 }
198
199 /*
200 * Get user templates from db.
201 */
202
203 // Stupid hack.
204 // https://core.trac.wordpress.org/ticket/18408.
205 global $post;
206 $backup_global_post = $post;
207 $local_templates = array();
208
209 $local_templates_query = new WP_Query(
210 array(
211 'post_type' => $plugin_main_post_type_prefix . '_template',
212 'posts_per_page' => -1,
213 'showposts' => -1,
214 'paged' => -1,
215 )
216 );
217
218 while ( $local_templates_query->have_posts() ) {
219 $local_templates_query->the_post();
220 $db_template = get_post();
221
222 $categories = array();
223 $category_terms = get_the_terms( $db_template->ID, $plugin_main_post_type_prefix . '_template_category' );
224
225 if ( $category_terms ) {
226 foreach ( $category_terms as $cat ) {
227 $categories[] = array(
228 'slug' => $cat->slug,
229 'name' => $cat->name,
230 );
231 }
232 }
233
234 $image_id = get_post_thumbnail_id( $db_template->ID );
235 $image_data = wp_get_attachment_image_src( $image_id, 'large' );
236
237 $local_templates[] = array(
238 'id' => $db_template->ID,
239 'title' => $db_template->post_title,
240 'types' => array(
241 array(
242 'slug' => 'local',
243 ),
244 ),
245 'categories' => empty( $categories ) ? false : $categories,
246 'url' => get_post_permalink( $db_template->ID ),
247 'thumbnail' => isset( $image_data[0] ) ? $image_data[0] : false,
248 'thumbnail_width' => isset( $image_data[1] ) ? $image_data[1] : false,
249 'thumbnail_height' => isset( $image_data[2] ) ? $image_data[2] : false,
250 );
251 }
252
253 // Restore the global $post as it was before custom WP_Query.
254 // phpcs:ignore
255 $post = $backup_global_post;
256
257 /*
258 * Get theme templates.
259 */
260 $theme_templates = array();
261 $theme_templates_data = array();
262
263 foreach ( glob( get_template_directory() . '/gutenify/templates/*/content.php' ) as $template ) {
264 $template_path = dirname( $template );
265 $template_url = get_template_directory_uri() . str_replace( get_template_directory(), '', $template_path );
266 $slug = basename( $template_path );
267
268 $theme_templates_data[ $slug ] = array(
269 'slug' => $slug,
270 'path' => $template_path,
271 'url' => $template_url,
272 );
273 }
274
275 // get child theme templates.
276 if ( get_stylesheet_directory() !== get_template_directory() ) {
277 foreach ( glob( get_stylesheet_directory() . '/gutenify/templates/*/content.php' ) as $template ) {
278 $template_path = dirname( $template );
279 $template_url = get_stylesheet_directory_uri() . str_replace( get_stylesheet_directory(), '', $template_path );
280 $slug = basename( $template_path );
281
282 $theme_templates_data[ $slug ] = array(
283 'slug' => $slug,
284 'path' => $template_path,
285 'url' => $template_url,
286 );
287 }
288 }
289
290 // natural sort.
291 array_multisort( array_keys( $theme_templates_data ), SORT_NATURAL, $theme_templates_data );
292
293 foreach ( $theme_templates_data as $template_data ) {
294 $file_data = get_file_data(
295 $template_data['path'] . '/content.php',
296 array(
297 'name' => 'Name',
298 'category' => 'Category',
299 'source' => 'Source',
300 )
301 );
302
303 $thumbnail = false;
304 $thumbnail_width = false;
305 $thumbnail_height = false;
306
307 if ( file_exists( $template_data['path'] . '/thumbnail.png' ) ) {
308 $thumbnail = $template_data['url'] . '/thumbnail.png';
309
310 list($thumbnail_width, $thumbnail_height) = getimagesize( $thumbnail );
311 }
312
313 if ( file_exists( $template_data['path'] . '/thumbnail.jpg' ) ) {
314 $thumbnail = $template_data['url'] . '/thumbnail.jpg';
315 }
316
317 $theme_templates[] = array(
318 'id' => basename( $template_data['path'] ),
319 'title' => $file_data['name'],
320 'types' => array(
321 array(
322 'slug' => 'theme',
323 ),
324 ),
325 'categories' => isset( $file_data['category'] ) && $file_data['category'] ? array(
326 array(
327 'slug' => $file_data['category'],
328 'name' => $file_data['category'],
329 ),
330 ) : false,
331 'url' => false,
332 'thumbnail' => $thumbnail,
333 'thumbnail_width' => $thumbnail_width,
334 'thumbnail_height' => $thumbnail_height,
335 );
336 }
337
338 // merge all available templates.
339 $templates = ! empty( $templates ) ? $templates : array();
340 $templates = array_merge( $templates, $local_templates, $theme_templates );
341
342 if ( is_array( $templates ) ) {
343 return $this->success( $templates );
344 } else {
345 return $this->error( 'no_templates', __( 'Templates not found.', 'gutenify' ) );
346 }
347 }
348
349 /**
350 * Get templates.
351 *
352 * @param WP_REST_Request $request request object.
353 *
354 * @return mixed
355 */
356 public function get_template_data( WP_REST_Request $request ) {
357 $constants = \gutenify\Helpers::plugin_constants();
358 $plugin_main_slug = $constants['plugin_main_slug'];
359 $plugin_main_function_prefix = $constants['plugin_main_function_prefix'];
360 $plugin_main_base_url = $constants['plugin_main_base_url'];
361 $plugin_main_version = $constants['plugin_main_version'];
362 $plugin_main_post_type_prefix = $constants['plugin_main_post_type_prefix'];
363
364 $api_site = defined( 'GUTENIFY_API_URL' ) ? GUTENIFY_API_URL : 'https://demo.gutenify.com/';
365 $url = $api_site . 'wp-json/gutenify-library/v1/get_library_data/';
366 $id = $request->get_param( 'id' );
367 $type = $request->get_param( 'type' );
368 $template_data = false;
369
370 if ( 1 > absint( $id ) || empty( $type ) ) {
371 return $this->error( 'no_template_data', __( 'Template data not found.', 'gutenify' ) );
372 }
373
374 $id = absint( $id );
375 $fast = ! empty( $request->get_param( 'fast' ) );
376
377 switch ( $type ) {
378 case 'remote':
379 $cache_key = 'gutenify_template_' . $type . '_' . $id;
380 $template_data = get_transient( $cache_key, false );
381
382 if ( ! $template_data ) {
383 $url = add_query_arg(
384 apply_filters(
385 'gutenify_rest_template_data_url_args',
386 array(
387 'id' => $id,
388 'gutenify_version' => GUTENIFY_VERSION,
389 'site_url' => site_url( '/' ),
390 )
391 ),
392 $url
393 );
394
395 $requested_template_data = wp_remote_get( $url );
396
397 if ( ! is_wp_error( $requested_template_data ) ) {
398 $new_template_data = wp_remote_retrieve_body( $requested_template_data );
399 $new_template_data = json_decode( $new_template_data, true );
400
401 if ( $new_template_data && isset( $new_template_data['response'] ) && is_array( $new_template_data['response'] ) ) {
402 $template_data = $new_template_data['response'];
403
404 if ( $fast ) {
405 // Editor-insert fast path: return the raw
406 // content immediately with remote image URLs
407 // still in place, so the click isn't blocked
408 // on every image's download. Deliberately
409 // NOT cached — the client follows up with a
410 // non-fast request (see 'needs_sideload'
411 // below) that does the real sideload and
412 // caches the result once it's actually done.
413 } elseif ( ! empty( $template_data['content'] ) ) {
414 $template_data['content'] = \gutenify\Helpers::sideload_remote_images( $template_data['content'], $api_site );
415 set_transient( $cache_key, $template_data, DAY_IN_SECONDS );
416 }
417 }
418 }
419 }
420 break;
421 case 'local':
422 $post = get_post( $id );
423
424 if ( $post && $plugin_main_post_type_prefix . '_template' === $post->post_type && 'publish' === $post->post_status ) {
425 $template_data = array(
426 'id' => $post->ID,
427 'title' => $post->post_title,
428 'content' => $post->post_content,
429 );
430 }
431
432 break;
433 }
434
435 if ( is_array( $template_data ) ) {
436 // Tells the client whether this response still has remote image
437 // URLs left to resolve — true for a 'fast' response, and also
438 // true if a normal (non-fast) sideload pass didn't fully
439 // succeed (e.g. one image's download failed). The editor uses
440 // this to decide whether a background follow-up + block-patch
441 // is needed at all.
442 $template_data['needs_sideload'] = ! empty( $template_data['content'] )
443 && \gutenify\Helpers::has_remote_images( $template_data['content'], $api_site );
444
445 return $this->success( $template_data );
446 } else {
447 return $this->error( 'no_template_data', __( 'Template data not found.', 'gutenify' ) );
448 }
449 }
450
451 /**
452 * Get settings.
453 *
454 * @return mixed
455 */
456 public function get_settings() {
457 $settings = gutenify_settings();
458
459 if ( is_array( $settings ) ) {
460 return $this->success( $settings );
461 } else {
462 return $this->error( 'no_settings', __( 'Settings data not found.', 'gutenify' ) );
463 }
464 }
465
466 /**
467 * Get edit options permissions.
468 *
469 * @return bool
470 */
471 public function update_settings_permission() {
472 return current_user_can( 'manage_options' );
473 }
474
475 /**
476 * Update Settings.
477 *
478 * @param WP_REST_Request $request request object.
479 *
480 * @return mixed
481 */
482 public function update_settings( WP_REST_Request $request ) {
483 $new_settings = $request->get_param( 'settings' );
484
485 if ( is_array( $new_settings ) ) {
486 $current_settings = get_option( 'gutenify_settings', array() );
487 update_option( 'gutenify_settings', array_merge( $current_settings, $new_settings ) );
488 }
489
490 return $this->success( true );
491 }
492
493 public function get_site_options() {
494 $options = get_option( 'gutenify_site_options' );
495 return $this->success( $options );
496 }
497
498 /**
499 * Update site options.
500 *
501 * @param WP_REST_Request $request request object.
502 *
503 * @return mixed
504 */
505 public function update_site_options( WP_REST_Request $request ) {
506 $options = $request->get_params();
507 $merged_options = array();
508 if ( is_array( $options ) ) {
509 $current_options = get_option( 'gutenify_site_options', array() );
510 if ( empty( $current_options ) ) {
511 $current_options = array();
512 }
513 $merged_options = array_merge( $current_options, $options );
514
515 // $site_fonts = array();
516 // if ( ! empty( $merged_options['styles']['siteFonts'] ) ) {
517 // $site_settings = wp_get_global_settings();
518 // $site_styles = wp_get_global_styles();
519 // $default_font_families = ! empty( $site_settings['typography']['fontFamilies']['theme'] )? $site_settings['typography']['fontFamilies']['theme'] : array();
520 // $default_font_families_slugs = wp_list_pluck( $default_font_families, 'slug' );
521 // error_log( print_r( $default_font_families_slugs, true ));
522 // foreach( $merged_options['styles']['siteFonts'] as $font ) {
523 // if ( ! in_array( $font['value'], $default_font_families_slugs, true ) ) {
524 // $site_fonts[] = array(
525 // 'fontFamily' => $font['label'],
526 // 'name' => $font['label'],
527 // 'slug' => $font['value'],
528 // );
529 // }
530 // }
531 // $new_font_families = array_merge( $default_font_families, $site_fonts );
532 // error_log( print_r( $new_font_families, true ));
533 // $site_settings['typography']['fontFamilies']['theme'] = $new_font_families;
534
535 // gutenify_update_global_styles( $site_settings, $site_styles );
536 // }
537
538 // Ideally the call to update_item would delete all of the appropriate transients and caches
539 delete_transient( 'global_styles' );
540 delete_transient( 'global_styles_' . get_stylesheet() );
541 delete_transient( 'gutenberg_global_styles' );
542 delete_transient( 'gutenberg_global_styles_' . get_stylesheet() );
543
544 if ( class_exists( 'wp_theme_json_resolver' ) ) {
545 wp_theme_json_resolver::clean_cached_data();
546 }
547 update_option( 'gutenify_site_options', array_merge( $current_options, $options ) );
548 }
549
550 return $this->success( $merged_options );
551 }
552
553 /**
554 * Update site options.
555 *
556 * @param WP_REST_Request $request request object.
557 *
558 * @return mixed
559 */
560 public function update_global_styles( WP_REST_Request $request ) {
561 $options = (array) $request->get_params();
562
563 if ( isset( $options['css'] ) ) {
564 // Sanitize CSS at save-time: strip any HTML tags before storing.
565 update_option( 'gutenify_global_style', wp_strip_all_tags( $options['css'] ) );
566 }
567
568 return $this->success( $options );
569 }
570
571 public function get_demo_categories( WP_REST_Request $request ) {
572 $options = (array) $request->get_params();
573 $demo_categories = false;
574 if ( empty( $options['force'] ) || 'false' === $options['force'] ) {
575 $demo_categories = get_transient( 'gutenify_demo_categories', false );
576 }
577 if ( false === $demo_categories ) {
578 $error = $this->error( 'error_demo_categories', __( 'Error listing demo', 'gutenify' ) );
579
580 try {
581 $url = 'https://demo.gutenify.com/wp-json/demo-api/v1/get_demo_categories';
582 // 'https://api.github.com/repos/gutenify/demo-content/contents/themes'
583 /** @var array|WP_Error $response */
584 $response = wp_remote_get(
585 $url,
586 array(
587 'timeout' => 120,
588 'httpversion' => '1.1',
589 'headers' => array(
590 'Accept' => 'application/json',
591 ),
592 )
593 );
594 if ( ( ! is_wp_error( $response ) ) && ( 200 === wp_remote_retrieve_response_code( $response ) ) ) {
595 if ( $body = wp_remote_retrieve_body( $response ) ) {
596 $responseBody = json_decode( $body );
597 $categories = array();
598 if ( ! empty( $responseBody ) && ! empty( $responseBody->response ) ) {
599 $categories = $responseBody->response;
600 }
601 set_transient( 'gutenify_demo_categories', json_encode( $categories ), DAY_IN_SECONDS );
602 return $this->success( $categories );
603 }
604 return $error;
605 }
606 } catch ( Exception $ex ) {
607 return $error;
608 }
609 }
610 return $this->success( json_decode( $demo_categories ) );
611 }
612
613 /**
614 * Success rest.
615 *
616 * @param mixed $response response data.
617 * @return mixed
618 */
619 public function success( $response ) {
620 return new WP_REST_Response(
621 array(
622 'success' => true,
623 'response' => $response,
624 ),
625 200
626 );
627 }
628
629 /**
630 * Error rest.
631 *
632 * @param mixed $code error code.
633 * @param mixed $response response data.
634 * @return mixed
635 */
636 public function error( $code, $response ) {
637 return new WP_REST_Response(
638 array(
639 'error' => true,
640 'success' => false,
641 'error_code' => $code,
642 'response' => $response,
643 ),
644 401
645 );
646 }
647 }
648 new Gutenify_Rest();
649