PluginProbe
Content Control – The Ultimate Content Restriction Plugin! Restrict Content, Create Conditional Blocks & More / 2.6.2
Content Control – The Ultimate Content Restriction Plugin! Restrict Content, Create Conditional Blocks & More v2.6.2
trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.1.0 1.1.1 1.1.10 1.1.2 1.1.3 1.1.4 1.1.5 1.1.6 1.1.7 1.1.8 2.0.0 2.0.1 2.0.10 2.0.11 2.0.12 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 All 47 releases
content-control / classes / RestAPI / ObjectSearch.php

ObjectSearch.php in Content Control – The Ultimate Content Restriction Plugin! Restrict Content, Create Conditional Blocks & More 2.6.2, at classes/RestAPI/ObjectSearch.php

436 lines 11.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * RestAPI Global Settings Endpoint.
4 *
5 * @copyright (c) 2021, Code Atlantic LLC.
6 * @package ContentControl
7 */
8
9 namespace ContentControl\RestAPI;
10
11 use WP_User_Query, WP_REST_Controller, WP_REST_Response, WP_REST_Server, WP_Error;
12
13 defined( 'ABSPATH' ) || exit;
14
15 /**
16 * Rest API Object Search Controller Class.
17 */
18 class ObjectSearch extends WP_REST_Controller {
19
20 /**
21 * Endpoint namespace.
22 *
23 * @var string
24 */
25 protected $namespace = 'content-control/v2';
26
27 /**
28 * Route base.
29 *
30 * @var string
31 */
32 protected $base = 'objectSearch';
33
34 /**
35 * Register API endpoint routes.
36 *
37 * @return void
38 */
39 public function register_routes() {
40 register_rest_route(
41 $this->namespace,
42 '/' . $this->base,
43 [
44 [
45 'methods' => WP_REST_Server::READABLE,
46 'callback' => [ $this, 'object_search' ],
47 'permission_callback' => '__return_true', // Read only, so anyone can view.
48 'args' => [
49 'nonce' => [
50 'description' => __( 'Nonce', 'content-control' ),
51 'type' => 'string',
52 'required' => true,
53 ],
54 'hash' => [
55 'description' => __( 'Hash', 'content-control' ),
56 'type' => 'string',
57 'required' => true,
58 ],
59 'entityKind' => [
60 'description' => __( 'Object kind, (postType, taxonomy)', 'content-control' ),
61 'type' => 'string',
62 'required' => true,
63 ],
64 'entityType' => [
65 'description' => __( 'Object type (post, category)', 'content-control' ),
66 'type' => 'string',
67 'required' => true,
68 ],
69 'paged' => [
70 'description' => __( 'Page number', 'content-control' ),
71 'type' => 'integer',
72 'required' => false,
73 ],
74 's' => [
75 'description' => __( 'Search term', 'content-control' ),
76 'type' => 'string',
77 'required' => false,
78 ],
79 'include' => [
80 'description' => __( 'Include IDs', 'content-control' ),
81 'type' => 'string',
82 'required' => false,
83 ],
84 'exclude' => [
85 'description' => __( 'Exclude IDs', 'content-control' ),
86 'type' => 'string',
87 'required' => false,
88 ],
89 ],
90 ],
91 ]
92 );
93 }
94
95 /**
96 * Get block type list.
97 *
98 * @param \WP_REST_Request<array<string,mixed>> $request Request object.
99 *
100 * @return WP_Error|WP_REST_Response
101 */
102 public function object_search( $request ) {
103 $nonce = $request->get_param( 'nonce' );
104 $params = $request->get_params();
105
106 if ( ! isset( $nonce ) || ! wp_verify_nonce( sanitize_key( wp_unslash( $nonce ) ), 'content_control_object_search_nonce' ) ) {
107 wp_send_json_error();
108 }
109
110 try {
111 $results = [
112 'hash' => $request->get_param( 'hash' ),
113 'items' => [],
114 'totalCount' => 0,
115 ];
116
117 $object_kind = isset( $params['entityKind'] ) ? sanitize_text_field( wp_unslash( $params['entityKind'] ) ) : '';
118 $object_type = isset( $params['entityType'] ) ? sanitize_text_field( wp_unslash( $params['entityType'] ) ) : '';
119 $include = ! empty( $params['include'] ) ? wp_parse_id_list( wp_unslash( $params['include'] ) ) : [];
120 $exclude = ! empty( $params['exclude'] ) ? wp_parse_id_list( wp_unslash( $params['exclude'] ) ) : [];
121
122 if ( ! empty( $include ) ) {
123 $exclude = array_merge( $include, $exclude );
124 }
125
126 switch ( $object_kind ) {
127 case 'post_type':
128 $post_type = ! empty( $object_type ) ? $object_type : 'post';
129
130 if ( ! empty( $include ) ) {
131 $include_query = $this->post_type_selectlist_query(
132 $post_type,
133 [
134 'post__in' => $include,
135 'posts_per_page' => - 1,
136 ],
137 true
138 );
139
140 foreach ( $include_query['items'] as $id => $name ) {
141 $results['items'][] = [
142 'id' => $id,
143 'text' => "$name (ID: $id)",
144 ];
145 }
146
147 $results['totalCount'] += (int) $include_query['totalCount'];
148 }
149
150 $query = $this->post_type_selectlist_query(
151 $post_type,
152 [
153 's' => ! empty( $params['s'] ) ? sanitize_text_field( wp_unslash( $params['s'] ) ) : null,
154 'paged' => ! empty( $params['paged'] ) ? absint( $params['paged'] ) : null,
155 'post__not_in' => $exclude,
156 'posts_per_page' => 10,
157 ],
158 true
159 );
160
161 foreach ( $query['items'] as $id => $name ) {
162 $results['items'][] = [
163 'id' => $id,
164 'text' => "$name (ID: $id)",
165 ];
166 }
167
168 $results['totalCount'] += (int) $query['totalCount'];
169 break;
170
171 case 'taxonomy':
172 $taxonomy = ! empty( $params['object_key'] ) ? sanitize_text_field( wp_unslash( $params['object_key'] ) ) : 'category';
173
174 if ( ! empty( $include ) ) {
175 $include_query = $this->taxonomy_selectlist_query(
176 $taxonomy,
177 [
178 'include' => $include,
179 'number' => 0,
180 ],
181 true
182 );
183
184 foreach ( $include_query['items'] as $id => $name ) {
185 $results['items'][] = [
186 'id' => $id,
187 'text' => "$name (ID: $id)",
188 ];
189 }
190
191 $results['totalCount'] += (int) $include_query['totalCount'];
192 }
193
194 $query = $this->taxonomy_selectlist_query(
195 $taxonomy,
196 [
197 'search' => ! empty( $params['s'] ) ? sanitize_text_field( wp_unslash( $params['s'] ) ) : null,
198 'paged' => ! empty( $params['paged'] ) ? absint( $params['paged'] ) : null,
199 'exclude' => $exclude,
200 'number' => 10,
201 ],
202 true
203 );
204
205 foreach ( $query['items'] as $id => $name ) {
206 $results['items'][] = [
207 'id' => $id,
208 'text' => "$name (ID: $id)",
209 ];
210 }
211
212 $results['totalCount'] += (int) $query['totalCount'];
213 break;
214 case 'user':
215 if ( ! current_user_can( 'list_users' ) ) {
216 wp_send_json_error();
217 }
218
219 $user_role = ! empty( $params['object_key'] ) ? sanitize_text_field( wp_unslash( $params['object_key'] ) ) : null;
220
221 if ( ! empty( $include ) ) {
222 $include_query = $this->user_selectlist_query(
223 [
224 'role' => $user_role,
225 'include' => $include,
226 'number' => - 1,
227 ],
228 true
229 );
230
231 foreach ( $include_query['items'] as $id => $name ) {
232 $results['items'][] = [
233 'id' => $id,
234 'text' => "$name (ID: $id)",
235 ];
236 }
237
238 $results['totalCount'] += (int) $include_query['totalCount'];
239 }
240
241 $query = $this->user_selectlist_query(
242 [
243 'role' => $user_role,
244 'search' => ! empty( $params['s'] ) ? '*' . sanitize_text_field( wp_unslash( $params['s'] ) ) . '*' : null,
245 'paged' => ! empty( $params['paged'] ) ? absint( $params['paged'] ) : null,
246 'exclude' => $exclude,
247 'number' => 10,
248 ],
249 true
250 );
251
252 foreach ( $query['items'] as $id => $name ) {
253 $results['items'][] = [
254 'id' => $id,
255 'text' => "$name (ID: $id)",
256 ];
257 }
258
259 $results['totalCount'] += (int) $query['totalCount'];
260 break;
261 }
262
263 // Take out keys which were only used to deduplicate.
264 $results['items'] = array_values( $results['items'] );
265
266 return new WP_REST_Response( $results, 200 );
267 } catch ( \Exception $e ) {
268 return new WP_Error( '500', __( 'Something went wrong, the results could not be returned.', 'content-control' ), [ 'status' => 500 ] );
269 }
270 }
271
272
273 /**
274 * Get a list of posts for a select list.
275 *
276 * @param string $post_type Post type(s) to query.
277 * @param array<string,mixed> $args Query arguments.
278 * @param boolean $include_total Whether to include the total count in the response.
279 * @return array{items:array<int,string>,totalCount:int}|array<int,string>
280 */
281 public function post_type_selectlist_query( $post_type, $args = [], $include_total = false ) {
282 if ( empty( $post_type ) ) {
283 $post_type = [ 'any' ];
284 }
285
286 $args = wp_parse_args( $args, [
287 'posts_per_page' => 10,
288 'post_type' => $post_type,
289 'post__in' => null,
290 'post__not_in' => null,
291 'post_status' => null,
292 'page' => 1,
293 // Performance Optimization.
294 'no_found_rows' => ! $include_total ? true : false,
295 'update_post_term_cache' => false,
296 'update_post_meta_cache' => false,
297 ] );
298
299 // $post_type should always be single string?
300 if ( 'attachment' === $post_type ) {
301 $args['post_status'] = 'inherit';
302 }
303
304 // Query Caching.
305 static $queries = [];
306
307 $key = md5( maybe_serialize( $args ) );
308
309 if ( ! isset( $queries[ $key ] ) ) {
310 $query = new \WP_Query( $args );
311
312 $posts = [];
313 foreach ( $query->posts as $post ) {
314 /**
315 * The post object.
316 *
317 * @var \WP_Post $post
318 */
319 $posts[ $post->ID ] = $post->post_title;
320 }
321
322 $results = [
323 'items' => $posts,
324 'totalCount' => $query->found_posts,
325 ];
326
327 $queries[ $key ] = $results;
328 } else {
329 $results = $queries[ $key ];
330 }
331
332 return ! $include_total ? $results['items'] : $results;
333 }
334
335 /**
336 * Get a list of terms for a select list.
337 *
338 * @param string $taxonomy Taxonomy(s) to query.
339 * @param array<string,mixed> $args Query arguments.
340 * @param boolean $include_total Whether to include the total count in the response.
341 * @return array{items:array<int,string>,totalCount:int}|array<int,string>
342 */
343 public function taxonomy_selectlist_query( $taxonomy, $args = [], $include_total = false ) {
344 if ( empty( $taxonomy ) ) {
345 $taxonomy = [ 'category' ];
346 }
347
348 $args = wp_parse_args( $args, [
349 'hide_empty' => false,
350 'number' => 10,
351 'search' => '',
352 'include' => null,
353 'exclude' => null,
354 'offset' => 0,
355 'page' => null,
356 'taxonomy' => $taxonomy,
357 ] );
358
359 if ( $args['page'] ) {
360 $args['offset'] = ( $args['page'] - 1 ) * $args['number'];
361 }
362
363 // Query Caching.
364 static $queries = [];
365
366 $key = md5( maybe_serialize( $args ) );
367
368 if ( ! isset( $queries[ $key ] ) ) {
369 $terms = [];
370
371 foreach ( get_terms( $args ) as $term ) {
372 $terms[ $term->term_id ] = $term->name;
373 }
374
375 $total_args = $args;
376 $total_args['fields'] = 'count';
377 unset( $total_args['number'] );
378 unset( $total_args['offset'] );
379
380 $results = [
381 'items' => $terms,
382 'totalCount' => $include_total ? get_terms( $total_args ) : null,
383 ];
384
385 $queries[ $key ] = $results;
386 } else {
387 $results = $queries[ $key ];
388 }
389
390 return ! $include_total ? $results['items'] : $results;
391 }
392
393 /**
394 * Get a list of users for a select list.
395 *
396 * @param array<string,mixed> $args Query arguments.
397 * @param bool $include_total Whether to include the total count in the response.
398 *
399 * @return array{items:array<int,string>,totalCount:int}|array<int,string>
400 */
401 public function user_selectlist_query( $args = [], $include_total = false ) {
402 $args = wp_parse_args(
403 $args,
404 [
405 'role' => null,
406 'count_total' => ! $include_total ? true : false,
407 ]
408 );
409
410 // Query Caching.
411 static $queries = [];
412
413 $key = md5( maybe_serialize( $args ) );
414
415 if ( ! isset( $queries[ $key ] ) ) {
416 $query = new WP_User_Query( $args );
417
418 $users = [];
419 foreach ( $query->get_results() as $user ) {
420 $users[ $user->ID ] = $user->display_name;
421 }
422
423 $results = [
424 'items' => $users,
425 'totalCount' => $query->get_total(),
426 ];
427
428 $queries[ $key ] = $results;
429 } else {
430 $results = $queries[ $key ];
431 }
432
433 return ! $include_total ? $results['items'] : $results;
434 }
435 }
436