PluginProbe
Post Grid Gutenberg Blocks – PostX / 5.0.41
Post Grid Gutenberg Blocks – PostX v5.0.41
5.0.41 5.0.39 5.0.38 5.0.37 5.0.36 5.0.35 5.0.34 5.0.33 5.0.32 5.0.31 5.0.30 5.0.29 5.0.28 5.0.27 5.0.26 5.0.25 5.0.23 5.0.24 5.0.22 5.0.21 5.0.20 5.0.19 5.0.18 5.0.17 2.1.1 All 238 releases
ultimate-post / addons / dynamic_content / includes / DCController.php

DCController.php in Post Grid Gutenberg Blocks – PostX 5.0.41, at addons/dynamic_content/includes/DCController.php

617 lines 13.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace ULTP;
3
4 use WP_REST_Response;
5
6 if ( ! defined( 'ABSPATH' ) ) {
7 exit;
8 }
9
10 /**
11 *
12 * Dynamic Content
13 *
14 * @package ULTP\Addons
15 * @since 4.1.1
16 */
17 final class DCController {
18
19 /**
20 * Setup class.
21 *
22 * @since v.4.1.1
23 */
24 public function __construct() {
25 require_once ULTP_PATH . '/addons/dynamic_content/includes/DCService.php';
26
27 add_action( 'rest_api_init', array( $this, 'register_routes' ) );
28 }
29
30 public function register_routes() {
31 register_rest_route(
32 'ultp/v2',
33 '/get_dynamic_content/',
34 array(
35 array(
36 'methods' => 'POST',
37 'callback' => array( $this, 'handle_dynamic_data' ),
38 // there is an unauthenticated route for fetching user data against post, that can be used to fetch user sensitive data like user email, user password reset token hast ( user_activation_key ) , private or draft post title e.t.c as unauthenticated user.
39 'permission_callback' => function ( $request ) {
40 $post_id = $this->get_request_post_id( $request );
41
42 if ( ! $this->user_can_access_post( $post_id ) ) {
43 return false;
44 }
45
46 $data_type = method_exists( $request, 'get_param' )
47 ? $request->get_param('data_type')
48 : ( isset( $request['data_type'] ) ? $request['data_type'] : '' );
49
50 // Restrict author_info to users who can edit the author OR admins
51 if ( $data_type === 'author_info' ) {
52 $post = get_post( $post_id );
53 $author_id = $post ? (int) $post->post_author : 0;
54 if ( ! current_user_can( 'edit_user', $author_id ) && ! current_user_can( 'manage_options' ) ) {
55 return false;
56 }
57 }
58
59 return true;
60 },
61 'args' => array(),
62 ),
63 )
64 );
65
66 register_rest_route(
67 'ultp/v2',
68 '/get_custom_fields/',
69 array(
70 array(
71 'methods' => 'POST',
72 'callback' => array( $this, 'handle_custom_fields' ),
73 // custom field keys can reveal the meta-field schema of posts the caller shouldn't be able to see (private/draft/pending/scheduled/password-protected), so require the same access check as get_dynamic_content.
74 'permission_callback' => function ( $request ) {
75 return $this->user_can_access_post( $this->get_request_post_id( $request ) );
76 },
77 'args' => array(),
78 ),
79 )
80 );
81 }
82
83 /**
84 * Reads the `post_id` request param, compatible with both WP_REST_Request and plain array access.
85 *
86 * @param WP_REST_Request|array $request Request object or params array.
87 * @return int
88 */
89 private function get_request_post_id( $request ) {
90 return method_exists( $request, 'get_param' )
91 ? intval( $request->get_param( 'post_id' ) )
92 : ( isset( $request['post_id'] ) ? intval( $request['post_id'] ) : 0 );
93 }
94
95 /**
96 * Whether the current user may access dynamic data/custom fields for the given post.
97 *
98 * @param int $post_id
99 * @return bool
100 */
101 private function user_can_access_post( $post_id ) {
102 // User must be logged in
103 if ( ! is_user_logged_in() ) {
104 return false;
105 }
106
107 // If no post_id, require edit_posts capability
108 if ( $post_id <= 0 ) {
109 return current_user_can( 'edit_posts' );
110 }
111
112 // Get the post
113 $post = get_post( $post_id );
114 if ( ! $post ) {
115 return false;
116 }
117
118 // Check if post is password protected
119 if ( post_password_required( $post ) ) {
120 return false;
121 }
122
123 // User must be able to edit this specific post
124 if ( ! current_user_can( 'edit_post', $post_id ) ) {
125 return false;
126 }
127
128 // For non-published posts, user must be author OR have edit_posts capability
129 if ( $post->post_status !== 'publish' ) {
130 if ( (int) $post->post_author !== get_current_user_id() && ! current_user_can( 'edit_posts' ) ) {
131 return false;
132 }
133 }
134
135 return true;
136 }
137
138 /**
139 * Dynamic data to show in the editor
140 *
141 * @since v.4.1.1
142 * @param WP_REST_Request $server
143 * @return WP_REST_Response
144 */
145 public function handle_dynamic_data( $server ) {
146 $args = $server->get_params();
147 $post_id = isset( $args['post_id'] ) ? intval( $args['post_id'] ) : '';
148 $data_type = isset( $args['data_type'] ) ? $args['data_type'] : '';
149 $key = isset( $args['key'] ) ? $args['key'] : '';
150
151 return rest_ensure_response(
152 array(
153 'data' => DCService::get_dynamic_data(
154 array(
155 'post_id' => $post_id,
156 'key' => $key,
157 'data_type' => $data_type,
158 )
159 ),
160 )
161 );
162 }
163
164 /**
165 * Gets custom fields keys and labels
166 *
167 * @since v.4.1.1
168 * @param WP_REST_Request $server
169 * @return WP_REST_Response
170 */
171 public function handle_custom_fields( $server ) {
172 $args = $server->get_params();
173
174 $post_id = isset( $args['post_id'] ) ? intval( $args['post_id'] ) : 0;
175 $post_type = isset( $args['post_type'] ) ? $args['post_type'] : '';
176 $field_type = isset( $args['acf_field_type'] ) ? $args['acf_field_type'] : '';
177
178 $res = array();
179
180 // All metas
181 $all_custom_metas = $this->get_custom_metas( $post_id, $post_type );
182
183 // ACF
184 $acf_field_keys = $this->get_acf_fields( $post_id, $field_type, $post_type );
185
186 // Meta Box
187 $mb_field_keys = $this->get_mb_fields( $post_id, $field_type, $post_type );
188
189 // Pods
190 $pods_field_keys = $this->get_pods_fields( $post_id, $field_type, $post_type );
191
192 $filtered_custom_metas = array_values( array_diff( $all_custom_metas, $acf_field_keys['_fields'] ) );
193 $filtered_custom_metas = array_filter(
194 $filtered_custom_metas,
195 function ( $item ) use ( $acf_field_keys ) {
196 foreach ( $acf_field_keys['prefixes'] as $prefix ) {
197 if ( str_starts_with( $item, $prefix ) ) {
198 return false;
199 }
200 }
201 return true;
202 }
203 );
204 $filtered_custom_metas = array_values( array_diff( $filtered_custom_metas, $mb_field_keys['_fields'] ) );
205 $filtered_custom_metas = array_values( array_diff( $filtered_custom_metas, $pods_field_keys['_fields'] ) );
206
207 // Return value
208 $res['custom_metas'] = array(
209 'fields' => array_map(
210 function ( $item ) {
211 return array(
212 'label' => $item,
213 'value' => $item,
214 );
215 },
216 $filtered_custom_metas
217 ),
218 );
219
220 $res['acf'] = array(
221 'fields' => $acf_field_keys['fields'],
222 );
223
224 $res['mb'] = array(
225 'fields' => $mb_field_keys['fields'],
226 );
227
228 $res['pods'] = array(
229 'fields' => $pods_field_keys['fields'],
230 );
231
232 return rest_ensure_response(
233 array(
234 'data' => $res,
235 )
236 );
237 }
238
239 /**
240 * Get ACF fields
241 *
242 * @param int $post_id
243 * @param string $field_type
244 * @param string $post_type
245 *
246 * @return array
247 * @since 4.1.1
248 */
249 public function get_acf_fields( $post_id, $field_type, $post_type ) {
250 $res = array(
251 'fields' => array(),
252 '_fields' => array(),
253 'prefixes' => array(),
254 );
255
256 if ( ! class_exists( 'ACF' ) ) {
257 return $res;
258 }
259
260 if ( empty( $post_id ) && empty( $post_type ) ) {
261 global $post;
262 $post_id = isset( $post->ID ) ? $post->ID : '';
263 }
264
265 $allowed_types = $this->get_allowed_acf_field_types( $field_type );
266
267 // If post_id set set, return ACF fields for that post
268 if ( ! empty( $post_id ) ) {
269 $fields = get_field_objects( $post_id );
270 if ( is_array( $fields ) ) {
271 foreach ( $fields as $field ) {
272 if ( in_array( $field['type'], $allowed_types, true ) ) {
273 $res['fields'][] = array(
274 'value' => $field['name'],
275 'label' => $field['label'],
276 );
277 }
278
279 $res['_fields'][] = $field['name'];
280
281 // For filtering out pesky repeater field's sub fields
282 if ( $field['type'] === 'repeater' ) {
283 $res['prefixes'][] = $field['name'];
284 }
285 }
286 }
287 } elseif ( ! empty( $post_type ) ) {
288 $groups = acf_get_field_groups( array( 'post_type' => $post_type ) );
289 foreach ( $groups as $group ) {
290 $fields = acf_get_fields( $group['ID'] );
291 if ( is_array( $fields ) ) {
292 foreach ( $fields as $field ) {
293 if ( in_array( $field['type'], $allowed_types, true ) ) {
294 $res['fields'][] = array(
295 'value' => $field['name'],
296 'label' => $field['label'] . ' [' . $group['title'] . ']',
297 );
298 }
299 $res['_fields'][] = $field['name'];
300
301 if ( $field['type'] === 'repeater' ) {
302 $res['prefixes'][] = $field['name'];
303 }
304 }
305 }
306 }
307 }
308
309 return $res;
310 }
311
312 /**
313 * Get Meta Box fields
314 *
315 * @param int $post_id
316 * @param string $field_type
317 * @param string $post_type
318 *
319 * @return array
320 * @since 4.1.1
321 */
322 public function get_mb_fields( $post_id, $field_type, $post_type ) {
323 $res = array(
324 'fields' => array(),
325 '_fields' => array(),
326 'prefixes' => array(),
327 );
328
329 if ( ! function_exists( 'rwmb_get_field_settings' ) ) {
330 return $res;
331 }
332
333 $value = null;
334
335 if ( empty( $post_id ) && empty( $post_type ) ) {
336 global $post;
337 $value = isset( $post->ID ) ? $post->ID : '';
338 } elseif ( ! empty( $post_id ) ) {
339 $value = $post_id;
340 } elseif ( ! empty( $post_type ) ) {
341 $value = $post_type;
342 }
343
344 if ( empty( $value ) ) {
345 return $res;
346 }
347
348 $allowed_types = self::get_allowed_mb_field_type( $field_type );
349
350 $fields = rwmb_get_object_fields( $value );
351
352 if ( is_array( $fields ) ) {
353 foreach ( $fields as $field ) {
354 if ( in_array( $field['type'], $allowed_types, true ) ) {
355 $res['fields'][] = array(
356 'value' => $field['id'],
357 'label' => $field['name'],
358 );
359 }
360
361 $res['_fields'][] = $field['id'];
362 }
363 }
364
365 return $res;
366 }
367
368 /**
369 * Get Pods fields
370 *
371 * @param int $post_id
372 * @param string $field_type
373 * @param string $post_type
374 *
375 * @return array
376 * @since 4.1.1
377 */
378 public function get_pods_fields( $post_id, $field_type, $post_type ) {
379 $res = array(
380 'fields' => array(),
381 '_fields' => array(),
382 'prefixes' => array(),
383 );
384
385 if ( ! function_exists( 'pods' ) ) {
386 return $res;
387 }
388
389 if ( empty( $post_id ) ) {
390 global $post;
391 $post_id = isset( $post->ID ) ? $post->ID : '';
392 }
393
394 if ( empty( $post_type ) ) {
395 $post_type = get_post_type( $post_id );
396 }
397
398 if ( empty( $post_type ) ) {
399 return $res;
400 }
401
402 $allowed_types = self::get_allowed_pods_field_types( $field_type );
403
404 $pods = pods( $post_type, $post_id );
405 if ( is_object( $pods ) && method_exists( $pods, 'exists' ) && $pods->exists() && method_exists( $pods, 'fields' ) ) {
406 $fields = $pods->fields();
407 if ( is_array( $fields ) ) {
408 foreach ( $fields as $field ) {
409 if ( in_array( $field['type'], $allowed_types, true ) &&
410 'field' === $field['object_type'] &&
411 'post_type' === $field['object_storage_type']
412 ) {
413 $res['fields'][] = array(
414 'value' => $field['name'],
415 'label' => $field['label'],
416 );
417 }
418
419 $res['_fields'][] = $field['name'];
420 }
421 }
422 }
423
424 return $res;
425 }
426
427 /**
428 * Get ACF allowed field types
429 *
430 * @param string $type optional, possible values 'text'|'image'|'url'.
431 *
432 * @return array
433 * @since 4.1.1
434 */
435 public static function get_allowed_acf_field_types( $type = 'text' ) {
436
437 if ( 'image' === $type ) {
438 return array(
439 'image',
440 );
441 } elseif ( 'url' === $type ) {
442 return array(
443 'text',
444 'email',
445 'image',
446 'file',
447 'page_link',
448 'url',
449 'link',
450 );
451 }
452
453 return array(
454 'text',
455 'textarea',
456 'number',
457 'range',
458 'email',
459 'url',
460 'password',
461 'wysiwyg',
462 'select',
463 'checkbox',
464 'radio',
465 'true_false',
466 'date_picker',
467 'time_picker',
468 'date_time_picker',
469 'color_picker',
470 );
471 }
472
473 /**
474 * Get Meta Box allowed field types
475 *
476 * @param string $type optional, possible values 'text'|'image'|'url'.
477 *
478 * @return array
479 * @since 4.1.1
480 */
481 public static function get_allowed_mb_field_type( $type ) {
482
483 if ( $type === 'image' ) {
484 return array(
485 'image',
486 'image_advanced',
487 'image_upload',
488 'single_image',
489 'url',
490 'file',
491 'file_advanced',
492 'file_input',
493 'file_upload',
494 );
495 } elseif ( $type === 'url' ) {
496 return array(
497 'url',
498 'file',
499 'file_advanced',
500 'file_input',
501 'file_upload',
502 );
503 }
504
505 return array(
506 'text',
507 'email',
508 'number',
509 'textaraa',
510 'select',
511 'radio',
512 'checkbox',
513 'checkbox_list',
514 );
515 }
516
517 /**
518 * Get Pods allowed field types
519 *
520 * @param string $type optional, possible values 'text'|'image'|'url'.
521 *
522 * @return array
523 * @since 4.1.1
524 */
525 public static function get_allowed_pods_field_types( $type = 'text' ) {
526
527 if ( 'image' === $type ) {
528 return array(
529 'images',
530 'file',
531 );
532 } elseif ( 'url' === $type ) {
533 return array(
534 'text',
535 'email',
536 'images',
537 'file',
538 'link',
539 'website',
540 );
541 }
542
543 return array(
544 'text',
545 'paragraph',
546 'password',
547 'phone',
548 'time',
549 'website',
550 'number',
551 'wysiwyg',
552 'email',
553 'link',
554 'boolean',
555 'code',
556 'number',
557 'currency',
558 'date',
559 'datetime',
560 );
561 }
562
563 /**
564 * Get custom post metas
565 *
566 * @param string $post_type Post Type.
567 * @since 4.1.0
568 * @return array
569 */
570 public function get_custom_metas( $post_id, $post_type ) {
571
572 $meta_keys = array();
573 $all_keys = array();
574
575 if ( $post_id !== 0 ) {
576 $all_keys = get_post_custom_keys( $post_id );
577
578 } else {
579 if ( ! isset( $post_type ) ) {
580 return $meta_keys;
581 }
582
583 $posts = get_posts(
584 array(
585 'post_type' => $post_type,
586 'posts_per_page' => -1,
587 'fields' => 'id',
588 )
589 );
590
591 if ( empty( $posts ) ) {
592 return $meta_keys;
593 }
594
595 foreach ( $posts as $post ) {
596 $post_id = isset( $post->ID ) ? $post->ID : 0;
597 $keys = get_post_custom_keys( $post_id );
598 if ( is_array( $keys ) ) {
599 foreach ( $keys as $key ) {
600 $all_keys[] = $key;
601 }
602 }
603 }
604 }
605
606 if ( is_array( $all_keys ) ) {
607 foreach ( $all_keys as $key ) {
608 if ( ! isset( $meta_keys[ $key ] ) && ! str_starts_with( $key, '_' ) ) {
609 $meta_keys[ $key ] = $key;
610 }
611 }
612 }
613
614 return array_keys( $meta_keys );
615 }
616 }
617