ViewBlock.php 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  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. namespace Cake\View;
  18. use Cake\Error;
  19. /**
  20. * ViewBlock implements the concept of Blocks or Slots in the View layer.
  21. * Slots or blocks are combined with extending views and layouts to afford slots
  22. * of content that are present in a layout or parent view, but are defined by the child
  23. * view or elements used in the view.
  24. *
  25. */
  26. class ViewBlock {
  27. /**
  28. * Append content
  29. *
  30. * @constant APPEND
  31. */
  32. const APPEND = 'append';
  33. /**
  34. * Prepend content
  35. *
  36. * @constant PREPEND
  37. */
  38. const PREPEND = 'prepend';
  39. /**
  40. * Block content. An array of blocks indexed by name.
  41. *
  42. * @var array
  43. */
  44. protected $_blocks = array();
  45. /**
  46. * The active blocks being captured.
  47. *
  48. * @var array
  49. */
  50. protected $_active = array();
  51. /**
  52. * Should the currently captured content be discarded on ViewBlock::end()
  53. *
  54. * @var boolean
  55. * @see ViewBlock::end()
  56. * @see ViewBlock::startIfEmpty()
  57. */
  58. protected $_discardActiveBufferOnEnd = false;
  59. /**
  60. * Start capturing output for a 'block'
  61. *
  62. * Blocks allow you to create slots or blocks of dynamic content in the layout.
  63. * view files can implement some or all of a layout's slots.
  64. *
  65. * You can end capturing blocks using View::end(). Blocks can be output
  66. * using View::get();
  67. *
  68. * @param string $name The name of the block to capture for.
  69. * @return void
  70. */
  71. public function start($name) {
  72. $this->_active[] = $name;
  73. ob_start();
  74. }
  75. /**
  76. * Start capturing output for a 'block' if it is empty
  77. *
  78. * Blocks allow you to create slots or blocks of dynamic content in the layout.
  79. * view files can implement some or all of a layout's slots.
  80. *
  81. * You can end capturing blocks using View::end(). Blocks can be output
  82. * using View::get();
  83. *
  84. * @param string $name The name of the block to capture for.
  85. * @return void
  86. */
  87. public function startIfEmpty($name) {
  88. if (empty($this->_blocks[$name])) {
  89. return $this->start($name);
  90. }
  91. $this->_discardActiveBufferOnEnd = true;
  92. ob_start();
  93. }
  94. /**
  95. * End a capturing block. The compliment to ViewBlock::start()
  96. *
  97. * @return void
  98. * @see ViewBlock::start()
  99. */
  100. public function end() {
  101. if ($this->_discardActiveBufferOnEnd) {
  102. $this->_discardActiveBufferOnEnd = false;
  103. ob_end_clean();
  104. return;
  105. }
  106. if (!empty($this->_active)) {
  107. $active = end($this->_active);
  108. $content = ob_get_clean();
  109. if (!isset($this->_blocks[$active])) {
  110. $this->_blocks[$active] = '';
  111. }
  112. $this->_blocks[$active] .= $content;
  113. array_pop($this->_active);
  114. }
  115. }
  116. /**
  117. * Concat content to an existing or new block.
  118. * Concating to a new block will create the block.
  119. *
  120. * Calling concat() without a value will create a new capturing
  121. * block that needs to be finished with View::end(). The content
  122. * of the new capturing context will be added to the existing block context.
  123. *
  124. * @param string $name Name of the block
  125. * @param mixed $value The content for the block
  126. * @param string $mode If ViewBlock::APPEND content will be appended to existing content.
  127. * If ViewBlock::PREPEND it will be prepended.
  128. * @return void
  129. */
  130. public function concat($name, $value = null, $mode = ViewBlock::APPEND) {
  131. if (isset($value)) {
  132. if (!isset($this->_blocks[$name])) {
  133. $this->_blocks[$name] = '';
  134. }
  135. if ($mode === ViewBlock::PREPEND) {
  136. $this->_blocks[$name] = $value . $this->_blocks[$name];
  137. } else {
  138. $this->_blocks[$name] .= $value;
  139. }
  140. } else {
  141. $this->start($name);
  142. }
  143. }
  144. /**
  145. * Set the content for a block. This will overwrite any
  146. * existing content.
  147. *
  148. * @param string $name Name of the block
  149. * @param mixed $value The content for the block.
  150. * @return void
  151. */
  152. public function set($name, $value) {
  153. $this->_blocks[$name] = (string)$value;
  154. }
  155. /**
  156. * Get the content for a block.
  157. *
  158. * @param string $name Name of the block
  159. * @param string $default Default string
  160. * @return string The block content or $default if the block does not exist.
  161. */
  162. public function get($name, $default = '') {
  163. if (!isset($this->_blocks[$name])) {
  164. return $default;
  165. }
  166. return $this->_blocks[$name];
  167. }
  168. /**
  169. * Get the names of all the existing blocks.
  170. *
  171. * @return array An array containing the blocks.
  172. */
  173. public function keys() {
  174. return array_keys($this->_blocks);
  175. }
  176. /**
  177. * Get the name of the currently open block.
  178. *
  179. * @return mixed Either null or the name of the last open block.
  180. */
  181. public function active() {
  182. return end($this->_active);
  183. }
  184. /**
  185. * Get the names of the unclosed/active blocks.
  186. *
  187. * @return array An array of unclosed blocks.
  188. */
  189. public function unclosed() {
  190. return $this->_active;
  191. }
  192. }