setEventManager($eventManager); } $this->request = $request; $this->response = $response; $this->modelFactory('Table', [$this->getTableLocator(), 'get']); $this->_validCellOptions = array_merge(['action', 'args'], $this->_validCellOptions); foreach ($this->_validCellOptions as $var) { if (isset($cellOptions[$var])) { $this->{$var} = $cellOptions[$var]; } } if (!empty($cellOptions['cache'])) { $this->_cache = $cellOptions['cache']; } $this->initialize(); } /** * Initialization hook method. * * Implement this method to avoid having to overwrite * the constructor and calling parent::__construct(). * * @return void */ public function initialize() { } /** * Render the cell. * * @param string|null $template Custom template name to render. If not provided (null), the last * value will be used. This value is automatically set by `CellTrait::cell()`. * @return string The rendered cell. * @throws \Cake\View\Exception\MissingCellViewException When a MissingTemplateException is raised during rendering. */ public function render($template = null) { $cache = []; if ($this->_cache) { $cache = $this->_cacheConfig($this->action, $template); } $render = function () use ($template) { try { $reflect = new ReflectionMethod($this, $this->action); $reflect->invokeArgs($this, $this->args); } catch (ReflectionException $e) { throw new BadMethodCallException(sprintf( 'Class %s does not have a "%s" method.', get_class($this), $this->action )); } $builder = $this->viewBuilder()->setLayout(false); if ($template !== null && strpos($template, '/') === false && strpos($template, '.') === false ) { $template = Inflector::underscore($template); } if ($template !== null) { $builder->setTemplate($template); } $className = get_class($this); $namePrefix = '\View\Cell\\'; $name = substr($className, strpos($className, $namePrefix) + strlen($namePrefix)); $name = substr($name, 0, -4); if (!$builder->getTemplatePath()) { $builder->setTemplatePath('Cell' . DIRECTORY_SEPARATOR . str_replace('\\', DIRECTORY_SEPARATOR, $name)); } $this->View = $this->createView(); try { return $this->View->render($template); } catch (MissingTemplateException $e) { throw new MissingCellViewException(['file' => $template, 'name' => $name], null, $e); } }; if ($cache) { return Cache::remember($cache['key'], $render, $cache['config']); } return $render(); } /** * Generate the cache key to use for this cell. * * If the key is undefined, the cell class and action name will be used. * * @param string $action The action invoked. * @param string|null $template The name of the template to be rendered. * @return array The cache configuration. */ protected function _cacheConfig($action, $template = null) { if (empty($this->_cache)) { return []; } $template = $template ?: 'default'; $key = 'cell_' . Inflector::underscore(get_class($this)) . '_' . $action . '_' . $template; $key = str_replace('\\', '_', $key); $default = [ 'config' => 'default', 'key' => $key ]; if ($this->_cache === true) { return $default; } return $this->_cache + $default; } /** * Magic method. * * Starts the rendering process when Cell is echoed. * * *Note* This method will trigger an error when view rendering has a problem. * This is because PHP will not allow a __toString() method to throw an exception. * * @return string Rendered cell * @throws \Error Include error details for PHP 7 fatal errors. */ public function __toString() { try { return $this->render(); } catch (Exception $e) { trigger_error(sprintf('Could not render cell - %s [%s, line %d]', $e->getMessage(), $e->getFile(), $e->getLine()), E_USER_WARNING); return ''; } catch (Error $e) { throw new Error(sprintf('Could not render cell - %s [%s, line %d]', $e->getMessage(), $e->getFile(), $e->getLine())); } } /** * Magic accessor for removed properties. * * @param string $name Property name * @return mixed */ public function __get($name) { $deprecated = [ 'template' => 'getTemplate', 'plugin' => 'getPlugin', 'helpers' => 'getHelpers', ]; if (isset($deprecated[$name])) { $method = $deprecated[$name]; deprecationWarning(sprintf( 'Cell::$%s is deprecated. Use $cell->viewBuilder()->%s() instead.', $name, $method )); return $this->viewBuilder()->{$method}(); } $protected = [ 'action', 'args', 'request', 'response', 'View', ]; if (in_array($name, $protected, true)) { deprecationWarning(sprintf( 'Cell::$%s is now protected and shouldn\'t be accessed from outside a child class.', $name )); } return $this->{$name}; } /** * Magic setter for removed properties. * * @param string $name Property name. * @param mixed $value Value to set. * @return void */ public function __set($name, $value) { $deprecated = [ 'template' => 'setTemplate', 'plugin' => 'setPlugin', 'helpers' => 'setHelpers', ]; if (isset($deprecated[$name])) { $method = $deprecated[$name]; deprecationWarning(sprintf( 'Cell::$%s is deprecated. Use $cell->viewBuilder()->%s() instead.', $name, $method )); $this->viewBuilder()->{$method}($value); return; } $protected = [ 'action', 'args', 'request', 'response', 'View', ]; if (in_array($name, $protected, true)) { deprecationWarning(sprintf( 'Cell::$%s is now protected and shouldn\'t be accessed from outside a child class.', $name )); } $this->{$name} = $value; } /** * Debug info. * * @return array */ public function __debugInfo() { return [ 'action' => $this->action, 'args' => $this->args, 'request' => $this->request, 'response' => $this->response, 'viewBuilder' => $this->viewBuilder(), ]; } }