ViewBlock.php 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. <?php
  2. /**
  3. * PHP 5
  4. *
  5. * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  6. * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  7. *
  8. * Licensed under The MIT License
  9. * For full copyright and license information, please see the LICENSE.txt
  10. * Redistributions of files must retain the above copyright notice.
  11. *
  12. * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  13. * @link http://cakephp.org CakePHP(tm) Project
  14. * @since CakePHP(tm) v2.1
  15. * @license http://www.opensource.org/licenses/mit-license.php MIT License
  16. */
  17. /**
  18. * ViewBlock implements the concept of Blocks or Slots in the View layer.
  19. * Slots or blocks are combined with extending views and layouts to afford slots
  20. * of content that are present in a layout or parent view, but are defined by the child
  21. * view or elements used in the view.
  22. *
  23. * @package Cake.View
  24. */
  25. class ViewBlock {
  26. /**
  27. * Append content
  28. *
  29. * @constant APPEND
  30. */
  31. const APPEND = 'append';
  32. /**
  33. * Prepend content
  34. *
  35. * @constant PREPEND
  36. */
  37. const PREPEND = 'prepend';
  38. /**
  39. * Block content. An array of blocks indexed by name.
  40. *
  41. * @var array
  42. */
  43. protected $_blocks = array();
  44. /**
  45. * The active blocks being captured.
  46. *
  47. * @var array
  48. */
  49. protected $_active = array();
  50. /**
  51. * Should the currently captured content be discarded on ViewBlock::end()
  52. *
  53. * @var boolean
  54. * @see ViewBlock::end()
  55. * @see ViewBlock::startIfEmpty()
  56. */
  57. protected $_discardActiveBufferOnEnd = false;
  58. /**
  59. * Start capturing output for a 'block'
  60. *
  61. * Blocks allow you to create slots or blocks of dynamic content in the layout.
  62. * view files can implement some or all of a layout's slots.
  63. *
  64. * You can end capturing blocks using View::end(). Blocks can be output
  65. * using View::get();
  66. *
  67. * @param string $name The name of the block to capture for.
  68. * @return void
  69. */
  70. public function start($name) {
  71. $this->_active[] = $name;
  72. ob_start();
  73. }
  74. /**
  75. * Start capturing output for a 'block' if it is empty
  76. *
  77. * Blocks allow you to create slots or blocks of dynamic content in the layout.
  78. * view files can implement some or all of a layout's slots.
  79. *
  80. * You can end capturing blocks using View::end(). Blocks can be output
  81. * using View::get();
  82. *
  83. * @param string $name The name of the block to capture for.
  84. * @return void
  85. */
  86. public function startIfEmpty($name) {
  87. if (empty($this->_blocks[$name])) {
  88. return $this->start($name);
  89. }
  90. $this->_discardActiveBufferOnEnd = true;
  91. ob_start();
  92. }
  93. /**
  94. * End a capturing block. The compliment to ViewBlock::start()
  95. *
  96. * @return void
  97. * @see ViewBlock::start()
  98. */
  99. public function end() {
  100. if ($this->_discardActiveBufferOnEnd) {
  101. $this->_discardActiveBufferOnEnd = false;
  102. ob_end_clean();
  103. return;
  104. }
  105. if (!empty($this->_active)) {
  106. $active = end($this->_active);
  107. $content = ob_get_clean();
  108. if (!isset($this->_blocks[$active])) {
  109. $this->_blocks[$active] = '';
  110. }
  111. $this->_blocks[$active] .= $content;
  112. array_pop($this->_active);
  113. }
  114. }
  115. /**
  116. * Concat content to an existing or new block.
  117. * Concating to a new block will create the block.
  118. *
  119. * Calling concat() without a value will create a new capturing
  120. * block that needs to be finished with View::end(). The content
  121. * of the new capturing context will be added to the existing block context.
  122. *
  123. * @param string $name Name of the block
  124. * @param string $value The content for the block
  125. * @param string $mode If ViewBlock::APPEND content will be appended to existing content.
  126. * If ViewBlock::PREPEND it will be prepended.
  127. * @return void
  128. * @throws CakeException when you use non-string values.
  129. */
  130. public function concat($name, $value = null, $mode = ViewBlock::APPEND) {
  131. if (isset($value)) {
  132. if (!is_string($value)) {
  133. throw new CakeException(__d('cake_dev', '%s must be a string.', '$value'));
  134. }
  135. if (!isset($this->_blocks[$name])) {
  136. $this->_blocks[$name] = '';
  137. }
  138. if ($mode === ViewBlock::PREPEND) {
  139. $this->_blocks[$name] = $value . $this->_blocks[$name];
  140. } else {
  141. $this->_blocks[$name] .= $value;
  142. }
  143. } else {
  144. $this->start($name);
  145. }
  146. }
  147. /**
  148. * Append to an existing or new block. Appending to a new
  149. * block will create the block.
  150. *
  151. * Calling append() without a value will create a new capturing
  152. * block that needs to be finished with View::end(). The content
  153. * of the new capturing context will be added to the existing block context.
  154. *
  155. * @param string $name Name of the block
  156. * @param string $value The content for the block.
  157. * @return void
  158. * @throws CakeException when you use non-string values.
  159. * @deprecated As of 2.3 use ViewBlock::concat() instead.
  160. */
  161. public function append($name, $value = null) {
  162. $this->concat($name, $value);
  163. }
  164. /**
  165. * Set the content for a block. This will overwrite any
  166. * existing content.
  167. *
  168. * @param string $name Name of the block
  169. * @param string $value The content for the block.
  170. * @return void
  171. * @throws CakeException when you use non-string values.
  172. */
  173. public function set($name, $value) {
  174. if (!is_string($value)) {
  175. throw new CakeException(__d('cake_dev', 'Blocks can only contain strings.'));
  176. }
  177. $this->_blocks[$name] = $value;
  178. }
  179. /**
  180. * Get the content for a block.
  181. *
  182. * @param string $name Name of the block
  183. * @param string $default Default string
  184. * @return string The block content or $default if the block does not exist.
  185. */
  186. public function get($name, $default = '') {
  187. if (!isset($this->_blocks[$name])) {
  188. return $default;
  189. }
  190. return $this->_blocks[$name];
  191. }
  192. /**
  193. * Get the names of all the existing blocks.
  194. *
  195. * @return array An array containing the blocks.
  196. */
  197. public function keys() {
  198. return array_keys($this->_blocks);
  199. }
  200. /**
  201. * Get the name of the currently open block.
  202. *
  203. * @return mixed Either null or the name of the last open block.
  204. */
  205. public function active() {
  206. return end($this->_active);
  207. }
  208. /**
  209. * Get the names of the unclosed/active blocks.
  210. *
  211. * @return array An array of unclosed blocks.
  212. */
  213. public function unclosed() {
  214. return $this->_active;
  215. }
  216. }