Completed
Pull Request — 2.x (#4569)
by Scott Kingsley
08:49
created

Pods_Pages::precode()   D

Complexity

Conditions 26
Paths 156

Size

Total Lines 72
Code Lines 41

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 26
eloc 41
nc 156
nop 0
dl 0
loc 72
rs 4.9969
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 26 and the first side effect is on line 20.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
2
/**
3
 * Name: Pages
4
 *
5
 * Description: Creates advanced URL structures using wildcards in order to enable the front-end display of Pods
6
 * Advanced Content Types. Not recommended for use with other content types.
7
 *
8
 * Version: 2.3
9
 *
10
 * Category: Advanced
11
 *
12
 * Menu Page: edit.php?post_type=_pods_page
13
 * Menu Add Page: post-new.php?post_type=_pods_page
14
 *
15
 * @package    Pods\Components
16
 * @subpackage Pages
17
 */
18
19
if ( class_exists( 'Pods_Pages' ) ) {
20
	return;
21
}
22
23
/**
24
 * Class Pods_Pages
25
 */
26
class Pods_Pages extends PodsComponent {
27
28
	/**
29
	 * Current Pod Page
30
	 *
31
	 * @var array
32
	 *
33
	 * @since 2.0
34
	 */
35
	public static $exists = null;
36
37
	/**
38
	 * Object type
39
	 *
40
	 * @var string
41
	 *
42
	 * @since 2.0
43
	 */
44
	private $object_type = '_pods_page';
45
46
	/**
47
	 * Whether the page has been checked already
48
	 *
49
	 * @var bool
50
	 *
51
	 * @since 2.1
52
	 */
53
	public static $checked = false;
54
55
	/**
56
	 * Keep track of if pods_content has been called yet
57
	 *
58
	 * @var bool
59
	 *
60
	 * @since 2.3
61
	 */
62
	public static $content_called = false;
63
64
	/**
65
	 * The capability type.
66
	 *
67
	 * @link https://codex.wordpress.org/Function_Reference/register_post_type
68
	 * @var string
69
	 */
70
	private $capability_type = 'pods_page';
71
72
	/**
73
	 * Do things like register/enqueue scripts and stylesheets
74
	 *
75
	 * @since 2.0
76
	 */
77
	public function __construct() {
78
79
		add_shortcode( 'pods-content', array( $this, 'shortcode' ) );
80
81
		$args = array(
82
			'label'        => 'Pod Pages',
83
			'labels'       => array( 'singular_name' => 'Pod Page' ),
84
			'public'       => false,
85
			'can_export'   => false,
86
			'show_ui'      => true,
87
			'show_in_menu' => false,
88
			'query_var'    => false,
89
			'rewrite'      => false,
90
			'has_archive'  => false,
91
			'hierarchical' => false,
92
			'supports'     => array( 'title', 'author', 'revisions' ),
93
			'menu_icon'    => 'dashicons-pods',
94
		);
95
96
		if ( ! pods_is_admin() ) {
97
			$args['capability_type'] = $this->capability_type;
98
		}
99
100
		$args = PodsInit::object_label_fix( $args, 'post_type' );
101
102
		register_post_type( $this->object_type, apply_filters( 'pods_internal_register_post_type_object_page', $args ) );
103
104
		add_filter( 'post_type_link', array( $this, 'post_type_link' ), 10, 2 );
105
106
		if ( ! is_admin() ) {
107
			add_action( 'load_textdomain', array( $this, 'page_check' ), 12 );
108
		} else {
109
			add_filter( 'post_updated_messages', array( $this, 'setup_updated_messages' ), 10, 1 );
110
111
			add_action( 'dbx_post_advanced', array( $this, 'edit_page_form' ) );
112
113
			add_action( 'pods_meta_groups', array( $this, 'add_meta_boxes' ) );
114
			add_filter( 'get_post_metadata', array( $this, 'get_meta' ), 10, 4 );
115
			add_filter( 'update_post_metadata', array( $this, 'save_meta' ), 10, 4 );
116
117
			add_action( 'pods_meta_save_pre_post__pods_page', array( $this, 'fix_filters' ), 10, 5 );
118
			add_action( 'post_updated', array( $this, 'clear_cache' ), 10, 3 );
119
			add_action( 'delete_post', array( $this, 'clear_cache' ), 10, 1 );
120
			add_filter( 'post_row_actions', array( $this, 'remove_row_actions' ), 10, 2 );
121
			add_filter( 'bulk_actions-edit-' . $this->object_type, array( $this, 'remove_bulk_actions' ) );
122
123
			add_filter( 'builder_layout_filter_non_layout_post_types', array( $this, 'disable_builder_layout' ) );
124
		}
125
126
		add_filter( 'members_get_capabilities', array( $this, 'get_capabilities' ) );
127
	}
128
129
	/**
130
	 * @param $caps
131
	 *
132
	 * @return array
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use string[].

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
133
	 */
134
	public function get_capabilities( $caps ) {
135
136
		$caps = array_merge(
137
			$caps, array(
138
				'edit_' . $this->capability_type,
139
				'read_' . $this->capability_type,
140
				'delete_' . $this->capability_type,
141
				'edit_' . $this->capability_type . 's',
142
				'edit_others_' . $this->capability_type . 's',
143
				'publish_' . $this->capability_type . 's',
144
				'read_private_' . $this->capability_type . 's',
145
				'edit_' . $this->capability_type . 's',
146
			)
147
		);
148
149
		return $caps;
150
	}
151
152
	/**
153
	 * Pod Page Content Shortcode support for use anywhere that supports WP Shortcodes
154
	 *
155
	 * @param array  $tags    An associative array of shortcode properties
156
	 * @param string $content Not currently used
0 ignored issues
show
Documentation introduced by
Should the type for parameter $content not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
157
	 *
158
	 * @return string
159
	 * @since 2.3.9
160
	 */
161
	public function shortcode( $tags, $content = null ) {
162
163
		if ( ! isset( $tags['page'] ) || empty( $tags['page'] ) ) {
164
			$tags['page'] = null;
165
		}
166
167
		$pods_page = self::exists( $tags['page'] );
168
169
		if ( empty( $pods_page ) ) {
170
			return '<p>Pods Page not found</p>';
171
		}
172
173
		return self::content( true, $pods_page );
174
	}
175
176
	/**
177
	 * Disable this Post Type from appearing in the Builder layouts list
178
	 *
179
	 * @param array $post_types
180
	 *
181
	 * @return array
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use string[].

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
182
	 */
183
	public function disable_builder_layout( $post_types ) {
184
185
		$post_types[] = $this->object_type;
186
187
		return $post_types;
188
	}
189
190
	/**
191
	 * Update Post Type messages
192
	 *
193
	 * @param array $messages
194
	 *
195
	 * @return array
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use array<*,array>.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
196
	 * @since 2.0.2
197
	 */
198
	public function setup_updated_messages( $messages ) {
199
200
		global $post, $post_ID;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
201
202
		$post_type = get_post_type_object( $this->object_type );
0 ignored issues
show
introduced by
Overridding WordPress globals is prohibited
Loading history...
203
204
		$labels = $post_type->labels;
205
206
		$messages[ $post_type->name ] = array(
207
			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 ),
208
			2  => __( 'Custom field updated.', 'pods' ),
209
			3  => __( 'Custom field deleted.', 'pods' ),
210
			4  => sprintf( __( '%s updated.', 'pods' ), $labels->singular_name ),
211
			/* translators: %s: date and time of the revision */
212
			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,
213
			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 ),
214
			7  => sprintf( __( '%s saved.', 'pods' ), $labels->singular_name ),
215
			8  => sprintf( __( '%1$s submitted. <a target="_blank" 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 ),
216
			9  => sprintf(
217
				__( '%s scheduled for: <strong>%1$s</strong>. <a target="_blank" href="%2$s">Preview %s</a>', 'pods' ), $labels->singular_name,
218
				// translators: Publish box date format, see http://php.net/date
219
				date_i18n( __( 'M j, Y @ G:i' ), strtotime( $post->post_date ) ), esc_url( get_permalink( $post_ID ) ), $labels->singular_name
220
			),
221
			10 => sprintf( __( '%1$s draft updated. <a target="_blank" 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 ),
222
		);
223
224
		if ( false === (boolean) $post_type->public ) {
225
			$messages[ $post_type->name ][1] = sprintf( __( '%s updated.', 'pods' ), $labels->singular_name );
226
			$messages[ $post_type->name ][6] = sprintf( __( '%s published.', 'pods' ), $labels->singular_name );
227
			$messages[ $post_type->name ][8] = sprintf( __( '%s submitted.', 'pods' ), $labels->singular_name );
228
			$messages[ $post_type->name ][9] = sprintf(
229
				__( '%s scheduled for: <strong>%1$s</strong>.', 'pods' ), $labels->singular_name,
230
				// translators: Publish box date format, see http://php.net/date
231
				date_i18n( __( 'M j, Y @ G:i' ), strtotime( $post->post_date ) )
232
			);
233
			$messages[ $post_type->name ][10] = sprintf( __( '%s draft updated.', 'pods' ), $labels->singular_name );
234
		}
235
236
		return $messages;
237
	}
238
239
	/**
240
	 * Enqueue styles
241
	 *
242
	 * @since 2.0
243
	 */
244
	public function admin_assets() {
245
246
		wp_enqueue_style( 'pods-styles' );
247
	}
248
249
	/**
250
	 * Fix filters, specifically removing balanceTags
251
	 *
252
	 * @since 2.0.1
253
	 *
254
	 * @param      $data
255
	 * @param null $pod
256
	 * @param null $id
257
	 * @param null $groups
258
	 * @param null $post
259
	 */
260
	public function fix_filters( $data, $pod = null, $id = null, $groups = null, $post = null ) {
0 ignored issues
show
introduced by
Overridding WordPress globals is prohibited
Loading history...
261
262
		remove_filter( 'content_save_pre', 'balanceTags', 50 );
263
	}
264
265
	/**
266
	 * Remove unused row actions
267
	 *
268
	 * @since 2.0.5
269
	 *
270
	 * @param $actions
271
	 * @param $post
272
	 *
273
	 * @return
274
	 */
275
	public function remove_row_actions( $actions, $post ) {
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
276
277
		global $current_screen;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
278
279
		if ( ! is_object( $current_screen ) || $this->object_type != $current_screen->post_type ) {
280
			return $actions;
281
		}
282
283
		if ( isset( $actions['view'] ) ) {
284
			unset( $actions['view'] );
285
		}
286
287
		if ( isset( $actions['inline hide-if-no-js'] ) ) {
288
			unset( $actions['inline hide-if-no-js'] );
289
		}
290
291
		// W3 Total Cache
292
		if ( isset( $actions['pgcache_purge'] ) ) {
293
			unset( $actions['pgcache_purge'] );
294
		}
295
296
		return $actions;
297
	}
298
299
	/**
300
	 * Remove unused bulk actions
301
	 *
302
	 * @since 2.0.5
303
	 *
304
	 * @param $actions
305
	 *
306
	 * @return
307
	 */
308
	public function remove_bulk_actions( $actions ) {
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
309
310
		if ( isset( $actions['edit'] ) ) {
311
			unset( $actions['edit'] );
312
		}
313
314
		return $actions;
315
	}
316
317
	/**
318
	 * Clear cache on save
319
	 *
320
	 * @since 2.0
321
	 *
322
	 * @param      $data
323
	 * @param null $pod
324
	 * @param null $id
325
	 * @param null $groups
326
	 * @param null $post
327
	 */
328
	public function clear_cache( $data, $pod = null, $id = null, $groups = null, $post = null ) {
0 ignored issues
show
introduced by
Overridding WordPress globals is prohibited
Loading history...
329
330
		$old_post = $id;
331
332
		if ( ! is_object( $id ) ) {
333
			$old_post = null;
334
		}
335
336
		if ( is_object( $post ) && $this->object_type != $post->post_type ) {
337
			return;
338
		}
339
340
		if ( ! is_array( $data ) && 0 < $data ) {
341
			$post = $data;
0 ignored issues
show
introduced by
Overridding WordPress globals is prohibited
Loading history...
342
			$post = get_post( $post );
0 ignored issues
show
introduced by
Overridding WordPress globals is prohibited
Loading history...
343
		}
344
345
		if ( $this->object_type == $post->post_type ) {
346
			pods_transient_clear( 'pods_object_pages' );
347
348
			if ( is_object( $old_post ) && $this->object_type == $old_post->post_type ) {
349
				pods_cache_clear( $old_post->post_title, 'pods_object_page_wildcard' );
350
			}
351
352
			pods_cache_clear( $post->post_title, 'pods_object_page_wildcard' );
353
354
			self::flush_rewrites();
355
		}
356
	}
357
358
	/**
359
	 * Change post title placeholder text
360
	 *
361
	 * @since 2.0
362
	 *
363
	 * @param $text
364
	 * @param $post
365
	 *
366
	 * @return string|void
367
	 */
368
	public function set_title_text( $text, $post ) {
369
370
		return __( 'Enter URL here', 'pods' );
371
	}
372
373
	/**
374
	 * Edit page form
375
	 *
376
	 * @since 2.0
377
	 */
378
	public function edit_page_form() {
379
380
		global $post_type;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
381
382
		if ( $this->object_type != $post_type ) {
383
			return;
384
		}
385
386
		add_filter( 'enter_title_here', array( $this, 'set_title_text' ), 10, 2 );
387
	}
388
389
	/**
390
	 * Filter permalinks and adjust for pod pages
391
	 *
392
	 * @param $post_link
393
	 * @param $post
394
	 *
395
	 * @return mixed
396
	 */
397
	public function post_type_link( $post_link, $post ) {
398
399
		if ( empty( $post ) || $this->object_type != $post->post_type ) {
400
			return $post_link;
401
		}
402
403
		$post_link = get_site_url() . '/';
404
405
		if ( false === strpos( $post->post_title, '*' ) ) {
406
			$post_link .= trim( $post->post_title, '/ ' ) . '/';
407
		}
408
409
		return $post_link;
410
	}
411
412
	/**
413
	 * Add meta boxes to the page
414
	 *
415
	 * @since 2.0
416
	 */
417
	public function add_meta_boxes() {
418
419
		$pod = array(
420
			'name' => $this->object_type,
421
			'type' => 'post_type',
422
		);
423
424
		if ( isset( PodsMeta::$post_types[ $pod['name'] ] ) ) {
425
			return;
426
		}
427
428
		if ( ! function_exists( 'get_page_templates' ) ) {
429
			include_once ABSPATH . 'wp-admin/includes/theme.php';
430
		}
431
432
		$page_templates = apply_filters( 'pods_page_templates', get_page_templates() );
433
434
		$page_templates[ __( '-- Page Template --', 'pods' ) ] = '';
435
436
		$page_templates[ __( 'Custom (uses only Pod Page content)', 'pods' ) ] = '_custom';
437
438
		if ( ! in_array( 'pods.php', $page_templates ) && locate_template( array( 'pods.php', false ) ) ) {
439
			$page_templates[ __( 'Pods (Pods Default)', 'pods' ) ] = 'pods.php';
440
		}
441
442
		if ( ! in_array( 'page.php', $page_templates ) && locate_template( array( 'page.php', false ) ) ) {
443
			$page_templates[ __( 'Page (WP Default)', 'pods' ) ] = 'page.php';
444
		}
445
446
		if ( ! in_array( 'index.php', $page_templates ) && locate_template( array( 'index.php', false ) ) ) {
447
			$page_templates[ __( 'Index (WP Fallback)', 'pods' ) ] = 'index.php';
448
		}
449
450
		ksort( $page_templates );
451
452
		$page_templates = array_flip( $page_templates );
453
454
		$fields = array(
455
			array(
456
				'name'  => 'page_title',
457
				'label' => __( 'Page Title', 'pods' ),
458
				'type'  => 'text',
459
			),
460
			array(
461
				'name'          => 'code',
462
				'label'         => __( 'Page Code', 'pods' ),
463
				'type'          => 'code',
464
				'attributes'    => array(
465
					'id' => 'content',
466
				),
467
				'label_options' => array(
468
					'attributes' => array(
469
						'for' => 'content',
470
					),
471
				),
472
			),
473
			array(
474
				'name'  => 'precode',
475
				'label' => __( 'Page Precode', 'pods' ),
476
				'type'  => 'code',
477
				'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' ),
478
			),
479
			array(
480
				'name'  => 'page_template',
481
				'label' => __( 'Page Template', 'pods' ),
482
				'type'  => 'pick',
483
				'data'  => $page_templates,
484
			),
485
		);
486
487
		pods_group_add( $pod, __( 'Page', 'pods' ), $fields, 'normal', 'high' );
488
489
		$associated_pods = array(
490
			0 => __( '-- Select a Pod --', 'pods' ),
491
		);
492
493
		$all_pods = pods_api()->load_pods( array( 'names' => true ) );
494
495
		if ( ! empty( $all_pods ) ) {
496
			foreach ( $all_pods as $pod_name => $pod_label ) {
0 ignored issues
show
Bug introduced by
The expression $all_pods of type array|object|integer|double|string|boolean is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
497
				$associated_pods[ $pod_name ] = $pod_label . ' (' . $pod_name . ')';
498
			}
499
		} else {
500
			$associated_pods[0] = __( 'None Found', 'pods' );
501
		}
502
503
		$fields = array(
504
			array(
505
				'name'       => 'pod',
506
				'label'      => __( 'Associated Pod', 'pods' ),
507
				'default'    => 0,
508
				'type'       => 'pick',
509
				'data'       => $associated_pods,
510
				'dependency' => true,
511
			),
512
			array(
513
				'name'        => 'pod_slug',
514
				'label'       => __( 'Wildcard Slug', 'pods' ),
515
				'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' ),
516
				'type'        => 'text',
517
				'excludes-on' => array( 'pod' => 0 ),
518
			),
519
		);
520
521
		pods_group_add( $pod, __( 'Pod Association', 'pods' ), $fields, 'normal', 'high' );
522
523
		$fields = array(
524
			array(
525
				'name'       => 'admin_only',
526
				'label'      => __( 'Restrict access to Admins?', 'pods' ),
527
				'default'    => 0,
528
				'type'       => 'boolean',
529
				'dependency' => true,
530
			),
531
			array(
532
				'name'       => 'restrict_role',
533
				'label'      => __( 'Restrict access by Role?', 'pods' ),
534
				'help'       => array(
535
					__( '<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' ),
536
					'http://codex.wordpress.org/Roles_and_Capabilities',
537
				),
538
				'default'    => 0,
539
				'type'       => 'boolean',
540
				'dependency' => true,
541
			),
542
			array(
543
				'name'              => 'roles_allowed',
544
				'label'             => __( 'Role(s) Allowed', 'pods' ),
545
				'type'              => 'pick',
546
				'pick_object'       => 'role',
547
				'pick_format_type'  => 'multi',
548
				'pick_format_multi' => 'autocomplete',
549
				'pick_ajax'         => false,
550
				'default'           => '',
551
				'depends-on'        => array(
552
					'restrict_role' => true,
553
				),
554
			),
555
			array(
556
				'name'       => 'restrict_capability',
557
				'label'      => __( 'Restrict access by Capability?', 'pods' ),
558
				'help'       => array(
559
					__( '<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' ),
560
					'http://codex.wordpress.org/Roles_and_Capabilities',
561
				),
562
				'default'    => 0,
563
				'type'       => 'boolean',
564
				'dependency' => true,
565
			),
566
			array(
567
				'name'              => 'capability_allowed',
568
				'label'             => __( 'Capability Allowed', 'pods' ),
569
				'type'              => 'pick',
570
				'pick_object'       => 'capability',
571
				'pick_format_type'  => 'multi',
572
				'pick_format_multi' => 'autocomplete',
573
				'pick_ajax'         => false,
574
				'default'           => '',
575
				'depends-on'        => array(
576
					'restrict_capability' => true,
577
				),
578
			),
579
			array(
580
				'name'       => 'restrict_redirect',
581
				'label'      => __( 'Redirect if Restricted?', 'pods' ),
582
				'default'    => 0,
583
				'type'       => 'boolean',
584
				'dependency' => true,
585
			),
586
			array(
587
				'name'       => 'restrict_redirect_login',
588
				'label'      => __( 'Redirect to WP Login page', 'pods' ),
589
				'default'    => 0,
590
				'type'       => 'boolean',
591
				'dependency' => true,
592
				'depends-on' => array(
593
					'restrict_redirect' => true,
594
				),
595
			),
596
			array(
597
				'name'       => 'restrict_redirect_url',
598
				'label'      => __( 'Redirect to a Custom URL', 'pods' ),
599
				'default'    => '',
600
				'type'       => 'text',
601
				'depends-on' => array(
602
					'restrict_redirect'       => true,
603
					'restrict_redirect_login' => false,
604
				),
605
			),
606
		);
607
608
		pods_group_add( $pod, __( 'Restrict Access', 'pods' ), $fields, 'normal', 'high' );
609
	}
610
611
	/**
612
	 * Get the fields
613
	 *
614
	 * @param null   $_null
615
	 * @param int    $post_ID
0 ignored issues
show
Documentation introduced by
Should the type for parameter $post_ID not be integer|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
616
	 * @param string $meta_key
0 ignored issues
show
Documentation introduced by
Should the type for parameter $meta_key not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
617
	 * @param bool   $single
618
	 *
619
	 * @return array|bool|int|mixed|null|string|void
620
	 */
621
	public function get_meta( $_null, $post_ID = null, $meta_key = null, $single = false ) {
0 ignored issues
show
introduced by
Overridding WordPress globals is prohibited
Loading history...
622
623
		if ( 'code' === $meta_key ) {
624
			$post = get_post( $post_ID );
0 ignored issues
show
introduced by
Overridding WordPress globals is prohibited
Loading history...
625
626
			if ( is_object( $post ) && $this->object_type == $post->post_type ) {
627
				return $post->post_content;
628
			}
629
		}
630
631
		return $_null;
632
	}
633
634
	/**
635
	 * Save the fields
636
	 *
637
	 * @param        $_null
638
	 * @param int    $post_ID
0 ignored issues
show
Documentation introduced by
Should the type for parameter $post_ID not be integer|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
639
	 * @param string $meta_key
0 ignored issues
show
Documentation introduced by
Should the type for parameter $meta_key not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
640
	 * @param null   $meta_value
641
	 *
642
	 * @return bool|int|null
643
	 */
644
	public function save_meta( $_null, $post_ID = null, $meta_key = null, $meta_value = null ) {
0 ignored issues
show
introduced by
Overridding WordPress globals is prohibited
Loading history...
645
646
		if ( 'code' === $meta_key ) {
647
			$post = get_post( $post_ID );
0 ignored issues
show
introduced by
Overridding WordPress globals is prohibited
Loading history...
648
649
			if ( is_object( $post ) && $this->object_type == $post->post_type ) {
650
				$postdata = array(
651
					'ID'           => $post_ID,
652
					'post_content' => $meta_value,
653
				);
654
655
				remove_filter( current_filter(), array( $this, __FUNCTION__ ) );
656
657
				$revisions = false;
658
659
				if ( has_action( 'pre_post_update', 'wp_save_post_revision' ) ) {
660
					remove_action( 'pre_post_update', 'wp_save_post_revision' );
661
662
					$revisions = true;
663
				}
664
665
				wp_update_post( (object) $postdata );
666
				// objects will be automatically sanitized
667
				if ( $revisions ) {
668
					add_action( 'pre_post_update', 'wp_save_post_revision' );
669
				}
670
671
				return true;
672
			}//end if
673
		}//end if
674
675
		return $_null;
676
	}
677
678
	/**
679
	 * Flush Pod Page Rewrite cache
680
	 *
681
	 * @return array Pod Page Rewrites
682
	 *
683
	 * @since 2.3.4
684
	 */
685
	public static function flush_rewrites() {
686
687
		$args = array(
688
			'post_type'      => '_pods_page',
689
			'nopaging'       => true,
0 ignored issues
show
introduced by
Disabling pagination is prohibited in VIP context, do not set nopaging to true ever.
Loading history...
690
			'posts_per_page' => - 1,
691
			'post_status'    => 'publish',
692
			'order'          => 'ASC',
693
			'orderby'        => 'title',
694
		);
695
696
		$pod_pages = get_posts( $args );
697
698
		$pod_page_rewrites = array();
699
700
		foreach ( $pod_pages as $pod_page ) {
701
			$pod_page_rewrites[ $pod_page->ID ] = $pod_page->post_title;
702
		}
703
704
		uksort( $pod_page_rewrites, 'pods_page_length_sort' );
705
706
		pods_transient_set( 'pods_object_page_rewrites', $pod_page_rewrites );
707
708
		$pod_page_rewrites = array_flip( $pod_page_rewrites );
709
710
		return $pod_page_rewrites;
711
	}
712
713
	/**
714
	 * Check to see if Pod Page exists and return data
715
	 *
716
	 * $uri not required, if NULL then returns REQUEST_URI matching Pod Page
717
	 *
718
	 * @param string $uri The Pod Page URI to check if exists
0 ignored issues
show
Documentation introduced by
Should the type for parameter $uri not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
719
	 *
720
	 * @return array|bool
721
	 */
722
	public static function exists( $uri = null ) {
723
724
		if ( null === $uri ) {
725
			$uri = parse_url( pods_current_url() );
726
			$uri = $uri['path'];
727
		} else {
728
			$uri = explode( '?', $uri );
729
			$uri = explode( '#', $uri[0] );
730
			$uri = $uri[0];
731
		}
732
733
		$home = parse_url( get_home_url() );
734
735
		if ( ! empty( $home ) && isset( $home['path'] ) && '/' !== $home['path'] ) {
736
			$uri = substr( $uri, strlen( $home['path'] ) );
737
		}
738
739
		$uri       = trim( $uri, '/' );
740
		$uri_depth = count( array_filter( explode( '/', $uri ) ) ) - 1;
741
742
		$pods_page_exclusions = array(
743
			'wp-admin',
744
			'wp-content',
745
			'wp-includes',
746
			'index.php',
747
			'wp-login.php',
748
			'wp-signup.php',
749
		);
750
751
		$pods_page_exclusions = apply_filters( 'pods_page_exclusions', $pods_page_exclusions );
752
753
		if ( is_admin() || empty( $uri ) ) {
754
			return false;
755
		}
756
757
		foreach ( $pods_page_exclusions as $exclusion ) {
758
			if ( 0 === strpos( $uri, $exclusion ) ) {
759
				return false;
760
			}
761
		}
762
763
		$object = apply_filters( 'pods_page_exists', false, $uri );
764
		if ( ! empty( $object ) ) {
765
			return $object;
766
		}
767
768
		if ( false === strpos( $uri, '*' ) && ! apply_filters( 'pods_page_regex_matching', false ) ) {
769
			$object = pods_by_title( $uri, ARRAY_A, '_pods_page', 'publish' );
770
		}
771
772
		$wildcard = false;
773
774
		if ( empty( $object ) ) {
775
			if ( false === strpos( $uri, '*' ) ) {
776
				$object = pods_cache_get( $uri, 'pods_object_page_wildcard' );
777
778
				if ( ! empty( $object ) ) {
779
					return $object;
780
				}
781
			}
782
783
			$pod_page_rewrites = pods_transient_get( 'pods_object_page_rewrites' );
784
785
			if ( empty( $pod_page_rewrites ) ) {
786
				$pod_page_rewrites = self::flush_rewrites();
787
			} else {
788
				$pod_page_rewrites = array_flip( $pod_page_rewrites );
789
			}
790
791
			$found_rewrite_page_id = 0;
0 ignored issues
show
Comprehensibility Naming introduced by
The variable name $found_rewrite_page_id exceeds the maximum configured length of 20.

Very long variable names usually make code harder to read. It is therefore recommended not to make variable names too verbose.

Loading history...
792
793
			if ( ! empty( $pod_page_rewrites ) ) {
794
				foreach ( $pod_page_rewrites as $pod_page => $pod_page_id ) {
795
					if ( ! apply_filters( 'pods_page_regex_matching', false ) ) {
796
						if ( false === strpos( $pod_page, '*' ) ) {
797
							continue;
798
						}
799
800
						$depth_check = strlen( $pod_page ) - strlen( str_replace( '/', '', $pod_page ) );
801
802
						$pod_page = preg_quote( $pod_page, '/' );
803
804
						$pod_page = str_replace( '\\*', '(.*)', $pod_page );
805
806
						if ( $uri_depth == $depth_check && preg_match( '/^' . $pod_page . '$/', $uri ) ) {
807
							$found_rewrite_page_id = $pod_page_id;
808
809
							break;
810
						}
811
					} elseif ( preg_match( '/^' . str_replace( '/', '\\/', $pod_page ) . '$/', $uri ) ) {
812
						$found_rewrite_page_id = $pod_page_id;
813
814
						break;
815
					}//end if
816
				}//end foreach
817
818
				if ( ! empty( $found_rewrite_page_id ) ) {
819
					$object = get_post( $found_rewrite_page_id, ARRAY_A );
820
821
					if ( empty( $object ) || '_pods_page' !== $object['post_type'] ) {
822
						$object = false;
823
					}
824
				}
825
			}//end if
826
827
			$wildcard = true;
828
		}//end if
829
830
		if ( ! empty( $object ) ) {
831
			$object = array(
832
				'id'                          => $object['ID'],
833
				'uri'                         => $object['post_title'],
834
				'code'                        => $object['post_content'],
835
				'phpcode'                     => $object['post_content'],
836
				// phpcode is deprecated
837
									'precode' => get_post_meta( $object['ID'], 'precode', true ),
838
				'page_template'               => get_post_meta( $object['ID'], 'page_template', true ),
839
				'title'                       => get_post_meta( $object['ID'], 'page_title', true ),
840
				'options'                     => array(
841
					'admin_only'              => (boolean) get_post_meta( $object['ID'], 'admin_only', true ),
842
					'restrict_role'           => (boolean) get_post_meta( $object['ID'], 'restrict_role', true ),
843
					'restrict_capability'     => (boolean) get_post_meta( $object['ID'], 'restrict_capability', true ),
844
					'roles_allowed'           => get_post_meta( $object['ID'], 'roles_allowed', true ),
845
					'capability_allowed'      => get_post_meta( $object['ID'], 'capability_allowed', true ),
846
					'restrict_redirect'       => (boolean) get_post_meta( $object['ID'], 'restrict_redirect', true ),
847
					'restrict_redirect_login' => (boolean) get_post_meta( $object['ID'], 'restrict_redirect_login', true ),
848
					'restrict_redirect_url'   => get_post_meta( $object['ID'], 'restrict_redirect_url', true ),
849
					'pod'                     => get_post_meta( $object['ID'], 'pod', true ),
850
					'pod_slug'                => get_post_meta( $object['ID'], 'pod_slug', true ),
851
				),
852
			);
853
854
			if ( $wildcard ) {
855
				pods_cache_set( $uri, $object, 'pods_object_page_wildcard', 3600 );
856
			}
857
858
			return $object;
859
		}//end if
860
861
		return false;
862
	}
863
864
	/**
865
	 * Check if a Pod Page exists
866
	 */
867
	public function page_check() {
868
869
		if ( self::$checked ) {
870
			return;
871
		}
872
873
		global $pods;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
874
875
		// Fix any global confusion wherever this runs
876
		if ( isset( $pods ) && ! isset( $GLOBALS['pods'] ) ) {
877
			$GLOBALS['pods'] =& $pods;
878
		} elseif ( ! isset( $pods ) && isset( $GLOBALS['pods'] ) ) {
879
			$pods =& $GLOBALS['pods'];
880
		}
881
882
		if ( ! defined( 'PODS_DISABLE_POD_PAGE_CHECK' ) || ! PODS_DISABLE_POD_PAGE_CHECK ) {
883
			if ( null === self::$exists ) {
884
				self::$exists = pod_page_exists();
885
			}
886
887
			if ( false !== self::$exists ) {
888
				$pods = apply_filters( 'pods_global', $pods, self::$exists );
889
890
				if ( ! is_wp_error( $pods ) && ( is_object( $pods ) || 404 != $pods ) ) {
891
					add_action( 'template_redirect', array( $this, 'template_redirect' ) );
892
					add_filter( 'redirect_canonical', '__return_false' );
893
					add_action( 'wp_head', array( $this, 'wp_head' ) );
894
					add_filter( 'wp_title', array( $this, 'wp_title' ), 0, 3 );
895
					add_filter( 'body_class', array( $this, 'body_class' ), 0, 1 );
896
					add_filter( 'status_header', array( $this, 'status_header' ) );
897
					add_action( 'after_setup_theme', array( $this, 'precode' ) );
898
					add_action( 'wp', array( $this, 'silence_404' ), 1 );
899
900
					// Genesis theme integration
901
					add_action( 'genesis_loop', 'pods_content', 11 );
902
				}
903
			}
904
905
			self::$checked = true;
906
		}//end if
907
	}
908
909
	/**
910
	 * Output Pod Page Content
911
	 *
912
	 * @param bool $return Whether to return or not (default is to echo)
913
	 *
914
	 * @param bool $pods_page
915
	 *
916
	 * @return string
917
	 */
918
	public static function content( $return = false, $pods_page = false ) {
919
920
		if ( empty( $pods_page ) ) {
921
			$pods_page = self::$exists;
922
		}
923
924
		$content = false;
925
926
		if ( $pods_page == self::$exists && self::$content_called ) {
927
			return $content;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $content; (false) is incompatible with the return type documented by Pods_Pages::content of type string.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
928
		}
929
930
		if ( ! empty( $pods_page ) ) {
931
			/**
932
			 * @var $pods \Pods
933
			 */
934
			global $pods;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
935
936
			// Fix any global confusion wherever this runs
937
			if ( isset( $pods ) && ! isset( $GLOBALS['pods'] ) ) {
938
				$GLOBALS['pods'] =& $pods;
939
			} elseif ( ! isset( $pods ) && isset( $GLOBALS['pods'] ) ) {
940
				$pods =& $GLOBALS['pods'];
941
			}
942
943
			if ( 0 < strlen( trim( $pods_page['code'] ) ) ) {
944
				$content = trim( $pods_page['code'] );
945
			}
946
947
			ob_start();
948
949
			do_action( 'pods_content_pre', $pods_page, $content );
950
951
			if ( 0 < strlen( $content ) ) {
952
				if ( false !== strpos( $content, '<?' ) && ( ! defined( 'PODS_DISABLE_EVAL' ) || ! PODS_DISABLE_EVAL ) ) {
953
					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' );
954
955
					eval( "?>$content" );
0 ignored issues
show
Coding Style introduced by
It is generally not recommended to use eval unless absolutely required.

On one hand, eval might be exploited by malicious users if they somehow manage to inject dynamic content. On the other hand, with the emergence of faster PHP runtimes like the HHVM, eval prevents some optimization that they perform.

Loading history...
introduced by
eval is prohibited, please use Anonymous functions instead.
Loading history...
956
				} elseif ( is_object( $pods ) && ! empty( $pods->id ) ) {
957
					echo $pods->do_magic_tags( $content );
958
				} else {
959
					echo $content;
960
				}
961
			}
962
963
			do_action( 'pods_content_post', $pods_page, $content );
964
965
			$content = ob_get_clean();
966
967
			if ( $pods_page == self::$exists ) {
968
				self::$content_called = true;
969
			}
970
		}//end if
971
972
		$content = apply_filters( 'pods_content', $content, $pods_page );
973
974
		if ( $return ) {
975
			return $content;
976
		}
977
978
		echo $content;
979
	}
980
981
	/**
982
	 * Run any precode for current Pod Page
983
	 */
984
	public function precode() {
985
986
		global $pods;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
987
988
		// Fix any global confusion wherever this runs
989
		if ( isset( $pods ) && ! isset( $GLOBALS['pods'] ) ) {
990
			$GLOBALS['pods'] =& $pods;
991
		} elseif ( ! isset( $pods ) && isset( $GLOBALS['pods'] ) ) {
992
			$pods =& $GLOBALS['pods'];
993
		}
994
995
		if ( false !== self::$exists ) {
996
			$permission = pods_permission( self::$exists['options'] );
997
998
			$permission = (boolean) apply_filters( 'pods_pages_permission', $permission, self::$exists );
999
1000
			if ( $permission ) {
1001
				$content = false;
1002
1003
				if ( ! is_object( $pods ) && 404 != $pods && 0 < strlen( pods_var( 'pod', self::$exists['options'] ) ) ) {
1004
					$slug = pods_var_raw( 'pod_slug', self::$exists['options'], null, null, true );
1005
1006
					// Handle special magic tags
1007
					if ( 0 < strlen( $slug ) ) {
1008
						$slug = pods_evaluate_tags( $slug, true );
1009
					}
1010
1011
					$pods = pods( pods_var( 'pod', self::$exists['options'] ), $slug );
1012
1013
					// Auto 404 handling if item doesn't exist
1014
					if ( 0 < strlen( $slug ) && ! $pods->exists() && apply_filters( 'pods_pages_auto_404', true, $slug, $pods, self::$exists ) ) {
1015
						$pods = 404;
1016
					}
1017
				}
1018
1019
				if ( 0 < strlen( trim( self::$exists['precode'] ) ) ) {
1020
					$content = self::$exists['precode'];
1021
				}
1022
1023
				if ( false !== $content && ( ! defined( 'PODS_DISABLE_EVAL' ) || ! PODS_DISABLE_EVAL ) ) {
1024
					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' );
1025
1026
					eval( "?>$content" );
0 ignored issues
show
Coding Style introduced by
It is generally not recommended to use eval unless absolutely required.

On one hand, eval might be exploited by malicious users if they somehow manage to inject dynamic content. On the other hand, with the emergence of faster PHP runtimes like the HHVM, eval prevents some optimization that they perform.

Loading history...
introduced by
eval is prohibited, please use Anonymous functions instead.
Loading history...
1027
				}
1028
1029
				do_action( 'pods_page_precode', self::$exists, $pods, $content );
1030
			} elseif ( self::$exists['options']['restrict_redirect'] ) {
1031
				$redirect_url = '';
1032
1033
				if ( self::$exists['options']['restrict_redirect_login'] ) {
1034
					$redirect_url = wp_login_url( pods_current_url() );
1035
				} elseif ( ! empty( self::$exists['options']['restrict_redirect_url'] ) ) {
1036
					$redirect_url = self::$exists['options']['restrict_redirect_url'];
1037
				}
1038
1039
				if ( ! empty( $redirect_url ) ) {
1040
					wp_redirect( $redirect_url );
1041
					die();
1042
				}
1043
			}//end if
1044
1045
			if ( ! $permission || ( ! is_object( $pods ) && ( 404 == $pods || is_wp_error( $pods ) ) ) ) {
1046
				remove_action( 'template_redirect', array( $this, 'template_redirect' ) );
1047
				remove_action( 'wp_head', array( $this, 'wp_head' ) );
1048
				remove_filter( 'redirect_canonical', '__return_false' );
1049
				remove_filter( 'wp_title', array( $this, 'wp_title' ) );
1050
				remove_filter( 'body_class', array( $this, 'body_class' ) );
1051
				remove_filter( 'status_header', array( $this, 'status_header' ) );
1052
				remove_action( 'wp', array( $this, 'silence_404' ), 1 );
1053
			}
1054
		}//end if
1055
	}
1056
1057
	/**
1058
	 *
1059
	 */
1060
	public function wp_head() {
1061
1062
		global $pods;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
1063
1064
		do_action( 'pods_wp_head' );
1065
1066
		if ( ! defined( 'PODS_DISABLE_VERSION_OUTPUT' ) || ! PODS_DISABLE_VERSION_OUTPUT ) {
1067
			?>
1068
			<!-- Pods Framework <?php echo esc_html( PODS_VERSION ); ?> -->
1069
			<?php
1070
		}
1071
		if ( ( ! defined( 'PODS_DISABLE_META' ) || ! PODS_DISABLE_META ) && is_object( $pods ) && ! is_wp_error( $pods ) ) {
1072
1073
			if ( isset( $pods->meta ) && is_array( $pods->meta ) && ! empty( $pods->meta ) ) {
1074
				foreach ( $pods->meta as $name => $content ) {
1075
					if ( 'title' === $name ) {
1076
						continue;
1077
					}
1078
					?>
1079
					<meta name="<?php echo esc_attr( $name ); ?>" content="<?php echo esc_attr( $content ); ?>" />
1080
					<?php
1081
				}
1082
			}
1083
1084
			if ( isset( $pods->meta_properties ) && is_array( $pods->meta_properties ) && ! empty( $pods->meta_properties ) ) {
1085
				foreach ( $pods->meta_properties as $property => $content ) {
1086
					?>
1087
					<meta property="<?php echo esc_attr( $property ); ?>" content="<?php echo esc_attr( $content ); ?>" />
1088
					<?php
1089
				}
1090
			}
1091
1092
			if ( isset( $pods->meta_extra ) && 0 < strlen( $pods->meta_extra ) ) {
1093
				echo $pods->meta_extra;
1094
			}
1095
		}//end if
1096
	}
1097
1098
	/**
1099
	 * @param $title
1100
	 * @param $sep
1101
	 * @param $seplocation
1102
	 *
1103
	 * @return mixed|void
1104
	 */
1105
	public function wp_title( $title, $sep, $seplocation ) {
1106
1107
		global $pods;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
1108
1109
		$page_title = trim( self::$exists['title'] );
1110
1111
		if ( 0 < strlen( $page_title ) ) {
1112
			if ( is_object( $pods ) && ! is_wp_error( $pods ) ) {
1113
				$page_title = $pods->do_magic_tags( $page_title );
1114
			}
1115
1116
			$title = ( 'right' === $seplocation ) ? "{$page_title} {$sep} " : " {$sep} {$page_title}";
1117
		} elseif ( strlen( trim( $title ) ) < 1 ) {
1118
			$uri = explode( '?', $_SERVER['REQUEST_URI'] );
1119
			$uri = preg_replace( '@^([/]?)(.*?)([/]?)$@', '$2', $uri[0] );
1120
			$uri = preg_replace( '@(-|_)@', ' ', $uri );
1121
			$uri = explode( '/', $uri );
1122
1123
			$title = '';
1124
1125
			foreach ( $uri as $key => $page_title ) {
1126
				$title .= ( 'right' === $seplocation ) ? ucwords( $page_title ) . " {$sep} " : " {$sep} " . ucwords( $page_title );
1127
			}
1128
		}
1129
1130
		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'] ) ) {
1131
			$title = $pods->meta['title'];
1132
		}
1133
1134
		return apply_filters( 'pods_title', $title, $sep, $seplocation, self::$exists );
1135
	}
1136
1137
	/**
1138
	 * @param $classes
1139
	 *
1140
	 * @return mixed|void
1141
	 */
1142
	public function body_class( $classes ) {
1143
1144
		global $pods;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
1145
1146
		if ( defined( 'PODS_DISABLE_BODY_CLASSES' ) && PODS_DISABLE_BODY_CLASSES ) {
1147
			return $classes;
1148
		}
1149
1150
		$classes[] = 'pods';
1151
1152
		$uri = explode( '?', self::$exists['uri'] );
1153
		$uri = explode( '#', $uri[0] );
1154
1155
		$class = str_replace( array( '*', '/' ), array( '_w_', '-' ), $uri[0] );
1156
		$class = sanitize_title( $class );
1157
		$class = str_replace( array( '_', '--', '--' ), '-', $class );
1158
		$class = trim( $class, '-' );
1159
1160
		$classes[] = 'pod-page-' . $class;
1161
1162
		if ( is_object( $pods ) && ! is_wp_error( $pods ) ) {
1163
			$class     = sanitize_title( $pods->pod );
1164
			$class     = str_replace( array( '_', '--', '--' ), '-', $class );
1165
			$class     = trim( $class, '-' );
1166
			$classes[] = 'pod-' . $class;
1167
		}
1168
1169
		if ( is_object( $pods ) && ! is_wp_error( $pods ) && isset( $pods->body_classes ) ) {
1170
			$classes[] = $pods->body_classes;
1171
		}
1172
1173
		return apply_filters( 'pods_body_class', $classes, $uri );
1174
	}
1175
1176
	/**
1177
	 * @return string
1178
	 */
1179
	public function status_header() {
1180
1181
		return $_SERVER['SERVER_PROTOCOL'] . ' 200 OK';
1182
	}
1183
1184
	/**
1185
	 *
1186
	 */
1187
	public function silence_404() {
1188
1189
		global $wp_query;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
1190
1191
		$wp_query->query_vars['error'] = '';
1192
		$wp_query->is_404              = false;
1193
	}
1194
1195
	/**
1196
	 *
1197
	 */
1198
	public function template_redirect() {
1199
1200
		global $pods;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
1201
1202
		if ( false !== self::$exists ) {
1203
			/*
1204
			 * Create pods.php in your theme directory, and
1205
			 * style it to suit your needs. Some helpful functions:
1206
			 *
1207
			 * get_header()
1208
			 * pods_content()
1209
			 * get_sidebar()
1210
			 * get_footer()
1211
			 */
1212
			$template = self::$exists['page_template'];
1213
			$template = apply_filters( 'pods_page_template', $template, self::$exists );
1214
1215
			$render_function = apply_filters( 'pods_template_redirect', null, $template, self::$exists );
1216
1217
			do_action( 'pods_page', $template, self::$exists );
1218
1219
			if ( '_custom' === $template ) {
1220
				pods_content();
1221
			} elseif ( null !== $render_function && is_callable( $render_function ) ) {
1222
				call_user_func( $render_function, $template, self::$exists );
1223
			} 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 ) ) {
1224
				$template = $pods->page_template;
1225
				// found the template and included it, we're good to go!
1226
			} elseif ( ! empty( self::$exists['page_template'] ) && '' != locate_template( array( self::$exists['page_template'] ), true ) ) {
1227
				$template = self::$exists['page_template'];
1228
				// found the template and included it, we're good to go!
1229
			} else {
1230
				$default_templates = array();
1231
1232
				$uri = explode( '?', self::$exists['uri'] );
1233
				$uri = explode( '#', $uri[0] );
1234
1235
				$page_path = explode( '/', $uri[0] );
1236
1237
				while ( $last = array_pop( $page_path ) ) {
1238
					$file_name = str_replace( '*', '-w-', implode( '/', $page_path ) . '/' . $last );
1239
					$sanitized = sanitize_title( $file_name );
1240
1241
					$default_templates[] = 'pods/' . trim( str_replace( '--', '-', $sanitized ), ' -' ) . '.php';
1242
					$default_templates[] = 'pods-' . trim( str_replace( '--', '-', $sanitized ), ' -' ) . '.php';
1243
				}
1244
1245
				$default_templates[] = 'pods.php';
1246
1247
				$default_templates = apply_filters( 'pods_page_default_templates', $default_templates );
1248
1249
				$template = locate_template( $default_templates, true );
1250
1251
				if ( '' !== $template ) {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
1252
					// found the template and included it, we're good to go!
1253
				} else {
1254
					$template = false;
1255
1256
					// templates not found in theme, default output
1257
					do_action( 'pods_page_default', $template, self::$exists );
1258
1259
					get_header();
1260
					pods_content();
1261
					get_sidebar();
1262
					get_footer();
1263
				}
1264
			}//end if
1265
1266
			do_action( 'pods_page_end', $template, self::$exists );
1267
1268
			exit;
1269
		}//end if
