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