/src/Snowcap/SiteBundle/Twig/Extension/CoreExtension.php

https://github.com/herdani/snowcap-website · PHP · 218 lines · 119 code · 33 blank · 66 comment · 19 complexity · 2be7654614b18ecd470bb83cf178b35b MD5 · raw file

  1. <?php
  2. namespace Snowcap\SiteBundle\Twig\Extension;
  3. class CoreExtension extends \Twig_Extension
  4. {
  5. /**
  6. * Get all available functions
  7. *
  8. * @return array
  9. */
  10. public function getFunctions()
  11. {
  12. return array(
  13. 'is_menu_active' => new \Twig_Function_Method($this, 'isMenuActive'),
  14. );
  15. }
  16. /**
  17. * Get all available filters
  18. *
  19. * @return array
  20. */
  21. public function getFilters()
  22. {
  23. return array(
  24. 'time_ago' => new \Twig_Filter_Method($this, 'timeAgo'),
  25. 'age' => new \Twig_Filter_Method($this, 'age'),
  26. 'safe_truncate' => new \Twig_Filter_Method($this, 'safeTruncate', array('is_safe' => array('html'))),
  27. 'parse_tweet' => new \Twig_Filter_Method($this, 'parseTweet', array('is_safe' => array('html'))),
  28. 'hr_columns' => new \Twig_Filter_Method($this, 'hrColumns', array('is_safe' => array('html'))),
  29. );
  30. }
  31. /**
  32. * Filter used to get a date interval between a date and now
  33. *
  34. * @param string|DateTime $datetime
  35. * @return \DateInterval
  36. */
  37. public function relativeTime($datetime = null, $format = 'ago')
  38. {
  39. if ($datetime === null) {
  40. return "";
  41. }
  42. if (is_string($datetime)) {
  43. $datetime = new \DateTime($datetime);
  44. }
  45. $current_date = new \DateTime();
  46. $interval = $current_date->diff($datetime);
  47. return $interval;
  48. }
  49. /**
  50. * Filter used to display the time ago for a specific date
  51. *
  52. * @param \Datetime|string $datetime
  53. * @return string
  54. */
  55. public function timeAgo($datetime) {
  56. $interval = $this->relativeTime($datetime);
  57. $years = $interval->format('%y');
  58. $months = $interval->format('%m');
  59. $days = $interval->format('%d');
  60. if ($years != 0) {
  61. $ago = $years . ' year(s) ago';
  62. } else {
  63. $ago = ($months == 0 ? $days . ' day(s) ago' : $months . ' month(s) ago');
  64. }
  65. return $ago;
  66. }
  67. /**
  68. * @param \Datetime|string $datetime
  69. * @return string
  70. */
  71. public function age($datetime) {
  72. $interval = $this->relativeTime($datetime);
  73. return $interval->format('%y');
  74. }
  75. /**
  76. * Filter used to safely truncate a string with html
  77. * @param string $value
  78. * @param int $length
  79. * @param bool $preserve
  80. * @param string $separator
  81. * @return string
  82. */
  83. public function safeTruncate($value, $length = 30, $preserve = true, $separator = ' ...')
  84. {
  85. if (strlen($value) > $length) {
  86. if ($preserve) {
  87. if (false !== ($breakpoint = strpos($value, ' ', $length))) {
  88. $length = $breakpoint;
  89. }
  90. }
  91. return $this->closetags(substr($value, 0, $length) . $separator);
  92. }
  93. return $value;
  94. }
  95. /**
  96. * Helper used to close html tags
  97. *
  98. * @param string $html
  99. * @return string
  100. */
  101. private function closetags($html)
  102. {
  103. preg_match_all('#<([a-z]+)(?: .*)?(?<![/|/ ])>#iU', $html, $result);
  104. $openedtags = $result[1]; #put all closed tags into an array
  105. preg_match_all('#</([a-z]+)>#iU', $html, $result);
  106. $closedtags = $result[1];
  107. $len_opened = count($openedtags);
  108. if (count($closedtags) == $len_opened) {
  109. return $html;
  110. }
  111. $openedtags = array_reverse($openedtags);
  112. for ($i = 0; $i < $len_opened; $i++) {
  113. if (!in_array($openedtags[$i], $closedtags)) {
  114. $html .= '</' . $openedtags[$i] . '>';
  115. } else {
  116. unset($closedtags[array_search($openedtags[$i], $closedtags)]);
  117. }
  118. }
  119. return $html;
  120. }
  121. /**
  122. * Return true if the menu should be active
  123. * @param string $activeController
  124. * @param string $controller
  125. * @param string $action
  126. * @return bool
  127. */
  128. public function isMenuActive($activeController, $controller, $action = null)
  129. {
  130. preg_match('/\\\([^\\\]+)Controller/', $activeController, $matches);
  131. $activeControllerName = $matches[1];
  132. if ($action !== null) {
  133. preg_match('/::([^::]+)Action/', $activeController, $matches);
  134. $activeActionName = $matches[1];
  135. return $controller == $activeControllerName && $action == $activeActionName;
  136. }
  137. return $controller == $activeControllerName;
  138. }
  139. /**
  140. * Parses tweets to make links to URL's, people and hashtags
  141. * @param string $tweet
  142. * @return string
  143. */
  144. public function parseTweet($tweet)
  145. {
  146. // links
  147. $tweet = preg_replace_callback(
  148. '/[a-z]+:\/\/[a-z0-9-_]+\.[a-z0-9-_:~%&\?\+#\/.=]+[^:\.,\)\s*$]/i',
  149. function($tweet) { return '<a href="'.$tweet[0].'">'.((strlen($tweet[0]) > 25) ? substr($tweet[0], 0, 24).'...' : $tweet[0]).'</a>'; },
  150. $tweet);
  151. // people
  152. $tweet = preg_replace_callback(
  153. '/(^|[^\w]+)\@([a-zA-Z0-9_]{1,15}(\/[a-zA-Z0-9-_]+)*)/',
  154. function($tweet) { return $tweet[1].'<a href="http://twitter.com/'.$tweet[2].'">@'.$tweet[2].'</a>'; },
  155. $tweet);
  156. // hashtags
  157. $tweet = preg_replace_callback(
  158. "/(^|[^&\w'\"]+)\#([a-zA-Z0-9_]+)/",
  159. function($tweet) { return $tweet[1].'#<a href="http://search.twitter.com/search?q=%23'.$tweet[2].'">'.$tweet[2].'</a>'; },
  160. $tweet);
  161. return $tweet;
  162. }
  163. /**
  164. * Converts <hr> tag to <div> column style
  165. *
  166. * @param string $content
  167. * @return string
  168. */
  169. public function hrColumns($content)
  170. {
  171. $content = '<div class="column">' .
  172. str_replace(array('<hr>', '<hr/>', '<hr />'), '</div><div class="column">', $content) .
  173. '</div>';
  174. return $content;
  175. }
  176. /**
  177. * Return the name of the extension
  178. *
  179. * @return string
  180. */
  181. public function getName()
  182. {
  183. return 'SnowcapSiteBundle';
  184. }
  185. }