1270
	}
1271
}
1272
1273
/**
1274
 * Find out if the current page is a Pod Page
1275
 *
1276
 * @param string $uri The Pod Page URI to check if currently on
0 ignored issues
show
Documentation introduced by
Should the type for parameter $uri not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
1277
 *
1278
 * @return bool
1279
 * @since 1.7.5
1280
 */
1281
function is_pod_page( $uri = null ) {
1282
1283
	if ( false !== Pods_Pages::$exists && ( null === $uri || $uri == Pods_Pages::$exists['uri'] || $uri == Pods_Pages::$exists['id'] ) ) {
0 ignored issues
show
Unused Code introduced by
This if statement, and the following return statement can be replaced with return false !== \Pods_P..._Pages::$exists['id']);.
Loading history...
1284
		return true;
1285
	}
1286
1287
	return false;
1288
}
1289
1290
/**
1291
 * Check for a specific page template for the current pod page
1292
 *
1293
 * @param string $template The theme template file
0 ignored issues
show
Documentation introduced by
Should the type for parameter $template not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
1294
 *
1295
 * @return bool
1296
 * @since 2.3.7
1297
 */
1298
function is_pod_page_template( $template = null ) {
1299
1300
	if ( false !== Pods_Pages::$exists && $template == Pods_Pages::$exists['page_template'] ) {
0 ignored issues
show
Unused Code introduced by
This if statement, and the following return statement can be replaced with return false !== \Pods_P...xists['page_template'];.
Loading history...
1301
		return true;
1302
	}
1303
1304
	return false;
1305
}
1306
1307
/**
1308
 * Get the current Pod Page URI
1309
 *
1310
 * @return string|bool
1311
 * @since 2.3.3
1312
 */
