PluginProbe ʕ •ᴥ•ʔ
Pods – Custom Content Types and Fields / 3.3.4
Pods – Custom Content Types and Fields v3.3.4
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 / components / Pages.php
pods / components Last commit date
Builder 3 years ago I18n 11 months ago Migrate-ACF 1 year ago Migrate-CPTUI 1 year ago Migrate-PHP 1 year ago Migrate-Packages 11 months ago Roles 11 months ago Templates 11 months ago Advanced-Content-Types.php 3 years ago Advanced-Relationships.php 3 years ago Markdown.php 2 years ago Pages.php 1 year ago Table-Storage.php 4 years ago
Pages.php
1914 lines
1 <?php
2 /**
3 * Name: Pages
4 *
5 * Menu Name: Pod Pages
6 *
7 * Description: Creates advanced URL structures using wildcards in order to enable the front-end display of Pods Advanced Content Types. Not recommended for use with other content types.
8 *
9 * Version: 2.3
10 *
11 * Category: Advanced
12 *
13 * Menu Page: edit.php?post_type=_pods_page
14 * Menu Add Page: post-new.php?post_type=_pods_page
15 *
16 * @package Pods\Components
17 * @subpackage Pages
18 */
19
20 use Pods\Whatsit\Field;
21 use Pods\Whatsit\Page;
22 use Pods\Whatsit\Storage;
23
24 if ( class_exists( 'Pods_Pages' ) ) {
25 return;
26 }
27
28 /**
29 * Class Pods_Pages
30 */
31 class Pods_Pages extends PodsComponent {
32
33 /**
34 * Current Pod Page
35 *
36 * @var array
37 *
38 * @since 2.0.0
39 */
40 public static $exists = null;
41
42 /**
43 * Object type
44 *
45 * @var string
46 *
47 * @since 2.0.0
48 */
49 private $object_type = '_pods_page';
50
51 /**
52 * Whether the page has been checked already
53 *
54 * @var bool
55 *
56 * @since 2.1.0
57 */
58 public static $checked = false;
59
60 /**
61 * Keep track of if pods_content has been called yet
62 *
63 * @var bool
64 *
65 * @since 2.3.0
66 */
67 public static $content_called = false;
68
69 /**
70 * The capability type.
71 *
72 * @link https://codex.wordpress.org/Function_Reference/register_post_type
73 * @var string
74 */
75 private $capability_type = 'pods_page';
76
77 /**
78 * {@inheritdoc}
79 */
80 public function init() {
81 if ( ! did_action( 'init' ) ) {
82 add_action( 'init', [ $this, 'register_config' ] );
83 } else {
84 $this->register_config();
85 }
86
87 add_shortcode( 'pods-content', array( $this, 'shortcode' ) );
88
89 add_filter( 'post_type_link', array( $this, 'post_type_link' ), 10, 2 );
90
91 if ( ! is_admin() ) {
92 add_action( 'load_textdomain', array( $this, 'page_check' ), 12 );
93 } else {
94 add_filter( 'post_updated_messages', array( $this, 'setup_updated_messages' ), 10, 1 );
95
96 add_action( 'add_meta_boxes_' . $this->object_type, array( $this, 'edit_page_form' ) );
97
98 add_filter( 'get_post_metadata', array( $this, 'get_meta' ), 10, 4 );
99 add_filter( 'update_post_metadata', array( $this, 'save_meta' ), 10, 4 );
100
101 add_action( 'pods_meta_save_pre_post__pods_page', array( $this, 'fix_filters' ), 10, 5 );
102 add_action( 'post_updated', array( $this, 'clear_cache' ), 10, 3 );
103 add_action( 'delete_post', array( $this, 'clear_cache' ), 10, 1 );
104 add_filter( 'post_row_actions', array( $this, 'remove_row_actions' ), 10, 2 );
105 add_filter( 'bulk_actions-edit-' . $this->object_type, array( $this, 'remove_bulk_actions' ) );
106
107 add_filter( 'builder_layout_filter_non_layout_post_types', array( $this, 'disable_builder_layout' ) );
108 }
109
110 add_filter( 'members_get_capabilities', array( $this, 'get_capabilities' ) );
111 }
112
113 /**
114 * Register the configuration for this object.
115 *
116 * @since 2.9.9
117 */
118 public function register_config() {
119 $args = array(
120 'label' => 'Pod Pages',
121 'labels' => array( 'singular_name' => 'Pod Page' ),
122 'public' => false,
123 'can_export' => false,
124 'show_ui' => true,
125 'show_in_menu' => false,
126 'query_var' => false,
127 'rewrite' => false,
128 'has_archive' => false,
129 'hierarchical' => false,
130 'supports' => array( 'title', 'author', 'revisions' ),
131 'menu_icon' => pods_svg_icon( 'pods' ),
132 'delete_with_user' => false,
133 );
134
135 if ( ! pods_is_admin() ) {
136 $args['capability_type'] = $this->capability_type;
137 }
138
139 $args = PodsInit::object_label_fix( $args, 'post_type', $this->object_type );
140
141 register_post_type( $this->object_type, apply_filters( 'pods_internal_register_post_type_object_page', $args ) );
142
143 $args = [
144 'internal' => true,
145 'type' => 'post_type',
146 'storage' => 'meta',
147 'name' => $this->object_type,
148 'label' => 'Pod Pages',
149 'label_singular' => 'Pod Page',
150 'description' => '',
151 'public' => 0,
152 'show_ui' => 1,
153 'rest_enable' => 0,
154 'supports_title' => 1,
155 'supports_editor' => 0,
156 'supports_author' => 1,
157 'supports_revisions' => 1,
158 ];
159
160 if ( ! pods_is_admin() ) {
161 $args['capability_type'] = 'custom';
162 $args['capability_type_custom'] = $this->capability_type;
163 }
164
165 pods_register_type( 'post_type', $this->object_type, $args );
166
167 $page_templates = static function() {
168 if ( ! function_exists( 'get_page_templates' ) ) {
169 include_once ABSPATH . 'wp-admin/includes/theme.php';
170 }
171
172 $wp_page_templates = apply_filters( 'pods_page_templates', get_page_templates() );
173
174 $page_templates = [];
175
176 foreach ( $wp_page_templates as $page_template => $file ) {
177 $page_templates[ $page_template . ' - ' . $file ] = $file;
178 }
179
180 $page_templates[ __( '-- Select a WP Page Template --', 'pods' ) ] = '';
181
182 $page_templates[ __( 'Custom (uses only Pod Page content)', 'pods' ) ] = '_custom';
183
184 if ( ! in_array( 'pods.php', $page_templates, true ) && locate_template( [ 'pods.php', false ] ) ) {
185 $page_templates[ __( 'Pods (Pods Default)', 'pods' ) . ' - pods.php' ] = 'pods.php';
186 }
187
188 if ( ! in_array( 'page.php', $page_templates, true ) && locate_template( [ 'page.php', false ] ) ) {
189 $page_templates[ __( 'Page (WP Default)', 'pods' ) . ' - page.php' ] = 'page.php';
190 }
191
192 if ( ! in_array( 'index.php', $page_templates, true ) && locate_template( [ 'index.php', false ] ) ) {
193 $page_templates[ __( 'Index (WP Fallback)', 'pods' ) . ' - index.php' ] = 'index.php';
194 }
195
196 ksort( $page_templates );
197
198 return array_flip( $page_templates );
199 };
200
201 $page_fields = [
202 [
203 'name' => 'page_title',
204 'label' => __( 'Page Title', 'pods' ),
205 'type' => 'text',
206 ],
207 [
208 'name' => 'code_php_notice',
209 'type' => 'html',
210 'html_content' => sprintf(
211 '
212 <div class="pods-ui-notice-admin pods-ui-notice-warning">
213 <p>⚠️&nbsp;&nbsp;%1$s</p>
214 <p><a href="%2$s" target="_blank" rel="noopener noreferrer">%3$s</a> | <a href="%4$s" target="_blank" rel="noopener noreferrer">%5$s</a></p>
215 </div>
216 ',
217 esc_html__( 'PHP detected, this feature is deprecated', 'pods' ),
218 'https://docs.pods.io/displaying-pods/pod-page-template-hierarchy-for-themes/',
219 esc_html__( 'Read more about file-based templates', 'pods' ),
220 admin_url( 'admin.php?page=pods-components' ),
221 esc_html__( 'Switch to file-based Pod Pages using our Migrate PHP into File-based templates component', 'pods' )
222 ),
223 'wildcard-on' => [
224 'code' => [
225 '\?>',
226 '<\?',
227 ],
228 ],
229 ],
230 [
231 'name' => 'code',
232 'label' => __( 'Page Code', 'pods' ),
233 'type' => 'code',
234 'attributes' => [
235 'id' => 'content',
236 ],
237 'label_options' => [
238 'attributes' => [
239 'for' => 'content',
240 ],
241 ],
242 ],
243 [
244 'name' => 'precode_notice',
245 'type' => 'html',
246 'html_content' => sprintf(
247 '
248 <div class="pods-ui-notice-admin pods-ui-notice-warning">
249 <p>⚠️&nbsp;&nbsp;%1$s</p>
250 <p><a href="%2$s" target="_blank" rel="noopener noreferrer">%3$s</a> | <a href="%4$s" target="_blank" rel="noopener noreferrer">%5$s</a></p>
251 </div>
252 ',
253 esc_html__( 'Precode detected, this feature is deprecated', 'pods' ),
254 'https://docs.pods.io/displaying-pods/pod-page-template-hierarchy-for-themes/',
255 esc_html__( 'Read more about file-based templates', 'pods' ),
256 admin_url( 'admin.php?page=pods-components' ),
257 esc_html__( 'Switch to file-based Pod Pages using our Migrate PHP into File-based templates component', 'pods' )
258 ),
259 'excludes-on' => [
260 'precode' => '',
261 ],
262 ],
263 [
264 'name' => 'precode',
265 'label' => __( 'Page Precode', 'pods' ),
266 'type' => 'code',
267 'help' => __( 'Precode will run before your theme outputs the page. It is expected that this value will be a block of PHP. You must open the PHP tag here, as we do not open it for you by default.', 'pods' ),
268 'excludes-on' => [
269 'precode' => '',
270 ],
271 ],
272 [
273 'name' => 'page_template',
274 'label' => __( 'Page Template', 'pods' ),
275 'default' => '',
276 'type' => 'pick',
277 'pick_object' => 'custom-simple',
278 'pick_format_type' => 'single',
279 'pick_format_single' => 'dropdown',
280 'data' => $page_templates,
281 'override_object_field' => true,
282 ],
283 ];
284
285 $associated_pods = static function() {
286 $associated_pods = [
287 0 => __( '-- Select a Pod --', 'pods' ),
288 ];
289
290 $all_pods = pods_api()->load_pods( [ 'labels' => true ] );
291
292 if ( ! empty( $all_pods ) ) {
293 foreach ( $all_pods as $pod_name => $pod_label ) {
294 $associated_pods[ $pod_name ] = $pod_label . ' (' . $pod_name . ')';
295 }
296 } else {
297 $associated_pods[0] = __( 'None Found', 'pods' );
298 }
299
300 return $associated_pods;
301 };
302
303 $association_fields = [
304 [
305 'name' => 'pod',
306 'label' => __( 'Associated Pod', 'pods' ),
307 'default' => 0,
308 'type' => 'pick',
309 'pick_object' => 'custom-simple',
310 'pick_format_type' => 'single',
311 'pick_format_single' => 'dropdown',
312 'placeholder' => __( 'Select Pod', 'pods' ),
313 'data' => $associated_pods,
314 'dependency' => true,
315 ],
316 [
317 'name' => 'pod_slug',
318 'label' => __( 'Wildcard Slug', 'pods' ),
319 'help' => __( 'Setting the Wildcard Slug is an easy way to setup a detail page. You can use the special tag {@url.2} to match the *third* level of the URL of a Pod Page named "first/second/*" part of the pod page. This is functionally the same as using pods_v_sanitized( 2, "url" ) in PHP.', 'pods' ),
320 'type' => 'text',
321 'excludes-on' => [ 'pod' => 0 ],
322 ],
323 ];
324
325 $restrict_fields = [
326 [
327 'name' => 'admin_only',
328 'label' => __( 'Restrict access to Admins', 'pods' ),
329 'default' => 0,
330 'type' => 'boolean',
331 'dependency' => true,
332 ],
333 [
334 'name' => 'restrict_role',
335 'label' => __( 'Restrict access by Role', 'pods' ),
336 'help' => [
337 __( '<h6>Roles</h6> Roles are assigned to users to provide them access to specific functionality in WordPress. Please see the Roles and Capabilities component in Pods for an easy tool to add your own roles and edit existing ones.', 'pods' ),
338 'http://codex.wordpress.org/Roles_and_Capabilities',
339 ],
340 'default' => 0,
341 'type' => 'boolean',
342 'dependency' => true,
343 ],
344 [
345 'name' => 'roles_allowed',
346 'label' => __( 'Role(s) Allowed', 'pods' ),
347 'type' => 'pick',
348 'pick_object' => 'role',
349 'pick_format_type' => 'multi',
350 'pick_format_multi' => 'autocomplete',
351 'pick_ajax' => false,
352 'default' => '',
353 'depends-on' => [
354 'pods_meta_restrict_role' => true,
355 ],
356 ],
357 [
358 'name' => 'restrict_capability',
359 'label' => __( 'Restrict access by Capability', 'pods' ),
360 'help' => [
361 __( '<h6>Capabilities</h6> Capabilities denote access to specific functionality in WordPress, and are assigned to specific User Roles. Please see the Roles and Capabilities component in Pods for an easy tool to add your own capabilities and roles.', 'pods' ),
362 'http://codex.wordpress.org/Roles_and_Capabilities',
363 ],
364 'default' => 0,
365 'type' => 'boolean',
366 'dependency' => true,
367 ],
368 [
369 'name' => 'capability_allowed',
370 'label' => __( 'Capability Allowed', 'pods' ),
371 'type' => 'pick',
372 'pick_object' => 'capability',
373 'pick_format_type' => 'multi',
374 'pick_format_multi' => 'autocomplete',
375 'pick_ajax' => false,
376 'default' => '',
377 'depends-on' => [
378 'pods_meta_restrict_capability' => true,
379 ],
380 ],
381 [
382 'name' => 'restrict_redirect',
383 'label' => __( 'Redirect if Restricted', 'pods' ),
384 'default' => 0,
385 'type' => 'boolean',
386 'dependency' => true,
387 ],
388 [
389 'name' => 'restrict_redirect_login',
390 'label' => __( 'Redirect to WP Login page', 'pods' ),
391 'default' => 0,
392 'type' => 'boolean',
393 'dependency' => true,
394 'depends-on' => [
395 'pods_meta_restrict_redirect' => true,
396 ],
397 ],
398 [
399 'name' => 'restrict_redirect_url',
400 'label' => __( 'Redirect to a Custom URL', 'pods' ),
401 'default' => '',
402 'type' => 'text',
403 'depends-on' => [
404 'pods_meta_restrict_redirect' => true,
405 'pods_meta_restrict_redirect_login' => false,
406 ],
407 ],
408 ];
409
410 pods_register_group(
411 [
412 'name' => 'pod-page',
413 'label' => __( 'Page', 'pods' ),
414 'description' => '',
415 'weight' => 0,
416 'meta_box_context' => 'normal',
417 'meta_box_priority' => 'high',
418 ],
419 $this->object_type,
420 $page_fields
421 );
422
423 pods_register_group(
424 [
425 'name' => 'pod-association',
426 'label' => __( 'Pod Association', 'pods' ),
427 'description' => '',
428 'weight' => 1,
429 'meta_box_context' => 'normal',
430 'meta_box_priority' => 'high',
431 ],
432 $this->object_type,
433 $association_fields
434 );
435
436 pods_register_group(
437 [
438 'name' => 'restrict-content',
439 'label' => __( 'Restrict Content', 'pods' ),
440 'description' => '',
441 'weight' => 2,
442 'meta_box_context' => 'normal',
443 'meta_box_priority' => 'high',
444 ],
445 $this->object_type,
446 $restrict_fields
447 );
448 }
449
450 /**
451 * @param $caps
452 *
453 * @return array
454 */
455 public function get_capabilities( $caps ) {
456
457 $caps = array_merge(
458 $caps, array(
459 'edit_' . $this->capability_type,
460 'read_' . $this->capability_type,
461 'delete_' . $this->capability_type,
462 'edit_' . $this->capability_type . 's',
463 'edit_others_' . $this->capability_type . 's',
464 'publish_' . $this->capability_type . 's',
465 'read_private_' . $this->capability_type . 's',
466 'edit_' . $this->capability_type . 's',
467 )
468 );
469
470 return $caps;
471 }
472
473 /**
474 * Pod Page Content Shortcode support for use anywhere that supports WP Shortcodes
475 *
476 * @param array $tags An associative array of shortcode properties
477 * @param string $content Not currently used
478 *
479 * @return string
480 * @since 2.3.9
481 */
482 public function shortcode( $tags, $content = null ) {
483
484 if ( ! isset( $tags['page'] ) || empty( $tags['page'] ) ) {
485 $tags['page'] = null;
486 }
487
488 $pods_page = self::exists( $tags['page'] );
489
490 if ( empty( $pods_page ) ) {
491 return '<p>Pods Page not found</p>';
492 }
493
494 return self::content( true, $pods_page );
495 }
496
497 /**
498 * Disable this Post Type from appearing in the Builder layouts list
499 *
500 * @param array $post_types
501 *
502 * @return array
503 */
504 public function disable_builder_layout( $post_types ) {
505
506 $post_types[] = $this->object_type;
507
508 return $post_types;
509 }
510
511 /**
512 * Update Post Type messages
513 *
514 * @param array $messages
515 *
516 * @return array
517 * @since 2.0.2
518 */
519 public function setup_updated_messages( $messages ) {
520
521 global $post, $post_ID;
522
523 $post_type = get_post_type_object( $this->object_type );
524
525 $labels = $post_type->labels;
526
527 $messages[ $post_type->name ] = array(
528 1 => sprintf( __( '%1$s updated. <a href="%2$s">%3$s</a>', 'pods' ), $labels->singular_name, esc_url( get_permalink( $post_ID ) ), $labels->view_item ),
529 2 => __( 'Custom field updated.', 'pods' ),
530 3 => __( 'Custom field deleted.', 'pods' ),
531 4 => sprintf( __( '%s updated.', 'pods' ), $labels->singular_name ),
532 /* translators: %s: date and time of the revision */
533 5 => isset( $_GET['revision'] ) ? sprintf( __( '%1$s restored to revision from %2$s', 'pods' ), $labels->singular_name, wp_post_revision_title( (int) $_GET['revision'], false ) ) : false,
534 6 => sprintf( __( '%1$s published. <a href="%2$s">%3$s</a>', 'pods' ), $labels->singular_name, esc_url( get_permalink( $post_ID ) ), $labels->view_item ),
535 7 => sprintf( __( '%s saved.', 'pods' ), $labels->singular_name ),
536 8 => sprintf( __( '%1$s submitted. <a target="_blank" rel="noopener noreferrer" href="%2$s">Preview %3$s</a>', 'pods' ), $labels->singular_name, esc_url( add_query_arg( 'preview', 'true', get_permalink( $post_ID ) ) ), $labels->singular_name ),
537 9 => sprintf(
538 __( '%1$s scheduled for: <strong>%2$s</strong>. <a target="_blank" rel="noopener noreferrer" href="%3$s">Preview %4$s</a>', 'pods' ), $labels->singular_name,
539 // translators: Publish box date format, see http://php.net/date
540 date_i18n( __( 'M j, Y @ G:i' ), strtotime( $post->post_date ) ), esc_url( get_permalink( $post_ID ) ), $labels->singular_name
541 ),
542 10 => sprintf( __( '%1$s draft updated. <a target="_blank" rel="noopener noreferrer" href="%2$s">Preview %3$s</a>', 'pods' ), $labels->singular_name, esc_url( add_query_arg( 'preview', 'true', get_permalink( $post_ID ) ) ), $labels->singular_name ),
543 );
544
545 if ( false === (boolean) $post_type->public ) {
546 $messages[ $post_type->name ][1] = sprintf( __( '%s updated.', 'pods' ), $labels->singular_name );
547 $messages[ $post_type->name ][6] = sprintf( __( '%s published.', 'pods' ), $labels->singular_name );
548 $messages[ $post_type->name ][8] = sprintf( __( '%s submitted.', 'pods' ), $labels->singular_name );
549 $messages[ $post_type->name ][9] = sprintf(
550 __( '%1$s scheduled for: <strong>%2$s</strong>.', 'pods' ), $labels->singular_name,
551 // translators: Publish box date format, see http://php.net/date
552 date_i18n( __( 'M j, Y @ G:i' ), strtotime( $post->post_date ) )
553 );
554 $messages[ $post_type->name ][10] = sprintf( __( '%s draft updated.', 'pods' ), $labels->singular_name );
555 }
556
557 return $messages;
558 }
559
560 /**
561 * Enqueue styles
562 *
563 * @since 2.0.0
564 */
565 public function admin_assets() {
566 wp_enqueue_script( 'pods-dfv' );
567 wp_enqueue_style( 'pods-styles' );
568 }
569
570 /**
571 * Fix filters, specifically removing balanceTags
572 *
573 * @since 2.0.1
574 *
575 * @param $data
576 * @param null $pod
577 * @param null $id
578 * @param null $groups
579 * @param null $post
580 */
581 public function fix_filters( $data, $pod = null, $id = null, $groups = null, $post = null ) {
582
583 remove_filter( 'content_save_pre', 'balanceTags', 50 );
584 }
585
586 /**
587 * Remove unused row actions
588 *
589 * @since 2.0.5
590 *
591 * @param $actions
592 * @param $post
593 *
594 * @return
595 */
596 public function remove_row_actions( $actions, $post ) {
597
598 global $current_screen;
599
600 if ( ! is_object( $current_screen ) || $this->object_type != $current_screen->post_type ) {
601 return $actions;
602 }
603
604 if ( isset( $actions['view'] ) ) {
605 unset( $actions['view'] );
606 }
607
608 if ( isset( $actions['inline hide-if-no-js'] ) ) {
609 unset( $actions['inline hide-if-no-js'] );
610 }
611
612 // W3 Total Cache
613 if ( isset( $actions['pgcache_purge'] ) ) {
614 unset( $actions['pgcache_purge'] );
615 }
616
617 return $actions;
618 }
619
620 /**
621 * Remove unused bulk actions
622 *
623 * @since 2.0.5
624 *
625 * @param $actions
626 *
627 * @return
628 */
629 public function remove_bulk_actions( $actions ) {
630
631 if ( isset( $actions['edit'] ) ) {
632 unset( $actions['edit'] );
633 }
634
635 return $actions;
636 }
637
638 /**
639 * Clear cache on save
640 *
641 * @since 2.0.0
642 *
643 * @param $data
644 * @param null $pod
645 * @param null $id
646 * @param null $groups
647 * @param null $post
648 */
649 public function clear_cache( $data, $pod = null, $id = null, $groups = null, $post = null ) {
650
651 $old_post = $id;
652
653 if ( ! is_object( $id ) ) {
654 $old_post = null;
655 }
656
657 if ( ! is_array( $data ) && 0 < $data ) {
658 $post = $data;
659 $post = get_post( $post );
660 }
661
662 if ( ! is_object( $post ) || $this->object_type !== $post->post_type ) {
663 return;
664 }
665
666 pods_transient_clear( 'pods_object_pages' );
667
668 if ( $old_post instanceof WP_Post && $this->object_type === $old_post->post_type ) {
669 pods_cache_clear( $old_post->post_title, 'pods_object_page_wildcard' );
670 }
671
672 pods_cache_clear( $post->post_title, 'pods_object_page_wildcard' );
673
674 self::flush_rewrites();
675 }
676
677 /**
678 * Change post title placeholder text
679 *
680 * @since 2.0.0
681 *
682 * @param $text
683 * @param $post
684 *
685 * @return string
686 */
687 public function set_title_text( $text, $post ) {
688 return __( 'Enter URL here', 'pods' );
689 }
690
691 /**
692 * Edit page form
693 *
694 * @since 2.0.0
695 */
696 public function edit_page_form() {
697
698 global $post_type;
699
700 if ( $this->object_type !== $post_type ) {
701 return;
702 }
703
704 add_action( 'admin_enqueue_scripts', array( $this, 'admin_assets' ), 21 );
705 add_filter( 'enter_title_here', array( $this, 'set_title_text' ), 10, 2 );
706
707 $page_code = get_the_content();
708 $pre_code = get_post_meta( get_the_ID(), 'precode', true );
709
710 $has_php = false !== strpos( $page_code, '<?' );
711 $has_precode = ! empty( $pre_code );
712
713 if ( $has_php && pods_eval_show_errors() ) {
714 pods_deprecated( 'Pod Page PHP code has been deprecated, please use WP Page Templates or hook into the pods_content filter instead of embedding PHP.', '2.1' );
715
716 pods_message(
717 sprintf(
718 '
719 <p><strong>%1$s:</strong> %2$s</p>
720 <p><a href="%3$s" target="_blank" rel="noopener noreferrer">%4$s</a> | <a href="%5$s" target="_blank" rel="noopener noreferrer">%6$s</a></p>
721 ',
722 esc_html__( 'Pod Page Error', 'pods' ),
723 esc_html__( 'This Pod Page contains PHP code that will not run due to security restrictions in Pods.', 'pods' ),
724 'https://docs.pods.io/displaying-pods/pod-page-template-hierarchy-for-themes/',
725 esc_html__( 'Read more about file-based templates', 'pods' ),
726 admin_url( 'admin.php?page=pods-components' ),
727 esc_html__( 'Switch to file-based Pod Pages using our Migrate PHP into File-based templates component', 'pods' )
728 ),
729 'error',
730 false,
731 false
732 );
733 }
734
735 if ( $has_precode && pods_eval_show_errors() ) {
736 pods_deprecated( 'Pod Page precode has been deprecated, please use WP Page Templates or hook into the pods_content filter instead of embedding PHP.', '2.1' );
737
738 pods_message(
739 sprintf(
740 '
741 <p><strong>%1$s:</strong> %2$s</p>
742 <p><a href="%3$s" target="_blank" rel="noopener noreferrer">%4$s</a> | <a href="%5$s" target="_blank" rel="noopener noreferrer">%6$s</a></p>
743 ',
744 __( 'Pod Page Error', 'pods' ),
745 __( 'This Pod Page contains precode (deprecated) that will not run due to security restrictions in Pods.', 'pods' ),
746 'https://docs.pods.io/displaying-pods/pod-page-template-hierarchy-for-themes/',
747 esc_html__( 'Read more about file-based templates', 'pods' ),
748 admin_url( 'admin.php?page=pods-components' ),
749 esc_html__( 'Switch to file-based Pod Pages using our Migrate PHP into File-based templates component', 'pods' )
750 ),
751 'error',
752 false,
753 false
754 );
755 }
756
757 }
758
759 /**
760 * Filter permalinks and adjust for pod pages
761 *
762 * @param $post_link
763 * @param $post
764 *
765 * @return mixed
766 */
767 public function post_type_link( $post_link, $post ) {
768
769 if ( empty( $post ) || $this->object_type != $post->post_type ) {
770 return $post_link;
771 }
772
773 $post_link = get_site_url() . '/';
774
775 if ( false === strpos( $post->post_title, '*' ) ) {
776 $post_link .= trim( $post->post_title, '/ ' ) . '/';
777 }
778
779 return $post_link;
780 }
781
782 /**
783 * Get the fields
784 *
785 * @param null $_null
786 * @param int $post_ID
787 * @param string $meta_key
788 * @param bool $single
789 *
790 * @return array|bool|int|mixed|null|string|void
791 */
792 public function get_meta( $_null, $post_ID = null, $meta_key = null, $single = false ) {
793 if ( 'code' !== $meta_key ) {
794 return $_null;
795 }
796
797 $post = get_post( $post_ID );
798
799 if ( ! is_object( $post ) || $this->object_type !== $post->post_type ) {
800 return $_null;
801 }
802
803 return $post->post_content;
804 }
805
806 /**
807 * Save the fields
808 *
809 * @param $_null
810 * @param int $post_ID
811 * @param string $meta_key
812 * @param string $meta_value
813 *
814 * @return bool|int|null
815 */
816 public function save_meta( $_null, $post_ID = null, $meta_key = null, $meta_value = null ) {
817 if ( 'code' !== $meta_key ) {
818 return $_null;
819 }
820
821 $post = get_post( $post_ID );
822
823 if ( ! is_object( $post ) || $this->object_type !== $post->post_type ) {
824 return $_null;
825 }
826
827 $postdata = array(
828 'ID' => $post_ID,
829 'post_content' => $meta_value,
830 );
831
832 remove_filter( current_filter(), array( $this, __FUNCTION__ ) );
833
834 $revisions = false;
835
836 if ( has_action( 'pre_post_update', 'wp_save_post_revision' ) ) {
837 remove_action( 'pre_post_update', 'wp_save_post_revision' );
838
839 $revisions = true;
840 }
841
842 wp_update_post( (object) $postdata );
843
844 // Flush the find posts cache.
845 pods_cache_clear( true, 'pods_post_type_storage_' . $this->object_type );
846
847 // objects will be automatically sanitized
848 if ( $revisions ) {
849 add_action( 'pre_post_update', [ $this, 'save_post_revision_for_post' ] );
850 }
851
852 return true;
853 }
854
855 /**
856 * Save post revision for a post without a return.
857 *
858 * @since 3.2.8
859 *
860 * @param int $post_id The post ID.
861 */
862 public function save_post_revision_for_post( $post_id ) {
863 wp_save_post_revision( $post_id );
864 }
865
866 /**
867 * Flush Pod Page Rewrite cache
868 *
869 * @return array Pod Page Rewrites
870 *
871 * @since 2.3.4
872 */
873 public static function flush_rewrites() {
874
875 $args = array(
876 'post_type' => '_pods_page',
877 'nopaging' => true,
878 'posts_per_page' => - 1,
879 'post_status' => 'publish',
880 'order' => 'ASC',
881 'orderby' => 'title',
882 );
883
884 $pod_pages = get_posts( $args );
885
886 $pod_page_rewrites = array();
887
888 foreach ( $pod_pages as $pod_page ) {
889 $pod_page_rewrites[ $pod_page->ID ] = $pod_page->post_title;
890 }
891
892 uksort( $pod_page_rewrites, 'pods_page_length_sort' );
893
894 pods_transient_set( 'pods_object_page_rewrites', $pod_page_rewrites, WEEK_IN_SECONDS );
895
896 $pod_page_rewrites = array_flip( $pod_page_rewrites );
897
898 return $pod_page_rewrites;
899 }
900
901 /**
902 * Check to see if Pod Page exists and return data
903 *
904 * $uri not required, if NULL then returns REQUEST_URI matching Pod Page
905 *
906 * @param string $uri The Pod Page URI to check if exists
907 *
908 * @return array|bool
909 */
910 public static function exists( $uri = null ) {
911 if ( null === $uri ) {
912 $uri = pods_current_path();
913 }
914
915 if ( empty( $uri ) ) {
916 return false;
917 }
918
919 $uri = explode( '?', $uri );
920 $uri = explode( '#', $uri[0] );
921 $uri = $uri[0];
922
923 $home_path = wp_parse_url( get_home_url(), PHP_URL_PATH );
924
925 if ( ! empty( $home_path ) && '/' !== $home_path ) {
926 $uri = substr( $uri, strlen( $home_path ) );
927 }
928
929 $uri = trim( $uri, '/' );
930 $uri_depth = count( array_filter( explode( '/', $uri ) ) ) - 1;
931
932 $pods_page_exclusions = array(
933 'wp-admin',
934 'wp-content',
935 'wp-includes',
936 'index.php',
937 'wp-login.php',
938 'wp-signup.php',
939 );
940
941 $pods_page_exclusions = apply_filters( 'pods_page_exclusions', $pods_page_exclusions );
942
943 if ( is_admin() || empty( $uri ) ) {
944 return false;
945 }
946
947 foreach ( $pods_page_exclusions as $exclusion ) {
948 if ( 0 === strpos( $uri, $exclusion ) ) {
949 return false;
950 }
951 }
952
953 $object = apply_filters( 'pods_page_exists', false, $uri );
954 if ( ! empty( $object ) ) {
955 return $object;
956 }
957
958 if ( false === strpos( $uri, '*' ) && ! apply_filters( 'pods_page_regex_matching', false ) ) {
959 $object = pods_by_title( $uri, ARRAY_A, '_pods_page', 'publish' );
960 }
961
962 $wildcard = false;
963
964 if ( empty( $object ) ) {
965 if ( false === strpos( $uri, '*' ) ) {
966 $object = pods_cache_get( $uri, 'pods_object_page_wildcard' );
967
968 if ( ! empty( $object ) ) {
969 return $object;
970 }
971 }
972
973 $pod_page_rewrites = pods_transient_get( 'pods_object_page_rewrites' );
974
975 if ( empty( $pod_page_rewrites ) ) {
976 $pod_page_rewrites = self::flush_rewrites();
977 } else {
978 $pod_page_rewrites = array_flip( $pod_page_rewrites );
979 }
980
981 $found_rewrite_page_id = 0;
982
983 if ( ! empty( $pod_page_rewrites ) ) {
984 foreach ( $pod_page_rewrites as $pod_page => $pod_page_id ) {
985 if ( ! apply_filters( 'pods_page_regex_matching', false ) ) {
986 if ( false === strpos( $pod_page, '*' ) ) {
987 continue;
988 }
989
990 $depth_check = strlen( $pod_page ) - strlen( str_replace( '/', '', $pod_page ) );
991
992 $pod_page = preg_quote( $pod_page, '/' );
993
994 $pod_page = str_replace( '\\*', '(.*)', $pod_page );
995
996 if ( $uri_depth == $depth_check && preg_match( '/^' . $pod_page . '$/', $uri ) ) {
997 $found_rewrite_page_id = $pod_page_id;
998
999 break;
1000 }
1001 } elseif ( preg_match( '/^' . str_replace( '/', '\\/', $pod_page ) . '$/', $uri ) ) {
1002 $found_rewrite_page_id = $pod_page_id;
1003
1004 break;
1005 }//end if
1006 }//end foreach
1007
1008 if ( ! empty( $found_rewrite_page_id ) ) {
1009 $object = get_post( $found_rewrite_page_id, ARRAY_A );
1010
1011 if ( empty( $object ) || '_pods_page' !== $object['post_type'] ) {
1012 $object = false;
1013 }
1014 }
1015 }//end if
1016
1017 $wildcard = true;
1018 }//end if
1019
1020 if ( ! empty( $object ) ) {
1021 $object = array(
1022 'id' => $object['ID'],
1023 'uri' => $object['post_title'],
1024 'code' => $object['post_content'],
1025 'phpcode' => $object['post_content'],
1026 // phpcode is deprecated
1027 'precode' => get_post_meta( $object['ID'], 'precode', true ),
1028 'page_template' => get_post_meta( $object['ID'], 'page_template', true ),
1029 'title' => get_post_meta( $object['ID'], 'page_title', true ),
1030 'options' => array(
1031 'admin_only' => (boolean) get_post_meta( $object['ID'], 'admin_only', true ),
1032 'restrict_role' => (boolean) get_post_meta( $object['ID'], 'restrict_role', true ),
1033 'restrict_capability' => (boolean) get_post_meta( $object['ID'], 'restrict_capability', true ),
1034 'roles_allowed' => get_post_meta( $object['ID'], 'roles_allowed', true ),
1035 'capability_allowed' => get_post_meta( $object['ID'], 'capability_allowed', true ),
1036 'restrict_redirect' => (boolean) get_post_meta( $object['ID'], 'restrict_redirect', true ),
1037 'restrict_redirect_login' => (boolean) get_post_meta( $object['ID'], 'restrict_redirect_login', true ),
1038 'restrict_redirect_url' => get_post_meta( $object['ID'], 'restrict_redirect_url', true ),
1039 'pod' => get_post_meta( $object['ID'], 'pod', true ),
1040 'pod_slug' => get_post_meta( $object['ID'], 'pod_slug', true ),
1041 ),
1042 );
1043
1044 if ( $wildcard ) {
1045 pods_cache_set( $uri, $object, 'pods_object_page_wildcard', 3600 );
1046 }
1047
1048 return $object;
1049 }//end if
1050
1051 return false;
1052 }
1053
1054 /**
1055 * Convert a Page object to a Pod Page data array.
1056 *
1057 * @since 3.2.8
1058 *
1059 * @param Page $object The Pod Page object.
1060 *
1061 * @return array The Pod Page data array.
1062 */
1063 public static function object_to_page( Page $object ): array {
1064 $id = $object->get_id();
1065
1066 return [
1067 'id' => $id,
1068 'name' => $object->get_name(),
1069 'uri' => $object->get_label(),
1070 'code' => $object->get_description(),
1071 'phpcode' => $object->get_description(),
1072 // phpcode is deprecated
1073 'precode' => get_post_meta( $id, 'precode', true ),
1074 'page_template' => get_post_meta( $id, 'page_template', true ),
1075 'title' => get_post_meta( $id, 'page_title', true ),
1076 'options' => [
1077 'admin_only' => (boolean) get_post_meta( $id, 'admin_only', true ),
1078 'restrict_role' => (boolean) get_post_meta( $id, 'restrict_role', true ),
1079 'restrict_capability' => (boolean) get_post_meta( $id, 'restrict_capability', true ),
1080 'roles_allowed' => get_post_meta( $id, 'roles_allowed', true ),
1081 'capability_allowed' => get_post_meta( $id, 'capability_allowed', true ),
1082 'restrict_redirect' => (boolean) get_post_meta( $id, 'restrict_redirect', true ),
1083 'restrict_redirect_login' => (boolean) get_post_meta( $id, 'restrict_redirect_login', true ),
1084 'restrict_redirect_url' => get_post_meta( $id, 'restrict_redirect_url', true ),
1085 'pod' => get_post_meta( $id, 'pod', true ),
1086 'pod_slug' => get_post_meta( $id, 'pod_slug', true ),
1087 ],
1088 ];
1089 }
1090
1091 /**
1092 * Check if a Pod Page exists
1093 */
1094 public function page_check() {
1095
1096 if ( self::$checked ) {
1097 return;
1098 }
1099
1100 global $pods;
1101
1102 // Fix any global confusion wherever this runs
1103 if ( isset( $pods ) && ! isset( $GLOBALS['pods'] ) ) {
1104 $GLOBALS['pods'] =& $pods;
1105 } elseif ( ! isset( $pods ) && isset( $GLOBALS['pods'] ) ) {
1106 $pods =& $GLOBALS['pods'];
1107 }
1108
1109 if ( ! defined( 'PODS_DISABLE_POD_PAGE_CHECK' ) || ! PODS_DISABLE_POD_PAGE_CHECK ) {
1110 if ( null === self::$exists ) {
1111 self::$exists = pod_page_exists();
1112 }
1113
1114 if ( false !== self::$exists ) {
1115 $pods = apply_filters( 'pods_global', $pods, self::$exists );
1116
1117 if ( ! is_wp_error( $pods ) && ( is_object( $pods ) || 404 != $pods ) ) {
1118 add_action( 'template_redirect', array( $this, 'template_redirect' ) );
1119 add_filter( 'redirect_canonical', '__return_false' );
1120 add_action( 'wp_head', array( $this, 'wp_head' ) );
1121 add_filter( 'wp_title', array( $this, 'wp_title' ), 0, 3 );
1122 add_filter( 'body_class', array( $this, 'body_class' ), 0, 1 );
1123 add_filter( 'status_header', array( $this, 'status_header' ) );
1124 add_action( 'after_setup_theme', array( $this, 'precode' ) );
1125 add_action( 'wp', array( $this, 'silence_404' ), 1 );
1126
1127 // Genesis theme integration.
1128 add_action( 'genesis_loop', [ $this, 'pods_page_content' ], 11 );
1129 }
1130 }
1131
1132 self::$checked = true;
1133 }//end if
1134 }
1135
1136 /**
1137 * Output Pdos Page content without return.
1138 *
1139 * @since 3.2.8
1140 */
1141 public function pods_page_content() {
1142 pods_content();
1143 }
1144
1145 /**
1146 * Output Pod Page Content
1147 *
1148 * @param bool $return Whether to return or not (default is to echo)
1149 *
1150 * @param bool $pods_page
1151 *
1152 * @return string|false
1153 */
1154 public static function content( $return = false, $pods_page = false ) {
1155
1156 if ( empty( $pods_page ) ) {
1157 $pods_page = self::$exists;
1158 }
1159
1160 $content = false;
1161
1162 if ( $pods_page == self::$exists && self::$content_called ) {
1163 return $content;
1164 }
1165
1166 if ( ! empty( $pods_page ) ) {
1167 /**
1168 * @var $pods \Pods
1169 */
1170 global $pods;
1171
1172 // Fix any global confusion wherever this runs
1173 if ( isset( $pods ) && ! isset( $GLOBALS['pods'] ) ) {
1174 $GLOBALS['pods'] =& $pods;
1175 } elseif ( ! isset( $pods ) && isset( $GLOBALS['pods'] ) ) {
1176 $pods =& $GLOBALS['pods'];
1177 }
1178
1179 if ( 0 < strlen( trim( $pods_page['code'] ) ) ) {
1180 $content = trim( $pods_page['code'] );
1181 }
1182
1183 ob_start();
1184
1185 do_action( 'pods_content_pre', $pods_page, $content );
1186
1187 $default_templates = self::get_templates_for_pod_page_content( $pods_page );
1188 $template_files_info = self::get_template_files_info( $default_templates );
1189
1190 $template_file = array_key_first( $template_files_info );
1191
1192 if ( $template_file ) {
1193 // Check if we are running this content function from within a Pod Page PHP template already to prevent recursion.
1194 if ( did_action( 'pods_page_loaded_template' ) ) {
1195 $content = '';
1196 } else {
1197 $content = pods_template_part( $template_file, compact( 'pods', 'pods_page' ), true );;
1198
1199 if ( $template_files_info[ $template_file ]['MagicTags'] ) {
1200 if ( is_object( $pods ) && ! empty( $pods->id ) ) {
1201 $content = $pods->do_magic_tags( $content );
1202 } else {
1203 _doing_it_wrong( 'Pods Pages', 'Pod Page template supports magic tags but cannot be processed because an associated Pod is not set in the Pod Page settings', '3.2.8' );
1204
1205 $content = '';
1206 }
1207 }
1208 }
1209
1210 echo $content;
1211 } elseif ( $content && 0 < strlen( $content ) ) {
1212 if ( false !== strpos( $content, '<?' ) ) {
1213 /**
1214 * Allow evaluating Pod Pages content by custom code snippet if needed.
1215 *
1216 * @since 3.3.0
1217 *
1218 * @param array $pods_page The Pod Page data.
1219 * @param Pods $pods The Pods instance.
1220 * @param string $content The content of the Pod Page.
1221 */
1222 do_action( 'pods_pages_eval_content', $pods_page, $pods, $content );
1223 } elseif ( is_object( $pods ) && ! empty( $pods->id ) ) {
1224 echo $pods->do_magic_tags( $content );
1225 } else {
1226 echo $content;
1227 }
1228 }
1229
1230 do_action( 'pods_content_post', $pods_page, $content );
1231
1232 $content = ob_get_clean();
1233
1234 if ( $pods_page == self::$exists ) {
1235 self::$content_called = true;
1236 }
1237 }//end if
1238
1239 $content = apply_filters( 'pods_content', $content, $pods_page );
1240
1241 if ( $return ) {
1242 return $content;
1243 }
1244
1245 echo $content;
1246
1247 return '';
1248 }
1249
1250 /**
1251 * Run any precode for current Pod Page
1252 */
1253 public function precode() {
1254
1255 global $pods;
1256
1257 // Fix any global confusion wherever this runs
1258 if ( isset( $pods ) && ! isset( $GLOBALS['pods'] ) ) {
1259 $GLOBALS['pods'] =& $pods;
1260 } elseif ( ! isset( $pods ) && isset( $GLOBALS['pods'] ) ) {
1261 $pods =& $GLOBALS['pods'];
1262 }
1263
1264 if ( false !== self::$exists ) {
1265 $permission = pods_permission( self::$exists );
1266
1267 $permission = (boolean) apply_filters( 'pods_pages_permission', $permission, self::$exists );
1268
1269 if ( $permission ) {
1270 $content = false;
1271
1272 if ( ! is_object( $pods ) && 404 != $pods && 0 < strlen( (string) pods_v( 'pod', self::$exists['options'] ) ) ) {
1273 $slug = pods_v( 'pod_slug', self::$exists['options'], null, null, true );
1274
1275 $has_slug = 0 < strlen( $slug );
1276
1277 // Handle special magic tags
1278 if ( $has_slug ) {
1279 $slug = pods_evaluate_tags( $slug, true );
1280 }
1281
1282 $pods = pods_get_instance( pods_v_sanitized( 'pod', self::$exists['options'] ), $slug );
1283
1284 // Auto 404 handling if item doesn't exist
1285 if ( $has_slug && ( empty( $slug ) || ! $pods->exists() ) && apply_filters( 'pods_pages_auto_404', true, $slug, $pods, self::$exists ) ) {
1286 $pods = 404;
1287 }
1288 }
1289
1290 if ( 0 < strlen( trim( self::$exists['precode'] ) ) ) {
1291 $content = trim( self::$exists['precode'] );
1292 }
1293
1294 do_action( 'pods_page_precode', self::$exists, $pods, $content );
1295 } elseif ( self::$exists['options']['restrict_redirect'] ) {
1296 $redirect_url = '';
1297
1298 if ( self::$exists['options']['restrict_redirect_login'] ) {
1299 $redirect_url = wp_login_url( pods_current_url() );
1300 } elseif ( ! empty( self::$exists['options']['restrict_redirect_url'] ) ) {
1301 $redirect_url = self::$exists['options']['restrict_redirect_url'];
1302 }
1303
1304 if ( ! empty( $redirect_url ) ) {
1305 wp_redirect( $redirect_url );
1306 die();
1307 }
1308 }//end if
1309
1310 if ( ! $permission || ( ! is_object( $pods ) && ( 404 == $pods || is_wp_error( $pods ) ) ) ) {
1311 remove_action( 'template_redirect', array( $this, 'template_redirect' ) );
1312 remove_action( 'wp_head', array( $this, 'wp_head' ) );
1313 remove_filter( 'redirect_canonical', '__return_false' );
1314 remove_filter( 'wp_title', array( $this, 'wp_title' ) );
1315 remove_filter( 'body_class', array( $this, 'body_class' ) );
1316 remove_filter( 'status_header', array( $this, 'status_header' ) );
1317 remove_action( 'wp', array( $this, 'silence_404' ), 1 );
1318 }
1319 }//end if
1320 }
1321
1322 /**
1323 *
1324 */
1325 public function wp_head() {
1326
1327 global $pods;
1328
1329 do_action( 'pods_wp_head' );
1330
1331 if ( ! defined( 'PODS_DISABLE_VERSION_OUTPUT' ) || ! PODS_DISABLE_VERSION_OUTPUT ) {
1332 ?>
1333 <!-- Pods Framework <?php echo esc_html( PODS_VERSION ); ?> -->
1334 <?php
1335 }
1336 if ( ( ! defined( 'PODS_DISABLE_META' ) || ! PODS_DISABLE_META ) && is_object( $pods ) && ! is_wp_error( $pods ) ) {
1337
1338 if ( isset( $pods->meta ) && is_array( $pods->meta ) && ! empty( $pods->meta ) ) {
1339 foreach ( $pods->meta as $name => $content ) {
1340 if ( 'title' === $name ) {
1341 continue;
1342 }
1343 ?>
1344 <meta name="<?php echo esc_attr( $name ); ?>" content="<?php echo esc_attr( $content ); ?>" />
1345 <?php
1346 }
1347 }
1348
1349 if ( isset( $pods->meta_properties ) && is_array( $pods->meta_properties ) && ! empty( $pods->meta_properties ) ) {
1350 foreach ( $pods->meta_properties as $property => $content ) {
1351 ?>
1352 <meta property="<?php echo esc_attr( $property ); ?>" content="<?php echo esc_attr( $content ); ?>" />
1353 <?php
1354 }
1355 }
1356
1357 if ( isset( $pods->meta_extra ) && 0 < strlen( $pods->meta_extra ) ) {
1358 echo $pods->meta_extra;
1359 }
1360 }//end if
1361 }
1362
1363 /**
1364 * @param $title
1365 * @param $sep
1366 * @param $seplocation
1367 *
1368 * @return mixed|void
1369 */
1370 public function wp_title( $title, $sep, $seplocation ) {
1371
1372 global $pods;
1373
1374 $page_title = trim( self::$exists['title'] );
1375
1376 if ( 0 < strlen( $page_title ) ) {
1377 if ( is_object( $pods ) && ! is_wp_error( $pods ) ) {
1378 $page_title = $pods->do_magic_tags( $page_title );
1379 }
1380
1381 $title = ( 'right' === $seplocation ) ? "{$page_title} {$sep} " : " {$sep} {$page_title}";
1382 } elseif ( strlen( trim( (string) $title ) ) < 1 ) {
1383 $uri = explode( '?', $_SERVER['REQUEST_URI'] );
1384 $uri = preg_replace( '@^([/]?)(.*?)([/]?)$@', '$2', $uri[0] );
1385 $uri = preg_replace( '@(-|_)@', ' ', $uri );
1386 $uri = explode( '/', $uri );
1387
1388 $title = '';
1389
1390 foreach ( $uri as $key => $page_title ) {
1391 $title .= ( 'right' === $seplocation ) ? ucwords( $page_title ) . " {$sep} " : " {$sep} " . ucwords( $page_title );
1392 }
1393 }
1394
1395 if ( ( ! defined( 'PODS_DISABLE_META' ) || ! PODS_DISABLE_META ) && is_object( $pods ) && ! is_wp_error( $pods ) && isset( $pods->meta ) && is_array( $pods->meta ) && isset( $pods->meta['title'] ) ) {
1396 $title = $pods->meta['title'];
1397 }
1398
1399 return apply_filters( 'pods_title', $title, $sep, $seplocation, self::$exists );
1400 }
1401
1402 /**
1403 * @param $classes
1404 *
1405 * @return mixed|void
1406 */
1407 public function body_class( $classes ) {
1408
1409 global $pods;
1410
1411 if ( defined( 'PODS_DISABLE_BODY_CLASSES' ) && PODS_DISABLE_BODY_CLASSES ) {
1412 return $classes;
1413 }
1414
1415 $classes[] = 'pods';
1416
1417 $uri = explode( '?', self::$exists['uri'] );
1418 $uri = explode( '#', $uri[0] );
1419
1420 $class = str_replace( array( '*', '/' ), array( '_w_', '-' ), $uri[0] );
1421 $class = sanitize_title( $class );
1422 $class = str_replace( array( '_', '--', '--' ), '-', $class );
1423 $class = trim( $class, '-' );
1424
1425 $classes[] = 'pod-page-' . $class;
1426
1427 if ( is_object( $pods ) && ! is_wp_error( $pods ) ) {
1428 $class = sanitize_title( $pods->pod );
1429 $class = str_replace( array( '_', '--', '--' ), '-', $class );
1430 $class = trim( $class, '-' );
1431 $classes[] = 'pod-' . $class;
1432 }
1433
1434 if ( is_object( $pods ) && ! is_wp_error( $pods ) && isset( $pods->body_classes ) ) {
1435 $classes[] = $pods->body_classes;
1436 }
1437
1438 return apply_filters( 'pods_body_class', $classes, $uri );
1439 }
1440
1441 /**
1442 * @return string
1443 */
1444 public function status_header() {
1445
1446 return $_SERVER['SERVER_PROTOCOL'] . ' 200 OK';
1447 }
1448
1449 /**
1450 *
1451 */
1452 public function silence_404() {
1453
1454 global $wp_query;
1455
1456 $wp_query->query_vars['error'] = '';
1457 $wp_query->is_404 = false;
1458 }
1459
1460 /**
1461 * Handle overriding the template used for a Pods Page.
1462 *
1463 * @since 2.8.11
1464 *
1465 * @param string $original_template The template to include.
1466 *
1467 * @return string The template to include.
1468 */
1469 public function template_include( $original_template ) {
1470 global $pods;
1471
1472 // Default to original template if pod page was not found.
1473 $template = $original_template;
1474
1475 if ( false !== self::$exists ) {
1476 /*
1477 * Create pods.php in your theme directory, and
1478 * style it to suit your needs. Some helpful functions:
1479 *
1480 * get_header()
1481 * pods_content()
1482 * get_sidebar()
1483 * get_footer()
1484 */
1485 $template = self::$exists['page_template'];
1486 $template = apply_filters( 'pods_page_template', $template, self::$exists );
1487
1488 $render_function = apply_filters( 'pods_template_redirect', null, $template, self::$exists );
1489
1490 if ( '_custom' === $template ) {
1491 pods_content();
1492 die();
1493 } elseif ( null !== $render_function && is_callable( $render_function ) ) {
1494 call_user_func( $render_function, $template, self::$exists );
1495 die();
1496 } elseif ( ( ! defined( 'PODS_DISABLE_DYNAMIC_TEMPLATE' ) || ! PODS_DISABLE_DYNAMIC_TEMPLATE ) && is_object( $pods ) && ! is_wp_error( $pods ) && ! empty( $pods->page_template ) ) {
1497 $template = $pods->page_template;
1498 // found the template and included it, we're good to go!
1499 } elseif ( ! empty( self::$exists['page_template'] ) ) {
1500 $template = self::$exists['page_template'];
1501 // found the template and included it, we're good to go!
1502 } else {
1503 $located_template = apply_filters( 'pods_page_locate_template', $template, self::$exists );
1504
1505 if ( $template !== $located_template ) {
1506 $template = $located_template;
1507 } else {
1508 $default_templates = self::get_templates_for_pod_page( self::$exists );
1509
1510 $template = locate_template( $default_templates );
1511
1512 if ( '' !== $template ) {
1513 /**
1514 * Allow determining whether a Pod Page template was loaded.
1515 *
1516 * @since 3.2.8
1517 *
1518 * @param string $template The template file that was loaded.
1519 * @param array $pod_page The Pods Page data.
1520 */
1521 do_action( 'pods_page_loaded_template', $template, self::$exists );
1522
1523 pods_template_part( $template, compact( 'pods' ) );
1524 } else {
1525 $template = false;
1526
1527 // templates not found in theme, default output
1528 do_action( 'pods_page_default', $template, self::$exists );
1529
1530 get_header();
1531 pods_content();
1532 get_sidebar();
1533 get_footer();
1534 die();
1535 }
1536 }//end if
1537 }//end if
1538 }
1539
1540 /**
1541 * Allow filtering the template to include for a Pods Page.
1542 *
1543 * @since 2.8.11
1544 *
1545 * @param string $template The template to use.
1546 * @param array $exists The Pods Page data.
1547 */
1548 $template = apply_filters( 'pods_page_template_include', $template, self::$exists );
1549
1550 // Attempt to set up a basic WP post object.
1551 if ( $template !== $original_template && function_exists( '\Roots\bootloader' ) && function_exists( 'resource_path' ) ) {
1552 $paths_to_check = [
1553 get_theme_file_path( '/resources/views' ),
1554 get_parent_theme_file_path( '/resources/views' ),
1555 resource_path( 'views' ),
1556 ];
1557
1558 foreach ( $paths_to_check as $path_to_check ) {
1559 $file_path = $path_to_check . DIRECTORY_SEPARATOR . $template;
1560
1561 if ( file_exists( $file_path ) ) {
1562 $template = $file_path;
1563
1564 break;
1565 }
1566 }
1567 }
1568
1569 return $template;
1570 }
1571
1572 /**
1573 *
1574 */
1575 public function template_redirect() {
1576 global $pods;
1577
1578 // Support the Sage theme, eventually we can implement template_include everywhere else after more testing.
1579 if ( function_exists( '\Roots\bootloader' ) ) {
1580 if ( ! empty( $pods ) && 0 < $pods->id() && 'post_type' === $pods->pod_data['type'] ) {
1581 // Set up the post object using the pod.
1582 query_posts( 'p=' . $pods->id() . '&post_type=' . $pods->pod_data['name'] );
1583
1584 $pod_post = get_post( $pods->id() );
1585
1586 if ( $pod_post ) {
1587 setup_postdata( $pod_post );
1588 }
1589 } elseif ( null === get_queried_object() ) {
1590 // Maybe set up the post using the front page for now.
1591 $front_page = (int) get_option( 'page_on_front' );
1592
1593 if ( 0 < $front_page ) {
1594 query_posts( 'page_id=' . $front_page );
1595
1596 $front_page_post = get_post( $front_page );
1597
1598 if ( $front_page_post ) {
1599 setup_postdata( $front_page_post );
1600 }
1601 }
1602 }
1603
1604 add_filter( 'template_include', [ $this, 'template_include' ] );
1605
1606 return;
1607 }
1608
1609 if ( false !== self::$exists ) {
1610 /*
1611 * Create pods.php in your theme directory, and
1612 * style it to suit your needs. Some helpful functions:
1613 *
1614 * get_header()
1615 * pods_content()
1616 * get_sidebar()
1617 * get_footer()
1618 */
1619 $template = self::$exists['page_template'];
1620 $template = apply_filters( 'pods_page_template', $template, self::$exists );
1621
1622 $render_function = apply_filters( 'pods_template_redirect', null, $template, self::$exists );
1623
1624 do_action( 'pods_page', $template, self::$exists );
1625
1626 if ( '_custom' === $template ) {
1627 pods_content();
1628 } elseif ( null !== $render_function && is_callable( $render_function ) ) {
1629 call_user_func( $render_function, $template, self::$exists );
1630 } elseif ( ( ! defined( 'PODS_DISABLE_DYNAMIC_TEMPLATE' ) || ! PODS_DISABLE_DYNAMIC_TEMPLATE ) && is_object( $pods ) && ! is_wp_error( $pods ) && isset( $pods->page_template ) && ! empty( $pods->page_template ) && '' != locate_template( array( $pods->page_template ), true ) ) {
1631 $template = $pods->page_template;
1632 // found the template and included it, we're good to go!
1633 } elseif ( ! empty( self::$exists['page_template'] ) && '' != locate_template( array( self::$exists['page_template'] ), true ) ) {
1634 $template = self::$exists['page_template'];
1635 // found the template and included it, we're good to go!
1636 } else {
1637 $located_template = apply_filters( 'pods_page_locate_template', $template, self::$exists );
1638
1639 if ( $template !== $located_template ) {
1640 $template = $located_template;
1641 } else {
1642 $default_templates = self::get_templates_for_pod_page( self::$exists );
1643
1644 $template = locate_template( $default_templates );
1645
1646 if ( '' !== $template ) {
1647 /**
1648 * Allow determining whether a Pod Page template was loaded.
1649 *
1650 * @since 3.2.8
1651 *
1652 * @param string $template The template file that was loaded.
1653 * @param array $pod_page The Pods Page data.
1654 */
1655 do_action( 'pods_page_loaded_template', $template, self::$exists );
1656
1657 pods_template_part( $template, compact( 'pods' ) );
1658 } else {
1659 $template = false;
1660
1661 // templates not found in theme, default output
1662 do_action( 'pods_page_default', $template, self::$exists );
1663
1664 get_header();
1665 pods_content();
1666 get_sidebar();
1667 get_footer();
1668 }
1669 }//end if
1670 }//end if
1671
1672 do_action( 'pods_page_end', $template, self::$exists );
1673
1674 exit;
1675 }//end if
1676 }
1677
1678 /**
1679 * Get templates for pod page.
1680 *
1681 * @since 3.2.8
1682 *
1683 * @param array|Page $pod_page The pod page data.
1684 *
1685 * @return array The list of templates for the pod page.
1686 */
1687 public static function get_templates_for_pod_page( $pod_page ): array {
1688 if ( $pod_page instanceof Page ) {
1689 $pod_page = self::object_to_page( $pod_page );
1690 }
1691
1692 $default_templates = [];
1693
1694 if ( ! empty( $pod_page ) ) {
1695 $uri = explode( '?', $pod_page['uri'] );
1696 $uri = explode( '#', $uri[0] );
1697 $uri = $uri[0];
1698
1699 $page_path = explode( '/', $uri );
1700
1701 while ( $last = array_pop( $page_path ) ) {
1702 $file_name = str_replace( '*', '-w-', implode( '/', $page_path ) . '/' . $last );
1703 $file_name = sanitize_title( $file_name );
1704 $file_name = trim( str_replace( '--', '-', $file_name ), ' -' );
1705
1706 $default_templates[] = 'pods/pages/' . $file_name . '.php';
1707 $default_templates[] = 'pods/' . $file_name . '.php';
1708 $default_templates[] = 'pods-' . $file_name . '.php';
1709 }
1710 }
1711
1712 $default_templates[] = 'pods.php';
1713
1714 /**
1715 * Allow filtering the list of default templates.
1716 *
1717 * @since unknown
1718 *
1719 * @param array $default_templates The list of default templates.
1720 * @param array $pod_page The current Pod Page data.
1721 */
1722 return (array) apply_filters( 'pods_page_default_templates', $default_templates, $pod_page );
1723 }
1724
1725 /**
1726 * Get templates for pod page content.
1727 *
1728 * @since 3.2.8
1729 *
1730 * @param array|Page $pod_page The pod page data.
1731 *
1732 * @return array The list of templates for the pod page content.
1733 */
1734 public static function get_templates_for_pod_page_content( $pod_page ): array {
1735 if ( $pod_page instanceof Page ) {
1736 $pod_page = self::object_to_page( $pod_page );
1737 }
1738
1739 $default_templates = [];
1740
1741 if ( ! empty( $pod_page ) ) {
1742 $uri = explode( '?', $pod_page['uri'] );
1743 $uri = explode( '#', $uri[0] );
1744 $uri = $uri[0];
1745
1746 $page_path = explode( '/', $uri );
1747
1748 while ( $last = array_pop( $page_path ) ) {
1749 $file_name = str_replace( '*', '-w-', implode( '/', $page_path ) . '/' . $last );
1750 $file_name = sanitize_title( $file_name );
1751 $file_name = trim( str_replace( '--', '-', $file_name ), ' -' );
1752
1753 $default_templates[] = 'pods/pages/content/' . $file_name . '.php';
1754 }
1755 }
1756
1757 /**
1758 * Allow filtering the list of default templates for Pod Page content.
1759 *
1760 * @since unknown
1761 *
1762 * @param array $default_templates The list of default templates for Pod Page content.
1763 * @param array $pod_page The current Pod Page data.
1764 */
1765 return (array) apply_filters( 'pods_page_content_default_templates', $default_templates, $pod_page );
1766 }
1767
1768 /**
1769 * Get the list of template header information for each of the template files.
1770 *
1771 * @since 3.2.8
1772 *
1773 * @param array<int,string> $template_files The list of template files.
1774 *
1775 * @return array The list of template header information for each of the template files.
1776 */
1777 public static function get_template_files_info( array $template_files ): array {
1778 $template_files_info = [];
1779
1780 foreach ( $template_files as $template_file ) {
1781 $file_path = locate_template( $template_file );
1782
1783 // Skip if template was not found.
1784 if ( '' === $file_path ) {
1785 continue;
1786 }
1787
1788 $data = get_file_data( $file_path, [
1789 'URI' => 'Pod Page URI',
1790 'MagicTags' => 'Magic Tags',
1791 ] );
1792
1793 $data['MagicTags'] = pods_is_truthy( $data['MagicTags'] );
1794
1795 $template_files_info[ $template_file ] = $data;
1796 }
1797
1798 return $template_files_info;
1799 }
1800 }
1801
1802 /**
1803 * Find out if the current page is a Pod Page
1804 *
1805 * @param string $uri The Pod Page URI to check if currently on
1806 *
1807 * @return bool
1808 * @since 1.7.5
1809 */
1810 function is_pod_page( $uri = null ) {
1811
1812 if ( false !== Pods_Pages::$exists && ( null === $uri || $uri == Pods_Pages::$exists['uri'] || $uri == Pods_Pages::$exists['id'] ) ) {
1813 return true;
1814 }
1815
1816 return false;
1817 }
1818
1819 /**
1820 * Check for a specific page template for the current pod page
1821 *
1822 * @param string $template The theme template file
1823 *
1824 * @return bool
1825 * @since 2.3.7
1826 */
1827 function is_pod_page_template( $template = null ) {
1828
1829 if ( false !== Pods_Pages::$exists && $template == Pods_Pages::$exists['page_template'] ) {
1830 return true;
1831 }
1832
1833 return false;
1834 }
1835
1836 /**
1837 * Get the current Pod Page URI
1838 *
1839 * @return string|bool
1840 * @since 2.3.3
1841 */
1842 function get_pod_page_uri() {
1843
1844 $pod_page = Pods_Pages::exists();
1845
1846 if ( ! empty( $pod_page ) ) {
1847 return $pod_page['uri'];
1848 }
1849
1850 return false;
1851 }
1852
1853 /**
1854 * Check to see if Pod Page exists and return data
1855 *
1856 * $uri not required, if NULL then returns REQUEST_URI matching Pod Page
1857 *
1858 * @param string $uri The Pod Page URI to check if exists
1859 *
1860 * @return array
1861 *
1862 * @since 1.7.5
1863 */
1864 function pod_page_exists( $uri = null ) {
1865 return Pods_Pages::exists( $uri );
1866 }
1867
1868 /**
1869 * Output Pod Page Content
1870 *
1871 * @param bool $return Whether to return or not (default is to echo)
1872 *
1873 * @param bool $pods_page
1874 *
1875 * @return string
1876 * @since 1.7.0
1877 */
1878 function pods_content( $return = false, $pods_page = false ) {
1879
1880 return Pods_Pages::content( $return, $pods_page );
1881 }
1882
1883 /**
1884 * Sort an array by length of items, descending, for use with uksort()
1885 *
1886 * @param string $a First array item
1887 * @param string $b Second array item
1888 *
1889 * @return int Length difference
1890 *
1891 * @since 2.3.4
1892 */
1893 function pods_page_length_sort( $a, $b ) {
1894
1895 return strlen( $b ) - strlen( $a );
1896 }
1897
1898 /**
1899 * Flush Pod Page Rewrite cache
1900 *
1901 * @return array Pod Page Rewrites
1902 *
1903 * @since 2.3.4
1904 */
1905 function pods_page_flush_rewrites() {
1906
1907 return Pods_Pages::flush_rewrites();
1908 }
1909
1910 /*
1911 * Deprecated global variable
1912 */
1913 $GLOBALS['pod_page_exists'] =& Pods_Pages::$exists;
1914