PageRenderTime 26ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 0ms

/Cake/views/haml.php

https://github.com/ChrisCinelli/phamlp
PHP | 287 lines | 102 code | 16 blank | 169 comment | 21 complexity | 7334b384b6564abe4554e333ba1d31f5 MD5 | raw file
  1. <?php
  2. /**
  3. * Haml view renderer class file.
  4. * Renders {@link http://haml-lang.com/ HAML} view files using
  5. * {@link http://phamlp.googlecode.com PHamlP}.
  6. * Please see the {@link documentation http://haml-lang.com/docs/yardoc/file.HAML_REFERENCE.html#plain_text HAML} for the syntax.
  7. *
  8. * * To use the Haml view renderer:
  9. * * Put {@link http://phamlp.googlecode.com PHamlP} in your vendors directory
  10. * * Put this file in your views directory
  11. * * Configure the view and HamlParser using
  12. * <pre>Configure::write('Haml.<optionName>', <optionValue>);</pre>
  13. * See below and HamlParser for a description of options
  14. * * Add the following line in your app_controller.php
  15. * <pre>var $view = 'Haml';</pre>
  16. * * Create .haml views in your view folders
  17. *
  18. * By default the parsed views (.ctp files) are cached under
  19. * <pre>APP.tmp.haml</pre>
  20. *
  21. * @author Chris Yates <chris.l.yates@gmail.com>
  22. * @copyright Copyright &copy; 2010 PBM Web Development
  23. * @license http://phamlp.googlecode.com/files/license.txt
  24. * @package PHamlP
  25. * @subpackage Cake
  26. */
  27. /**
  28. * Haml allows you to write view files in {@link Haml http://haml-lang.com/} and
  29. * render them using {@link http://phamlp.googlecode.com PHamlP}.
  30. *
  31. * If a .haml view is not found a .ctp or .thtml view is used.
  32. * @package PHamlP
  33. * @subpackage Cake
  34. */
  35. class HamlView extends View {
  36. /**#@+
  37. * Configurable Options
  38. */
  39. /**
  40. * @var string the extension name of the view file. Defaults to '.haml'.
  41. */
  42. var $ext;
  43. /**
  44. * @var boolean whether to use Cake's cache directory. If false the view file
  45. * is created in the view directory. Defaults to true.
  46. */
  47. var $useCachePath;
  48. /**
  49. * @var integer the chmod permission for temporary directories and files
  50. * generated during parsing. Defaults to 0755 (owner rwx, group rx and others rx).
  51. */
  52. var $filePermission;
  53. /**
  54. * @var boolean whether to cache parsed files. If false files will be parsed
  55. * every time.
  56. */
  57. var $cache;
  58. /**
  59. * @var array default option values.
  60. */
  61. var $defaults = array('ext'=>'.haml','useCachePath'=>true,'filePermission'=>0755,'cache'=>true);
  62. /**#@-*/
  63. /**
  64. * @var HamlParser the Haml parser
  65. */
  66. private $haml;
  67. /**
  68. * @var array Haml parser option names. These are passed to the parser if set.
  69. *
  70. * format: string DOCTYPE format
  71. *
  72. * doctype: string custom doctype. If null (default) {@link format} must be
  73. * a key in {@link doctypes}
  74. *
  75. * escapeHtml: boolean whether or not to escape X(HT)ML-sensitive characters
  76. * in script. If this is true, = behaves like &=; otherwise, it behaves like
  77. * !=. Note that if this is set, != should be used for yielding to
  78. * subtemplates and rendering partials.
  79. * Defaults to false.
  80. *
  81. * suppressEval: boolean Whether or not attribute hashes and scripts
  82. * designated by = or ~ should be evaluated. If true, the scripts are rendered
  83. * as empty strings.
  84. * Defaults to false.
  85. *
  86. * attrWrapper: string The character that should wrap element attributes.
  87. * Characters of this type within attributes will be escaped (e.g. by
  88. * replacing them with &apos;) if the character is an apostrophe or a
  89. * quotation mark.
  90. * Defaults to " (an quotation mark).
  91. *
  92. * style: string style of output. Can be:
  93. * nested: output is nested according to the indent level in the source
  94. * expanded: block tags have their own lines as does content which is indented
  95. * compact: block tags and their content go on one line
  96. * compressed: all unneccessary whitepaces is removed. If ugly is true this
  97. * style is used.
  98. *
  99. * ugly: boolean if true no attempt is made to properly indent or format
  100. * the output. Reduces size of output file but is not very readable.
  101. * Defaults to true.
  102. *
  103. * preserveComments: boolean if true comments are preserved in ugly mode.
  104. * If not in ugly mode comments are always output.
  105. * Defaults to false.
  106. *
  107. * debug: integer Initial debug setting:
  108. * no debug, show source, show output, or show all.
  109. * Debug settings can be controlled in the template
  110. * Defaults to DEBUG_NONE.
  111. *
  112. * filterDir: string Path to filters. If specified this will be searched
  113. * first followed by 'vendors.phmlp.haml.filters'.
  114. * This allows the default filters to be overridden.
  115. *
  116. * doctypes: array supported doctypes
  117. * See HamlRender for default
  118. *
  119. * emptyTags: array A list of tag names that should be automatically
  120. * self-closed if they have no content.
  121. * See HamlRender for default
  122. *
  123. * inlineTags: array A list of inline tags for which whitespace is not collapsed
  124. * fully when in ugly mode or stripping outer whitespace.
  125. * See HamlRender for default
  126. *
  127. * minimizedAttributes: array attributes that are minimised.
  128. * See HamlRender for default
  129. *
  130. * preserve: array A list of tag names that should automatically have their
  131. * newlines preserved.
  132. */
  133. var $hamlOptions = array('format', 'doctype', 'escapeHtml', 'suppressEval', 'attrWrapper', 'style', 'ugly', 'preserveComments', 'debug', 'filterDir', 'doctypes', 'emptyTags', 'inlineTags', 'minimizedAttributes', 'preserve', 'helperFile');
  134. /**
  135. * Initialises HamlView.
  136. * @param Controller $controller
  137. * @return HamlView
  138. */
  139. function __construct(&$controller) {
  140. parent::__construct($controller);
  141. foreach ($this->defaults as $key=>$value) {
  142. $option = Configure::read("Haml.$key");
  143. $this->$key = (is_null($option)?$value:$option);
  144. } // foreach
  145. }
  146. /**
  147. * Do a sanity check on the options and setup alias to filters
  148. */
  149. private function _init() {
  150. $options = array();
  151. foreach ($this->hamlOptions as $option) {
  152. $_option = Configure::read("Haml.$option");
  153. if (!is_null($_option)) {
  154. $options[$option] = $_option;
  155. }
  156. } // foreach
  157. App::import('Vendor', 'HamlParser', array('file'=>'phamlp'.DS.'haml'.DS.'HamlParser.php'));
  158. $this->haml = new HamlParser($options);
  159. }
  160. /**
  161. * Renders a piece of PHP with provided parameters and returns HTML, XML, or
  162. * any other string.
  163. *
  164. * This realizes the concept of Elements, (or "partial layouts")
  165. * and the $params array is used to send data to be used in the
  166. * Element. Elements can be cached through use of the cache key.
  167. *
  168. * Overrides View::element() to provide fallback to .ctp elements.
  169. *
  170. * @param string $name Name of template file in the/app/views/elements/ folder
  171. * @param array $params Array of data to be made available to the for rendered
  172. * view (i.e. the Element)
  173. * Special params:
  174. * cache - enable caching for this element accepts boolean or strtotime
  175. * compatible string.
  176. * Can also be an array. If an array,'time' is used to specify duration of the
  177. * cache.
  178. * 'key' can be used to create unique cache files.
  179. * @return string Rendered Element
  180. * @access public
  181. */
  182. function element($name, $params = array(), $loadHelpers = false) {
  183. $file = $plugin = $key = null;
  184. if (isset($params['plugin'])) {
  185. $plugin = $params['plugin'];
  186. }
  187. if (isset($this->plugin) && !$plugin) {
  188. $plugin = $this->plugin;
  189. }
  190. if (isset($params['cache'])) {
  191. $expires = '+1 day';
  192. if (is_array($params['cache'])) {
  193. $expires = $params['cache']['time'];
  194. $key = Inflector::slug($params['cache']['key']);
  195. } elseif ($params['cache'] !== true) {
  196. $expires = $params['cache'];
  197. $key = implode('_', array_keys($params));
  198. }
  199. if ($expires) {
  200. $cacheFile = 'element_' . $key . '_' . $plugin . Inflector::slug($name);
  201. $cache = cache('views' . DS . $cacheFile, null, $expires);
  202. if (is_string($cache)) {
  203. return $cache;
  204. }
  205. }
  206. }
  207. $paths = $this->_paths($plugin);
  208. foreach ($paths as $path) {
  209. if (file_exists($path . 'elements' . DS . $name . $this->ext)) {
  210. $file = $path . 'elements' . DS . $name . $this->ext;
  211. break;
  212. } elseif (file_exists($path . 'elements' . DS . $name . '.ctp')) {
  213. $file = $path . 'elements' . DS . $name . '.ctp';
  214. break;
  215. } elseif (file_exists($path . 'elements' . DS . $name . '.thtml')) {
  216. $file = $path . 'elements' . DS . $name . '.thtml';
  217. break;
  218. }
  219. }
  220. if (is_file($file)) {
  221. $params = array_merge_recursive($params, $this->loaded);
  222. $element = $this->_render($file, array_merge($this->viewVars, $params), $loadHelpers);
  223. if (isset($params['cache']) && isset($cacheFile) && isset($expires)) {
  224. cache('views' . DS . $cacheFile, $element, $expires);
  225. }
  226. return $element;
  227. }
  228. $file = $paths[0] . 'elements' . DS . $name . $this->ext;
  229. if (Configure::read() > 0) {
  230. return "Not Found: " . $file;
  231. }
  232. }
  233. /**
  234. * Renders and returns output for given view filename with its
  235. * array of data.
  236. *
  237. * @param string Filename of the view
  238. * @param array Data to include in rendered view
  239. * @return string Rendered output
  240. * @access protected
  241. */
  242. function _render($___viewFn, $___dataForView, $loadHelpers = true, $cached = false) {
  243. if (substr($___viewFn, strrpos($___viewFn, '.')) == $this->ext) {
  244. $cachedViewFile = $this->_getCachedViewFileName($___viewFn);
  245. if(!$this->cache||@filemtime($___viewFn)>@filemtime($cachedViewFile)) {
  246. if (empty($this->haml)) $this->_init();
  247. file_put_contents($cachedViewFile, $data = $this->haml->parse($___viewFn));
  248. @chmod($cachedViewFile, $this->filePermission);
  249. }
  250. return parent::_render($cachedViewFile, $___dataForView, $loadHelpers, $cached);
  251. }
  252. else {
  253. return parent::_render($___viewFn, $___dataForView, $loadHelpers, $cached);
  254. }
  255. }
  256. /**
  257. * Generates the cached view file path.
  258. * @param string source view file path
  259. * @return string cached view file path
  260. * @access private
  261. */
  262. private function _getCachedViewFileName($file) {
  263. $cachedViewFile = str_replace(substr($file, strrpos($file, '.')), '.ctp', $file);
  264. if($this->useCachePath) {
  265. $cachedViewFile = str_replace(VIEWS, CACHE.'haml'.DS, $cachedViewFile);
  266. if(!is_file($cachedViewFile))
  267. @mkdir(dirname($cachedViewFile),$this->filePermission,true);
  268. }
  269. return $cachedViewFile;
  270. }
  271. }