ViewBlock.php 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. <?php
  2. /**
  3. * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  4. * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  5. *
  6. * Licensed under The MIT License
  7. * For full copyright and license information, please see the LICENSE.txt
  8. * Redistributions of files must retain the above copyright notice.
  9. *
  10. * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  11. * @link http://cakephp.org CakePHP(tm) Project
  12. * @since 2.1.0
  13. * @license http://www.opensource.org/licenses/mit-license.php MIT License
  14. */
  15. namespace Cake\View;
  16. use Cake\Core\Exception\Exception;
  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. */
  24. class ViewBlock {
  25. /**
  26. * Append content
  27. *
  28. * @var string
  29. */
  30. const APPEND = 'append';
  31. /**
  32. * Prepend content
  33. *
  34. * @var string
  35. */
  36. const PREPEND = 'prepend';
  37. /**
  38. * Block content. An array of blocks indexed by name.
  39. *
  40. * @var array
  41. */
  42. protected $_blocks = array();
  43. /**
  44. * The active blocks being captured.
  45. *
  46. * @var array
  47. */
  48. protected $_active = array();
  49. /**
  50. * Should the currently captured content be discarded on ViewBlock::end()
  51. *
  52. * @var bool
  53. * @see ViewBlock::end()
  54. * @see ViewBlock::startIfEmpty()
  55. */
  56. protected $_discardActiveBufferOnEnd = false;
  57. /**
  58. * Start capturing output for a 'block'
  59. *
  60. * Blocks allow you to create slots or blocks of dynamic content in the layout.
  61. * view files can implement some or all of a layout's slots.
  62. *
  63. * You can end capturing blocks using View::end(). Blocks can be output
  64. * using View::get();
  65. *
  66. * @param string $name The name of the block to capture for.
  67. * @throws \Cake\Core\Exception\Exception When starting a block twice
  68. * @return void
  69. */
  70. public function start($name) {
  71. if (in_array($name, $this->_active)) {
  72. throw new Exception(sprintf("A view block with the name '%s' is already/still open.", $name));
  73. }
  74. $this->_active[] = $name;
  75. ob_start();
  76. }
  77. /**
  78. * End a capturing block. The compliment to ViewBlock::start()
  79. *
  80. * @return void
  81. * @see ViewBlock::start()
  82. */
  83. public function end() {
  84. if ($this->_discardActiveBufferOnEnd) {
  85. $this->_discardActiveBufferOnEnd = false;
  86. ob_end_clean();
  87. return;
  88. }
  89. if (!empty($this->_active)) {
  90. $active = end($this->_active);
  91. $content = ob_get_clean();
  92. $this->_blocks[$active] = $content;
  93. array_pop($this->_active);
  94. }
  95. }
  96. /**
  97. * Concat content to an existing or new block.
  98. * Concating to a new block will create the block.
  99. *
  100. * Calling concat() without a value will create a new capturing
  101. * block that needs to be finished with View::end(). The content
  102. * of the new capturing context will be added to the existing block context.
  103. *
  104. * @param string $name Name of the block
  105. * @param mixed $value The content for the block
  106. * @param string $mode If ViewBlock::APPEND content will be appended to existing content.
  107. * If ViewBlock::PREPEND it will be prepended.
  108. * @return void
  109. */
  110. public function concat($name, $value, $mode = ViewBlock::APPEND) {
  111. if (!isset($this->_blocks[$name])) {
  112. $this->_blocks[$name] = '';
  113. }
  114. if ($mode === ViewBlock::PREPEND) {
  115. $this->_blocks[$name] = $value . $this->_blocks[$name];
  116. } else {
  117. $this->_blocks[$name] .= $value;
  118. }
  119. }
  120. /**
  121. * Set the content for a block. This will overwrite any
  122. * existing content.
  123. *
  124. * @param string $name Name of the block
  125. * @param mixed $value The content for the block.
  126. * @return void
  127. */
  128. public function set($name, $value) {
  129. $this->_blocks[$name] = (string)$value;
  130. }
  131. /**
  132. * Get the content for a block.
  133. *
  134. * @param string $name Name of the block
  135. * @param string $default Default string
  136. * @return string The block content or $default if the block does not exist.
  137. */
  138. public function get($name, $default = '') {
  139. if (!isset($this->_blocks[$name])) {
  140. return $default;
  141. }
  142. return $this->_blocks[$name];
  143. }
  144. /**
  145. * Check if a block exists
  146. *
  147. * @param string $name Name of the block
  148. * @return bool
  149. */
  150. public function exists($name) {
  151. return isset($this->_blocks[$name]);
  152. }
  153. /**
  154. * Get the names of all the existing blocks.
  155. *
  156. * @return array An array containing the blocks.
  157. */
  158. public function keys() {
  159. return array_keys($this->_blocks);
  160. }
  161. /**
  162. * Get the name of the currently open block.
  163. *
  164. * @return mixed Either null or the name of the last open block.
  165. */
  166. public function active() {
  167. return end($this->_active);
  168. }
  169. /**
  170. * Get the names of the unclosed/active blocks.
  171. *
  172. * @return array An array of unclosed blocks.
  173. */
  174. public function unclosed() {
  175. return $this->_active;
  176. }
  177. }