PluginProbe
Content Control – The Ultimate Content Restriction Plugin! Restrict Content, Create Conditional Blocks & More / 2.6.4
Content Control – The Ultimate Content Restriction Plugin! Restrict Content, Create Conditional Blocks & More v2.6.4
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.4, at classes/RestAPI/ObjectSearch.php

433 lines 11.2 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 return new WP_REST_Response( $results, 200 );
264 } catch ( \Exception $e ) {
265 return new WP_Error( '500', __( 'Something went wrong, the results could not be returned.', 'content-control' ), [ 'status' => 500 ] );
266 }
267 }
268
269
270 /**
271 * Get a list of posts for a select list.
272 *
273 * @param string $post_type Post type(s) to query.
274 * @param array<string,mixed> $args Query arguments.
275 * @param boolean $include_total Whether to include the total count in the response.
276 * @return array{items:array<int,string>,totalCount:int}|array<int,string>
277 */
278 public function post_type_selectlist_query( $post_type, $args = [], $include_total = false ) {
279 if ( empty( $post_type ) ) {
280 $post_type = [ 'any' ];
281 }
282
283 $args = wp_parse_args( $args, [
284 'posts_per_page' => 10,
285 'post_type' => $post_type,
286 'post__in' => null,
287 'post__not_in' => null,
288 'post_status' => null,
289 'page' => 1,
290 // Performance Optimization.
291 'no_found_rows' => ! $include_total ? true : false,
292 'update_post_term_cache' => false,
293 'update_post_meta_cache' => false,
294 ] );
295
296 // $post_type should always be single string?
297 if ( 'attachment' === $post_type ) {
298 $args['post_status'] = 'inherit';
299 }
300
301 // Query Caching.
302 static $queries = [];
303
304 $key = md5( maybe_serialize( $args ) );
305
306 if ( ! isset( $queries[ $key ] ) ) {
307 $query = new \WP_Query( $args );
308
309 $posts = [];
310 foreach ( $query->posts as $post ) {
311 /**
312 * The post object.
313 *
314 * @var \WP_Post $post
315 */
316 $posts[ $post->ID ] = $post->post_title;
317 }
318
319 $results = [
320 'items' => $posts,
321 'totalCount' => $query->found_posts,
322 ];
323
324 $queries[ $key ] = $results;
325 } else {
326 $results = $queries[ $key ];
327 }
328
329 return ! $include_total ? $results['items'] : $results;
330 }
331
332 /**
333 * Get a list of terms for a select list.
334 *
335 * @param string $taxonomy Taxonomy(s) to query.
336 * @param array<string,mixed> $args Query arguments.
337 * @param boolean $include_total Whether to include the total count in the response.
338 * @return array{items:array<int,string>,totalCount:int}|array<int,string>
339 */
340 public function taxonomy_selectlist_query( $taxonomy, $args = [], $include_total = false ) {
341 if ( empty( $taxonomy ) ) {
342 $taxonomy = [ 'category' ];
343 }
344
345 $args = wp_parse_args( $args, [
346 'hide_empty' => false,
347 'number' => 10,
348 'search' => '',
349 'include' => null,
350 'exclude' => null,
351 'offset' => 0,
352 'page' => null,
353 'taxonomy' => $taxonomy,
354 ] );
355
356 if ( $args['page'] ) {
357 $args['offset'] = ( $args['page'] - 1 ) * $args['number'];
358 }
359
360 // Query Caching.
361 static $queries = [];
362
363 $key = md5( maybe_serialize( $args ) );
364
365 if ( ! isset( $queries[ $key ] ) ) {
366 $terms = [];
367
368 foreach ( get_terms( $args ) as $term ) {
369 $terms[ $term->term_id ] = $term->name;
370 }
371
372 $total_args = $args;
373 $total_args['fields'] = 'count';
374 unset( $total_args['number'] );
375 unset( $total_args['offset'] );
376
377 $results = [
378 'items' => $terms,
379 'totalCount' => $include_total ? get_terms( $total_args ) : null,
380 ];
381
382 $queries[ $key ] = $results;
383 } else {
384 $results = $queries[ $key ];
385 }
386
387 return ! $include_total ? $results['items'] : $results;
388 }
389
390 /**
391 * Get a list of users for a select list.
392 *
393 * @param array<string,mixed> $args Query arguments.
394 * @param bool $include_total Whether to include the total count in the response.
395 *
396 * @return array{items:array<int,string>,totalCount:int}|array<int,string>
397 */
398 public function user_selectlist_query( $args = [], $include_total = false ) {
399 $args = wp_parse_args(
400 $args,
401 [
402 'role' => null,
403 'count_total' => ! $include_total ? true : false,
404 ]
405 );
406
407 // Query Caching.
408 static $queries = [];
409
410 $key = md5( maybe_serialize( $args ) );
411
412 if ( ! isset( $queries[ $key ] ) ) {
413 $query = new WP_User_Query( $args );
414
415 $users = [];
416 foreach ( $query->get_results() as $user ) {
417 $users[ $user->ID ] = $user->display_name;
418 }
419
420 $results = [
421 'items' => $users,
422 'totalCount' => $query->get_total(),
423 ];
424
425 $queries[ $key ] = $results;
426 } else {
427 $results = $queries[ $key ];
428 }
429
430 return ! $include_total ? $results['items'] : $results;
431 }
432 }
433