1313
function get_pod_page_uri() {
1314
1315
	$pod_page = Pods_Pages::exists();
1316
1317
	if ( ! empty( $pod_page ) ) {
1318
		return $pod_page['uri'];
1319
	}
1320
1321
	return false;
1322
}
1323
1324
/**
1325
 * Check to see if Pod Page exists and return data
1326
 *
1327
 * $uri not required, if NULL then returns REQUEST_URI matching Pod Page
1328
 *
1329
 * @param string $uri The Pod Page URI to check if exists
0 ignored issues
show
Documentation introduced by
Should the type for parameter $uri not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
1330
 *
1331
 * @return array
0 ignored issues
show
Documentation introduced by
Should the return type not be array|boolean? Also, consider making the array more specific, something like array<String>, or String[].

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

If the return type contains the type array, this check recommends the use of a more specific type like String[] or array<String>.

Loading history...
1332
 *
1333
 * @since 1.7.5
1334
 */
1335
function pod_page_exists( $uri = null ) {
1336
1337
	return Pods_Pages::exists( $uri );
1338
}
1339
1340
/**
1341
 * Output Pod Page Content
1342
 *
1343
 * @param bool $return Whether to return or not (default is to echo)
1344
 *
1345
 * @param bool $pods_page
1346
 *
1347
 * @return string
1348
 * @since 1.7.0
1349
 */
