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