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