PageRenderTime 25ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/timber-twig.php

https://gitlab.com/aristath/timber
PHP | 374 lines | 256 code | 32 blank | 86 comment | 31 complexity | e464a4f2952f2076a4896b54856a8ab7 MD5 | raw file
  1. <?php
  2. class TimberTwig {
  3. public static $dir_name;
  4. /**
  5. * @codeCoverageIgnore
  6. */
  7. public static function init() {
  8. new TimberTwig();
  9. }
  10. /**
  11. * @codeCoverageIgnore
  12. */
  13. function __construct() {
  14. add_action( 'timber/twig/filters', array( $this, 'add_timber_filters_deprecated' ) );
  15. add_action( 'timber/twig/filters', array( $this, 'add_timber_filters' ) );
  16. }
  17. /**
  18. * These are all deprecated and will be removed in 0.21.0
  19. *
  20. * @param Twig_Environment $twig
  21. * @deprecated since 0.20.7
  22. * @return Twig_Environment
  23. */
  24. function add_timber_filters_deprecated( $twig ) {
  25. $twig->addFilter( new Twig_SimpleFilter( 'get_src_from_attachment_id', 'twig_get_src_from_attachment_id' ) );
  26. $twig->addFilter( new Twig_SimpleFilter( 'wp_body_class', array( $this, 'body_class' ) ) );
  27. $twig->addFilter( new Twig_SimpleFilter( 'twitterify', array( 'TimberHelper', 'twitterify' ) ) );
  28. $twig->addFilter( new Twig_SimpleFilter( 'twitterfy', array( 'TimberHelper', 'twitterify' ) ) );
  29. $twig->addFilter( new Twig_SimpleFilter( 'string', function($arr, $glue = ' '){
  30. return twig_join_filter($arr, $glue);
  31. } ) );
  32. return $twig;
  33. }
  34. /**
  35. *
  36. *
  37. * @param Twig_Environment $twig
  38. * @return Twig_Environment
  39. */
  40. function add_timber_filters( $twig ) {
  41. /* image filters */
  42. $twig->addFilter( new Twig_SimpleFilter( 'resize', array( 'TimberImageHelper', 'resize' ) ) );
  43. $twig->addFilter( new Twig_SimpleFilter( 'retina', array( 'TimberImageHelper', 'retina_resize' ) ) );
  44. $twig->addFilter( new Twig_SimpleFilter( 'letterbox', array( 'TimberImageHelper', 'letterbox' ) ) );
  45. $twig->addFilter( new Twig_SimpleFilter( 'tojpg', array( 'TimberImageHelper', 'img_to_jpg' ) ) );
  46. /* debugging filters */
  47. $twig->addFilter( new Twig_SimpleFilter( 'docs', 'twig_object_docs' ) );
  48. $twig->addFilter( new Twig_SimpleFilter( 'get_class', 'get_class' ) );
  49. $twig->addFilter( new Twig_SimpleFilter( 'get_type', 'get_type' ) );
  50. $twig->addFilter( new Twig_SimpleFilter( 'print_r', function( $arr ) {
  51. return print_r( $arr, true );
  52. } ) );
  53. $twig->addFilter( new Twig_SimpleFilter( 'print_a', function( $arr ) {
  54. return '<pre>' . self::object_docs( $arr, true ) . '</pre>';
  55. } ) );
  56. /* other filters */
  57. $twig->addFilter( new Twig_SimpleFilter( 'stripshortcodes', 'strip_shortcodes' ) );
  58. $twig->addFilter( new Twig_SimpleFilter( 'array', array( $this, 'to_array' ) ) );
  59. $twig->addFilter( new Twig_SimpleFilter( 'excerpt', 'wp_trim_words' ) );
  60. $twig->addFilter( new Twig_SimpleFilter( 'function', array( $this, 'exec_function' ) ) );
  61. $twig->addFilter( new Twig_SimpleFilter( 'pretags', array( $this, 'twig_pretags' ) ) );
  62. $twig->addFilter( new Twig_SimpleFilter( 'sanitize', 'sanitize_title' ) );
  63. $twig->addFilter( new Twig_SimpleFilter( 'shortcodes', 'do_shortcode' ) );
  64. $twig->addFilter( new Twig_SimpleFilter( 'time_ago', array( $this, 'time_ago' ) ) );
  65. $twig->addFilter( new Twig_SimpleFilter( 'wpautop', 'wpautop' ) );
  66. $twig->addFilter( new Twig_SimpleFilter( 'list', array( $this, 'add_list_separators' ) ) );
  67. $twig->addFilter( new Twig_SimpleFilter( 'relative', function ( $link ) {
  68. return TimberURLHelper::get_rel_url( $link, true );
  69. } ) );
  70. $twig->addFilter( new Twig_SimpleFilter( 'date', array( $this, 'intl_date' ) ) );
  71. $twig->addFilter( new Twig_SimpleFilter( 'truncate', function ( $text, $len ) {
  72. return TimberHelper::trim_words( $text, $len );
  73. } ) );
  74. /* actions and filters */
  75. $twig->addFunction( new Twig_SimpleFunction( 'action', function ( $context ) {
  76. $args = func_get_args();
  77. array_shift( $args );
  78. $args[] = $context;
  79. call_user_func_array( 'do_action', $args );
  80. }, array( 'needs_context' => true ) ) );
  81. $twig->addFilter( new Twig_SimpleFilter( 'apply_filters', function () {
  82. $args = func_get_args();
  83. $tag = current( array_splice( $args, 1, 1 ) );
  84. return apply_filters_ref_array( $tag, $args );
  85. } ) );
  86. $twig->addFunction( new Twig_SimpleFunction( 'function', array( &$this, 'exec_function' ) ) );
  87. $twig->addFunction( new Twig_SimpleFunction( 'fn', array( &$this, 'exec_function' ) ) );
  88. $twig->addFunction( new Twig_SimpleFunction( 'shortcode', 'do_shortcode' ) );
  89. /* TimberObjects */
  90. $twig->addFunction( new Twig_SimpleFunction( 'TimberPost', function ( $pid, $PostClass = 'TimberPost' ) {
  91. if ( is_array( $pid ) && !TimberHelper::is_array_assoc( $pid ) ) {
  92. foreach ( $pid as &$p ) {
  93. $p = new $PostClass( $p );
  94. }
  95. return $pid;
  96. }
  97. return new $PostClass( $pid );
  98. } ) );
  99. $twig->addFunction( new Twig_SimpleFunction( 'TimberImage', function ( $pid = false, $ImageClass = 'TimberImage' ) {
  100. if ( is_array( $pid ) && !TimberHelper::is_array_assoc( $pid ) ) {
  101. foreach ( $pid as &$p ) {
  102. $p = new $ImageClass( $p );
  103. }
  104. return $pid;
  105. }
  106. return new $ImageClass( $pid );
  107. } ) );
  108. $twig->addFunction( new Twig_SimpleFunction( 'TimberTerm', function ( $pid, $TermClass = 'TimberTerm' ) {
  109. if ( is_array( $pid ) && !TimberHelper::is_array_assoc( $pid ) ) {
  110. foreach ( $pid as &$p ) {
  111. $p = new $TermClass( $p );
  112. }
  113. return $pid;
  114. }
  115. return new $TermClass( $pid );
  116. } ) );
  117. $twig->addFunction( new Twig_SimpleFunction( 'TimberUser', function ( $pid, $UserClass = 'TimberUser' ) {
  118. if ( is_array( $pid ) && !TimberHelper::is_array_assoc( $pid ) ) {
  119. foreach ( $pid as &$p ) {
  120. $p = new $UserClass( $p );
  121. }
  122. return $pid;
  123. }
  124. return new $UserClass( $pid );
  125. } ) );
  126. /* TimberObjects Alias */
  127. $twig->addFunction( new Twig_SimpleFunction( 'Post', function ( $pid, $PostClass = 'TimberPost' ) {
  128. if ( is_array( $pid ) && !TimberHelper::is_array_assoc( $pid ) ) {
  129. foreach ( $pid as &$p ) {
  130. $p = new $PostClass( $p );
  131. }
  132. return $pid;
  133. }
  134. return new $PostClass( $pid );
  135. } ) );
  136. $twig->addFunction( new Twig_SimpleFunction( 'Image', function ( $pid, $ImageClass = 'TimberImage' ) {
  137. if ( is_array( $pid ) && !TimberHelper::is_array_assoc( $pid ) ) {
  138. foreach ( $pid as &$p ) {
  139. $p = new $ImageClass( $p );
  140. }
  141. return $pid;
  142. }
  143. return new $ImageClass( $pid );
  144. } ) );
  145. $twig->addFunction( new Twig_SimpleFunction( 'Term', function ( $pid, $TermClass = 'TimberTerm' ) {
  146. if ( is_array( $pid ) && !TimberHelper::is_array_assoc( $pid ) ) {
  147. foreach ( $pid as &$p ) {
  148. $p = new $TermClass( $p );
  149. }
  150. return $pid;
  151. }
  152. return new $TermClass( $pid );
  153. } ) );
  154. $twig->addFunction( new Twig_SimpleFunction( 'User', function ( $pid, $UserClass = 'TimberUser' ) {
  155. if ( is_array( $pid ) && !TimberHelper::is_array_assoc( $pid ) ) {
  156. foreach ( $pid as &$p ) {
  157. $p = new $UserClass( $p );
  158. }
  159. return $pid;
  160. }
  161. return new $UserClass( $pid );
  162. } ) );
  163. /* bloginfo and translate */
  164. $twig->addFunction( 'bloginfo', new Twig_SimpleFunction( 'bloginfo', function ( $show = '', $filter = 'raw' ) {
  165. return get_bloginfo( $show, $filter );
  166. } ) );
  167. $twig->addFunction( '__', new Twig_SimpleFunction( '__', function ( $text, $domain = 'default' ) {
  168. return __( $text, $domain );
  169. } ) );
  170. $twig->addFunction( 'translate', new Twig_SimpleFunction( 'translate', function ( $text, $domain = 'default' ) {
  171. return translate( $text, $domain );
  172. } ) );
  173. $twig->addFunction( '_e', new Twig_SimpleFunction( '_e', function ( $text, $domain = 'default' ) {
  174. return _e( $text, $domain );
  175. } ) );
  176. $twig->addFunction( '_n', new Twig_SimpleFunction( '_n', function ( $single, $plural, $number, $domain = 'default' ) {
  177. return _n( $single, $plural, $number, $domain );
  178. } ) );
  179. $twig->addFunction( '_x', new Twig_SimpleFunction( '_x', function ( $text, $context, $domain = 'default' ) {
  180. return _x( $text, $context, $domain );
  181. } ) );
  182. $twig->addFunction( '_ex', new Twig_SimpleFunction( '_ex', function ( $text, $context, $domain = 'default' ) {
  183. return _ex( $text, $context, $domain );
  184. } ) );
  185. $twig->addFunction( '_nx', new Twig_SimpleFunction( '_nx', function ( $single, $plural, $number, $context, $domain = 'default' ) {
  186. return _nx( $single, $plural, $number, $context, $domain );
  187. } ) );
  188. $twig->addFunction( '_n_noop', new Twig_SimpleFunction( '_n_noop', function ( $singular, $plural, $domain = 'default' ) {
  189. return _n_noop( $singular, $plural, $domain );
  190. } ) );
  191. $twig->addFunction( '_nx_noop', new Twig_SimpleFunction( '_nx_noop', function ( $singular, $plural, $context, $domain = 'default' ) {
  192. return _nx_noop( $singular, $plural, $context, $domain );
  193. } ) );
  194. $twig->addFunction( 'translate_nooped_plural', new Twig_SimpleFunction( 'translate_nooped_plural', function ( $nooped_plural, $count, $domain = 'default' ) {
  195. return translate_nooped_plural( $nooped_plural, $count, $domain );
  196. } ) );
  197. /* get_twig is deprecated, use timber/twig */
  198. $twig = apply_filters( 'get_twig', $twig );
  199. $twig = apply_filters( 'timber/twig', $twig );
  200. return $twig;
  201. }
  202. /**
  203. *
  204. *
  205. * @param mixed $arr
  206. * @return array
  207. */
  208. function to_array( $arr ) {
  209. if ( is_array( $arr ) ) {
  210. return $arr;
  211. }
  212. $arr = array( $arr );
  213. return $arr;
  214. }
  215. /**
  216. *
  217. *
  218. * @param string $function_name
  219. * @return mixed
  220. */
  221. function exec_function( $function_name ) {
  222. $args = func_get_args();
  223. array_shift( $args );
  224. if ( is_string($function_name) ) {
  225. $function_name = trim( $function_name );
  226. }
  227. return call_user_func_array( $function_name, ( $args ) );
  228. }
  229. /**
  230. *
  231. *
  232. * @param string $content
  233. * @return string
  234. */
  235. function twig_pretags( $content ) {
  236. return preg_replace_callback( '|<pre.*>(.*)</pre|isU', array( &$this, 'convert_pre_entities' ), $content );
  237. }
  238. /**
  239. *
  240. *
  241. * @param array $matches
  242. * @return string
  243. */
  244. function convert_pre_entities( $matches ) {
  245. return str_replace( $matches[1], htmlentities( $matches[1] ), $matches[0] );
  246. }
  247. /**
  248. * @param mixed $body_classes
  249. * @deprecated 0.20.7
  250. * @return string
  251. */
  252. function body_class( $body_classes ) {
  253. ob_start();
  254. if ( is_array( $body_classes ) ) {
  255. $body_classes = explode( ' ', $body_classes );
  256. }
  257. body_class( $body_classes );
  258. $return = ob_get_contents();
  259. ob_end_clean();
  260. return $return;
  261. }
  262. /**
  263. *
  264. *
  265. * @param string $date
  266. * @param string $format (optional)
  267. * @return string
  268. */
  269. function intl_date( $date, $format = null ) {
  270. if ( $format === null ) {
  271. $format = get_option( 'date_format' );
  272. }
  273. if ( $date instanceof DateTime ) {
  274. $timestamp = $date->getTimestamp() + $date->getOffset();
  275. } else if (is_numeric( $date ) && strtotime( $date ) === false ) {
  276. $timestamp = intval( $date );
  277. } else {
  278. $timestamp = strtotime( $date );
  279. }
  280. return date_i18n( $format, $timestamp );
  281. }
  282. //debug
  283. /**
  284. *
  285. *
  286. * @param mixed $obj
  287. * @param bool $methods
  288. * @deprecated since 0.20.7
  289. * @return string
  290. */
  291. function object_docs( $obj, $methods = true ) {
  292. $class = get_class( $obj );
  293. $properties = (array)$obj;
  294. if ( $methods ) {
  295. /** @var array $methods */
  296. $methods = $obj->get_method_values();
  297. }
  298. $rets = array_merge( $properties, $methods );
  299. ksort( $rets );
  300. $str = print_r( $rets, true );
  301. $str = str_replace( 'Array', $class . ' Object', $str );
  302. return $str;
  303. }
  304. /**
  305. * @param int|string $from
  306. * @param int|string $to
  307. * @param string $format_past
  308. * @param string $format_future
  309. * @return string
  310. */
  311. function time_ago( $from, $to = null, $format_past = '%s ago', $format_future = '%s from now' ) {
  312. $to = $to === null ? time() : $to;
  313. $to = is_int( $to ) ? $to : strtotime( $to );
  314. $from = is_int( $from ) ? $from : strtotime( $from );
  315. if ( $from < $to ) {
  316. return sprintf( $format_past, human_time_diff( $from, $to ) );
  317. } else {
  318. return sprintf( $format_future, human_time_diff( $to, $from ) );
  319. }
  320. }
  321. /**
  322. * @param array $arr
  323. * @param string $first_delimiter
  324. * @param string $second_delimiter
  325. * @return string
  326. */
  327. function add_list_separators( $arr, $first_delimiter = ',', $second_delimiter = 'and' ) {
  328. $length = count( $arr );
  329. $list = '';
  330. foreach( $arr as $index => $item ) {
  331. if ( $index < $length - 2 ) {
  332. $delimiter = $first_delimiter.' ';
  333. } elseif ( $index == $length - 2 ) {
  334. $delimiter = ' '.$second_delimiter.' ';
  335. } else {
  336. $delimiter = '';
  337. }
  338. $list = $list.$item.$delimiter;
  339. }
  340. return $list;
  341. }
  342. }