/classes/PodsView.php

https://github.com/ElmsPark/pods · PHP · 364 lines · 191 code · 80 blank · 93 comment · 67 complexity · 1120d8d6d0727948d38e7cc11175cf57 MD5 · raw file

  1. <?php
  2. /**
  3. * @package Pods
  4. */
  5. class PodsView {
  6. /**
  7. * @var array $cache_modes Array of available cache modes
  8. */
  9. static $cache_modes = array( 'none', 'transient', 'site-transient', 'cache' );
  10. /**
  11. *
  12. */
  13. private function __construct () {
  14. }
  15. /**
  16. * @static
  17. *
  18. * @param string $view Path of the view file
  19. * @param array|null $data (optional) Data to pass on to the template
  20. * @param bool|int|array $expires (optional) Time in seconds for the cache to expire, if 0 caching is disabled.
  21. * @param string $cache_mode (optional) Decides the caching method to use for the view.
  22. *
  23. * @return bool|mixed|null|string|void
  24. *
  25. * @since 2.0.0
  26. */
  27. public static function view ( $view, $data = null, $expires = false, $cache_mode = 'cache' ) {
  28. // Different $expires if user is anonymous or logged in or specific capability
  29. if ( is_array( $expires ) ) {
  30. $anon = pods_var_raw( 0, $expires, false );
  31. $user = pods_var_raw( 1, $expires, false );
  32. $capability = pods_var_raw( 2, $expires, null, null, true );
  33. $expires = pods_var_user( $anon, $user, $capability );
  34. }
  35. if ( 'none' == $cache_mode )
  36. $expires = false;
  37. if ( false !== $expires && empty( $expires ) )
  38. $expires = 0;
  39. if ( !in_array( $cache_mode, self::$cache_modes ) )
  40. $cache_mode = 'cache';
  41. $view_key = $view;
  42. if ( is_array( $view_key ) )
  43. $view_key = implode( '-', $view_key ) . '.php';
  44. $cache_key = sanitize_title( pods_str_replace( array( PODS_DIR . 'ui/', PODS_DIR . 'components/', ABSPATH, WP_CONTENT_DIR, '.php' ), array( 'ui-', 'ui-', 'custom-', 'custom-', '' ), $view_key, 1 ) );
  45. $view = apply_filters( 'pods_view_inc_' . $cache_key, $view, $data, $expires, $cache_mode );
  46. $view_key = $view;
  47. if ( is_array( $view_key ) )
  48. $view_key = implode( '-', $view_key ) . '.php';
  49. if ( false === strpos( $view_key, PODS_DIR . 'ui/' ) && false === strpos( $view_key, PODS_DIR . 'components/' ) && false === strpos( $view_key, WP_CONTENT_DIR ) && false === strpos( $view_key, ABSPATH ) ) {
  50. $output = self::get( 'pods-view-' . $cache_key, $cache_mode, 'pods_view' );
  51. if ( false !== $output && null !== $output ) {
  52. if ( false !== $expires )
  53. return $output;
  54. else
  55. self::clear( 'pods-view-' . $cache_key, $cache_mode, 'pods_view' );
  56. }
  57. }
  58. $output = self::get_template_part( $view, $data );
  59. if ( false === $output )
  60. return false;
  61. if ( false !== $expires )
  62. self::set( 'pods-view-' . $cache_key, $output, $expires, $cache_mode, 'pods_view' );
  63. $output = apply_filters( 'pods_view_output_' . $cache_key, $output, $view, $data, $expires, $cache_mode );
  64. $output = apply_filters( 'pods_view_output', $output, $view, $data, $expires, $cache_mode );
  65. return $output;
  66. }
  67. /**
  68. * @static
  69. *
  70. * @param string $key Key for the cache
  71. * @param string $cache_mode (optional) Decides the caching method to use for the view.
  72. * @param string $group (optional) Set the group of the value.
  73. *
  74. * @return bool|mixed|null|void
  75. *
  76. * @since 2.0.0
  77. */
  78. public static function get ( $key, $cache_mode = 'cache', $group = '' ) {
  79. $object_cache = false;
  80. if ( isset( $GLOBALS[ 'wp_object_cache' ] ) && is_object( $GLOBALS[ 'wp_object_cache' ] ) )
  81. $object_cache = true;
  82. if ( !in_array( $cache_mode, self::$cache_modes ) )
  83. $cache_mode = 'cache';
  84. $group_key = '';
  85. if ( !empty( $group ) )
  86. $group_key = $group . '_';
  87. $original_key = $key;
  88. // Patch for limitations in DB
  89. if ( 44 < strlen( $group_key . $key ) ) {
  90. $key = md5( $key );
  91. if ( empty( $group_key ) )
  92. $group_key = 'pods_';
  93. }
  94. $value = null;
  95. if ( 'transient' == $cache_mode )
  96. $value = get_transient( $group_key . $key );
  97. elseif ( 'site-transient' == $cache_mode )
  98. $value = get_site_transient( $group_key . $key );
  99. elseif ( 'cache' == $cache_mode && $object_cache )
  100. $value = wp_cache_get( $key, ( empty( $group ) ? 'pods_view' : $group ) );
  101. $value = apply_filters( 'pods_view_get_' . $cache_mode, $value, $original_key, $group );
  102. return $value;
  103. }
  104. /**
  105. * @static
  106. *
  107. * Set a cached value
  108. *
  109. * @param string $key Key for the cache
  110. * @param mixed $value Value to add to the cache
  111. * @param int $expires (optional) Time in seconds for the cache to expire, if 0 caching is disabled.
  112. * @param string $cache_mode (optional) Decides the caching method to use for the view.
  113. * @param string $group (optional) Set the group of the value.
  114. *
  115. * @return bool|mixed|null|string|void
  116. *
  117. * @since 2.0.0
  118. */
  119. public static function set ( $key, $value, $expires = 0, $cache_mode = null, $group = '' ) {
  120. $object_cache = false;
  121. if ( isset( $GLOBALS[ 'wp_object_cache' ] ) && is_object( $GLOBALS[ 'wp_object_cache' ] ) )
  122. $object_cache = true;
  123. if ( (int) $expires < 1 )
  124. $expires = 0;
  125. if ( !in_array( $cache_mode, self::$cache_modes ) )
  126. $cache_mode = 'cache';
  127. $group_key = '';
  128. if ( !empty( $group ) )
  129. $group_key = $group . '_';
  130. $original_key = $key;
  131. // Patch for limitations in DB
  132. if ( 44 < strlen( $group_key . $key ) ) {
  133. $key = md5( $key );
  134. if ( empty( $group_key ) )
  135. $group_key = 'pods_';
  136. }
  137. if ( 'transient' == $cache_mode )
  138. set_transient( $group_key . $key, $value, $expires );
  139. elseif ( 'site-transient' == $cache_mode )
  140. set_site_transient( $group_key . $key, $value, $expires );
  141. elseif ( 'cache' == $cache_mode && $object_cache )
  142. wp_cache_set( $key, $value, ( empty( $group ) ? 'pods_view' : $group ), $expires );
  143. do_action( 'pods_view_set_' . $cache_mode, $original_key, $value, $expires, $group );
  144. return $value;
  145. }
  146. /**
  147. * @static
  148. *
  149. * Clear a cached value
  150. *
  151. * @param string|bool $key Key for the cache
  152. * @param string $cache_mode (optional) Decides the caching method to use for the view.
  153. * @param string $group (optional) Set the group.
  154. *
  155. * @return bool
  156. *
  157. * @since 2.0.0
  158. */
  159. public static function clear ( $key = true, $cache_mode = null, $group = '' ) {
  160. $object_cache = false;
  161. if ( isset( $GLOBALS[ 'wp_object_cache' ] ) && is_object( $GLOBALS[ 'wp_object_cache' ] ) )
  162. $object_cache = true;
  163. global $wpdb;
  164. if ( !in_array( $cache_mode, self::$cache_modes ) )
  165. $cache_mode = 'cache';
  166. $group_key = '';
  167. if ( !empty( $group ) )
  168. $group_key = $group . '_';
  169. $original_key = $key;
  170. // Patch for limitations in DB
  171. if ( 44 < strlen( $group_key . $key ) ) {
  172. $key = md5( $key );
  173. if ( empty( $group_key ) )
  174. $group_key = 'pods_';
  175. }
  176. if ( 'transient' == $cache_mode ) {
  177. if ( true === $key ) {
  178. $wpdb->query( "DELETE FROM `{$wpdb->options}` WHERE option_name LIKE '_transient_{$group_key}%'" );
  179. if ( $object_cache )
  180. wp_cache_flush();
  181. }
  182. else
  183. delete_transient( $group_key . $key );
  184. }
  185. elseif ( 'site-transient' == $cache_mode ) {
  186. if ( true === $key ) {
  187. $wpdb->query( "DELETE FROM `{$wpdb->options}` WHERE option_name LIKE '_site_transient_{$group_key}%'" );
  188. if ( $object_cache )
  189. wp_cache_flush();
  190. }
  191. else
  192. delete_site_transient( $group_key . $key );
  193. }
  194. elseif ( 'cache' == $cache_mode && $object_cache ) {
  195. if ( true === $key )
  196. wp_cache_flush();
  197. else
  198. wp_cache_delete( ( empty( $key ) ? 'pods_view' : $key ), 'pods_view' );
  199. }
  200. do_action( 'pods_view_clear_' . $cache_mode, $original_key, $group );
  201. return true;
  202. }
  203. /**
  204. * @static
  205. *
  206. * @param $_view
  207. * @param null|array $_data
  208. *
  209. * @return bool|mixed|string|void
  210. */
  211. private static function get_template_part ( $_view, $_data = null ) {
  212. /* to be reviewed later, should have more checks and restrictions like a whitelist etc
  213. if ( 0 === strpos( $_view, 'http://' ) || 0 === strpos( $_view, 'https://' ) ) {
  214. $_view = apply_filters( 'pods_view_url_include', $_view );
  215. if ( empty( $_view ) || ( defined( 'PODS_REMOTE_VIEWS' ) && PODS_REMOTE_VIEWS ) )
  216. return '';
  217. $response = wp_remote_get( $_view );
  218. return wp_remote_retrieve_body( $response );
  219. }*/
  220. $_view = self::locate_template( $_view );
  221. if ( empty( $_view ) )
  222. return $_view;
  223. if ( !empty( $_data ) && is_array( $_data ) )
  224. extract( $_data, EXTR_SKIP );
  225. ob_start();
  226. require $_view;
  227. $output = ob_get_clean();
  228. return $output;
  229. }
  230. /**
  231. * @static
  232. *
  233. * @param $_view
  234. *
  235. * @return bool|mixed|string|void
  236. */
  237. private static function locate_template ( $_view ) {
  238. if ( is_array( $_view ) ) {
  239. $_views = array();
  240. $_view_count = count( $_view );
  241. for ( $_view_x = $_view_count; 0 < $_view_x; $_view_x-- ) {
  242. $_view_v = array_slice( $_view, 0, $_view_x );
  243. $_views[] = implode( '-', $_view_v ) . '.php';
  244. }
  245. $_view = false;
  246. foreach ( $_views as $_view_check ) {
  247. $_view = self::locate_template( $_view_check );
  248. if ( !empty( $_view ) )
  249. break;
  250. }
  251. return $_view;
  252. }
  253. // Keep it safe
  254. $_view = trim( str_replace( array( '../', '\\' ), array( '', '/' ), (string) $_view ) );
  255. $_view = preg_replace( '/\/+/', '/', $_view );
  256. $located = false;
  257. if ( empty( $_view ) )
  258. return false;
  259. // Look for basic file includes
  260. elseif ( false === strpos( $_view, realpath( WP_PLUGIN_DIR ) ) && false === strpos( $_view, realpath( WPMU_PLUGIN_DIR ) ) ) {
  261. $_view = rtrim( $_view, '/' );
  262. if ( empty( $_view ) )
  263. return false;
  264. if ( file_exists( STYLESHEETPATH . '/' . $_view ) )
  265. $located = STYLESHEETPATH . '/' . $_view;
  266. elseif ( file_exists( TEMPLATEPATH . '/' . $_view ) )
  267. $located = TEMPLATEPATH . '/' . $_view;
  268. }
  269. // Allow includes within plugins directory too for plugins utilizing this
  270. elseif ( file_exists( $_view ) )
  271. $located = $_view;
  272. else
  273. $located = apply_filters( 'pods_view_locate_template', $located, $_view );
  274. return $located;
  275. }
  276. private static function filter_callback ( $value ) {
  277. if ( in_array( $value, array( '', null, false ) ) )
  278. return false;
  279. return true;
  280. }
  281. }