1350
function pods_content( $return = false, $pods_page = false ) {
1351
1352
	return Pods_Pages::content( $return, $pods_page );
1353
}
1354
1355
/**
1356
 * Sort an array by length of items, descending, for use with uksort()
1357
 *
1358
 * @param string $a First array item
1359
 * @param string $b Second array item
1360
 *
1361
 * @return int Length difference
1362
 *
1363
 * @since 2.3.4
1364
 */
1365
function pods_page_length_sort( $a, $b ) {
0 ignored issues
show
Comprehensibility introduced by
Avoid variables with short names like $a. Configured minimum length is 3.

Short variable names may make your code harder to understand. Variable names should be self-descriptive. This check looks for variable names who are shorter than a configured minimum.

Loading history...
Comprehensibility introduced by
Avoid variables with short names like $b. Configured minimum length is 3.

Short variable names may make your code harder to understand. Variable names should be self-descriptive. This check looks for variable names who are shorter than a configured minimum.

Loading history...
1366
1367
	return strlen( $b ) - strlen( $a );
1368
}
1369
1370
/**
1371
 * Flush Pod Page Rewrite cache
1372
 *
1373
 * @return array Pod Page Rewrites
1374
 *
1375
 * @since 2.3.4
1376
 */
1377
function pods_page_flush_rewrites() {
1378
1379
	return Pods_Pages::flush_rewrites();
1380
}
1381
1382
/*
1383
 * Deprecated global variable
1384
 */
1385
$GLOBALS['pod_page_exists'] =& Pods_Pages::$exists;
1386