PluginProbe ʕ •ᴥ•ʔ
Pods – Custom Content Types and Fields / 3.2.2
Pods – Custom Content Types and Fields v3.2.2
trunk 1.14.8 2.7.31.3 2.8.23.3 2.9.19.3 3.0.10.3 3.1.4.1 3.2.0 3.2.1 3.2.1.1 3.2.2 3.2.4 3.2.5 3.2.6 3.2.7 3.2.7.1 3.2.8 3.2.8.1 3.2.8.2 3.3.0 3.3.1 3.3.2 3.3.3 3.3.4 3.3.5 3.3.6 3.3.7 3.3.8 3.3.9
pods / classes / PodsAdmin.php
pods / classes Last commit date
cli 3 years ago fields 2 years ago widgets 3 years ago Pods.php 2 years ago PodsAPI.php 2 years ago PodsAdmin.php 2 years ago PodsArray.php 2 years ago PodsComponent.php 8 years ago PodsComponents.php 3 years ago PodsData.php 2 years ago PodsField.php 2 years ago PodsForm.php 2 years ago PodsI18n.php 4 years ago PodsInit.php 2 years ago PodsMeta.php 2 years ago PodsMigrate.php 3 years ago PodsRESTFields.php 2 years ago PodsRESTHandlers.php 3 years ago PodsTermSplitting.php 3 years ago PodsUI.php 2 years ago PodsView.php 2 years ago
PodsAdmin.php
4939 lines
1 <?php
2
3 use Pods\Admin\Config\Pod as Config_Pod;
4 use Pods\Admin\Config\Group as Config_Group;
5 use Pods\Admin\Config\Field as Config_Field;
6 use Pods\Admin\Settings;
7 use Pods\Tools\Repair;
8 use Pods\Whatsit\Pod;
9
10 /**
11 * @package Pods
12 */
13 class PodsAdmin {
14
15 /**
16 * @var PodsAdmin
17 */
18 public static $instance = null;
19
20 /**
21 * Singleton handling for a basic pods_admin() request
22 *
23 * @return \PodsAdmin
24 *
25 * @since 2.3.5
26 */
27 public static function init() {
28
29 if ( ! is_object( self::$instance ) ) {
30 self::$instance = new PodsAdmin();
31 }
32
33 return self::$instance;
34 }
35
36 /**
37 * Setup and Handle Admin functionality
38 *
39 * @return \PodsAdmin
40 *
41 * @license http://www.gnu.org/licenses/gpl-2.0.html
42 * @since 2.0.0
43 */
44 public function __construct() {
45
46 // Scripts / Stylesheets
47 add_action( 'admin_enqueue_scripts', array( $this, 'admin_head' ), 20 );
48
49 // AJAX $_POST fix
50 add_action( 'admin_init', array( $this, 'admin_init' ), 9 );
51
52 // Menus
53 add_action( 'admin_menu', array( $this, 'admin_menu' ), 9 );
54
55 // AJAX for Admin
56 add_action( 'wp_ajax_pods_admin', array( $this, 'admin_ajax' ) );
57 add_action( 'wp_ajax_nopriv_pods_admin', array( $this, 'admin_ajax' ) );
58
59 // Add Media Bar button for Shortcode
60 add_action( 'media_buttons', array( $this, 'media_button' ), 12 );
61
62 // Add the Pods capabilities
63 add_filter( 'members_get_capabilities', array( $this, 'admin_capabilities' ) );
64
65 add_action( 'admin_head-media-upload-popup', array( $this, 'register_media_assets' ) );
66
67 // Add our debug to Site Info.
68 add_filter( 'debug_information', array( $this, 'add_debug_information' ) );
69
70 // Add our status tests.
71 add_filter( 'site_status_tests', [ $this, 'site_status_tests' ] );
72
73 $this->rest_admin();
74
75 }
76
77 /**
78 * Init the admin area
79 *
80 * @since 2.0.0
81 */
82 public function admin_init() {
83
84 // Fix for plugins that *don't do it right* so we don't cause issues for users
85 // @codingStandardsIgnoreLine
86 if ( defined( 'DOING_AJAX' ) && ! empty( $_POST ) ) {
87 $pods_admin_ajax_actions = array(
88 'pods_admin',
89 'pods_relationship',
90 'pods_upload',
91 'pods_admin_components',
92 );
93
94 /**
95 * Admin AJAX Callbacks
96 *
97 * @since unknown
98 *
99 * @param array $pods_admin_ajax_actions Array of actions to handle.
100 */
101 $pods_admin_ajax_actions = apply_filters( 'pods_admin_ajax_actions', $pods_admin_ajax_actions );
102
103 if ( in_array( pods_v( 'action' ), $pods_admin_ajax_actions, true ) || in_array( pods_v( 'action', 'post' ), $pods_admin_ajax_actions, true ) ) {
104 // @codingStandardsIgnoreLine
105 foreach ( $_POST as $key => $value ) {
106 if ( 'action' === $key || 0 === strpos( $key, '_podsfix_' ) ) {
107 continue;
108 }
109
110 // @codingStandardsIgnoreLine
111 unset( $_POST[ $key ] );
112
113 // @codingStandardsIgnoreLine
114 $_POST[ '_podsfix_' . $key ] = $value;
115 }
116 }
117 }//end if
118 }
119
120 /**
121 * Attach requirements to admin header
122 *
123 * @since 2.0.0
124 */
125 public function admin_head() {
126 wp_register_script( 'pods-upgrade', PODS_URL . 'ui/js/jquery.pods.upgrade.js', array(), PODS_VERSION );
127
128 $page = sanitize_text_field( pods_v( 'page' ) );
129
130 if ( empty( $page ) ) {
131 return;
132 }
133
134 if ( 'pods' !== $page && 0 !== strpos( $page, 'pods-' ) ) {
135 return;
136 }
137 ?>
138 <script>
139 if ( 'undefined' === typeof PODS_URL ) {
140 const PODS_URL = '<?php echo esc_js( PODS_URL ); ?>';
141 }
142 </script>
143 <?php
144
145 // To be phased out.
146 wp_enqueue_script( 'jquery' );
147 wp_enqueue_script( 'jquery-ui-core' );
148 wp_enqueue_script( 'jquery-ui-sortable' );
149
150 // To be replaced.
151 wp_enqueue_script( 'jquery-qtip2' );
152 wp_enqueue_script( 'pods-qtip-init' );
153
154 // To be phased out.
155 wp_enqueue_script( 'pods' );
156
157 $action = sanitize_text_field( pods_v( 'action', 'get', 'manage' ) );
158
159 if (
160 0 === strpos( $page, 'pods-manage-' )
161 || 0 === strpos( $page, 'pods-add-new-' )
162 || 0 === strpos( $page, 'pods-settings-' )
163 ) {
164 wp_enqueue_script( 'post' );
165 } elseif (
166 in_array( $page, [ 'pods', 'pods-add-new', 'pods-packages', 'pods-wizard', 'pods-upgrade' ], true )
167 || in_array( $action, [ 'add', 'manage' ], true )
168 ) {
169 wp_enqueue_style( 'pods-wizard' );
170
171 if ( 'pods-upgrade' === $page ) {
172 wp_enqueue_script( 'pods-upgrade' );
173 }
174 }
175
176 wp_enqueue_script( 'pods-dfv' );
177 wp_enqueue_style( 'pods-styles' );
178 }
179
180 /**
181 * Build the admin menus
182 *
183 * @since 2.0.0
184 */
185 public function admin_menu() {
186
187 $advanced_content_types = PodsMeta::$advanced_content_types;
188 $taxonomies = PodsMeta::$taxonomies;
189 $settings = PodsMeta::$settings;
190
191 if ( ! PodsInit::$upgrade_needed || ( pods_is_admin() && 1 === (int) pods_v( 'pods_upgrade_bypass' ) ) ) {
192 $submenu_items = array();
193
194 if ( ! empty( $advanced_content_types ) ) {
195 $submenu = array();
196
197 $pods_pages = 0;
198
199 foreach ( (array) $advanced_content_types as $pod ) {
200 if ( ! $pod instanceof Pod ) {
201 continue;
202 } elseif ( ! pods_is_admin(
203 array(
204 'pods',
205 'pods_content',
206 'pods_add_' . $pod['name'],
207 'pods_edit_' . $pod['name'],
208 'pods_delete_' . $pod['name'],
209 )
210 ) ) {
211 continue;
212 }
213
214 $pod_name = $pod['name'];
215
216 $pod = apply_filters( "pods_advanced_content_type_pod_data_{$pod_name}", $pod, $pod['name'] );
217 $pod = apply_filters( 'pods_advanced_content_type_pod_data', $pod, $pod['name'] );
218
219 if ( 1 === (int) pods_v( 'show_in_menu', $pod['options'], 0 ) ) {
220 $page_title = pods_v( 'label', $pod, ucwords( str_replace( '_', ' ', $pod['name'] ) ), true );
221 $page_title = apply_filters( 'pods_admin_menu_page_title', $page_title, $pod );
222
223 $menu_label = pods_v( 'menu_name', $pod['options'], $page_title, true );
224 $menu_label = strip_tags( $menu_label );
225 $menu_label = apply_filters( 'pods_admin_menu_label', $menu_label, $pod );
226
227 $singular_label = pods_v( 'label_singular', $pod['options'], pods_v( 'label', $pod, ucwords( str_replace( '_', ' ', $pod['name'] ) ), true ), true );
228 $plural_label = pods_v( 'label', $pod, ucwords( str_replace( '_', ' ', $pod['name'] ) ), true );
229
230 $menu_location = pods_v( 'menu_location', $pod['options'], 'objects' );
231 $menu_location_custom = pods_v( 'menu_location_custom', $pod['options'], '' );
232
233 $menu_position = pods_v( 'menu_position', $pod['options'], '', true );
234 $menu_icon = pods_evaluate_tags( pods_v( 'menu_icon', $pod['options'], '', true ), true );
235
236 if ( empty( $menu_position ) ) {
237 $menu_position = null;
238 }
239
240 $parent_page = null;
241
242 if ( pods_is_admin(
243 array(
244 'pods',
245 'pods_content',
246 'pods_edit_' . $pod['name'],
247 'pods_delete_' . $pod['name'],
248 )
249 ) ) {
250 if ( ! empty( $menu_location_custom ) ) {
251 if ( ! isset( $submenu_items[ $menu_location_custom ] ) ) {
252 $submenu_items[ $menu_location_custom ] = array();
253 }
254
255 $submenu_items[ $menu_location_custom ][] = array(
256 $menu_location_custom,
257 $page_title,
258 $menu_label,
259 'read',
260 'pods-manage-' . $pod['name'],
261 array( $this, 'admin_content' ),
262 );
263
264 continue;
265 } else {
266 $pods_pages ++;
267
268 $page = 'pods-manage-' . $pod['name'];
269 $parent_page = $page;
270
271 if ( empty( $menu_position ) ) {
272 $menu_position = null;
273 }
274 add_menu_page( $page_title, $menu_label, 'read', $parent_page, '', $menu_icon, $menu_position );
275
276 $all_title = $plural_label;
277 $all_label = pods_v( 'label_all_items', $pod['options'], __( 'All', 'pods' ) . ' ' . $plural_label );
278
279 if ( pods_v( 'page' ) === $page ) {
280 if ( 'edit' === pods_v( 'action', 'get', 'manage' ) ) {
281 $all_title = pods_v( 'label_edit_item', $pod['options'], __( 'Edit', 'pods' ) . ' ' . $singular_label );
282 } elseif ( 'add' === pods_v( 'action', 'get', 'manage' ) ) {
283 $all_title = pods_v( 'label_add_new_item', $pod['options'], sprintf( __( 'Add New %s', 'pods' ), $singular_label ) );
284 }
285 }
286
287 add_submenu_page(
288 $parent_page, $all_title, $all_label, 'read', $page, array(
289 $this,
290 'admin_content',
291 )
292 );
293 }//end if
294 }//end if
295
296 if ( pods_is_admin( array( 'pods', 'pods_content', 'pods_add_' . $pod['name'] ) ) ) {
297 $page = 'pods-add-new-' . $pod['name'];
298
299 if ( null === $parent_page ) {
300 $pods_pages ++;
301
302 $parent_page = $page;
303
304 if ( empty( $menu_position ) ) {
305 $menu_position = null;
306 }
307 add_menu_page( $page_title, $menu_label, 'read', $parent_page, '', $menu_icon, $menu_position );
308 }
309
310 $add_title = pods_v( 'label_add_new_item', $pod['options'], sprintf( __( 'Add New %s', 'pods' ), $singular_label ) );
311 $add_label = pods_v( 'label_add_new', $pod['options'], sprintf( __( 'Add New %s', 'pods' ), $singular_label ) );
312
313 add_submenu_page(
314 $parent_page, $add_title, $add_label, 'read', $page, array(
315 $this,
316 'admin_content',
317 )
318 );
319 }//end if
320 } elseif ( 1 === (int) pods_v( 'use_submenu_fallback', $pod['options'], 1 ) ) {
321 $submenu[] = $pod;
322 }//end if
323 }//end foreach
324
325 $submenu = apply_filters( 'pods_admin_menu_secondary_content', $submenu );
326
327 if ( ! empty( $submenu ) && ( ! defined( 'PODS_DISABLE_CONTENT_MENU' ) || ! PODS_DISABLE_CONTENT_MENU ) ) {
328 $parent_page = null;
329
330 foreach ( $submenu as $item ) {
331 $singular_label = pods_v( 'label_singular', $item['options'], pods_v( 'label', $item, ucwords( str_replace( '_', ' ', $item['name'] ) ), true ), true );
332 $plural_label = pods_v( 'label', $item, ucwords( str_replace( '_', ' ', $item['name'] ) ), true );
333
334 if ( pods_is_admin(
335 array(
336 'pods',
337 'pods_content',
338 'pods_edit_' . $item['name'],
339 'pods_delete_' . $item['name'],
340 )
341 ) ) {
342 $page = 'pods-manage-' . $item['name'];
343
344 if ( null === $parent_page ) {
345 $parent_page = $page;
346
347 add_menu_page( 'Pods', 'Pods', 'read', $parent_page, null, pods_svg_icon( 'pods' ), '58.5' );
348 }
349
350 $all_title = $plural_label;
351 $all_label = __( 'Manage', 'pods' ) . ' ' . $plural_label;
352
353 if ( pods_v( 'page' ) === $page ) {
354 if ( 'edit' === pods_v( 'action', 'get', 'manage' ) ) {
355 $all_title = __( 'Edit', 'pods' ) . ' ' . $singular_label;
356 } elseif ( 'add' === pods_v( 'action', 'get', 'manage' ) ) {
357 $all_title = __( 'Add New', 'pods' ) . ' ' . $singular_label;
358 }
359 }
360
361 add_submenu_page(
362 $parent_page, $all_title, $all_label, 'read', $page, array(
363 $this,
364 'admin_content',
365 )
366 );
367 } elseif ( current_user_can( 'pods_add_' . $item['name'] ) ) {
368 $page = 'pods-add-new-' . $item['name'];
369
370 if ( null === $parent_page ) {
371 $parent_page = $page;
372
373 add_menu_page( 'Pods', 'Pods', 'read', $parent_page, null, pods_svg_icon( 'pods' ), '58.5' );
374 }
375
376 $add_title = __( 'Add New', 'pods' ) . ' ' . $singular_label;
377 $add_label = __( 'Manage', 'pods' ) . ' ' . $plural_label;
378
379 add_submenu_page(
380 $parent_page, $add_title, $add_label, 'read', $page, array(
381 $this,
382 'admin_content',
383 )
384 );
385 }//end if
386 }//end foreach
387 }//end if
388 }//end if
389
390 if ( ! empty( $taxonomies ) ) {
391 foreach ( (array) $taxonomies as $pod ) {
392 // Default taxonomy capability
393 $capability = 'manage_categories';
394
395 if ( ! empty( $pod['options']['capability_type'] ) ) {
396 if ( 'custom' === $pod['options']['capability_type'] && ! empty( $pod['options']['capability_type_custom'] ) ) {
397 $capability = 'manage_' . (string) $pod['options']['capability_type_custom'] . '_terms';
398 }
399 }
400
401 // Check capabilities.
402 if ( ! pods_is_admin(
403 array(
404 'pods',
405 'pods_content',
406 'pods_edit_' . $pod['name'],
407 $capability,
408 )
409 ) ) {
410 continue;
411 }
412
413 // Check UI settings
414 if ( 1 !== (int) pods_v( 'show_ui', $pod['options'], 0 ) || 1 !== (int) pods_v( 'show_in_menu', $pod['options'], 0 ) ) {
415 continue;
416 }
417
418 $menu_location = pods_v( 'menu_location', $pod['options'], 'default' );
419
420 if ( 'default' === $menu_location ) {
421 continue;
422 }
423
424 $page_title = pods_v( 'label', $pod, ucwords( str_replace( '_', ' ', $pod['name'] ) ), true );
425 $page_title = apply_filters( 'pods_admin_menu_page_title', $page_title, $pod );
426
427 $menu_label = pods_v( 'menu_name', $pod['options'], $page_title, true );
428 $menu_label = strip_tags( $menu_label );
429 $menu_label = apply_filters( 'pods_admin_menu_label', $menu_label, $pod );
430
431 $menu_icon = pods_evaluate_tags( pods_v( 'menu_icon', $pod['options'], '', true ), true );
432 $menu_slug = 'edit-tags.php?taxonomy=' . $pod['name'];
433 $menu_location_custom = pods_v( 'menu_location_custom', $pod['options'], '' );
434
435 $menu_position = pods_v( 'menu_position', $pod['options'], '', true );
436 if ( empty( $menu_position ) ) {
437 $menu_position = null;
438 }
439
440 $taxonomy_data = get_taxonomy( $pod['name'] );
441
442 foreach ( (array) $taxonomy_data->object_type as $post_type ) {
443 if ( 'post' === $post_type ) {
444 remove_submenu_page( 'edit.php', $menu_slug );
445 } elseif ( 'attachment' === $post_type ) {
446 remove_submenu_page( 'upload.php', $menu_slug . '&amp;post_type=' . $post_type );
447 } else {
448 remove_submenu_page( 'edit.php?post_type=' . $post_type, $menu_slug . '&amp;post_type=' . $post_type );
449 }
450 }
451
452 if ( 'settings' === $menu_location ) {
453 add_options_page( $page_title, $menu_label, 'read', $menu_slug );
454 } elseif ( 'appearances' === $menu_location ) {
455 add_theme_page( $page_title, $menu_label, 'read', $menu_slug );
456 } elseif ( 'objects' === $menu_location || 'top' === $menu_location ) {
457 add_menu_page( $page_title, $menu_label, 'read', $menu_slug, '', $menu_icon, $menu_position );
458 } elseif ( 'submenu' === $menu_location && ! empty( $menu_location_custom ) ) {
459 if ( ! isset( $submenu_items[ $menu_location_custom ] ) ) {
460 $submenu_items[ $menu_location_custom ] = array();
461 }
462
463 $submenu_items[ $menu_location_custom ][] = array(
464 $menu_location_custom,
465 $page_title,
466 $menu_label,
467 'read',
468 $menu_slug,
469 '',
470 );
471 }//end if
472 }//end foreach
473 }//end if
474
475 if ( ! empty( $settings ) ) {
476 foreach ( (array) $settings as $pod ) {
477 if ( ! pods_is_admin( array( 'pods', 'pods_content', 'pods_edit_' . $pod['name'] ) ) ) {
478 continue;
479 }
480
481 $page_title = pods_v( 'label', $pod, ucwords( str_replace( '_', ' ', $pod['name'] ) ), true );
482 $page_title = apply_filters( 'pods_admin_menu_page_title', $page_title, $pod );
483
484 $menu_label = pods_v( 'menu_name', $pod['options'], $page_title, true );
485 $menu_label = strip_tags( $menu_label );
486 $menu_label = apply_filters( 'pods_admin_menu_label', $menu_label, $pod );
487
488 $menu_icon = pods_evaluate_tags( pods_v( 'menu_icon', $pod['options'], '', true ), true );
489
490 $menu_position = pods_v( 'menu_position', $pod['options'], '', true );
491 if ( empty( $menu_position ) ) {
492 $menu_position = null;
493 }
494
495 $menu_slug = 'pods-settings-' . $pod['name'];
496 $menu_location = pods_v( 'menu_location', $pod['options'], 'settings' );
497 $menu_location_custom = pods_v( 'menu_location_custom', $pod['options'], '' );
498 $menu_callback = array( $this, 'admin_content_settings' );
499
500 if ( 'settings' === $menu_location ) {
501 add_options_page( $page_title, $menu_label, 'read', $menu_slug, $menu_callback, $menu_position );
502 } elseif ( 'appearances' === $menu_location ) {
503 add_theme_page( $page_title, $menu_label, 'read', $menu_slug, $menu_callback, $menu_position );
504 } elseif ( 'objects' === $menu_location || 'top' === $menu_location ) {
505 add_menu_page( $page_title, $menu_label, 'read', $menu_slug, $menu_callback, $menu_icon, $menu_position );
506 } elseif ( 'submenu' === $menu_location && ! empty( $menu_location_custom ) ) {
507 if ( ! isset( $submenu_items[ $menu_location_custom ] ) ) {
508 $submenu_items[ $menu_location_custom ] = array();
509 }
510
511 $submenu_items[ $menu_location_custom ][] = array(
512 $menu_location_custom,
513 $page_title,
514 $menu_label,
515 'read',
516 $menu_slug,
517 $menu_callback,
518 $menu_position,
519 );
520 }//end if
521 }//end foreach
522 }//end if
523
524 foreach ( $submenu_items as $items ) {
525 foreach ( $items as $item ) {
526 call_user_func_array( 'add_submenu_page', $item );
527 }
528 }
529
530 $edit_pods_title = null;
531
532 if ( 'pods' === pods_v( 'page' ) && 'edit' === pods_v( 'action' ) ) {
533 $edit_pods_title = __( 'Edit Pod', 'pods' );
534 }
535
536 $admin_menus = array(
537 'pods' => array(
538 'label' => __( 'Edit Pods', 'pods' ),
539 'title' => $edit_pods_title,
540 'function' => array( $this, 'admin_setup' ),
541 'access' => 'pods',
542 ),
543 'pods-add-new' => array(
544 'label' => __( 'Add New', 'pods' ),
545 'title' => __( 'Add New Pod', 'pods' ),
546 'function' => array( $this, 'admin_setup' ),
547 'access' => 'pods',
548 ),
549 'pods-components' => array(
550 'label' => __( 'Components', 'pods' ),
551 'title' => __( 'Pods Components', 'pods' ),
552 'function' => array( $this, 'admin_components' ),
553 'access' => 'pods_components',
554 ),
555 'pods-access-rights-review' => array(
556 'label' => __( 'Review Access Rights', 'pods' ),
557 'title' => __( 'Pods Review Access Rights', 'pods' ),
558 'function' => array( $this, 'admin_access_rights_review' ),
559 'access' => 'pods',
560 ),
561 'pods-settings' => array(
562 'label' => __( 'Settings', 'pods' ),
563 'title' => __( 'Pods Settings', 'pods' ),
564 'function' => array( $this, 'admin_settings' ),
565 'access' => 'pods_settings',
566 ),
567 'pods-help' => array(
568 'label' => __( 'Help', 'pods' ),
569 'title' => __( 'Pods Help', 'pods' ),
570 'function' => array( $this, 'admin_help' ),
571 ),
572 );
573
574 add_filter( 'parent_file', array( $this, 'parent_file' ) );
575 } else {
576 $admin_menus = array(
577 'pods-upgrade' => array(
578 'label' => __( 'Upgrade', 'pods' ),
579 'function' => array( $this, 'admin_upgrade' ),
580 'access' => 'manage_options',
581 ),
582 'pods-settings' => array(
583 'label' => __( 'Settings', 'pods' ),
584 'title' => __( 'Pods Settings', 'pods' ),
585 'function' => array( $this, 'admin_settings' ),
586 'access' => 'pods_settings',
587 ),
588 'pods-help' => array(
589 'label' => __( 'Help', 'pods' ),
590 'title' => __( 'Pods Help', 'pods' ),
591 'function' => array( $this, 'admin_help' ),
592 ),
593 );
594
595 add_action( 'admin_notices', array( $this, 'upgrade_notice' ) );
596 }//end if
597
598 /**
599 * Add or change Pods Admin menu items
600 *
601 * @param array $admin_menus The submenu items in Pods Admin menu.
602 *
603 * @since unknown
604 */
605 $admin_menus = apply_filters( 'pods_admin_menu', $admin_menus );
606
607 $parent = false;
608
609 // PODS_LIGHT disables all Pods components so remove the components menu
610 if ( pods_light() ) {
611 unset( $admin_menus['pods-components'] );
612 }
613
614 if ( ! empty( $admin_menus ) && ( ! defined( 'PODS_DISABLE_ADMIN_MENU' ) || ! PODS_DISABLE_ADMIN_MENU ) ) {
615 foreach ( $admin_menus as $page => $menu_item ) {
616 if ( ! pods_is_admin( pods_v( 'access', $menu_item ) ) ) {
617 continue;
618 }
619
620 // Don't just show the help page
621 if ( false === $parent && 'pods-help' === $page ) {
622 continue;
623 }
624
625 if ( empty( $menu_item['label'] ) ) {
626 $menu_item['label'] = $page;
627 }
628
629 if ( empty( $menu_item['title'] ) ) {
630 $menu_item['title'] = $menu_item['label'];
631 }
632
633 if ( false === $parent ) {
634 $parent = $page;
635
636 $menu = __( 'Pods Admin', 'pods' );
637
638 if ( 'pods-upgrade' === $parent ) {
639 $menu = __( 'Pods Upgrade', 'pods' );
640 }
641
642 add_menu_page( $menu, $menu, 'read', $parent, null, pods_svg_icon( 'pods' ) );
643 }
644
645 add_submenu_page( $parent, $menu_item['title'], $menu_item['label'], 'read', $page, $menu_item['function'] );
646
647 if ( 'pods-components' === $page && is_object( PodsInit::$components ) ) {
648 PodsInit::$components->menu( $parent );
649 }
650 }//end foreach
651 }//end if
652 }
653
654 /**
655 * Set the correct parent_file to highlight the correct top level menu
656 *
657 * @param string $parent_file The parent file.
658 *
659 * @return mixed|string
660 *
661 * @since unknown
662 */
663 public function parent_file( $parent_file ) {
664 global $current_screen, $submenu_file;
665
666 if ( isset( $current_screen ) && ! empty( $current_screen->taxonomy ) ) {
667 $taxonomies = PodsMeta::$taxonomies;
668 if ( ! empty( $taxonomies ) ) {
669 foreach ( (array) $taxonomies as $pod ) {
670 if ( $current_screen->taxonomy !== $pod['name'] ) {
671 continue;
672 }
673
674 $menu_slug = 'edit-tags.php?taxonomy=' . $pod['name'];
675 $menu_location = pods_v( 'menu_location', $pod['options'], 'default' );
676 $menu_location_custom = pods_v( 'menu_location_custom', $pod['options'], '' );
677
678 if ( 'settings' === $menu_location ) {
679 $parent_file = 'options-general.php';
680 } elseif ( 'appearances' === $menu_location ) {
681 $parent_file = 'themes.php';
682 } elseif ( 'objects' === $menu_location ) {
683 $parent_file = $menu_slug;
684 } elseif ( 'top' === $menu_location ) {
685 $parent_file = $menu_slug;
686 } elseif ( 'submenu' === $menu_location && ! empty( $menu_location_custom ) ) {
687 $parent_file = $menu_location_custom;
688 }
689
690 break;
691 }//end foreach
692 }//end if
693 }//end if
694
695 if ( isset( $current_screen ) && ! empty( $current_screen->post_type ) && is_object( PodsInit::$components ) ) {
696 $components_menu_items = PodsInit::$components->components_menu_items;
697
698 foreach ( $components_menu_items as $menu_item ) {
699 if ( empty( $menu_item['menu_page'] ) || $parent_file !== $menu_item['menu_page'] ) {
700 continue;
701 }
702
703 $parent_file = 'pods';
704
705 // @codingStandardsIgnoreLine
706 $submenu_file = $menu_item['menu_page'];
707
708 break;
709 }
710 }
711
712 return $parent_file;
713 }
714
715 /**
716 * Show upgrade notice.
717 */
718 public function upgrade_notice() {
719
720 echo '<div class="error fade"><p>';
721 // @codingStandardsIgnoreLine
722 echo sprintf( __( '<strong>NOTICE:</strong> Pods %1$s requires your action to complete the upgrade. Please run the <a href="%2$s">Upgrade Wizard</a>.', 'pods' ), esc_html( PODS_VERSION ), esc_url( admin_url( 'admin.php?page=pods-upgrade' ) ) );
723 echo '</p></div>';
724 }
725
726 /**
727 * Create PodsUI content for the administration pages
728 */
729 public function admin_content() {
730
731 // @codingStandardsIgnoreLine
732 $pod_name = str_replace( array( 'pods-manage-', 'pods-add-new-' ), '', $_GET['page'] );
733
734 $pod = pods_get_instance( $pod_name, pods_v( 'id', 'get', null, true ) );
735
736 if ( ! $pod->pod_data->has_fields() ) {
737 pods_message( __( 'This Pod does not have any fields defined.', 'pods' ), 'error' );
738 return;
739 }
740
741 // @codingStandardsIgnoreLine
742 if ( false !== strpos( $_GET['page'], 'pods-add-new-' ) ) {
743 // @codingStandardsIgnoreLine
744 $_GET['action'] = pods_v( 'action', 'get', 'add' );
745 }
746
747 $pod->ui();
748 }
749
750 /**
751 * Create PodsUI content for the settings administration pages
752 */
753 public function admin_content_settings() {
754
755 // @codingStandardsIgnoreLine
756 $pod_name = str_replace( 'pods-settings-', '', $_GET['page'] );
757
758 $pod = pods_get_instance( $pod_name );
759
760 if ( 'custom' !== pods_v( 'ui_style', $pod->pod_data['options'], 'settings', true ) ) {
761 $actions_disabled = array(
762 'manage' => 'manage',
763 'add' => 'add',
764 'delete' => 'delete',
765 'duplicate' => 'duplicate',
766 'view' => 'view',
767 'export' => 'export',
768 );
769
770 // @codingStandardsIgnoreLine
771 $_GET['action'] = 'edit';
772
773 $page_title = pods_v( 'label', $pod->pod_data, ucwords( str_replace( '_', ' ', $pod->pod_data['name'] ) ), true );
774 $page_title = apply_filters( 'pods_admin_menu_page_title', $page_title, $pod->pod_data );
775
776 $pod_pod_name = $pod->pod;
777
778 $ui = array(
779 'id' => $pod_pod_name,
780 'pod' => $pod,
781 'fields' => array(
782 'edit' => $pod->pod_data->get_fields(),
783 ),
784 'header' => array(
785 'edit' => $page_title,
786 ),
787 'label' => array(
788 'edit' => __( 'Save Changes', 'pods' ),
789 ),
790 'style' => pods_v( 'ui_style', $pod->pod_data['options'], 'settings', true ),
791 'icon' => pods_evaluate_tags( pods_v( 'menu_icon', $pod->pod_data['options'] ), true ),
792 'actions_disabled' => $actions_disabled,
793 );
794
795 $ui = apply_filters( "pods_admin_ui_{$pod_pod_name}", apply_filters( 'pods_admin_ui', $ui, $pod->pod, $pod ), $pod->pod, $pod );
796
797 // Force disabled actions, do not pass go, do not collect $two_hundred
798 $ui['actions_disabled'] = $actions_disabled;
799
800 pods_ui( $ui );
801 } else {
802 $pod_pod_name = $pod->pod;
803 do_action( 'pods_admin_ui_custom', $pod );
804 do_action( "pods_admin_ui_custom_{$pod_pod_name}", $pod );
805 }//end if
806 }
807
808 /**
809 * Add media button for Pods shortcode
810 *
811 * @param string $context Media button context.
812 */
813 public function media_button( $context = null ) {
814 if ( ! empty( $_GET['action'] ) && 'elementor' === $_GET['action'] ) {
815 return;
816 }
817
818 // If shortcodes are disabled don't show the button
819 if ( defined( 'PODS_DISABLE_SHORTCODE' ) && PODS_DISABLE_SHORTCODE ) {
820 return;
821 }
822
823 /**
824 * Filter to remove Pods shortcode button from the post editor.
825 *
826 * @param bool $show_button Set to false to block the shortcode button from appearing.
827 * @param string $context Media button context.
828 *
829 * @since 2.3.19
830 */
831 if ( ! apply_filters( 'pods_admin_media_button', true, $context ) ) {
832 return;
833 }
834
835 $current_page = basename( $_SERVER['PHP_SELF'] );
836 $current_page = explode( '?', $current_page );
837 $current_page = explode( '#', $current_page[0] );
838 $current_page = $current_page[0];
839
840 // Only show the button on post type pages
841 if ( ! in_array(
842 $current_page, array(
843 'post-new.php',
844 'post.php',
845 ), true
846 ) ) {
847 return;
848 }
849
850 add_action( 'admin_footer', array( $this, 'mce_popup' ) );
851
852 echo '<a href="#TB_inline?width=640&inlineId=pods_shortcode_form" class="thickbox button" id="add_pod_button" title="Pods Shortcode"><img style="padding: 0px 6px 0px 0px; margin: -3px 0px 0px;" src="' . esc_url( PODS_URL . 'ui/images/icon16.png' ) . '" alt="' . esc_attr__( 'Pods Shortcode', 'pods' ) . '" />' . esc_html__( 'Pods Shortcode', 'pods' ) . '</a>';
853 }
854
855 /**
856 * Enqueue assets for Media Library Popup
857 */
858 public function register_media_assets() {
859
860 if ( 'pods_media_attachment' === pods_v( 'inlineId' ) ) {
861 wp_enqueue_style( 'pods-styles' );
862 }
863 }
864
865 /**
866 * Output Pods shortcode popup window
867 */
868 public function mce_popup() {
869
870 pods_view( PODS_DIR . 'ui/admin/shortcode.php', compact( array_keys( get_defined_vars() ) ) );
871 }
872
873 /**
874 * Handle main Pods Setup area for managing Pods and Fields
875 */
876 public function admin_setup() {
877 $api = pods_api();
878
879 $pods = $api->load_pods( array( 'fields' => false ) );
880
881 $id = pods_v( 'id' );
882 $action = pods_v( 'action' );
883 $view = pods_v( 'view', 'get', 'all', true );
884
885 // @codingStandardsIgnoreLine
886 if ( empty( $pods ) && ! isset( $_GET['action'] ) ) {
887 // @codingStandardsIgnoreLine
888 $_GET['action'] = 'add';
889 }
890
891 if ( 'pods' === $_GET['page'] && empty( $pods ) ) {
892 pods_message( __( 'You do not have any Pods set up yet. You can set up your very first Pod below.', 'pods ' ) );
893 }
894
895 // @codingStandardsIgnoreLine
896 if ( 'pods-add-new' === $_GET['page'] || empty( $pods ) ) {
897 // @codingStandardsIgnoreLine
898 if ( isset( $_GET['action'] ) && 'add' !== $_GET['action'] ) {
899 pods_redirect(
900 pods_query_arg(
901 array(
902 'page' => 'pods',
903 // @codingStandardsIgnoreLine
904 'action' => $_GET['action'],
905 )
906 )
907 );
908 } else {
909 // @codingStandardsIgnoreLine
910 $_GET['action'] = 'add';
911 }
912 // @codingStandardsIgnoreLine
913 } elseif ( isset( $_GET['action'] ) && 'add' === $_GET['action'] ) {
914 pods_redirect(
915 pods_query_arg(
916 array(
917 'page' => 'pods-add-new',
918 'action' => '',
919 'id' => '',
920 'do' => '',
921 '_wpnonce' => '',
922 )
923 )
924 );
925 }//end if
926
927 $pod_types = $api->get_pod_types();
928 $storage_types = $api->get_storage_types();
929
930 $row = false;
931
932 $pod_types_found = [];
933 $sources_found = [];
934 $source_types = [];
935
936 $include_row_counts = filter_var( pods_v( 'pods_include_row_counts' ), FILTER_VALIDATE_BOOLEAN );
937 $include_row_counts_refresh = filter_var( pods_v( 'pods_include_row_counts_refresh' ), FILTER_VALIDATE_BOOLEAN );
938
939 $fields = [
940 'label' => [
941 'label' => __( 'Label', 'pods' ),
942 ],
943 'name' => [
944 'label' => __( 'Name', 'pods' ),
945 ],
946 'type' => [
947 'label' => __( 'Type', 'pods' ),
948 ],
949 'source' => [
950 'label' => __( 'Source', 'pods' ),
951 'width' => '10%',
952 'type' => 'raw',
953 ],
954 'storage' => [
955 'label' => __( 'Storage Type', 'pods' ),
956 'width' => '10%',
957 ],
958 'group_count' => [
959 'label' => __( 'Groups', 'pods' ),
960 'width' => '8%',
961 ],
962 'field_count' => [
963 'label' => __( 'Fields', 'pods' ),
964 'width' => '8%',
965 ],
966 ];
967
968 if ( $include_row_counts ) {
969 $fields['row_count'] = [
970 'label' => __( 'Data Rows', 'pods' ),
971 'width' => '8%',
972 ];
973
974 $fields['row_meta_count'] = [
975 'label' => __( 'Meta Rows', 'pods' ),
976 'width' => '8%',
977 ];
978
979 $fields['podsrel_count'] = [
980 // translators: "PodsRel" references the name of the Pods relationships table in the database.
981 'label' => __( 'PodsRel Rows', 'pods' ),
982 'width' => '10%',
983 ];
984 }
985
986 $total_groups = 0;
987 $total_fields = 0;
988 $total_rows = 0;
989 $total_row_meta = 0;
990 $total_podsrel_rows = 0;
991
992 /**
993 * Filters whether to extend internal Pods.
994 *
995 * @since 2.8.0
996 *
997 * @param bool $extend_internal Whether to extend internal Pods.
998 */
999 $extend_internal = apply_filters( 'pods_admin_setup_extend_pods_internal', false );
1000
1001 $pod_list = array();
1002
1003 $is_tableless = pods_tableless();
1004
1005 $has_source = false;
1006 $has_storage_type = false;
1007
1008 foreach ( $pods as $k => $pod ) {
1009 $pod_type = $pod['type'];
1010 $pod_type_label = null;
1011 $pod_storage = $pod['storage'];
1012
1013 if ( empty( $pod_type ) || ! is_string( $pod_type ) ) {
1014 $pod_type = 'post_type';
1015 }
1016
1017 if ( empty( $pod_storage ) || ! is_string( $pod_storage ) ) {
1018 $pod_storage = 'meta';
1019 }
1020
1021 $show_meta_count = 'meta' === $pod_storage || in_array( $pod['type'], [ 'post_type', 'taxonomy', 'user', 'comment' ], true );
1022
1023 if ( ! empty( $pod['internal'] ) ) {
1024 // Don't show internal if we aren't extending them.
1025 if ( ! $extend_internal ) {
1026 continue;
1027 }
1028
1029 $pod_type = 'internal';
1030 $pod_storage = 'meta';
1031 }
1032
1033 if ( 'settings' === $pod_type ) {
1034 $pod_storage = 'option';
1035 }
1036
1037 if ( 'meta' !== $pod_storage ) {
1038 $has_storage_type = true;
1039 }
1040
1041 if ( isset( $pod_types[ $pod_type ] ) ) {
1042 $pod_type_label = $pod_types[ $pod_type ];
1043 }
1044
1045 $pod_real_type = $pod_type;
1046
1047 $storage_type_label = ucwords( $pod_storage );
1048
1049 if ( isset( $storage_types[ $pod_storage ] ) ) {
1050 $storage_type_label = $storage_types[ $pod_storage ];
1051 }
1052
1053 if ( null !== $pod_type_label ) {
1054 if ( ! $pod->is_extended() && in_array( $pod_type, array(
1055 'post_type',
1056 'taxonomy',
1057 ), true ) ) {
1058 if ( 'post_type' === $pod_type ) {
1059 $pod_type = 'cpt';
1060 } else {
1061 $pod_type = 'ct';
1062 }
1063
1064 if ( isset( $pod_types[ $pod_type ] ) ) {
1065 $pod_type_label = $pod_types[ $pod_type ];
1066 }
1067 }
1068
1069 if ( ! isset( $pod_types_found[ $pod_type ] ) ) {
1070 $pod_types_found[ $pod_type ] = 1;
1071 } else {
1072 $pod_types_found[ $pod_type ] ++;
1073 }
1074
1075 if ( 'all' !== $view && $view !== $pod_type ) {
1076 continue;
1077 }
1078
1079 $pod_real_type = $pod_type;
1080 $pod_type = $pod_type_label;
1081 } elseif ( 'all' !== $view ) {
1082 continue;
1083 }//end if
1084
1085 $group_count = 0;
1086 $field_count = 0;
1087
1088 if ( ! pods_is_types_only( false, $pod->get_name() ) ) {
1089 $group_count = $pod->count_groups();
1090 $field_count = $pod->count_fields();
1091 }
1092
1093 if ( $include_row_counts ) {
1094 $count_transient_prefix = 'pods_admin_' . $pod['type'] . '_' . $pod['name'] . '_';
1095
1096 $row_counts = [
1097 'row_count' => false,
1098 'row_meta_count' => false,
1099 'podsrel_count' => false,
1100 ];
1101
1102 if ( ! $include_row_counts_refresh ) {
1103 $row_counts['row_count'] = pods_transient_get( $count_transient_prefix . 'row_count' );
1104 $row_counts['row_meta_count'] = pods_transient_get( $count_transient_prefix . 'row_meta_count' );
1105 $row_counts['podsrel_count'] = pods_transient_get( $count_transient_prefix . 'podsrel_count' );
1106 }
1107
1108 if ( ! is_numeric( $row_counts['row_count'] ) ) {
1109 $row_counts['row_count'] = $pod->count_rows();
1110
1111 pods_transient_set( $count_transient_prefix . 'row_count', $row_counts['row_count'], HOUR_IN_SECONDS * 3 );
1112 }
1113
1114 if ( $show_meta_count && ! is_numeric( $row_counts['row_meta_count'] ) ) {
1115 $row_counts['row_meta_count'] = $pod->count_row_meta();
1116
1117 pods_transient_set( $count_transient_prefix . 'row_meta_count', $row_counts['row_meta_count'], HOUR_IN_SECONDS * 3 );
1118 }
1119
1120 if ( ! $is_tableless && ! is_numeric( $row_counts['podsrel_count'] ) ) {
1121 $row_counts['podsrel_count'] = $pod->count_podsrel_rows();
1122
1123 pods_transient_set( $count_transient_prefix . 'podsrel_count', $row_counts['podsrel_count'], HOUR_IN_SECONDS * 3 );
1124 }
1125 }
1126
1127 $object_storage_type = $pod->get_object_storage_type();
1128 $source = $pod->get_object_storage_type_label();
1129
1130 if ( $source ) {
1131 $source_types[ $object_storage_type ] = $source;
1132
1133 if ( ! isset( $sources_found[ $object_storage_type ] ) ) {
1134 $sources_found[ $object_storage_type ] = 1;
1135 } else {
1136 $sources_found[ $object_storage_type ] ++;
1137 }
1138 }
1139
1140 $source = esc_html( $source );
1141
1142 if ( 'post_type' !== $object_storage_type ) {
1143 $has_source = true;
1144
1145 if ( 'file' === $object_storage_type ) {
1146 $file_source = $pod->get_arg( '_pods_file_source' );
1147
1148 if ( $file_source ) {
1149 if ( 0 === strpos( $file_source, ABSPATH ) ) {
1150 $file_source = str_replace( ABSPATH, '', $file_source );
1151 }
1152
1153 ob_start();
1154
1155 pods_help(
1156 sprintf(
1157 '<strong>%s:</strong> %s',
1158 esc_html__( 'File source', 'pods' ),
1159 esc_html( $file_source )
1160 ),
1161 null,
1162 '.pods-admin-container'
1163 );
1164
1165 $source .= ' ' . ob_get_clean();
1166 }
1167 } elseif ( 'collection' === $object_storage_type ) {
1168 $code_source = $pod->get_arg( '_pods_code_source' );
1169
1170 if ( $code_source ) {
1171 if ( 0 === strpos( $code_source, ABSPATH ) ) {
1172 $code_source = str_replace( ABSPATH, '', $code_source );
1173 }
1174
1175 ob_start();
1176
1177 pods_help(
1178 sprintf(
1179 '<strong>%s:</strong> %s',
1180 esc_html__( 'Code source', 'pods' ),
1181 esc_html( $code_source )
1182 ),
1183 null,
1184 '.pods-admin-container'
1185 );
1186
1187 $source .= ' ' . ob_get_clean();
1188 }
1189 }
1190 }
1191
1192 $pod = [
1193 'id' => $pod['id'],
1194 'label' => $pod['label'],
1195 'name' => $pod['name'],
1196 'object' => $pod['object'],
1197 'type' => $pod_type,
1198 'real_type' => $pod_real_type,
1199 'storage' => $storage_type_label,
1200 'source' => $source,
1201 'pod_object' => $pod,
1202 ];
1203
1204 if ( ! pods_is_types_only( false, $pod['name'] ) ) {
1205 $pod['group_count'] = number_format_i18n( $group_count );
1206 $pod['field_count'] = number_format_i18n( $field_count );
1207
1208 $total_groups += $group_count;
1209 $total_fields += $field_count;
1210 }
1211
1212 if ( $include_row_counts ) {
1213 $pod['row_count'] = number_format_i18n( $row_counts['row_count'] );
1214
1215 $total_rows += $row_counts['row_count'];
1216
1217 $pod['row_meta_count'] = 'n/a';
1218 $pod['podsrel_count'] = 'n/a';
1219
1220 if ( $show_meta_count ) {
1221 $pod['row_meta_count'] = number_format_i18n( $row_counts['row_meta_count'] );
1222
1223 $total_row_meta += $row_counts['row_meta_count'];
1224 }
1225
1226 if ( ! $is_tableless ) {
1227 $pod['podsrel_count'] = number_format_i18n( $row_counts['podsrel_count'] );
1228
1229 $total_podsrel_rows += $row_counts['podsrel_count'];
1230 }
1231 }
1232
1233 // @codingStandardsIgnoreLine
1234 if ( 'manage' !== pods_v( 'action' ) ) {
1235 $found_id = (int) pods_v( 'id' );
1236 $found_name = pods_v( 'name' );
1237
1238 if (
1239 (
1240 $found_id
1241 && $pod['id'] === $found_id
1242 )
1243 || (
1244 $found_name
1245 && $pod['name'] === $found_name
1246 )
1247 ) {
1248 $row = $pod;
1249 }
1250 }
1251
1252 $pod_list[] = $pod;
1253 }//end foreach
1254
1255 if ( ! $has_storage_type ) {
1256 unset( $fields['storage'] );
1257 }
1258
1259 if ( ! $has_source ) {
1260 unset( $fields['source'] );
1261 }
1262
1263 if (
1264 (
1265 0 === $total_groups
1266 && 0 === $total_fields
1267 )
1268 || pods_is_types_only()
1269 ) {
1270 unset( $fields['group_count'], $fields['field_count'] );
1271 }
1272
1273 if ( false === $row && 0 < pods_v( 'id' ) && 'delete' !== pods_v( 'action' ) ) {
1274 pods_message( 'Pod not found', 'error' );
1275
1276 // @codingStandardsIgnoreLine
1277 unset( $_GET['id'], $_GET['action'] );
1278 }
1279
1280 $total_pods = count( $pod_list );
1281
1282 $extra_total_text = '';
1283
1284 if ( ! pods_is_types_only() ) {
1285 $extra_total_text .= sprintf(
1286 ', %1$s %2$s, %3$s %4$s',
1287 number_format_i18n( $total_groups ),
1288 _n( 'group', 'groups', $total_groups, 'pods' ),
1289 number_format_i18n( $total_fields ),
1290 _n( 'field', 'fields', $total_fields, 'pods' )
1291 );
1292 }
1293
1294 if ( $include_row_counts ) {
1295 $extra_total_text .= sprintf(
1296 ', %1$s %2$s, %3$s %4$s, %5$s %6$s',
1297 number_format_i18n( $total_rows ),
1298 _n( 'data row', 'data rows', $total_rows, 'pods' ),
1299 number_format_i18n( $total_row_meta ),
1300 _n( 'meta row', 'meta rows', $total_row_meta, 'pods' ),
1301 number_format_i18n( $total_podsrel_rows ),
1302 // translators: "podsrel" references the name of the Pods relationships table in the database.
1303 _n( 'podsrel row', 'podsrel rows', $total_podsrel_rows, 'pods' )
1304 );
1305 }
1306
1307 $pod_list = wp_list_sort( $pod_list, 'label', 'ASC', true );
1308
1309 $ui = [
1310 'data' => $pod_list,
1311 'row' => $row,
1312 'total' => $total_pods,
1313 'total_found' => $total_pods,
1314 'items' => 'Pods',
1315 'item' => 'Pod',
1316 'fields' => [
1317 'manage' => $fields,
1318 ],
1319 'sql' => [
1320 'field_id' => 'id',
1321 'field_index' => 'label',
1322 ],
1323 'actions_disabled' => [ 'view', 'export', 'delete', 'duplicate' ],
1324 'actions_custom' => [
1325 'add' => [ $this, 'admin_setup_add' ],
1326 'edit' => [
1327 'callback' => [ $this, 'admin_setup_edit' ],
1328 'restrict_callback' => [ $this, 'admin_restrict_non_db_type' ],
1329 ],
1330 'duplicate_pod' => [
1331 'label' => __( 'Duplicate', 'pods' ),
1332 'callback' => [ $this, 'admin_setup_duplicate' ],
1333 'restrict_callback' => [ $this, 'admin_setup_duplicate_restrict' ],
1334 'nonce' => true,
1335 ],
1336 'delete_pod' => [
1337 'label' => __( 'Delete', 'pods' ),
1338 'confirm' => __( 'Are you sure you want to delete this Pod?', 'pods' )
1339 . "\n\n"
1340 . __( 'All of the content and items will remain in the database.', 'pods' )
1341 . "\n\n"
1342 . __( 'You may want to go to Pods Admin > Settings > Cleanup & Reset > "Delete all content for a Pod" first.', 'pods' ),
1343 'callback' => [ $this, 'admin_setup_delete' ],
1344 'restrict_callback' => [ $this, 'admin_restrict_non_db_type' ],
1345 'nonce' => true,
1346 'span_class' => 'delete',
1347 ],
1348 ],
1349 'action_links' => [
1350 'add' => pods_query_arg( [
1351 'page' => 'pods-add-new',
1352 'action' => '',
1353 'id' => '',
1354 'do' => '',
1355 '_wpnonce' => '',
1356 ] ),
1357 'duplicate_pod' => pods_query_arg( [
1358 'action' => 'duplicate_pod',
1359 'id' => '{@id}',
1360 'name' => '{@name}',
1361 ] ),
1362 ],
1363 'search' => false,
1364 'searchable' => false,
1365 'sortable' => true,
1366 'pagination' => false,
1367 'extra' => [
1368 'total' => $extra_total_text,
1369 ],
1370 ];
1371
1372 if ( 1 < count( $pod_types_found ) ) {
1373 $ui['views'] = [ 'all' => __( 'All', 'pods' ) . ' (' . $total_pods . ')' ];
1374 $ui['view'] = $view;
1375 $ui['heading'] = [ 'views' => __( 'Type', 'pods' ) ];
1376 $ui['filters_enhanced'] = true;
1377
1378 foreach ( $pod_types_found as $pod_type => $number_found ) {
1379 $ui['views'][ $pod_type ] = sprintf(
1380 '%1$s (%2$s)',
1381 $pod_types[ $pod_type ],
1382 number_format_i18n( $number_found )
1383 );
1384 }
1385
1386 if ( $has_source && 1 < count( $sources_found ) ) {
1387 foreach ( $sources_found as $source_type => $number_found ) {
1388 $ui['views'][ 'source/' . $source_type ] = sprintf(
1389 '%1$s: %2$s (%3$s)',
1390 __( 'Source', 'pods' ),
1391 $source_types[ $source_type ],
1392 $number_found
1393 );
1394 }
1395 }
1396 }
1397
1398 // Maybe auto-map the slugs to ID when editing.
1399 if ( 'edit' === $action && $id && ! is_numeric( $id ) ) {
1400 foreach ( $ui['data'] as $check_pod ) {
1401 if ( $check_pod['name'] === $id && $check_pod['id'] && is_numeric( $check_pod['id'] ) ) {
1402 pods_redirect( pods_query_arg( [ 'id' => (int) $check_pod['id'] ] ) );
1403
1404 break;
1405 }
1406 }
1407 }
1408
1409 // Add our custom callouts.
1410 $this->handle_callouts_updates();
1411
1412 add_filter( 'pods_ui_manage_custom_container_classes', array( $this, 'admin_manage_container_class' ) );
1413
1414 if ( $this->has_horizontal_callout() ) {
1415 add_action( 'pods_ui_manage_before_container', [ $this, 'admin_manage_callouts' ] );
1416 } else {
1417 add_action( 'pods_ui_manage_after_container', [ $this, 'admin_manage_callouts' ] );
1418 }
1419
1420 pods_ui( $ui );
1421 }
1422
1423 /**
1424 * Handle the Review Access Rights screen.
1425 */
1426 public function admin_access_rights_review() {
1427 $api = pods_api();
1428
1429 $pods = $api->load_pods( [ 'fields' => false ] );
1430
1431 if ( empty( $pods ) ) {
1432 pods_message( __( 'You do not have any Pods set up yet.', 'pods ' ) );
1433 }
1434
1435 $pod_types = $api->get_pod_types();
1436
1437 $first_pods_version = get_option( 'pods_framework_version_first' );
1438 $first_pods_version = '' === $first_pods_version ? PODS_VERSION : $first_pods_version;
1439
1440 $dynamic_features_allow_options = pods_access_get_dynamic_features_allow_options();
1441 $restricted_dynamic_features_options = pods_access_get_restricted_dynamic_features_options();
1442
1443 $other_view_groups = [
1444 'public' => [
1445 'label' => __( 'Content Privacy', 'pods' ),
1446 'views' => [
1447 '1' => [
1448 'label' => __( 'Public', 'pods' ),
1449 'count' => 0,
1450 ],
1451 '0' => [
1452 'label' => __( 'Private', 'pods' ),
1453 'count' => 0,
1454 ],
1455 ],
1456 ],
1457 'dynamic_features_allow' => [
1458 'label' => __( 'Dynamic Features', 'pods' ),
1459 'views' => [],
1460 ],
1461 'restricted_dynamic_features' => [
1462 'label' => __( 'Dynamic Features', 'pods' ),
1463 'views' => [
1464 'unrestricted' => [
1465 'label' => __( 'Unrestricted', 'pods' ),
1466 'count' => 0,
1467 ],
1468 'restricted' => [
1469 'label' => __( 'Restricted', 'pods' ),
1470 'count' => 0,
1471 ],
1472 ],
1473 ],
1474 ];
1475
1476 foreach ( $dynamic_features_allow_options as $dynamic_features_allow_option => $dynamic_features_allow_option_label ) {
1477 $other_view_groups['dynamic_features_allow']['views'][ $dynamic_features_allow_option ] = [
1478 'label' => trim( str_replace( '🔒', '', $dynamic_features_allow_option_label ) ),
1479 'count' => 0,
1480 ];
1481 }
1482
1483 $other_view_groups['dynamic_features_allow']['views']['inherit']['label'] = __( 'WP Default', 'pods' );
1484
1485 $row = false;
1486
1487 $pod_types_found = [];
1488 $sources_found = [];
1489 $source_types = [];
1490
1491 $fields = [
1492 'label' => [
1493 'label' => __( 'Label', 'pods' ),
1494 ],
1495 'name' => [
1496 'label' => __( 'Name', 'pods' ),
1497 ],
1498 'type' => [
1499 'label' => __( 'Type', 'pods' ),
1500 ],
1501 'source' => [
1502 'label' => __( 'Source', 'pods' ),
1503 'width' => '10%',
1504 'type' => 'raw',
1505 ],
1506 'public' => [
1507 'label' => __( 'Content Privacy', 'pods' ),
1508 'type' => 'raw',
1509 ],
1510 'dynamic_features_allow' => [
1511 'label' => __( 'Allow Dynamic Features', 'pods' ),
1512 'type' => 'raw',
1513 ],
1514 'restricted_dynamic_features' => [
1515 'label' => __( 'Restricted Dynamic Features', 'pods' ),
1516 'type' => 'pick',
1517 ],
1518 ];
1519
1520 /**
1521 * Filters whether to extend internal Pods.
1522 *
1523 * @since 2.8.0
1524 *
1525 * @param bool $extend_internal Whether to extend internal Pods.
1526 */
1527 $extend_internal = apply_filters( 'pods_admin_setup_extend_pods_internal', false );
1528
1529 $pod_list = array();
1530
1531 $has_source = false;
1532
1533 foreach ( $pods as $k => $pod ) {
1534 $pod_type = $pod['type'];
1535 $pod_type_label = null;
1536
1537 if ( empty( $pod_type ) || ! is_string( $pod_type ) ) {
1538 $pod_type = 'post_type';
1539 }
1540
1541 if ( ! empty( $pod['internal'] ) ) {
1542 // Don't show internal if we aren't extending them.
1543 if ( ! $extend_internal ) {
1544 continue;
1545 }
1546
1547 $pod_type = 'internal';
1548 }
1549
1550 if ( isset( $pod_types[ $pod_type ] ) ) {
1551 $pod_type_label = $pod_types[ $pod_type ];
1552 }
1553
1554 $pod_real_type = $pod_type;
1555
1556 if ( null !== $pod_type_label ) {
1557 if ( ! $pod->is_extended() && in_array( $pod_type, array(
1558 'post_type',
1559 'taxonomy',
1560 ), true ) ) {
1561 if ( 'post_type' === $pod_type ) {
1562 $pod_type = 'cpt';
1563 } else {
1564 $pod_type = 'ct';
1565 }
1566
1567 if ( isset( $pod_types[ $pod_type ] ) ) {
1568 $pod_type_label = $pod_types[ $pod_type ];
1569 }
1570 }
1571
1572 if ( ! isset( $pod_types_found[ $pod_type ] ) ) {
1573 $pod_types_found[ $pod_type ] = 1;
1574 } else {
1575 $pod_types_found[ $pod_type ] ++;
1576 }
1577
1578 $pod_real_type = $pod_type;
1579 $pod_type = $pod_type_label;
1580 }
1581
1582 $object_storage_type = $pod->get_object_storage_type();
1583 $source = $pod->get_object_storage_type_label();
1584
1585 if ( $source ) {
1586 $source_types[ $object_storage_type ] = $source;
1587
1588 if ( ! isset( $sources_found[ $object_storage_type ] ) ) {
1589 $sources_found[ $object_storage_type ] = 1;
1590 } else {
1591 $sources_found[ $object_storage_type ] ++;
1592 }
1593 }
1594
1595 $source = esc_html( $source );
1596
1597 if ( 'post_type' !== $object_storage_type ) {
1598 $has_source = true;
1599
1600 if ( 'file' === $object_storage_type ) {
1601 $file_source = $pod->get_arg( '_pods_file_source' );
1602
1603 if ( $file_source ) {
1604 if ( 0 === strpos( $file_source, ABSPATH ) ) {
1605 $file_source = str_replace( ABSPATH, '', $file_source );
1606 }
1607
1608 $source .= ' ' . pods_help(
1609 sprintf(
1610 '<strong>%s:</strong> %s',
1611 esc_html__( 'File source', 'pods' ),
1612 esc_html( $file_source )
1613 ),
1614 null,
1615 '.pods-admin-container',
1616 true
1617 );
1618 }
1619 } elseif ( 'collection' === $object_storage_type ) {
1620 $code_source = $pod->get_arg( '_pods_code_source' );
1621
1622 if ( $code_source ) {
1623 if ( 0 === strpos( $code_source, ABSPATH ) ) {
1624 $code_source = str_replace( ABSPATH, '', $code_source );
1625 }
1626
1627 $source .= ' ' . pods_help(
1628 sprintf(
1629 '<strong>%s:</strong> %s',
1630 esc_html__( 'Code source', 'pods' ),
1631 esc_html( $code_source )
1632 ),
1633 null,
1634 '.pods-admin-container',
1635 true
1636 );
1637 }
1638 }
1639 }
1640
1641 $is_public = pods_is_type_public(
1642 [
1643 'pod' => $pod,
1644 ]
1645 );
1646
1647 $dynamic_features_allow_default = 'inherit';
1648
1649 if ( 'pod' === $pod->get_type() ) {
1650 $dynamic_features_allow_default = version_compare( $first_pods_version, '3.1.0-a-1', '<' ) ? '1' : '0';
1651 }
1652
1653 $dynamic_features_allow = $pod->get_arg( 'dynamic_features_allow', $dynamic_features_allow_default, true );
1654
1655 if ( isset( $other_view_groups['dynamic_features_allow']['views'][ $dynamic_features_allow ] ) ) {
1656 $other_view_groups['dynamic_features_allow']['views'][ $dynamic_features_allow ]['count'] ++;
1657 }
1658
1659 $dynamic_features_allow_label = isset( $dynamic_features_allow_options[ $dynamic_features_allow ] ) ? $dynamic_features_allow_options[ $dynamic_features_allow ] : $dynamic_features_allow_options[ $dynamic_features_allow_default ];
1660
1661 if ( $dynamic_features_allow_label === $dynamic_features_allow_options['inherit'] ) {
1662 $dynamic_features_allow_label .= ' - ' . ( $is_public ? $dynamic_features_allow_options['1'] : $dynamic_features_allow_options['0'] );
1663 }
1664
1665 $restrict_dynamic_features = (int) $pod->get_arg( 'restrict_dynamic_features', '1' );
1666
1667 $pod_row = [
1668 'id' => $pod['id'],
1669 'label' => $pod['label'],
1670 'name' => $pod['name'],
1671 'object' => $pod['object'],
1672 'type' => $pod_type,
1673 'real_type' => $pod_real_type,
1674 'source' => $source,
1675 'real_source' => $object_storage_type,
1676 'bulk_disabled' => 'post_type' !== $object_storage_type,
1677 'pod_object' => $pod,
1678 'public' => $is_public ? __( 'Public', 'pods' ) : '🔒 ' . __( 'Private', 'pods' ),
1679 'real_public' => $is_public ? 1 : 0,
1680 'dynamic_features_allow' => $dynamic_features_allow_label,
1681 'real_dynamic_features_allow' => $dynamic_features_allow,
1682 'restricted_dynamic_features' => $pod->get_arg( 'restricted_dynamic_features' ),
1683 ];
1684
1685 if ( 0 === $restrict_dynamic_features ) {
1686 $pod_row['restricted_dynamic_features'] = [];
1687 }
1688
1689 if ( ! is_array( $pod_row['restricted_dynamic_features'] ) ) {
1690 $pod_row['restricted_dynamic_features'] = [
1691 'display',
1692 'form',
1693 ];
1694 }
1695
1696 if ( $pod->is_extended() ) {
1697 $extended_help_text = pods_help(
1698 __( 'This is an extended content type. The Content Privacy cannot be changed by Pods. You can choose to enable Dynamic Features separately anyway if it has "WP Default" used.', 'pods' ),
1699 null,
1700 '.pods-admin-container',
1701 true
1702 );
1703
1704 $pod_row['public'] .= $extended_help_text;
1705
1706 if ( 'inherit' === $dynamic_features_allow ) {
1707 $pod_row['dynamic_features_allow'] .= $extended_help_text;
1708 }
1709 }
1710
1711 $other_view_groups['public']['views'][ (string) $pod_row['real_public'] ]['count'] ++;
1712
1713 if ( empty( $pod_row['restricted_dynamic_features'] ) ) {
1714 $pod_row['restricted_dynamic_features'] = __( 'Unrestricted', 'pods' );
1715 $pod_row['real_restricted_dynamic_features'] = 'unrestricted';
1716 } else {
1717 foreach ( $pod_row['restricted_dynamic_features'] as $fk => $feature ) {
1718 $pod_row['restricted_dynamic_features'][ $fk ] = pods_v( $feature, $restricted_dynamic_features_options, ucwords( $feature ) );
1719 }
1720
1721 $pod_row['real_restricted_dynamic_features'] = 'restricted';
1722 }
1723
1724 $other_view_groups['restricted_dynamic_features']['views'][ $pod_row['real_restricted_dynamic_features'] ]['count'] ++;
1725
1726 // @codingStandardsIgnoreLine
1727 if ( 'manage' !== pods_v( 'action' ) ) {
1728 $found_id = (int) pods_v( 'id' );
1729 $found_name = pods_v( 'name' );
1730
1731 if (
1732 (
1733 $found_id
1734 && $pod_row['id'] === $found_id
1735 )
1736 || (
1737 $found_name
1738 && $pod_row['name'] === $found_name
1739 )
1740 ) {
1741 $row = $pod_row;
1742 }
1743 }
1744
1745 $pod_list[] = $pod_row;
1746 }//end foreach
1747
1748 if ( ! $has_source ) {
1749 unset( $fields['source'] );
1750 }
1751
1752 if ( false === $row && 0 < pods_v( 'id' ) && 'delete' !== pods_v( 'action' ) ) {
1753 pods_message( 'Pod not found', 'error' );
1754
1755 // @codingStandardsIgnoreLine
1756 unset( $_GET['id'], $_GET['action'] );
1757 }
1758
1759 $total_pods = count( $pod_list );
1760
1761 $total_pods_unfiltered = $total_pods;
1762
1763 // Handle filtering.
1764 $view_filters = [
1765 'type' => 'real_type',
1766 'source' => 'real_source',
1767 'public' => 'real_public',
1768 'dynamic_features_allow' => 'real_dynamic_features_allow',
1769 'restricted_dynamic_features' => 'real_restricted_dynamic_features',
1770 ];
1771
1772 $view = pods_v( 'view', 'get', 'all', true );
1773 $view_filter_info = explode( '/', $view );
1774 $view_filter_group_active = isset( $view_filter_info[0] ) ? $view_filter_info[0] : null;
1775 $view_filter_key_active = isset( $view_filter_info[1] ) ? $view_filter_info[1] : null;
1776
1777 foreach ( $view_filters as $view_filter => $real_key ) {
1778 if ( $view_filter_group_active !== $view_filter ) {
1779 continue;
1780 }
1781
1782 foreach ( $pod_list as $pod_key => $pod ) {
1783 // Maybe remove the pod from the list.
1784 if ( (string) $view_filter_key_active !== (string) $pod[ $real_key ] ) {
1785 unset( $pod_list[ $pod_key ] );
1786 }
1787 }
1788 }
1789
1790 $pod_list = wp_list_sort( array_values( $pod_list ), 'label' );
1791
1792 $total_pods = count( $pod_list );
1793
1794 $ui = [
1795 'data' => $pod_list,
1796 'row' => $row,
1797 'total' => $total_pods,
1798 'total_found' => $total_pods,
1799 'items' => 'Pods',
1800 'item' => 'Pod',
1801 'header' => [
1802 'manage' => '🔒 ' . __( 'Review Access Rights for Pods', 'pods' ),
1803 ],
1804 'fields' => [
1805 'manage' => $fields,
1806 ],
1807 'sql' => [
1808 'field_id' => 'id',
1809 'field_index' => 'label',
1810 ],
1811 'actions_disabled' => [ 'add', 'view', 'export', 'delete', 'duplicate' ],
1812 'actions_custom' => [
1813 'edit' => [
1814 'label' => __( 'Edit Pod', 'pods' ),
1815 'restrict_callback' => [ $this, 'admin_restrict_non_db_type' ],
1816 ],
1817 'make_public' => [
1818 'label' => __( 'Make public', 'pods' ),
1819 'callback' => [ $this, 'admin_access_rights_review_make_public' ],
1820 'restrict_callback' => [ $this, 'admin_restrict_access_rights_review_make_public' ],
1821 'nonce' => true,
1822 ],
1823 'make_private' => [
1824 'label' => __( 'Make private', 'pods' ),
1825 'callback' => [ $this, 'admin_access_rights_review_make_private' ],
1826 'restrict_callback' => [ $this, 'admin_restrict_access_rights_review_make_private' ],
1827 'nonce' => true,
1828 ],
1829 'wp_default_dynamic_features' => [
1830 'label' => __( 'Set Dynamic Features to WP Default', 'pods' ),
1831 'callback' => [ $this, 'admin_access_rights_review_wp_default_dynamic_features' ],
1832 'restrict_callback' => [ $this, 'admin_restrict_access_rights_review_wp_default_dynamic_features' ],
1833 'nonce' => true,
1834 ],
1835 'enable_dynamic_features' => [
1836 'label' => __( 'Enable Dynamic Features', 'pods' ),
1837 'callback' => [ $this, 'admin_access_rights_review_enable_dynamic_features' ],
1838 'restrict_callback' => [ $this, 'admin_restrict_access_rights_review_enable_dynamic_features' ],
1839 'nonce' => true,
1840 ],
1841 'disable_dynamic_features' => [
1842 'label' => __( 'Disable Dynamic Features', 'pods' ),
1843 'callback' => [ $this, 'admin_access_rights_review_disable_dynamic_features' ],
1844 'restrict_callback' => [ $this, 'admin_restrict_access_rights_review_disable_dynamic_features' ],
1845 'nonce' => true,
1846 ],
1847 'restrict_dynamic_features' => [
1848 'label' => __( 'Restrict all dynamic features', 'pods' ),
1849 'callback' => [ $this, 'admin_access_rights_review_restrict_dynamic_features' ],
1850 'restrict_callback' => [ $this, 'admin_restrict_access_rights_review_restrict_dynamic_features' ],
1851 'nonce' => true,
1852 ],
1853 'unrestrict_dynamic_features' => [
1854 'label' => __( 'Unrestrict all dynamic features', 'pods' ),
1855 'callback' => [ $this, 'admin_access_rights_review_unrestrict_dynamic_features' ],
1856 'restrict_callback' => [ $this, 'admin_restrict_access_rights_review_unrestrict_dynamic_features' ],
1857 'nonce' => true,
1858 ],
1859 ],
1860 'actions_bulk' => [
1861 'make_public' => [
1862 'label' => __( 'Make public', 'pods' ),
1863 'callback' => [ $this, 'admin_access_rights_review_make_public_bulk' ],
1864 ],
1865 'make_private' => [
1866 'label' => __( 'Make private', 'pods' ),
1867 'callback' => [ $this, 'admin_access_rights_review_make_private_bulk' ],
1868 ],
1869 'wp_default_dynamic_features' => [
1870 'label' => __( 'Set Dynamic Features to WP Default', 'pods' ),
1871 'callback' => [ $this, 'admin_access_rights_review_wp_default_dynamic_features_bulk' ],
1872 ],
1873 'enable_dynamic_features' => [
1874 'label' => __( 'Enable Dynamic Features', 'pods' ),
1875 'callback' => [ $this, 'admin_access_rights_review_enable_dynamic_features_bulk' ],
1876 ],
1877 'disable_dynamic_features' => [
1878 'label' => __( 'Disable Dynamic Features', 'pods' ),
1879 'callback' => [ $this, 'admin_access_rights_review_disable_dynamic_features_bulk' ],
1880 ],
1881 'restrict_dynamic_features' => [
1882 'label' => __( 'Restrict all dynamic features', 'pods' ),
1883 'callback' => [ $this, 'admin_access_rights_review_restrict_dynamic_features_bulk' ],
1884 ],
1885 'unrestrict_dynamic_features' => [
1886 'label' => __( 'Unrestrict all dynamic features', 'pods' ),
1887 'callback' => [ $this, 'admin_access_rights_review_unrestrict_dynamic_features_bulk' ],
1888 ],
1889 ],
1890 'action_links' => [
1891 'edit' => pods_query_arg( [
1892 'page' => 'pods',
1893 'action' => 'edit',
1894 'id' => '{@id}',
1895 'name' => '{@name}',
1896 ] ),
1897 ],
1898 'search' => false,
1899 'searchable' => false,
1900 'sortable' => true,
1901 'pagination' => false,
1902 ];
1903
1904 $ui['views'] = [ 'all' => __( 'All', 'pods' ) . ' (' . $total_pods_unfiltered . ')' ];
1905 $ui['view'] = $view;
1906 $ui['heading'] = [ 'views' => __( 'View', 'pods' ) ];
1907 $ui['filters_enhanced'] = true;
1908
1909 if ( 1 < count( $pod_types_found ) ) {
1910 foreach ( $pod_types_found as $pod_type => $number_found ) {
1911 $ui['views'][ 'type/' . $pod_type ] = sprintf(
1912 '<strong>%1$s:</strong> %2$s (%3$s)',
1913 esc_html__( 'Type', 'pods' ),
1914 esc_html( $pod_types[ $pod_type ] ),
1915 number_format_i18n( $number_found )
1916 );
1917 }
1918 }
1919
1920 if ( $has_source && 1 < count( $sources_found ) ) {
1921 foreach ( $sources_found as $source_type => $number_found ) {
1922 $ui['views'][ 'source/' . $source_type ] = sprintf(
1923 '<strong>%1$s:</strong> %2$s (%3$s)',
1924 esc_html__( 'Source', 'pods' ),
1925 esc_html( $source_types[ $source_type ] ),
1926 number_format_i18n( $number_found )
1927 );
1928 }
1929 }
1930
1931 foreach ( $other_view_groups as $view_group_key => $view_group_info ) {
1932 if ( empty( $view_group_info['views'] ) ) {
1933 continue;
1934 }
1935
1936 foreach ( $view_group_info['views'] as $view_key => $view_info ) {
1937 $ui['views'][ $view_group_key . '/' . $view_key ] = sprintf(
1938 '<strong>%1$s:</strong> %2$s (%3$s)',
1939 $view_group_info['label'],
1940 esc_html( $view_info['label'] ),
1941 number_format_i18n( $view_info['count'] )
1942 );
1943 }
1944 }
1945
1946 $this->handle_callouts_updates();
1947
1948 add_action( 'pods_ui_manage_before_filters', static function() {
1949 $callout_dismiss_link = add_query_arg( [
1950 'pods_callout_dismiss' => 'access_rights',
1951 'pods_callout_dismiss_nonce' => wp_create_nonce( 'pods_callout_dismiss_access_rights' ),
1952 ] );
1953
1954 pods_message(
1955 wpautop(
1956 esc_html__( 'This screen is for reviewing the access rights and settings for your Pods. You can change the access rights for each Pod individually or in bulk.', 'pods' )
1957 . "\n\n" . esc_html__( 'Carefully review whether your content types should be public and if dynamic features should be allowed.', 'pods' )
1958 . "\n\n" . '<a href="https://docs.pods.io/displaying-pods/access-rights-in-pods/" target="_blank" rel="noopener noreferrer">' . esc_html__( 'Read the documentation for more information', 'pods' ) . ' &raquo;</a>'
1959 ),
1960 'info',
1961 false,
1962 false
1963 );
1964
1965 $callouts = PodsAdmin::$instance->get_callouts();
1966
1967 if ( ! empty( $callouts['access_rights'] ) ) {
1968 pods_message(
1969 wpautop(
1970 esc_html__( 'You have not confirmed your Pods access rights below yet.', 'pods' )
1971 . "\n\n" . esc_html__( 'Make changes below or confirm them.', 'pods' )
1972 . "\n\n" . '<a href="' . esc_url( $callout_dismiss_link ) . '" class="button button-primary">' . esc_html__( 'Yes, I confirm the access rights below are correct for my site', 'pods' ) . '</a>'
1973 ),
1974 'warning',
1975 false,
1976 false
1977 );
1978 }
1979
1980 if ( ! pods_can_use_dynamic_features() ) {
1981 pods_message(
1982 wpautop(
1983 sprintf(
1984 '
1985 🔒 %s
1986
1987 <a href="%s">%s &raquo;</a>
1988 ',
1989 esc_html__( 'Dynamic Features are currently disabled globally which will automatically override any Dynamic Feature setting below from being referenced.', 'pods' ),
1990 esc_url( admin_url( 'admin.php?page=pods-settings' ) ),
1991 esc_html__( 'You can adjust this in your Pods Settings', 'pods' )
1992 )
1993 ),
1994 'error',
1995 false,
1996 false
1997 );
1998 }
1999 } );
2000
2001 pods_ui( $ui );
2002 }
2003
2004 /**
2005 * Get list of callouts to show.
2006 *
2007 * @since 2.7.17
2008 *
2009 * @return array List of callouts.
2010 */
2011 public function get_callouts() {
2012 // Demo mode always bypasses callouts.
2013 if ( pods_is_demo() ) {
2014 return [];
2015 }
2016
2017 $force_callouts = 1 === (int) pods_v( 'pods_force_callouts' );
2018
2019 $page = pods_v( 'page' );
2020
2021 if ( in_array( $page, array( 'pods-settings', 'pods-help' ), true ) ) {
2022 $force_callouts = true;
2023 }
2024
2025 $callouts = get_option( 'pods_callouts' );
2026
2027 if ( ! $callouts ) {
2028 $callouts = [
2029 'friends_2023_docs' => 1,
2030 'access_rights' => (
2031 PodsInit::$version_last
2032 && version_compare( PodsInit::$version_last, '3.1.0-a-1', '<' )
2033 ) ? 0 : 1,
2034 ];
2035
2036 update_option( 'pods_callouts', $callouts );
2037 }
2038
2039 // Handle callouts logic.
2040 $callouts['access_rights'] = ! isset( $callouts['access_rights'] ) || $callouts['access_rights'] ? 1 : 0;
2041 $callouts['friends_2023_docs'] = ! isset( $callouts['friends_2023_docs'] ) || $callouts['friends_2023_docs'] || $force_callouts ? 1 : 0;
2042
2043 /**
2044 * Allow hooking into whether or not the specific callouts should show.
2045 *
2046 * @since 2.7.17
2047 *
2048 * @param array $callouts List of callouts to enable.
2049 */
2050 $callouts = apply_filters( 'pods_admin_callouts', $callouts );
2051
2052 return $callouts;
2053 }
2054
2055 /**
2056 * Determine whether there's a horizontal callout.
2057 *
2058 * @since 3.1.0
2059 *
2060 * @param array $callouts The list of callouts if available, otherwise it will be fetched.
2061 *
2062 * @return bool Whether there's a horizontal callout.
2063 */
2064 public function has_horizontal_callout( array $callouts = [] ): bool {
2065 if ( ! $callouts ) {
2066 $callouts = $this->get_callouts();
2067 }
2068
2069 return ! empty( $callouts['access_rights'] );
2070 }
2071
2072 /**
2073 * Handle callouts update logic.
2074 *
2075 * @since 2.7.17
2076 */
2077 public function handle_callouts_updates() {
2078 $callouts = get_option( 'pods_callouts' );
2079
2080 if ( ! $callouts ) {
2081 $callouts = array();
2082 }
2083
2084 $callout_dismiss = sanitize_text_field( pods_v( 'pods_callout_dismiss' ) );
2085 $callout_dismiss_nonce = pods_v( 'pods_callout_dismiss_nonce' );
2086
2087 // Demo mode will auto-update the option for future loads.
2088 $is_demo = pods_is_demo();
2089
2090 // Handle reset dismiss separately.
2091 if ( 'reset' === $callout_dismiss ) {
2092 // Reset callouts.
2093 update_option( 'pods_callouts', [] );
2094
2095 return;
2096 }
2097
2098 // Invalid nonce, cannot do anything with this dismiss request.
2099 if (
2100 ! $is_demo
2101 && (
2102 ! $callout_dismiss_nonce
2103 || false === wp_verify_nonce( $callout_dismiss_nonce, 'pods_callout_dismiss_' . $callout_dismiss )
2104 )
2105 ) {
2106 return;
2107 }
2108
2109 if ( $is_demo ) {
2110 // Disable Friends of Pods callout on demos.
2111 $callout_dismiss = 'friends_2023_docs';
2112 }
2113
2114 if ( $callout_dismiss ) {
2115 $this->update_callout( $callout_dismiss, false );
2116 }
2117 }
2118
2119 /**
2120 * Handle updating whether a callout should be enabled.
2121 *
2122 * @since 3.1.0
2123 *
2124 * @param string $callout The callout to update.
2125 * @param bool $enabled Whether the callout should be enabled.
2126 */
2127 public function update_callout( string $callout, bool $enabled ) {
2128 $callouts = get_option( 'pods_callouts' );
2129
2130 if ( ! $callouts ) {
2131 $callouts = array();
2132 }
2133
2134 $callouts[ $callout ] = (int) $enabled;
2135
2136 update_option( 'pods_callouts', $callouts );
2137 }
2138
2139 /**
2140 * Add class to container if we have callouts to show.
2141 *
2142 * @since 2.7.17
2143 *
2144 * @param array $classes List of classes to use.
2145 *
2146 * @return array List of classes to use.
2147 */
2148 public function admin_manage_container_class( $classes ) {
2149 $callouts = $this->get_callouts();
2150
2151 // Only get enabled callouts.
2152 $callouts = array_filter( $callouts );
2153
2154 if ( ! empty( $callouts ) ) {
2155 if ( $this->has_horizontal_callout( $callouts ) ) {
2156 $classes[] = 'pods-admin--flex-horizontal';
2157 } else {
2158 $classes[] = 'pods-admin--flex';
2159 }
2160 }
2161
2162 return $classes;
2163 }
2164
2165 /**
2166 * Add callouts to let admins know about certain things.
2167 *
2168 * @since 2.7.17
2169 */
2170 public function admin_manage_callouts() {
2171 static $did_callout = false;
2172
2173 if ( $did_callout ) {
2174 return;
2175 }
2176
2177 $force_callouts = false;
2178
2179 $page = pods_v( 'page' );
2180
2181 if ( in_array( $page, array( 'pods-settings', 'pods-help' ), true ) ) {
2182 $force_callouts = true;
2183 }
2184
2185 $callouts = $this->get_callouts();
2186
2187 if ( ! empty( $callouts['access_rights'] ) ) {
2188 $did_callout = true;
2189
2190 pods_view( PODS_DIR . 'ui/admin/callouts/access_rights.php', compact( array_keys( get_defined_vars() ) ) );
2191 } elseif ( ! empty( $callouts['friends_2023_docs'] ) ) {
2192 $did_callout = true;
2193
2194 pods_view( PODS_DIR . 'ui/admin/callouts/friends_2023_docs.php', compact( array_keys( get_defined_vars() ) ) );
2195 }
2196 }
2197
2198 /**
2199 * Get the add page of an object
2200 *
2201 * @param PodsUI $obj PodsUI object.
2202 */
2203 public function admin_setup_add( $obj ) {
2204 pods_view( PODS_DIR . 'ui/admin/setup-add.php', compact( array_keys( get_defined_vars() ) ) );
2205 }
2206
2207 /**
2208 * Get the edit page of an object
2209 *
2210 * @param boolean $duplicate Whether the screen is for duplicating.
2211 * @param PodsUI $obj PodsUI object.
2212 */
2213 public function admin_setup_edit( $duplicate, $obj ) {
2214 $api = pods_api();
2215
2216 $pod = $obj->row['pod_object'];
2217
2218 if ( ! $pod instanceof Pod ) {
2219 $obj->id = null;
2220 $obj->row = [];
2221 $obj->action = 'manage';
2222
2223 $obj->error( __( 'Invalid Pod configuration detected.', 'pods' ) );
2224 $obj->manage();
2225
2226 return null;
2227 }
2228
2229 if ( 'post_type' !== $pod->get_object_storage_type() ) {
2230 $obj->id = null;
2231 $obj->row = [];
2232 $obj->action = 'manage';
2233
2234 // translators: %s: The pod label.
2235 $obj->error( sprintf( __( 'Unable to edit the "%s" Pod configuration.', 'pods' ), $pod->get_label() ) );
2236 $obj->manage();
2237
2238 return null;
2239 }
2240
2241 $original_field_count = 0;
2242
2243 foreach ( $obj->data as $row ) {
2244 if ( (int) $row['id'] === (int) $obj->id ) {
2245 if ( ! isset( $row['field_count'] ) ) {
2246 $row['field_count'] = 0;
2247 }
2248
2249 $original_field_count = (int) $row['field_count'];
2250
2251 break;
2252 }
2253 }
2254
2255 $find_orphan_fields = (
2256 1 === (int) pods_v( 'pods_debug_find_orphan_fields', 'get', 0 )
2257 && pods_is_admin( array( 'pods' ) )
2258 );
2259
2260 $migrated = false;
2261
2262 if ( $find_orphan_fields || 1 !== (int) $pod->get_arg( '_migrated_28' ) ) {
2263 $pod = $this->maybe_migrate_pod_fields_into_group( $pod );
2264
2265 $migrated = true;
2266
2267 // Maybe redirect the page to reload it fresh.
2268 if ( $find_orphan_fields ) {
2269 pods_redirect( pods_query_arg( [ 'pods_debug_find_orphan_fields' => null ] ) );
2270 die();
2271 }
2272
2273 // Check again in case the pod migrated wrong.
2274 if ( ! $pod instanceof Pod ) {
2275 $obj->id = null;
2276 $obj->row = [];
2277 $obj->action = 'manage';
2278
2279 $obj->error( __( 'Invalid Pod configuration detected.', 'pods' ) );
2280 $obj->manage();
2281
2282 return null;
2283 }
2284 }
2285
2286 $current_pod = $pod->export( [
2287 'include_groups' => true,
2288 'include_group_fields' => true,
2289 'include_fields' => false,
2290 ] );
2291
2292 $group_field_count = wp_list_pluck( $current_pod['groups'], 'fields' );
2293 $group_field_count = array_map( 'count', $group_field_count );
2294 $group_field_count = array_sum( $group_field_count );
2295
2296 // Detect if there may be a migration/repair needed.
2297 if ( $original_field_count !== $group_field_count ) {
2298 if ( ! $migrated ) {
2299 $pod = $this->maybe_migrate_pod_fields_into_group( $pod );
2300
2301 // Check again in case the pod migrated wrong.
2302 if ( ! $pod instanceof Pod ) {
2303 $obj->id = null;
2304 $obj->row = [];
2305 $obj->action = 'manage';
2306
2307 $obj->error( __( 'Invalid Pod configuration detected.', 'pods' ) );
2308 $obj->manage();
2309
2310 return null;
2311 }
2312
2313 $current_pod = $pod->export( [
2314 'include_groups' => true,
2315 'include_group_fields' => true,
2316 'include_fields' => false,
2317 ] );
2318 } else {
2319 pods_message( __( 'You may need to repair this Pod, we detected some fields not assigned to the groups shown in this configuration. You can find the tool at Pods Admin > Settings > Tools.', 'pods' ) );
2320 }
2321 }
2322
2323 $config = [
2324 'currentPod' => $current_pod,
2325 'global' => $this->get_global_config( $pod ),
2326 'fieldTypes' => PodsForm::field_types(),
2327 'relatedObjects' => $this->get_field_related_objects(),
2328 'podTypes' => $api->get_pod_types(),
2329 'storageTypes' => $api->get_storage_types(),
2330 // @todo SKC: Remove these below and replace any references to podsDFVConfig
2331 'wp_locale' => $GLOBALS['wp_locale'],
2332 'userLocale' => str_replace( '_', '-', get_user_locale() ),
2333 'currencies' => PodsField_Currency::data_currencies(),
2334 'datetime' => [
2335 'start_of_week' => (int) get_option( 'start_of_week', 0 ),
2336 'gmt_offset' => (int) get_option( 'gmt_offset', 0 ),
2337 ],
2338 ];
2339
2340 $config['currentPod']['podType'] = [
2341 'name' => $config['currentPod']['type'],
2342 ];
2343
2344 $config['currentPod']['storageType'] = [
2345 'name' => $config['currentPod']['storage'],
2346 ];
2347
2348 if ( ! empty( $config['currentPod']['internal'] ) ) {
2349 $config['currentPod']['podType']['name'] = 'internal';
2350 } elseif ( ! $pod->is_extended() ) {
2351 if ( 'post_type' === $config['currentPod']['type'] ) {
2352 $config['currentPod']['podType']['name'] = 'cpt';
2353 } elseif ( 'taxonomy' === $config['currentPod']['type'] ) {
2354 $config['currentPod']['podType']['name'] = 'ct';
2355 }
2356 }
2357
2358 $config['currentPod']['podType']['label'] = ucwords( str_replace( '_', ' ', $config['currentPod']['podType']['name'] ) );
2359
2360 if ( ! empty( $config['podTypes'][ $config['currentPod']['podType']['name'] ] ) ) {
2361 $config['currentPod']['podType']['label'] = $config['podTypes'][ $config['currentPod']['podType']['name'] ];
2362 }
2363
2364 if ( 'settings' === $config['currentPod']['type'] ) {
2365 $config['currentPod']['storageType']['name'] = 'option';
2366 }
2367
2368 $config['currentPod']['storageType']['label'] = ucwords( $config['currentPod']['storageType']['name'] );
2369
2370 if ( ! empty( $config['storageTypes'][ $config['currentPod']['storageType']['name'] ] ) ) {
2371 $config['currentPod']['storageType']['label'] = $config['storageTypes'][ $config['currentPod']['storageType']['name'] ];
2372 }
2373
2374 /**
2375 * Allow filtering the admin config data.
2376 *
2377 * @since 2.8.0
2378 *
2379 * @param array $config The admin config data.
2380 * @param Pod $pod The pod object.
2381 * @param PodsUI $obj The PodsUI object.
2382 */
2383 $config = apply_filters( 'pods_admin_setup_edit_pod_config', $config, $pod, $obj );
2384
2385 wp_localize_script( 'pods-dfv', 'podsAdminConfig', $config );
2386
2387 pods_view( PODS_DIR . 'ui/admin/setup-edit.php', compact( array_keys( get_defined_vars() ) ) );
2388 }
2389
2390 /**
2391 * Get list of field related objects.
2392 *
2393 * @since 2.8.0
2394 *
2395 * @return array List of field related objects.
2396 */
2397 protected function get_field_related_objects() {
2398 $related_object_groups = PodsForm::field_method( 'pick', 'related_objects', true );
2399
2400 $related_objects = [];
2401
2402 foreach ( $related_object_groups as $group => $group_objects ) {
2403 foreach ( $group_objects as $name => $label ) {
2404 $related_objects[ $name ] = [
2405 'name' => $name,
2406 'label' => $label,
2407 ];
2408 }
2409 }
2410
2411 return $related_objects;
2412 }
2413
2414 /**
2415 * Maybe migrate pod fields into a group (if they have no group).
2416 *
2417 * @since 2.8.0
2418 *
2419 * @param Pod $pod The pod object.
2420 *
2421 * @return Pod The pod object.
2422 */
2423 public function maybe_migrate_pod_fields_into_group( $pod ) {
2424 $tool = pods_container( Repair::class );
2425
2426 $results = $tool->repair_groups_and_fields_for_pod( $pod, 'upgrade' );
2427
2428 if ( '' !== $results['message_html'] ) {
2429 if ( 'pods' === pods_v( 'page' ) && 'edit' === pods_v( 'action' ) && 'create' === pods_v( 'do' ) ) {
2430 // Refresh the page if we just added the Pod.
2431 pods_redirect();
2432 } else {
2433 pods_message( $results['message_html'] );
2434 }
2435 }
2436
2437 return $results['upgraded_pod'];
2438 }
2439
2440 /**
2441 * Get the global config for Pods admin.
2442 *
2443 * @param null|\Pods\Whatsit $current_pod
2444 *
2445 * @return array Global config array.
2446 *@since 2.8.0
2447 *
2448 */
2449 public function get_global_config( $current_pod = null ) {
2450 $config_pod = pods_container( Config_Pod::class );
2451 $config_group = pods_container( Config_Group::class );
2452 $config_field = pods_container( Config_Field::class );
2453
2454 // Pod: Backwards compatible configs and hooks.
2455 $pod_tabs = $config_pod->get_tabs( $current_pod);
2456 $pod_tab_options = $config_pod->get_fields( $current_pod, $pod_tabs );
2457
2458 $this->backcompat_convert_tabs_to_groups( $pod_tabs, $pod_tab_options, 'pod/_pods_pod' );
2459
2460 // If not types-only mode, handle groups/fields configs.
2461 if ( ! pods_is_types_only( false, $current_pod->get_name() ) ) {
2462 // Group: Backwards compatible methods and hooks.
2463 $group_tabs = $config_group->get_tabs( $current_pod);
2464 $group_tab_options = $config_group->get_fields( $current_pod, $group_tabs );
2465
2466 $this->backcompat_convert_tabs_to_groups( $group_tabs, $group_tab_options, 'pod/_pods_group' );
2467
2468 // Field: Backwards compatible methods and hooks.
2469 $field_tabs = $config_field->get_tabs( $current_pod);
2470 $field_tab_options = $config_field->get_fields( $current_pod, $field_tabs );
2471
2472 $this->backcompat_convert_tabs_to_groups( $field_tabs, $field_tab_options, 'pod/_pods_field' );
2473 }
2474
2475 $object_collection = Pods\Whatsit\Store::get_instance();
2476
2477 /** @var Pods\Whatsit\Storage $storage */
2478 $storage = $object_collection->get_storage_object( 'collection' );
2479
2480 // Get objects from storage.
2481 $pod_object = $storage->get( [
2482 'object_type' => 'pod',
2483 'name' => '_pods_pod',
2484 'bypass_cache' => true,
2485 ] );
2486
2487 $group_object = $storage->get( [
2488 'object_type' => 'pod',
2489 'name' => '_pods_group',
2490 'bypass_cache' => true,
2491 ] );
2492
2493 $field_object = $storage->get( [
2494 'object_type' => 'pod',
2495 'name' => '_pods_field',
2496 'bypass_cache' => true,
2497 ] );
2498
2499 $global_config = [
2500 'showFields' => ! pods_is_types_only( false, $current_pod->get_name() ),
2501 'pod' => $pod_object->export( [
2502 'include_groups' => true,
2503 'include_group_fields' => true,
2504 'include_fields' => false,
2505 'include_field_data' => true,
2506 'bypass_cache' => true,
2507 'ref_id' => 'global/' . $pod_object->get_type() . '/' . $pod_object->get_name(),
2508 ] ),
2509 'group' => $group_object->export( [
2510 'include_groups' => true,
2511 'include_group_fields' => true,
2512 'include_fields' => false,
2513 'include_field_data' => true,
2514 'bypass_cache' => true,
2515 'ref_id' => 'global/' . $pod_object->get_type() . '/' . $pod_object->get_name(),
2516 ] ),
2517 'field' => $field_object->export( [
2518 'include_groups' => true,
2519 'include_group_fields' => true,
2520 'include_fields' => false,
2521 'include_field_data' => true,
2522 'bypass_cache' => true,
2523 'ref_id' => 'global/' . $pod_object->get_type() . '/' . $pod_object->get_name(),
2524 ] ),
2525 ];
2526
2527 /**
2528 * Allow hooking into the global config setup for a Pod.
2529 *
2530 * @param array $global_config The global config object.
2531 * @param null|\Pods\Whatsit $current_pod The Pod object.
2532 */
2533 $global_config = apply_filters( 'pods_admin_setup_global_config', $global_config, $current_pod );
2534
2535 return $global_config;
2536 }
2537
2538 /**
2539 * Convert the tabs and their options to groups/fields in the collection storage.
2540 *
2541 * @since 2.8.0
2542 *
2543 * @param array $tabs List of registered tabs.
2544 * @param array $options List of tab options.
2545 * @param string $parent The parent object to register to.
2546 *
2547 * @return array Global config array.
2548 */
2549 protected function backcompat_convert_tabs_to_groups( array $tabs, array $options, $parent ) {
2550 $object_collection = Pods\Whatsit\Store::get_instance();
2551
2552 /** @var Pods\Whatsit\Storage\Collection $storage */
2553 $storage = $object_collection->get_storage_object( 'collection' );
2554
2555 $groups = [];
2556 $fields = [];
2557
2558 foreach ( $tabs as $group_name => $group_label ) {
2559 if ( empty( $options[ $group_name ] ) ) {
2560 continue;
2561 }
2562
2563 if ( is_array( $group_label ) ) {
2564 $group_args = $group_label;
2565 } else {
2566 $group_args = [
2567 'name' => $group_name,
2568 'label' => $group_label,
2569 ];
2570 }
2571
2572 $group_args['parent'] = $parent;
2573
2574 $group = new \Pods\Whatsit\Group( $group_args );
2575
2576 $groups[] = $storage->add( $group );
2577
2578 $group_fields = $options[ $group_name ];
2579
2580 $sections = false;
2581
2582 foreach ( $group_fields as $field_name => $field_options ) {
2583 // Support sections.
2584 if ( ! isset( $field_options['label'] ) ) {
2585 $sections = true;
2586 }
2587
2588 break;
2589 }
2590
2591 $group_sections = $group_fields;
2592
2593 // Store the same whether it's a section or not.
2594 if ( ! $sections ) {
2595 $group_sections = [
2596 $group_fields,
2597 ];
2598 }
2599
2600 foreach ( $group_sections as $section_label => $section_fields ) {
2601 // Add section field (maybe).
2602 if ( ! is_int( $section_label ) ) {
2603 $field_args = [
2604 'name' => sanitize_title( $section_label ),
2605 'label' => $section_label,
2606 'type' => 'heading',
2607 'parent' => $parent,
2608 'group' => 'group/' . $parent . '/' . $group_name,
2609 ];
2610
2611 $field = new \Pods\Whatsit\Field( $field_args );
2612
2613 $fields[] = $storage->add( $field );
2614 }
2615
2616 if ( ! is_array( $section_fields ) ) {
2617 continue;
2618 }
2619
2620 // Add fields for section.
2621 foreach ( $section_fields as $field_name => $field_options ) {
2622 $boolean_group = [];
2623
2624 // Handle auto-formatting from shorthand.
2625 if ( ! empty( $field_options['boolean_group'] ) ) {
2626 $boolean_group = $field_options['boolean_group'];
2627
2628 foreach ( $boolean_group as $bgf_key => $boolean_group_field ) {
2629 // Make sure each field has a field name.
2630 if ( is_string( $bgf_key ) ) {
2631 $boolean_group[ $bgf_key ]['name'] = $bgf_key;
2632 }
2633 }
2634
2635 $boolean_group = array_values( $boolean_group );
2636
2637 $field_options['boolean_group'] = $boolean_group;
2638 }
2639
2640 if ( empty( $field_options['type'] ) ) {
2641 continue;
2642 }
2643
2644 // Set a unique field name for boolean group headings.
2645 if ( ! empty( $boolean_group ) ) {
2646 $field_options['name'] = $field_name . '_' . md5( json_encode( $boolean_group ) );
2647 }
2648
2649 $field = $this->backcompat_convert_tabs_to_groups_setup_field( [
2650 'field_name' => $field_name,
2651 'field_options' => $field_options,
2652 'parent' => $parent,
2653 'group_name' => $group_name,
2654 ] );
2655
2656 $fields[] = $storage->add( $field );
2657 }
2658 }
2659 }
2660
2661 return compact( 'groups', 'fields' );
2662 }
2663
2664 /**
2665 * Setup field for backwards compatibility tabs to groups layer.
2666 *
2667 * @since 2.8.0
2668 *
2669 * @param array $args {
2670 * The field arguments.
2671 *
2672 * @type string $field_name The field name.
2673 * @type array $field_options The field options.
2674 * @type string|int $parent The parent group.
2675 * @type string $group_name The group name.
2676 * }
2677 *
2678 * @return \Pods\Whatsit\Field The field object.
2679 */
2680 public function backcompat_convert_tabs_to_groups_setup_field( $args ) {
2681 $field_name = $args['field_name'];
2682 $field_options = $args['field_options'];
2683 $parent = $args['parent'];
2684 $group_name = $args['group_name'];
2685
2686 $field_args = $field_options;
2687
2688 if ( ! isset( $field_args['name'] ) ) {
2689 $field_args['name'] = $field_name;
2690 }
2691
2692 $field_args['parent'] = $parent;
2693 $field_args['group'] = 'group/' . $parent . '/' . $group_name;
2694
2695 $dfv_args = (object) [
2696 'id' => 0,
2697 'name' => $field_args['name'],
2698 'value' => '',
2699 'pod' => null,
2700 'type' => pods_v( 'type', $field_args ),
2701 'options' => array_merge( [
2702 'id' => 0,
2703 ], $field_args ),
2704 'build_item_data' => true,
2705 ];
2706
2707 if ( ! empty( $dfv_args->type ) ) {
2708 $field_args = PodsForm::field_method( $dfv_args->type, 'build_dfv_field_options', $field_args, $dfv_args );
2709 }
2710
2711 return new \Pods\Whatsit\Field( $field_args );
2712 }
2713
2714 /**
2715 * Duplicate a pod
2716 *
2717 * @param PodsUI $obj PodsUI object.
2718 */
2719 public function admin_setup_duplicate( $obj ) {
2720 $new_id = pods_api()->duplicate_pod( array( 'name' => $obj->row['name'] ) );
2721
2722 if ( 0 < $new_id ) {
2723 pods_redirect(
2724 pods_query_arg(
2725 array(
2726 'action' => 'edit',
2727 'id' => $new_id,
2728 'do' => 'duplicate',
2729 'name' => null,
2730 )
2731 )
2732 );
2733
2734 return;
2735 }
2736
2737 $obj->error( __( 'An error occurred, the Pod was not duplicated.', 'pods' ) );
2738 }
2739
2740 /**
2741 * Restrict Duplicate action to custom types, not extended
2742 *
2743 * @param bool $restricted Whether action is restricted.
2744 * @param array $restrict Restriction array.
2745 * @param string $action Current action.
2746 * @param array $row Item data row.
2747 * @param PodsUI $obj PodsUI object.
2748 *
2749 * @since 2.3.10
2750 *
2751 * @return bool
2752 */
2753 public function admin_setup_duplicate_restrict( $restricted, $restrict, $action, $row, $obj ) {
2754 if ( in_array(
2755 $row['real_type'], array(
2756 'user',
2757 'media',
2758 'comment',
2759 ), true
2760 ) ) {
2761 $restricted = true;
2762 }
2763
2764 return $restricted;
2765 }
2766
2767 /**
2768 * Delete a pod
2769 *
2770 * @param PodsUI $obj PodsUI object.
2771 * @param int|string $id Item ID.
2772 *
2773 * @return mixed
2774 */
2775 public function admin_setup_delete( $obj, $id ) {
2776
2777 $pod = pods_api()->load_pod( array( 'id' => $id ), false );
2778
2779 if ( empty( $pod ) ) {
2780 return $obj->error( __( 'Pod not found.', 'pods' ) );
2781 }
2782
2783 if ( 'post_type' !== $pod->get_object_storage_type() ) {
2784 return $obj->error( __( 'Pod cannot be deleted.', 'pods' ) );
2785 }
2786
2787 pods_api()->delete_pod( array( 'id' => $id ) );
2788
2789 foreach ( $obj->data as $key => $data_pod ) {
2790 if ( (int) $id === (int) $data_pod['id'] ) {
2791 unset( $obj->data[ $key ] );
2792 }
2793 }
2794
2795 $obj->total = count( $obj->data );
2796 $obj->total_found = count( $obj->data );
2797
2798 $obj->message( __( 'Pod deleted successfully.', 'pods' ) );
2799
2800 $obj->manage();
2801 }
2802
2803 /**
2804 * Handle access rights review bulk action to make public for a pod.
2805 *
2806 * @since 3.1.0
2807 *
2808 * @param int[]|string[] $ids Item IDs.
2809 * @param PodsUI $obj PodsUI object.
2810 *
2811 * @return false This always returns false unless there was a real error.
2812 */
2813 public function admin_access_rights_review_make_public_bulk( $ids, $obj ) {
2814 foreach ( $ids as $id ) {
2815 if ( ! $id ) {
2816 continue;
2817 }
2818
2819 $this->admin_access_rights_review_make_public( $obj, $id, 'bulk' );
2820 }
2821
2822 $obj->message( __( 'Selected Pod(s) made public successfully.', 'pods' ) );
2823
2824 $this->update_callout( 'access_rights', false );
2825
2826 return false;
2827 }
2828
2829 /**
2830 * Handle access rights review action to make public for a pod.
2831 *
2832 * @since 3.1.0
2833 *
2834 * @param PodsUI $obj PodsUI object.
2835 * @param int|string $id Item ID.
2836 * @param string $mode Action mode.
2837 *
2838 * @return mixed
2839 */
2840 public function admin_access_rights_review_make_public( $obj, $id, $mode = 'single' ) {
2841 $pod = pods_api()->load_pod( [ 'id' => $id ], false );
2842
2843 if ( empty( $pod ) ) {
2844 return 'bulk' !== $mode ? $obj->error( __( 'Pod not found.', 'pods' ) ) : false;
2845 }
2846
2847 if ( 'post_type' !== $pod->get_object_storage_type() || $pod->is_extended() ) {
2848 return 'bulk' !== $mode ? $obj->error( __( 'Pod cannot be modified.', 'pods' ) ) : false;
2849 }
2850
2851 $params = [
2852 'id' => $id,
2853 'public' => 1,
2854 ];
2855
2856 if ( in_array( $pod->get_type(), [ 'post_type', 'taxonomy' ], true ) ) {
2857 $params['publicly_queryable'] = 1;
2858 }
2859
2860 pods_api()->save_pod( $params );
2861
2862 foreach ( $obj->data as $key => $data_pod ) {
2863 if ( (int) $id === (int) $data_pod['id'] ) {
2864 $obj->data[ $key ]['public'] = __( 'Public', 'pods' );
2865 $obj->data[ $key ]['real_public'] = 1;
2866 }
2867 }
2868
2869 if ( 'bulk' !== $mode ) {
2870 $obj->message( __( 'Pod made public successfully.', 'pods' ) );
2871
2872 $this->update_callout( 'access_rights', false );
2873
2874 $obj->manage();
2875 }
2876 }
2877
2878 /**
2879 * Handle access rights review bulk action to make private for a pod.
2880 *
2881 * @since 3.1.0
2882 *
2883 * @param int[]|string[] $ids Item IDs.
2884 * @param PodsUI $obj PodsUI object.
2885 *
2886 * @return false This always returns false unless there was a real error.
2887 */
2888 public function admin_access_rights_review_make_private_bulk( $ids, $obj ) {
2889 foreach ( $ids as $id ) {
2890 if ( ! $id ) {
2891 continue;
2892 }
2893
2894 $this->admin_access_rights_review_make_private( $obj, $id, 'bulk' );
2895 }
2896
2897 $obj->message( __( 'Selected Pod(s) made private successfully.', 'pods' ) );
2898
2899 $this->update_callout( 'access_rights', false );
2900
2901 return false;
2902 }
2903
2904 /**
2905 * Handle access rights review action to make private for a pod.
2906 *
2907 * @since 3.1.0
2908 *
2909 * @param PodsUI $obj PodsUI object.
2910 * @param int|string $id Item ID.
2911 * @param string $mode Action mode.
2912 *
2913 * @return mixed
2914 */
2915 public function admin_access_rights_review_make_private( $obj, $id, $mode = 'single' ) {
2916 $pod = pods_api()->load_pod( [ 'id' => $id ], false );
2917
2918 if ( empty( $pod ) ) {
2919 return 'bulk' !== $mode ? $obj->error( __( 'Pod not found.', 'pods' ) ) : false;
2920 }
2921
2922 if ( 'post_type' !== $pod->get_object_storage_type() || $pod->is_extended() ) {
2923 return 'bulk' !== $mode ? $obj->error( __( 'Pod cannot be modified.', 'pods' ) ) : false;
2924 }
2925
2926 $params = [
2927 'id' => $id,
2928 ];
2929
2930 if ( in_array( $pod->get_type(), [ 'post_type', 'taxonomy' ], true ) ) {
2931 $params['publicly_queryable'] = 0;
2932 } else {
2933 $params['public'] = 0;
2934 }
2935
2936 pods_api()->save_pod( $params );
2937
2938 foreach ( $obj->data as $key => $data_pod ) {
2939 if ( (int) $id === (int) $data_pod['id'] ) {
2940 $obj->data[ $key ]['public'] = '🔒 ' . __( 'Private', 'pods' );
2941 $obj->data[ $key ]['real_public'] = 0;
2942 }
2943 }
2944
2945 if ( 'bulk' !== $mode ) {
2946 $obj->message( __( 'Pod made private successfully.', 'pods' ) );
2947
2948 $this->update_callout( 'access_rights', false );
2949
2950 $obj->manage();
2951 }
2952 }
2953
2954 /**
2955 * Handle access rights review bulk action to restrict dynamic features for a pod.
2956 *
2957 * @since 3.1.0
2958 *
2959 * @param int[]|string[] $ids Item IDs.
2960 * @param PodsUI $obj PodsUI object.
2961 *
2962 * @return false This always returns false unless there was a real error.
2963 */
2964 public function admin_access_rights_review_restrict_dynamic_features_bulk( $ids, $obj ) {
2965 foreach ( $ids as $id ) {
2966 if ( ! $id ) {
2967 continue;
2968 }
2969
2970 $this->admin_access_rights_review_restrict_dynamic_features( $obj, $id, 'bulk' );
2971 }
2972
2973 $obj->message( __( 'Selected Pod(s) restricted dynamic features successfully.', 'pods' ) );
2974
2975 $this->update_callout( 'access_rights', false );
2976
2977 return false;
2978 }
2979
2980 /**
2981 * Handle access rights review action to restrict dynamic features for a pod.
2982 *
2983 * @since 3.1.0
2984 *
2985 * @param PodsUI $obj PodsUI object.
2986 * @param int|string $id Item ID.
2987 * @param string $mode Action mode.
2988 *
2989 * @return mixed
2990 */
2991 public function admin_access_rights_review_restrict_dynamic_features( $obj, $id, $mode = 'single' ) {
2992 $pod = pods_api()->load_pod( [ 'id' => $id ], false );
2993
2994 if ( empty( $pod ) ) {
2995 return 'bulk' !== $mode ? $obj->error( __( 'Pod not found.', 'pods' ) ) : false;
2996 }
2997
2998 if ( 'post_type' !== $pod->get_object_storage_type() ) {
2999 return 'bulk' !== $mode ? $obj->error( __( 'Pod cannot be modified.', 'pods' ) ) : false;
3000 }
3001
3002 pods_api()->save_pod( [
3003 'id' => $id,
3004 'restrict_dynamic_features' => '1',
3005 'restricted_dynamic_features' => [
3006 'display',
3007 'form',
3008 ],
3009 ] );
3010
3011 foreach ( $obj->data as $key => $data_pod ) {
3012 if ( (int) $id === (int) $data_pod['id'] ) {
3013 $obj->data[ $key ]['restricted_dynamic_features'] = pods_access_get_restricted_dynamic_features_options();
3014
3015 $obj->data[ $key ]['real_restricted_dynamic_features'] = 'restricted';
3016 }
3017 }
3018
3019 if ( 'bulk' !== $mode ) {
3020 $obj->message( __( 'Pod restricted dynamic features successfully.', 'pods' ) );
3021
3022 $this->update_callout( 'access_rights', false );
3023
3024 $obj->manage();
3025 }
3026 }
3027
3028 /**
3029 * Handle access rights review bulk action to restrict dynamic features for a pod.
3030 *
3031 * @since 3.1.0
3032 *
3033 * @param int[]|string[] $ids Item IDs.
3034 * @param PodsUI $obj PodsUI object.
3035 *
3036 * @return false This always returns false unless there was a real error.
3037 */
3038 public function admin_access_rights_review_unrestrict_dynamic_features_bulk( $ids, $obj ) {
3039 foreach ( $ids as $id ) {
3040 if ( ! $id ) {
3041 continue;
3042 }
3043
3044 $this->admin_access_rights_review_unrestrict_dynamic_features( $obj, $id, 'bulk' );
3045 }
3046
3047 $obj->message( __( 'Selected Pod(s) unrestricted dynamic features successfully.', 'pods' ) );
3048
3049 $this->update_callout( 'access_rights', false );
3050
3051 return false;
3052 }
3053
3054 /**
3055 * Handle access rights review action to unrestrict dynamic features for a pod.
3056 *
3057 * @since 3.1.0
3058 *
3059 * @param PodsUI $obj PodsUI object.
3060 * @param int|string $id Item ID.
3061 * @param string $mode Action mode.
3062 *
3063 * @return mixed
3064 */
3065 public function admin_access_rights_review_unrestrict_dynamic_features( $obj, $id, $mode = 'single' ) {
3066 $pod = pods_api()->load_pod( [ 'id' => $id ], false );
3067
3068 if ( empty( $pod ) ) {
3069 return 'bulk' !== $mode ? $obj->error( __( 'Pod not found.', 'pods' ) ) : false;
3070 }
3071
3072 if ( 'post_type' !== $pod->get_object_storage_type() ) {
3073 return 'bulk' !== $mode ? $obj->error( __( 'Pod cannot be modified.', 'pods' ) ) : false;
3074 }
3075
3076 pods_api()->save_pod( [
3077 'id' => $id,
3078 'restrict_dynamic_features' => '0',
3079 'restricted_dynamic_features' => [],
3080 ] );
3081
3082 foreach ( $obj->data as $key => $data_pod ) {
3083 if ( (int) $id === (int) $data_pod['id'] ) {
3084 $obj->data[ $key ]['restricted_dynamic_features'] = __( 'Unrestricted', 'pods' );
3085 $obj->data[ $key ]['real_restricted_dynamic_features'] = 'unrestricted';
3086 }
3087 }
3088
3089 if ( 'bulk' !== $mode ) {
3090 $obj->message( __( 'Pod unrestricted dynamic features successfully.', 'pods' ) );
3091
3092 $this->update_callout( 'access_rights', false );
3093
3094 $obj->manage();
3095 }
3096 }
3097
3098 /**
3099 * Restrict actions that can't be done for Pods with a non DB source.
3100 *
3101 * @since 3.1.0
3102 *
3103 * @param bool $restricted Whether action is restricted.
3104 * @param array $restrict Restriction array.
3105 * @param string $action Current action.
3106 * @param array $row Item data row.
3107 * @param PodsUI $obj PodsUI object.
3108 *
3109 * @return bool Whether the action is restricted.
3110 */
3111 public function admin_restrict_non_db_type( $restricted, $restrict, $action, $row, $obj ) {
3112 if ( __( 'DB', 'pods' ) !== $row['source'] ) {
3113 $restricted = true;
3114 }
3115
3116 return $restricted;
3117 }
3118
3119 /**
3120 * Restrict actions that can't be done for Pods with a non DB source.
3121 *
3122 * @since 3.1.0
3123 *
3124 * @param bool $restricted Whether action is restricted.
3125 * @param array $restrict Restriction array.
3126 * @param string $action Current action.
3127 * @param array $row Item data row.
3128 * @param PodsUI $obj PodsUI object.
3129 *
3130 * @return bool Whether the action is restricted.
3131 */
3132 public function admin_restrict_access_rights_review_make_public( $restricted, $restrict, $action, $row, $obj ) {
3133 $restricted = $this->admin_restrict_non_db_type( $restricted, $restrict, $action, $row, $obj );
3134
3135 if (
3136 ! $restricted
3137 && (
3138 1 === $row['real_public']
3139 || $row['pod_object']->is_extended()
3140 )
3141 ) {
3142 $restricted = true;
3143 }
3144
3145 return $restricted;
3146 }
3147
3148 /**
3149 * Restrict actions that can't be done for Pods with a non DB source.
3150 *
3151 * @since 3.1.0
3152 *
3153 * @param bool $restricted Whether action is restricted.
3154 * @param array $restrict Restriction array.
3155 * @param string $action Current action.
3156 * @param array $row Item data row.
3157 * @param PodsUI $obj PodsUI object.
3158 *
3159 * @return bool Whether the action is restricted.
3160 */
3161 public function admin_restrict_access_rights_review_make_private( $restricted, $restrict, $action, $row, $obj ) {
3162 $restricted = $this->admin_restrict_non_db_type( $restricted, $restrict, $action, $row, $obj );
3163
3164 if (
3165 ! $restricted
3166 && (
3167 0 === $row['real_public']
3168 || $row['pod_object']->is_extended()
3169 )
3170 ) {
3171 $restricted = true;
3172 }
3173
3174 return $restricted;
3175 }
3176
3177 /**
3178 * Restrict actions that can't be done for Pods with a non DB source.
3179 *
3180 * @since 3.1.0
3181 *
3182 * @param bool $restricted Whether action is restricted.
3183 * @param array $restrict Restriction array.
3184 * @param string $action Current action.
3185 * @param array $row Item data row.
3186 * @param PodsUI $obj PodsUI object.
3187 *
3188 * @return bool Whether the action is restricted.
3189 */
3190 public function admin_restrict_access_rights_review_restrict_dynamic_features( $restricted, $restrict, $action, $row, $obj ) {
3191 $restricted = $this->admin_restrict_non_db_type( $restricted, $restrict, $action, $row, $obj );
3192
3193 if ( ! $restricted && 'restricted' === $row['real_restricted_dynamic_features'] ) {
3194 $restricted = true;
3195 }
3196
3197 return $restricted;
3198 }
3199
3200 /**
3201 * Handle access rights review bulk action to set dynamic features as WP Default for a pod.
3202 *
3203 * @since 3.1.0
3204 *
3205 * @param int[]|string[] $ids Item IDs.
3206 * @param PodsUI $obj PodsUI object.
3207 *
3208 * @return false This always returns false unless there was a real error.
3209 */
3210 public function admin_access_rights_review_wp_default_dynamic_features_bulk( $ids, $obj ) {
3211 foreach ( $ids as $id ) {
3212 if ( ! $id ) {
3213 continue;
3214 }
3215
3216 $this->admin_access_rights_review_wp_default_dynamic_features( $obj, $id, 'bulk' );
3217 }
3218
3219 $obj->message( __( 'Selected Pod(s) Dynamic Features set to WP Default successfully.', 'pods' ) );
3220
3221 $this->update_callout( 'access_rights', false );
3222
3223 return false;
3224 }
3225
3226 /**
3227 * Handle access rights review bulk action to set dynamic features as WP Default for a pod.
3228 *
3229 * @since 3.1.0
3230 *
3231 * @param PodsUI $obj PodsUI object.
3232 * @param int|string $id Item ID.
3233 * @param string $mode Action mode.
3234 *
3235 * @return mixed
3236 */
3237 public function admin_access_rights_review_wp_default_dynamic_features( $obj, $id, $mode = 'single' ) {
3238 $pod = pods_api()->load_pod( [ 'id' => $id ], false );
3239
3240 if ( empty( $pod ) ) {
3241 return 'bulk' !== $mode ? $obj->error( __( 'Pod not found.', 'pods' ) ) : false;
3242 }
3243
3244 if ( 'post_type' !== $pod->get_object_storage_type() || $pod->is_extended() ) {
3245 return 'bulk' !== $mode ? $obj->error( __( 'Pod cannot be modified.', 'pods' ) ) : false;
3246 }
3247
3248 $is_public = pods_is_type_public(
3249 [
3250 'pod' => $pod,
3251 ]
3252 );
3253
3254 $options = pods_access_get_dynamic_features_allow_options();
3255 $value = 'inherit';
3256 $label = $options[ $value ] . ' - ' . ( $is_public ? $options['1'] : $options['0'] );
3257
3258 pods_api()->save_pod( [ 'id' => $id, 'dynamic_features_allow' => $value ] );
3259
3260 foreach ( $obj->data as $key => $data_pod ) {
3261 if ( (int) $id === (int) $data_pod['id'] ) {
3262 $obj->data[ $key ]['dynamic_features_allow'] = $label;
3263 $obj->data[ $key ]['real_dynamic_features_allow'] = $value;
3264 }
3265 }
3266
3267 if ( 'bulk' !== $mode ) {
3268 $obj->message( __( 'Pod Dynamic Features set to WP Default successfully.', 'pods' ) );
3269
3270 $this->update_callout( 'access_rights', false );
3271
3272 $obj->manage();
3273 }
3274 }
3275
3276 /**
3277 * Restrict actions that can't be done for Pods with a non DB source.
3278 *
3279 * @since 3.1.0
3280 *
3281 * @param bool $restricted Whether action is restricted.
3282 * @param array $restrict Restriction array.
3283 * @param string $action Current action.
3284 * @param array $row Item data row.
3285 * @param PodsUI $obj PodsUI object.
3286 *
3287 * @return bool Whether the action is restricted.
3288 */
3289 public function admin_restrict_access_rights_review_wp_default_dynamic_features( $restricted, $restrict, $action, $row, $obj ) {
3290 $restricted = $this->admin_restrict_non_db_type( $restricted, $restrict, $action, $row, $obj );
3291
3292 if ( ! $restricted && 'inherit' === $row['real_dynamic_features_allow'] ) {
3293 $restricted = true;
3294 }
3295
3296 return $restricted;
3297 }
3298
3299 /**
3300 * Handle access rights review bulk action to set dynamic features as enabled for a pod.
3301 *
3302 * @since 3.1.0
3303 *
3304 * @param int[]|string[] $ids Item IDs.
3305 * @param PodsUI $obj PodsUI object.
3306 *
3307 * @return false This always returns false unless there was a real error.
3308 */
3309 public function admin_access_rights_review_enable_dynamic_features_bulk( $ids, $obj ) {
3310 foreach ( $ids as $id ) {
3311 if ( ! $id ) {
3312 continue;
3313 }
3314
3315 $this->admin_access_rights_review_enable_dynamic_features( $obj, $id, 'bulk' );
3316 }
3317
3318 $obj->message( __( 'Selected Pod(s) Dynamic Features set to Enabled successfully.', 'pods' ) );
3319
3320 $this->update_callout( 'access_rights', false );
3321
3322 return false;
3323 }
3324
3325 /**
3326 * Handle access rights review bulk action to set dynamic features as enabled for a pod.
3327 *
3328 * @since 3.1.0
3329 *
3330 * @param PodsUI $obj PodsUI object.
3331 * @param int|string $id Item ID.
3332 * @param string $mode Action mode.
3333 *
3334 * @return mixed
3335 */
3336 public function admin_access_rights_review_enable_dynamic_features( $obj, $id, $mode = 'single' ) {
3337 $pod = pods_api()->load_pod( [ 'id' => $id ], false );
3338
3339 if ( empty( $pod ) ) {
3340 return 'bulk' !== $mode ? $obj->error( __( 'Pod not found.', 'pods' ) ) : false;
3341 }
3342
3343 if ( 'post_type' !== $pod->get_object_storage_type() || $pod->is_extended() ) {
3344 return 'bulk' !== $mode ? $obj->error( __( 'Pod cannot be modified.', 'pods' ) ) : false;
3345 }
3346
3347 $options = pods_access_get_dynamic_features_allow_options();
3348 $value = '1';
3349 $label = $options[ $value ];
3350
3351 pods_api()->save_pod( [ 'id' => $id, 'dynamic_features_allow' => $value ] );
3352
3353 foreach ( $obj->data as $key => $data_pod ) {
3354 if ( (int) $id === (int) $data_pod['id'] ) {
3355 $obj->data[ $key ]['dynamic_features_allow'] = $label;
3356 $obj->data[ $key ]['real_dynamic_features_allow'] = $value;
3357 }
3358 }
3359
3360 if ( 'bulk' !== $mode ) {
3361 $obj->message( __( 'Pod Dynamic Features set to Enabled successfully.', 'pods' ) );
3362
3363 $this->update_callout( 'access_rights', false );
3364
3365 $obj->manage();
3366 }
3367 }
3368
3369 /**
3370 * Restrict actions that can't be done for Pods with a non DB source.
3371 *
3372 * @since 3.1.0
3373 *
3374 * @param bool $restricted Whether action is restricted.
3375 * @param array $restrict Restriction array.
3376 * @param string $action Current action.
3377 * @param array $row Item data row.
3378 * @param PodsUI $obj PodsUI object.
3379 *
3380 * @return bool Whether the action is restricted.
3381 */
3382 public function admin_restrict_access_rights_review_enable_dynamic_features( $restricted, $restrict, $action, $row, $obj ) {
3383 $restricted = $this->admin_restrict_non_db_type( $restricted, $restrict, $action, $row, $obj );
3384
3385 if ( ! $restricted && '1' === $row['real_dynamic_features_allow'] ) {
3386 $restricted = true;
3387 }
3388
3389 return $restricted;
3390 }
3391
3392 /**
3393 * Handle access rights review bulk action to set dynamic features as disabled for a pod.
3394 *
3395 * @since 3.1.0
3396 *
3397 * @param int[]|string[] $ids Item IDs.
3398 * @param PodsUI $obj PodsUI object.
3399 *
3400 * @return false This always returns false unless there was a real error.
3401 */
3402 public function admin_access_rights_review_disable_dynamic_features_bulk( $ids, $obj ) {
3403 foreach ( $ids as $id ) {
3404 if ( ! $id ) {
3405 continue;
3406 }
3407
3408 $this->admin_access_rights_review_disable_dynamic_features( $obj, $id, 'bulk' );
3409 }
3410
3411 $obj->message( __( 'Selected Pod(s) Dynamic Features set to Disabled successfully.', 'pods' ) );
3412
3413 $this->update_callout( 'access_rights', false );
3414
3415 return false;
3416 }
3417
3418 /**
3419 * Handle access rights review bulk action to set dynamic features as disabled for a pod.
3420 *
3421 * @since 3.1.0
3422 *
3423 * @param PodsUI $obj PodsUI object.
3424 * @param int|string $id Item ID.
3425 * @param string $mode Action mode.
3426 *
3427 * @return mixed
3428 */
3429 public function admin_access_rights_review_disable_dynamic_features( $obj, $id, $mode = 'single' ) {
3430 $pod = pods_api()->load_pod( [ 'id' => $id ], false );
3431
3432 if ( empty( $pod ) ) {
3433 return 'bulk' !== $mode ? $obj->error( __( 'Pod not found.', 'pods' ) ) : false;
3434 }
3435
3436 if ( 'post_type' !== $pod->get_object_storage_type() || $pod->is_extended() ) {
3437 return 'bulk' !== $mode ? $obj->error( __( 'Pod cannot be modified.', 'pods' ) ) : false;
3438 }
3439
3440 $options = pods_access_get_dynamic_features_allow_options();
3441 $value = '0';
3442 $label = $options[ $value ];
3443
3444 pods_api()->save_pod( [ 'id' => $id, 'dynamic_features_allow' => $value ] );
3445
3446 foreach ( $obj->data as $key => $data_pod ) {
3447 if ( (int) $id === (int) $data_pod['id'] ) {
3448 $obj->data[ $key ]['dynamic_features_allow'] = $label;
3449 $obj->data[ $key ]['real_dynamic_features_allow'] = $value;
3450 }
3451 }
3452
3453 if ( 'bulk' !== $mode ) {
3454 $obj->message( __( 'Pod Dynamic Features set to Disabled successfully.', 'pods' ) );
3455
3456 $this->update_callout( 'access_rights', false );
3457
3458 $obj->manage();
3459 }
3460 }
3461
3462 /**
3463 * Restrict actions that can't be done for Pods with a non DB source.
3464 *
3465 * @since 3.1.0
3466 *
3467 * @param bool $restricted Whether action is restricted.
3468 * @param array $restrict Restriction array.
3469 * @param string $action Current action.
3470 * @param array $row Item data row.
3471 * @param PodsUI $obj PodsUI object.
3472 *
3473 * @return bool Whether the action is restricted.
3474 */
3475 public function admin_restrict_access_rights_review_disable_dynamic_features( $restricted, $restrict, $action, $row, $obj ) {
3476 $restricted = $this->admin_restrict_non_db_type( $restricted, $restrict, $action, $row, $obj );
3477
3478 if ( ! $restricted && '0' === $row['real_dynamic_features_allow'] ) {
3479 $restricted = true;
3480 }
3481
3482 return $restricted;
3483 }
3484
3485 /**
3486 * Restrict actions that can't be done for Pods with a non DB source.
3487 *
3488 * @since 3.1.0
3489 *
3490 * @param bool $restricted Whether action is restricted.
3491 * @param array $restrict Restriction array.
3492 * @param string $action Current action.
3493 * @param array $row Item data row.
3494 * @param PodsUI $obj PodsUI object.
3495 *
3496 * @return bool Whether the action is restricted.
3497 */
3498 public function admin_restrict_access_rights_review_unrestrict_dynamic_features( $restricted, $restrict, $action, $row, $obj ) {
3499 $restricted = $this->admin_restrict_non_db_type( $restricted, $restrict, $action, $row, $obj );
3500
3501 if ( ! $restricted && 'unrestricted' === $row['real_restricted_dynamic_features'] ) {
3502 $restricted = true;
3503 }
3504
3505 return $restricted;
3506 }
3507
3508 /**
3509 * Get advanced administration view.
3510 */
3511 public function admin_advanced() {
3512
3513 pods_view( PODS_DIR . 'ui/admin/advanced.php', compact( array_keys( get_defined_vars() ) ) );
3514 }
3515
3516 /**
3517 * Get settings administration view
3518 */
3519 public function admin_settings() {
3520 // Add our custom callouts.
3521 $this->handle_callouts_updates();
3522
3523 /**
3524 * Allow hooking into our settings page to set up hooks.
3525 *
3526 * @since 2.8.0
3527 */
3528 do_action( 'pods_admin_settings_init' );
3529
3530 // Add our custom callouts.
3531 if ( $this->has_horizontal_callout() ) {
3532 add_action( 'pods_admin_before_settings', [ $this, 'admin_manage_callouts' ] );
3533 } else {
3534 add_action( 'pods_admin_after_settings', [ $this, 'admin_manage_callouts' ] );
3535 }
3536
3537 pods_view( PODS_DIR . 'ui/admin/settings.php', compact( array_keys( get_defined_vars() ) ) );
3538 }
3539
3540 /**
3541 * Get components administration UI
3542 */
3543 public function admin_components() {
3544
3545 if ( ! is_object( PodsInit::$components ) ) {
3546 return;
3547 }
3548
3549 $components = PodsInit::$components->components;
3550
3551 $view = pods_v( 'view', 'get', 'all', true );
3552
3553 $recommended = array(
3554 'advanced-relationships',
3555 'advanced-content-types',
3556 'migrate-packages',
3557 'roles-and-capabilities',
3558 'pages',
3559 'table-storage',
3560 'templates',
3561 );
3562
3563 foreach ( $components as $component => &$component_data ) {
3564 if ( ! in_array(
3565 $view, array(
3566 'all',
3567 'recommended',
3568 'dev',
3569 ), true
3570 ) && ( ! isset( $component_data['Category'] ) || sanitize_title( $component_data['Category'] ) !== $view ) ) {
3571 unset( $components[ $component ] );
3572
3573 continue;
3574 } elseif ( 'recommended' === $view && ! in_array( $component_data['ID'], $recommended, true ) ) {
3575 unset( $components[ $component ] );
3576
3577 continue;
3578 } elseif ( 'dev' === $view && pods_developer() && ! pods_v( 'DeveloperMode', $component_data, false ) ) {
3579 unset( $components[ $component ] );
3580
3581 continue;
3582 } elseif ( pods_v( 'DeveloperMode', $component_data, false ) && ! pods_developer() ) {
3583 unset( $components[ $component ] );
3584
3585 continue;
3586 } elseif ( ! pods_v( 'TablelessMode', $component_data, false ) && pods_tableless() ) {
3587 unset( $components[ $component ] );
3588
3589 continue;
3590 }//end if
3591
3592 $component_data['Name'] = strip_tags( $component_data['Name'] );
3593
3594 if ( pods_v( 'DeveloperMode', $component_data, false ) ) {
3595 $component_data['Name'] .= ' <em style="font-weight: normal; color:#333;">(Developer Preview)</em>';
3596 }
3597
3598 $meta = array();
3599
3600 if ( ! empty( $component_data['Version'] ) ) {
3601 $meta[] = sprintf( __( 'Version %s', 'pods' ), $component_data['Version'] );
3602 }
3603
3604 if ( empty( $component_data['Author'] ) ) {
3605 $component_data['Author'] = 'Pods Framework Team';
3606 $component_data['AuthorURI'] = 'https://pods.io/';
3607 }
3608
3609 if ( ! empty( $component_data['AuthorURI'] ) ) {
3610 $component_data['Author'] = '<a href="' . $component_data['AuthorURI'] . '">' . $component_data['Author'] . '</a>';
3611 }
3612
3613 $meta[] = sprintf( __( 'by %s', 'pods' ), $component_data['Author'] );
3614
3615 if ( ! empty( $component_data['URI'] ) ) {
3616 $meta[] = '<a href="' . $component_data['URI'] . '">' . __( 'Visit component site', 'pods' ) . '</a>';
3617 }
3618
3619 if ( pods_is_truthy( pods_v( 'Deprecated', $component_data, false ) ) ) {
3620 $deprecated = __( 'Deprecated', 'pods' );
3621
3622 $component_data['Name'] .= sprintf(
3623 ' <em style="font-weight: normal; color:#333;">(%s)</em>',
3624 $deprecated
3625 );
3626
3627 $deprecated_in_version = pods_v( 'DeprecatedInVersion', $component_data );
3628 $deprecated_removal_version = pods_v( 'DeprecatedRemovalVersion', $component_data );
3629
3630 if ( empty( $deprecated_removal_version ) ) {
3631 // translators: TBD means To Be Determined.
3632 $deprecated_removal_version = __( 'TBD', 'pods' );
3633 }
3634
3635 if ( $deprecated_in_version ) {
3636 $deprecated = sprintf(
3637 // translators: %1$s is the version the deprecation starts and %2$s is the version the code will be removed.
3638 __( 'Deprecated in %1$s, will be removed in %2$s', 'pods' ),
3639 $deprecated_in_version,
3640 $deprecated_removal_version
3641 );
3642 }
3643
3644 $meta[] = $deprecated;
3645 }
3646
3647 $component_data['Description'] = wpautop( trim( make_clickable( strip_tags( $component_data['Description'], 'em,strong' ) ) ) );
3648
3649 if ( ! empty( $meta ) ) {
3650 $description_style = '';
3651
3652 if ( ! empty( $component_data['Description'] ) ) {
3653 $description_style = ' style="padding:8px 0 4px;"';
3654 }
3655
3656 $component_data['Description'] .= '<div class="pods-component-meta" ' . $description_style . '>' . implode( '&nbsp;&nbsp;|&nbsp;&nbsp;', $meta ) . '</div>';
3657 }
3658
3659 $component_data = array(
3660 'id' => $component_data['ID'],
3661 'name' => $component_data['Name'],
3662 'category' => $component_data['Category'],
3663 'version' => '',
3664 'description' => $component_data['Description'],
3665 'mustuse' => pods_v( 'MustUse', $component_data, false ),
3666 'toggle' => 0,
3667 );
3668
3669 if ( ! empty( $component_data['category'] ) ) {
3670 $category_url = pods_query_arg(
3671 array(
3672 'view' => sanitize_title( $component_data['category'] ),
3673 'pg' => '',
3674 // @codingStandardsIgnoreLine
3675 'page' => $_GET['page'],
3676 )
3677 );
3678
3679 $component_data['category'] = '<a href="' . esc_url( $category_url ) . '">' . $component_data['category'] . '</a>';
3680 }
3681
3682 if ( isset( PodsInit::$components->settings['components'][ $component_data['id'] ] ) && 0 !== PodsInit::$components->settings['components'][ $component_data['id'] ] ) {
3683 $component_data['toggle'] = 1;
3684 } elseif ( $component_data['mustuse'] ) {
3685 $component_data['toggle'] = 1;
3686 }
3687 }//end foreach
3688
3689 $ui = array(
3690 'sql' => array(
3691 'field_id' => 'id',
3692 ),
3693 'data' => $components,
3694 'total' => count( $components ),
3695 'total_found' => count( $components ),
3696 'items' => __( 'Components', 'pods' ),
3697 'item' => __( 'Component', 'pods' ),
3698 'fields' => array(
3699 'manage' => array(
3700 'name' => array(
3701 'label' => __( 'Name', 'pods' ),
3702 'width' => '30%',
3703 'type' => 'text',
3704 'options' => array(
3705 'text_allow_html' => true,
3706 ),
3707 ),
3708 'category' => array(
3709 'label' => __( 'Category', 'pods' ),
3710 'width' => '10%',
3711 'type' => 'text',
3712 'options' => array(
3713 'text_allow_html' => true,
3714 ),
3715 ),
3716 'description' => array(
3717 'label' => __( 'Description', 'pods' ),
3718 'width' => '60%',
3719 'type' => 'text',
3720 'options' => array(
3721 'text_allow_html' => true,
3722 'text_allowed_html_tags' => 'strong em a ul ol li b i br div',
3723 ),
3724 ),
3725 ),
3726 ),
3727 'actions_disabled' => array( 'duplicate', 'view', 'export', 'add', 'edit', 'delete' ),
3728 'actions_custom' => array(
3729 'toggle' => array(
3730 'callback' => array( $this, 'admin_components_toggle' ),
3731 'nonce' => true,
3732 ),
3733 ),
3734 'filters_enhanced' => true,
3735 'views' => array(
3736 'all' => __( 'All', 'pods' ),
3737 // 'recommended' => __( 'Recommended', 'pods' ),
3738 'field-types' => __( 'Field Types', 'pods' ),
3739 'tools' => __( 'Tools', 'pods' ),
3740 'integration' => __( 'Integration', 'pods' ),
3741 'migration' => __( 'Migration', 'pods' ),
3742 'advanced' => __( 'Advanced', 'pods' ),
3743 ),
3744 'view' => $view,
3745 'heading' => array(
3746 'views' => __( 'Category', 'pods' ),
3747 ),
3748 'search' => false,
3749 'searchable' => false,
3750 'sortable' => false,
3751 'pagination' => false,
3752 );
3753
3754 if ( pods_developer() ) {
3755 $ui['views']['dev'] = __( 'Developer Preview', 'pods' );
3756 }
3757
3758 // Add our custom callouts.
3759 $this->handle_callouts_updates();
3760
3761 add_filter( 'pods_ui_manage_custom_container_classes', array( $this, 'admin_manage_container_class' ) );
3762
3763 if ( $this->has_horizontal_callout() ) {
3764 add_action( 'pods_ui_manage_before_container', [ $this, 'admin_manage_callouts' ] );
3765 } else {
3766 add_action( 'pods_ui_manage_after_container', [ $this, 'admin_manage_callouts' ] );
3767 }
3768
3769 pods_ui( $ui );
3770 }
3771
3772 /**
3773 * Toggle a component on or off
3774 *
3775 * @param PodsUI $ui PodsUI object.
3776 */
3777 public function admin_components_toggle( $ui ) {
3778 $component = pods_v( 'id' );
3779
3780 if ( ! empty( PodsInit::$components->components[ $component ]['PluginDependency'] ) ) {
3781 $dependency = explode( '|', PodsInit::$components->components[ $component ]['PluginDependency'] );
3782
3783 if ( ! pods_is_plugin_active( $dependency[1] ) ) {
3784 $website = 'http://wordpress.org/extend/plugins/' . dirname( $dependency[1] ) . '/';
3785
3786 if ( isset( $dependency[2] ) ) {
3787 $website = $dependency[2];
3788 }
3789
3790 if ( ! empty( $website ) ) {
3791 $website = ' ' . sprintf( __( 'You can find it at %s', 'pods' ), '<a href="' . $website . '" target="_blank" rel="noopener noreferrer">' . $website . '</a>' );
3792 }
3793
3794 $message = sprintf( __( 'The %1$s component requires that you have the <strong>%2$s</strong> plugin installed and activated.', 'pods' ), PodsInit::$components->components[ $component ]['Name'], $dependency[0] ) . $website;
3795
3796 $ui->error( $message );
3797
3798 $ui->manage();
3799
3800 return;
3801 }
3802 }//end if
3803
3804 if ( ! empty( PodsInit::$components->components[ $component ]['ThemeDependency'] ) ) {
3805 $dependency = explode( '|', PodsInit::$components->components[ $component ]['ThemeDependency'] );
3806
3807 $check = strtolower( $dependency[1] );
3808
3809 if ( strtolower( get_template() ) !== $check && strtolower( get_stylesheet() ) !== $check ) {
3810 $website = '';
3811
3812 if ( isset( $dependency[2] ) ) {
3813 $website = ' ' . sprintf( __( 'You can find it at %s', 'pods' ), '<a href="' . $dependency[2] . '" target="_blank" rel="noopener noreferrer">' . $dependency[2] . '</a>' );
3814 }
3815
3816 $message = sprintf( __( 'The %1$s component requires that you have the <strong>%2$s</strong> theme installed and activated.', 'pods' ), PodsInit::$components->components[ $component ]['Name'], $dependency[0] ) . $website;
3817
3818 $ui->error( $message );
3819
3820 $ui->manage();
3821
3822 return;
3823 }
3824 }//end if
3825
3826 if ( ! empty( PodsInit::$components->components[ $component ]['MustUse'] ) ) {
3827 $message = sprintf( __( 'The %s component can not be disabled from here. You must deactivate the plugin or theme that added it.', 'pods' ), PodsInit::$components->components[ $component ]['Name'] );
3828
3829 $ui->error( $message );
3830
3831 $ui->manage();
3832
3833 return;
3834 }
3835
3836 if ( 1 === (int) pods_v( 'toggled' ) ) {
3837 $toggle = PodsInit::$components->toggle( $component );
3838
3839 if ( true === $toggle ) {
3840 $ui->message( PodsInit::$components->components[ $component ]['Name'] . ' ' . __( 'Component enabled', 'pods' ) );
3841 } elseif ( false === $toggle ) {
3842 $ui->message( PodsInit::$components->components[ $component ]['Name'] . ' ' . __( 'Component disabled', 'pods' ) );
3843 }
3844
3845 $components = PodsInit::$components->components;
3846
3847 foreach ( $components as $component => &$component_data ) {
3848 $toggle = 0;
3849
3850 if ( isset( PodsInit::$components->settings['components'][ $component_data['ID'] ] ) ) {
3851 if ( 0 !== PodsInit::$components->settings['components'][ $component_data['ID'] ] ) {
3852 $toggle = 1;
3853 }
3854 }
3855 if ( true === $component_data['DeveloperMode'] ) {
3856 if ( ! pods_developer() ) {
3857 unset( $components[ $component ] );
3858 continue;
3859 }
3860 }
3861
3862 $component_data = array(
3863 'id' => $component_data['ID'],
3864 'name' => $component_data['Name'],
3865 'description' => make_clickable( $component_data['Description'] ),
3866 'version' => $component_data['Version'],
3867 'author' => $component_data['Author'],
3868 'toggle' => $toggle,
3869 );
3870 }//end foreach
3871
3872 $ui->data = $components;
3873
3874 pods_transient_clear( 'pods_components' );
3875
3876 $url = pods_query_arg( array( 'toggled' => null ) );
3877
3878 pods_redirect( $url );
3879 } elseif ( 1 === (int) pods_v( 'toggle' ) ) {
3880 $ui->message( PodsInit::$components->components[ $component ]['Name'] . ' ' . __( 'Component enabled', 'pods' ) );
3881 } else {
3882 $ui->message( PodsInit::$components->components[ $component ]['Name'] . ' ' . __( 'Component disabled', 'pods' ) );
3883 }//end if
3884
3885 $ui->manage();
3886 }
3887
3888 /**
3889 * Get the admin upgrade page
3890 */
3891 public function admin_upgrade() {
3892
3893 foreach ( PodsInit::$upgrades as $old_version => $new_version ) {
3894 if ( version_compare( $old_version, PodsInit::$version_last, '<=' ) && version_compare( PodsInit::$version_last, $new_version, '<' ) ) {
3895 $new_version = str_replace( '.', '_', $new_version );
3896
3897 pods_view( PODS_DIR . 'ui/admin/upgrade/upgrade_' . $new_version . '.php', compact( array_keys( get_defined_vars() ) ) );
3898
3899 break;
3900 }
3901 }
3902 }
3903
3904 /**
3905 * Get the admin help page
3906 */
3907 public function admin_help() {
3908 // Add our custom callouts.
3909 $this->handle_callouts_updates();
3910
3911 if ( $this->has_horizontal_callout() ) {
3912 add_action( 'pods_admin_before_help', [ $this, 'admin_manage_callouts' ] );
3913 } else {
3914 add_action( 'pods_admin_after_help', [ $this, 'admin_manage_callouts' ] );
3915 }
3916
3917 pods_view( PODS_DIR . 'ui/admin/help.php', compact( array_keys( get_defined_vars() ) ) );
3918 }
3919
3920 /**
3921 * Add pods specific capabilities.
3922 *
3923 * @param array $capabilities List of extra capabilities to add.
3924 *
3925 * @return array
3926 */
3927 public function admin_capabilities( $capabilities ) {
3928
3929 $pods = pods_api()->load_pods(
3930 array(
3931 'type' => array(
3932 'settings',
3933 'post_type',
3934 'taxonomy',
3935 ),
3936 )
3937 );
3938
3939 $other_pods = pods_api()->load_pods(
3940 array(
3941 'type' => array(
3942 'pod',
3943 'table',
3944 ),
3945 )
3946 );
3947
3948 $pods = array_merge( $pods, $other_pods );
3949
3950 $capabilities[] = 'pods';
3951 $capabilities[] = 'pods_content';
3952 $capabilities[] = 'pods_settings';
3953 $capabilities[] = 'pods_components';
3954
3955 foreach ( $pods as $pod ) {
3956 if ( 'settings' === $pod['type'] ) {
3957 $capabilities[] = 'pods_edit_' . $pod['name'];
3958 } elseif ( 'post_type' === $pod['type'] ) {
3959 $capability_type = pods_v_sanitized( 'capability_type_custom', $pod['options'], pods_v( 'name', $pod ) );
3960
3961 if ( 'custom' === pods_v( 'capability_type', $pod['options'] ) && is_string( $capability_type ) && 0 < strlen( $capability_type ) ) {
3962 $capabilities[] = 'read_' . $capability_type;
3963 $capabilities[] = 'edit_' . $capability_type;
3964 $capabilities[] = 'delete_' . $capability_type;
3965
3966 if ( 1 === (int) pods_v( 'capability_type_extra', $pod['options'], 1 ) ) {
3967 $capability_type_plural = $capability_type . 's';
3968
3969 $capabilities[] = 'read_private_' . $capability_type_plural;
3970 $capabilities[] = 'edit_' . $capability_type_plural;
3971 $capabilities[] = 'edit_others_' . $capability_type_plural;
3972 $capabilities[] = 'edit_private_' . $capability_type_plural;
3973 $capabilities[] = 'edit_published_' . $capability_type_plural;
3974 $capabilities[] = 'publish_' . $capability_type_plural;
3975 $capabilities[] = 'delete_' . $capability_type_plural;
3976 $capabilities[] = 'delete_private_' . $capability_type_plural;
3977 $capabilities[] = 'delete_published_' . $capability_type_plural;
3978 $capabilities[] = 'delete_others_' . $capability_type_plural;
3979 }
3980 }
3981 } elseif ( 'taxonomy' === $pod['type'] ) {
3982 if ( 'custom' === pods_v( 'capability_type', $pod['options'], 'terms' ) ) {
3983 $capability_type = pods_v_sanitized( 'capability_type_custom', $pod['options'], pods_v( 'name', $pod ) . 's' );
3984
3985 $capability_type .= '_term';
3986 $capability_type_plural = $capability_type . 's';
3987
3988 // Singular
3989 $capabilities[] = 'edit_' . $capability_type;
3990 $capabilities[] = 'delete_' . $capability_type;
3991 $capabilities[] = 'assign_' . $capability_type;
3992 // Plural
3993 $capabilities[] = 'manage_' . $capability_type_plural;
3994 $capabilities[] = 'edit_' . $capability_type_plural;
3995 $capabilities[] = 'delete_' . $capability_type_plural;
3996 $capabilities[] = 'assign_' . $capability_type_plural;
3997 }
3998 } else {
3999 $capabilities[] = 'pods_add_' . $pod['name'];
4000 $capabilities[] = 'pods_edit_' . $pod['name'];
4001 $capabilities[] = 'pods_delete_' . $pod['name'];
4002
4003 if ( $pod instanceof Pod ) {
4004 $author_field = $pod->get_field( 'author', null, false );
4005 } else {
4006 $author_field = pods_v( 'author', $pod['fields'] );
4007 }
4008
4009 if ( $author_field && 'pick' === $author_field['type'] && 'user' === $author_field['pick_object'] ) {
4010 $capabilities[] = 'pods_edit_others_' . $pod['name'];
4011 $capabilities[] = 'pods_delete_others_' . $pod['name'];
4012 }
4013
4014 $actions_enabled = pods_v( 'ui_actions_enabled', $pod['options'] );
4015
4016 if ( ! empty( $actions_enabled ) ) {
4017 $actions_enabled = (array) $actions_enabled;
4018 } else {
4019 $actions_enabled = array();
4020 }
4021
4022 $available_actions = array(
4023 'add',
4024 'edit',
4025 'duplicate',
4026 'delete',
4027 'reorder',
4028 'export',
4029 );
4030
4031 if ( ! empty( $actions_enabled ) ) {
4032 $actions_disabled = array(
4033 'view' => 'view',
4034 );
4035
4036 foreach ( $available_actions as $action ) {
4037 if ( ! in_array( $action, $actions_enabled, true ) ) {
4038 $actions_disabled[ $action ] = $action;
4039 }
4040 }
4041
4042 if ( ! in_array( 'export', $actions_disabled, true ) ) {
4043 $capabilities[] = 'pods_export_' . $pod['name'];
4044 }
4045
4046 if ( ! in_array( 'reorder', $actions_disabled, true ) ) {
4047 $capabilities[] = 'pods_reorder_' . $pod['name'];
4048 }
4049 } elseif ( 1 === (int) pods_v( 'ui_export', $pod['options'], 0 ) ) {
4050 $capabilities[] = 'pods_export_' . $pod['name'];
4051 }//end if
4052 }//end if
4053 }//end foreach
4054
4055 return $capabilities;
4056 }
4057
4058 /**
4059 * Handle ajax calls for the administration
4060 */
4061 public function admin_ajax() {
4062
4063 if ( false === headers_sent() ) {
4064 pods_session_start();
4065
4066 header( 'Content-Type: text/html; charset=' . get_bloginfo( 'charset' ) );
4067 }
4068
4069 // Sanitize input
4070 // @codingStandardsIgnoreLine
4071 $params = pods_unslash( (array) $_POST );
4072
4073 foreach ( $params as $key => $value ) {
4074 if ( 'action' === $key ) {
4075 continue;
4076 }
4077
4078 // Fixup $_POST data @codingStandardsIgnoreLine
4079 $_POST[ str_replace( '_podsfix_', '', $key ) ] = $_POST[ $key ];
4080
4081 // Fixup $params with unslashed data
4082 $params[ str_replace( '_podsfix_', '', $key ) ] = $value;
4083
4084 // Unset the _podsfix_* keys
4085 unset( $params[ $key ] );
4086 }
4087
4088 $params = (object) $params;
4089
4090 $methods = array(
4091 'add_pod' => array( 'priv' => true ),
4092 'save_pod' => array( 'priv' => true ),
4093 'load_sister_fields' => array( 'priv' => true ),
4094 'process_form' => array( 'custom_nonce' => true ),
4095 // priv handled through nonce
4096 'upgrade' => array( 'priv' => true ),
4097 'migrate' => array( 'priv' => true ),
4098 );
4099
4100 /**
4101 * AJAX Callbacks in field editor
4102 *
4103 * @since unknown
4104 *
4105 * @param array $methods Callback methods.
4106 * @param PodsAdmin $obj PodsAdmin object.
4107 */
4108 $methods = apply_filters( 'pods_admin_ajax_methods', $methods, $this );
4109
4110 if ( ! isset( $params->method ) || ! isset( $methods[ $params->method ] ) ) {
4111 pods_error( __( 'Invalid AJAX request', 'pods' ), $this );
4112 }
4113
4114 $defaults = array(
4115 'priv' => null,
4116 'name' => $params->method,
4117 'custom_nonce' => null,
4118 );
4119
4120 $method = (object) array_merge( $defaults, (array) $methods[ $params->method ] );
4121
4122 if (
4123 true !== $method->custom_nonce
4124 && (
4125 ! is_user_logged_in()
4126 || ! isset( $params->_wpnonce )
4127 || false === wp_verify_nonce( $params->_wpnonce, 'pods-' . $params->method )
4128 )
4129 ) {
4130 pods_error( __( 'Unauthorized request', 'pods' ), $this );
4131 }
4132
4133 // Cleaning up $params
4134 unset( $params->action );
4135 unset( $params->method );
4136
4137 if ( true !== $method->custom_nonce ) {
4138 unset( $params->_wpnonce );
4139 }
4140
4141 // Check permissions (convert to array to support multiple)
4142 if ( ! empty( $method->priv ) && ! pods_is_admin( array( 'pods' ) ) ) {
4143 if ( true !== $method->priv && pods_is_admin( $method->priv ) ) {
4144 // They have access to the custom priv.
4145 } else {
4146 // They do not have access.
4147 pods_error( __( 'Access denied', 'pods' ), $this );
4148 }
4149 }
4150
4151 $params->method = $method->name;
4152
4153 $method_name = $method->name;
4154
4155 $params = apply_filters( "pods_api_{$method_name}", $params, $method );
4156
4157 $api = pods_api();
4158
4159 $api->display_errors = false;
4160
4161 if ( 'upgrade' === $method->name ) {
4162 $output = (string) pods_upgrade( $params->version )->ajax( $params );
4163 } elseif ( 'migrate' === $method->name ) {
4164 $output = (string) apply_filters( 'pods_api_migrate_run', $params );
4165 } else {
4166 if ( ! method_exists( $api, $method->name ) ) {
4167 pods_error( __( 'API method does not exist', 'pods' ), $this );
4168 } elseif ( 'save_pod' === $method->name ) {
4169 if ( isset( $params->field_data_json ) && is_array( $params->field_data_json ) ) {
4170 $params->fields = $params->field_data_json;
4171
4172 unset( $params->field_data_json );
4173
4174 foreach ( $params->fields as $k => $v ) {
4175 if ( empty( $v ) ) {
4176 unset( $params->fields[ $k ] );
4177 } elseif ( ! is_array( $v ) ) {
4178 $params->fields[ $k ] = (array) @json_decode( $v, true );
4179 }
4180 }
4181 }
4182 }
4183
4184 // Dynamically call the API method
4185 $params = (array) $params;
4186
4187 $output = call_user_func( array( $api, $method->name ), $params );
4188 }//end if
4189
4190 // Output in json format
4191 if ( false !== $output ) {
4192
4193 /**
4194 * Pods Admin AJAX request was successful
4195 *
4196 * @since 2.6.8
4197 *
4198 * @param array $params AJAX parameters.
4199 * @param array|object|string $output Output for AJAX request.
4200 */
4201 do_action( "pods_admin_ajax_success_{$method->name}", $params, $output );
4202
4203 if ( is_array( $output ) || is_object( $output ) ) {
4204 wp_send_json( $output );
4205 } else {
4206 // @codingStandardsIgnoreLine
4207 echo $output;
4208 }
4209 } else {
4210 pods_error( __( 'There was a problem with your request.', 'pods' ) );
4211 }//end if
4212
4213 die();
4214 // KBAI!
4215 }
4216
4217 /**
4218 * Profiles the Pods configuration
4219 *
4220 * @param null|string|array $pod Which Pod(s) to get configuration for. Can be a the name
4221 * of one Pod, or an array of names of Pods, or null, which is the
4222 * default, to profile all Pods.
4223 * @param bool $full_field_info If true all info about each field is returned. If false,
4224 * which is the default only name and type, will be returned.
4225 *
4226 * @return array
4227 *
4228 * @since 2.7.0
4229 * @deprecated 2.8.0
4230 */
4231 public function configuration( $pod = null, $full_field_info = false ) {
4232 pods_deprecated( 'PodsAdmin::configuration', '2.8' );
4233
4234 $api = pods_api();
4235
4236 if ( null === $pod ) {
4237 $the_pods = $api->load_pods();
4238 } elseif ( is_array( $pod ) ) {
4239 foreach ( $pod as $p ) {
4240 $the_pods[] = $api->load_pod( $p );
4241 }
4242 } else {
4243 $the_pods[] = $api->load_pod( $pod );
4244 }
4245
4246 foreach ( $the_pods as $the_pod ) {
4247 $configuration[ $the_pod['name'] ] = array(
4248 'name' => $the_pod['name'],
4249 'ID' => $the_pod['id'],
4250 'storage' => $the_pod['storage'],
4251 'fields' => $the_pod['fields'],
4252 );
4253 }
4254
4255 if ( ! $full_field_info ) {
4256 foreach ( $the_pods as $the_pod ) {
4257 $fields = $configuration[ $the_pod['name'] ]['fields'];
4258
4259 unset( $configuration[ $the_pod['name'] ]['fields'] );
4260
4261 foreach ( $fields as $field ) {
4262 $info = array(
4263 'name' => $field['name'],
4264 'type' => $field['type'],
4265 );
4266
4267 if ( 'pick' === $info['type'] ) {
4268 $info['pick_object'] = $field['pick_object'];
4269
4270 if ( isset( $field['pick_val'] ) && '' !== $field['pick_val'] ) {
4271 $info['pick_val'] = $field['pick_val'];
4272 }
4273 }
4274
4275 if ( is_array( $info ) ) {
4276 $configuration[ $the_pod['name'] ]['fields'][ $field['name'] ] = $info;
4277 }
4278
4279 unset( $info );
4280
4281 }//end foreach
4282 }//end foreach
4283 }//end if
4284
4285 if ( is_array( $configuration ) ) {
4286 return $configuration;
4287 }
4288
4289 }
4290
4291 /**
4292 * Build UI for extending REST API, if makes sense to do so.
4293 *
4294 * @since 2.6.0
4295 *
4296 * @access protected
4297 */
4298 protected function rest_admin() {
4299
4300 if ( function_exists( 'register_rest_field' ) ) {
4301 add_filter(
4302 'pods_admin_setup_edit_field_options', array(
4303 $this,
4304 'add_rest_fields_to_field_editor',
4305 ), 12, 2
4306 );
4307 add_filter( 'pods_admin_setup_edit_field_tabs', array( $this, 'add_rest_field_tab' ), 12, 2 );
4308 }
4309
4310 add_filter( 'pods_admin_setup_edit_tabs', array( $this, 'add_rest_settings_tab' ), 12, 2 );
4311 add_filter( 'pods_admin_setup_edit_options', array( $this, 'add_rest_settings_tab_fields' ), 12, 2 );
4312
4313 }
4314
4315 /**
4316 * Check if Pod type <em>could</em> extend core REST API response
4317 *
4318 * @since 2.5.6
4319 *
4320 * @access protected
4321 *
4322 * @param array $pod Pod options.
4323 *
4324 * @return bool
4325 */
4326 protected function restable_pod( $pod ) {
4327
4328 $type = $pod['type'];
4329
4330 $restable_types = array(
4331 'post_type',
4332 'user',
4333 'taxonomy',
4334 'media',
4335 );
4336
4337 return in_array( $type, $restable_types, true );
4338
4339 }
4340
4341 /**
4342 * Add a rest api tab.
4343 *
4344 * @since 2.6.0
4345 *
4346 * @param array $tabs Tab array.
4347 * @param array $pod Pod options.
4348 *
4349 * @return array
4350 */
4351 public function add_rest_settings_tab( $tabs, $pod ) {
4352 if ( ! $this->restable_pod( $pod ) ) {
4353 return $tabs;
4354 }
4355
4356 $tabs['rest-api'] = __( 'REST API', 'pods' );
4357
4358 return $tabs;
4359
4360 }
4361
4362 /**
4363 * Populate REST API tab.
4364 *
4365 * @since 0.1.0
4366 *
4367 * @param array $options Tab options.
4368 * @param Pod $pod Pod options.
4369 *
4370 * @return array
4371 */
4372 public function add_rest_settings_tab_fields( $options, $pod ) {
4373 if ( ! $this->restable_pod( $pod ) ) {
4374 return $options;
4375 }
4376
4377 $options['rest-api'] = [
4378 'rest_enable' => [
4379 'label' => __( 'Enable', 'pods' ),
4380 'help' => __( 'Add REST API support for this Pod.', 'pods' ),
4381 'type' => 'boolean',
4382 'default' => '',
4383 'dependency' => true,
4384 ],
4385 'rest_base' => [
4386 'label' => __( 'REST Base (if any)', 'pods' ),
4387 'help' => __( 'This will form the url for the route. Default / empty value here will use the pod name.', 'pods' ),
4388 'type' => 'text',
4389 'default' => '',
4390 'depends-on' => [ 'rest_enable' => true ],
4391 ],
4392 'rest_namespace' => [
4393 'label' => __( 'REST API namespace', 'pods' ),
4394 'help' => __( 'This will change the namespace URL of the REST API route to a different one from the default one that all normal route endpoints use.', 'pods' ),
4395 'type' => 'text',
4396 'default' => '',
4397 'placeholder' => 'wp/v2',
4398 'depends-on' => [ 'rest_enable' => true ],
4399 ],
4400 'read_all' => [
4401 'label' => __( 'Show All Fields (read-only)', 'pods' ),
4402 'help' => __( 'Show all fields in REST API. If unchecked fields must be enabled on a field by field basis.', 'pods' ),
4403 'type' => 'boolean',
4404 'default' => '',
4405 'depends-on' => [ 'rest_enable' => true ],
4406 'dependency' => true,
4407 ],
4408 'read_all_access' => [
4409 'label' => __( 'Read All Access', 'pods' ),
4410 'help' => __( 'By default the REST API will allow the fields to be returned for everyone who has access to that endpoint/object. You can also restrict the access of your field based on whether the person is logged in.', 'pods' ),
4411 'type' => 'boolean',
4412 'boolean_yes_label' => __( 'Require being logged in to read all field values via REST', 'pods' ),
4413 'depends-on' => [
4414 'read_all' => true,
4415 ],
4416 ],
4417 'write_all' => [
4418 'label' => __( 'Allow All Fields To Be Updated', 'pods' ),
4419 'help' => __( 'Allow all fields to be updated via the REST API. If unchecked fields must be enabled on a field by field basis.', 'pods' ),
4420 'type' => 'boolean',
4421 'default' => pods_v( 'name', $pod ),
4422 'depends-on' => [ 'rest_enable' => true, 'read_all' => true ],
4423 ],
4424 /*'write_all_access' => [
4425 'label' => __( 'Write All Access', 'pods' ),
4426 'help' => __( 'By default the REST API will allow the fields to be written by everyone who has access to edit that object. You can also restrict the access of your field based on whether the person is logged in.', 'pods' ),
4427 'type' => 'boolean',
4428 'boolean_yes_label' => __( 'Require being logged in to write to all field values via REST', 'pods' ),
4429 'depends-on' => [
4430 'write_all' => true,
4431 ],
4432 ],*/
4433 'rest_api_field_mode' => [
4434 'label' => __( 'Field Mode', 'pods' ),
4435 'help' => __( 'Specify how you would like your values returned in the REST API responses. If you choose to show Both raw and rendered values then an object will be returned for each field that contains the value and rendered properties.', 'pods' ),
4436 'type' => 'pick',
4437 'pick_format_single' => 'radio',
4438 'default' => 'value',
4439 'depends-on' => [ 'rest_enable' => true ],
4440 'data' => [
4441 'value' => __( 'Raw values', 'pods' ),
4442 'render' => __( 'Rendered values', 'pods' ),
4443 'value_and_render' => __( 'Both raw and rendered values {value: raw_value, rendered: rendered_value}', 'pods' ),
4444 ],
4445 ],
4446 'rest_api_field_location' => [
4447 'label' => __( 'Field Location', 'pods' ),
4448 'help' => __( 'Specify where you would like your values returned in the REST API responses. To show in the "meta" object of the response, you must have Custom Fields enabled in the Post Type Supports features.', 'pods' ),
4449 'type' => 'pick',
4450 'pick_format_single' => 'radio',
4451 'default' => 'object',
4452 'depends-on' => [ 'rest_enable' => true ],
4453 'data' => [
4454 'object' => __( 'Show as a custom object field (response.field_name)', 'pods' ),
4455 'meta' => __( 'Include in the meta object (response.meta.field_name)', 'pods' ),
4456 ],
4457 ],
4458 ];
4459
4460 if ( ! $pod->is_extended() ) {
4461 unset( $options['rest_base'] );
4462 unset( $options['rest_namespace'] );
4463 }
4464
4465 if ( 'post_type' !== $pod->get_type() ) {
4466 unset( $options['rest_api_field_location'] );
4467 }
4468
4469 return $options;
4470 }
4471
4472 /**
4473 * Add a REST API section to advanced tab of field editor.
4474 *
4475 * @since 2.5.6
4476 *
4477 * @param array $options Tab options.
4478 * @param array $pod Pod options.
4479 *
4480 * @return array
4481 */
4482 public function add_rest_fields_to_field_editor( $options, $pod ) {
4483 if ( ! $this->restable_pod( $pod ) ) {
4484 return $options;
4485 }
4486
4487 $layout_non_input_field_types = PodsForm::layout_field_types() + PodsForm::non_input_field_types();
4488
4489 $options['rest'] = [
4490 'rest_read_write' => [
4491 'name' => 'rest_read_write',
4492 'type' => 'heading',
4493 'label' => __( 'Read/Write', 'pods' ),
4494 ],
4495 'rest_read' => [
4496 'label' => __( 'Read via REST API', 'pods' ),
4497 'help' => __( 'Should this field be readable via the REST API? You must enable REST API support for this Pod.', 'pods' ),
4498 'type' => 'boolean',
4499 'default' => '',
4500 'excludes-on' => [
4501 'type' => $layout_non_input_field_types,
4502 ],
4503 ],
4504 'rest_read_access' => [
4505 'label' => __( 'Read Access', 'pods' ),
4506 'help' => __( 'By default the REST API will allow the fields to be returned for everyone who has access to that endpoint/object. You can also restrict the access of your field based on whether the person is logged in.', 'pods' ),
4507 'type' => 'boolean',
4508 'boolean_yes_label' => __( 'Require being logged in to read this field value via REST', 'pods' ),
4509 'depends-on' => [
4510 'rest_read' => true,
4511 ],
4512 'excludes-on' => [
4513 'type' => $layout_non_input_field_types,
4514 ],
4515 ],
4516 'rest_write' => [
4517 'label' => __( 'Write via REST API', 'pods' ),
4518 'help' => __( 'Should this field be writeable via the REST API? You must enable REST API support for this Pod.', 'pods' ),
4519 'type' => 'boolean',
4520 'default' => '',
4521 'excludes-on' => [
4522 'type' => $layout_non_input_field_types,
4523 ],
4524 ],
4525 /*'rest_write_access' => [
4526 'label' => __( 'Write Access', 'pods' ),
4527 'help' => __( 'By default the REST API will allow the fields to be written by everyone who has access to edit that object. You can also restrict the access of your field based on whether the person is logged in.', 'pods' ),
4528 'type' => 'boolean',
4529 'boolean_yes_label' => __( 'Require being logged in to write to this field value via REST', 'pods' ),
4530 'depends-on' => [
4531 'rest_write' => true,
4532 ],
4533 'excludes-on' => [
4534 'type' => $layout_non_input_field_types,
4535 ],
4536 ],*/
4537 'rest_field_options' => [
4538 'name' => 'rest_field_options',
4539 'label' => __( 'Relationship Field Options', 'pods' ),
4540 'type' => 'heading',
4541 'depends-on' => [
4542 'type' => 'pick',
4543 ],
4544 ],
4545 'rest_pick_response' => [
4546 'label' => __( 'Response Type', 'pods' ),
4547 'help' => __( 'This will determine what amount of data for the related items will be returned.', 'pods' ),
4548 'type' => 'pick',
4549 'pick_format_single' => 'dropdown',
4550 'default' => 'array',
4551 'depends-on' => [
4552 'type' => 'pick',
4553 ],
4554 'dependency' => true,
4555 'data' => [
4556 'array' => __( 'All fields', 'pods' ),
4557 'id' => __( 'ID only', 'pods' ),
4558 'name' => __( 'Name only', 'pods' ),
4559 'custom' => __( 'Custom return (specify field to return)', 'pods' ),
4560 ],
4561 'excludes-on' => [
4562 'type' => $layout_non_input_field_types,
4563 ],
4564 ],
4565 'rest_pick_depth' => [
4566 'label' => __( 'Depth', 'pods' ),
4567 'help' => __( 'How far to traverse relationships in response. 1 will get you all of the fields on the related item. 2 will get you all of those fields plus related items and their fields. The higher the depth, the more data will be returned and the slower performance the REST API calls will be. Updates to this field do NOT take depth into account, so you will always send the ID of the related item when saving.', 'pods' ),
4568 'type' => 'number',
4569 'default' => '1',
4570 'depends-on' => [
4571 'type' => 'pick',
4572 'rest_pick_response' => 'array',
4573 ],
4574 'excludes-on' => [
4575 'type' => $layout_non_input_field_types,
4576 ],
4577 ],
4578 'rest_pick_custom' => [
4579 'label' => __( 'Custom return', 'pods' ),
4580 'help' => __( 'Specify the field to use following the established this_field_name.ID traversal pattern. You must include this field name in the selector for this to work properly.', 'pods' ),
4581 'type' => 'text',
4582 'default' => '',
4583 'placeholder' => 'this_field_name.ID',
4584 'depends-on' => [
4585 'type' => 'pick',
4586 'rest_pick_response' => 'custom',
4587 ],
4588 'excludes-on' => [
4589 'type' => $layout_non_input_field_types,
4590 ],
4591 ],
4592 ];
4593
4594 return $options;
4595 }
4596
4597 /**
4598 * Add REST field tab
4599 *
4600 * @since 2.5.6
4601 *
4602 * @param array $tabs Tab list.
4603 * @param array $pod The ood object.
4604 *
4605 * @return array
4606 */
4607 public function add_rest_field_tab( $tabs, $pod ) {
4608 if ( ! $this->restable_pod( $pod ) ) {
4609 return $tabs;
4610 }
4611
4612 $tabs['rest'] = __( 'REST API', 'pods' );
4613
4614 return $tabs;
4615 }
4616
4617 /**
4618 * Add Pods-specific debug info to Site Info debug area.
4619 *
4620 * @since 2.7.13
4621 *
4622 * @param array $info Debug info.
4623 *
4624 * @return array Debug info with Pods-specific debug info added.
4625 */
4626 public function add_debug_information( $info ) {
4627 $auto_start = pods_session_auto_start();
4628
4629 if ( 'auto' !== $auto_start ) {
4630 // Turn boolean into 0/1.
4631 $auto_start = (int) $auto_start;
4632 }
4633
4634 // Turn into a string.
4635 $auto_start = (string) $auto_start;
4636
4637 $settings = pods_container( Settings::class );
4638
4639 $settings_fields = $settings->get_setting_fields();
4640
4641 $settings_values = $settings->get_settings();
4642
4643 $auto_start = pods_v( $auto_start, $settings_fields['session_auto_start']['data'], __( 'Unknown', 'pods' ) );
4644
4645 global $wpdb;
4646
4647 $info['pods'] = [
4648 'label' => 'Pods',
4649 'description' => __( 'Debug information for Pods installations.', 'pods' ),
4650 'fields' => [
4651 'pods-version' => [
4652 'label' => __( 'Pods Version', 'pods' ),
4653 'value' => PODS_VERSION,
4654 ],
4655 'pods-first-version' => [
4656 'label' => __( 'Pods Version (First installed)', 'pods' ),
4657 'value' => get_option( 'pods_framework_version_first', PODS_VERSION ),
4658 ],
4659 'pods-last-version' => [
4660 'label' => __( 'Pods Version (Last updated from)', 'pods' ),
4661 'value' => get_option( 'pods_framework_version_last', PODS_VERSION ),
4662 ],
4663 'pods-server-software' => [
4664 'label' => __( 'Server Software', 'pods' ),
4665 'value' => ! empty( $_SERVER['SERVER_SOFTWARE'] ) ? $_SERVER['SERVER_SOFTWARE'] : 'N/A',
4666 ],
4667 'pods-user-agent' => [
4668 'label' => __( 'Your User Agent', 'pods' ),
4669 'value' => ! empty( $_SERVER['HTTP_USER_AGENT'] ) ? $_SERVER['HTTP_USER_AGENT'] : 'N/A',
4670 ],
4671 'pods-session-save-path' => [
4672 'label' => __( 'Session Save Path', 'pods' ),
4673 'value' => session_save_path(),
4674 ],
4675 'pods-session-save-path-exists' => [
4676 'label' => __( 'Session Save Path Exists', 'pods' ),
4677 'value' => file_exists( session_save_path() ) ? __( 'Yes', 'pods' ) : __( 'No', 'pods' ),
4678 ],
4679 'pods-session-save-path-writable' => [
4680 'label' => __( 'Session Save Path Writeable', 'pods' ),
4681 'value' => is_writable( session_save_path() ) ? __( 'Yes', 'pods' ) : __( 'No', 'pods' ),
4682 ],
4683 'pods-session-max-lifetime' => [
4684 'label' => __( 'Session Max Lifetime', 'pods' ),
4685 'value' => ini_get( 'session.gc_maxlifetime' ),
4686 ],
4687 'pods-opcode-cache-apc' => [
4688 'label' => __( 'Opcode Cache: Apc', 'pods' ),
4689 'value' => function_exists( 'apc_cache_info' ) ? __( 'Yes', 'pods' ) : __( 'No', 'pods' ),
4690 ],
4691 'pods-opcode-cache-memcached' => [
4692 'label' => __( 'Opcode Cache: Memcached', 'pods' ),
4693 'value' => class_exists( 'eaccelerator_put' ) ? __( 'Yes', 'pods' ) : __( 'No', 'pods' ),
4694 ],
4695 'pods-opcode-cache-opcache' => [
4696 'label' => __( 'Opcode Cache: OPcache', 'pods' ),
4697 'value' => function_exists( 'opcache_get_status' ) ? __( 'Yes', 'pods' ) : __( 'No', 'pods' ),
4698 ],
4699 'pods-opcode-cache-redis' => [
4700 'label' => __( 'Opcode Cache: Redis', 'pods' ),
4701 'value' => class_exists( 'xcache_set' ) ? __( 'Yes', 'pods' ) : __( 'No', 'pods' ),
4702 ],
4703 'pods-object-cache-apc' => [
4704 'label' => __( 'Object Cache: APC', 'pods' ),
4705 'value' => function_exists( 'apc_cache_info' ) ? __( 'Yes', 'pods' ) : __( 'No', 'pods' ),
4706 ],
4707 'pods-object-cache-apcu' => [
4708 'label' => __( 'Object Cache: APCu', 'pods' ),
4709 'value' => function_exists( 'apcu_cache_info' ) ? __( 'Yes', 'pods' ) : __( 'No', 'pods' ),
4710 ],
4711 'pods-object-cache-memcache' => [
4712 'label' => __( 'Object Cache: Memcache', 'pods' ),
4713 'value' => class_exists( 'Memcache' ) ? __( 'Yes', 'pods' ) : __( 'No', 'pods' ),
4714 ],
4715 'pods-object-cache-memcached' => [
4716 'label' => __( 'Object Cache: Memcached', 'pods' ),
4717 'value' => class_exists( 'Memcached' ) ? __( 'Yes', 'pods' ) : __( 'No', 'pods' ),
4718 ],
4719 'pods-object-cache-redis' => [
4720 'label' => __( 'Object Cache: Redis', 'pods' ),
4721 'value' => class_exists( 'Redis' ) ? __( 'Yes', 'pods' ) : __( 'No', 'pods' ),
4722 ],
4723 'pods-memory-current-usage' => [
4724 'label' => __( 'Current Memory Usage', 'pods' ),
4725 'value' => number_format_i18n( memory_get_usage() / 1024 / 1024, 3 ) . 'M' . ( defined( 'WP_MEMORY_LIMIT' ) ? ' / ' . WP_MEMORY_LIMIT : '' ),
4726 ],
4727 'pods-memory-current-usage-real' => [
4728 'label' => __( 'Current Memory Usage (real)', 'pods' ),
4729 'value' => number_format_i18n( memory_get_usage( true ) / 1024 / 1024, 3 ) . 'M',
4730 ],
4731 'pods-network-wide' => [
4732 'label' => __( 'Pods Network-Wide Activated', 'pods' ),
4733 'value' => is_plugin_active_for_network( basename( PODS_DIR ) . '/init.php' ) ? __( 'Yes', 'pods' ) : __( 'No', 'pods' ),
4734 ],
4735 'pods-install-location' => [
4736 'label' => __( 'Pods Install Location', 'pods' ),
4737 'value' => str_replace( ABSPATH, '/', PODS_DIR ),
4738 ],
4739 'pods-developer' => [
4740 'label' => __( 'Pods Developer Activated' ),
4741 'value' => ( pods_developer() ) ? __( 'Yes', 'pods' ) : __( 'No', 'pods' ),
4742 ],
4743 'pods-tableless-mode' => [
4744 'label' => __( 'Pods Tableless Mode Activated', 'pods' ),
4745 'value' => ( pods_tableless() ) ? __( 'Yes', 'pods' ) : __( 'No', 'pods' ),
4746 ],
4747 'pods-relationship-table-enabled' => [
4748 'label' => __( 'Pods Relationship Table Enabled', 'pods' ),
4749 'value' => ( pods_podsrel_enabled() ) ? __( 'Yes', 'pods' ) : __( 'No', 'pods' ),
4750 ],
4751 'pods-relationship-table-status' => [
4752 'label' => __( 'Pods Relationship Table Count' ),
4753 'value' => ( ! pods_tableless() ? number_format( (float) $wpdb->get_var( "SELECT COUNT(*) FROM {$wpdb->prefix}podsrel" ) ) : 'No table' ),
4754 ],
4755 'pods-light-mode' => [
4756 'label' => __( 'Pods Light Mode Activated', 'pods' ),
4757 'value' => ( pods_light() ) ? __( 'Yes', 'pods' ) : __( 'No', 'pods' ),
4758 ],
4759 'pods-strict' => [
4760 'label' => __( 'Pods Strict Activated' ),
4761 'value' => ( pods_strict( false ) ) ? __( 'Yes', 'pods' ) : __( 'No', 'pods' ),
4762 ],
4763 'pods-allow-deprecated' => [
4764 'label' => __( 'Pods Allow Deprecated' ),
4765 'value' => ( pods_allow_deprecated() ) ? __( 'Yes', 'pods' ) : __( 'No', 'pods' ),
4766 ],
4767 'pods-api-cache' => [
4768 'label' => __( 'Pods API Cache Activated' ),
4769 'value' => ( pods_api_cache() ) ? __( 'Yes', 'pods' ) : __( 'No', 'pods' ),
4770 ],
4771 'pods-shortcode-allow-evaluate-tags' => [
4772 'label' => __( 'Pods Shortcode Allow Evaluate Tags' ),
4773 'value' => ( pods_shortcode_allow_evaluate_tags() ) ? __( 'Yes', 'pods' ) : __( 'No', 'pods' ),
4774 ],
4775 'pods-can-use-sessions' => [
4776 'label' => __( 'Pods Can Use Sessions' ),
4777 'value' => ( pods_can_use_sessions( true ) ) ? __( 'Yes', 'pods' ) : __( 'No', 'pods' ),
4778 ],
4779 ],
4780 ];
4781
4782 foreach ( $settings_fields as $setting_name => $setting_field ) {
4783 if ( empty( $setting_field['site_health_include_in_info'] ) ) {
4784 continue;
4785 }
4786
4787 if ( isset( $setting_field['name'] ) ) {
4788 $setting_name = $setting_field['name'];
4789 }
4790
4791 $setting_key = 'pods-settings-' . sanitize_title_with_dashes( $setting_name );
4792
4793 $value = pods_v( $setting_name, $settings_values );
4794
4795 $original_value = is_array( $value ) ? implode( ',', $value ) : (string) $value;
4796
4797 if ( is_array( $value ) ) {
4798 foreach ( $value as $k => $v ) {
4799 $v = (string) $v;
4800
4801 $has_v = 0 < strlen( $v );
4802
4803 if ( $has_v && isset( $setting_field['site_health_data'] ) && isset( $setting_field['site_health_data'][ $v ] ) ) {
4804 $value[ $k ] = $setting_field['site_health_data'][ $v ];
4805 } elseif ( $has_v && isset( $setting_field['data'] ) && isset( $setting_field['data'][ $v ] ) ) {
4806 $value[ $k ] = $setting_field['data'][ $v ];
4807 }
4808 }
4809
4810 $value = pods_serial_comma( $value );
4811 } else {
4812 $value = (string) $value;
4813
4814 $has_value = 0 < strlen( $value );
4815
4816 if ( $has_value && isset( $setting_field['site_health_data'] ) && isset( $setting_field['site_health_data'][ $value ] ) ) {
4817 $value = $setting_field['site_health_data'][ $value ];
4818 } elseif ( $has_value && isset( $setting_field['data'] ) && isset( $setting_field['data'][ $value ] ) ) {
4819 $value = $setting_field['data'][ $value ];
4820 } elseif ( 'boolean' === $setting_field['data'] || '1' === $value || '0' === $value ) {
4821 $value = '1' === $value ? __( 'Yes', 'pods' ) : __( 'No', 'pods' );
4822 }
4823 }
4824
4825 if ( 'unknown' === $value || '' === $value ) {
4826 $value = __( 'Unknown', 'pods' );
4827 }
4828
4829 $info['pods']['fields'][ $setting_key ] = [
4830 'label' => $setting_field['label'],
4831 'value' => $value . ( $value !== $original_value ? ' [' . $setting_name . '=' . $original_value . ']' : '' ),
4832 ];
4833 }
4834
4835 // @todo Later we should add which components are active.
4836
4837 return $info;
4838 }
4839
4840 /**
4841 * Add our site status tests.
4842 *
4843 * @since 2.8.0
4844 *
4845 * @param array $tests The list of status tests.
4846 *
4847 * @return array The list of status tests.
4848 */
4849 public function site_status_tests( $tests ) {
4850 $plugin_search_url = 'plugin-install.php?tab=search&type=term&s=';
4851
4852 if ( is_multisite() && ! is_network_admin() ) {
4853 $plugin_search_url = network_admin_url( $plugin_search_url );
4854 } else {
4855 $plugin_search_url = self_admin_url( $plugin_search_url );
4856 }
4857
4858 if ( ! is_pods_alternative_cache_activated() && ! wp_using_ext_object_cache() ) {
4859 $tests['direct']['pods_alternative_cache'] = [
4860 'label' => __( 'Pods Alternative Cache', 'pods' ),
4861 'test' => static function () use ( $plugin_search_url ) {
4862 return [
4863 'label' => __( 'The Pods Team recommends you install the Pods Alternative Cache plugin', 'pods' ),
4864 'status' => 'recommended',
4865 'badge' => [
4866 'label' => __( 'Performance', 'pods' ),
4867 'color' => 'blue',
4868 ],
4869 'description' => sprintf( '<p>%s</p>', __( 'You are not using an external object cache for this site. Pods Alternative Cache is usually useful for Pods installs that use Shared Hosting with limited Object Cache capabilities.', 'pods' ) ),
4870 'actions' => sprintf( '<p><a href="%s">%s</a></p>', esc_url( $plugin_search_url . urlencode( 'Pods Alternative Cache' ) ), __( 'Install Pods Alternative Cache', 'pods' ) ),
4871 'test' => 'pods_alternative_cache',
4872 ];
4873 },
4874 ];
4875 }
4876
4877 return $tests;
4878 }
4879
4880 /**
4881 * Check whether the requirements were met and maybe display error messages.
4882 *
4883 * @since 2.9.0
4884 *
4885 * @param array $requirements List of requirements.
4886 *
4887 * @return bool Whether the requirements were met.
4888 */
4889 public function check_requirements( array $requirements ) {
4890 foreach ( $requirements as $requirement ) {
4891 // Check if requirement passed.
4892 if ( $requirement['check'] ) {
4893 continue;
4894 }
4895
4896 // Show admin notice if there's a message to be shown.
4897 if ( ! empty( $requirement['message'] ) && $this->should_show_notices() ) {
4898 pods_message( $requirement['message'], 'error' );
4899 }
4900
4901 return false;
4902 }
4903
4904 return true;
4905 }
4906
4907 /**
4908 * Check whether we should show notices.
4909 *
4910 * @since 2.9.0
4911 *
4912 * @return bool Whether we should show notices.
4913 */
4914 public function should_show_notices() {
4915 global $pagenow;
4916
4917 // We only show notices on admin pages.
4918 if ( ! is_admin() ) {
4919 return false;
4920 }
4921
4922 $page = isset( $_GET['page'] ) ? $_GET['page'] : '';
4923
4924 // We only show on the plugins.php page or on Pods Admin pages.
4925 if (
4926 (
4927 'plugins.php' !== $pagenow
4928 && 0 !== strpos( $page, 'pods' )
4929 )
4930 || 0 === strpos( $page, 'pods-manage-' )
4931 ) {
4932 return false;
4933 }
4934
4935 return true;
4936 }
4937
4938 }
4939