Cell.php 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  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 3.0.0
  13. * @license http://www.opensource.org/licenses/mit-license.php MIT License
  14. */
  15. namespace Cake\View;
  16. use Cake\Datasource\ModelAwareTrait;
  17. use Cake\Event\EventDispatcherTrait;
  18. use Cake\Event\EventManager;
  19. use Cake\Network\Request;
  20. use Cake\Network\Response;
  21. use Cake\ORM\Locator\LocatorAwareTrait;
  22. use Cake\Utility\Inflector;
  23. use Cake\View\Exception\MissingCellViewException;
  24. use Cake\View\Exception\MissingTemplateException;
  25. use Cake\View\ViewVarsTrait;
  26. /**
  27. * Cell base.
  28. *
  29. */
  30. abstract class Cell
  31. {
  32. use EventDispatcherTrait;
  33. use LocatorAwareTrait;
  34. use ModelAwareTrait;
  35. use ViewVarsTrait;
  36. /**
  37. * Instance of the View created during rendering. Won't be set until after
  38. * Cell::__toString() is called.
  39. *
  40. * @var \Cake\View\View
  41. * @deprecated 3.1.0 Use getView() instead.
  42. */
  43. public $View;
  44. /**
  45. * Name of the template that will be rendered.
  46. * This property is inflected from the action name that was invoked.
  47. *
  48. * @var string
  49. */
  50. public $template;
  51. /**
  52. * Automatically set to the name of a plugin.
  53. *
  54. * @var string
  55. */
  56. public $plugin = null;
  57. /**
  58. * An instance of a Cake\Network\Request object that contains information about the current request.
  59. * This object contains all the information about a request and several methods for reading
  60. * additional information about the request.
  61. *
  62. * @var \Cake\Network\Request
  63. */
  64. public $request;
  65. /**
  66. * An instance of a Response object that contains information about the impending response
  67. *
  68. * @var \Cake\Network\Response
  69. */
  70. public $response;
  71. /**
  72. * The helpers this cell uses.
  73. *
  74. * This property is copied automatically when using the CellTrait
  75. *
  76. * @var array
  77. */
  78. public $helpers = [];
  79. /**
  80. * These properties can be set directly on Cell and passed to the View as options.
  81. *
  82. * @var array
  83. * @see \Cake\View\View
  84. */
  85. protected $_validViewOptions = [
  86. 'viewPath'
  87. ];
  88. /**
  89. * List of valid options (constructor's fourth arguments)
  90. * Override this property in subclasses to whitelist
  91. * which options you want set as properties in your Cell.
  92. *
  93. * @var array
  94. */
  95. protected $_validCellOptions = [];
  96. /**
  97. * Caching setup.
  98. *
  99. * @var array|bool
  100. */
  101. protected $_cache = false;
  102. /**
  103. * Constructor.
  104. *
  105. * @param \Cake\Network\Request $request The request to use in the cell.
  106. * @param \Cake\Network\Response $response The response to use in the cell.
  107. * @param \Cake\Event\EventManager $eventManager The eventManager to bind events to.
  108. * @param array $cellOptions Cell options to apply.
  109. */
  110. public function __construct(
  111. Request $request = null,
  112. Response $response = null,
  113. EventManager $eventManager = null,
  114. array $cellOptions = []
  115. ) {
  116. $this->eventManager($eventManager);
  117. $this->request = $request;
  118. $this->response = $response;
  119. $this->modelFactory('Table', [$this->tableLocator(), 'get']);
  120. foreach ($this->_validCellOptions as $var) {
  121. if (isset($cellOptions[$var])) {
  122. $this->{$var} = $cellOptions[$var];
  123. }
  124. }
  125. if (!empty($cellOptions['cache'])) {
  126. $this->_cache = $cellOptions['cache'];
  127. }
  128. }
  129. /**
  130. * Render the cell.
  131. *
  132. * @param string|null $template Custom template name to render. If not provided (null), the last
  133. * value will be used. This value is automatically set by `CellTrait::cell()`.
  134. * @return string The rendered cell.
  135. * @throws \Cake\View\Exception\MissingCellViewException When a MissingTemplateException is raised during rendering.
  136. */
  137. public function render($template = null)
  138. {
  139. if ($template !== null &&
  140. strpos($template, '/') === false &&
  141. strpos($template, '.') === false
  142. ) {
  143. $template = Inflector::underscore($template);
  144. }
  145. if ($template === null) {
  146. $template = $this->template;
  147. }
  148. $builder = $this->viewBuilder();
  149. $builder->layout(false);
  150. $builder->template($template);
  151. $cache = [];
  152. if ($this->_cache) {
  153. $cache = $this->_cacheConfig($template);
  154. }
  155. $this->View = $this->getView();
  156. $render = function () use ($template) {
  157. $className = substr(strrchr(get_class($this), "\\"), 1);
  158. $name = substr($className, 0, -4);
  159. $this->_view->viewPath('Cell' . DS . $name);
  160. try {
  161. return $this->_view->render($template);
  162. } catch (MissingTemplateException $e) {
  163. throw new MissingCellViewException(['file' => $template, 'name' => $name]);
  164. }
  165. };
  166. if ($cache) {
  167. return $this->_view->cache(function () use ($render) {
  168. echo $render();
  169. }, $cache);
  170. }
  171. return $render();
  172. }
  173. /**
  174. * Generate the cache key to use for this cell.
  175. *
  176. * If the key is undefined, the cell class and template will be used.
  177. *
  178. * @param string $template The template being rendered.
  179. * @return array The cache configuration.
  180. */
  181. protected function _cacheConfig($template)
  182. {
  183. if (empty($this->_cache)) {
  184. return [];
  185. }
  186. $key = 'cell_' . Inflector::underscore(get_class($this)) . '_' . $template;
  187. $key = str_replace('\\', '_', $key);
  188. $default = [
  189. 'config' => 'default',
  190. 'key' => $key
  191. ];
  192. if ($this->_cache === true) {
  193. return $default;
  194. }
  195. return $this->_cache + $default;
  196. }
  197. /**
  198. * Magic method.
  199. *
  200. * Starts the rendering process when Cell is echoed.
  201. *
  202. * *Note* This method will trigger an error when view rendering has a problem.
  203. * This is because PHP will not allow a __toString() method to throw an exception.
  204. *
  205. * @return string Rendered cell
  206. */
  207. public function __toString()
  208. {
  209. try {
  210. return $this->render();
  211. } catch (\Exception $e) {
  212. trigger_error('Could not render cell - ' . $e->getMessage(), E_USER_WARNING);
  213. return '';
  214. }
  215. }
  216. /**
  217. * Debug info.
  218. *
  219. * @return array
  220. */
  221. public function __debugInfo()
  222. {
  223. return [
  224. 'plugin' => $this->plugin,
  225. 'template' => $this->template,
  226. 'viewClass' => $this->viewClass,
  227. 'request' => $this->request,
  228. 'response' => $this->response,
  229. ];
  230. }
  231. }