PageRenderTime 49ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/plugins/timber-library/lib/Helper.php

https://bitbucket.org/nikolaswise/fuel
PHP | 458 lines | 190 code | 42 blank | 226 comment | 42 complexity | a91735d6aa2b4bae87567f1cca72242f MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause, GPL-3.0
  1. <?php
  2. namespace Timber;
  3. use Timber\FunctionWrapper;
  4. use Timber\URLHelper;
  5. /**
  6. * As the name suggests these are helpers for Timber (and you!) when developing. You can find additional (mainly internally-focused helpers) in TimberURLHelper
  7. */
  8. class Helper {
  9. /**
  10. * A utility for a one-stop shop for Transients
  11. * @api
  12. * @example
  13. * ```php
  14. * $context = Timber::get_context();
  15. * $context['favorites'] = Timber\Helper::transient('user-' .$uid. '-favorites', function() use ($uid) {
  16. * //some expensive query here that's doing something you want to store to a transient
  17. * return $favorites;
  18. * }, 600);
  19. * Timber::render('single.twig', $context);
  20. * ```
  21. *
  22. * @param string $slug Unique identifier for transient
  23. * @param callable $callback Callback that generates the data that's to be cached
  24. * @param integer $transient_time (optional) Expiration of transients in seconds
  25. * @param integer $lock_timeout (optional) How long (in seconds) to lock the transient to prevent race conditions
  26. * @param boolean $force (optional) Force callback to be executed when transient is locked
  27. * @return mixed
  28. */
  29. public static function transient( $slug, $callback, $transient_time = 0, $lock_timeout = 5, $force = false ) {
  30. $slug = apply_filters('timber/transient/slug', $slug);
  31. $enable_transients = ($transient_time === false || (defined('WP_DISABLE_TRANSIENTS') && WP_DISABLE_TRANSIENTS)) ? false : true;
  32. $data = $enable_transients ? get_transient($slug) : false;
  33. if ( false === $data ) {
  34. $data = self::handle_transient_locking($slug, $callback, $transient_time, $lock_timeout, $force, $enable_transients);
  35. }
  36. return $data;
  37. }
  38. /**
  39. * Does the dirty work of locking the transient, running the callback and unlocking
  40. * @param string $slug
  41. * @param callable $callback
  42. * @param integer $transient_time Expiration of transients in seconds
  43. * @param integer $lock_timeout How long (in seconds) to lock the transient to prevent race conditions
  44. * @param boolean $force Force callback to be executed when transient is locked
  45. * @param boolean $enable_transients Force callback to be executed when transient is locked
  46. */
  47. protected static function handle_transient_locking( $slug, $callback, $transient_time, $lock_timeout, $force, $enable_transients ) {
  48. if ( $enable_transients && self::_is_transient_locked($slug) ) {
  49. $force = apply_filters('timber_force_transients', $force);
  50. $force = apply_filters('timber_force_transient_'.$slug, $force);
  51. if ( !$force ) {
  52. //the server is currently executing the process.
  53. //We're just gonna dump these users. Sorry!
  54. return false;
  55. }
  56. $enable_transients = false;
  57. }
  58. // lock timeout shouldn't be higher than 5 seconds, unless
  59. // remote calls with high timeouts are made here
  60. if ( $enable_transients ) {
  61. self::_lock_transient($slug, $lock_timeout);
  62. }
  63. $data = $callback();
  64. if ( $enable_transients ) {
  65. set_transient($slug, $data, $transient_time);
  66. self::_unlock_transient($slug);
  67. }
  68. return $data;
  69. }
  70. /**
  71. * @internal
  72. * @param string $slug
  73. * @param integer $lock_timeout
  74. */
  75. public static function _lock_transient( $slug, $lock_timeout ) {
  76. set_transient($slug.'_lock', true, $lock_timeout);
  77. }
  78. /**
  79. * @internal
  80. * @param string $slug
  81. */
  82. public static function _unlock_transient( $slug ) {
  83. delete_transient($slug.'_lock', true);
  84. }
  85. /**
  86. * @internal
  87. * @param string $slug
  88. */
  89. public static function _is_transient_locked( $slug ) {
  90. return (bool) get_transient($slug.'_lock');
  91. }
  92. /* These are for measuring page render time */
  93. /**
  94. * For measuring time, this will start a timer
  95. * @api
  96. * @return float
  97. */
  98. public static function start_timer() {
  99. $time = microtime();
  100. $time = explode(' ', $time);
  101. $time = $time[1] + $time[0];
  102. return $time;
  103. }
  104. /**
  105. * For stopping time and getting the data
  106. * @example
  107. * ```php
  108. * $start = TimberHelper::start_timer();
  109. * // do some stuff that takes awhile
  110. * echo TimberHelper::stop_timer( $start );
  111. * ```
  112. * @param int $start
  113. * @return string
  114. */
  115. public static function stop_timer( $start ) {
  116. $time = microtime();
  117. $time = explode(' ', $time);
  118. $time = $time[1] + $time[0];
  119. $finish = $time;
  120. $total_time = round(($finish - $start), 4);
  121. return $total_time.' seconds.';
  122. }
  123. /* Function Utilities
  124. ======================== */
  125. /**
  126. * Calls a function with an output buffer. This is useful if you have a function that outputs text that you want to capture and use within a twig template.
  127. * @example
  128. * ```php
  129. * function the_form() {
  130. * echo '<form action="form.php"><input type="text" /><input type="submit /></form>';
  131. * }
  132. *
  133. * $context = Timber::get_context();
  134. * $context['post'] = new TimberPost();
  135. * $context['my_form'] = TimberHelper::ob_function('the_form');
  136. * Timber::render('single-form.twig', $context);
  137. * ```
  138. * ```twig
  139. * <h1>{{ post.title }}</h1>
  140. * {{ my_form }}
  141. * ```
  142. * ```html
  143. * <h1>Apply to my contest!</h1>
  144. * <form action="form.php"><input type="text" /><input type="submit /></form>
  145. * ```
  146. * @api
  147. * @param callback $function
  148. * @param array $args
  149. * @return string
  150. */
  151. public static function ob_function( $function, $args = array(null) ) {
  152. ob_start();
  153. call_user_func_array($function, $args);
  154. $data = ob_get_contents();
  155. ob_end_clean();
  156. return $data;
  157. }
  158. /**
  159. * @deprecated since 1.3.0
  160. *
  161. * @param mixed $function_name String or array( $class( string|object ), $function_name ).
  162. * @param array $defaults Optional.
  163. * @param bool $return_output_buffer Optional. Return function output instead of return value. Default false.
  164. * @return FunctionWrapper|mixed
  165. */
  166. public static function function_wrapper( $function_name, $defaults = array(), $return_output_buffer = false ) {
  167. Helper::warn( 'function_wrapper is deprecated and will be removed in 1.4. Use {{ function( \'function_to_call\' ) }} instead or use FunctionWrapper directly. For more information refer to https://timber.github.io/docs/guides/functions/' );
  168. return new FunctionWrapper( $function_name, $defaults, $return_output_buffer );
  169. }
  170. /**
  171. *
  172. *
  173. * @param mixed $arg that you want to error_log
  174. * @return void
  175. */
  176. public static function error_log( $error ) {
  177. global $timber_disable_error_log;
  178. if ( !WP_DEBUG || $timber_disable_error_log ) {
  179. return;
  180. }
  181. if ( is_object($error) || is_array($error) ) {
  182. $error = print_r($error, true);
  183. }
  184. return error_log($error);
  185. }
  186. /**
  187. * @param string $message that you want to output
  188. * @return boolean
  189. */
  190. public static function warn( $message ) {
  191. return trigger_error($message, E_USER_WARNING);
  192. }
  193. /**
  194. *
  195. *
  196. * @param string $separator
  197. * @param string $seplocation
  198. * @return string
  199. */
  200. public static function get_wp_title( $separator = ' ', $seplocation = 'left' ) {
  201. $separator = apply_filters('timber_wp_title_seperator', $separator);
  202. return trim(wp_title($separator, false, $seplocation));
  203. }
  204. /* Text Utitilites */
  205. /* Object Utilities
  206. ======================== */
  207. /**
  208. * @codeCoverageIgnore
  209. * @deprecated since 1.2.0
  210. * @see TextHelper::trim_words
  211. * @param string $text
  212. * @param int $num_words
  213. * @param string|null|false $more text to appear in "Read more...". Null to use default, false to hide
  214. * @param string $allowed_tags
  215. * @return string
  216. */
  217. public static function trim_words( $text, $num_words = 55, $more = null, $allowed_tags = 'p a span b i br blockquote' ) {
  218. return TextHelper::trim_words($text, $num_words, $more, $allowed_tags);
  219. }
  220. /**
  221. * @deprecated since 1.2.0
  222. * @see TextHelper::close_tags
  223. * @param string $html
  224. * @return string
  225. */
  226. public static function close_tags( $html ) {
  227. return TextHelper::close_tags($html);
  228. }
  229. /**
  230. *
  231. *
  232. * @param array $array
  233. * @param string $prop
  234. * @return void
  235. */
  236. public static function osort( &$array, $prop ) {
  237. usort($array, function( $a, $b ) use ($prop) {
  238. return $a->$prop > $b->$prop ? 1 : -1;
  239. } );
  240. }
  241. /**
  242. *
  243. *
  244. * @param array $arr
  245. * @return bool
  246. */
  247. public static function is_array_assoc( $arr ) {
  248. if ( !is_array($arr) ) {
  249. return false;
  250. }
  251. return (bool) count(array_filter(array_keys($arr), 'is_string'));
  252. }
  253. /**
  254. *
  255. *
  256. * @param array $array
  257. * @return \stdClass
  258. */
  259. public static function array_to_object( $array ) {
  260. $obj = new \stdClass;
  261. foreach ( $array as $k => $v ) {
  262. if ( is_array($v) ) {
  263. $obj->{$k} = self::array_to_object($v); //RECURSION
  264. } else {
  265. $obj->{$k} = $v;
  266. }
  267. }
  268. return $obj;
  269. }
  270. /**
  271. *
  272. *
  273. * @param array $array
  274. * @param string $key
  275. * @param mixed $value
  276. * @return bool|int
  277. */
  278. public static function get_object_index_by_property( $array, $key, $value ) {
  279. if ( is_array($array) ) {
  280. $i = 0;
  281. foreach ( $array as $arr ) {
  282. if ( is_array($arr) ) {
  283. if ( $arr[$key] == $value ) {
  284. return $i;
  285. }
  286. } else {
  287. if ( $arr->$key == $value ) {
  288. return $i;
  289. }
  290. }
  291. $i++;
  292. }
  293. }
  294. return false;
  295. }
  296. /**
  297. *
  298. *
  299. * @param array $array
  300. * @param string $key
  301. * @param mixed $value
  302. * @return array|null
  303. * @throws Exception
  304. */
  305. public static function get_object_by_property( $array, $key, $value ) {
  306. if ( is_array($array) ) {
  307. foreach ( $array as $arr ) {
  308. if ( $arr->$key == $value ) {
  309. return $arr;
  310. }
  311. }
  312. return false;
  313. }
  314. throw new \InvalidArgumentException('$array is not an array, got:');
  315. Helper::error_log($array);
  316. }
  317. /**
  318. *
  319. *
  320. * @param array $array
  321. * @param int $len
  322. * @return array
  323. */
  324. public static function array_truncate( $array, $len ) {
  325. if ( sizeof($array) > $len ) {
  326. $array = array_splice($array, 0, $len);
  327. }
  328. return $array;
  329. }
  330. /* Bool Utilities
  331. ======================== */
  332. /**
  333. *
  334. *
  335. * @param mixed $value
  336. * @return bool
  337. */
  338. public static function is_true( $value ) {
  339. if ( isset($value) ) {
  340. if ( is_string($value) ) {
  341. $value = strtolower($value);
  342. }
  343. if ( ($value == 'true' || $value === 1 || $value === '1' || $value == true) && $value !== false && $value !== 'false' ) {
  344. return true;
  345. }
  346. }
  347. return false;
  348. }
  349. /**
  350. *
  351. *
  352. * @param int $i
  353. * @return bool
  354. */
  355. public static function iseven( $i ) {
  356. return ($i % 2) == 0;
  357. }
  358. /**
  359. *
  360. *
  361. * @param int $i
  362. * @return bool
  363. */
  364. public static function isodd( $i ) {
  365. return ($i % 2) != 0;
  366. }
  367. /**
  368. * Plucks the values of a certain key from an array of objects
  369. * @param array $array
  370. * @param string $key
  371. */
  372. public static function pluck( $array, $key ) {
  373. $return = array();
  374. foreach ( $array as $obj ) {
  375. if ( is_object($obj) && method_exists($obj, $key) ) {
  376. $return[] = $obj->$key();
  377. } elseif ( is_object($obj) && property_exists($obj, $key) ) {
  378. $return[] = $obj->$key;
  379. } elseif ( is_array($obj) && isset($obj[$key]) ) {
  380. $return[] = $obj[$key];
  381. }
  382. }
  383. return $return;
  384. }
  385. /* Links, Forms, Etc. Utilities
  386. ======================== */
  387. /**
  388. *
  389. * Gets the comment form for use on a single article page
  390. * @deprecated 0.21.8 use `{{ function('comment_form') }}` instead
  391. * @param int $post_id which post_id should the form be tied to?
  392. * @param array $args this $args thing is a fucking mess, [fix at some point](http://codex.wordpress.org/Function_Reference/comment_form)
  393. * @return string
  394. */
  395. public static function get_comment_form( $post_id = null, $args = array() ) {
  396. return self::ob_function('comment_form', array($args, $post_id));
  397. }
  398. /**
  399. * @codeCoverageIgnore
  400. * @deprecated since 1.1.2
  401. * @param array $args
  402. * @return array
  403. */
  404. public static function paginate_links( $args = array() ) {
  405. Helper::warn('Helper/paginate_links has been moved to Pagination/paginate_links');
  406. return Pagination::paginate_links($args);
  407. }
  408. /**
  409. * @codeCoverageIgnore
  410. * @return string
  411. */
  412. public function get_current_url() {
  413. Helper::warn('TimberHelper::get_current_url() is deprecated and will be removed in future versions, use Timber\URLHelper::get_current_url()');
  414. return URLHelper::get_current_url();
  415. }
  416. }