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

431 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 // 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 $posts[ $post->ID ] = $post->post_title;
315 }
316
317 $results = [
318 'items' => $posts,
319 'totalCount' => $query->found_posts,
320 ];
321
322 $queries[ $key ] = $results;
323 } else {
324 $results = $queries[ $key ];
325 }
326
327 return ! $include_total ? $results['items'] : $results;
328 }
329
330 /**
331 * Get a list of terms for a select list.
332 *
333 * @param string $taxonomy Taxonomy(s) to query.
334 * @param array<string,mixed> $args Query arguments.
335 * @param boolean $include_total Whether to include the total count in the response.
336 * @return array{items:array<int,string>,totalCount:int}|array<int,string>
337 */
338 public function taxonomy_selectlist_query( $taxonomy, $args = [], $include_total = false ) {
339 if ( empty( $taxonomy ) ) {
340 $taxonomy = [ 'category' ];
341 }
342
343 $args = wp_parse_args( $args, [
344 'hide_empty' => false,
345 'number' => 10,
346 'search' => '',
347 'include' => null,
348 'exclude' => null,
349 'offset' => 0,
350 'page' => null,
351 'taxonomy' => $taxonomy,
352 ] );
353
354 if ( $args['page'] ) {
355 $args['offset'] = ( $args['page'] - 1 ) * $args['number'];
356 }
357
358 // Query Caching.
359 static $queries = [];
360
361 $key = md5( maybe_serialize( $args ) );
362
363 if ( ! isset( $queries[ $key ] ) ) {
364 $terms = [];
365
366 foreach ( get_terms( $args ) as $term ) {
367 $terms[ $term->term_id ] = $term->name;
368 }
369
370 $total_args = $args;
371 $total_args['fields'] = 'count';
372 unset( $total_args['number'] );
373 unset( $total_args['offset'] );
374
375 $results = [
376 'items' => $terms,
377 'totalCount' => $include_total ? get_terms( $total_args ) : null,
378 ];
379
380 $queries[ $key ] = $results;
381 } else {
382 $results = $queries[ $key ];
383 }
384
385 return ! $include_total ? $results['items'] : $results;
386 }
387
388 /**
389 * Get a list of users for a select list.
390 *
391 * @param array<string,mixed> $args Query arguments.
392 * @param bool $include_total Whether to include the total count in the response.
393 *
394 * @return array{items:array<int,string>,totalCount:int}|array<int,string>
395 */
396 public function user_selectlist_query( $args = [], $include_total = false ) {
397 $args = wp_parse_args(
398 $args,
399 [
400 'role' => null,
401 'count_total' => ! $include_total ? true : false,
402 ]
403 );
404
405 // Query Caching.
406 static $queries = [];
407
408 $key = md5( maybe_serialize( $args ) );
409
410 if ( ! isset( $queries[ $key ] ) ) {
411 $query = new WP_User_Query( $args );
412
413 $users = [];
414 foreach ( $query->get_results() as $user ) {
415 $users[ $user->ID ] = $user->display_name;
416 }
417
418 $results = [
419 'items' => $users,
420 'totalCount' => $query->get_total(),
421 ];
422
423 $queries[ $key ] = $results;
424 } else {
425 $results = $queries[ $key ];
426 }
427
428 return ! $include_total ? $results['items'] : $results;
429 }
430 }
431