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