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