PluginProbe ʕ •ᴥ•ʔ
Pods – Custom Content Types and Fields / 3.3.7
Pods – Custom Content Types and Fields v3.3.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 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
990 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 $view_key = (string) $view_key;
248
249 $pods_ui_dir = realpath( PODS_DIR . 'ui/' );
250 $pods_components_dir = realpath( PODS_DIR . 'components/' );
251 $abspath_dir = realpath( ABSPATH );
252
253 $cache_key = pods_str_replace( $abspath_dir, '/', $view_key, 1 );
254
255 $output = false;
256
257 $caching = false;
258
259 if ( false !== $expires && false === strpos( $view_key, $pods_ui_dir ) && false === strpos( $view_key, $pods_components_dir ) ) {
260 $caching = true;
261 }
262
263 if ( $caching ) {
264 $output = self::get( 'pods-view-' . $cache_key . $view_id, $cache_mode, 'pods_view' );
265 }
266
267 if ( false === $output || null === $output ) {
268 $output = self::get_template_part( $view, $data );
269 }
270
271 if ( false !== $output && $caching ) {
272 self::set( 'pods-view-' . $cache_key . $view_id, $output, $expires, $cache_mode, 'pods_view' );
273 }
274
275 /**
276 * Allow filtering the path of the view to use based on the cache key.
277 *
278 * @since unknown
279 *
280 * @param string|false $output The view output. Returns as false if the view fails to load.
281 * @param string $view Path of the view file.
282 * @param array|null $data Data to pass on to the template.
283 * @param bool|int|array $expires Time in seconds for the cache to expire, if 0 no expiration.
284 * @param string $cache_mode Decides the caching method to use for the view.
285 * @param bool $limited Whether to limit the view to only the theme directory, defaults to false.
286 */
287 $output = apply_filters( "pods_view_output_{$cache_key}", $output, $view, $data, $expires, $cache_mode, $limited );
288
289 /**
290 * Allow filtering the path of the view to use.
291 *
292 * @since unknown
293 *
294 * @param string|false $output The view output. Returns as false if the view fails to load.
295 * @param string $view Path of the view file.
296 * @param array|null $data Data to pass on to the template.
297 * @param bool|int|array $expires Time in seconds for the cache to expire, if 0 no expiration.
298 * @param string $cache_mode Decides the caching method to use for the view.
299 * @param bool $limited Whether to limit the view to only the theme directory, defaults to false.
300 */
301 $output = apply_filters( 'pods_view_output', $output, $view, $data, $expires, $cache_mode, $limited );
302
303 return $output;
304 }
305
306 /**
307 * Get the full path of the view if it exists.
308 *
309 * @since 3.1.0
310 *
311 * @param string $view Path of the view file
312 * @param bool $limited (optional) Whether to limit the view to only the theme directory, defaults to false
313 *
314 * @return string|false The full path of the view if it exists.
315 */
316 public static function view_get_path( $view, $limited = false ) {
317 // Support my-view.php?custom-key=X#hash keying for cache
318 if ( ! is_array( $view ) ) {
319 $view_q = explode( '?', $view );
320
321 if ( 1 < count( $view_q ) ) {
322 $view = $view_q[0];
323 }
324
325 $view_h = explode( '#', $view );
326
327 if ( 1 < count( $view_h ) ) {
328 $view = $view_h[0];
329 }
330 }
331
332 $view = apply_filters( 'pods_view_inc', $view, null, false, 'cache', $limited );
333
334 $view_key = $view;
335
336 if ( is_array( $view_key ) ) {
337 $view_key = implode( '-', $view_key ) . '.php';
338 }
339
340 if ( false !== realpath( $view_key ) ) {
341 $view_key = realpath( $view_key );
342 }
343
344 $view_path = self::locate_template( $view_key, $limited );
345
346 if ( empty( $view_path ) ) {
347 return false;
348 }
349
350 return $view_path;
351 }
352
353 /**
354 * Get the cache key, salted with current Pods version, peppered with md5 if too long
355 *
356 * @param string $key
357 * @param string $group_key
358 *
359 * @return string
360 *
361 * @since 2.6.2
362 */
363 public static function get_key( string $key, string $group_key = '' ): string {
364
365 // Add some salt
366 $key .= '-' . sanitize_key( PODS_VERSION );
367
368 // Patch for limitations in DB
369 if ( is_string( $group_key ) && 44 < strlen( $group_key . $key ) ) {
370 $key = md5( $key );
371 }
372
373 return $key;
374
375 }
376
377 /**
378 * @static
379 *
380 * @param string $key Key for the cache
381 * @param string $cache_mode (optional) Decides the caching method to use for the view.
382 * @param string $group (optional) Set the group of the value.
383 * @param string $callback (optional) Callback function to run to set the value if not cached.
384 *
385 * @return bool|mixed|null|void
386 *
387 * @since 2.0.0
388 */
389 public static function get( $key, $cache_mode = 'cache', $group = '', $callback = null ) {
390 $external_object_cache = wp_using_ext_object_cache();
391
392 $object_cache_enabled = (
393 (
394 isset( $GLOBALS['wp_object_cache'] )
395 && is_object( $GLOBALS['wp_object_cache'] )
396 )
397 || $external_object_cache
398 );
399
400 if ( ! self::is_cache_mode_valid( $cache_mode ) ) {
401 $cache_mode = 'cache';
402 }
403
404 $group_key = 'pods_';
405
406 if ( ! empty( $group ) ) {
407 $group_key = $group . '_';
408 }
409
410 $original_key = $key;
411
412 // Get proper cache key
413 $key = self::get_key( $key, $group_key );
414
415 $value = null;
416
417 $called = false;
418
419 $pods_nocache = pods_v( 'pods_nocache' );
420 $nocache = array();
421
422 if ( null !== $pods_nocache && 'static-cache' !== $cache_mode && pods_is_admin() ) {
423 if ( is_string( $pods_nocache ) && 1 < strlen( $pods_nocache ) ) {
424 $nocache = explode( ',', $pods_nocache );
425 $nocache = array_flip( $nocache );
426 } else {
427 $nocache = self::$cache_modes;
428 }
429 }
430
431 $cache_enabled = ! isset( $nocache[ $cache_mode ] );
432
433 if ( apply_filters( 'pods_view_cache_alt_get', false, $cache_mode, $group_key . $key, $original_key, $group ) ) {
434 $value = apply_filters( 'pods_view_cache_alt_get_value', $value, $cache_mode, $group_key . $key, $original_key, $group );
435 } elseif ( $cache_enabled ) {
436 if ( 'transient' === $cache_mode ) {
437 $value = get_transient( $group_key . $key );
438 } elseif ( 'site-transient' === $cache_mode ) {
439 $value = get_site_transient( $group_key . $key );
440 } elseif ( 'cache' === $cache_mode && $object_cache_enabled ) {
441 $value = wp_cache_get( $key, ( empty( $group ) ? 'pods_view' : $group ) );
442 } elseif ( 'option-cache' === $cache_mode ) {
443 $pre = apply_filters( "pre_transient_{$key}", false ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
444
445 if ( false !== $pre ) {
446 $value = $pre;
447 } elseif ( $external_object_cache ) {
448 $cache_found = false;
449
450 $value = wp_cache_get( $key, ( empty( $group ) ? 'pods_option_cache' : $group ), false, $cache_found );
451
452 if ( false === $value || ! $cache_found ) {
453 if ( is_callable( $callback ) ) {
454 // Callback function should do it's own set/update for cache
455 $callback_value = call_user_func( $callback, $original_key, $group, $cache_mode );
456
457 if ( null !== $callback_value && false !== $callback_value ) {
458 $value = $callback_value;
459 }
460
461 $called = true;
462 }
463 }
464 } else {
465 $transient_option = '_pods_option_' . $key;
466 $transient_timeout = '_pods_option_timeout_' . $key;
467
468 $value = get_option( $transient_option );
469 $timeout = get_option( $transient_timeout );
470
471 if ( ! empty( $timeout ) && $timeout < time() ) {
472 if ( is_callable( $callback ) ) {
473 // Callback function should do it's own set/update for cache
474 $callback_value = call_user_func( $callback, $original_key, $group, $cache_mode );
475
476 if ( null !== $callback_value && false !== $callback_value ) {
477 $value = $callback_value;
478 }
479
480 $called = true;
481 } else {
482 $value = false;
483
484 delete_option( $transient_option );
485 delete_option( $transient_timeout );
486 }
487 }
488 }//end if
489
490 if ( false !== $value ) {
491 $value = apply_filters( "transient_{$key}", $value ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
492 }
493 } elseif ( 'static-cache' === $cache_mode ) {
494 $static_cache = pods_container( Static_Cache::class );
495
496 if ( $static_cache ) {
497 $value = $static_cache->get( $key, ( empty( $group ) ? 'pods_view' : $group ) );
498 } else {
499 $value = false;
500 }
501 } else {
502 $value = false;
503 }//end if
504 } else {
505 $value = false;
506 }//end if
507
508 if ( false === $value && is_callable( $callback ) && ! $called ) {
509 // Callback function should do it's own set/update for cache
510 $callback_value = call_user_func( $callback, $original_key, $group, $cache_mode );
511
512 if ( null !== $callback_value && false !== $callback_value ) {
513 $value = $callback_value;
514 }
515 }
516
517 $value = apply_filters( "pods_view_get_{$cache_mode}", $value, $original_key, $group );
518
519 return $value;
520 }
521
522 /**
523 * @static
524 *
525 * Set a cached value
526 *
527 * @param string $key Key for the cache
528 * @param mixed $value Value to add to the cache
529 * @param int $expires (optional) Time in seconds for the cache to expire, if 0 no expiration.
530 * @param string $cache_mode (optional) Decides the caching method to use for the view.
531 * @param string $group (optional) Set the group of the value.
532 *
533 * @return bool|mixed|null|string|void
534 *
535 * @since 2.0.0
536 */
537 public static function set( $key, $value, $expires = 0, $cache_mode = null, $group = '' ) {
538 $external_object_cache = wp_using_ext_object_cache();
539
540 $object_cache_enabled = (
541 (
542 isset( $GLOBALS['wp_object_cache'] )
543 && is_object( $GLOBALS['wp_object_cache'] )
544 )
545 || $external_object_cache
546 );
547
548 // Advanced $expires handling
549 $expires = self::expires( $expires, $cache_mode );
550
551 if ( ! self::is_cache_mode_valid( $cache_mode ) ) {
552 $cache_mode = 'cache';
553 }
554
555 $group_key = 'pods_';
556
557 if ( ! empty( $group ) ) {
558 $group_key = $group . '_';
559 }
560
561 $original_key = $key;
562
563 // Get proper cache key
564 $key = self::get_key( $key, $group_key );
565
566 if ( apply_filters( 'pods_view_cache_alt_set', false, $cache_mode, $group_key . $key, $original_key, $value, $expires, $group ) ) {
567 self::add_cached_key( $cache_mode, $group_key . $key, null, $original_key );
568
569 return $value;
570 } elseif ( 'transient' === $cache_mode ) {
571 self::add_cached_key( $cache_mode, $group_key . $key, null, $original_key );
572
573 set_transient( $group_key . $key, $value, $expires );
574 } elseif ( 'site-transient' === $cache_mode ) {
575 self::add_cached_key( $cache_mode, $group_key . $key, null, $original_key );
576
577 set_site_transient( $group_key . $key, $value, $expires );
578 } elseif ( 'cache' === $cache_mode && $object_cache_enabled ) {
579 $group = ( empty( $group ) ? 'pods_view' : $group );
580 $key = ( empty( $key ) ? 'pods_view' : $key );
581
582 self::add_cached_key( $cache_mode, $key, $group, $original_key );
583
584 wp_cache_set( $key, $value, $group, $expires );
585 } elseif ( 'option-cache' === $cache_mode ) {
586 $group = ( empty( $group ) ? 'pods_option_cache' : $group );
587
588 $value = apply_filters( "pre_set_transient_{$key}", $value ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
589
590 if ( $external_object_cache ) {
591 $result = wp_cache_set( $key, $value, $group, $expires );
592 } else {
593 $transient_timeout = '_pods_option_timeout_' . $key;
594 $key = '_pods_option_' . $key;
595
596 if ( false === get_option( $key ) ) {
597 if ( $expires ) {
598 add_option( $transient_timeout, time() + $expires, '', 'no' );
599 }
600
601 $result = add_option( $key, $value, '', 'no' );
602 } else {
603 if ( $expires ) {
604 update_option( $transient_timeout, time() + $expires );
605 }
606
607 $result = update_option( $key, $value );
608 }
609 }//end if
610
611 self::add_cached_key( $cache_mode, $key, $group, $original_key );
612
613 if ( $result ) {
614 do_action( "set_transient_{$key}", $value, $expires ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
615 do_action( 'setted_transient', $key, $value, $expires ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
616 }
617 } elseif ( 'static-cache' === $cache_mode ) {
618 $static_cache = pods_container( Static_Cache::class );
619
620 if ( $static_cache ) {
621 $group = ( empty( $group ) ? __CLASS__ : $group );
622
623 self::add_cached_key( $cache_mode, $key, $group, $original_key );
624
625 $static_cache->set( $key, $value, $group );
626 }
627 }//end if
628
629 do_action( "pods_view_set_{$cache_mode}", $original_key, $value, $expires, $group );
630
631 return $value;
632 }
633
634 /**
635 * @static
636 *
637 * Clear a cached value
638 *
639 * @param string|bool $key Key for the cache
640 * @param string $cache_mode (optional) Decides the caching method to use for the view.
641 * @param string $group (optional) Set the group.
642 *
643 * @return bool
644 *
645 * @since 2.0.0
646 */
647 public static function clear( $key = true, $cache_mode = null, $group = '' ) {
648 $external_object_cache = wp_using_ext_object_cache();
649
650 $object_cache_enabled = (
651 (
652 isset( $GLOBALS['wp_object_cache'] )
653 && is_object( $GLOBALS['wp_object_cache'] )
654 )
655 || $external_object_cache
656 );
657
658 global $wpdb;
659
660 if ( ! self::is_cache_mode_valid( $cache_mode ) ) {
661 $cache_mode = 'cache';
662 }
663
664 $group_key = 'pods_';
665
666 if ( ! empty( $group ) ) {
667 $group_key = $group . '_';
668 }
669
670 $full_key = $key;
671 $original_key = $key;
672
673 if ( true !== $key ) {
674 // Get proper cache key
675 $key = self::get_key( $key, $group_key );
676
677 $full_key = $group_key . $key;
678 }
679
680 if ( apply_filters( 'pods_view_cache_alt_set', false, $cache_mode, $full_key, $original_key, '', 0, $group ) ) {
681 self::remove_cached_key( $cache_mode, $full_key );
682
683 return true;
684 } elseif ( 'transient' === $cache_mode ) {
685 if ( true === $key ) {
686 $wpdb->query(
687 $wpdb->prepare(
688 "DELETE FROM `{$wpdb->options}` WHERE `option_name` LIKE %s",
689 '_transient_' . $wpdb->esc_like( $group_key ) . '%'
690 )
691 );
692
693 if ( $object_cache_enabled ) {
694 if ( $group && function_exists( 'wp_cache_flush_group' ) && wp_cache_supports( 'flush_group' ) ) {
695 wp_cache_flush_group( $group );
696 } else {
697 wp_cache_flush();
698 }
699 }
700
701 self::reset_cached_keys( $cache_mode );
702 } else {
703 delete_transient( $group_key . $key );
704
705 self::remove_cached_key( $cache_mode, $group_key . $key );
706 }
707 } elseif ( 'site-transient' === $cache_mode ) {
708 if ( true === $key ) {
709 $wpdb->query(
710 $wpdb->prepare(
711 "DELETE FROM `{$wpdb->options}` WHERE `option_name` LIKE %s",
712 '_site_transient_' . $wpdb->esc_like( $group_key ) . '%'
713 )
714 );
715
716 if ( $object_cache_enabled ) {
717 if ( $group && function_exists( 'wp_cache_flush_group' ) && wp_cache_supports( 'flush_group' ) ) {
718 wp_cache_flush_group( $group );
719 } else {
720 wp_cache_flush();
721 }
722 }
723
724 self::reset_cached_keys( $cache_mode );
725 } else {
726 delete_site_transient( $group_key . $key );
727
728 self::remove_cached_key( $cache_mode, $group_key . $key );
729 }
730 } elseif ( 'cache' === $cache_mode && $object_cache_enabled ) {
731 if ( true === $key ) {
732 if ( $group && function_exists( 'wp_cache_flush_group' ) && wp_cache_supports( 'flush_group' ) ) {
733 wp_cache_flush_group( $group );
734
735 self::reset_cached_keys( $cache_mode, $group );
736 } else {
737 wp_cache_flush();
738
739 self::reset_cached_keys( $cache_mode );
740 }
741 } else {
742 $group = ( empty( $group ) ? 'pods_view' : $group );
743 $key = ( empty( $key ) ? 'pods_view' : $key );
744
745 wp_cache_delete( $key, $group );
746
747 self::remove_cached_key( $cache_mode, $key, $group );
748 }
749 } elseif ( 'option-cache' === $cache_mode ) {
750 do_action( "delete_transient_{$key}", $key ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
751
752 $group = ( empty( $group ) ? 'pods_option_cache' : $group );
753
754 if ( $external_object_cache ) {
755 $result = wp_cache_delete( $key, $group );
756
757 wp_cache_delete( '_timeout_' . $key, $group );
758 } else {
759 $option_timeout = '_pods_option_timeout_' . $key;
760 $option = '_pods_option_' . $key;
761
762 $result = delete_option( $option );
763
764 if ( $result ) {
765 delete_option( $option_timeout );
766 }
767 }
768
769 self::remove_cached_key( $cache_mode, $key, $group );
770
771 if ( $result ) {
772 do_action( 'deleted_transient', $key ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
773 }
774 } elseif ( 'static-cache' === $cache_mode ) {
775 $static_cache = pods_container( Static_Cache::class );
776
777 if ( $static_cache ) {
778 $group = ( empty( $group ) ? __CLASS__ : $group );
779
780 if ( true === $key ) {
781 $static_cache->flush( $group );
782
783 self::reset_cached_keys( $cache_mode, $group );
784 } else {
785 $static_cache->delete( $key, $group );
786
787 self::remove_cached_key( $cache_mode, $key, $group );
788 }
789 }
790 }//end if
791
792 do_action( "pods_view_clear_{$cache_mode}", $original_key, $group );
793
794 return true;
795 }
796
797 /**
798 * @static
799 *
800 * @param $_view
801 * @param null|array $_data
802 * @param bool $limited (optional) Whether to limit the view to only the theme directory, defaults to false
803 *
804 * @return bool|mixed|string|void
805 */
806 public static function get_template_part( $_view, $_data = null, $limited = false ) {
807
808 /*
809 To be reviewed later, should have more checks and restrictions like a whitelist etc.
810
811 if ( 0 === strpos( $_view, 'http://' ) || 0 === strpos( $_view, 'https://' ) ) {
812 $_view = apply_filters( 'pods_view_url_include', $_view );
813
814 if ( empty( $_view ) || ( defined( 'PODS_REMOTE_VIEWS' ) && PODS_REMOTE_VIEWS ) )
815 return '';
816
817 $response = wp_remote_get( $_view );
818
819 return wp_remote_retrieve_body( $response );
820 }
821 */
822
823 $_view = self::locate_template( $_view, $limited );
824
825 if ( empty( $_view ) ) {
826 return $_view;
827 }
828
829 if ( ! empty( $_data ) && is_array( $_data ) ) {
830 extract( $_data, EXTR_SKIP );
831 }
832
833 ob_start();
834 require $_view;
835 $output = ob_get_clean();
836
837 return $output;
838 }
839
840 /**
841 * @static
842 *
843 * @param array|string $_view
844 * @param bool $limited (optional) Whether to limit the view to only the theme directory, defaults to false
845 *
846 * @return bool|mixed|string|void
847 */
848 private static function locate_template( $_view, $limited = false ) {
849 if ( is_array( $_view ) ) {
850 $_views = [];
851
852 if ( isset( $_view[0] ) && false === strpos( (string) $_view[0], '.php' ) ) {
853 $_view_count = count( $_view );
854
855 for ( $_view_x = $_view_count; 0 < $_view_x; $_view_x -- ) {
856 $_view_v = array_slice( $_view, 0, $_view_x );
857
858 $_views[] = implode( '-', $_view_v ) . '.php';
859 }
860 } else {
861 $_views = $_view;
862 }
863
864 $_view = false;
865
866 foreach ( $_views as $_view_check ) {
867 $_view = self::locate_template( $_view_check );
868
869 if ( ! empty( $_view ) ) {
870 break;
871 }
872 }
873
874 return $_view;
875 }//end if
876
877 $paths_to_check = [ 'plugins', 'pods', 'theme' ];
878
879 if ( $limited ) {
880 $paths_to_check = [ 'theme' ];
881 }
882
883 // Is the view's file somewhere within the plugin directory tree?
884 // Note: we include PODS_DIR for the case of symlinks (see issue #2945).
885 $located = pods_validate_safe_path( $_view, $paths_to_check );
886
887 /**
888 * Allow filtering the validated view file path to use.
889 *
890 * @since unknown
891 *
892 * @param string|false $located The validated view file path to use, or false if it was not valid.
893 * @param string $_view The original view file path to use.
894 */
895 $located = apply_filters( 'pods_view_locate_template', $located, $_view );
896
897 if ( ! $located ) {
898 return false;
899 }
900
901 return $located;
902
903 }
904
905 /**
906 * Advanced $expires handling
907 *
908 * @param array|bool|int $expires
909 * @param string $cache_mode
910 *
911 * @return bool|int
912 *
913 * @since 2.7.0
914 * @static
915 */
916 public static function expires( $expires, $cache_mode = 'cache' ) {
917
918 // Different $expires if user is anonymous or logged in or specific capability
919 if ( is_array( $expires ) ) {
920 if ( ( isset( $expires['anonymous'] ) || isset( $expires['user_with_access'] ) ) && isset( $expires['user'] ) ) {
921 if ( isset( $expires['user_with_access'] ) ) {
922 $expires = array(
923 pods_v( 'anonymous', $expires, false ),
924 pods_v( 'user', $expires, false ),
925 pods_v( 'user_with_access', $expires, false ),
926 pods_v( 'capability', $expires, null, null, true ),
927 );
928 } elseif ( isset( $expires['anonymous'] ) ) {
929 $expires = array(
930 pods_v( 'anonymous', $expires, false ),
931 pods_v( 'user', $expires, false ),
932 pods_v( 'capability', $expires, null, null, true ),
933 );
934 }
935 } else {
936 $expires = array_values( $expires );
937 }
938
939 if ( 4 === count( $expires ) ) {
940 if ( ! is_user_logged_in() ) {
941 $expires = pods_v( 0, $expires, false );
942 } else {
943 $user_no_access = pods_v( 1, $expires, false );
944 $user_with_access = pods_v( 2, $expires, false );
945 $capability = pods_v( 3, $expires, null, true );
946
947 $expires = pods_var_user( $user_no_access, $user_with_access, $capability );
948 }
949 } else {
950 $anon = pods_v( 0, $expires, false );
951 $user = pods_v( 1, $expires, false );
952 $capability = pods_v( 2, $expires, null, true );
953
954 $expires = pods_var_user( $anon, $user, $capability );
955 }
956 }//end if
957
958 if ( 'none' === $cache_mode ) {
959 $expires = false;
960 } elseif ( false !== $expires ) {
961 $expires = (int) $expires;
962
963 if ( $expires < 1 ) {
964 $expires = 0;
965 }
966 }
967
968 return $expires;
969
970 }
971
972 /**
973 * Determine whether the cache mode is valid.
974 *
975 * @since 2.9.14
976 *
977 * @param string|mixed $cache_mode The cache mode.
978 *
979 * @return bool Whether the cache mode is valid.
980 */
981 public static function is_cache_mode_valid( $cache_mode ) {
982 return (
983 $cache_mode
984 && is_string( $cache_mode )
985 && isset( self::$cache_modes[ $cache_mode ] )
986 );
987 }
988
989 }
990