Layout.php 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. <?php
  2. /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
  3. namespace eYaf;
  4. /**
  5. * Layout class used for render layouts and views.
  6. *
  7. * Layout class allows to use of a base layout skeleton and render views inside
  8. * this layout template.
  9. * The concept is to not render and display the view template directly but storing it
  10. * in {@link $content} property. Then will render the skeleton layout and
  11. * pass the {@link $content} property to it.
  12. * <code>
  13. * application/views/layouts/front.phtml
  14. *
  15. * <html>
  16. * <head>
  17. * <title><?php echo $title ?></title>
  18. * </head>
  19. * <body>
  20. * <?= $_content_ // This is where your view from each action
  21. * will be displayed ?>
  22. * </body>
  23. * </html>
  24. * </code>
  25. *
  26. * If no layout is defined then returns the renderd action view template.
  27. *
  28. * Also allows to set variable to views and access them from the base
  29. * skeleton layout. In above layout $title variable is set to title tag.
  30. * Then in a view template we can set the value for $title variable.
  31. * <code>
  32. * application/views/index/index.phtml
  33. *
  34. * <?php $this->title = "Index Action" ?>
  35. * <h1>Index Action</h1>
  36. * </code>
  37. *
  38. * @author Andreas Kollaros <[email protected]>
  39. *
  40. */
  41. class Layout implements \Yaf\View_Interface
  42. {
  43. /**
  44. * The template engine to render views and layout templates.
  45. *
  46. * Default engine is Yaf\View\Simple
  47. *
  48. * @var Yaf\View\Simple
  49. */
  50. public $engine;
  51. /**
  52. * Options to be passed to template engine.
  53. *
  54. * @var array
  55. */
  56. protected $options=array();
  57. /**
  58. *
  59. */
  60. protected $layout_path;
  61. /**
  62. * The name of layout file without extension.
  63. *
  64. * @var string
  65. */
  66. protected $layout = 'layout';
  67. /**
  68. * Handles the rendered action view data.
  69. *
  70. * @var string
  71. */
  72. protected $content;
  73. /**
  74. * Array with assigned template variables.
  75. *
  76. * @var array
  77. */
  78. protected $tpl_vars = array();
  79. /**
  80. * Template directory.
  81. *
  82. * @var string
  83. */
  84. protected $tpl_dir;
  85. /**
  86. * Constructor
  87. *
  88. * @param array $options key/value pair of options to be assigned to
  89. * template engine.
  90. *
  91. * @return void
  92. */
  93. public function __construct($path, $options=array())
  94. {
  95. $this->layout_path = $path;
  96. $this->options = $options;
  97. }
  98. /**
  99. * Return the instance of a template engine.
  100. *
  101. * @return Yaf\View\Simple
  102. */
  103. protected function engine()
  104. {
  105. $this->engine = $this->engine ?: new \Yaf\View\Simple(
  106. $this->tpl_dir,
  107. $this->options
  108. );
  109. return $this->engine;
  110. }
  111. /**
  112. * Create engine instance and set the path of views and layout templates.
  113. *
  114. * Layout path is set by default to layout directory inside views path.
  115. *
  116. * @param string $path The directory to set as the path.
  117. *
  118. * @return void
  119. */
  120. public function setScriptPath($path)
  121. {
  122. if (is_readable($path)) {
  123. $this->tpl_dir = $path;
  124. $this->engine()->setScriptPath($path);
  125. // Overwirte layouts path by setting it where views path is.
  126. // This will force layout in modules to be placed in
  127. // modules/views/layouts directory
  128. $this->layout_path = $path . "/layouts";
  129. return true;
  130. }
  131. throw new \Exception("Invalid path: {$path}");
  132. }
  133. /**
  134. * Getter method for views path.
  135. *
  136. * @return string
  137. */
  138. public function getScriptPath()
  139. {
  140. return $this->engine()->getScriptPath();
  141. }
  142. /**
  143. * Setter for Layout::layout variable
  144. *
  145. * @param string $name the name of layout file without extension.
  146. *
  147. * @return void
  148. */
  149. public function setLayout($name)
  150. {
  151. $this->layout = $name;
  152. }
  153. /**
  154. * Getter for Layout::layout variable
  155. *
  156. * @return string the name of layout file without extension
  157. */
  158. public function getLayout()
  159. {
  160. return $this->layout;
  161. }
  162. public function setLayoutPath($path)
  163. {
  164. $this->layout_path = $path;
  165. }
  166. /**
  167. * Get full layout path with filename and extension.
  168. *
  169. * @return string
  170. */
  171. public function getLayoutPath()
  172. {
  173. $config = \Yaf\Application::app()->getConfig()->get('application');
  174. return $this->layout_path . "/" . $this->layout . ".{$config->view->ext}";
  175. }
  176. /**
  177. * Assign a variable to the template
  178. *
  179. * @param string $name The variable name.
  180. * @param mixed $value The variable value.
  181. *
  182. * @return void
  183. */
  184. public function __set($name, $value)
  185. {
  186. $this->assign($name, $value);
  187. }
  188. /**
  189. * Allows testing with empty() and isset() to work
  190. *
  191. * @param string $name
  192. *
  193. * @return boolean
  194. */
  195. public function __isset($name)
  196. {
  197. return (null !== $this->engine()->$name);
  198. }
  199. /**
  200. * Allows unset() on object properties to work
  201. *
  202. * @param string $name
  203. *
  204. * @return void
  205. */
  206. public function __unset($name)
  207. {
  208. $this->engine()->clear($name);
  209. }
  210. /**
  211. * Assign variables to the template
  212. *
  213. * Allows setting a specific key to the specified value, OR passing
  214. * an array of key => value pairs to set en masse.
  215. *
  216. * @see __set()
  217. *
  218. * @param string|array $name The assignment strategy to use (key or
  219. * array of key => value pairs)
  220. * @param mixed $value (Optional) If assigning a named variable,
  221. * use this as the value.
  222. *
  223. * @return void
  224. */
  225. public function assign($name, $value = null)
  226. {
  227. $this->tpl_vars[$name] = $value;
  228. $this->engine()->assign($name, $value);
  229. }
  230. /**
  231. * Assign variables by reference to the template
  232. *
  233. */
  234. public function assignRef($name, &$value)
  235. {
  236. $this->tpl_vars[$name] = $value;
  237. $this->engine()->assignRef($name, $value);
  238. }
  239. /**
  240. * Clear all assigned variables
  241. *
  242. * Clears all variables assigned to Yaf\View either via
  243. * {@link assign()} or property overloading
  244. * ({@link __get()}/{@link __set()}).
  245. *
  246. * @return void
  247. */
  248. public function clearVars() {
  249. $this->tpl_vars = array();
  250. $this->engine()->clear();
  251. }
  252. /**
  253. * Processes a view and returns the output.
  254. *
  255. * This method called once from controller to render the given view.
  256. * So render the view at $this->content property and then render the
  257. * layout template.
  258. *
  259. * @param string $tpl The template to process.
  260. * @param array $tpl_vars Additional variables to be assigned to template.
  261. *
  262. * @return string The view or layout template output.
  263. */
  264. public function render($tpl, $tpl_vars=array()) {
  265. $tpl_vars = array_merge($this->tpl_vars, $tpl_vars);
  266. $this->content = $this->engine()->render($tpl, $tpl_vars);
  267. // if no layout is defined,
  268. // return the rendered view template
  269. if (null == $this->layout) {
  270. return $this->content;
  271. }
  272. // If we assign some variables into view template, then maybe we need
  273. // them to layout view.
  274. // Hack??
  275. // Get template vars from view via Reflection class and assign them to
  276. // layout view
  277. $ref = new \ReflectionClass($this->engine());
  278. $prop = $ref->getProperty('_tpl_vars');
  279. $prop->setAccessible(true);
  280. $view_vars = $prop->getValue($this->engine());
  281. $tpl_vars = array_merge($tpl_vars, $view_vars);
  282. $tpl_vars['_content_'] = $this->content;
  283. return $this->engine()->render(
  284. $this->getLayoutPath(),
  285. $tpl_vars
  286. );
  287. }
  288. /**
  289. * Directly display the constens of a view / layout template.
  290. *
  291. * @param string $tpl The template to process.
  292. * @param array $tpl_vars Additional variables to be assigned to template.
  293. *
  294. * @return void
  295. */
  296. public function display($tpl, $tpl_vars=array()) {
  297. echo $this->render($tpl, $tpl_vars);
  298. }
  299. }