PluginProbe ʕ •ᴥ•ʔ
Pods – Custom Content Types and Fields / 2.9.19.4
Pods – Custom Content Types and Fields v2.9.19.4
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
3478 lines
1 <?php
2
3 use Pods\Admin\Config\Pod as Config_Pod;
4 use Pods\Admin\Config\Group as Config_Group;
5 use Pods\Admin\Config\Field as Config_Field;
6 use Pods\Admin\Settings;
7 use Pods\Tools\Repair;
8 use Pods\Whatsit\Pod;
9
10 /**
11 * @package Pods
12 */
13 class PodsAdmin {
14
15 /**
16 * @var PodsAdmin
17 */
18 public static $instance = null;
19
20 /**
21 * Singleton handling for a basic pods_admin() request
22 *
23 * @return \PodsAdmin
24 *
25 * @since 2.3.5
26 */
27 public static function init() {
28
29 if ( ! is_object( self::$instance ) ) {
30 self::$instance = new PodsAdmin();
31 }
32
33 return self::$instance;
34 }
35
36 /**
37 * Setup and Handle Admin functionality
38 *
39 * @return \PodsAdmin
40 *
41 * @license http://www.gnu.org/licenses/gpl-2.0.html
42 * @since 2.0.0
43 */
44 public function __construct() {
45
46 // Scripts / Stylesheets
47 add_action( 'admin_enqueue_scripts', array( $this, 'admin_head' ), 20 );
48
49 // AJAX $_POST fix
50 add_action( 'admin_init', array( $this, 'admin_init' ), 9 );
51
52 // Menus
53 add_action( 'admin_menu', array( $this, 'admin_menu' ), 9 );
54
55 // AJAX for Admin
56 add_action( 'wp_ajax_pods_admin', array( $this, 'admin_ajax' ) );
57
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'], __( 'Add New', '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'], __( 'Add New', 'pods' ) . ' ' . $singular_label );
310 $add_label = pods_v( 'label_add_new', $pod['options'], __( 'Add New', 'pods' ) );
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-settings' => array(
555 'label' => __( 'Settings', 'pods' ),
556 'title' => __( 'Pods Settings', 'pods' ),
557 'function' => array( $this, 'admin_settings' ),
558 'access' => 'pods_settings',
559 ),
560 'pods-help' => array(
561 'label' => __( 'Help', 'pods' ),
562 'title' => __( 'Pods Help', 'pods' ),
563 'function' => array( $this, 'admin_help' ),
564 ),
565 );
566
567 add_filter( 'parent_file', array( $this, 'parent_file' ) );
568 } else {
569 $admin_menus = array(
570 'pods-upgrade' => array(
571 'label' => __( 'Upgrade', 'pods' ),
572 'function' => array( $this, 'admin_upgrade' ),
573 'access' => 'manage_options',
574 ),
575 'pods-settings' => array(
576 'label' => __( 'Settings', 'pods' ),
577 'title' => __( 'Pods Settings', 'pods' ),
578 'function' => array( $this, 'admin_settings' ),
579 'access' => 'pods_settings',
580 ),
581 'pods-help' => array(
582 'label' => __( 'Help', 'pods' ),
583 'title' => __( 'Pods Help', 'pods' ),
584 'function' => array( $this, 'admin_help' ),
585 ),
586 );
587
588 add_action( 'admin_notices', array( $this, 'upgrade_notice' ) );
589 }//end if
590
591 /**
592 * Add or change Pods Admin menu items
593 *
594 * @param array $admin_menus The submenu items in Pods Admin menu.
595 *
596 * @since unknown
597 */
598 $admin_menus = apply_filters( 'pods_admin_menu', $admin_menus );
599
600 $parent = false;
601
602 // PODS_LIGHT disables all Pods components so remove the components menu
603 if ( pods_light() ) {
604 unset( $admin_menus['pods-components'] );
605 }
606
607 if ( ! empty( $admin_menus ) && ( ! defined( 'PODS_DISABLE_ADMIN_MENU' ) || ! PODS_DISABLE_ADMIN_MENU ) ) {
608 foreach ( $admin_menus as $page => $menu_item ) {
609 if ( ! pods_is_admin( pods_v( 'access', $menu_item ) ) ) {
610 continue;
611 }
612
613 // Don't just show the help page
614 if ( false === $parent && 'pods-help' === $page ) {
615 continue;
616 }
617
618 if ( empty( $menu_item['label'] ) ) {
619 $menu_item['label'] = $page;
620 }
621
622 if ( empty( $menu_item['title'] ) ) {
623 $menu_item['title'] = $menu_item['label'];
624 }
625
626 if ( false === $parent ) {
627 $parent = $page;
628
629 $menu = __( 'Pods Admin', 'pods' );
630
631 if ( 'pods-upgrade' === $parent ) {
632 $menu = __( 'Pods Upgrade', 'pods' );
633 }
634
635 add_menu_page( $menu, $menu, 'read', $parent, null, pods_svg_icon( 'pods' ) );
636 }
637
638 add_submenu_page( $parent, $menu_item['title'], $menu_item['label'], 'read', $page, $menu_item['function'] );
639
640 if ( 'pods-components' === $page && is_object( PodsInit::$components ) ) {
641 PodsInit::$components->menu( $parent );
642 }
643 }//end foreach
644 }//end if
645 }
646
647 /**
648 * Set the correct parent_file to highlight the correct top level menu
649 *
650 * @param string $parent_file The parent file.
651 *
652 * @return mixed|string
653 *
654 * @since unknown
655 */
656 public function parent_file( $parent_file ) {
657 global $current_screen, $submenu_file;
658
659 if ( isset( $current_screen ) && ! empty( $current_screen->taxonomy ) ) {
660 $taxonomies = PodsMeta::$taxonomies;
661 if ( ! empty( $taxonomies ) ) {
662 foreach ( (array) $taxonomies as $pod ) {
663 if ( $current_screen->taxonomy !== $pod['name'] ) {
664 continue;
665 }
666
667 $menu_slug = 'edit-tags.php?taxonomy=' . $pod['name'];
668 $menu_location = pods_v( 'menu_location', $pod['options'], 'default' );
669 $menu_location_custom = pods_v( 'menu_location_custom', $pod['options'], '' );
670
671 if ( 'settings' === $menu_location ) {
672 $parent_file = 'options-general.php';
673 } elseif ( 'appearances' === $menu_location ) {
674 $parent_file = 'themes.php';
675 } elseif ( 'objects' === $menu_location ) {
676 $parent_file = $menu_slug;
677 } elseif ( 'top' === $menu_location ) {
678 $parent_file = $menu_slug;
679 } elseif ( 'submenu' === $menu_location && ! empty( $menu_location_custom ) ) {
680 $parent_file = $menu_location_custom;
681 }
682
683 break;
684 }//end foreach
685 }//end if
686 }//end if
687
688 if ( isset( $current_screen ) && ! empty( $current_screen->post_type ) && is_object( PodsInit::$components ) ) {
689 $components_menu_items = PodsInit::$components->components_menu_items;
690
691 foreach ( $components_menu_items as $menu_item ) {
692 if ( empty( $menu_item['menu_page'] ) || $parent_file !== $menu_item['menu_page'] ) {
693 continue;
694 }
695
696 $parent_file = 'pods';
697
698 // @codingStandardsIgnoreLine
699 $submenu_file = $menu_item['menu_page'];
700
701 break;
702 }
703 }
704
705 return $parent_file;
706 }
707
708 /**
709 * Show upgrade notice.
710 */
711 public function upgrade_notice() {
712
713 echo '<div class="error fade"><p>';
714 // @codingStandardsIgnoreLine
715 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' ) ) );
716 echo '</p></div>';
717 }
718
719 /**
720 * Create PodsUI content for the administration pages
721 */
722 public function admin_content() {
723
724 // @codingStandardsIgnoreLine
725 $pod_name = str_replace( array( 'pods-manage-', 'pods-add-new-' ), '', $_GET['page'] );
726
727 $pod = pods_get_instance( $pod_name, pods_v( 'id', 'get', null, true ) );
728
729 if ( ! $pod->pod_data->has_fields() ) {
730 pods_message( __( 'This Pod does not have any fields defined.', 'pods' ), 'error' );
731 return;
732 }
733
734 // @codingStandardsIgnoreLine
735 if ( false !== strpos( $_GET['page'], 'pods-add-new-' ) ) {
736 // @codingStandardsIgnoreLine
737 $_GET['action'] = pods_v( 'action', 'get', 'add' );
738 }
739
740 $pod->ui();
741 }
742
743 /**
744 * Create PodsUI content for the settings administration pages
745 */
746 public function admin_content_settings() {
747
748 // @codingStandardsIgnoreLine
749 $pod_name = str_replace( 'pods-settings-', '', $_GET['page'] );
750
751 $pod = pods_get_instance( $pod_name );
752
753 if ( 'custom' !== pods_v( 'ui_style', $pod->pod_data['options'], 'settings', true ) ) {
754 $actions_disabled = array(
755 'manage' => 'manage',
756 'add' => 'add',
757 'delete' => 'delete',
758 'duplicate' => 'duplicate',
759 'view' => 'view',
760 'export' => 'export',
761 );
762
763 // @codingStandardsIgnoreLine
764 $_GET['action'] = 'edit';
765
766 $page_title = pods_v( 'label', $pod->pod_data, ucwords( str_replace( '_', ' ', $pod->pod_data['name'] ) ), true );
767 $page_title = apply_filters( 'pods_admin_menu_page_title', $page_title, $pod->pod_data );
768
769 $ui = array(
770 'pod' => $pod,
771 'fields' => array(
772 'edit' => $pod->pod_data->get_fields(),
773 ),
774 'header' => array(
775 'edit' => $page_title,
776 ),
777 'label' => array(
778 'edit' => __( 'Save Changes', 'pods' ),
779 ),
780 'style' => pods_v( 'ui_style', $pod->pod_data['options'], 'settings', true ),
781 'icon' => pods_evaluate_tags( pods_v( 'menu_icon', $pod->pod_data['options'] ), true ),
782 'actions_disabled' => $actions_disabled,
783 );
784
785 $pod_pod_name = $pod->pod;
786
787 $ui = apply_filters( "pods_admin_ui_{$pod_pod_name}", apply_filters( 'pods_admin_ui', $ui, $pod->pod, $pod ), $pod->pod, $pod );
788
789 // Force disabled actions, do not pass go, do not collect $two_hundred
790 $ui['actions_disabled'] = $actions_disabled;
791
792 pods_ui( $ui );
793 } else {
794 $pod_pod_name = $pod->pod;
795 do_action( 'pods_admin_ui_custom', $pod );
796 do_action( "pods_admin_ui_custom_{$pod_pod_name}", $pod );
797 }//end if
798 }
799
800 /**
801 * Add media button for Pods shortcode
802 *
803 * @param string $context Media button context.
804 *
805 * @return string
806 */
807 public function media_button( $context = null ) {
808 if ( ! empty( $_GET['action'] ) && 'elementor' === $_GET['action'] ) {
809 return '';
810 }
811
812 // If shortcodes are disabled don't show the button
813 if ( defined( 'PODS_DISABLE_SHORTCODE' ) && PODS_DISABLE_SHORTCODE ) {
814 return '';
815 }
816
817 /**
818 * Filter to remove Pods shortcode button from the post editor.
819 *
820 * @param bool $show_button Set to false to block the shortcode button from appearing.
821 * @param string $context Media button context.
822 *
823 * @since 2.3.19
824 */
825 if ( ! apply_filters( 'pods_admin_media_button', true, $context ) ) {
826 return '';
827 }
828
829 $current_page = basename( $_SERVER['PHP_SELF'] );
830 $current_page = explode( '?', $current_page );
831 $current_page = explode( '#', $current_page[0] );
832 $current_page = $current_page[0];
833
834 // Only show the button on post type pages
835 if ( ! in_array(
836 $current_page, array(
837 'post-new.php',
838 'post.php',
839 ), true
840 ) ) {
841 return '';
842 }
843
844 add_action( 'admin_footer', array( $this, 'mce_popup' ) );
845
846 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>';
847 }
848
849 /**
850 * Enqueue assets for Media Library Popup
851 */
852 public function register_media_assets() {
853
854 if ( 'pods_media_attachment' === pods_v( 'inlineId' ) ) {
855 wp_enqueue_style( 'pods-styles' );
856 }
857 }
858
859 /**
860 * Output Pods shortcode popup window
861 */
862 public function mce_popup() {
863
864 pods_view( PODS_DIR . 'ui/admin/shortcode.php', compact( array_keys( get_defined_vars() ) ) );
865 }
866
867 /**
868 * Handle main Pods Setup area for managing Pods and Fields
869 */
870 public function admin_setup() {
871 $api = pods_api();
872
873 $pods = $api->load_pods( array( 'fields' => false ) );
874
875 $view = pods_v( 'view', 'get', 'all', true );
876
877 // @codingStandardsIgnoreLine
878 if ( empty( $pods ) && ! isset( $_GET['action'] ) ) {
879 // @codingStandardsIgnoreLine
880 $_GET['action'] = 'add';
881 }
882
883 if ( 'pods' === $_GET['page'] && empty( $pods ) ) {
884 pods_message( __( 'You do not have any Pods set up yet. You can set up your very first Pod below.', 'pods ' ) );
885 }
886
887 // @codingStandardsIgnoreLine
888 if ( 'pods-add-new' === $_GET['page'] || empty( $pods ) ) {
889 // @codingStandardsIgnoreLine
890 if ( isset( $_GET['action'] ) && 'add' !== $_GET['action'] ) {
891 pods_redirect(
892 pods_query_arg(
893 array(
894 'page' => 'pods',
895 // @codingStandardsIgnoreLine
896 'action' => $_GET['action'],
897 )
898 )
899 );
900 } else {
901 // @codingStandardsIgnoreLine
902 $_GET['action'] = 'add';
903 }
904 // @codingStandardsIgnoreLine
905 } elseif ( isset( $_GET['action'] ) && 'add' === $_GET['action'] ) {
906 pods_redirect(
907 pods_query_arg(
908 array(
909 'page' => 'pods-add-new',
910 'action' => '',
911 'id' => '',
912 'do' => '',
913 '_wpnonce' => '',
914 )
915 )
916 );
917 }//end if
918
919 $pod_types = $api->get_pod_types();
920 $storage_types = $api->get_storage_types();
921
922 $row = false;
923
924 $pod_types_found = [];
925 $sources_found = [];
926 $source_types = [];
927
928 $include_row_counts = filter_var( pods_v( 'pods_include_row_counts' ), FILTER_VALIDATE_BOOLEAN );
929 $include_row_counts_refresh = filter_var( pods_v( 'pods_include_row_counts_refresh' ), FILTER_VALIDATE_BOOLEAN );
930
931 $fields = [
932 'label' => [
933 'label' => __( 'Label', 'pods' ),
934 ],
935 'name' => [
936 'label' => __( 'Name', 'pods' ),
937 ],
938 'type' => [
939 'label' => __( 'Type', 'pods' ),
940 ],
941 'source' => [
942 'label' => __( 'Source', 'pods' ),
943 'width' => '10%',
944 'type' => 'raw',
945 ],
946 'storage' => [
947 'label' => __( 'Storage Type', 'pods' ),
948 'width' => '10%',
949 ],
950 'group_count' => [
951 'label' => __( 'Groups', 'pods' ),
952 'width' => '8%',
953 ],
954 'field_count' => [
955 'label' => __( 'Fields', 'pods' ),
956 'width' => '8%',
957 ],
958 ];
959
960 if ( $include_row_counts ) {
961 $fields['row_count'] = [
962 'label' => __( 'Data Rows', 'pods' ),
963 'width' => '8%',
964 ];
965
966 $fields['row_meta_count'] = [
967 'label' => __( 'Meta Rows', 'pods' ),
968 'width' => '8%',
969 ];
970
971 $fields['podsrel_count'] = [
972 // translators: "PodsRel" references the name of the Pods relationships table in the database.
973 'label' => __( 'PodsRel Rows', 'pods' ),
974 'width' => '10%',
975 ];
976 }
977
978 $total_groups = 0;
979 $total_fields = 0;
980 $total_rows = 0;
981 $total_row_meta = 0;
982 $total_podsrel_rows = 0;
983
984 /**
985 * Filters whether to extend internal Pods.
986 *
987 * @since 2.8.0
988 *
989 * @param bool $extend_internal Whether to extend internal Pods.
990 */
991 $extend_internal = apply_filters( 'pods_admin_setup_extend_pods_internal', false );
992
993 $pod_list = array();
994
995 $is_tableless = pods_tableless();
996
997 $has_source = false;
998 $has_storage_type = false;
999
1000 foreach ( $pods as $k => $pod ) {
1001 $pod_type = $pod['type'];
1002 $pod_type_label = null;
1003 $pod_storage = $pod['storage'];
1004
1005 if ( empty( $pod_type ) || ! is_string( $pod_type ) ) {
1006 $pod_type = 'post_type';
1007 }
1008
1009 if ( empty( $pod_storage ) || ! is_string( $pod_storage ) ) {
1010 $pod_storage = 'meta';
1011 }
1012
1013 $show_meta_count = 'meta' === $pod_storage || in_array( $pod['type'], [ 'post_type', 'taxonomy', 'user', 'comment' ], true );
1014
1015 if ( ! empty( $pod['internal'] ) ) {
1016 // Don't show internal if we aren't extending them.
1017 if ( ! $extend_internal ) {
1018 continue;
1019 }
1020
1021 $pod_type = 'internal';
1022 $pod_storage = 'meta';
1023 }
1024
1025 if ( 'settings' === $pod_type ) {
1026 $pod_storage = 'option';
1027 }
1028
1029 if ( 'meta' !== $pod_storage ) {
1030 $has_storage_type = true;
1031 }
1032
1033 if ( isset( $pod_types[ $pod_type ] ) ) {
1034 $pod_type_label = $pod_types[ $pod_type ];
1035 }
1036
1037 $pod_real_type = $pod_type;
1038
1039 $storage_type_label = ucwords( $pod_storage );
1040
1041 if ( isset( $storage_types[ $pod_storage ] ) ) {
1042 $storage_type_label = $storage_types[ $pod_storage ];
1043 }
1044
1045 if ( null !== $pod_type_label ) {
1046 if ( ! $pod->is_extended() && in_array( $pod_type, array(
1047 'post_type',
1048 'taxonomy',
1049 ), true ) ) {
1050 if ( 'post_type' === $pod_type ) {
1051 $pod_type = 'cpt';
1052 } else {
1053 $pod_type = 'ct';
1054 }
1055
1056 if ( isset( $pod_types[ $pod_type ] ) ) {
1057 $pod_type_label = $pod_types[ $pod_type ];
1058 }
1059 }
1060
1061 if ( ! isset( $pod_types_found[ $pod_type ] ) ) {
1062 $pod_types_found[ $pod_type ] = 1;
1063 } else {
1064 $pod_types_found[ $pod_type ] ++;
1065 }
1066
1067 if ( 'all' !== $view && $view !== $pod_type ) {
1068 continue;
1069 }
1070
1071 $pod_real_type = $pod_type;
1072 $pod_type = $pod_type_label;
1073 } elseif ( 'all' !== $view ) {
1074 continue;
1075 }//end if
1076
1077 $group_count = 0;
1078 $field_count = 0;
1079
1080 if ( ! pods_is_types_only( false, $pod->get_name() ) ) {
1081 $group_count = $pod->count_groups();
1082 $field_count = $pod->count_fields();
1083 }
1084
1085 if ( $include_row_counts ) {
1086 $count_transient_prefix = 'pods_admin_' . $pod['type'] . '_' . $pod['name'] . '_';
1087
1088 $row_counts = [
1089 'row_count' => false,
1090 'row_meta_count' => false,
1091 'podsrel_count' => false,
1092 ];
1093
1094 if ( ! $include_row_counts_refresh ) {
1095 $row_counts['row_count'] = pods_transient_get( $count_transient_prefix . 'row_count' );
1096 $row_counts['row_meta_count'] = pods_transient_get( $count_transient_prefix . 'row_meta_count' );
1097 $row_counts['podsrel_count'] = pods_transient_get( $count_transient_prefix . 'podsrel_count' );
1098 }
1099
1100 if ( ! is_numeric( $row_counts['row_count'] ) ) {
1101 $row_counts['row_count'] = $pod->count_rows();
1102
1103 pods_transient_set( $count_transient_prefix . 'row_count', $row_counts['row_count'], HOUR_IN_SECONDS * 3 );
1104 }
1105
1106 if ( $show_meta_count && ! is_numeric( $row_counts['row_meta_count'] ) ) {
1107 $row_counts['row_meta_count'] = $pod->count_row_meta();
1108
1109 pods_transient_set( $count_transient_prefix . 'row_meta_count', $row_counts['row_meta_count'], HOUR_IN_SECONDS * 3 );
1110 }
1111
1112 if ( ! $is_tableless && ! is_numeric( $row_counts['podsrel_count'] ) ) {
1113 $row_counts['podsrel_count'] = $pod->count_podsrel_rows();
1114
1115 pods_transient_set( $count_transient_prefix . 'podsrel_count', $row_counts['podsrel_count'], HOUR_IN_SECONDS * 3 );
1116 }
1117 }
1118
1119 $object_storage_type = $pod->get_object_storage_type();
1120 $source = $pod->get_object_storage_type_label();
1121
1122 if ( $source ) {
1123 $source_types[ $object_storage_type ] = $source;
1124
1125 if ( ! isset( $sources_found[ $object_storage_type ] ) ) {
1126 $sources_found[ $object_storage_type ] = 1;
1127 } else {
1128 $sources_found[ $object_storage_type ] ++;
1129 }
1130 }
1131
1132 $source = esc_html( $source );
1133
1134 if ( 'post_type' !== $object_storage_type ) {
1135 $has_source = true;
1136
1137 if ( 'file' === $object_storage_type ) {
1138 $file_source = $pod->get_arg( '_pods_file_source' );
1139
1140 if ( $file_source ) {
1141 if ( 0 === strpos( $file_source, ABSPATH ) ) {
1142 $file_source = str_replace( ABSPATH, '', $file_source );
1143 }
1144
1145 ob_start();
1146
1147 pods_help(
1148 sprintf(
1149 '<strong>%s:</strong> %s',
1150 esc_html__( 'File source', 'pods' ),
1151 esc_html( $file_source )
1152 ),
1153 null,
1154 '.pods-admin-container'
1155 );
1156
1157 $source .= ' ' . ob_get_clean();
1158 }
1159 } elseif ( 'collection' === $object_storage_type ) {
1160 $code_source = $pod->get_arg( '_pods_code_source' );
1161
1162 if ( $code_source ) {
1163 if ( 0 === strpos( $code_source, ABSPATH ) ) {
1164 $code_source = str_replace( ABSPATH, '', $code_source );
1165 }
1166
1167 ob_start();
1168
1169 pods_help(
1170 sprintf(
1171 '<strong>%s:</strong> %s',
1172 esc_html__( 'Code source', 'pods' ),
1173 esc_html( $code_source )
1174 ),
1175 null,
1176 '.pods-admin-container'
1177 );
1178
1179 $source .= ' ' . ob_get_clean();
1180 }
1181 }
1182 }
1183
1184 $pod = [
1185 'id' => $pod['id'],
1186 'label' => $pod['label'],
1187 'name' => $pod['name'],
1188 'object' => $pod['object'],
1189 'type' => $pod_type,
1190 'real_type' => $pod_real_type,
1191 'storage' => $storage_type_label,
1192 'source' => $source,
1193 'pod_object' => $pod,
1194 ];
1195
1196 if ( ! pods_is_types_only( false, $pod['name'] ) ) {
1197 $pod['group_count'] = number_format_i18n( $group_count );
1198 $pod['field_count'] = number_format_i18n( $field_count );
1199
1200 $total_groups += $group_count;
1201 $total_fields += $field_count;
1202 }
1203
1204 if ( $include_row_counts ) {
1205 $pod['row_count'] = number_format_i18n( $row_counts['row_count'] );
1206
1207 $total_rows += $row_counts['row_count'];
1208
1209 $pod['row_meta_count'] = 'n/a';
1210 $pod['podsrel_count'] = 'n/a';
1211
1212 if ( $show_meta_count ) {
1213 $pod['row_meta_count'] = number_format_i18n( $row_counts['row_meta_count'] );
1214
1215 $total_row_meta += $row_counts['row_meta_count'];
1216 }
1217
1218 if ( ! $is_tableless ) {
1219 $pod['podsrel_count'] = number_format_i18n( $row_counts['podsrel_count'] );
1220
1221 $total_podsrel_rows += $row_counts['podsrel_count'];
1222 }
1223 }
1224
1225 // @codingStandardsIgnoreLine
1226 if ( 'manage' !== pods_v( 'action' ) ) {
1227 $found_id = (int) pods_v( 'id' );
1228 $found_name = pods_v( 'name' );
1229
1230 if (
1231 (
1232 $found_id
1233 && $pod['id'] === $found_id
1234 )
1235 || (
1236 $found_name
1237 && $pod['name'] === $found_name
1238 )
1239 ) {
1240 $row = $pod;
1241 }
1242 }
1243
1244 $pod_list[] = $pod;
1245 }//end foreach
1246
1247 if ( ! $has_storage_type ) {
1248 unset( $fields['storage'] );
1249 }
1250
1251 if ( ! $has_source ) {
1252 unset( $fields['source'] );
1253 }
1254
1255 if (
1256 (
1257 0 === $total_groups
1258 && 0 === $total_fields
1259 )
1260 || pods_is_types_only()
1261 ) {
1262 unset( $fields['group_count'], $fields['field_count'] );
1263 }
1264
1265 if ( false === $row && 0 < pods_v( 'id' ) && 'delete' !== pods_v( 'action' ) ) {
1266 pods_message( 'Pod not found', 'error' );
1267
1268 // @codingStandardsIgnoreLine
1269 unset( $_GET['id'], $_GET['action'] );
1270 }
1271
1272 $total_pods = count( $pod_list );
1273
1274 $extra_total_text = '';
1275
1276 if ( ! pods_is_types_only() ) {
1277 $extra_total_text .= sprintf(
1278 ', %1$s %2$s, %3$s %4$s',
1279 number_format_i18n( $total_groups ),
1280 _n( 'group', 'groups', $total_groups, 'pods' ),
1281 number_format_i18n( $total_fields ),
1282 _n( 'field', 'fields', $total_fields, 'pods' )
1283 );
1284 }
1285
1286 if ( $include_row_counts ) {
1287 $extra_total_text .= sprintf(
1288 ', %1$s %2$s, %3$s %4$s, %5$s %6$s',
1289 number_format_i18n( $total_rows ),
1290 _n( 'data row', 'data rows', $total_rows, 'pods' ),
1291 number_format_i18n( $total_row_meta ),
1292 _n( 'meta row', 'meta rows', $total_row_meta, 'pods' ),
1293 number_format_i18n( $total_podsrel_rows ),
1294 // translators: "podsrel" references the name of the Pods relationships table in the database.
1295 _n( 'podsrel row', 'podsrel rows', $total_podsrel_rows, 'pods' )
1296 );
1297 }
1298
1299 $pod_list = wp_list_sort( $pod_list, 'label', 'ASC', true );
1300
1301 $ui = [
1302 'data' => $pod_list,
1303 'row' => $row,
1304 'total' => $total_pods,
1305 'total_found' => $total_pods,
1306 'items' => 'Pods',
1307 'item' => 'Pod',
1308 'fields' => [
1309 'manage' => $fields,
1310 ],
1311 'sql' => [
1312 'field_id' => 'id',
1313 'field_index' => 'label',
1314 ],
1315 'actions_disabled' => [ 'view', 'export', 'delete', 'duplicate' ],
1316 'actions_custom' => [
1317 'add' => [ $this, 'admin_setup_add' ],
1318 'edit' => [
1319 'callback' => [ $this, 'admin_setup_edit' ],
1320 'restrict_callback' => [ $this, 'admin_setup_edit_restrict' ],
1321 ],
1322 'duplicate_pod' => [
1323 'label' => __( 'Duplicate', 'pods' ),
1324 'callback' => [ $this, 'admin_setup_duplicate' ],
1325 'restrict_callback' => [ $this, 'admin_setup_duplicate_restrict' ],
1326 'nonce' => true,
1327 ],
1328 'delete_pod' => [
1329 'label' => __( 'Delete', 'pods' ),
1330 'confirm' => __( 'Are you sure you want to delete this Pod?', 'pods' )
1331 . "\n\n"
1332 . __( 'All of the content and items will remain in the database.', 'pods' )
1333 . "\n\n"
1334 . __( 'You may want to go to Pods Admin > Settings > Cleanup & Reset > "Delete all content for a Pod" first.', 'pods' ),
1335 'callback' => [ $this, 'admin_setup_delete' ],
1336 'restrict_callback' => [ $this, 'admin_setup_delete_restrict' ],
1337 'nonce' => true,
1338 'span_class' => 'delete',
1339 ],
1340 ],
1341 'action_links' => [
1342 'add' => pods_query_arg( [
1343 'page' => 'pods-add-new',
1344 'action' => '',
1345 'id' => '',
1346 'do' => '',
1347 '_wpnonce' => '',
1348 ] ),
1349 'duplicate_pod' => pods_query_arg( [
1350 'action' => 'duplicate_pod',
1351 'id' => '{@id}',
1352 'name' => '{@name}',
1353 ] ),
1354 ],
1355 'search' => false,
1356 'searchable' => false,
1357 'sortable' => true,
1358 'pagination' => false,
1359 'extra' => [
1360 'total' => $extra_total_text,
1361 ],
1362 ];
1363
1364 if ( 1 < count( $pod_types_found ) ) {
1365 $ui['views'] = [ 'all' => __( 'All', 'pods' ) . ' (' . $total_pods . ')' ];
1366 $ui['view'] = $view;
1367 $ui['heading'] = [ 'views' => __( 'Type', 'pods' ) ];
1368 $ui['filters_enhanced'] = true;
1369
1370 foreach ( $pod_types_found as $pod_type => $number_found ) {
1371 $ui['views'][ $pod_type ] = sprintf(
1372 '%1$s (%2$s)',
1373 $pod_types[ $pod_type ],
1374 number_format_i18n( $number_found )
1375 );
1376 }
1377
1378 if ( $has_source && 1 < count( $sources_found ) ) {
1379 foreach ( $sources_found as $source_type => $number_found ) {
1380 $ui['views'][ 'source/' . $source_type ] = sprintf(
1381 '%1$s: %2$s (%3$s)',
1382 __( 'Source', 'pods' ),
1383 $source_types[ $source_type ],
1384 $number_found
1385 );
1386 }
1387 }
1388 }
1389
1390 // Add our custom callouts.
1391 $this->handle_callouts_updates();
1392
1393 add_filter( 'pods_ui_manage_custom_container_classes', array( $this, 'admin_manage_container_class' ) );
1394 add_action( 'pods_ui_manage_after_container', array( $this, 'admin_manage_callouts' ) );
1395
1396 pods_ui( $ui );
1397 }
1398
1399 /**
1400 * Get list of callouts to show.
1401 *
1402 * @since 2.7.17
1403 *
1404 * @return array List of callouts.
1405 */
1406 public function get_callouts() {
1407 // Demo mode always bypasses callouts.
1408 if ( pods_is_demo() ) {
1409 return [];
1410 }
1411
1412 $force_callouts = false;
1413
1414 $page = pods_v( 'page' );
1415
1416 if ( in_array( $page, array( 'pods-settings', 'pods-help' ), true ) ) {
1417 $force_callouts = true;
1418 }
1419
1420 $callouts = get_option( 'pods_callouts' );
1421
1422 if ( ! $callouts ) {
1423 $callouts = array(
1424 'friends_2022_30' => 1,
1425 );
1426 }
1427
1428 // Handle Friends of Pods callout logic.
1429 $callouts['friends_2022_30'] = ! isset( $callouts['friends_2022_30'] ) || $callouts['friends_2022_30'] || $force_callouts ? 1 : 0;
1430
1431 /**
1432 * Allow hooking into whether or not the specific callouts should show.
1433 *
1434 * @since 2.7.17
1435 *
1436 * @param array List of callouts to enable.
1437 */
1438 $callouts = apply_filters( 'pods_admin_callouts', $callouts );
1439
1440 return $callouts;
1441 }
1442
1443 /**
1444 * Handle callouts update logic.
1445 *
1446 * @since 2.7.17
1447 */
1448 public function handle_callouts_updates() {
1449 // Don't show callouts right now until Pods 3.0.
1450 return;
1451
1452 $callouts = get_option( 'pods_callouts' );
1453
1454 if ( ! $callouts ) {
1455 $callouts = array();
1456 }
1457
1458 $callout_dismiss = pods_v( 'pods_callout_dismiss' );
1459
1460 // Demo mode will auto-update the option for future loads.
1461 $is_demo = pods_is_demo();
1462
1463 // Disable Friends of Pods callout.
1464 if ( $is_demo || 'friends_2022_30' === $callout_dismiss ) {
1465 $callouts['friends_2022_30'] = 0;
1466
1467 update_option( 'pods_callouts', $callouts );
1468 } elseif ( 'reset' === $callout_dismiss ) {
1469 $callouts = array();
1470
1471 update_option( 'pods_callouts', $callouts );
1472 }
1473 }
1474
1475 /**
1476 * Add class to container if we have callouts to show.
1477 *
1478 * @since 2.7.17
1479 *
1480 * @param array $classes List of classes to use.
1481 *
1482 * @return array List of classes to use.
1483 */
1484 public function admin_manage_container_class( $classes ) {
1485 $callouts = $this->get_callouts();
1486
1487 // Only get enabled callouts.
1488 $callouts = array_filter( $callouts );
1489
1490 if ( ! empty( $callouts ) ) {
1491 $classes[] = 'pods-admin--flex';
1492 }
1493
1494 return $classes;
1495 }
1496
1497 /**
1498 * Add callouts to let admins know about certain things.
1499 *
1500 * @since 2.7.17
1501 */
1502 public function admin_manage_callouts() {
1503 $force_callouts = false;
1504
1505 $page = pods_v( 'page' );
1506
1507 if ( in_array( $page, array( 'pods-settings', 'pods-help' ), true ) ) {
1508 $force_callouts = true;
1509 }
1510
1511 $callouts = $this->get_callouts();
1512
1513 if ( ! empty( $callouts['friends_2022_30'] ) ) {
1514 pods_view( PODS_DIR . 'ui/admin/callouts/friends_2022_30.php', compact( array_keys( get_defined_vars() ) ) );
1515 }
1516 }
1517
1518 /**
1519 * Get the add page of an object
1520 *
1521 * @param PodsUI $obj PodsUI object.
1522 */
1523 public function admin_setup_add( $obj ) {
1524 pods_view( PODS_DIR . 'ui/admin/setup-add.php', compact( array_keys( get_defined_vars() ) ) );
1525 }
1526
1527 /**
1528 * Get the edit page of an object
1529 *
1530 * @param boolean $duplicate Whether the screen is for duplicating.
1531 * @param PodsUI $obj PodsUI object.
1532 */
1533 public function admin_setup_edit( $duplicate, $obj ) {
1534 $api = pods_api();
1535
1536 $pod = $obj->row['pod_object'];
1537
1538 if ( ! $pod instanceof Pod ) {
1539 $obj->id = null;
1540 $obj->row = [];
1541 $obj->action = 'manage';
1542
1543 $obj->error( __( 'Invalid Pod configuration detected.', 'pods' ) );
1544 $obj->manage();
1545
1546 return null;
1547 }
1548
1549 if ( 'post_type' !== $pod->get_object_storage_type() ) {
1550 $obj->id = null;
1551 $obj->row = [];
1552 $obj->action = 'manage';
1553
1554 // translators: %s: The pod label.
1555 $obj->error( sprintf( __( 'Unable to edit the "%s" Pod configuration.', 'pods' ), $pod->get_label() ) );
1556 $obj->manage();
1557
1558 return null;
1559 }
1560
1561 $original_field_count = 0;
1562
1563 foreach ( $obj->data as $row ) {
1564 if ( (int) $row['id'] === (int) $obj->id ) {
1565 if ( ! isset( $row['field_count'] ) ) {
1566 $row['field_count'] = 0;
1567 }
1568
1569 $original_field_count = (int) $row['field_count'];
1570
1571 break;
1572 }
1573 }
1574
1575 $find_orphan_fields = (
1576 1 === (int) pods_v( 'pods_debug_find_orphan_fields', 'get', 0 )
1577 && pods_is_admin( array( 'pods' ) )
1578 );
1579
1580 $migrated = false;
1581
1582 if ( $find_orphan_fields || 1 !== (int) $pod->get_arg( '_migrated_28' ) ) {
1583 $pod = $this->maybe_migrate_pod_fields_into_group( $pod );
1584
1585 $migrated = true;
1586
1587 // Maybe redirect the page to reload it fresh.
1588 if ( $find_orphan_fields ) {
1589 pods_redirect( pods_query_arg( [ 'pods_debug_find_orphan_fields' => null ] ) );
1590 die();
1591 }
1592
1593 // Check again in case the pod migrated wrong.
1594 if ( ! $pod instanceof Pod ) {
1595 $obj->id = null;
1596 $obj->row = [];
1597 $obj->action = 'manage';
1598
1599 $obj->error( __( 'Invalid Pod configuration detected.', 'pods' ) );
1600 $obj->manage();
1601
1602 return null;
1603 }
1604 }
1605
1606 $current_pod = $pod->export( [
1607 'include_groups' => true,
1608 'include_group_fields' => true,
1609 'include_fields' => false,
1610 ] );
1611
1612 $group_field_count = wp_list_pluck( $current_pod['groups'], 'fields' );
1613 $group_field_count = array_map( 'count', $group_field_count );
1614 $group_field_count = array_sum( $group_field_count );
1615
1616 // Detect if there may be a migration/repair needed.
1617 if ( $original_field_count !== $group_field_count ) {
1618 if ( ! $migrated ) {
1619 $pod = $this->maybe_migrate_pod_fields_into_group( $pod );
1620
1621 // Check again in case the pod migrated wrong.
1622 if ( ! $pod instanceof Pod ) {
1623 $obj->id = null;
1624 $obj->row = [];
1625 $obj->action = 'manage';
1626
1627 $obj->error( __( 'Invalid Pod configuration detected.', 'pods' ) );
1628 $obj->manage();
1629
1630 return null;
1631 }
1632
1633 $current_pod = $pod->export( [
1634 'include_groups' => true,
1635 'include_group_fields' => true,
1636 'include_fields' => false,
1637 ] );
1638 } else {
1639 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' ) );
1640 }
1641 }
1642
1643 $config = [
1644 'currentPod' => $current_pod,
1645 'global' => $this->get_global_config( $pod ),
1646 'fieldTypes' => PodsForm::field_types(),
1647 'relatedObjects' => $this->get_field_related_objects(),
1648 'podTypes' => $api->get_pod_types(),
1649 'storageTypes' => $api->get_storage_types(),
1650 // @todo SKC: Remove these below and replace any references to podsDFVConfig
1651 'wp_locale' => $GLOBALS['wp_locale'],
1652 'userLocale' => str_replace( '_', '-', get_user_locale() ),
1653 'currencies' => PodsField_Currency::data_currencies(),
1654 'datetime' => [
1655 'start_of_week' => (int) get_option( 'start_of_week', 0 ),
1656 'gmt_offset' => (int) get_option( 'gmt_offset', 0 ),
1657 ],
1658 ];
1659
1660 $config['currentPod']['podType'] = [
1661 'name' => $config['currentPod']['type'],
1662 ];
1663
1664 $config['currentPod']['storageType'] = [
1665 'name' => $config['currentPod']['storage'],
1666 ];
1667
1668 if ( ! empty( $config['currentPod']['internal'] ) ) {
1669 $config['currentPod']['podType']['name'] = 'internal';
1670 } elseif ( ! $pod->is_extended() ) {
1671 if ( 'post_type' === $config['currentPod']['type'] ) {
1672 $config['currentPod']['podType']['name'] = 'cpt';
1673 } elseif ( 'taxonomy' === $config['currentPod']['type'] ) {
1674 $config['currentPod']['podType']['name'] = 'ct';
1675 }
1676 }
1677
1678 $config['currentPod']['podType']['label'] = ucwords( str_replace( '_', ' ', $config['currentPod']['podType']['name'] ) );
1679
1680 if ( ! empty( $config['podTypes'][ $config['currentPod']['podType']['name'] ] ) ) {
1681 $config['currentPod']['podType']['label'] = $config['podTypes'][ $config['currentPod']['podType']['name'] ];
1682 }
1683
1684 if ( 'settings' === $config['currentPod']['type'] ) {
1685 $config['currentPod']['storageType']['name'] = 'option';
1686 }
1687
1688 $config['currentPod']['storageType']['label'] = ucwords( $config['currentPod']['storageType']['name'] );
1689
1690 if ( ! empty( $config['storageTypes'][ $config['currentPod']['storageType']['name'] ] ) ) {
1691 $config['currentPod']['storageType']['label'] = $config['storageTypes'][ $config['currentPod']['storageType']['name'] ];
1692 }
1693
1694 /**
1695 * Allow filtering the admin config data.
1696 *
1697 * @since 2.8.0
1698 *
1699 * @param array $config The admin config data.
1700 * @param Pod $pod The pod object.
1701 * @param PodsUI $obj The PodsUI object.
1702 */
1703 $config = apply_filters( 'pods_admin_setup_edit_pod_config', $config, $pod, $obj );
1704
1705 wp_localize_script( 'pods-dfv', 'podsAdminConfig', $config );
1706
1707 pods_view( PODS_DIR . 'ui/admin/setup-edit.php', compact( array_keys( get_defined_vars() ) ) );
1708 }
1709
1710 /**
1711 * Restrict Edit action.
1712 *
1713 * @param bool $restricted Whether action is restricted.
1714 * @param array $restrict Restriction array.
1715 * @param string $action Current action.
1716 * @param array $row Item data row.
1717 * @param PodsUI $obj PodsUI object.
1718 *
1719 * @since 2.3.10
1720 *
1721 * @return bool
1722 */
1723 public function admin_setup_edit_restrict( $restricted, $restrict, $action, $row, $obj ) {
1724 if ( __( 'DB', 'pods' ) !== $row['source'] ) {
1725 $restricted = true;
1726 }
1727
1728 return $restricted;
1729 }
1730
1731 /**
1732 * Get list of field related objects.
1733 *
1734 * @since 2.8.0
1735 *
1736 * @return array List of field related objects.
1737 */
1738 protected function get_field_related_objects() {
1739 $related_object_groups = PodsForm::field_method( 'pick', 'related_objects', true );
1740
1741 $related_objects = [];
1742
1743 foreach ( $related_object_groups as $group => $group_objects ) {
1744 foreach ( $group_objects as $name => $label ) {
1745 $related_objects[ $name ] = [
1746 'name' => $name,
1747 'label' => $label,
1748 ];
1749 }
1750 }
1751
1752 return $related_objects;
1753 }
1754
1755 /**
1756 * Maybe migrate pod fields into a group (if they have no group).
1757 *
1758 * @since 2.8.0
1759 *
1760 * @param Pod $pod The pod object.
1761 *
1762 * @return Pod The pod object.
1763 */
1764 public function maybe_migrate_pod_fields_into_group( $pod ) {
1765 $tool = pods_container( Repair::class );
1766
1767 $results = $tool->repair_groups_and_fields_for_pod( $pod, 'upgrade' );
1768
1769 if ( '' !== $results['message_html'] ) {
1770 if ( 'pods' === pods_v( 'page' ) && 'edit' === pods_v( 'action' ) && 'create' === pods_v( 'do' ) ) {
1771 // Refresh the page if we just added the Pod.
1772 pods_redirect();
1773 } else {
1774 pods_message( $results['message_html'] );
1775 }
1776 }
1777
1778 return $results['upgraded_pod'];
1779 }
1780
1781 /**
1782 * Get the global config for Pods admin.
1783 *
1784 * @param null|\Pods\Whatsit $current_pod
1785 *
1786 * @return array Global config array.
1787 *@since 2.8.0
1788 *
1789 */
1790 public function get_global_config( $current_pod = null ) {
1791 $config_pod = pods_container( Config_Pod::class );
1792 $config_group = pods_container( Config_Group::class );
1793 $config_field = pods_container( Config_Field::class );
1794
1795 // Pod: Backwards compatible configs and hooks.
1796 $pod_tabs = $config_pod->get_tabs( $current_pod);
1797 $pod_tab_options = $config_pod->get_fields( $current_pod, $pod_tabs );
1798
1799 $this->backcompat_convert_tabs_to_groups( $pod_tabs, $pod_tab_options, 'pod/_pods_pod' );
1800
1801 // If not types-only mode, handle groups/fields configs.
1802 if ( ! pods_is_types_only( false, $current_pod->get_name() ) ) {
1803 // Group: Backwards compatible methods and hooks.
1804 $group_tabs = $config_group->get_tabs( $current_pod);
1805 $group_tab_options = $config_group->get_fields( $current_pod, $group_tabs );
1806
1807 $this->backcompat_convert_tabs_to_groups( $group_tabs, $group_tab_options, 'pod/_pods_group' );
1808
1809 // Field: Backwards compatible methods and hooks.
1810 $field_tabs = $config_field->get_tabs( $current_pod);
1811 $field_tab_options = $config_field->get_fields( $current_pod, $field_tabs );
1812
1813 $this->backcompat_convert_tabs_to_groups( $field_tabs, $field_tab_options, 'pod/_pods_field' );
1814 }
1815
1816 $object_collection = Pods\Whatsit\Store::get_instance();
1817
1818 /** @var Pods\Whatsit\Storage $storage */
1819 $storage = $object_collection->get_storage_object( 'collection' );
1820
1821 // Get objects from storage.
1822 $pod_object = $storage->get( [
1823 'object_type' => 'pod',
1824 'name' => '_pods_pod',
1825 ] );
1826
1827 $group_object = $storage->get( [
1828 'object_type' => 'pod',
1829 'name' => '_pods_group',
1830 ] );
1831
1832 $field_object = $storage->get( [
1833 'object_type' => 'pod',
1834 'name' => '_pods_field',
1835 ] );
1836
1837 $global_config = [
1838 'showFields' => ! pods_is_types_only( false, $current_pod->get_name() ),
1839 'pod' => $pod_object->export( [
1840 'include_groups' => true,
1841 'include_group_fields' => true,
1842 'include_fields' => false,
1843 'include_field_data' => true,
1844 ] ),
1845 'group' => $group_object->export( [
1846 'include_groups' => true,
1847 'include_group_fields' => true,
1848 'include_fields' => false,
1849 'include_field_data' => true,
1850 ] ),
1851 'field' => $field_object->export( [
1852 'include_groups' => true,
1853 'include_group_fields' => true,
1854 'include_fields' => false,
1855 'include_field_data' => true,
1856 ] ),
1857 ];
1858
1859 /**
1860 * Allow hooking into the global config setup for a Pod.
1861 *
1862 * @param array $global_config The global config object.
1863 * @param null|\Pods\Whatsit $current_pod The Pod object.
1864 */
1865 $global_config = apply_filters( 'pods_admin_setup_global_config', $global_config, $current_pod );
1866
1867 return $global_config;
1868 }
1869
1870 /**
1871 * Convert the tabs and their options to groups/fields in the collection storage.
1872 *
1873 * @since 2.8.0
1874 *
1875 * @param array $tabs List of registered tabs.
1876 * @param array $options List of tab options.
1877 * @param string $parent The parent object to register to.
1878 *
1879 * @return array Global config array.
1880 */
1881 protected function backcompat_convert_tabs_to_groups( array $tabs, array $options, $parent ) {
1882 $object_collection = Pods\Whatsit\Store::get_instance();
1883
1884 /** @var Pods\Whatsit\Storage\Collection $storage */
1885 $storage = $object_collection->get_storage_object( 'collection' );
1886
1887 $groups = [];
1888 $fields = [];
1889
1890 foreach ( $tabs as $group_name => $group_label ) {
1891 if ( empty( $options[ $group_name ] ) ) {
1892 continue;
1893 }
1894
1895 if ( is_array( $group_label ) ) {
1896 $group_args = $group_label;
1897 } else {
1898 $group_args = [
1899 'name' => $group_name,
1900 'label' => $group_label,
1901 ];
1902 }
1903
1904 $group_args['parent'] = $parent;
1905
1906 $group = new \Pods\Whatsit\Group( $group_args );
1907
1908 $groups[] = $storage->add( $group );
1909
1910 $group_fields = $options[ $group_name ];
1911
1912 $sections = false;
1913
1914 foreach ( $group_fields as $field_name => $field_options ) {
1915 // Support sections.
1916 if ( ! isset( $field_options['label'] ) ) {
1917 $sections = true;
1918 }
1919
1920 break;
1921 }
1922
1923 $group_sections = $group_fields;
1924
1925 // Store the same whether it's a section or not.
1926 if ( ! $sections ) {
1927 $group_sections = [
1928 $group_fields,
1929 ];
1930 }
1931
1932 foreach ( $group_sections as $section_label => $section_fields ) {
1933 // Add section field (maybe).
1934 if ( ! is_int( $section_label ) ) {
1935 $field_args = [
1936 'name' => sanitize_title( $section_label ),
1937 'label' => $section_label,
1938 'type' => 'heading',
1939 'parent' => $parent,
1940 'group' => 'group/' . $parent . '/' . $group_name,
1941 ];
1942
1943 $field = new \Pods\Whatsit\Field( $field_args );
1944
1945 $fields[] = $storage->add( $field );
1946 }
1947
1948 if ( ! is_array( $section_fields ) ) {
1949 continue;
1950 }
1951
1952 // Add fields for section.
1953 foreach ( $section_fields as $field_name => $field_options ) {
1954 $boolean_group = [];
1955
1956 // Handle auto-formatting from shorthand.
1957 if ( ! empty( $field_options['boolean_group'] ) ) {
1958 $boolean_group = $field_options['boolean_group'];
1959
1960 foreach ( $boolean_group as $bgf_key => $boolean_group_field ) {
1961 // Make sure each field has a field name.
1962 if ( is_string( $bgf_key ) ) {
1963 $boolean_group[ $bgf_key ]['name'] = $bgf_key;
1964 }
1965 }
1966
1967 $boolean_group = array_values( $boolean_group );
1968
1969 $field_options['boolean_group'] = $boolean_group;
1970 }
1971
1972 if ( empty( $field_options['type'] ) ) {
1973 continue;
1974 }
1975
1976 // Set a unique field name for boolean group headings.
1977 if ( ! empty( $boolean_group ) ) {
1978 $field_options['name'] = $field_name . '_' . md5( json_encode( $boolean_group ) );
1979 }
1980
1981 $field = $this->backcompat_convert_tabs_to_groups_setup_field( [
1982 'field_name' => $field_name,
1983 'field_options' => $field_options,
1984 'parent' => $parent,
1985 'group_name' => $group_name,
1986 ] );
1987
1988 $fields[] = $storage->add( $field );
1989 }
1990 }
1991 }
1992
1993 return compact( 'groups', 'fields' );
1994 }
1995
1996 /**
1997 * Setup field for backwards compatibility tabs to groups layer.
1998 *
1999 * @since 2.8.0
2000 *
2001 * @param array $args {
2002 * The field arguments.
2003 *
2004 * @type string $field_name The field name.
2005 * @type array $field_options The field options.
2006 * @type string|int $parent The parent group.
2007 * @type string $group_name The group name.
2008 * }
2009 *
2010 * @return \Pods\Whatsit\Field The field object.
2011 */
2012 public function backcompat_convert_tabs_to_groups_setup_field( $args ) {
2013 $field_name = $args['field_name'];
2014 $field_options = $args['field_options'];
2015 $parent = $args['parent'];
2016 $group_name = $args['group_name'];
2017
2018 $field_args = $field_options;
2019
2020 if ( ! isset( $field_args['name'] ) ) {
2021 $field_args['name'] = $field_name;
2022 }
2023
2024 $field_args['parent'] = $parent;
2025 $field_args['group'] = 'group/' . $parent . '/' . $group_name;
2026
2027 $dfv_args = (object) [
2028 'id' => 0,
2029 'name' => $field_args['name'],
2030 'value' => '',
2031 'pod' => null,
2032 'type' => pods_v( 'type', $field_args ),
2033 'options' => array_merge( [
2034 'id' => 0,
2035 ], $field_args )
2036 ];
2037
2038 if ( ! empty( $dfv_args->type ) ) {
2039 $field_args = PodsForm::field_method( $dfv_args->type, 'build_dfv_field_options', $field_args, $dfv_args );
2040 }
2041
2042 return new \Pods\Whatsit\Field( $field_args );
2043 }
2044
2045 /**
2046 * Duplicate a pod
2047 *
2048 * @param PodsUI $obj PodsUI object.
2049 */
2050 public function admin_setup_duplicate( $obj ) {
2051 $new_id = pods_api()->duplicate_pod( array( 'name' => $obj->row['name'] ) );
2052
2053 if ( 0 < $new_id ) {
2054 pods_redirect(
2055 pods_query_arg(
2056 array(
2057 'action' => 'edit',
2058 'id' => $new_id,
2059 'do' => 'duplicate',
2060 'name' => null,
2061 )
2062 )
2063 );
2064
2065 return;
2066 }
2067
2068 $obj->error( __( 'An error occurred, the Pod was not duplicated.', 'pods' ) );
2069 }
2070
2071 /**
2072 * Restrict Duplicate action to custom types, not extended
2073 *
2074 * @param bool $restricted Whether action is restricted.
2075 * @param array $restrict Restriction array.
2076 * @param string $action Current action.
2077 * @param array $row Item data row.
2078 * @param PodsUI $obj PodsUI object.
2079 *
2080 * @since 2.3.10
2081 *
2082 * @return bool
2083 */
2084 public function admin_setup_duplicate_restrict( $restricted, $restrict, $action, $row, $obj ) {
2085 if ( in_array(
2086 $row['real_type'], array(
2087 'user',
2088 'media',
2089 'comment',
2090 ), true
2091 ) ) {
2092 $restricted = true;
2093 }
2094
2095 return $restricted;
2096 }
2097
2098 /**
2099 * Delete a pod
2100 *
2101 * @param PodsUI $obj PodsUI object.
2102 * @param int|string $id Item ID.
2103 *
2104 * @return mixed
2105 */
2106 public function admin_setup_delete( $obj, $id ) {
2107
2108 $pod = pods_api()->load_pod( array( 'id' => $id ), false );
2109
2110 if ( empty( $pod ) ) {
2111 return $obj->error( __( 'Pod not found.', 'pods' ) );
2112 }
2113
2114 pods_api()->delete_pod( array( 'id' => $id ) );
2115
2116 foreach ( $obj->data as $key => $data_pod ) {
2117 if ( (int) $id === (int) $data_pod['id'] ) {
2118 unset( $obj->data[ $key ] );
2119 }
2120 }
2121
2122 $obj->total = count( $obj->data );
2123 $obj->total_found = count( $obj->data );
2124
2125 $obj->message( __( 'Pod deleted successfully.', 'pods' ) );
2126
2127 $obj->manage();
2128 }
2129
2130 /**
2131 * Restrict Delete action.
2132 *
2133 * @param bool $restricted Whether action is restricted.
2134 * @param array $restrict Restriction array.
2135 * @param string $action Current action.
2136 * @param array $row Item data row.
2137 * @param PodsUI $obj PodsUI object.
2138 *
2139 * @since 2.3.10
2140 *
2141 * @return bool
2142 */
2143 public function admin_setup_delete_restrict( $restricted, $restrict, $action, $row, $obj ) {
2144 if ( __( 'DB', 'pods' ) !== $row['source'] ) {
2145 $restricted = true;
2146 }
2147
2148 return $restricted;
2149 }
2150
2151 /**
2152 * Get advanced administration view.
2153 */
2154 public function admin_advanced() {
2155
2156 pods_view( PODS_DIR . 'ui/admin/advanced.php', compact( array_keys( get_defined_vars() ) ) );
2157 }
2158
2159 /**
2160 * Get settings administration view
2161 */
2162 public function admin_settings() {
2163 $hide_notice = filter_var( get_option( 'pods_tmp_hide_notice_31', false ), FILTER_VALIDATE_BOOLEAN );
2164
2165 if ( ! $hide_notice ) {
2166 if (
2167 ! empty( $_GET['hide_notice_31'] )
2168 && ! empty( $_GET['hide_notice_31_nonce'] )
2169 && wp_verify_nonce( $_GET['hide_notice_31_nonce'], 'hide_notice_31' )
2170 ) {
2171 update_option( 'pods_tmp_hide_notice_31', 1, 'no' );
2172 } else {
2173 pods_message(
2174 sprintf(
2175 '⚠️ %s <a href="%s">%s</a>',
2176 __( 'You are running an outdated version of Pods. Upgrade to Pods 3.1 to get the most out of Access Rights, security fixes, and future features.', 'pods' ),
2177 esc_url( add_query_arg( [ 'hide_notice_31' => 1, 'hide_notice_31_nonce' => wp_create_nonce( 'hide_notice_31' ) ] ) ),
2178 __( 'Hide this notice', 'pods' )
2179 ),
2180 'error'
2181 );
2182 }
2183 }
2184
2185 /**
2186 * Allow hooking into our settings page to set up hooks.
2187 *
2188 * @since 2.8.0
2189 */
2190 do_action( 'pods_admin_settings_init' );
2191
2192 // Add our custom callouts.
2193 add_action( 'pods_admin_after_settings', array( $this, 'admin_manage_callouts' ) );
2194
2195 pods_view( PODS_DIR . 'ui/admin/settings.php', compact( array_keys( get_defined_vars() ) ) );
2196 }
2197
2198 /**
2199 * Get components administration UI
2200 */
2201 public function admin_components() {
2202
2203 if ( ! is_object( PodsInit::$components ) ) {
2204 return;
2205 }
2206
2207 $components = PodsInit::$components->components;
2208
2209 $view = pods_v( 'view', 'get', 'all', true );
2210
2211 $recommended = array(
2212 'advanced-relationships',
2213 'advanced-content-types',
2214 'migrate-packages',
2215 'roles-and-capabilities',
2216 'pages',
2217 'table-storage',
2218 'templates',
2219 );
2220
2221 foreach ( $components as $component => &$component_data ) {
2222 if ( ! in_array(
2223 $view, array(
2224 'all',
2225 'recommended',
2226 'dev',
2227 ), true
2228 ) && ( ! isset( $component_data['Category'] ) || sanitize_title( $component_data['Category'] ) !== $view ) ) {
2229 unset( $components[ $component ] );
2230
2231 continue;
2232 } elseif ( 'recommended' === $view && ! in_array( $component_data['ID'], $recommended, true ) ) {
2233 unset( $components[ $component ] );
2234
2235 continue;
2236 } elseif ( 'dev' === $view && pods_developer() && ! pods_v( 'DeveloperMode', $component_data, false ) ) {
2237 unset( $components[ $component ] );
2238
2239 continue;
2240 } elseif ( pods_v( 'DeveloperMode', $component_data, false ) && ! pods_developer() ) {
2241 unset( $components[ $component ] );
2242
2243 continue;
2244 } elseif ( ! pods_v( 'TablelessMode', $component_data, false ) && pods_tableless() ) {
2245 unset( $components[ $component ] );
2246
2247 continue;
2248 }//end if
2249
2250 $component_data['Name'] = strip_tags( $component_data['Name'] );
2251
2252 if ( pods_v( 'DeveloperMode', $component_data, false ) ) {
2253 $component_data['Name'] .= ' <em style="font-weight: normal; color:#333;">(Developer Preview)</em>';
2254 }
2255
2256 $meta = array();
2257
2258 if ( ! empty( $component_data['Version'] ) ) {
2259 $meta[] = sprintf( __( 'Version %s', 'pods' ), $component_data['Version'] );
2260 }
2261
2262 if ( empty( $component_data['Author'] ) ) {
2263 $component_data['Author'] = 'Pods Framework Team';
2264 $component_data['AuthorURI'] = 'https://pods.io/';
2265 }
2266
2267 if ( ! empty( $component_data['AuthorURI'] ) ) {
2268 $component_data['Author'] = '<a href="' . $component_data['AuthorURI'] . '">' . $component_data['Author'] . '</a>';
2269 }
2270
2271 $meta[] = sprintf( __( 'by %s', 'pods' ), $component_data['Author'] );
2272
2273 if ( ! empty( $component_data['URI'] ) ) {
2274 $meta[] = '<a href="' . $component_data['URI'] . '">' . __( 'Visit component site', 'pods' ) . '</a>';
2275 }
2276
2277 if ( pods_is_truthy( pods_v( 'Deprecated', $component_data, false ) ) ) {
2278 $deprecated = __( 'Deprecated', 'pods' );
2279
2280 $component_data['Name'] .= sprintf(
2281 ' <em style="font-weight: normal; color:#333;">(%s)</em>',
2282 $deprecated
2283 );
2284
2285 $deprecated_in_version = pods_v( 'DeprecatedInVersion', $component_data );
2286 $deprecated_removal_version = pods_v( 'DeprecatedRemovalVersion', $component_data );
2287
2288 if ( empty( $deprecated_removal_version ) ) {
2289 // translators: TBD means To Be Determined.
2290 $deprecated_removal_version = __( 'TBD', 'pods' );
2291 }
2292
2293 if ( $deprecated_in_version ) {
2294 $deprecated = sprintf(
2295 // translators: %1$s is the version the deprecation starts and %2$s is the version the code will be removed.
2296 __( 'Deprecated in %1$s, will be removed in %2$s', 'pods' ),
2297 $deprecated_in_version,
2298 $deprecated_removal_version
2299 );
2300 }
2301
2302 $meta[] = $deprecated;
2303 }
2304
2305 $component_data['Description'] = wpautop( trim( make_clickable( strip_tags( $component_data['Description'], 'em,strong' ) ) ) );
2306
2307 if ( ! empty( $meta ) ) {
2308 $description_style = '';
2309
2310 if ( ! empty( $component_data['Description'] ) ) {
2311 $description_style = ' style="padding:8px 0 4px;"';
2312 }
2313
2314 $component_data['Description'] .= '<div class="pods-component-meta" ' . $description_style . '>' . implode( '&nbsp;&nbsp;|&nbsp;&nbsp;', $meta ) . '</div>';
2315 }
2316
2317 $component_data = array(
2318 'id' => $component_data['ID'],
2319 'name' => $component_data['Name'],
2320 'category' => $component_data['Category'],
2321 'version' => '',
2322 'description' => $component_data['Description'],
2323 'mustuse' => pods_v( 'MustUse', $component_data, false ),
2324 'toggle' => 0,
2325 );
2326
2327 if ( ! empty( $component_data['category'] ) ) {
2328 $category_url = pods_query_arg(
2329 array(
2330 'view' => sanitize_title( $component_data['category'] ),
2331 'pg' => '',
2332 // @codingStandardsIgnoreLine
2333 'page' => $_GET['page'],
2334 )
2335 );
2336
2337 $component_data['category'] = '<a href="' . esc_url( $category_url ) . '">' . $component_data['category'] . '</a>';
2338 }
2339
2340 if ( isset( PodsInit::$components->settings['components'][ $component_data['id'] ] ) && 0 !== PodsInit::$components->settings['components'][ $component_data['id'] ] ) {
2341 $component_data['toggle'] = 1;
2342 } elseif ( $component_data['mustuse'] ) {
2343 $component_data['toggle'] = 1;
2344 }
2345 }//end foreach
2346
2347 $ui = array(
2348 'sql' => array(
2349 'field_id' => 'id',
2350 ),
2351 'data' => $components,
2352 'total' => count( $components ),
2353 'total_found' => count( $components ),
2354 'items' => __( 'Components', 'pods' ),
2355 'item' => __( 'Component', 'pods' ),
2356 'fields' => array(
2357 'manage' => array(
2358 'name' => array(
2359 'label' => __( 'Name', 'pods' ),
2360 'width' => '30%',
2361 'type' => 'text',
2362 'options' => array(
2363 'text_allow_html' => true,
2364 ),
2365 ),
2366 'category' => array(
2367 'label' => __( 'Category', 'pods' ),
2368 'width' => '10%',
2369 'type' => 'text',
2370 'options' => array(
2371 'text_allow_html' => true,
2372 ),
2373 ),
2374 'description' => array(
2375 'label' => __( 'Description', 'pods' ),
2376 'width' => '60%',
2377 'type' => 'text',
2378 'options' => array(
2379 'text_allow_html' => true,
2380 'text_allowed_html_tags' => 'strong em a ul ol li b i br div',
2381 ),
2382 ),
2383 ),
2384 ),
2385 'actions_disabled' => array( 'duplicate', 'view', 'export', 'add', 'edit', 'delete' ),
2386 'actions_custom' => array(
2387 'toggle' => array(
2388 'callback' => array( $this, 'admin_components_toggle' ),
2389 'nonce' => true,
2390 ),
2391 ),
2392 'filters_enhanced' => true,
2393 'views' => array(
2394 'all' => __( 'All', 'pods' ),
2395 // 'recommended' => __( 'Recommended', 'pods' ),
2396 'field-types' => __( 'Field Types', 'pods' ),
2397 'tools' => __( 'Tools', 'pods' ),
2398 'integration' => __( 'Integration', 'pods' ),
2399 'migration' => __( 'Migration', 'pods' ),
2400 'advanced' => __( 'Advanced', 'pods' ),
2401 ),
2402 'view' => $view,
2403 'heading' => array(
2404 'views' => __( 'Category', 'pods' ),
2405 ),
2406 'search' => false,
2407 'searchable' => false,
2408 'sortable' => false,
2409 'pagination' => false,
2410 );
2411
2412 if ( pods_developer() ) {
2413 $ui['views']['dev'] = __( 'Developer Preview', 'pods' );
2414 }
2415
2416 // Add our custom callouts.
2417 $this->handle_callouts_updates();
2418
2419 add_filter( 'pods_ui_manage_custom_container_classes', array( $this, 'admin_manage_container_class' ) );
2420 add_action( 'pods_ui_manage_after_container', array( $this, 'admin_manage_callouts' ) );
2421
2422 pods_ui( $ui );
2423 }
2424
2425 /**
2426 * Toggle a component on or off
2427 *
2428 * @param PodsUI $ui PodsUI object.
2429 *
2430 * @return bool
2431 */
2432 public function admin_components_toggle( $ui ) {
2433
2434 // @codingStandardsIgnoreLine
2435 $component = $_GET['id'];
2436
2437 if ( ! empty( PodsInit::$components->components[ $component ]['PluginDependency'] ) ) {
2438 $dependency = explode( '|', PodsInit::$components->components[ $component ]['PluginDependency'] );
2439
2440 if ( ! pods_is_plugin_active( $dependency[1] ) ) {
2441 $website = 'http://wordpress.org/extend/plugins/' . dirname( $dependency[1] ) . '/';
2442
2443 if ( isset( $dependency[2] ) ) {
2444 $website = $dependency[2];
2445 }
2446
2447 if ( ! empty( $website ) ) {
2448 $website = ' ' . sprintf( __( 'You can find it at %s', 'pods' ), '<a href="' . $website . '" target="_blank" rel="noopener noreferrer">' . $website . '</a>' );
2449 }
2450
2451 $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;
2452
2453 $ui->error( $message );
2454
2455 $ui->manage();
2456
2457 return;
2458 }
2459 }//end if
2460
2461 if ( ! empty( PodsInit::$components->components[ $component ]['ThemeDependency'] ) ) {
2462 $dependency = explode( '|', PodsInit::$components->components[ $component ]['ThemeDependency'] );
2463
2464 $check = strtolower( $dependency[1] );
2465
2466 if ( strtolower( get_template() ) !== $check && strtolower( get_stylesheet() ) !== $check ) {
2467 $website = '';
2468
2469 if ( isset( $dependency[2] ) ) {
2470 $website = ' ' . sprintf( __( 'You can find it at %s', 'pods' ), '<a href="' . $dependency[2] . '" target="_blank" rel="noopener noreferrer">' . $dependency[2] . '</a>' );
2471 }
2472
2473 $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;
2474
2475 $ui->error( $message );
2476
2477 $ui->manage();
2478
2479 return;
2480 }
2481 }//end if
2482
2483 if ( ! empty( PodsInit::$components->components[ $component ]['MustUse'] ) ) {
2484 $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'] );
2485
2486 $ui->error( $message );
2487
2488 $ui->manage();
2489
2490 return;
2491 }
2492
2493 if ( 1 === (int) pods_v( 'toggled' ) ) {
2494 $toggle = PodsInit::$components->toggle( $component );
2495
2496 if ( true === $toggle ) {
2497 $ui->message( PodsInit::$components->components[ $component ]['Name'] . ' ' . __( 'Component enabled', 'pods' ) );
2498 } elseif ( false === $toggle ) {
2499 $ui->message( PodsInit::$components->components[ $component ]['Name'] . ' ' . __( 'Component disabled', 'pods' ) );
2500 }
2501
2502 $components = PodsInit::$components->components;
2503
2504 foreach ( $components as $component => &$component_data ) {
2505 $toggle = 0;
2506
2507 if ( isset( PodsInit::$components->settings['components'][ $component_data['ID'] ] ) ) {
2508 if ( 0 !== PodsInit::$components->settings['components'][ $component_data['ID'] ] ) {
2509 $toggle = 1;
2510 }
2511 }
2512 if ( true === $component_data['DeveloperMode'] ) {
2513 if ( ! pods_developer() ) {
2514 unset( $components[ $component ] );
2515 continue;
2516 }
2517 }
2518
2519 $component_data = array(
2520 'id' => $component_data['ID'],
2521 'name' => $component_data['Name'],
2522 'description' => make_clickable( $component_data['Description'] ),
2523 'version' => $component_data['Version'],
2524 'author' => $component_data['Author'],
2525 'toggle' => $toggle,
2526 );
2527 }//end foreach
2528
2529 $ui->data = $components;
2530
2531 pods_transient_clear( 'pods_components' );
2532
2533 $url = pods_query_arg( array( 'toggled' => null ) );
2534
2535 pods_redirect( $url );
2536 } elseif ( 1 === (int) pods_v( 'toggle' ) ) {
2537 $ui->message( PodsInit::$components->components[ $component ]['Name'] . ' ' . __( 'Component enabled', 'pods' ) );
2538 } else {
2539 $ui->message( PodsInit::$components->components[ $component ]['Name'] . ' ' . __( 'Component disabled', 'pods' ) );
2540 }//end if
2541
2542 $ui->manage();
2543 }
2544
2545 /**
2546 * Get the admin upgrade page
2547 */
2548 public function admin_upgrade() {
2549
2550 foreach ( PodsInit::$upgrades as $old_version => $new_version ) {
2551 if ( version_compare( $old_version, PodsInit::$version_last, '<=' ) && version_compare( PodsInit::$version_last, $new_version, '<' ) ) {
2552 $new_version = str_replace( '.', '_', $new_version );
2553
2554 pods_view( PODS_DIR . 'ui/admin/upgrade/upgrade_' . $new_version . '.php', compact( array_keys( get_defined_vars() ) ) );
2555
2556 break;
2557 }
2558 }
2559 }
2560
2561 /**
2562 * Get the admin help page
2563 */
2564 public function admin_help() {
2565 // Add our custom callouts.
2566 $this->handle_callouts_updates();
2567
2568 add_action( 'pods_admin_after_help', array( $this, 'admin_manage_callouts' ) );
2569
2570 pods_view( PODS_DIR . 'ui/admin/help.php', compact( array_keys( get_defined_vars() ) ) );
2571 }
2572
2573 /**
2574 * Add pods specific capabilities.
2575 *
2576 * @param array $capabilities List of extra capabilities to add.
2577 *
2578 * @return array
2579 */
2580 public function admin_capabilities( $capabilities ) {
2581
2582 $pods = pods_api()->load_pods(
2583 array(
2584 'type' => array(
2585 'settings',
2586 'post_type',
2587 'taxonomy',
2588 ),
2589 )
2590 );
2591
2592 $other_pods = pods_api()->load_pods(
2593 array(
2594 'type' => array(
2595 'pod',
2596 'table',
2597 ),
2598 )
2599 );
2600
2601 $pods = array_merge( $pods, $other_pods );
2602
2603 $capabilities[] = 'pods';
2604 $capabilities[] = 'pods_content';
2605 $capabilities[] = 'pods_settings';
2606 $capabilities[] = 'pods_components';
2607
2608 foreach ( $pods as $pod ) {
2609 if ( 'settings' === $pod['type'] ) {
2610 $capabilities[] = 'pods_edit_' . $pod['name'];
2611 } elseif ( 'post_type' === $pod['type'] ) {
2612 $capability_type = pods_v_sanitized( 'capability_type_custom', $pod['options'], pods_v( 'name', $pod ) );
2613
2614 if ( 'custom' === pods_v( 'capability_type', $pod['options'] ) && is_string( $capability_type ) && 0 < strlen( $capability_type ) ) {
2615 $capabilities[] = 'read_' . $capability_type;
2616 $capabilities[] = 'edit_' . $capability_type;
2617 $capabilities[] = 'delete_' . $capability_type;
2618
2619 if ( 1 === (int) pods_v( 'capability_type_extra', $pod['options'], 1 ) ) {
2620 $capability_type_plural = $capability_type . 's';
2621
2622 $capabilities[] = 'read_private_' . $capability_type_plural;
2623 $capabilities[] = 'edit_' . $capability_type_plural;
2624 $capabilities[] = 'edit_others_' . $capability_type_plural;
2625 $capabilities[] = 'edit_private_' . $capability_type_plural;
2626 $capabilities[] = 'edit_published_' . $capability_type_plural;
2627 $capabilities[] = 'publish_' . $capability_type_plural;
2628 $capabilities[] = 'delete_' . $capability_type_plural;
2629 $capabilities[] = 'delete_private_' . $capability_type_plural;
2630 $capabilities[] = 'delete_published_' . $capability_type_plural;
2631 $capabilities[] = 'delete_others_' . $capability_type_plural;
2632 }
2633 }
2634 } elseif ( 'taxonomy' === $pod['type'] ) {
2635 if ( 'custom' === pods_v( 'capability_type', $pod['options'], 'terms' ) ) {
2636 $capability_type = pods_v_sanitized( 'capability_type_custom', $pod['options'], pods_v( 'name', $pod ) . 's' );
2637
2638 $capability_type .= '_term';
2639 $capability_type_plural = $capability_type . 's';
2640
2641 // Singular
2642 $capabilities[] = 'edit_' . $capability_type;
2643 $capabilities[] = 'delete_' . $capability_type;
2644 $capabilities[] = 'assign_' . $capability_type;
2645 // Plural
2646 $capabilities[] = 'manage_' . $capability_type_plural;
2647 $capabilities[] = 'edit_' . $capability_type_plural;
2648 $capabilities[] = 'delete_' . $capability_type_plural;
2649 $capabilities[] = 'assign_' . $capability_type_plural;
2650 }
2651 } else {
2652 $capabilities[] = 'pods_add_' . $pod['name'];
2653 $capabilities[] = 'pods_edit_' . $pod['name'];
2654 $capabilities[] = 'pods_delete_' . $pod['name'];
2655
2656 if ( $pod instanceof Pod ) {
2657 $author_field = $pod->get_field( 'author', null, false );
2658 } else {
2659 $author_field = pods_v( 'author', $pod['fields'] );
2660 }
2661
2662 if ( $author_field && 'pick' === $author_field['type'] && 'user' === $author_field['pick_object'] ) {
2663 $capabilities[] = 'pods_edit_others_' . $pod['name'];
2664 $capabilities[] = 'pods_delete_others_' . $pod['name'];
2665 }
2666
2667 $actions_enabled = pods_v( 'ui_actions_enabled', $pod['options'] );
2668
2669 if ( ! empty( $actions_enabled ) ) {
2670 $actions_enabled = (array) $actions_enabled;
2671 } else {
2672 $actions_enabled = array();
2673 }
2674
2675 $available_actions = array(
2676 'add',
2677 'edit',
2678 'duplicate',
2679 'delete',
2680 'reorder',
2681 'export',
2682 );
2683
2684 if ( ! empty( $actions_enabled ) ) {
2685 $actions_disabled = array(
2686 'view' => 'view',
2687 );
2688
2689 foreach ( $available_actions as $action ) {
2690 if ( ! in_array( $action, $actions_enabled, true ) ) {
2691 $actions_disabled[ $action ] = $action;
2692 }
2693 }
2694
2695 if ( ! in_array( 'export', $actions_disabled, true ) ) {
2696 $capabilities[] = 'pods_export_' . $pod['name'];
2697 }
2698
2699 if ( ! in_array( 'reorder', $actions_disabled, true ) ) {
2700 $capabilities[] = 'pods_reorder_' . $pod['name'];
2701 }
2702 } elseif ( 1 === (int) pods_v( 'ui_export', $pod['options'], 0 ) ) {
2703 $capabilities[] = 'pods_export_' . $pod['name'];
2704 }//end if
2705 }//end if
2706 }//end foreach
2707
2708 return $capabilities;
2709 }
2710
2711 /**
2712 * Handle ajax calls for the administration
2713 */
2714 public function admin_ajax() {
2715
2716 if ( false === headers_sent() ) {
2717 pods_session_start();
2718
2719 header( 'Content-Type: text/html; charset=' . get_bloginfo( 'charset' ) );
2720 }
2721
2722 // Sanitize input
2723 // @codingStandardsIgnoreLine
2724 $params = pods_unslash( (array) $_POST );
2725
2726 foreach ( $params as $key => $value ) {
2727 if ( 'action' === $key ) {
2728 continue;
2729 }
2730
2731 // Fixup $_POST data @codingStandardsIgnoreLine
2732 $_POST[ str_replace( '_podsfix_', '', $key ) ] = $_POST[ $key ];
2733
2734 // Fixup $params with unslashed data
2735 $params[ str_replace( '_podsfix_', '', $key ) ] = $value;
2736
2737 // Unset the _podsfix_* keys
2738 unset( $params[ $key ] );
2739 }
2740
2741 $params = (object) $params;
2742
2743 $methods = array(
2744 'add_pod' => array( 'priv' => true ),
2745 'save_pod' => array( 'priv' => true ),
2746 'load_sister_fields' => array( 'priv' => true ),
2747 'process_form' => array( 'custom_nonce' => true ),
2748 // priv handled through nonce
2749 'upgrade' => array( 'priv' => true ),
2750 'migrate' => array( 'priv' => true ),
2751 );
2752
2753 /**
2754 * AJAX Callbacks in field editor
2755 *
2756 * @since unknown
2757 *
2758 * @param array $methods Callback methods.
2759 * @param PodsAdmin $obj PodsAdmin object.
2760 */
2761 $methods = apply_filters( 'pods_admin_ajax_methods', $methods, $this );
2762
2763 if ( ! isset( $params->method ) || ! isset( $methods[ $params->method ] ) ) {
2764 return pods_error( __( 'Invalid AJAX request', 'pods' ), $this );
2765 }
2766
2767 $defaults = array(
2768 'priv' => null,
2769 'name' => $params->method,
2770 'custom_nonce' => null,
2771 );
2772
2773 $method = (object) array_merge( $defaults, (array) $methods[ $params->method ] );
2774
2775 if (
2776 true !== $method->custom_nonce
2777 && (
2778 ! is_user_logged_in()
2779 || ! isset( $params->_wpnonce )
2780 || false === wp_verify_nonce( $params->_wpnonce, 'pods-' . $params->method )
2781 )
2782 ) {
2783 return pods_error( __( 'Unauthorized request', 'pods' ), $this );
2784 }
2785
2786 // Cleaning up $params
2787 unset( $params->action );
2788 unset( $params->method );
2789
2790 if ( true !== $method->custom_nonce ) {
2791 unset( $params->_wpnonce );
2792 }
2793
2794 // Check permissions (convert to array to support multiple)
2795 if ( ! empty( $method->priv ) && ! pods_is_admin( array( 'pods' ) ) ) {
2796 if ( true !== $method->priv && pods_is_admin( $method->priv ) ) {
2797 // They have access to the custom priv.
2798 } else {
2799 // They do not have access.
2800 return pods_error( __( 'Access denied', 'pods' ), $this );
2801 }
2802 }
2803
2804 $params->method = $method->name;
2805
2806 $method_name = $method->name;
2807
2808 $params = apply_filters( "pods_api_{$method_name}", $params, $method );
2809
2810 $api = pods_api();
2811
2812 $api->display_errors = false;
2813
2814 if ( 'upgrade' === $method->name ) {
2815 $output = (string) pods_upgrade( $params->version )->ajax( $params );
2816 } elseif ( 'migrate' === $method->name ) {
2817 $output = (string) apply_filters( 'pods_api_migrate_run', $params );
2818 } else {
2819 if ( ! method_exists( $api, $method->name ) ) {
2820 return pods_error( __( 'API method does not exist', 'pods' ), $this );
2821 } elseif ( 'save_pod' === $method->name ) {
2822 if ( isset( $params->field_data_json ) && is_array( $params->field_data_json ) ) {
2823 $params->fields = $params->field_data_json;
2824
2825 unset( $params->field_data_json );
2826
2827 foreach ( $params->fields as $k => $v ) {
2828 if ( empty( $v ) ) {
2829 unset( $params->fields[ $k ] );
2830 } elseif ( ! is_array( $v ) ) {
2831 $params->fields[ $k ] = (array) @json_decode( $v, true );
2832 }
2833 }
2834 }
2835 }
2836
2837 // Dynamically call the API method
2838 $params = (array) $params;
2839
2840 $output = call_user_func( array( $api, $method->name ), $params );
2841 }//end if
2842
2843 // Output in json format
2844 if ( false !== $output ) {
2845
2846 /**
2847 * Pods Admin AJAX request was successful
2848 *
2849 * @since 2.6.8
2850 *
2851 * @param array $params AJAX parameters.
2852 * @param array|object|string $output Output for AJAX request.
2853 */
2854 do_action( "pods_admin_ajax_success_{$method->name}", $params, $output );
2855
2856 if ( is_array( $output ) || is_object( $output ) ) {
2857 wp_send_json( $output );
2858 } else {
2859 // @codingStandardsIgnoreLine
2860 echo $output;
2861 }
2862 } else {
2863 return pods_error( __( 'There was a problem with your request.', 'pods' ) );
2864 }//end if
2865
2866 die();
2867 // KBAI!
2868 }
2869
2870 /**
2871 * Profiles the Pods configuration
2872 *
2873 * @param null|string|array $pod Which Pod(s) to get configuration for. Can be a the name
2874 * of one Pod, or an array of names of Pods, or null, which is the
2875 * default, to profile all Pods.
2876 * @param bool $full_field_info If true all info about each field is returned. If false,
2877 * which is the default only name and type, will be returned.
2878 *
2879 * @return array
2880 *
2881 * @since 2.7.0
2882 * @deprecated 2.8.0
2883 */
2884 public function configuration( $pod = null, $full_field_info = false ) {
2885 pods_deprecated( 'PodsAdmin::configuration', '2.8' );
2886
2887 $api = pods_api();
2888
2889 if ( null === $pod ) {
2890 $the_pods = $api->load_pods();
2891 } elseif ( is_array( $pod ) ) {
2892 foreach ( $pod as $p ) {
2893 $the_pods[] = $api->load_pod( $p );
2894 }
2895 } else {
2896 $the_pods[] = $api->load_pod( $pod );
2897 }
2898
2899 foreach ( $the_pods as $the_pod ) {
2900 $configuration[ $the_pod['name'] ] = array(
2901 'name' => $the_pod['name'],
2902 'ID' => $the_pod['id'],
2903 'storage' => $the_pod['storage'],
2904 'fields' => $the_pod['fields'],
2905 );
2906 }
2907
2908 if ( ! $full_field_info ) {
2909 foreach ( $the_pods as $the_pod ) {
2910 $fields = $configuration[ $the_pod['name'] ]['fields'];
2911
2912 unset( $configuration[ $the_pod['name'] ]['fields'] );
2913
2914 foreach ( $fields as $field ) {
2915 $info = array(
2916 'name' => $field['name'],
2917 'type' => $field['type'],
2918 );
2919
2920 if ( 'pick' === $info['type'] ) {
2921 $info['pick_object'] = $field['pick_object'];
2922
2923 if ( isset( $field['pick_val'] ) && '' !== $field['pick_val'] ) {
2924 $info['pick_val'] = $field['pick_val'];
2925 }
2926 }
2927
2928 if ( is_array( $info ) ) {
2929 $configuration[ $the_pod['name'] ]['fields'][ $field['name'] ] = $info;
2930 }
2931
2932 unset( $info );
2933
2934 }//end foreach
2935 }//end foreach
2936 }//end if
2937
2938 if ( is_array( $configuration ) ) {
2939 return $configuration;
2940 }
2941
2942 }
2943
2944 /**
2945 * Build UI for extending REST API, if makes sense to do so.
2946 *
2947 * @since 2.6.0
2948 *
2949 * @access protected
2950 */
2951 protected function rest_admin() {
2952
2953 if ( function_exists( 'register_rest_field' ) ) {
2954 add_filter(
2955 'pods_admin_setup_edit_field_options', array(
2956 $this,
2957 'add_rest_fields_to_field_editor',
2958 ), 12, 2
2959 );
2960 add_filter( 'pods_admin_setup_edit_field_tabs', array( $this, 'add_rest_field_tab' ), 12, 2 );
2961 }
2962
2963 add_filter( 'pods_admin_setup_edit_tabs', array( $this, 'add_rest_settings_tab' ), 12, 2 );
2964 add_filter( 'pods_admin_setup_edit_options', array( $this, 'add_rest_settings_tab_fields' ), 12, 2 );
2965
2966 }
2967
2968 /**
2969 * Check if Pod type <em>could</em> extend core REST API response
2970 *
2971 * @since 2.5.6
2972 *
2973 * @access protected
2974 *
2975 * @param array $pod Pod options.
2976 *
2977 * @return bool
2978 */
2979 protected function restable_pod( $pod ) {
2980
2981 $type = $pod['type'];
2982
2983 $restable_types = array(
2984 'post_type',
2985 'user',
2986 'taxonomy',
2987 'media',
2988 );
2989
2990 return in_array( $type, $restable_types, true );
2991
2992 }
2993
2994 /**
2995 * Add a rest api tab.
2996 *
2997 * @since 2.6.0
2998 *
2999 * @param array $tabs Tab array.
3000 * @param array $pod Pod options.
3001 *
3002 * @return array
3003 */
3004 public function add_rest_settings_tab( $tabs, $pod ) {
3005 if ( ! $this->restable_pod( $pod ) ) {
3006 return $tabs;
3007 }
3008
3009 $tabs['rest-api'] = __( 'REST API', 'pods' );
3010
3011 return $tabs;
3012
3013 }
3014
3015 /**
3016 * Populate REST API tab.
3017 *
3018 * @since 0.1.0
3019 *
3020 * @param array $options Tab options.
3021 * @param array $pod Pod options.
3022 *
3023 * @return array
3024 */
3025 public function add_rest_settings_tab_fields( $options, $pod ) {
3026 if ( ! $this->restable_pod( $pod ) ) {
3027 return $options;
3028 }
3029
3030 $options['rest-api'] = [
3031 'rest_enable' => [
3032 'label' => __( 'Enable', 'pods' ),
3033 'help' => __( 'Add REST API support for this Pod.', 'pods' ),
3034 'type' => 'boolean',
3035 'default' => '',
3036 'dependency' => true,
3037 ],
3038 'rest_base' => [
3039 'label' => __( 'REST Base (if any)', 'pods' ),
3040 'help' => __( 'This will form the url for the route. Default / empty value here will use the pod name.', 'pods' ),
3041 'type' => 'text',
3042 'default' => '',
3043 'depends-on' => [ 'rest_enable' => true ],
3044 ],
3045 'rest_namespace' => [
3046 'label' => __( 'REST API namespace', 'pods' ),
3047 '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' ),
3048 'type' => 'text',
3049 'default' => '',
3050 'placeholder' => 'wp/v2',
3051 'depends-on' => [ 'rest_enable' => true ],
3052 ],
3053 'read_all' => [
3054 'label' => __( 'Show All Fields (read-only)', 'pods' ),
3055 'help' => __( 'Show all fields in REST API. If unchecked fields must be enabled on a field by field basis.', 'pods' ),
3056 'type' => 'boolean',
3057 'default' => '',
3058 'depends-on' => [ 'rest_enable' => true ],
3059 'dependency' => true,
3060 ],
3061 'write_all' => [
3062 'label' => __( 'Allow All Fields To Be Updated', 'pods' ),
3063 'help' => __( 'Allow all fields to be updated via the REST API. If unchecked fields must be enabled on a field by field basis.', 'pods' ),
3064 'type' => 'boolean',
3065 'default' => pods_v( 'name', $pod ),
3066 'depends-on' => [ 'rest_enable' => true, 'read_all' => true ],
3067 ],
3068 'rest_api_field_mode' => [
3069 'label' => __( 'Field Mode', 'pods' ),
3070 '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' ),
3071 'type' => 'pick',
3072 'pick_format_single' => 'dropdown',
3073 'default' => 'value',
3074 'depends-on' => [ 'rest_enable' => true ],
3075 'data' => [
3076 'value' => __( 'Raw values', 'pods' ),
3077 'render' => __( 'Rendered values', 'pods' ),
3078 'value_and_render' => __( 'Both raw and rendered values {value: raw_value, rendered: rendered_value}', 'pods' ),
3079 ],
3080 ],
3081 ];
3082
3083 return $options;
3084 }
3085
3086 /**
3087 * Add a REST API section to advanced tab of field editor.
3088 *
3089 * @since 2.5.6
3090 *
3091 * @param array $options Tab options.
3092 * @param array $pod Pod options.
3093 *
3094 * @return array
3095 */
3096 public function add_rest_fields_to_field_editor( $options, $pod ) {
3097 if ( ! $this->restable_pod( $pod ) ) {
3098 return $options;
3099 }
3100
3101 $options['rest'][ __( 'Read/ Write', 'pods' ) ] = [
3102 'rest_read' => [
3103 'label' => __( 'Read via REST API', 'pods' ),
3104 'help' => __( 'Should this field be readable via the REST API? You must enable REST API support for this Pod.', 'pods' ),
3105 'type' => 'boolean',
3106 'default' => '',
3107 ],
3108 'rest_write' => [
3109 'label' => __( 'Write via REST API', 'pods' ),
3110 'help' => __( 'Should this field be writeable via the REST API? You must enable REST API support for this Pod.', 'pods' ),
3111 'type' => 'boolean',
3112 'default' => '',
3113 ],
3114 ];
3115
3116 $options['rest'][ __( 'Relationship Field Options', 'pods' ) ] = [
3117 'rest_pick_response' => [
3118 'label' => __( 'Response Type', 'pods' ),
3119 'help' => __( 'This will determine what amount of data for the related items will be returned.', 'pods' ),
3120 'type' => 'pick',
3121 'pick_format_single' => 'dropdown',
3122 'default' => 'array',
3123 'depends-on' => [
3124 'type' => 'pick',
3125 ],
3126 'dependency' => true,
3127 'data' => [
3128 'array' => __( 'All fields', 'pods' ),
3129 'id' => __( 'ID only', 'pods' ),
3130 'name' => __( 'Name only', 'pods' ),
3131 'custom' => __( 'Custom return (specify field to return)', 'pods' ),
3132 ],
3133 ],
3134 'rest_pick_depth' => [
3135 'label' => __( 'Depth', 'pods' ),
3136 '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' ),
3137 'type' => 'number',
3138 'default' => '1',
3139 'depends-on' => [
3140 'type' => 'pick',
3141 'rest_pick_response' => 'array',
3142 ],
3143 ],
3144 'rest_pick_custom' => [
3145 'label' => __( 'Custom return', 'pods' ),
3146 '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' ),
3147 'type' => 'text',
3148 'default' => '',
3149 'placeholder' => 'this_field_name.ID',
3150 'depends-on' => [
3151 'type' => 'pick',
3152 'rest_pick_response' => 'custom',
3153 ],
3154 ],
3155 'rest_pick_notice' => [
3156 'label' => 'Relationship Options',
3157 'type' => 'html',
3158 'html_content' => __( 'If you have a relationship field, you will see additional options to customize here.', 'pods' ),
3159 'excludes-on' => [ 'type' => 'pick' ],
3160 ],
3161 ];
3162
3163 return $options;
3164 }
3165
3166 /**
3167 * Add REST field tab
3168 *
3169 * @since 2.5.6
3170 *
3171 * @param array $tabs Tab list.
3172 * @param array $pod The ood object.
3173 *
3174 * @return array
3175 */
3176 public function add_rest_field_tab( $tabs, $pod ) {
3177 if ( ! $this->restable_pod( $pod ) ) {
3178 return $tabs;
3179 }
3180
3181 $tabs['rest'] = __( 'REST API', 'pods' );
3182
3183 return $tabs;
3184 }
3185
3186 /**
3187 * Add Pods-specific debug info to Site Info debug area.
3188 *
3189 * @since 2.7.13
3190 *
3191 * @param array $info Debug info.
3192 *
3193 * @return array Debug info with Pods-specific debug info added.
3194 */
3195 public function add_debug_information( $info ) {
3196 $auto_start = pods_session_auto_start();
3197
3198 if ( 'auto' !== $auto_start ) {
3199 // Turn boolean into 0/1.
3200 $auto_start = (int) $auto_start;
3201 }
3202
3203 // Turn into a string.
3204 $auto_start = (string) $auto_start;
3205
3206 $settings = pods_container( Settings::class );
3207
3208 $fields = $settings->get_setting_fields();
3209
3210 $settings_values = $settings->get_settings();
3211
3212 $auto_start = pods_v( $auto_start, $fields['session_auto_start']['data'], __( 'Unknown', 'pods' ) );
3213
3214 global $wpdb;
3215
3216 $info['pods'] = [
3217 'label' => 'Pods',
3218 'description' => __( 'Debug information for Pods installations.', 'pods' ),
3219 'fields' => [
3220 'pods-server-software' => [
3221 'label' => __( 'Server Software', 'pods' ),
3222 'value' => ! empty( $_SERVER['SERVER_SOFTWARE'] ) ? $_SERVER['SERVER_SOFTWARE'] : 'N/A',
3223 ],
3224 'pods-user-agent' => [
3225 'label' => __( 'Your User Agent', 'pods' ),
3226 'value' => ! empty( $_SERVER['HTTP_USER_AGENT'] ) ? $_SERVER['HTTP_USER_AGENT'] : 'N/A',
3227 ],
3228 'pods-session-save-path' => [
3229 'label' => __( 'Session Save Path', 'pods' ),
3230 'value' => session_save_path(),
3231 ],
3232 'pods-session-save-path-exists' => [
3233 'label' => __( 'Session Save Path Exists', 'pods' ),
3234 'value' => file_exists( session_save_path() ) ? __( 'Yes', 'pods' ) : __( 'No', 'pods' ),
3235 ],
3236 'pods-session-save-path-writable' => [
3237 'label' => __( 'Session Save Path Writeable', 'pods' ),
3238 'value' => is_writable( session_save_path() ) ? __( 'Yes', 'pods' ) : __( 'No', 'pods' ),
3239 ],
3240 'pods-session-max-lifetime' => [
3241 'label' => __( 'Session Max Lifetime', 'pods' ),
3242 'value' => ini_get( 'session.gc_maxlifetime' ),
3243 ],
3244 'pods-opcode-cache-apc' => [
3245 'label' => __( 'Opcode Cache: Apc', 'pods' ),
3246 'value' => function_exists( 'apc_cache_info' ) ? __( 'Yes', 'pods' ) : __( 'No', 'pods' ),
3247 ],
3248 'pods-opcode-cache-memcached' => [
3249 'label' => __( 'Opcode Cache: Memcached', 'pods' ),
3250 'value' => class_exists( 'eaccelerator_put' ) ? __( 'Yes', 'pods' ) : __( 'No', 'pods' ),
3251 ],
3252 'pods-opcode-cache-opcache' => [
3253 'label' => __( 'Opcode Cache: OPcache', 'pods' ),
3254 'value' => function_exists( 'opcache_get_status' ) ? __( 'Yes', 'pods' ) : __( 'No', 'pods' ),
3255 ],
3256 'pods-opcode-cache-redis' => [
3257 'label' => __( 'Opcode Cache: Redis', 'pods' ),
3258 'value' => class_exists( 'xcache_set' ) ? __( 'Yes', 'pods' ) : __( 'No', 'pods' ),
3259 ],
3260 'pods-object-cache-apc' => [
3261 'label' => __( 'Object Cache: APC', 'pods' ),
3262 'value' => function_exists( 'apc_cache_info' ) ? __( 'Yes', 'pods' ) : __( 'No', 'pods' ),
3263 ],
3264 'pods-object-cache-apcu' => [
3265 'label' => __( 'Object Cache: APCu', 'pods' ),
3266 'value' => function_exists( 'apcu_cache_info' ) ? __( 'Yes', 'pods' ) : __( 'No', 'pods' ),
3267 ],
3268 'pods-object-cache-memcache' => [
3269 'label' => __( 'Object Cache: Memcache', 'pods' ),
3270 'value' => class_exists( 'Memcache' ) ? __( 'Yes', 'pods' ) : __( 'No', 'pods' ),
3271 ],
3272 'pods-object-cache-memcached' => [
3273 'label' => __( 'Object Cache: Memcached', 'pods' ),
3274 'value' => class_exists( 'Memcached' ) ? __( 'Yes', 'pods' ) : __( 'No', 'pods' ),
3275 ],
3276 'pods-object-cache-redis' => [
3277 'label' => __( 'Object Cache: Redis', 'pods' ),
3278 'value' => class_exists( 'Redis' ) ? __( 'Yes', 'pods' ) : __( 'No', 'pods' ),
3279 ],
3280 'pods-memory-current-usage' => [
3281 'label' => __( 'Current Memory Usage', 'pods' ),
3282 'value' => number_format_i18n( memory_get_usage() / 1024 / 1024, 3 ) . 'M' . ( defined( 'WP_MEMORY_LIMIT' ) ? ' / ' . WP_MEMORY_LIMIT : '' ),
3283 ],
3284 'pods-memory-current-usage-real' => [
3285 'label' => __( 'Current Memory Usage (real)', 'pods' ),
3286 'value' => number_format_i18n( memory_get_usage( true ) / 1024 / 1024, 3 ) . 'M',
3287 ],
3288 'pods-network-wide' => [
3289 'label' => __( 'Pods Network-Wide Activated', 'pods' ),
3290 'value' => is_plugin_active_for_network( basename( PODS_DIR ) . '/init.php' ) ? __( 'Yes', 'pods' ) : __( 'No', 'pods' ),
3291 ],
3292 'pods-install-location' => [
3293 'label' => __( 'Pods Install Location', 'pods' ),
3294 'value' => str_replace( ABSPATH, '/', PODS_DIR ),
3295 ],
3296 'pods-developer' => [
3297 'label' => __( 'Pods Developer Activated' ),
3298 'value' => ( pods_developer() ) ? __( 'Yes', 'pods' ) : __( 'No', 'pods' ),
3299 ],
3300 'pods-tableless-mode' => [
3301 'label' => __( 'Pods Tableless Mode Activated', 'pods' ),
3302 'value' => ( pods_tableless() ) ? __( 'Yes', 'pods' ) : __( 'No', 'pods' ),
3303 ],
3304 'pods-relationship-table-enabled' => [
3305 'label' => __( 'Pods Relationship Table Enabled', 'pods' ),
3306 'value' => ( pods_podsrel_enabled() ) ? __( 'Yes', 'pods' ) : __( 'No', 'pods' ),
3307 ],
3308 'pods-relationship-table-status' => [
3309 'label' => __( 'Pods Relationship Table Count' ),
3310 'value' => ( ! pods_tableless() ? number_format( (float) $wpdb->get_var( "SELECT COUNT(*) FROM {$wpdb->prefix}podsrel" ) ) : 'No table' ),
3311 ],
3312 'pods-light-mode' => [
3313 'label' => __( 'Pods Light Mode Activated', 'pods' ),
3314 'value' => ( pods_light() ) ? __( 'Yes', 'pods' ) : __( 'No', 'pods' ),
3315 ],
3316 'pods-strict' => [
3317 'label' => __( 'Pods Strict Activated' ),
3318 'value' => ( pods_strict( false ) ) ? __( 'Yes', 'pods' ) : __( 'No', 'pods' ),
3319 ],
3320 'pods-allow-deprecated' => [
3321 'label' => __( 'Pods Allow Deprecated' ),
3322 'value' => ( pods_allow_deprecated() ) ? __( 'Yes', 'pods' ) : __( 'No', 'pods' ),
3323 ],
3324 'pods-api-cache' => [
3325 'label' => __( 'Pods API Cache Activated' ),
3326 'value' => ( pods_api_cache() ) ? __( 'Yes', 'pods' ) : __( 'No', 'pods' ),
3327 ],
3328 'pods-shortcode-allow-evaluate-tags' => [
3329 'label' => __( 'Pods Shortcode Allow Evaluate Tags' ),
3330 'value' => ( pods_shortcode_allow_evaluate_tags() ) ? __( 'Yes', 'pods' ) : __( 'No', 'pods' ),
3331 ],
3332 'pods-sessions' => [
3333 'label' => __( 'Pods Sessions' ),
3334 'value' => $auto_start,
3335 ],
3336 'pods-can-use-sessions' => [
3337 'label' => __( 'Pods Can Use Sessions' ),
3338 'value' => ( pods_can_use_sessions( true ) ) ? __( 'Yes', 'pods' ) : __( 'No', 'pods' ),
3339 ],
3340 ],
3341 ];
3342
3343 $settings_to_show = [
3344 'types_only' => __( 'Setting: Types only', 'pods' ),
3345 'watch_changed_fields' => __( 'Setting: Watch Changed fields', 'pods' ),
3346 'metadata_integration' => __( 'Setting: Watch WP Metadata calls', 'pods' ),
3347 'metadata_override_get' => __( 'Setting: Override WP Metadata values', 'pods' ),
3348 ];
3349
3350 foreach ( $settings_to_show as $setting => $label ) {
3351 $setting_key = 'pods-settings-' . sanitize_title_with_dashes( $setting );
3352
3353 $value = ucwords(
3354 str_replace(
3355 [ '_', '-' ],
3356 ' ',
3357 (string) pods_v( $setting, $settings_values, __( 'Unknown', 'pods' )
3358 )
3359 )
3360 );
3361
3362 if ( '0' === $value ) {
3363 $value = __( 'No', 'pods' );
3364 } elseif ( '1' === $value ) {
3365 $value = __( 'Yes', 'pods' );
3366 }
3367
3368 $info['pods']['fields'][ $setting_key ] = [
3369 'label' => $label,
3370 'value' => $value,
3371 ];
3372 }
3373
3374 // @todo Later we should add which components are active.
3375
3376 return $info;
3377 }
3378
3379 /**
3380 * Add our site status tests.
3381 *
3382 * @since 2.8.0
3383 *
3384 * @param array $tests The list of status tests.
3385 *
3386 * @return array The list of status tests.
3387 */
3388 public function site_status_tests( $tests ) {
3389 $plugin_search_url = 'plugin-install.php?tab=search&type=term&s=';
3390
3391 if ( is_multisite() && ! is_network_admin() ) {
3392 $plugin_search_url = network_admin_url( $plugin_search_url );
3393 } else {
3394 $plugin_search_url = self_admin_url( $plugin_search_url );
3395 }
3396
3397 if ( ! is_pods_alternative_cache_activated() && ! wp_using_ext_object_cache() ) {
3398 $tests['direct']['pods_alternative_cache'] = [
3399 'label' => __( 'Pods Alternative Cache', 'pods' ),
3400 'test' => static function () use ( $plugin_search_url ) {
3401 return [
3402 'label' => __( 'The Pods Team recommends you install the Pods Alternative Cache plugin', 'pods' ),
3403 'status' => 'recommended',
3404 'badge' => [
3405 'label' => __( 'Performance', 'pods' ),
3406 'color' => 'blue',
3407 ],
3408 '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' ) ),
3409 'actions' => sprintf( '<p><a href="%s">%s</a></p>', esc_url( $plugin_search_url . urlencode( 'Pods Alternative Cache' ) ), __( 'Install Pods Alternative Cache', 'pods' ) ),
3410 'test' => 'pods_alternative_cache',
3411 ];
3412 },
3413 ];
3414 }
3415
3416 return $tests;
3417 }
3418
3419 /**
3420 * Check whether the requirements were met and maybe display error messages.
3421 *
3422 * @since 2.9.0
3423 *
3424 * @param array $requirements List of requirements.
3425 *
3426 * @return bool Whether the requirements were met.
3427 */
3428 public function check_requirements( array $requirements ) {
3429 foreach ( $requirements as $requirement ) {
3430 // Check if requirement passed.
3431 if ( $requirement['check'] ) {
3432 continue;
3433 }
3434
3435 // Show admin notice if there's a message to be shown.
3436 if ( ! empty( $requirement['message'] ) && $this->should_show_notices() ) {
3437 pods_message( $requirement['message'], 'error' );
3438 }
3439
3440 return false;
3441 }
3442
3443 return true;
3444 }
3445
3446 /**
3447 * Check whether we should show notices.
3448 *
3449 * @since 2.9.0
3450 *
3451 * @return bool Whether we should show notices.
3452 */
3453 public function should_show_notices() {
3454 global $pagenow;
3455
3456 // We only show notices on admin pages.
3457 if ( ! is_admin() ) {
3458 return false;
3459 }
3460
3461 $page = isset( $_GET['page'] ) ? $_GET['page'] : '';
3462
3463 // We only show on the plugins.php page or on Pods Admin pages.
3464 if (
3465 (
3466 'plugins.php' !== $pagenow
3467 && 0 !== strpos( $page, 'pods' )
3468 )
3469 || 0 === strpos( $page, 'pods-manage-' )
3470 ) {
3471 return false;
3472 }
3473
3474 return true;
3475 }
3476
3477 }
3478