PluginProbe ʕ •ᴥ•ʔ
GenerateBlocks / 2.2.0
GenerateBlocks v2.2.0
trunk 1.0 1.0.1 1.0.2 1.1.0 1.1.1 1.1.2 1.2.0 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 1.6.0 1.7.0 1.7.1 1.7.2 1.7.3 1.8.0 1.8.1 1.8.2 1.8.3 1.9.0 1.9.1 2.0.0 2.0.1 2.0.2 2.1.0 2.1.1 2.1.2 2.2.0 2.2.1 2.3.0
generateblocks / includes / pattern-library / class-pattern-library-rest.php
generateblocks / includes / pattern-library Last commit date
templates 2 years ago class-libraries.php 1 year ago class-library-dto.php 2 years ago class-pattern-library-rest.php 1 year ago
class-pattern-library-rest.php
405 lines
1 <?php
2 /**
3 * The Pattern library class file.
4 *
5 * @package GenerateBlocks\Pattern_Library
6 */
7
8 if ( ! defined( 'ABSPATH' ) ) {
9 exit; // Exit if accessed directly.
10 }
11
12 /**
13 * Main class for the Pattern Library Rest functions.
14 *
15 * @since 1.9
16 */
17 class GenerateBlocks_Pattern_Library_Rest extends GenerateBlocks_Singleton {
18
19 /**
20 * Initialize all hooks.
21 *
22 * @return void
23 */
24 public function init() {
25 add_action( 'rest_api_init', array( $this, 'register_routes' ) );
26 }
27
28 /**
29 * Register the REST routes.
30 *
31 * @return void
32 */
33 public function register_routes(): void {
34 $namespace = 'generateblocks/v1';
35
36 register_rest_route(
37 $namespace,
38 '/pattern-library/libraries',
39 array(
40 'methods' => WP_REST_Server::READABLE,
41 'callback' => array( $this, 'list_libraries' ),
42 'permission_callback' => function() {
43 return apply_filters(
44 'generateblocks_can_view_pattern_library',
45 $this->edit_posts_permission()
46 );
47 },
48 )
49 );
50
51 register_rest_route(
52 $namespace,
53 '/pattern-library/libraries/save',
54 array(
55 'methods' => WP_REST_Server::CREATABLE,
56 'callback' => array( $this, 'save_libraries' ),
57 'permission_callback' => array( $this, 'manage_options_permission' ),
58 )
59 );
60
61 register_rest_route(
62 $namespace,
63 '/pattern-library/categories',
64 array(
65 'methods' => WP_REST_Server::READABLE,
66 'callback' => array( $this, 'list_categories' ),
67 'permission_callback' => function() {
68 return apply_filters(
69 'generateblocks_can_view_pattern_library',
70 $this->edit_posts_permission()
71 );
72 },
73 )
74 );
75
76 register_rest_route(
77 $namespace,
78 '/pattern-library/patterns',
79 array(
80 'methods' => WP_REST_Server::READABLE,
81 'callback' => array( $this, 'list_patterns' ),
82 'permission_callback' => function() {
83 return apply_filters(
84 'generateblocks_can_view_pattern_library',
85 $this->edit_posts_permission()
86 );
87 },
88 )
89 );
90
91 register_rest_route(
92 $namespace,
93 '/pattern-library/get-cache-data',
94 array(
95 'methods' => WP_REST_Server::READABLE,
96 'callback' => array( $this, 'get_cache_data' ),
97 'permission_callback' => function() {
98 return apply_filters(
99 'generateblocks_can_view_pattern_library',
100 $this->edit_posts_permission()
101 );
102 },
103 )
104 );
105
106 register_rest_route(
107 $namespace,
108 '/pattern-library/clear-cache',
109 array(
110 'methods' => WP_REST_Server::EDITABLE,
111 'callback' => array( $this, 'clear_cache' ),
112 'permission_callback' => array( $this, 'edit_posts_permission' ),
113 )
114 );
115 }
116
117 /**
118 * Manage options permission callback.
119 *
120 * @return bool
121 */
122 public function manage_options_permission(): bool {
123 return current_user_can( 'manage_options' );
124 }
125
126 /**
127 * Manage options permission callback.
128 *
129 * @return bool
130 */
131 public function edit_posts_permission(): bool {
132 return current_user_can( 'edit_posts' );
133 }
134
135 /**
136 * Returns a list of registered libraries.
137 *
138 * @param WP_REST_Request $request The request.
139 *
140 * @return WP_REST_Response
141 */
142 public function list_libraries( WP_REST_Request $request ): WP_REST_Response {
143 $is_enabled = $request->get_param( 'is_enabled' );
144 $libraries = GenerateBlocks_Libraries::get_instance();
145 $data = $libraries->get_all( rest_sanitize_boolean( $is_enabled ) );
146 $data = array_values( $data ); // Fix indexes.
147
148 return new WP_REST_Response(
149 array(
150 'error' => false,
151 'data' => $data,
152 ),
153 200
154 );
155 }
156
157 /**
158 * Saves the list of libraries.
159 *
160 * @param WP_REST_Request $request The request.
161 *
162 * @return WP_REST_Response
163 */
164 public function save_libraries( WP_REST_Request $request ): WP_REST_Response {
165 $data = $request->get_param( 'data' );
166 $libraries = array_map(
167 function( $library ) {
168 if ( ! $library['isLocal'] && ! $library['isDefault'] ) {
169 // Save all data if this is a remote library.
170 return $library;
171 }
172
173 // Only save the ID and status for local and default libraries.
174 // The rest of the data will be supplied via the PHP filter.
175 return [
176 'id' => $library['id'],
177 'isEnabled' => $library['isEnabled'],
178 ];
179 },
180 $data
181 );
182
183 update_option( 'generateblocks_pattern_libraries', $libraries );
184 return $this->success( $libraries );
185 }
186
187 /**
188 * Returns a list of categories.
189 *
190 * @param WP_REST_Request $request The request.
191 *
192 * @return WP_REST_Response
193 */
194 public function list_categories( WP_REST_Request $request ): WP_REST_Response {
195 $library_id = $request->get_param( 'libraryId' );
196
197 if ( ! $library_id ) {
198 return $this->error( 404, "Library of id \"$library_id\" was not found." );
199 }
200
201 $libraries = GenerateBlocks_Libraries::get_instance();
202 $library = $libraries->get_one( $library_id );
203
204 if ( ! is_null( $library ) ) {
205 return self::remote_fetch( $library, 'categories' );
206 }
207
208 return $this->error( 404, "Library of id \"$library_id\" was not found." );
209 }
210
211 /**
212 * Returns a list of patterns.
213 *
214 * @param WP_REST_Request $request The request.
215 *
216 * @return WP_REST_Response
217 */
218 public function list_patterns( WP_REST_Request $request ): WP_REST_Response {
219 $library_id = $request->get_param( 'libraryId' );
220 $search = $request->get_param( 'search' );
221 $category_id = $request->get_param( 'categoryId' );
222
223 if ( ! $library_id ) {
224 return $this->error( 404, "Library of id \"$library_id\" was not found." );
225 }
226
227 $libraries = GenerateBlocks_Libraries::get_instance();
228 $library = $libraries->get_one( $library_id );
229
230 if ( ! is_null( $library ) ) {
231 return self::remote_fetch(
232 $library,
233 'patterns',
234 array(
235 'search' => $search,
236 'categoryId' => $category_id,
237 )
238 );
239 }
240
241 return $this->error( 404, "Library of id \"$library_id\" was not found." );
242 }
243
244 /**
245 * Fetch pattern library remotely.
246 *
247 * @param GenerateBlocks_Library_DTO $library The library to fetch data.
248 * @param string $collection The collection type. Either 'categories' or 'patterns'.
249 * @param array $query_args The extra query arguments.
250 *
251 * @return WP_REST_Response
252 */
253 private function remote_fetch(
254 GenerateBlocks_Library_DTO $library,
255 string $collection,
256 array $query_args = array()
257 ): WP_REST_Response {
258 $endpoint = "$library->domain/wp-json/generateblocks-pro/v1/pattern-library/$collection";
259 $url = add_query_arg( $query_args, $endpoint );
260 $cache_key = $library->id . '-' . $collection;
261 $cache = GenerateBlocks_Libraries::get_cached_data( $cache_key, $query_args, $collection );
262
263 if ( false !== $cache ) {
264 return $this->success( $cache );
265 }
266
267 $request = wp_remote_get(
268 $url,
269 array(
270 'headers' => array(
271 'X-GB-Public-Key' => $library->public_key,
272 ),
273 )
274 );
275
276 if ( is_wp_error( $request ) ) {
277 return $this->error( 500, "Unable to request from $endpoint" );
278 }
279
280 $body = wp_remote_retrieve_body( $request );
281 $body = json_decode( $body, true );
282 $data = $body['response']['data'] ?? [];
283
284 // Cache our data.
285 GenerateBlocks_Libraries::set_cached_data( $data, $cache_key, $collection );
286
287 return $this->success( $data );
288 }
289
290 /**
291 * Get the expiry time of a cache.
292 *
293 * @param WP_REST_Request $request The request.
294 *
295 * @return WP_REST_Response
296 */
297 public function get_cache_data( WP_REST_Request $request ): WP_REST_Response {
298 $id = $request->get_param( 'id' );
299 $expiration_time = get_option( '_transient_timeout_' . $id . '-patterns_0' );
300
301 if ( ! $expiration_time ) {
302 return $this->failed( 'no_cache' );
303 }
304
305 $current_time = time();
306 $cache_made_time = $expiration_time - GenerateBlocks_Libraries::get_cache_expiry();
307 $can_clear_cache = $current_time > ( $cache_made_time + 300 );
308
309 return $this->success(
310 [
311 'expiry_time_raw' => $expiration_time,
312 'expiry_time' => gmdate( 'Y-m-d H:i:s', $expiration_time ),
313 'can_clear' => $can_clear_cache,
314 ]
315 );
316 }
317
318 /**
319 * Clear caches for a specific collection.
320 *
321 * @param WP_REST_Request $request The request.
322 *
323 * @return WP_REST_Response
324 */
325 public function clear_cache( WP_REST_Request $request ): WP_REST_Response {
326 $id = $request->get_param( 'id' );
327
328 global $wpdb;
329 $id = sanitize_text_field( $id );
330 $prefix = $wpdb->esc_like( '_transient_' . $id );
331
332 $transient_ids = $wpdb->get_col(
333 $wpdb->prepare(
334 "SELECT option_name FROM $wpdb->options WHERE option_name LIKE %s",
335 $prefix . '%'
336 )
337 );
338
339 foreach ( $transient_ids as $transient_id ) {
340 $transient = str_replace( '_transient_', '', $transient_id );
341 delete_transient( $transient );
342 }
343
344 return $this->success( [] );
345 }
346
347 /**
348 * Returns a success response.
349 *
350 * @param array $data The data.
351 *
352 * @return WP_REST_Response
353 */
354 private function success( array $data ): WP_REST_Response {
355 return new WP_REST_Response(
356 array(
357 'success' => true,
358 'response' => array(
359 'data' => $data,
360 ),
361 ),
362 200
363 );
364 }
365
366 /**
367 * Returns a success response.
368 *
369 * @param string $message The error message.
370 *
371 * @return WP_REST_Response
372 */
373 private function failed( string $message ): WP_REST_Response {
374 return new WP_REST_Response(
375 array(
376 'success' => false,
377 'response' => $message,
378 ),
379 200
380 );
381 }
382
383 /**
384 * Returns a error response.
385 *
386 * @param int $code Error code.
387 * @param string $message Error message.
388 *
389 * @return WP_REST_Response
390 */
391 private function error( int $code, string $message ): WP_REST_Response {
392 return new WP_REST_Response(
393 array(
394 'error' => true,
395 'success' => false,
396 'error_code' => $code,
397 'response' => $message,
398 ),
399 $code
400 );
401 }
402 }
403
404 GenerateBlocks_Pattern_Library_Rest::get_instance()->init();
405