MyHelper.php 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. <?php
  2. App::uses('Helper', 'View');
  3. App::uses('Router', 'Routing');
  4. App::uses('UrlCacheManager', 'Tools.Routing');
  5. /**
  6. * Helper enhancements for CakePHP
  7. *
  8. * @author Mark Scherer
  9. * @license MIT
  10. */
  11. class MyHelper extends Helper {
  12. public function __construct($View = null, $settings = array()) {
  13. if (class_exists('Packages')) {
  14. Packages::initialize($this, __CLASS__);
  15. }
  16. parent::__construct($View, $settings);
  17. }
  18. /**
  19. * Manually load helpers
  20. *
  21. * @param array $helpers (either strings, or [string => array(config...)])
  22. * @param boolean $callbacks - trigger missed callbacks
  23. * @return void
  24. */
  25. public function loadHelpers($helpers = array(), $callbacks = false) {
  26. foreach ((array)$helpers as $helper => $config) {
  27. if (is_int($helper)) {
  28. $helper = $config;
  29. $config = array();
  30. }
  31. list($plugin, $helperName) = pluginSplit($helper, true);
  32. if (isset($this->{$helperName})) {
  33. continue;
  34. }
  35. App::uses($helperName . 'Helper', $plugin . 'View/Helper');
  36. $helperFullName = $helperName . 'Helper';
  37. $this->{$helperName} = new $helperFullName($this->_View, (array)$config);
  38. if ($callbacks) {
  39. if (method_exists($helper, 'beforeRender')) {
  40. $this->{$helperName}->beforeRender();
  41. }
  42. }
  43. }
  44. }
  45. /**
  46. * //TODO: remove
  47. * Not a very good solution, as it takes a lot of resources, file lookups.
  48. *
  49. * Problems: what if inside plugin webroot? not easy to do...
  50. */
  51. public function imageIfExists($path, $options = array(), $default = '---') {
  52. if (startsWith($path, '/')) {
  53. /*
  54. $completePath = Router::url($path);
  55. //echo (returns(file_exists($completePath)));
  56. //die($completePath);
  57. # problem with plugin files!!! needs "webroot" added after plugin name
  58. if (!file_exists($completePath)) {
  59. return $default;
  60. }
  61. */
  62. } else {
  63. $completePath = Router::url($path);
  64. }
  65. if (!empty($completePath) && !file_exists($completePath)) {
  66. return $default;
  67. }
  68. return $this->image($path, $options);
  69. }
  70. /**
  71. * Display image tag from blob content.
  72. * Enhancement for HtmlHelper. Defaults to png image
  73. *
  74. * Options:
  75. * - type: png, gif, jpg, ...
  76. *
  77. * @param binary $content
  78. * @param array $options
  79. * @return string html imageTag
  80. */
  81. public function imageFromBlob($content, $options = array()) {
  82. $options += array('type' => 'png');
  83. $mimeType = 'image/' . $options['type'];
  84. $text = 'data:' . $mimeType . ';base64,' . base64_encode($content);
  85. return sprintf($this->_tags['image'], $text, $this->_parseAttributes($options, null, '', ' '));
  86. }
  87. /**
  88. * HTML Helper extension for HTML5 time
  89. * The time element represents either a time on a 24 hour clock,
  90. * or a precise date in the proleptic Gregorian calendar,
  91. * optionally with a time and a time-zone offset.
  92. *
  93. * Options:
  94. * - 'format' STRING: Use the specified TimeHelper method (or format()).
  95. * FALSE: Generate the datetime. NULL: Do nothing.
  96. * - 'datetime' STRING: If 'format' is STRING use as the formatting string.
  97. * FALSE: Don't generate attribute
  98. *
  99. * @param $content string Time
  100. * @param $options array Options
  101. * @return string HTML time tag.
  102. */
  103. public function time($content, $options = array()) {
  104. if (!isset($this->tags['time'])) {
  105. $this->tags['time'] = '<time%s>%s</time>';
  106. }
  107. $options = array_merge(array(
  108. 'datetime' => '%Y-%m-%d %T',
  109. 'pubdate' => false,
  110. 'format' => '%Y-%m-%d %T',
  111. ), $options);
  112. if ($options['format'] !== null) {
  113. if (!isset($this->Time)) {
  114. App::uses('TimeHelper', 'View/Helper');
  115. $this->Time = new TimeHelper($this->_View);
  116. }
  117. }
  118. if ($options['format']) {
  119. if (method_exists($this->Time, $options['format'])) {
  120. $content = $this->Time->$options['format']($content);
  121. } else {
  122. $content = $this->Time->i18nFormat($content, $options['format']);
  123. }
  124. $options['datetime'] = $this->Time->i18nFormat(strtotime($content), $options['datetime']);
  125. } elseif ($options['format'] === false && $options['datetime']) {
  126. $options['datetime'] = $this->Time->i18nFormat(strtotime($content), $options['datetime']);
  127. }
  128. if ($options['pubdate']) {
  129. $pubdate = true;
  130. }
  131. unset($options['format']);
  132. unset($options['pubdate']);
  133. $attributes = $this->_parseAttributes($options, array(0), ' ', '');
  134. if (isset($pubdate)) {
  135. $attributes .= ' pubdate';
  136. }
  137. return sprintf($this->tags['time'], $attributes, $content);
  138. }
  139. /**
  140. * For convenience functions Html::defaultLink() and defaultUrl().
  141. *
  142. * @var array
  143. */
  144. protected $_linkDefaults = null;
  145. /**
  146. * Keep named and query params for pagination/filter after edit etc.
  147. *
  148. * @params same as Html::link($title, $url, $options, $confirmMessage)
  149. * @return string Link
  150. */
  151. public function completeLink($title, $url = null, $options = array(), $confirmMessage = false) {
  152. // Named are deprecated
  153. if (is_array($url)) {
  154. $url += $this->params['named'];
  155. }
  156. if (is_array($url)) {
  157. if (!isset($url['?'])) {
  158. $url['?'] = array();
  159. }
  160. $url['?'] += $this->request->query;
  161. }
  162. return $this->link($title, $url, $options, $confirmMessage);
  163. }
  164. /**
  165. * Keep named and query params for pagination/filter after edit etc.
  166. *
  167. * @params same as Html::url($url, $options, $escape)
  168. * @return string Link
  169. */
  170. public function completeUrl($url = null, $full = false, $escape = true) {
  171. // Named are deprecated
  172. if (is_array($url)) {
  173. $url += $this->params['named'];
  174. }
  175. if (is_array($url)) {
  176. if (!isset($url['?'])) {
  177. $url['?'] = array();
  178. }
  179. $url['?'] += $this->request->query;
  180. }
  181. return $this->url($url, $options, $escape);
  182. }
  183. /**
  184. * Convenience function for normal links.
  185. * Useful for layout links and links inside elements etc if you don't want to
  186. * verbosely reset all parts of it (prefix, plugin, ...).
  187. *
  188. * @params same as Html::link($title, $url, $options, $confirmMessage)
  189. * @return string HTML Link
  190. */
  191. public function defaultLink($title, $url = null, $options = array(), $confirmMessage = false) {
  192. if ($this->_linkDefaults === null) {
  193. if (!class_exists('CommonComponent')) {
  194. App::uses('CommonComponent', 'Tools.Controller/Component');
  195. }
  196. $this->_linkDefaults = CommonComponent::defaultUrlParams();
  197. }
  198. if (!defined('PREFIX_ADMIN')) {
  199. define('PREFIX_ADMIN', 'admin');
  200. }
  201. if ($url !== null && is_array($url)) {
  202. $url = array_merge($this->_linkDefaults, $url);
  203. if (!empty($url[PREFIX_ADMIN])) {
  204. $options['rel'] = 'nofollow';
  205. }
  206. } elseif (is_array($title)) {
  207. $title = array_merge($this->_linkDefaults, $title);
  208. if (!empty($title[PREFIX_ADMIN])) {
  209. $options['rel'] = 'nofollow';
  210. }
  211. }
  212. //$this->log($url, '404');
  213. return $this->link($title, $url, $options, $confirmMessage);
  214. }
  215. /**
  216. * Convenience function for normal urls.
  217. * Useful for layout links and links inside elements etc if you don't want to
  218. * verbosely reset all parts of it (prefix, plugin, ...).
  219. *
  220. * @params same as Html::url($url, $full)
  221. * @return string URL
  222. */
  223. public function defaultUrl($url = null, $full = false) {
  224. if ($this->_linkDefaults === null) {
  225. if (!class_exists('CommonComponent')) {
  226. App::uses('CommonComponent', 'Tools.Controller/Component');
  227. }
  228. $this->_linkDefaults = CommonComponent::defaultUrlParams();
  229. }
  230. if ($url !== null && is_array($url)) {
  231. $url = array_merge($this->_linkDefaults, $url);
  232. }
  233. return $this->url($url, $full);
  234. }
  235. /**
  236. * Enhancement to htmlHelper which allows the crumbs protected array
  237. * to be cleared so that more than one set of crumbs can be generated in the same view.
  238. *
  239. * @return void
  240. */
  241. public function resetCrumbs() {
  242. $this->_crumbs = array();
  243. }
  244. /**
  245. * This function is responsible for setting up the Url cache before the application starts generating urls in views
  246. *
  247. * @return void
  248. */
  249. public function beforeRender($viewFile) {
  250. if (!Configure::read('UrlCache.active') || Configure::read('UrlCache.runtime.beforeRender')) {
  251. return;
  252. }
  253. # todo: maybe lazy load with HtmlHelper::url()?
  254. UrlCacheManager::init($this->_View);
  255. Configure::write('UrlCache.runtime.beforeRender', true);
  256. }
  257. /**
  258. * This method will store the current generated urls into a persistent cache for next use
  259. *
  260. * @return void
  261. */
  262. public function afterLayout($layoutFile) {
  263. if (!Configure::read('UrlCache.active') || Configure::read('UrlCache.runtime.afterLayout')) {
  264. return;
  265. }
  266. UrlCacheManager::finalize();
  267. Configure::write('UrlCache.runtime.afterLayout', true);
  268. }
  269. /**
  270. * Intercepts the parent url function to first look if the cache was already generated for the same params
  271. *
  272. * @param mixed $url url to generate using cakephp array syntax
  273. * @param boolean|array $full whether to generate a full url or not (http scheme). As array: full, escape.
  274. * @return string
  275. * @see Helper::url()
  276. */
  277. public function url($url = null, $full = false) {
  278. if (is_array($full)) {
  279. $escape = isset($full['ecape']) ? $full['escape'] : true;
  280. $full = isset($full['full']) ? $full['full'] : false;
  281. } else {
  282. $escape = true;
  283. }
  284. if (Configure::read('UrlCache.active')) {
  285. if ($cachedUrl = UrlCacheManager::get($url, $full)) {
  286. return $cachedUrl;
  287. }
  288. }
  289. if (!$escape) {
  290. $routerUrl = Router::url($url, $full);
  291. } else {
  292. $routerUrl = parent::url($url, $full);
  293. }
  294. if (Configure::read('UrlCache.active')) {
  295. UrlCacheManager::set($routerUrl);
  296. }
  297. return $routerUrl;
  298. }
  299. }