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