PageRenderTime 49ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 1ms

/core/classes/framework/view/view.php

https://github.com/GinoPane/fantasia
PHP | 448 lines | 305 code | 53 blank | 90 comment | 27 complexity | 61eb271ea4d02224d9f413d024c8318d MD5 | raw file
  1. <?php
  2. class View {
  3. private $_templates = array();
  4. private $_templateStack = array();
  5. private $_vars = array();
  6. /**
  7. *
  8. * Indicates that block contents will be appended to the contents of the
  9. * block with the same name. By default contents is replaced
  10. *
  11. */
  12. const BLOCK_APPEND = 1;
  13. /**
  14. *
  15. * Indicates that block contents will be prepended to the contents of the
  16. * block with the same name. By default contents is replaced
  17. *
  18. */
  19. const BLOCK_PREPEND = 2;
  20. /**
  21. *
  22. * If block is enclosed by another block, then its contents may be or may
  23. * not be included into the parent block contents. By default blocks are
  24. * private and their contents is closed. Otherwise you should use
  25. * BLOCK_NOT_PRIVATE flag
  26. *
  27. */
  28. const BLOCK_NOT_PRIVATE = 4;
  29. private $_blocks = array();
  30. private $_blockKeys = array();
  31. /**
  32. *
  33. * Contains list of environments
  34. *
  35. * @var array environment filters list
  36. */
  37. private $_environments = array();
  38. public static function registerFunction($key, array $callArgs) {
  39. }
  40. public static function callRegistered($key, $params = array()) {
  41. }
  42. /**
  43. *
  44. * Outputs variable specified by key, that was used to set this variable
  45. *
  46. * <pre><code>
  47. * <?php
  48. * $this->out('foo|abs'); //if foo = -5, outputs '5'
  49. * ?>
  50. * </code></pre>
  51. *
  52. * @param string $keyVar variable key, specify the list of filters to use before
  53. * outputting the value after the vbar "|", separate
  54. * them with the comma
  55. */
  56. public function out($keyVar)
  57. {
  58. @list($keyVar, $filters) = explode('|', strval($keyVar));
  59. if (isset($this->_vars[$keyVar]))
  60. {
  61. return $this->outValue($this->_vars[$keyVar], $filters);
  62. }
  63. else
  64. {
  65. return null;
  66. }
  67. }
  68. /**
  69. *
  70. * @param mixed $value
  71. * @param array $filters
  72. */
  73. public function outValue($value, $filterString = "")
  74. {
  75. if ($filterString)
  76. {
  77. $filterArray = array_values(array_unique(
  78. array_merge(
  79. (array)end($this->_environments),
  80. array_filter(array_map('trim', explode(',', $filterString)))
  81. )
  82. ));
  83. }
  84. else
  85. {
  86. $filterArray = (array)end($this->_environments);
  87. }
  88. //find exluding filters
  89. if (strpos($filterString, '^') !== false){
  90. $count = count($filterArray);
  91. $excluding = array();
  92. for($i=0; $i < $count; $i++)
  93. {
  94. if ($filterArray[$i][0] == '^')
  95. $excluding[] = str_replace('^', '', $filterArray[$i]);
  96. }
  97. $filterArray = array_diff($filterArray, $excluding);
  98. }
  99. echo $this->applyFilters($value, $filterArray);
  100. }
  101. /**
  102. *
  103. * @param mixed $value
  104. * @param array $filters
  105. */
  106. public function applyFilters($value, $filters = array())
  107. {
  108. foreach($filters as $filter)
  109. {
  110. if (is_string($filter))
  111. {
  112. $value = Filters::$filter($value);
  113. }
  114. }
  115. return $value;
  116. }
  117. /**
  118. *
  119. * Creates environment for output. Filters will be applied to all
  120. * output values
  121. *
  122. * @param string $filters string of comma-separated filters
  123. */
  124. public function openEnv($filters)
  125. {
  126. $envOptions = array_map('trim', explode(',', $filters));
  127. array_push($this->_environments, $envOptions);
  128. }
  129. /**
  130. *
  131. * Closes current opened environment
  132. *
  133. * @return array set of filters from the closed environment
  134. */
  135. public function closeEnv()
  136. {
  137. return array_pop($this->_environments);
  138. }
  139. /**
  140. *
  141. * Starts buffering of the block with the defined key-name
  142. *
  143. * @param mixed $key
  144. */
  145. public function startBlock($key)
  146. {
  147. $key = $this->_modifyBlockKey($key);
  148. if (!in_array($key, $this->_blockKeys))
  149. {
  150. array_push($this->_blockKeys, $key);
  151. ob_start();
  152. }
  153. else
  154. {
  155. trigger_error("This block has been already started", E_USER_WARNING);
  156. }
  157. }
  158. /**
  159. *
  160. * @param mixed $key
  161. * @param int $flags BLOCK_APPEND, BLOCK_PREPEND, BLOCK_NOT_PRIVATE flags combination
  162. *
  163. */
  164. public function endBlock($key, $flags = 0)
  165. {
  166. $key = $this->_modifyBlockKey($key);
  167. $keyToClose = array_pop($this->_blockKeys);
  168. if ($keyToClose && ob_get_status())
  169. {
  170. if (0 === strcmp($key, $keyToClose))
  171. {
  172. if (!($flags & View::BLOCK_NOT_PRIVATE))
  173. {
  174. $buffer = ob_get_clean();
  175. }
  176. else
  177. {
  178. $buffer = ob_get_flush();
  179. }
  180. if (isset($this->_blocks[$key]))
  181. {
  182. if ($flags & View::BLOCK_APPEND)
  183. {
  184. $this->_blocks[$key] = $this->_blocks[$key] . $buffer;
  185. }
  186. elseif($flags & View::BLOCK_PREPEND)
  187. {
  188. $this->_blocks[$key] = $buffer . $this->_blocks[$key];
  189. }
  190. else
  191. {
  192. $this->_blocks[$key] = $buffer;
  193. }
  194. }
  195. else
  196. {
  197. $this->_blocks[$key] = $buffer;
  198. }
  199. }
  200. else
  201. {
  202. array_push($this->_blockKeys, $keyToClose);
  203. trigger_error("Currently opened block is \"$keyToClose\", but you tried to close \"$key\"", E_USER_WARNING);
  204. }
  205. }
  206. else
  207. {
  208. trigger_error("There's no currently opened blocks to close", E_USER_WARNING);
  209. }
  210. }
  211. /**
  212. *
  213. * Returns data associated with the block
  214. *
  215. * @param string $key
  216. * @return string block data or null if no block present
  217. */
  218. public function getBlock($key)
  219. {
  220. return isset($this->_blocks[$key]) ? $this->_blocks[$key] : null;
  221. }
  222. /**
  223. *
  224. * Outputs block data
  225. *
  226. * @param string $key
  227. */
  228. public function printBlock($key)
  229. {
  230. echo $this->getBlock($key);
  231. }
  232. private function _modifyBlockKey($key)
  233. {
  234. return strtolower(strval($key));
  235. }
  236. public function __get($name) {
  237. return isset($this->_vars[$name]) ? $this->_vars[$name] : null;
  238. }
  239. public function __set($name, $value) {
  240. $this->_vars[$name] = $value;
  241. }
  242. /**
  243. *
  244. * Registers template for view
  245. *
  246. * @param string $filename
  247. * @param mixed $key
  248. */
  249. public function setTemplate($filename, $key = "default")
  250. {
  251. if (isset($this->_templates[$key]))
  252. {
  253. trigger_error("Template key duplication for the key \"$key\"! Overriding previous value.", E_USER_WARNING);
  254. }
  255. $this->_templates[$key] = $filename;
  256. }
  257. /**
  258. *
  259. * Registers multiple templates for route
  260. *
  261. * @param array $templates
  262. */
  263. public function setTemplates(array $templates = array())
  264. {
  265. foreach($templates as $tplKey => $tplValue)
  266. {
  267. $this->setTemplate($tplValue, $tplKey);
  268. }
  269. }
  270. /**
  271. *
  272. * Returns the template from template collection
  273. *
  274. * @param string $key
  275. * @return string
  276. */
  277. public function getTemplate($key = "default")
  278. {
  279. if (!isset($this->_templates[$key]))
  280. {
  281. trigger_error("Template with key \"$key\" doesn't exist!", E_USER_WARNING);
  282. return null;
  283. }
  284. else
  285. {
  286. return $this->_templates[$key];
  287. }
  288. }
  289. /**
  290. *
  291. * Render template content
  292. *
  293. * @param array 'key' key to define template,
  294. * 'file' to define template file,
  295. * 'forceSystemUse' to force using system templates instead of custom,
  296. * 'packName' to search templates in specified pack,
  297. * 'componentName' to search templates in specified component
  298. * @return render response
  299. */
  300. public function renderTpl($options = array())
  301. {
  302. $templateFile = $this->getTemplateFileName($options);
  303. if ($templateFile)
  304. {
  305. if (!in_array($templateFile, $this->_templateStack))
  306. {
  307. //eliminates current active environment influense
  308. $this->openEnv("");
  309. array_push($this->_templateStack, $templateFile);
  310. ob_start();
  311. $obLevel = ob_get_level();
  312. include $templateFile;
  313. //clear unclosed buffers
  314. while ($obLevel !== ob_get_level())
  315. ob_get_clean();
  316. //restores environment state
  317. $this->closeEnv();
  318. array_pop($this->_templateStack);
  319. return ob_get_clean();
  320. }
  321. else
  322. {
  323. array_push($this->_templateStack, $templateFile);
  324. trigger_error("Template loop detected! Templates: " . var_export($this->_templateStack, true), E_USER_WARNING);
  325. }
  326. }
  327. }
  328. public function getTemplateFileName($options = array())
  329. {
  330. $key = "";
  331. $file = "";
  332. $forceUseSystem = false;
  333. extract($options, EXTR_OVERWRITE | EXTR_IF_EXISTS);
  334. $template = "";
  335. if ($key)
  336. {
  337. $template = $this->getTemplate($key);
  338. }
  339. elseif($file)
  340. {
  341. $template = $file;
  342. }
  343. if ($template)
  344. {
  345. if (!is_readable($template))
  346. {
  347. $templates = array(
  348. Loader::getComponentTplFilePath($template, $options),
  349. Loader::getPackTplFilePath($template, $options),
  350. Loader::getSystemTplFilePath($template)
  351. );
  352. }
  353. else
  354. {
  355. $templates = array(
  356. $template
  357. );
  358. }
  359. if ($forceUseSystem)
  360. {
  361. $templates = array_reverse($templates);
  362. }
  363. $templateFile = "";
  364. foreach($templates as $tmpTemplate)
  365. {
  366. if (is_file($tmpTemplate) && is_readable($tmpTemplate))
  367. {
  368. $templateFile = $tmpTemplate;
  369. break;
  370. }
  371. }
  372. if ($templateFile)
  373. {
  374. return $templateFile;
  375. }
  376. else
  377. {
  378. trigger_error("Template file not found!", E_USER_WARNING);
  379. }
  380. }
  381. else
  382. {
  383. trigger_error("There's no template!", E_USER_WARNING);
  384. }
  385. }
  386. }