PluginProbe ʕ •ᴥ•ʔ
Pods – Custom Content Types and Fields / 3.2.7
Pods – Custom Content Types and Fields v3.2.7
trunk 1.14.8 2.7.31.3 2.8.23.3 2.9.19.3 3.0.10.3 3.1.4.1 3.2.0 3.2.1 3.2.1.1 3.2.2 3.2.4 3.2.5 3.2.6 3.2.7 3.2.7.1 3.2.8 3.2.8.1 3.2.8.2 3.3.0 3.3.1 3.3.2 3.3.3 3.3.4 3.3.5 3.3.6 3.3.7 3.3.8 3.3.9
pods / classes / PodsView.php
pods / classes Last commit date
cli 3 years ago fields 1 year ago widgets 3 years ago Pods.php 1 year ago PodsAPI.php 1 year ago PodsAdmin.php 1 year ago PodsArray.php 2 years ago PodsComponent.php 8 years ago PodsComponents.php 1 year ago PodsData.php 1 year ago PodsField.php 2 years ago PodsForm.php 1 year ago PodsI18n.php 4 years ago PodsInit.php 1 year ago PodsMeta.php 1 year ago PodsMigrate.php 3 years ago PodsRESTFields.php 1 year ago PodsRESTHandlers.php 1 year ago PodsTermSplitting.php 3 years ago PodsUI.php 1 year ago PodsView.php 1 year ago
PodsView.php
977 lines
1 <?php
2
3 use Pods\Static_Cache;
4
5 /**
6 * @package Pods
7 */
8 class PodsView {
9
10 /**
11 * List of keys that have been cached grouped by cache mode.
12 *
13 * @since 3.0
14 *
15 * @var array
16 */
17 private static $cached_keys = [
18 'transient' => [],
19 'site-transient' => [],
20 'cache' => [],
21 'static-cache' => [],
22 'option-cache' => [],
23 ];
24
25 /**
26 * @var array $cache_modes Array of available cache modes
27 */
28 public static $cache_modes = [
29 'none' => true,
30 'transient' => true,
31 'site-transient' => true,
32 'cache' => true,
33 'static-cache' => true,
34 'option-cache' => true,
35 ];
36
37 /**
38 * @return \PodsView
39 */
40 private function __construct() {
41 // !nope
42 }
43
44 /**
45 * Add a cache key to keep track of for a cache mode.
46 *
47 * @since 3.0
48 *
49 * @param string $cache_mode The cache mode.
50 * @param string $cache_key The cache key.
51 * @param null|string $group The cache group, if needed.
52 * @param null|string $original_key The original cache key, if different from the cache key.
53 */
54 public static function add_cached_key( $cache_mode, $cache_key, $group = null, $original_key = null ) {
55 if ( ! isset( self::$cached_keys[ $cache_mode ] ) ) {
56 self::$cached_keys[ $cache_mode ] = [];
57 }
58
59 if ( null === $original_key ) {
60 $original_key = $cache_key;
61 }
62
63 if ( $group ) {
64 if ( ! isset( self::$cached_keys[ $cache_mode ][ $group ] ) ) {
65 self::$cached_keys[ $cache_mode ][ $group ] = [];
66 }
67
68 self::$cached_keys[ $cache_mode ][ $group ][ $cache_key ] = $original_key;
69
70 return;
71 }
72
73 self::$cached_keys[ $cache_mode ][ $cache_key ] = $original_key;
74 }
75
76 /**
77 * Remove a cache key from tracking for a cache mode.
78 *
79 * @since 3.0
80 *
81 * @param string $cache_mode The cache mode.
82 * @param string $cache_key The cache key.
83 * @param null|string $group The cache group, if needed.
84 */
85 public static function remove_cached_key( $cache_mode, $cache_key, $group = null ) {
86 if ( ! isset( self::$cached_keys[ $cache_mode ] ) ) {
87 return;
88 }
89
90 if ( $group ) {
91 if ( ! isset( self::$cached_keys[ $cache_mode ][ $group ] ) ) {
92 return;
93 }
94
95 unset( self::$cached_keys[ $cache_mode ][ $group ][ $cache_key ] );
96
97 return;
98 }
99
100 if ( ! isset( self::$cached_keys[ $cache_mode ][ $cache_key ] ) ) {
101 return;
102 }
103
104 unset( self::$cached_keys[ $cache_mode ][ $cache_key ] );
105 }
106
107 /**
108 * Get the list of cache keys based on cache mode.
109 *
110 * @since 3.0
111 *
112 * @param string $cache_mode The cache mode.
113 * @param null|string $group The cache group, if needed.
114 */
115 public static function get_cached_keys( $cache_mode, $group = null ) : array {
116 if ( $group ) {
117 return self::$cached_keys[ $cache_mode ][ $group ] ?? [];
118 }
119
120 return self::$cached_keys[ $cache_mode ] ?? [];
121 }
122
123 /**
124 * Reset cache keys based on cache mode.
125 *
126 * @since 3.0
127 *
128 * @param null|string $cache_mode The cache mode, null if resetting all.
129 * @param null|string $group The cache group, if needed.
130 */
131 public static function reset_cached_keys( $cache_mode = null, $group = null ) {
132 if ( null === $cache_mode ) {
133 foreach ( self::$cache_modes as $cache_mode_to_reset => $unused ) {
134 if ( isset( self::$cached_keys[ $cache_mode_to_reset ] ) ) {
135 self::$cached_keys[ $cache_mode_to_reset ] = [];
136 }
137 }
138
139 return;
140 }
141
142 if ( $group ) {
143 if ( isset( self::$cached_keys[ $cache_mode ][ $group ] ) ) {
144 self::$cached_keys[ $cache_mode ][ $group ] = [];
145 }
146
147 return;
148 }
149
150 if ( isset( self::$cached_keys[ $cache_mode ] ) ) {
151 self::$cached_keys[ $cache_mode ] = [];
152 }
153 }
154
155 /**
156 * @static
157 *
158 * @param string $view Path of the view file
159 * @param array|null $data (optional) Data to pass on to the template
160 * @param bool|int|array $expires (optional) Time in seconds for the cache to expire, if 0 no expiration.
161 * @param string $cache_mode (optional) Decides the caching method to use for the view.
162 * @param bool $limited (optional) Whether to limit the view to only the theme directory, defaults to false
163 *
164 * @return bool|mixed|null|string|void
165 *
166 * @since 2.0.0
167 */
168 public static function view( $view, $data = null, $expires = false, $cache_mode = 'cache', $limited = false ) {
169
170 /**
171 * Allow filtering the view before the logic runs.
172 *
173 * @since 2.4.1
174 *
175 * @param null|false|string $filter_check The filter check. If not set to null, return the value as the output. Set to false to fail to load the view.
176 * @param string $view Path of the view file.
177 * @param array|null $data Data to pass on to the template.
178 * @param bool|int|array $expires Time in seconds for the cache to expire, if 0 no expiration.
179 * @param string $cache_mode Decides the caching method to use for the view.
180 * @param bool $limited Whether to limit the view to only the theme directory, defaults to false.
181 */
182 $filter_check = apply_filters( 'pods_view_alt_view', null, $view, $data, $expires, $cache_mode, $limited );
183
184 if ( null !== $filter_check ) {
185 return $filter_check;
186 }
187
188 // Advanced $expires handling
189 $expires = self::expires( $expires, $cache_mode );
190
191 if ( ! self::is_cache_mode_valid( $cache_mode ) ) {
192 $cache_mode = 'cache';
193 }
194
195 // Support my-view.php?custom-key=X#hash keying for cache
196 $view_id = '';
197
198 if ( ! is_array( $view ) ) {
199 $view_q = explode( '?', $view );
200
201 if ( 1 < count( $view_q ) ) {
202 $view_id = '?' . $view_q[1];
203
204 $view = $view_q[0];
205 }
206
207 $view_h = explode( '#', $view );
208
209 if ( 1 < count( $view_h ) ) {
210 $view_id .= '#' . $view_h[1];
211
212 $view = $view_h[0];
213 }
214
215 // Support dynamic tags!
216 $view_id = pods_evaluate_tags( $view_id );
217 }
218
219 /**
220 * Allow filtering the path of the view to use.
221 *
222 * @since unknown
223 *
224 * @param string $view Path of the view file.
225 * @param array|null $data Data to pass on to the template.
226 * @param bool|int|array $expires Time in seconds for the cache to expire, if 0 no expiration.
227 * @param string $cache_mode Decides the caching method to use for the view.
228 * @param bool $limited Whether to limit the view to only the theme directory, defaults to false.
229 */
230 $view = apply_filters( 'pods_view_inc', $view, $data, $expires, $cache_mode, $limited );
231
232 $view_key = $view;
233
234 if ( is_array( $view_key ) ) {
235 $view_key = implode( '-', $view_key ) . '.php';
236 }
237
238 if ( false !== realpath( $view_key ) ) {
239 $view_key = realpath( $view_key );
240 }
241
242 $pods_ui_dir = realpath( PODS_DIR . 'ui/' );
243 $pods_components_dir = realpath( PODS_DIR . 'components/' );
244 $abspath_dir = realpath( ABSPATH );
245
246 $cache_key = pods_str_replace( $abspath_dir, '/', $view_key, 1 );
247
248 $output = false;
249
250 $caching = false;
251
252 if ( false !== $expires && false === strpos( $view_key, $pods_ui_dir ) && false === strpos( $view_key, $pods_components_dir ) ) {
253 $caching = true;
254 }
255
256 if ( $caching ) {
257 $output = self::get( 'pods-view-' . $cache_key . $view_id, $cache_mode, 'pods_view' );
258 }
259
260 if ( false === $output || null === $output ) {
261 $output = self::get_template_part( $view, $data );
262 }
263
264 if ( false !== $output && $caching ) {
265 self::set( 'pods-view-' . $cache_key . $view_id, $output, $expires, $cache_mode, 'pods_view' );
266 }
267
268 /**
269 * Allow filtering the path of the view to use based on the cache key.
270 *
271 * @since unknown
272 *
273 * @param string|false $output The view output. Returns as false if the view fails to load.
274 * @param string $view Path of the view file.
275 * @param array|null $data Data to pass on to the template.
276 * @param bool|int|array $expires Time in seconds for the cache to expire, if 0 no expiration.
277 * @param string $cache_mode Decides the caching method to use for the view.
278 * @param bool $limited Whether to limit the view to only the theme directory, defaults to false.
279 */
280 $output = apply_filters( "pods_view_output_{$cache_key}", $output, $view, $data, $expires, $cache_mode, $limited );
281
282 /**
283 * Allow filtering the path of the view to use.
284 *
285 * @since unknown
286 *
287 * @param string|false $output The view output. Returns as false if the view fails to load.
288 * @param string $view Path of the view file.
289 * @param array|null $data Data to pass on to the template.
290 * @param bool|int|array $expires Time in seconds for the cache to expire, if 0 no expiration.
291 * @param string $cache_mode Decides the caching method to use for the view.
292 * @param bool $limited Whether to limit the view to only the theme directory, defaults to false.
293 */
294 $output = apply_filters( 'pods_view_output', $output, $view, $data, $expires, $cache_mode, $limited );
295
296 return $output;
297 }
298
299 /**
300 * Get the full path of the view if it exists.
301 *
302 * @since 3.1.0
303 *
304 * @param string $view Path of the view file
305 * @param bool $limited (optional) Whether to limit the view to only the theme directory, defaults to false
306 *
307 * @return string|false The full path of the view if it exists.
308 */
309 public static function view_get_path( $view, $limited = false ) {
310 // Support my-view.php?custom-key=X#hash keying for cache
311 if ( ! is_array( $view ) ) {
312 $view_q = explode( '?', $view );
313
314 if ( 1 < count( $view_q ) ) {
315 $view = $view_q[0];
316 }
317
318 $view_h = explode( '#', $view );
319
320 if ( 1 < count( $view_h ) ) {
321 $view = $view_h[0];
322 }
323 }
324
325 $view = apply_filters( 'pods_view_inc', $view, null, false, 'cache', $limited );
326
327 $view_key = $view;
328
329 if ( is_array( $view_key ) ) {
330 $view_key = implode( '-', $view_key ) . '.php';
331 }
332
333 if ( false !== realpath( $view_key ) ) {
334 $view_key = realpath( $view_key );
335 }
336
337 $view_path = self::locate_template( $view_key, $limited );
338
339 if ( empty( $view_path ) ) {
340 return false;
341 }
342
343 return $view_path;
344 }
345
346 /**
347 * Get the cache key, salted with current Pods version, peppered with md5 if too long
348 *
349 * @param string $key
350 * @param string $group_key
351 *
352 * @return string
353 *
354 * @since 2.6.2
355 */
356 public static function get_key( $key, $group_key = '' ) {
357
358 // Add some salt
359 $key .= '-' . sanitize_key( PODS_VERSION );
360
361 // Patch for limitations in DB
362 if ( is_string( $group_key ) && 44 < strlen( $group_key . $key ) ) {
363 $key = md5( $key );
364 }
365
366 return $key;
367
368 }
369
370 /**
371 * @static
372 *
373 * @param string $key Key for the cache
374 * @param string $cache_mode (optional) Decides the caching method to use for the view.
375 * @param string $group (optional) Set the group of the value.
376 * @param string $callback (optional) Callback function to run to set the value if not cached.
377 *
378 * @return bool|mixed|null|void
379 *
380 * @since 2.0.0
381 */
382 public static function get( $key, $cache_mode = 'cache', $group = '', $callback = null ) {
383 $external_object_cache = wp_using_ext_object_cache();
384
385 $object_cache_enabled = (
386 (
387 isset( $GLOBALS['wp_object_cache'] )
388 && is_object( $GLOBALS['wp_object_cache'] )
389 )
390 || $external_object_cache
391 );
392
393 if ( ! self::is_cache_mode_valid( $cache_mode ) ) {
394 $cache_mode = 'cache';
395 }
396
397 $group_key = 'pods_';
398
399 if ( ! empty( $group ) ) {
400 $group_key = $group . '_';
401 }
402
403 $original_key = $key;
404
405 // Get proper cache key
406 $key = self::get_key( $key, $group_key );
407
408 $value = null;
409
410 $called = false;
411
412 $pods_nocache = pods_v( 'pods_nocache' );
413 $nocache = array();
414
415 if ( null !== $pods_nocache && 'static-cache' !== $cache_mode && pods_is_admin() ) {
416 if ( is_string( $pods_nocache ) && 1 < strlen( $pods_nocache ) ) {
417 $nocache = explode( ',', $pods_nocache );
418 $nocache = array_flip( $nocache );
419 } else {
420 $nocache = self::$cache_modes;
421 }
422 }
423
424 $cache_enabled = ! isset( $nocache[ $cache_mode ] );
425
426 if ( apply_filters( 'pods_view_cache_alt_get', false, $cache_mode, $group_key . $key, $original_key, $group ) ) {
427 $value = apply_filters( 'pods_view_cache_alt_get_value', $value, $cache_mode, $group_key . $key, $original_key, $group );
428 } elseif ( $cache_enabled ) {
429 if ( 'transient' === $cache_mode ) {
430 $value = get_transient( $group_key . $key );
431 } elseif ( 'site-transient' === $cache_mode ) {
432 $value = get_site_transient( $group_key . $key );
433 } elseif ( 'cache' === $cache_mode && $object_cache_enabled ) {
434 $value = wp_cache_get( $key, ( empty( $group ) ? 'pods_view' : $group ) );
435 } elseif ( 'option-cache' === $cache_mode ) {
436 $pre = apply_filters( "pre_transient_{$key}", false );
437
438 if ( false !== $pre ) {
439 $value = $pre;
440 } elseif ( $external_object_cache ) {
441 $cache_found = false;
442
443 $value = wp_cache_get( $key, ( empty( $group ) ? 'pods_option_cache' : $group ), false, $cache_found );
444
445 if ( false === $value || ! $cache_found ) {
446 if ( is_callable( $callback ) ) {
447 // Callback function should do it's own set/update for cache
448 $callback_value = call_user_func( $callback, $original_key, $group, $cache_mode );
449
450 if ( null !== $callback_value && false !== $callback_value ) {
451 $value = $callback_value;
452 }
453
454 $called = true;
455 }
456 }
457 } else {
458 $transient_option = '_pods_option_' . $key;
459 $transient_timeout = '_pods_option_timeout_' . $key;
460
461 $value = get_option( $transient_option );
462 $timeout = get_option( $transient_timeout );
463
464 if ( ! empty( $timeout ) && $timeout < time() ) {
465 if ( is_callable( $callback ) ) {
466 // Callback function should do it's own set/update for cache
467 $callback_value = call_user_func( $callback, $original_key, $group, $cache_mode );
468
469 if ( null !== $callback_value && false !== $callback_value ) {
470 $value = $callback_value;
471 }
472
473 $called = true;
474 } else {
475 $value = false;
476
477 delete_option( $transient_option );
478 delete_option( $transient_timeout );
479 }
480 }
481 }//end if
482
483 if ( false !== $value ) {
484 $value = apply_filters( "transient_{$key}", $value );
485 }
486 } elseif ( 'static-cache' === $cache_mode ) {
487 $static_cache = pods_container( Static_Cache::class );
488
489 if ( $static_cache ) {
490 $value = $static_cache->get( $key, ( empty( $group ) ? 'pods_view' : $group ) );
491 } else {
492 $value = false;
493 }
494 } else {
495 $value = false;
496 }//end if
497 } else {
498 $value = false;
499 }//end if
500
501 if ( false === $value && is_callable( $callback ) && ! $called ) {
502 // Callback function should do it's own set/update for cache
503 $callback_value = call_user_func( $callback, $original_key, $group, $cache_mode );
504
505 if ( null !== $callback_value && false !== $callback_value ) {
506 $value = $callback_value;
507 }
508 }
509
510 $value = apply_filters( "pods_view_get_{$cache_mode}", $value, $original_key, $group );
511
512 return $value;
513 }
514
515 /**
516 * @static
517 *
518 * Set a cached value
519 *
520 * @param string $key Key for the cache
521 * @param mixed $value Value to add to the cache
522 * @param int $expires (optional) Time in seconds for the cache to expire, if 0 no expiration.
523 * @param string $cache_mode (optional) Decides the caching method to use for the view.
524 * @param string $group (optional) Set the group of the value.
525 *
526 * @return bool|mixed|null|string|void
527 *
528 * @since 2.0.0
529 */
530 public static function set( $key, $value, $expires = 0, $cache_mode = null, $group = '' ) {
531 $external_object_cache = wp_using_ext_object_cache();
532
533 $object_cache_enabled = (
534 (
535 isset( $GLOBALS['wp_object_cache'] )
536 && is_object( $GLOBALS['wp_object_cache'] )
537 )
538 || $external_object_cache
539 );
540
541 // Advanced $expires handling
542 $expires = self::expires( $expires, $cache_mode );
543
544 if ( ! self::is_cache_mode_valid( $cache_mode ) ) {
545 $cache_mode = 'cache';
546 }
547
548 $group_key = 'pods_';
549
550 if ( ! empty( $group ) ) {
551 $group_key = $group . '_';
552 }
553
554 $original_key = $key;
555
556 // Get proper cache key
557 $key = self::get_key( $key, $group_key );
558
559 if ( apply_filters( 'pods_view_cache_alt_set', false, $cache_mode, $group_key . $key, $original_key, $value, $expires, $group ) ) {
560 self::add_cached_key( $cache_mode, $group_key . $key, null, $original_key );
561
562 return $value;
563 } elseif ( 'transient' === $cache_mode ) {
564 self::add_cached_key( $cache_mode, $group_key . $key, null, $original_key );
565
566 set_transient( $group_key . $key, $value, $expires );
567 } elseif ( 'site-transient' === $cache_mode ) {
568 self::add_cached_key( $cache_mode, $group_key . $key, null, $original_key );
569
570 set_site_transient( $group_key . $key, $value, $expires );
571 } elseif ( 'cache' === $cache_mode && $object_cache_enabled ) {
572 $group = ( empty( $group ) ? 'pods_view' : $group );
573 $key = ( empty( $key ) ? 'pods_view' : $key );
574
575 self::add_cached_key( $cache_mode, $key, $group, $original_key );
576
577 wp_cache_set( $key, $value, $group, $expires );
578 } elseif ( 'option-cache' === $cache_mode ) {
579 $group = ( empty( $group ) ? 'pods_option_cache' : $group );
580
581 $value = apply_filters( "pre_set_transient_{$key}", $value );
582
583 if ( $external_object_cache ) {
584 $result = wp_cache_set( $key, $value, $group, $expires );
585 } else {
586 $transient_timeout = '_pods_option_timeout_' . $key;
587 $key = '_pods_option_' . $key;
588
589 if ( false === get_option( $key ) ) {
590 if ( $expires ) {
591 add_option( $transient_timeout, time() + $expires, '', 'no' );
592 }
593
594 $result = add_option( $key, $value, '', 'no' );
595 } else {
596 if ( $expires ) {
597 update_option( $transient_timeout, time() + $expires );
598 }
599
600 $result = update_option( $key, $value );
601 }
602 }//end if
603
604 self::add_cached_key( $cache_mode, $key, $group, $original_key );
605
606 if ( $result ) {
607 do_action( "set_transient_{$key}", $value, $expires );
608 do_action( 'setted_transient', $key, $value, $expires );
609 }
610 } elseif ( 'static-cache' === $cache_mode ) {
611 $static_cache = pods_container( Static_Cache::class );
612
613 if ( $static_cache ) {
614 $group = ( empty( $group ) ? __CLASS__ : $group );
615
616 self::add_cached_key( $cache_mode, $key, $group, $original_key );
617
618 $static_cache->set( $key, $value, $group );
619 }
620 }//end if
621
622 do_action( "pods_view_set_{$cache_mode}", $original_key, $value, $expires, $group );
623
624 return $value;
625 }
626
627 /**
628 * @static
629 *
630 * Clear a cached value
631 *
632 * @param string|bool $key Key for the cache
633 * @param string $cache_mode (optional) Decides the caching method to use for the view.
634 * @param string $group (optional) Set the group.
635 *
636 * @return bool
637 *
638 * @since 2.0.0
639 */
640 public static function clear( $key = true, $cache_mode = null, $group = '' ) {
641 $external_object_cache = wp_using_ext_object_cache();
642
643 $object_cache_enabled = (
644 (
645 isset( $GLOBALS['wp_object_cache'] )
646 && is_object( $GLOBALS['wp_object_cache'] )
647 )
648 || $external_object_cache
649 );
650
651 global $wpdb;
652
653 if ( ! self::is_cache_mode_valid( $cache_mode ) ) {
654 $cache_mode = 'cache';
655 }
656
657 $group_key = 'pods_';
658
659 if ( ! empty( $group ) ) {
660 $group_key = $group . '_';
661 }
662
663 $full_key = $key;
664 $original_key = $key;
665
666 if ( true !== $key ) {
667 // Get proper cache key
668 $key = self::get_key( $key, $group_key );
669
670 $full_key = $group_key . $key;
671 }
672
673 if ( apply_filters( 'pods_view_cache_alt_set', false, $cache_mode, $full_key, $original_key, '', 0, $group ) ) {
674 self::remove_cached_key( $cache_mode, $full_key );
675
676 return true;
677 } elseif ( 'transient' === $cache_mode ) {
678 if ( true === $key ) {
679 $group_key = pods_sanitize_like( $group_key );
680
681 $wpdb->query( "DELETE FROM `{$wpdb->options}` WHERE option_name LIKE '_transient_{$group_key}%'" );
682
683 if ( $object_cache_enabled ) {
684 if ( $group && function_exists( 'wp_cache_flush_group' ) && wp_cache_supports( 'flush_group' ) ) {
685 wp_cache_flush_group( $group );
686 } else {
687 wp_cache_flush();
688 }
689 }
690
691 self::reset_cached_keys( $cache_mode );
692 } else {
693 delete_transient( $group_key . $key );
694
695 self::remove_cached_key( $cache_mode, $group_key . $key );
696 }
697 } elseif ( 'site-transient' === $cache_mode ) {
698 if ( true === $key ) {
699 $group_key = pods_sanitize_like( $group_key );
700
701 $wpdb->query( "DELETE FROM `{$wpdb->options}` WHERE option_name LIKE '_site_transient_{$group_key}%'" );
702
703 if ( $object_cache_enabled ) {
704 if ( $group && function_exists( 'wp_cache_flush_group' ) && wp_cache_supports( 'flush_group' ) ) {
705 wp_cache_flush_group( $group );
706 } else {
707 wp_cache_flush();
708 }
709 }
710
711 self::reset_cached_keys( $cache_mode );
712 } else {
713 delete_site_transient( $group_key . $key );
714
715 self::remove_cached_key( $cache_mode, $group_key . $key );
716 }
717 } elseif ( 'cache' === $cache_mode && $object_cache_enabled ) {
718 if ( true === $key ) {
719 if ( $group && function_exists( 'wp_cache_flush_group' ) && wp_cache_supports( 'flush_group' ) ) {
720 wp_cache_flush_group( $group );
721
722 self::reset_cached_keys( $cache_mode, $group );
723 } else {
724 wp_cache_flush();
725
726 self::reset_cached_keys( $cache_mode );
727 }
728 } else {
729 $group = ( empty( $group ) ? 'pods_view' : $group );
730 $key = ( empty( $key ) ? 'pods_view' : $key );
731
732 wp_cache_delete( $key, $group );
733
734 self::remove_cached_key( $cache_mode, $key, $group );
735 }
736 } elseif ( 'option-cache' === $cache_mode ) {
737 do_action( "delete_transient_{$key}", $key );
738
739 $group = ( empty( $group ) ? 'pods_option_cache' : $group );
740
741 if ( $external_object_cache ) {
742 $result = wp_cache_delete( $key, $group );
743
744 wp_cache_delete( '_timeout_' . $key, $group );
745 } else {
746 $option_timeout = '_pods_option_timeout_' . $key;
747 $option = '_pods_option_' . $key;
748
749 $result = delete_option( $option );
750
751 if ( $result ) {
752 delete_option( $option_timeout );
753 }
754 }
755
756 self::remove_cached_key( $cache_mode, $key, $group );
757
758 if ( $result ) {
759 do_action( 'deleted_transient', $key );
760 }
761 } elseif ( 'static-cache' === $cache_mode ) {
762 $static_cache = pods_container( Static_Cache::class );
763
764 if ( $static_cache ) {
765 $group = ( empty( $group ) ? __CLASS__ : $group );
766
767 if ( true === $key ) {
768 $static_cache->flush( $group );
769
770 self::reset_cached_keys( $cache_mode, $group );
771 } else {
772 $static_cache->delete( $key, $group );
773
774 self::remove_cached_key( $cache_mode, $key, $group );
775 }
776 }
777 }//end if
778
779 do_action( "pods_view_clear_{$cache_mode}", $original_key, $group );
780
781 return true;
782 }
783
784 /**
785 * @static
786 *
787 * @param $_view
788 * @param null|array $_data
789 * @param bool $limited (optional) Whether to limit the view to only the theme directory, defaults to false
790 *
791 * @return bool|mixed|string|void
792 */
793 public static function get_template_part( $_view, $_data = null, $limited = false ) {
794
795 /*
796 To be reviewed later, should have more checks and restrictions like a whitelist etc.
797
798 if ( 0 === strpos( $_view, 'http://' ) || 0 === strpos( $_view, 'https://' ) ) {
799 $_view = apply_filters( 'pods_view_url_include', $_view );
800
801 if ( empty( $_view ) || ( defined( 'PODS_REMOTE_VIEWS' ) && PODS_REMOTE_VIEWS ) )
802 return '';
803
804 $response = wp_remote_get( $_view );
805
806 return wp_remote_retrieve_body( $response );
807 }
808 */
809
810 $_view = self::locate_template( $_view, $limited );
811
812 if ( empty( $_view ) ) {
813 return $_view;
814 }
815
816 if ( ! empty( $_data ) && is_array( $_data ) ) {
817 extract( $_data, EXTR_SKIP );
818 }
819
820 ob_start();
821 require $_view;
822 $output = ob_get_clean();
823
824 return $output;
825 }
826
827 /**
828 * @static
829 *
830 * @param array|string $_view
831 * @param bool $limited (optional) Whether to limit the view to only the theme directory, defaults to false
832 *
833 * @return bool|mixed|string|void
834 */
835 private static function locate_template( $_view, $limited = false ) {
836 if ( is_array( $_view ) ) {
837 $_views = [];
838
839 if ( isset( $_view[0] ) && false === strpos( $_view[0], '.php' ) ) {
840 $_view_count = count( $_view );
841
842 for ( $_view_x = $_view_count; 0 < $_view_x; $_view_x -- ) {
843 $_view_v = array_slice( $_view, 0, $_view_x );
844
845 $_views[] = implode( '-', $_view_v ) . '.php';
846 }
847 } else {
848 $_views = $_view;
849 }
850
851 $_view = false;
852
853 foreach ( $_views as $_view_check ) {
854 $_view = self::locate_template( $_view_check );
855
856 if ( ! empty( $_view ) ) {
857 break;
858 }
859 }
860
861 return $_view;
862 }//end if
863
864 $paths_to_check = [ 'plugins', 'pods', 'theme' ];
865
866 if ( $limited ) {
867 $paths_to_check = [ 'theme' ];
868 }
869
870 // Is the view's file somewhere within the plugin directory tree?
871 // Note: we include PODS_DIR for the case of symlinks (see issue #2945).
872 $located = pods_validate_safe_path( $_view, $paths_to_check );
873
874 /**
875 * Allow filtering the validated view file path to use.
876 *
877 * @since unknown
878 *
879 * @param string|false $located The validated view file path to use, or false if it was not valid.
880 * @param string $_view The original view file path to use.
881 */
882 $located = apply_filters( 'pods_view_locate_template', $located, $_view );
883
884 if ( ! $located ) {
885 return false;
886 }
887
888 return $located;
889
890 }
891
892 /**
893 * Advanced $expires handling
894 *
895 * @param array|bool|int $expires
896 * @param string $cache_mode
897 *
898 * @return bool|int
899 *
900 * @since 2.7.0
901 * @static
902 */
903 public static function expires( $expires, $cache_mode = 'cache' ) {
904
905 // Different $expires if user is anonymous or logged in or specific capability
906 if ( is_array( $expires ) ) {
907 if ( ( isset( $expires['anonymous'] ) || isset( $expires['user_with_access'] ) ) && isset( $expires['user'] ) ) {
908 if ( isset( $expires['user_with_access'] ) ) {
909 $expires = array(
910 pods_v( 'anonymous', $expires, false ),
911 pods_v( 'user', $expires, false ),
912 pods_v( 'user_with_access', $expires, false ),
913 pods_v( 'capability', $expires, null, null, true ),
914 );
915 } elseif ( isset( $expires['anonymous'] ) ) {
916 $expires = array(
917 pods_v( 'anonymous', $expires, false ),
918 pods_v( 'user', $expires, false ),
919 pods_v( 'capability', $expires, null, null, true ),
920 );
921 }
922 } else {
923 $expires = array_values( $expires );
924 }
925
926 if ( 4 === count( $expires ) ) {
927 if ( ! is_user_logged_in() ) {
928 $expires = pods_v( 0, $expires, false );
929 } else {
930 $user_no_access = pods_v( 1, $expires, false );
931 $user_with_access = pods_v( 2, $expires, false );
932 $capability = pods_v( 3, $expires, null, true );
933
934 $expires = pods_var_user( $user_no_access, $user_with_access, $capability );
935 }
936 } else {
937 $anon = pods_v( 0, $expires, false );
938 $user = pods_v( 1, $expires, false );
939 $capability = pods_v( 2, $expires, null, true );
940
941 $expires = pods_var_user( $anon, $user, $capability );
942 }
943 }//end if
944
945 if ( 'none' === $cache_mode ) {
946 $expires = false;
947 } elseif ( false !== $expires ) {
948 $expires = (int) $expires;
949
950 if ( $expires < 1 ) {
951 $expires = 0;
952 }
953 }
954
955 return $expires;
956
957 }
958
959 /**
960 * Determine whether the cache mode is valid.
961 *
962 * @since 2.9.14
963 *
964 * @param string|mixed $cache_mode The cache mode.
965 *
966 * @return bool Whether the cache mode is valid.
967 */
968 public static function is_cache_mode_valid( $cache_mode ) {
969 return (
970 $cache_mode
971 && is_string( $cache_mode )
972 && isset( self::$cache_modes[ $cache_mode ] )
973 );
974 }
975
976 }
977