PluginProbe
Block Animations, Motion & Scroll Effects – Ghost Kit / 2.25.0
Block Animations, Motion & Scroll Effects – Ghost Kit v2.25.0
3.7.2 3.7.1 3.7.0 3.6.1 trunk 1.6.3 2.25.0 3.3.0 3.3.1 3.3.2 3.3.3 3.4.0 3.4.1 3.4.2 3.4.3 3.4.4 3.4.5 3.4.6 3.5.0 3.5.1 3.6.0
ghostkit / classes / class-rest.php

class-rest.php in Block Animations, Motion & Scroll Effects – Ghost Kit 2.25.0, at classes/class-rest.php

1,794 lines 62.1 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 ghostkit
6 */
7
8 if ( ! defined( 'ABSPATH' ) ) {
9 exit;
10 }
11
12 /**
13 * Class GhostKit_Rest
14 */
15 class GhostKit_Rest extends WP_REST_Controller {
16 /**
17 * Namespace.
18 *
19 * @var string
20 */
21 protected $namespace = 'ghostkit/v';
22
23 /**
24 * Version.
25 *
26 * @var string
27 */
28 protected $version = '1';
29
30 /**
31 * GhostKit_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 layouts list.
44 register_rest_route(
45 $namespace,
46 '/get_customizer/',
47 array(
48 'methods' => WP_REST_Server::READABLE,
49 'callback' => array( $this, 'get_customizer' ),
50 'permission_callback' => array( $this, 'get_customizer_permission' ),
51 )
52 );
53
54 // Get attachment image <img> tag.
55 register_rest_route(
56 $namespace,
57 '/get_attachment_image/(?P<id>[\d]+)',
58 array(
59 'methods' => WP_REST_Server::READABLE,
60 'callback' => array( $this, 'get_attachment_image' ),
61 'permission_callback' => array( $this, 'get_attachment_image_permission' ),
62 )
63 );
64
65 // Get Instagram profile.
66 register_rest_route(
67 $namespace,
68 '/get_instagram_profile/',
69 array(
70 'methods' => WP_REST_Server::READABLE,
71 'callback' => array( $this, 'get_instagram_profile' ),
72 'permission_callback' => array( $this, 'get_instagram_profile_permission' ),
73 )
74 );
75
76 // Get Instagram feed.
77 register_rest_route(
78 $namespace,
79 '/get_instagram_feed/',
80 array(
81 'methods' => WP_REST_Server::READABLE,
82 'callback' => array( $this, 'get_instagram_feed' ),
83 'permission_callback' => array( $this, 'get_instagram_feed_permission' ),
84 )
85 );
86
87 // Get Twitter profile.
88 register_rest_route(
89 $namespace,
90 '/get_twitter_profile/',
91 array(
92 'methods' => WP_REST_Server::READABLE,
93 'callback' => array( $this, 'get_twitter_profile' ),
94 'permission_callback' => array( $this, 'get_twitter_profile_permission' ),
95 )
96 );
97
98 // Get Twitter feed.
99 register_rest_route(
100 $namespace,
101 '/get_twitter_feed/',
102 array(
103 'methods' => WP_REST_Server::READABLE,
104 'callback' => array( $this, 'get_twitter_feed' ),
105 'permission_callback' => array( $this, 'get_twitter_feed_permission' ),
106 )
107 );
108
109 // Get TOC.
110 register_rest_route(
111 $namespace,
112 '/get_table_of_contents/',
113 array(
114 'methods' => WP_REST_Server::READABLE,
115 'callback' => array( $this, 'get_table_of_contents' ),
116 'permission_callback' => '__return_true',
117 )
118 );
119
120 // Get Templates.
121 register_rest_route(
122 $namespace,
123 '/get_templates/',
124 array(
125 'methods' => WP_REST_Server::READABLE,
126 'callback' => array( $this, 'get_templates' ),
127 'permission_callback' => '__return_true',
128 )
129 );
130
131 // Get template data.
132 register_rest_route(
133 $namespace,
134 '/get_template_data/',
135 array(
136 'methods' => WP_REST_Server::READABLE,
137 'callback' => array( $this, 'get_template_data' ),
138 'permission_callback' => '__return_true',
139 )
140 );
141
142 // Get Custom Code.
143 register_rest_route(
144 $namespace,
145 '/get_custom_code/',
146 array(
147 'methods' => WP_REST_Server::READABLE,
148 'callback' => array( $this, 'get_custom_code' ),
149 'permission_callback' => array( $this, 'get_custom_code_permission' ),
150 )
151 );
152
153 // Update Custom Code.
154 register_rest_route(
155 $namespace,
156 '/update_custom_code/',
157 array(
158 'methods' => WP_REST_Server::EDITABLE,
159 'callback' => array( $this, 'update_custom_code' ),
160 'permission_callback' => array( $this, 'update_custom_code_permission' ),
161 )
162 );
163
164 // Update Color Palette.
165 register_rest_route(
166 $namespace,
167 '/update_color_palette/',
168 array(
169 'methods' => WP_REST_Server::EDITABLE,
170 'callback' => array( $this, 'update_color_palette' ),
171 'permission_callback' => array( $this, 'update_color_palette_permission' ),
172 )
173 );
174
175 // Get Typography.
176 register_rest_route(
177 $namespace,
178 '/get_custom_typography/',
179 array(
180 'methods' => WP_REST_Server::READABLE,
181 'callback' => array( $this, 'get_custom_typography' ),
182 'permission_callback' => array( $this, 'get_custom_typography_permission' ),
183 )
184 );
185
186 // Update Typography.
187 register_rest_route(
188 $namespace,
189 '/update_custom_typography/',
190 array(
191 'methods' => WP_REST_Server::EDITABLE,
192 'callback' => array( $this, 'update_custom_typography' ),
193 'permission_callback' => array( $this, 'update_custom_typography_permission' ),
194 )
195 );
196
197 // Update Google Maps API key.
198 register_rest_route(
199 $namespace,
200 '/update_google_maps_api_key/',
201 array(
202 'methods' => WP_REST_Server::EDITABLE,
203 'callback' => array( $this, 'update_google_maps_api_key' ),
204 'permission_callback' => array( $this, 'update_google_maps_api_key_permission' ),
205 )
206 );
207
208 // Update Google reCaptcha keys.
209 register_rest_route(
210 $namespace,
211 '/update_google_recaptcha_keys/',
212 array(
213 'methods' => WP_REST_Server::EDITABLE,
214 'callback' => array( $this, 'update_google_recaptcha_keys' ),
215 'permission_callback' => array( $this, 'update_google_recaptcha_keys_permission' ),
216 )
217 );
218
219 // Update Disabled Blocks.
220 register_rest_route(
221 $namespace,
222 '/update_disabled_blocks/',
223 array(
224 'methods' => WP_REST_Server::EDITABLE,
225 'callback' => array( $this, 'update_disabled_blocks' ),
226 'permission_callback' => array( $this, 'update_disabled_blocks_permission' ),
227 )
228 );
229
230 // Update Settings.
231 register_rest_route(
232 $namespace,
233 '/update_settings/',
234 array(
235 'methods' => WP_REST_Server::EDITABLE,
236 'callback' => array( $this, 'update_settings' ),
237 'permission_callback' => array( $this, 'update_settings_permission' ),
238 )
239 );
240 }
241
242 /**
243 * Get read customizer permissions.
244 *
245 * @return bool
246 */
247 public function get_customizer_permission() {
248 if ( ! current_user_can( 'edit_theme_options' ) ) {
249 return $this->error( 'user_dont_have_permission', __( 'User don\'t have permissions to change Customizer options.', 'ghostkit' ), true );
250 }
251 return true;
252 }
253
254 /**
255 * Get attachment image <img> tag permissions.
256 *
257 * @return bool
258 */
259 public function get_attachment_image_permission() {
260 return true;
261 }
262
263 /**
264 * Get Instagram feed permissions.
265 *
266 * @return bool
267 */
268 public function get_instagram_feed_permission() {
269 return true;
270 }
271
272 /**
273 * Get Instagram profile permissions.
274 *
275 * @return bool
276 */
277 public function get_instagram_profile_permission() {
278 return true;
279 }
280
281 /**
282 * Get Twitter feed permissions.
283 *
284 * @return bool
285 */
286 public function get_twitter_feed_permission() {
287 return true;
288 }
289
290 /**
291 * Get Twitter profile permissions.
292 *
293 * @return bool
294 */
295 public function get_twitter_profile_permission() {
296 return true;
297 }
298
299 /**
300 * Get read custom code permissions.
301 *
302 * @return bool
303 */
304 public function get_custom_code_permission() {
305 if ( ! current_user_can( 'edit_theme_options' ) ) {
306 return $this->error( 'user_dont_have_permission', __( 'User don\'t have permissions to change options.', 'ghostkit' ), true );
307 }
308
309 return true;
310 }
311
312 /**
313 * Get edit custom code permissions.
314 *
315 * @return bool
316 */
317 public function update_custom_code_permission() {
318 if ( ! current_user_can( 'manage_options' ) ) {
319 return $this->error( 'user_dont_have_permission', __( 'User don\'t have permissions to change options.', 'ghostkit' ), true );
320 }
321
322 return true;
323 }
324
325 /**
326 * Get edit color palette permissions.
327 *
328 * @return bool
329 */
330 public function update_color_palette_permission() {
331 if ( ! current_user_can( 'manage_options' ) ) {
332 return $this->error( 'user_dont_have_permission', __( 'User don\'t have permissions to change options.', 'ghostkit' ), true );
333 }
334
335 return true;
336 }
337
338 /**
339 * Get read typography permissions.
340 *
341 * @return bool
342 */
343 public function get_custom_typography_permission() {
344 if ( ! current_user_can( 'edit_theme_options' ) ) {
345 return $this->error( 'user_dont_have_permission', __( 'User don\'t have permissions to change options.', 'ghostkit' ), true );
346 }
347
348 return true;
349 }
350
351 /**
352 * Get edit typography permissions.
353 *
354 * @return bool
355 */
356 public function update_custom_typography_permission() {
357 if ( ! current_user_can( 'manage_options' ) ) {
358 return $this->error( 'user_dont_have_permission', __( 'User don\'t have permissions to change options.', 'ghostkit' ), true );
359 }
360
361 return true;
362 }
363
364 /**
365 * Get read Google Maps API key permissions.
366 *
367 * @return bool
368 */
369 public function update_google_maps_api_key_permission() {
370 if ( ! current_user_can( 'manage_options' ) ) {
371 return $this->error( 'user_dont_have_permission', __( 'User don\'t have permissions to change options.', 'ghostkit' ), true );
372 }
373
374 return true;
375 }
376
377 /**
378 * Get read Google reCaptcha API keys permissions.
379 *
380 * @return bool
381 */
382 public function update_google_recaptcha_keys_permission() {
383 if ( ! current_user_can( 'manage_options' ) ) {
384 return $this->error( 'user_dont_have_permission', __( 'User don\'t have permissions to change options.', 'ghostkit' ), true );
385 }
386
387 return true;
388 }
389
390 /**
391 * Get edit options permissions.
392 *
393 * @return bool
394 */
395 public function update_disabled_blocks_permission() {
396 if ( ! current_user_can( 'manage_options' ) ) {
397 return $this->error( 'user_dont_have_permission', __( 'User don\'t have permissions to change options.', 'ghostkit' ), true );
398 }
399
400 return true;
401 }
402
403 /**
404 * Get edit options permissions.
405 *
406 * @return bool
407 */
408 public function update_settings_permission() {
409 if ( ! current_user_can( 'manage_options' ) ) {
410 return $this->error( 'user_dont_have_permission', __( 'User don\'t have permissions to change options.', 'ghostkit' ), true );
411 }
412
413 return true;
414 }
415
416 /**
417 * Get customizer data.
418 *
419 * @return mixed
420 */
421 public function get_customizer() {
422 $options = get_option( 'ghostkit_customizer_fields' );
423
424 if ( ! empty( $options ) ) {
425 return $this->success( $options );
426 } else {
427 return $this->error( 'no_options_found', __( 'Options not found.', 'ghostkit' ) );
428 }
429 }
430
431 /**
432 * Get attachment image <img> tag.
433 *
434 * @param WP_REST_Request $request request object.
435 *
436 * @return mixed
437 */
438 public function get_attachment_image( WP_REST_Request $request ) {
439 $id = $request->get_param( 'id' );
440 $size = $request->get_param( 'size' );
441 $icon = $request->get_param( 'icon' );
442 $attr = $request->get_param( 'attr' );
443 $div_tag = $request->get_param( 'div_tag' );
444
445 if ( ! $id ) {
446 return $this->error( 'no_id_found', __( 'Provide image ID.', 'ghostkit' ) );
447 }
448
449 $attr = isset( $attr ) && $attr && is_array( $attr ) ? $attr : array();
450
451 if ( $div_tag ) {
452 $image_url = wp_get_attachment_image_url( $id, $size, $icon );
453
454 if ( ! isset( $attr['style'] ) ) {
455 $attr['style'] = '';
456 }
457
458 $attr['style'] .= 'background-image: url("' . esc_url( $image_url ) . '");';
459
460 $attr = array_map( 'esc_attr', $attr );
461 $image = '<div';
462
463 foreach ( $attr as $name => $value ) {
464 $image .= " $name=" . '"' . $value . '"';
465 }
466
467 $image .= '></div>';
468 } else {
469 $image_src = wp_get_attachment_image_src( $id, $size, $icon );
470
471 if ( $image_src ) {
472 list( $src, $width, $height ) = $image_src;
473
474 $alt = trim( wp_strip_all_tags( get_post_meta( $id, '_wp_attachment_image_alt', true ) ) );
475
476 if ( $alt ) {
477 $attr['alt'] = $alt;
478 }
479
480 if ( ! isset( $attr['class'] ) ) {
481 $attr['class'] = 'wp-image-' . $id;
482 } else {
483 $attr['class'] = 'wp-image-' . $id . ' ' . $attr['class'];
484 }
485
486 $attr['width'] = $width;
487 $attr['height'] = $height;
488
489 $attrs_str = '';
490
491 if ( isset( $attr ) && is_array( $attr ) ) {
492 foreach ( $attr as $name => $val ) {
493 $attrs_str .= ' ' . $name . '="' . esc_attr( $val ) . '"';
494 }
495 }
496
497 $image = '<img src="' . esc_url( $src ) . '"' . $attrs_str . ' />';
498 }
499 }
500
501 if ( isset( $image ) && $image ) {
502 return $this->success( $image );
503 } else {
504 return $this->error( 'no_image_found', __( 'Image not found.', 'ghostkit' ) );
505 }
506 }
507
508 /**
509 * Get Instagram feed.
510 *
511 * @param WP_REST_Request $request request object.
512 *
513 * @return mixed
514 */
515 public function get_instagram_feed( WP_REST_Request $request ) {
516 $cache_name = 'ghostkit_instagram_feed_cache';
517 $cache_expiration = $request->get_param( 'cache_expiration' ) ? $request->get_param( 'cache_expiration' ) : DAY_IN_SECONDS;
518 $count = $request->get_param( 'count' ) ? $request->get_param( 'count' ) : 6;
519 $access_token = $request->get_param( 'access_token' );
520
521 if ( ! $access_token ) {
522 return $this->error( 'no_token_found', __( 'Provide Instagram Access Token.', 'ghostkit' ) );
523 }
524
525 $hash = md5(
526 wp_json_encode(
527 array(
528 $access_token,
529 $count,
530 $cache_expiration,
531 )
532 )
533 );
534
535 $cache_name = $cache_name . '_' . $hash;
536
537 // get cached data.
538 $result = get_transient( $cache_name );
539
540 // if there is no cache available, request instagram feed.
541 if ( false === $result && $access_token ) {
542 // Make Requests.
543 $feed = wp_remote_get( 'https://api.instagram.com/v1/users/self/media/recent/?access_token=' . $access_token . '&count=' . $count );
544
545 if ( ! is_wp_error( $feed ) && isset( $feed['body'] ) ) {
546 $feed = json_decode( $feed['body'], true );
547 } else {
548 $feed = false;
549 }
550
551 if ( $feed && is_array( $feed ) ) {
552 $result = $feed;
553 set_transient( $cache_name, $result, $cache_expiration );
554 }
555 }
556
557 if ( $result ) {
558 return $this->success( $result );
559 } else {
560 return $this->error( 'no_instagram_data_loaded', __( 'Instagram data failed to load.', 'ghostkit' ) );
561 }
562 }
563
564 /**
565 * Get Instagram profile.
566 *
567 * @param WP_REST_Request $request request object.
568 *
569 * @return mixed
570 */
571 public function get_instagram_profile( WP_REST_Request $request ) {
572 $cache_name = 'ghostkit_instagram_profile_cache';
573 $cache_expiration = $request->get_param( 'cache_expiration' ) ? $request->get_param( 'cache_expiration' ) : DAY_IN_SECONDS;
574 $access_token = $request->get_param( 'access_token' );
575
576 if ( ! $access_token ) {
577 return $this->error( 'no_token_found', __( 'Provide Instagram Access Token.', 'ghostkit' ) );
578 }
579
580 $hash = md5(
581 wp_json_encode(
582 array(
583 $access_token,
584 $cache_expiration,
585 )
586 )
587 );
588
589 $cache_name = $cache_name . '_' . $hash;
590
591 // get cached data.
592 $result = get_transient( $cache_name );
593
594 // if there is no cache available, request instagram feed.
595 if ( false === $result && $access_token ) {
596 // Make Requests.
597 $profile = wp_remote_get( 'https://api.instagram.com/v1/users/self/?access_token=' . $access_token );
598
599 if ( ! is_wp_error( $profile ) && isset( $profile['body'] ) ) {
600 $profile = json_decode( $profile['body'], true );
601 } else {
602 $profile = false;
603 }
604
605 if ( $profile && is_array( $profile ) ) {
606 $result = $profile;
607 set_transient( $cache_name, $result, $cache_expiration );
608 }
609 }
610
611 if ( $result ) {
612 return $this->success( $result );
613 } else {
614 return $this->error( 'no_instagram_data_loaded', __( 'Instagram data failed to load.', 'ghostkit' ) );
615 }
616 }
617
618 /**
619 * Get Twitter profile.
620 *
621 * @param WP_REST_Request $request request object.
622 *
623 * @return mixed
624 */
625 public function get_twitter_profile( WP_REST_Request $request ) {
626 $cache_name = 'ghostkit_twitter_profile_cache';
627 $cache_expiration = $request->get_param( 'cache_expiration' ) ? $request->get_param( 'cache_expiration' ) : DAY_IN_SECONDS;
628
629 $consumer_key = $request->get_param( 'consumer_key' );
630 $consumer_secret = $request->get_param( 'consumer_secret' );
631 $access_token = $request->get_param( 'access_token' );
632 $access_token_secret = $request->get_param( 'access_token_secret' );
633 $screen_name = $request->get_param( 'screen_name' );
634
635 if ( ! $consumer_key ) {
636 return $this->error( 'no_consumer_key_found', __( 'Provide Twitter Consumer Key.', 'ghostkit' ) );
637 }
638 if ( ! $consumer_secret ) {
639 return $this->error( 'no_consumer_secret_found', __( 'Provide Twitter Consumer Secret.', 'ghostkit' ) );
640 }
641 if ( ! $access_token ) {
642 return $this->error( 'no_access_token_found', __( 'Provide Twitter Access Token.', 'ghostkit' ) );
643 }
644 if ( ! $access_token_secret ) {
645 return $this->error( 'no_access_token_secret_found', __( 'Provide Twitter Access Token Secret.', 'ghostkit' ) );
646 }
647 if ( ! $screen_name ) {
648 return $this->error( 'no_screen_name_found', __( 'Provide Username.', 'ghostkit' ) );
649 }
650
651 $api_data_ready = $consumer_key && $consumer_secret && $access_token && $access_token_secret;
652
653 $hash = md5(
654 wp_json_encode(
655 array(
656 $consumer_key,
657 $consumer_secret,
658 $access_token,
659 $access_token_secret,
660 $cache_expiration,
661 )
662 )
663 );
664
665 $cache_name = $cache_name . '_' . $screen_name . '_' . $hash;
666
667 // get cached data.
668 $result = get_transient( $cache_name );
669
670 // if there is no cache available, request twitter feed.
671 if ( false === $result && $api_data_ready ) {
672 // request_api_twitter.
673 $profile = $this->request_api_twitter(
674 array(
675 'url' => 'https://api.twitter.com/1.1/users/show.json',
676 'consumer_key' => $consumer_key,
677 'consumer_secret' => $consumer_secret,
678 'access_token' => $access_token,
679 'access_token_secret' => $access_token_secret,
680 'include_entities' => 'true',
681 'screen_name' => $screen_name,
682 )
683 );
684
685 if ( $profile && isset( $profile['screen_name'] ) ) {
686 $result = $profile;
687
688 // prepare different profile image sizes.
689 if ( $result['profile_image_url'] ) {
690 $result['profile_images'] = $this->get_twitter_profile_images( $result['profile_image_url'] );
691 }
692 if ( $result['profile_image_url_https'] ) {
693 $result['profile_images_https'] = $this->get_twitter_profile_images( $result['profile_image_url_https'] );
694 }
695
696 // prepare short counts.
697 $result['followers_count_short'] = $this->convert_number_short( $result['followers_count'] );
698 $result['friends_count_short'] = $this->convert_number_short( $result['friends_count'] );
699 $result['listed_count_short'] = $this->convert_number_short( $result['listed_count'] );
700 $result['favourites_count_short'] = $this->convert_number_short( $result['favourites_count'] );
701 $result['statuses_count_short'] = $this->convert_number_short( $result['statuses_count'] );
702
703 // prepare url link.
704 if ( $result['url'] && isset( $result['entities']['url'] ) ) {
705 $result['url_entitled'] = $this->add_tweet_entity_links( $result['url'], $result['entities']['url'] );
706 }
707
708 // description with links.
709 if ( isset( $result['entities']['description'] ) ) {
710 $result['description_entitled'] = $this->add_tweet_entity_links( $result['description'], $result['entities']['description'] );
711 }
712
713 set_transient( $cache_name, $result, $cache_expiration );
714 }
715 }
716
717 if ( $result ) {
718 return $this->success( $result );
719 } else {
720 return $this->error( 'no_twitter_data_loaded', __( 'Twitter data failed to load.', 'ghostkit' ) );
721 }
722 }
723
724 /**
725 * Get Twitter feed.
726 *
727 * @param WP_REST_Request $request request object.
728 *
729 * @return mixed
730 */
731 public function get_twitter_feed( WP_REST_Request $request ) {
732 $cache_name = 'ghostkit_twitter_feed_cache';
733 $cache_expiration = $request->get_param( 'cache_expiration' ) ? $request->get_param( 'cache_expiration' ) : DAY_IN_SECONDS;
734
735 $count = (int) ( $request->get_param( 'count' ) ? $request->get_param( 'count' ) : 6 );
736 $consumer_key = $request->get_param( 'consumer_key' );
737 $consumer_secret = $request->get_param( 'consumer_secret' );
738 $access_token = $request->get_param( 'access_token' );
739 $access_token_secret = $request->get_param( 'access_token_secret' );
740 $screen_name = $request->get_param( 'screen_name' );
741 $exclude_replies = 'true' === $request->get_param( 'exclude_replies' );
742 $include_rts = 'true' === $request->get_param( 'include_rts' );
743 $tweet_mode_extended = 'true' === $request->get_param( 'tweet_mode_extended' );
744
745 $api_data_ready = $consumer_key && $consumer_secret && $access_token && $access_token_secret;
746
747 if ( ! $consumer_key ) {
748 return $this->error( 'no_consumer_key_found', __( 'Provide Twitter Consumer Key.', 'ghostkit' ) );
749 }
750 if ( ! $consumer_secret ) {
751 return $this->error( 'no_consumer_secret_found', __( 'Provide Twitter Consumer Secret.', 'ghostkit' ) );
752 }
753 if ( ! $access_token ) {
754 return $this->error( 'no_access_token_found', __( 'Provide Twitter Access Token.', 'ghostkit' ) );
755 }
756 if ( ! $access_token_secret ) {
757 return $this->error( 'no_access_token_secret_found', __( 'Provide Twitter Access Token Secret.', 'ghostkit' ) );
758 }
759 if ( ! $screen_name ) {
760 return $this->error( 'no_screen_name_found', __( 'Provide Username.', 'ghostkit' ) );
761 }
762
763 $hash = md5(
764 wp_json_encode(
765 array(
766 $consumer_key,
767 $consumer_secret,
768 $access_token,
769 $access_token_secret,
770 $cache_expiration,
771 $tweet_mode_extended,
772 )
773 )
774 );
775
776 $cache_name = $cache_name . '_' . $screen_name . '_' . $hash;
777
778 // get cached data.
779 $feed = get_transient( $cache_name );
780
781 $result = array();
782
783 if ( $api_data_ready ) {
784 // if there is no cache available, request twitter feed.
785 if ( false === $feed ) {
786 $feed = $this->request_api_twitter(
787 array(
788 'url' => 'https://api.twitter.com/1.1/statuses/user_timeline.json',
789 'consumer_key' => $consumer_key,
790 'consumer_secret' => $consumer_secret,
791 'access_token' => $access_token,
792 'access_token_secret' => $access_token_secret,
793 'screen_name' => $screen_name,
794 'tweet_mode_extended' => $tweet_mode_extended,
795 'exclude_replies' => 'false',
796 'include_rts' => 'true',
797 'count' => 200,
798 )
799 );
800
801 if ( $feed && ! ( isset( $feed['errors'] ) && count( $feed['errors'] ) > 0 ) ) {
802 set_transient( $cache_name, $feed, $cache_expiration );
803 } else {
804 $feed = false;
805 }
806 }
807
808 $tweets_count = $feed ? count( $feed ) : 0;
809 $limit_to_display = min( $count, $tweets_count );
810
811 if ( $limit_to_display > 0 ) {
812 for ( $i = 0; $i < $tweets_count; $i++ ) {
813 $new_item = $feed[ $i ];
814
815 // check for replies.
816 if ( $exclude_replies && $new_item['in_reply_to_user_id'] ) {
817 continue;
818 }
819
820 // check for retweets.
821 if ( ! $include_rts && isset( $new_item['retweeted_status'] ) ) {
822 continue;
823 }
824
825 // full text.
826 if ( $tweet_mode_extended || ! isset( $new_item['text'] ) ) {
827 $text = isset( $new_item['full_text'] ) ? $new_item['full_text'] : null;
828
829 if ( null === $text ) {
830 $text = isset( $new_item['text'] ) ? $new_item['text'] : '';
831 }
832
833 $new_item['text'] = $text;
834 }
835
836 // prepare tweet content.
837 $new_item = $this->prepare_tweet_content( $new_item );
838
839 if ( isset( $new_item['retweeted_status'] ) ) {
840 // full text.
841 if ( $tweet_mode_extended || ! isset( $new_item['retweeted_status']['text'] ) ) {
842 $text = isset( $new_item['retweeted_status']['full_text'] ) ? $new_item['retweeted_status']['full_text'] : null;
843
844 if ( null === $text ) {
845 $text = isset( $new_item['retweeted_status']['text'] ) ? $new_item['retweeted_status']['text'] : '';
846 }
847
848 $new_item['retweeted_status']['text'] = $text;
849 }
850
851 $new_item['retweeted_status'] = $this->prepare_tweet_content( $new_item['retweeted_status'] );
852 }
853
854 $result[] = $new_item;
855
856 if ( count( $result ) >= $limit_to_display ) {
857 break;
858 }
859 }
860 }
861 }
862
863 if ( $result ) {
864 return $this->success( $result );
865 } else {
866 return $this->error( 'no_twitter_data_loaded', __( 'Twitter data failed to load.', 'ghostkit' ) );
867 }
868 }
869
870 /**
871 * Get Twitter API url result
872 *
873 * @param array $data - api request data.
874 *
875 * @return bool|mixed
876 */
877 public function request_api_twitter( $data ) {
878 $data = array_merge(
879 array(
880 'url' => 'https://api.twitter.com/1.1/statuses/user_timeline.json',
881 'consumer_key' => '',
882 'consumer_secret' => '',
883 'access_token' => '',
884 'access_token_secret' => '',
885 'screen_name' => '',
886 'exclude_replies' => '',
887 'include_rts' => '',
888 'count' => '',
889 'include_entities' => '',
890 'tweet_mode_extended' => '',
891 ),
892 $data
893 );
894
895 $oauth = array(
896 'oauth_consumer_key' => $data['consumer_key'],
897 'oauth_nonce' => time(),
898 'oauth_signature_method' => 'HMAC-SHA1',
899 'oauth_token' => $data['access_token'],
900 'oauth_timestamp' => time(),
901 'oauth_version' => '1.0',
902 );
903
904 $base_info_url = $data['url'];
905
906 if ( $data['screen_name'] ) {
907 $data['url'] .= strpos( $data['url'], '?' ) !== false ? '&' : '?';
908 $data['url'] .= 'screen_name=' . $data['screen_name'];
909 $oauth['screen_name'] = $data['screen_name'];
910 }
911 if ( $data['exclude_replies'] ) {
912 $data['url'] .= strpos( $data['url'], '?' ) !== false ? '&' : '?';
913 $data['url'] .= 'exclude_replies=' . $data['exclude_replies'];
914 $oauth['exclude_replies'] = $data['exclude_replies'];
915 }
916 if ( $data['include_rts'] ) {
917 $data['url'] .= strpos( $data['url'], '?' ) !== false ? '&' : '?';
918 $data['url'] .= 'include_rts=' . $data['include_rts'];
919 $oauth['include_rts'] = $data['include_rts'];
920 }
921 if ( $data['count'] ) {
922 $data['url'] .= strpos( $data['url'], '?' ) !== false ? '&' : '?';
923 $data['url'] .= 'count=' . $data['count'];
924 $oauth['count'] = $data['count'];
925 }
926 if ( $data['include_entities'] ) {
927 $data['url'] .= strpos( $data['url'], '?' ) !== false ? '&' : '?';
928 $data['url'] .= 'include_entities=' . $data['include_entities'];
929 $oauth['include_entities'] = $data['include_entities'];
930 }
931
932 // Tweet Mode.
933 if ( $data['tweet_mode_extended'] ) {
934 $data['url'] .= strpos( $data['url'], '?' ) !== false ? '&' : '?';
935 $data['url'] .= 'tweet_mode=extended';
936 $oauth['tweet_mode'] = 'extended';
937 }
938
939 $base_info = $this->build_base_string( $base_info_url, 'GET', $oauth );
940 $composite_key = rawurlencode( $data['consumer_secret'] ) . '&' . rawurlencode( $data['access_token_secret'] );
941
942 // phpcs:ignore
943 $oauth_signature = base64_encode( hash_hmac( 'sha1', $base_info, $composite_key, true ) );
944 $oauth['oauth_signature'] = $oauth_signature;
945
946 // Make Requests.
947 $header = array( $this->build_authorization_header( $oauth ), 'Expect:' );
948 $options_buf = wp_remote_get(
949 $data['url'],
950 array(
951 'headers' => implode( "\n", $header ),
952 'sslverify' => false,
953 )
954 );
955
956 if ( ! is_wp_error( $options_buf ) && isset( $options_buf['body'] ) ) {
957 return json_decode( $options_buf['body'], true );
958 } else {
959 return false;
960 }
961 }
962
963 /**
964 * Build base string
965 *
966 * @param string $base_uri - url.
967 * @param string $method - method.
968 * @param array $params - params.
969 *
970 * @return string
971 */
972 private function build_base_string( $base_uri, $method, $params ) {
973 $r = array();
974 ksort( $params );
975 foreach ( $params as $key => $value ) {
976 $r[] = "$key=" . rawurlencode( $value );
977 }
978 return $method . '&' . rawurlencode( $base_uri ) . '&' . rawurlencode( implode( '&', $r ) );
979 }
980
981 /**
982 * Build authorization header
983 *
984 * @param array $oauth - auth data.
985 *
986 * @return string
987 */
988 private function build_authorization_header( $oauth ) {
989 $r = 'Authorization: OAuth ';
990 $values = array();
991
992 foreach ( $oauth as $key => $value ) {
993 $values[] = "$key=\"" . rawurlencode( $value ) . '"';
994 }
995
996 $r .= implode( ', ', $values );
997
998 return $r;
999 }
1000
1001 /**
1002 * Prepare tweet content.
1003 *
1004 * @param array $tweet - tweet data.
1005 *
1006 * @return array - new tweet data.
1007 */
1008 public function prepare_tweet_content( $tweet ) {
1009 // prepare different profile image sizes.
1010 if ( $tweet['user']['profile_image_url'] ) {
1011 $tweet['user']['profile_images'] = $this->get_twitter_profile_images( $tweet['user']['profile_image_url'] );
1012 }
1013 if ( $tweet['user']['profile_image_url_https'] ) {
1014 $tweet['user']['profile_images_https'] = $this->get_twitter_profile_images( $tweet['user']['profile_image_url_https'] );
1015 }
1016
1017 // prepare short counts.
1018 $tweet['retweet_count_short'] = $this->convert_number_short( $tweet['retweet_count'] );
1019 $tweet['favorite_count_short'] = $this->convert_number_short( $tweet['favorite_count'] );
1020
1021 // user friendly date.
1022 $date = strtotime( $tweet['created_at'] );
1023 $now = time();
1024 $diff_date = $now - $date;
1025
1026 if ( $diff_date / 60 < 1 ) {
1027 // seconds.
1028 // translators: %d - seconds.
1029 $date = sprintf( esc_html__( '%ds', 'ghostkit' ), intval( $diff_date % 60 ) );
1030 } elseif ( $diff_date / 60 < 60 ) {
1031 // minutes.
1032 // translators: %d - minutes.
1033 $date = sprintf( esc_html__( '%dm', 'ghostkit' ), intval( $diff_date / 60 ) );
1034 } elseif ( $diff_date / 3600 < 24 ) {
1035 // hours.
1036 // translators: %d - hours.
1037 $date = sprintf( esc_html__( '%dh', 'ghostkit' ), intval( $diff_date / 3600 ) );
1038 } elseif ( gmdate( 'Y' ) === gmdate( 'Y', $date ) ) {
1039 // current year.
1040 $date = gmdate( esc_html__( 'M j', 'ghostkit' ), $date );
1041 } else {
1042 // past years.
1043 $date = gmdate( esc_html__( 'Y M j', 'ghostkit' ), $date );
1044 }
1045
1046 $tweet['date_formatted'] = $date;
1047
1048 // text with links and media.
1049 $tweet['text_entitled'] = $this->add_tweet_entity_links( $tweet['text'], $tweet['entities'] );
1050
1051 // text with links only.
1052 $tweet['text_entitled_no_media'] = $this->add_tweet_entity_links( $tweet['text'], $tweet['entities'], false );
1053
1054 return $tweet;
1055 }
1056
1057 /**
1058 * Adds a link around any entities in a twitter feed
1059 * twitter entities include urls, user mentions, hashtags and media
1060 * http://stackoverflow.com/a/15390225
1061 *
1062 * @param string $text - tweet text.
1063 * @param array $entities - available entities.
1064 * @param boolean $show_media - show tweet images.
1065 *
1066 * @return string tweet
1067 */
1068 public function add_tweet_entity_links( $text, $entities, $show_media = true ) {
1069 $replacements = array();
1070 if ( isset( $entities['hashtags'] ) ) {
1071 foreach ( $entities['hashtags'] as $hashtag ) {
1072 list ($start, $end) = $hashtag['indices'];
1073 $replacements[ $start ] = array(
1074 $start,
1075 $end,
1076 "<a href=\"https://twitter.com/hashtag/{$hashtag['text']}\" target=\"_blank\">#{$hashtag['text']}</a>",
1077 );
1078 }
1079 }
1080 if ( isset( $entities['urls'] ) ) {
1081 foreach ( $entities['urls'] as $url ) {
1082 list ($start, $end) = $url['indices'];
1083 // you can also use $url['expanded_url'] in place of $url['url'].
1084 $replacements[ $start ] = array(
1085 $start,
1086 $end,
1087 "<a href=\"{$url['url']}\" target=\"_blank\">{$url['display_url']}</a>",
1088 );
1089 }
1090 }
1091 if ( isset( $entities['user_mentions'] ) ) {
1092 foreach ( $entities['user_mentions'] as $mention ) {
1093 list ($start, $end) = $mention['indices'];
1094 $replacements[ $start ] = array(
1095 $start,
1096 $end,
1097 "<a href=\"https://twitter.com/{$mention['screen_name']}\" target=\"_blank\">@{$mention['screen_name']}</a>",
1098 );
1099 }
1100 }
1101 if ( isset( $entities['media'] ) ) {
1102 foreach ( $entities['media'] as $media ) {
1103 list ($start, $end) = $media['indices'];
1104
1105 if ( $show_media ) {
1106 $replacements[ $start ] = array(
1107 $start,
1108 $end,
1109 "<div><a href=\"{$media['url']}\" target=\"_blank\"><img src=\"{$media['media_url_https']}\" /></a></div>",
1110 );
1111 } else {
1112 $replacements[ $start ] = array(
1113 $start,
1114 $end,
1115 "<a href=\"{$media['url']}\" target=\"_blank\">{$media['url']}</a>",
1116 );
1117 }
1118 }
1119 }
1120
1121 // sort in reverse order by start location.
1122 krsort( $replacements );
1123
1124 foreach ( $replacements as $replace_data ) {
1125 list ($start, $end, $replace_text) = $replace_data;
1126
1127 $text = mb_substr( $text, 0, $start, 'UTF-8' ) . $replace_text . mb_substr( $text, $end, null, 'UTF-8' );
1128 }
1129
1130 return $text;
1131 }
1132
1133 /**
1134 * Convert long numbers to short. eg: 1500 -> 1.5K
1135 * Thanks https://code.recuweb.com/2018/php-format-numbers-to-nearest-thousands/ .
1136 *
1137 * @param number $num - number.
1138 * @return string
1139 */
1140 public function convert_number_short( $num ) {
1141 if ( $num > 1000 ) {
1142 $x = round( $num );
1143 $x_number_format = number_format( $x );
1144 $x_array = explode( ',', $x_number_format );
1145 $x_parts = array( 'K', 'M', 'B', 'T' );
1146 $x_count_parts = count( $x_array ) - 1;
1147 $x_display = $x;
1148 $x_display = $x_array[0] . ( (int) 0 !== $x_array[1][0] ? '.' . $x_array[1][0] : '' );
1149 $x_display .= $x_parts[ $x_count_parts - 1 ];
1150
1151 return $x_display;
1152 }
1153
1154 return $num;
1155 }
1156
1157 /**
1158 * Prepare profile image urls
1159 * https://developer.twitter.com/en/docs/accounts-and-users/user-profile-images-and-banners
1160 *
1161 * @param string $url - profile image.
1162 *
1163 * @return array images
1164 */
1165 public function get_twitter_profile_images( $url ) {
1166 if ( strpos( $url, '.jpg' ) !== false ) {
1167 return array(
1168 'normal' => $url,
1169 'bigger' => str_replace( '_normal.jpg', '_bigger.jpg', $url ),
1170 'mini' => str_replace( '_normal.jpg', '_mini.jpg', $url ),
1171 'original' => str_replace( '_normal.jpg', '.jpg', $url ),
1172 );
1173 }
1174
1175 return array(
1176 'normal' => $url,
1177 'bigger' => str_replace( '_normal.png', '_bigger.png', $url ),
1178 'mini' => str_replace( '_normal.png', '_mini.png', $url ),
1179 'original' => str_replace( '_normal.png', '.png', $url ),
1180 );
1181 }
1182
1183 /**
1184 * Get TOC.
1185 *
1186 * @param WP_REST_Request $request request object.
1187 *
1188 * @return mixed
1189 */
1190 public function get_table_of_contents( WP_REST_Request $request ) {
1191 $headings = $request->get_param( 'headings' );
1192 $allowed_headers = $request->get_param( 'allowedHeaders' );
1193 $list_style = $request->get_param( 'listStyle' ) ? $request->get_param( 'listStyle' ) : 'ol';
1194
1195 $html = '';
1196
1197 if ( ! $allowed_headers || empty( $allowed_headers ) ) {
1198 return $this->success( $html );
1199 }
1200
1201 // covert string values to int.
1202 $allowed_headers = array_map( 'intval', $allowed_headers );
1203
1204 $current_depth = 6;
1205 $numbered_items = array();
1206 $numbered_items_min = null;
1207 $count = count( $headings );
1208
1209 // find the minimum heading to establish our baseline.
1210 for ( $i = 0; $i < $count; $i++ ) {
1211 if ( $current_depth > (int) $headings[ $i ]['level'] ) {
1212 $current_depth = (int) $headings[ $i ]['level'];
1213 }
1214 }
1215
1216 $numbered_items[ $current_depth ] = 0;
1217 $numbered_items_min = $current_depth;
1218 for ( $i = 0; $i < $count; $i ++ ) {
1219 if ( $current_depth === (int) $headings[ $i ]['level'] ) {
1220 $html .= '<li>';
1221 }
1222
1223 // start lists.
1224 if ( $current_depth !== (int) $headings[ $i ]['level'] ) {
1225 for ( $current_depth; $current_depth < (int) $headings[ $i ]['level']; $current_depth++ ) {
1226 $numbered_items[ $current_depth + 1 ] = 0;
1227
1228 if ( ! in_array( $current_depth, $allowed_headers, true ) ) {
1229 continue;
1230 }
1231
1232 $html .= '<ul>';
1233 $html .= '<li>';
1234 }
1235 }
1236
1237 $html .= '<a href="' . esc_attr( '#' . $headings[ $i ]['anchor'] ) . '">' . wp_kses_post( $headings[ $i ]['content'] ) . '</a>';
1238
1239 // end lists.
1240 if ( $i !== $count - 1 ) {
1241 if ( $current_depth > (int) $headings[ $i + 1 ]['level'] ) {
1242 for ( $current_depth; $current_depth > (int) $headings[ $i + 1 ]['level']; $current_depth-- ) {
1243 $numbered_items[ $current_depth ] = 0;
1244
1245 if ( ! in_array( $current_depth, $allowed_headers, true ) ) {
1246 continue;
1247 }
1248
1249 $html .= '</li>';
1250 $html .= '</ul>';
1251 }
1252 }
1253 if ( isset( $headings[ $i + 1 ]['level'] ) && (int) $headings[ $i + 1 ]['level'] === $current_depth ) {
1254 $html .= '</li>';
1255 }
1256 } else {
1257 // this is the last item, make sure we close off all tags.
1258 for ( $current_depth; $current_depth >= $numbered_items_min; $current_depth-- ) {
1259 if ( ! in_array( $current_depth, $allowed_headers, true ) ) {
1260 continue;
1261 }
1262
1263 $html .= '</li>';
1264 if ( $current_depth !== $numbered_items_min ) {
1265 $html .= '</ul>';
1266 }
1267 }
1268 }
1269 }
1270
1271 // Wrapper.
1272 if ( $html ) {
1273 $list = 'ol';
1274 $list_class_name = '';
1275
1276 switch ( $list_style ) {
1277 case 'ul':
1278 $list = 'ul';
1279 break;
1280 case 'ul-styled':
1281 $list = 'ul';
1282 $list_class_name = 'is-style-styled';
1283 break;
1284 case 'ol-styled':
1285 $list_class_name = 'is-style-styled';
1286 break;
1287 }
1288
1289 $html = '<' . $list . ( $list_class_name ? ( ' class="' . $list_class_name . '"' ) : '' ) . '>' . $html . '</' . $list . '>';
1290 }
1291
1292 return $this->success( $html );
1293 }
1294
1295 /**
1296 * Get templates.
1297 *
1298 * @return mixed
1299 */
1300 public function get_templates() {
1301 $url = 'https://library.ghostkit.io/wp-json/ghostkit-library/v1/get_library/';
1302 $templates = get_transient( 'ghostkit_remote_templates', false );
1303
1304 /*
1305 * Get remote templates.
1306 */
1307 if ( ! $templates ) {
1308 $requested_templates = wp_remote_get(
1309 add_query_arg(
1310 array(
1311 'ghostkit_version' => '2.25.0',
1312 'ghostkit_pro' => function_exists( 'ghostkit_pro' ),
1313 'ghostkit_pro_version' => function_exists( 'ghostkit_pro' ) ? ghostkit_pro()->plugin_version : null,
1314 ),
1315 $url
1316 )
1317 );
1318
1319 if ( ! is_wp_error( $requested_templates ) ) {
1320 $new_templates = wp_remote_retrieve_body( $requested_templates );
1321 $new_templates = json_decode( $new_templates, true );
1322
1323 if ( $new_templates && isset( $new_templates['response'] ) && is_array( $new_templates['response'] ) ) {
1324 $templates = $new_templates['response'];
1325 set_transient( 'ghostkit_remote_templates', $templates, DAY_IN_SECONDS );
1326 }
1327 }
1328 }
1329
1330 // Remove Pro templates from array, cause for now there is no way to check if pro addon is activated.
1331 if ( $templates ) {
1332 foreach ( $templates as $k => $template ) {
1333 $is_pro = false;
1334
1335 if ( isset( $template['types'] ) && is_array( $template['types'] ) ) {
1336 foreach ( $template['types'] as $type ) {
1337 $is_pro = $is_pro || 'pro' === $type['slug'];
1338 }
1339 }
1340
1341 if ( $is_pro ) {
1342 unset( $templates[ $k ] );
1343 }
1344 }
1345 }
1346
1347 /*
1348 * Get user templates from db.
1349 */
1350
1351 // Stupid hack.
1352 // https://core.trac.wordpress.org/ticket/18408.
1353 global $post;
1354 $backup_global_post = $post;
1355 $local_templates = array();
1356
1357 $local_templates_query = new WP_Query(
1358 array(
1359 'post_type' => 'ghostkit_template',
1360 'posts_per_page' => -1,
1361 'showposts' => -1,
1362 'paged' => -1,
1363 )
1364 );
1365
1366 while ( $local_templates_query->have_posts() ) {
1367 $local_templates_query->the_post();
1368 $db_template = get_post();
1369
1370 $categories = array();
1371 $category_terms = get_the_terms( $db_template->ID, 'ghostkit_template_category' );
1372
1373 if ( $category_terms ) {
1374 foreach ( $category_terms as $cat ) {
1375 $categories[] = array(
1376 'slug' => $cat->slug,
1377 'name' => $cat->name,
1378 );
1379 }
1380 }
1381
1382 $image_id = get_post_thumbnail_id( $db_template->ID );
1383 $image_data = wp_get_attachment_image_src( $image_id, 'large' );
1384
1385 $local_templates[] = array(
1386 'id' => $db_template->ID,
1387 'title' => $db_template->post_title,
1388 'types' => array(
1389 array(
1390 'slug' => 'local',
1391 ),
1392 ),
1393 'categories' => empty( $categories ) ? false : $categories,
1394 'url' => get_post_permalink( $db_template->ID ),
1395 'thumbnail' => isset( $image_data[0] ) ? $image_data[0] : false,
1396 'thumbnail_width' => isset( $image_data[1] ) ? $image_data[1] : false,
1397 'thumbnail_height' => isset( $image_data[2] ) ? $image_data[2] : false,
1398 );
1399 }
1400
1401 // Restore the global $post as it was before custom WP_Query.
1402 // phpcs:ignore
1403 $post = $backup_global_post;
1404
1405 /*
1406 * Get theme templates.
1407 */
1408 $theme_templates = array();
1409 $theme_templates_data = array();
1410
1411 foreach ( glob( get_template_directory() . '/ghostkit/templates/*/content.php' ) as $template ) {
1412 $template_path = dirname( $template );
1413 $template_url = get_template_directory_uri() . str_replace( get_template_directory(), '', $template_path );
1414 $slug = basename( $template_path );
1415
1416 $theme_templates_data[ $slug ] = array(
1417 'slug' => $slug,
1418 'path' => $template_path,
1419 'url' => $template_url,
1420 );
1421 }
1422
1423 // get child theme templates.
1424 if ( get_stylesheet_directory() !== get_template_directory() ) {
1425 foreach ( glob( get_stylesheet_directory() . '/ghostkit/templates/*/content.php' ) as $template ) {
1426 $template_path = dirname( $template );
1427 $template_url = get_stylesheet_directory_uri() . str_replace( get_stylesheet_directory(), '', $template_path );
1428 $slug = basename( $template_path );
1429
1430 $theme_templates_data[ $slug ] = array(
1431 'slug' => $slug,
1432 'path' => $template_path,
1433 'url' => $template_url,
1434 );
1435 }
1436 }
1437
1438 // natural sort.
1439 array_multisort( array_keys( $theme_templates_data ), SORT_NATURAL, $theme_templates_data );
1440
1441 foreach ( $theme_templates_data as $template_data ) {
1442 $file_data = get_file_data(
1443 $template_data['path'] . '/content.php',
1444 array(
1445 'name' => 'Name',
1446 'category' => 'Category',
1447 'source' => 'Source',
1448 )
1449 );
1450
1451 $thumbnail = false;
1452 $thumbnail_width = false;
1453 $thumbnail_height = false;
1454
1455 if ( file_exists( $template_data['path'] . '/thumbnail.png' ) ) {
1456 $thumbnail = $template_data['url'] . '/thumbnail.png';
1457
1458 list($thumbnail_width, $thumbnail_height) = getimagesize( $thumbnail );
1459 }
1460
1461 if ( file_exists( $template_data['path'] . '/thumbnail.jpg' ) ) {
1462 $thumbnail = $template_data['url'] . '/thumbnail.jpg';
1463 }
1464
1465 $theme_templates[] = array(
1466 'id' => basename( $template_data['path'] ),
1467 'title' => $file_data['name'],
1468 'types' => array(
1469 array(
1470 'slug' => 'theme',
1471 ),
1472 ),
1473 'categories' => isset( $file_data['category'] ) && $file_data['category'] ? array(
1474 array(
1475 'slug' => $file_data['category'],
1476 'name' => $file_data['category'],
1477 ),
1478 ) : false,
1479 'url' => false,
1480 'thumbnail' => $thumbnail,
1481 'thumbnail_width' => $thumbnail_width,
1482 'thumbnail_height' => $thumbnail_height,
1483 );
1484 }
1485
1486 // merge all available templates.
1487 $templates = array_merge( $templates, $local_templates, $theme_templates );
1488
1489 if ( is_array( $templates ) ) {
1490 return $this->success( $templates );
1491 } else {
1492 return $this->error( 'no_templates', __( 'Templates not found.', 'ghostkit' ) );
1493 }
1494 }
1495
1496 /**
1497 * Get templates.
1498 *
1499 * @param WP_REST_Request $request request object.
1500 *
1501 * @return mixed
1502 */
1503 public function get_template_data( WP_REST_Request $request ) {
1504 $url = 'https://library.ghostkit.io/wp-json/ghostkit-library/v1/get_library_item/';
1505 $id = $request->get_param( 'id' );
1506 $type = $request->get_param( 'type' );
1507 $template_data = false;
1508
1509 switch ( $type ) {
1510 case 'remote':
1511 $template_data = get_transient( 'ghostkit_template_' . $type . '_' . $id, false );
1512
1513 if ( ! $template_data ) {
1514 $requested_template_data = wp_remote_get(
1515 add_query_arg(
1516 array(
1517 'id' => $id,
1518 'ghostkit_version' => '2.25.0',
1519 'ghostkit_pro' => function_exists( 'ghostkit_pro' ),
1520 'ghostkit_pro_version' => function_exists( 'ghostkit_pro' ) ? ghostkit_pro()->plugin_version : null,
1521 ),
1522 $url
1523 )
1524 );
1525
1526 if ( ! is_wp_error( $requested_template_data ) ) {
1527 $new_template_data = wp_remote_retrieve_body( $requested_template_data );
1528 $new_template_data = json_decode( $new_template_data, true );
1529
1530 if ( $new_template_data && isset( $new_template_data['response'] ) && is_array( $new_template_data['response'] ) ) {
1531 $template_data = $new_template_data['response'];
1532 set_transient( 'ghostkit_template_' . $type . '_' . $id, $template_data, DAY_IN_SECONDS );
1533 }
1534 }
1535 }
1536 break;
1537 case 'local':
1538 $post = get_post( $id );
1539
1540 if ( $post && 'ghostkit_template' === $post->post_type ) {
1541 $template_data = array(
1542 'id' => $post->ID,
1543 'title' => $post->post_title,
1544 'content' => $post->post_content,
1545 );
1546 }
1547
1548 break;
1549 case 'theme':
1550 $template_content_file = get_stylesheet_directory() . '/ghostkit/templates/' . $id . '/content.php';
1551
1552 if ( ! file_exists( $template_content_file ) ) {
1553 $template_content_file = get_template_directory() . '/ghostkit/templates/' . $id . '/content.php';
1554 }
1555
1556 if ( file_exists( $template_content_file ) ) {
1557 ob_start();
1558 include $template_content_file;
1559 $template_content = ob_get_clean();
1560
1561 if ( $template_content ) {
1562 $template_data = get_file_data(
1563 $template_content_file,
1564 array(
1565 'name' => 'Name',
1566 )
1567 );
1568
1569 $template_data = array(
1570 'id' => $id,
1571 'title' => $template_data['name'],
1572 'content' => $template_content,
1573 );
1574 }
1575 }
1576 break;
1577 }
1578
1579 if ( is_array( $template_data ) ) {
1580 return $this->success( $template_data );
1581 } else {
1582 return $this->error( 'no_template_data', __( 'Template data not found.', 'ghostkit' ) );
1583 }
1584 }
1585
1586 /**
1587 * Get custom code.
1588 *
1589 * @return mixed
1590 */
1591 public function get_custom_code() {
1592 $custom_code = get_option( 'ghostkit_custom_code', array() );
1593
1594 if ( is_array( $custom_code ) ) {
1595 return $this->success( $custom_code );
1596 } else {
1597 return $this->error( 'no_custom_code', __( 'Custom code not found.', 'ghostkit' ) );
1598 }
1599 }
1600
1601 /**
1602 * Update custom code.
1603 *
1604 * @param WP_REST_Request $request request object.
1605 *
1606 * @return mixed
1607 */
1608 public function update_custom_code( WP_REST_Request $request ) {
1609 $new_code = $request->get_param( 'data' );
1610
1611 if ( is_array( $new_code ) ) {
1612 $current_code = get_option( 'ghostkit_custom_code', array() );
1613 update_option( 'ghostkit_custom_code', array_merge( $current_code, $new_code ) );
1614 }
1615
1616 return $this->success( true );
1617 }
1618
1619 /**
1620 * Update color palette.
1621 *
1622 * @param WP_REST_Request $request request object.
1623 *
1624 * @return mixed
1625 */
1626 public function update_color_palette( WP_REST_Request $request ) {
1627 $colors = $request->get_param( 'data' );
1628
1629 if ( is_array( $colors ) ) {
1630 update_option( 'ghostkit_color_palette', $colors );
1631 }
1632
1633 return $this->success( true );
1634 }
1635
1636 /**
1637 * Get custom typography.
1638 *
1639 * @return mixed
1640 */
1641 public function get_custom_typography() {
1642 $typography = get_option( 'ghostkit_typography', array() );
1643
1644 if ( is_array( $typography ) ) {
1645 return $this->success( $typography );
1646 } else {
1647 return $this->error( 'no_typography', __( 'Typography not found.', 'ghostkit' ) );
1648 }
1649 }
1650
1651 /**
1652 * Update typography.
1653 *
1654 * @param WP_REST_Request $request request object.
1655 *
1656 * @return mixed
1657 */
1658 public function update_custom_typography( WP_REST_Request $request ) {
1659 $new_typography = $request->get_param( 'data' );
1660 $updated_option = array();
1661
1662 if ( is_array( $new_typography ) ) {
1663 $current_typography = get_option( 'ghostkit_typography', array() );
1664
1665 if ( empty( $current_typography ) ) {
1666 $updated_option = $new_typography;
1667 } else {
1668 $current_typography['ghostkit_typography'] = json_decode( $current_typography['ghostkit_typography'], true );
1669 $new_typography['ghostkit_typography'] = json_decode( $new_typography['ghostkit_typography'], true );
1670
1671 $updated_option = array_merge( $current_typography, $new_typography );
1672
1673 $updated_option['ghostkit_typography'] = wp_json_encode( $updated_option['ghostkit_typography'] );
1674 }
1675
1676 update_option( 'ghostkit_typography', $updated_option );
1677 }
1678
1679 return $this->success( true );
1680 }
1681
1682 /**
1683 * Update Google Maps API key.
1684 *
1685 * @param WP_REST_Request $request request object.
1686 *
1687 * @return mixed
1688 */
1689 public function update_google_maps_api_key( WP_REST_Request $request ) {
1690 update_option( 'ghostkit_google_maps_api_key', $request->get_param( 'key' ) );
1691
1692 return $this->success( true );
1693 }
1694
1695 /**
1696 * Update Google reCaptcha API keys.
1697 *
1698 * @param WP_REST_Request $request request object.
1699 *
1700 * @return mixed
1701 */
1702 public function update_google_recaptcha_keys( WP_REST_Request $request ) {
1703 update_option( 'ghostkit_google_recaptcha_api_site_key', $request->get_param( 'site_key' ) );
1704 update_option( 'ghostkit_google_recaptcha_api_secret_key', $request->get_param( 'secret_key' ) );
1705
1706 return $this->success( true );
1707 }
1708
1709 /**
1710 * Update Disabled Blocks.
1711 *
1712 * @param WP_REST_Request $request request object.
1713 *
1714 * @return mixed
1715 */
1716 public function update_disabled_blocks( WP_REST_Request $request ) {
1717 $new_disabled_blocks = $request->get_param( 'blocks' );
1718
1719 if ( is_array( $new_disabled_blocks ) ) {
1720 $disabled_blocks = array_merge( get_option( 'ghostkit_disabled_blocks', array() ), $new_disabled_blocks );
1721 $result = array();
1722
1723 foreach ( $disabled_blocks as $k => $block_disabled ) {
1724 if ( $block_disabled ) {
1725 $result[ $k ] = true;
1726 }
1727 }
1728
1729 update_option( 'ghostkit_disabled_blocks', $result );
1730 }
1731
1732 return $this->success( true );
1733 }
1734
1735 /**
1736 * Update Settings.
1737 *
1738 * @param WP_REST_Request $request request object.
1739 *
1740 * @return mixed
1741 */
1742 public function update_settings( WP_REST_Request $request ) {
1743 $new_settings = $request->get_param( 'settings' );
1744
1745 if ( is_array( $new_settings ) ) {
1746 $current_settings = get_option( 'ghostkit_settings', array() );
1747 update_option( 'ghostkit_settings', array_merge( $current_settings, $new_settings ) );
1748 }
1749
1750 return $this->success( true );
1751 }
1752
1753 /**
1754 * Success rest.
1755 *
1756 * @param mixed $response response data.
1757 * @return mixed
1758 */
1759 public function success( $response ) {
1760 return new WP_REST_Response(
1761 array(
1762 'success' => true,
1763 'response' => $response,
1764 ),
1765 200
1766 );
1767 }
1768
1769 /**
1770 * Error rest.
1771 *
1772 * @param mixed $code error code.
1773 * @param mixed $response response data.
1774 * @param boolean $true_error use true error response to stop the code processing.
1775 * @return mixed
1776 */
1777 public function error( $code, $response, $true_error = false ) {
1778 if ( $true_error ) {
1779 return new WP_Error( $code, $response, array( 'status' => 401 ) );
1780 }
1781
1782 return new WP_REST_Response(
1783 array(
1784 'error' => true,
1785 'success' => false,
1786 'error_code' => $code,
1787 'response' => $response,
1788 ),
1789 401
1790 );
1791 }
1792 }
1793 new GhostKit_Rest();
1794