view.php 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. <?php namespace Laravel;
  2. class View {
  3. /**
  4. * The name of the view.
  5. *
  6. * @var string
  7. */
  8. public $view;
  9. /**
  10. * The view data.
  11. *
  12. * @var array
  13. */
  14. public $data;
  15. /**
  16. * The path to the view on disk.
  17. *
  18. * @var string
  19. */
  20. protected $path;
  21. /**
  22. * Create a new view instance.
  23. *
  24. * @param string $view
  25. * @param array $data
  26. * @return void
  27. */
  28. protected function __construct($view, $data = array())
  29. {
  30. $this->view = $view;
  31. $this->data = $data;
  32. $this->path = $this->path($view);
  33. }
  34. /**
  35. * Create a new view instance.
  36. *
  37. * @param string $view
  38. * @param array $data
  39. * @return View
  40. */
  41. public static function make($view, $data = array())
  42. {
  43. return new static($view, $data);
  44. }
  45. /**
  46. * Create a new view instance from a view name.
  47. *
  48. * View names are defined in the application composers file.
  49. *
  50. * <code>
  51. * // Create a new named view instance
  52. * $view = View::of('layout');
  53. *
  54. * // Create a new named view instance with bound data
  55. * $view = View::of('layout', array('name' => 'Fred'));
  56. * </code>
  57. *
  58. * @param string $name
  59. * @param array $data
  60. * @return View
  61. */
  62. public static function of($name, $data = array())
  63. {
  64. if ( ! is_null($view = Composer::name($name)))
  65. {
  66. return new static($view, $data);
  67. }
  68. throw new \Exception("Named view [$name] is not defined.");
  69. }
  70. /**
  71. * Get the path to a given view on disk.
  72. *
  73. * @param string $view
  74. * @return string
  75. */
  76. protected function path($view)
  77. {
  78. $view = str_replace('.', '/', $view);
  79. if (file_exists($path = VIEW_PATH.$view.'.blade'.EXT))
  80. {
  81. return $path;
  82. }
  83. elseif (file_exists($path = VIEW_PATH.$view.EXT))
  84. {
  85. return $path;
  86. }
  87. throw new \Exception('View ['.$view.'] does not exist.');
  88. }
  89. /**
  90. * Get the evaluated string content of the view.
  91. *
  92. * If the view has a composer, it will be executed. All sub-views and responses will
  93. * also be evaluated and converted to their string values.
  94. *
  95. * @return string
  96. */
  97. public function render()
  98. {
  99. Composer::compose($this);
  100. foreach ($this->data as &$data)
  101. {
  102. if ($data instanceof View or $data instanceof Response) $data = $data->render();
  103. }
  104. ob_start() and extract($this->data, EXTR_SKIP);
  105. $content = ($this->bladed()) ? Blade::parse($this->path) : file_get_contents($this->path);
  106. eval('?>'.$content);
  107. return ob_get_clean();
  108. }
  109. /**
  110. * Determine if the view is using the blade view engine.
  111. *
  112. * @return bool
  113. */
  114. protected function bladed()
  115. {
  116. return (strpos($this->path, '.blade'.EXT) !== false);
  117. }
  118. /**
  119. * Add a view instance to the view data.
  120. *
  121. * <code>
  122. * // Bind a partial view to the view data
  123. * $view->partial('footer', 'partials/footer');
  124. *
  125. * // Bind a partial view to the view data with it's own bound data
  126. * $view->partial('footer', 'partials/footer', array('name' => 'Fred'));
  127. * </code>
  128. *
  129. * @param string $key
  130. * @param string $view
  131. * @param array $data
  132. * @return View
  133. */
  134. public function partial($key, $view, $data = array())
  135. {
  136. return $this->with($key, new static($view, $data));
  137. }
  138. /**
  139. * Add a key / value pair to the view data.
  140. *
  141. * Bound data will be available to the view as variables.
  142. *
  143. * <code>
  144. * // Bind a piece of data to a view instance
  145. * $view->with('name', 'Fred');
  146. * </code>
  147. *
  148. * @param string $key
  149. * @param mixed $value
  150. * @return View
  151. */
  152. public function with($key, $value)
  153. {
  154. $this->data[$key] = $value;
  155. return $this;
  156. }
  157. /**
  158. * Magic Method for getting items from the view data.
  159. */
  160. public function __get($key)
  161. {
  162. return $this->data[$key];
  163. }
  164. /**
  165. * Magic Method for setting items in the view data.
  166. */
  167. public function __set($key, $value)
  168. {
  169. $this->with($key, $value);
  170. }
  171. /**
  172. * Magic Method for determining if an item is in the view data.
  173. */
  174. public function __isset($key)
  175. {
  176. return array_key_exists($key, $this->data);
  177. }
  178. /**
  179. * Magic Method for removing an item from the view data.
  180. */
  181. public function __unset($key)
  182. {
  183. unset($this->data[$key]);
  184. }
  185. /**
  186. * Magic Method for handling the dynamic creation of named views.
  187. *
  188. * <code>
  189. * // Create an instance of the "layout" named view
  190. * $view = View::of_layout();
  191. *
  192. * // Create an instance of the "layout" named view with bound data
  193. * $view = View::of_layout(array('name' => 'Fred'));
  194. * </code>
  195. */
  196. public static function __callStatic($method, $parameters)
  197. {
  198. if (strpos($method, 'of_') === 0)
  199. {
  200. return static::of(substr($method, 3), Arr::get($parameters, 0, array()));
  201. }
  202. }
  203. }
  204. /**
  205. * The view composer class is responsible for calling the composer on a view and
  206. * searching through the view composers for a given view name.
  207. */
  208. class Composer {
  209. /**
  210. * The view composers.
  211. *
  212. * @var array
  213. */
  214. public static $composers;
  215. /**
  216. * Find the key for a view by name.
  217. *
  218. * @param string $name
  219. * @return string
  220. */
  221. public static function name($name)
  222. {
  223. foreach (static::$composers as $key => $value)
  224. {
  225. if ($name === $value or (isset($value['name']) and $name === $value['name'])) { return $key; }
  226. }
  227. }
  228. /**
  229. * Call the composer for the view instance.
  230. *
  231. * @param View $view
  232. * @return void
  233. */
  234. public static function compose(View $view)
  235. {
  236. if (isset(static::$composers['shared'])) call_user_func(static::$composers['shared'], $view);
  237. if (isset(static::$composers[$view->view]))
  238. {
  239. foreach ((array) static::$composers[$view->view] as $key => $value)
  240. {
  241. if ($value instanceof \Closure) return call_user_func($value, $view);
  242. }
  243. }
  244. }
  245. }
  246. /**
  247. * Load the application's composers into the composers property.
  248. */
  249. Composer::$composers = require APP_PATH.'composers'.EXT;