PageRenderTime 43ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/fuel/core/classes/viewmodel.php

https://bitbucket.org/trujka/codegrounds
PHP | 298 lines | 150 code | 35 blank | 113 comment | 5 complexity | f13ae59ca3be96a546d16d55ed9765ac MD5 | raw file
Possible License(s): MIT, BSD-3-Clause, LGPL-2.1
  1. <?php
  2. /**
  3. * Part of the Fuel framework.
  4. *
  5. * @package Fuel
  6. * @version 1.6
  7. * @author Fuel Development Team
  8. * @license MIT License
  9. * @copyright 2010 - 2013 Fuel Development Team
  10. * @link http://fuelphp.com
  11. */
  12. namespace Fuel\Core;
  13. /**
  14. * ViewModel
  15. *
  16. * @package Fuel
  17. * @subpackage Core
  18. * @category Core
  19. * @author Jelmer Schreuder
  20. */
  21. abstract class ViewModel
  22. {
  23. /**
  24. * Factory for fetching the ViewModel
  25. *
  26. * @param string ViewModel classname without View_ prefix or full classname
  27. * @param string Method to execute
  28. * @return ViewModel
  29. */
  30. public static function forge($view, $method = 'view', $auto_filter = null)
  31. {
  32. // strip any extensions from the view name to determine the viewmodel to load
  33. $viewmodel = \Inflector::words_to_upper(str_replace(
  34. array('/', DS),
  35. '_',
  36. strpos($view, '.') === false ? $view : substr($view, 0, -strlen(strrchr($view, '.')))
  37. ));
  38. // determine the viewmodel namespace from the current request context
  39. $namespace = \Request::active() ? ucfirst(\Request::active()->module) : '';
  40. // list of possible viewmodel classnames, start with the namespaced one
  41. $classes = array($namespace.'\\View_'.$viewmodel);
  42. // add the global version if needed
  43. empty($namespace) or $classes[] = 'View_'.$viewmodel;
  44. /**
  45. * Add non View_ prefixed classnames to the list, for BC reasons
  46. *
  47. * @deprecated 1.6
  48. */
  49. $classes[] = $namespace.'\\'.$viewmodel;
  50. // and add the global version of that if needed
  51. empty($namespace) or $classes[] = $viewmodel;
  52. // check if we can find one
  53. foreach ($classes as $class)
  54. {
  55. if (class_exists($class))
  56. {
  57. return new $class($method, $auto_filter, $view);
  58. }
  59. }
  60. throw new \OutOfBoundsException('ViewModel "'.reset($classes).'" could not be found.');
  61. }
  62. /**
  63. * @var string method to execute when rendering
  64. */
  65. protected $_method;
  66. /**
  67. * @var string|View view name, after instantiation a View object
  68. */
  69. protected $_view;
  70. /**
  71. * @var bool whether or not to use auto filtering
  72. */
  73. protected $_auto_filter;
  74. /**
  75. * @var Request active request during ViewModel creation for proper context
  76. */
  77. protected $_active_request;
  78. protected function __construct($method, $auto_filter = null, $view = null)
  79. {
  80. $this->_auto_filter = $auto_filter;
  81. $this->_view === null and $this->_view = $view;
  82. class_exists('Request', false) and $this->_active_request = \Request::active();
  83. if (empty($this->_view))
  84. {
  85. // Take the class name and guess the view name
  86. $class = get_class($this);
  87. $this->_view = strtolower(str_replace('_', DS, preg_replace('#^([a-z0-9_]*\\\\)?(View_)?#i', '', $class)));
  88. }
  89. $this->set_view();
  90. $this->_method = $method;
  91. }
  92. /**
  93. * Returns the View object associated with this Viewmodel
  94. *
  95. * @return View
  96. */
  97. public function get_view()
  98. {
  99. return $this->_view;
  100. }
  101. /**
  102. * Construct the View object
  103. */
  104. protected function set_view()
  105. {
  106. $this->_view = \View::forge($this->_view);
  107. }
  108. /**
  109. * Returns the active request object.
  110. *
  111. * @return Request
  112. */
  113. protected function request()
  114. {
  115. return $this->_active_request;
  116. }
  117. /**
  118. * Executed before the view method
  119. */
  120. public function before() {}
  121. /**
  122. * The default view method
  123. * Should set all expected variables upon itself
  124. */
  125. public function view() {}
  126. /**
  127. * Executed after the view method
  128. */
  129. public function after() {}
  130. /**
  131. * Fetches an existing value from the template
  132. *
  133. * @return mixed
  134. */
  135. public function & __get($name)
  136. {
  137. return $this->get($name);
  138. }
  139. /**
  140. * Gets a variable from the template
  141. *
  142. * @param string
  143. */
  144. public function & get($key = null, $default = null)
  145. {
  146. if (is_null($default) and func_num_args() === 1)
  147. {
  148. return $this->_view->get($key);
  149. }
  150. return $this->_view->get($key, $default);
  151. }
  152. /**
  153. * Sets and sanitizes a variable on the template
  154. *
  155. * @param string
  156. * @param mixed
  157. */
  158. public function __set($key, $value)
  159. {
  160. return $this->set($key, $value);
  161. }
  162. /**
  163. * Sets a variable on the template
  164. *
  165. * @param string
  166. * @param mixed
  167. * @param bool|null
  168. */
  169. public function set($key, $value, $filter = null)
  170. {
  171. is_null($filter) and $filter = $this->_auto_filter;
  172. $this->_view->set($key, $value, $filter);
  173. return $this;
  174. }
  175. /**
  176. * Magic method, determines if a variable is set.
  177. *
  178. * isset($view->foo);
  179. *
  180. * @param string variable name
  181. * @return boolean
  182. */
  183. public function __isset($key)
  184. {
  185. return isset($this->_view->$key);
  186. }
  187. /**
  188. * Assigns a value by reference. The benefit of binding is that values can
  189. * be altered without re-setting them. It is also possible to bind variables
  190. * before they have values. Assigned values will be available as a
  191. * variable within the view file:
  192. *
  193. * $this->bind('ref', $bar);
  194. *
  195. * @param string variable name
  196. * @param mixed referenced variable
  197. * @param bool Whether to filter the var on output
  198. * @return $this
  199. */
  200. public function bind($key, &$value, $filter = null)
  201. {
  202. $this->_view->bind($key, $value, $filter);
  203. return $this;
  204. }
  205. /**
  206. * Change auto filter setting
  207. *
  208. * @param null|bool change setting (bool) or get the current setting (null)
  209. * @return void|bool returns current setting or nothing when it is changed
  210. */
  211. public function auto_filter($setting = null)
  212. {
  213. if (func_num_args() == 0)
  214. {
  215. return $this->_view->auto_filter();
  216. }
  217. return $this->_view->auto_filter($setting);
  218. }
  219. /**
  220. * Add variables through method and after() and create template as a string
  221. */
  222. public function render()
  223. {
  224. if (class_exists('Request', false))
  225. {
  226. $current_request = Request::active();
  227. Request::active($this->_active_request);
  228. }
  229. $this->before();
  230. $this->{$this->_method}();
  231. $this->after();
  232. $return = $this->_view->render();
  233. if (class_exists('Request', false))
  234. {
  235. Request::active($current_request);
  236. }
  237. return $return;
  238. }
  239. /**
  240. * Auto-render on toString
  241. */
  242. public function __toString()
  243. {
  244. try
  245. {
  246. return $this->render();
  247. }
  248. catch (\Exception $e)
  249. {
  250. \Error::exception_handler($e);
  251. return '';
  252. }
  253. }
  254. }