Skip to content

Instantly share code, notes, and snippets.

@TamiasSibiricus
Last active August 29, 2015 14:05
Show Gist options
  • Save TamiasSibiricus/95eb56e66bb97b6753cf to your computer and use it in GitHub Desktop.
Save TamiasSibiricus/95eb56e66bb97b6753cf to your computer and use it in GitHub Desktop.
merge view helpers with cell helpers
<?php
/**
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @since 3.0.0
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace Cake\View;
use Cake\Event\EventManager;
use Cake\Event\EventManagerTrait;
use Cake\Model\ModelAwareTrait;
use Cake\Network\Request;
use Cake\Network\Response;
use Cake\Utility\Inflector;
use Cake\View\Error\MissingCellViewException;
use Cake\View\Error\MissingViewException;
use Cake\View\ViewVarsTrait;
/**
* Cell base.
*
*/
abstract class Cell {
use EventManagerTrait;
use ModelAwareTrait;
use ViewVarsTrait;
/**
* Instance of the View created during rendering. Won't be set until after
* Cell::__toString() is called.
*
* @var \Cake\View\View
*/
public $View;
/**
* Name of the template that will be rendered.
* This property is inflected from the action name that was invoked.
*
* @var string
*/
public $template;
/**
* An array containing the names of helpers this controller uses. The array elements should
* not contain the "Helper" part of the class name.
*
* @var mixed
*/
public $helpers = [];
/**
* Automatically set to the name of a plugin.
*
* @var string
*/
public $plugin = null;
/**
* An instance of a Cake\Network\Request object that contains information about the current request.
* This object contains all the information about a request and several methods for reading
* additional information about the request.
*
* @var \Cake\Network\Request
*/
public $request;
/**
* An instance of a Response object that contains information about the impending response
*
* @var \Cake\Network\Response
*/
public $response;
/**
* The name of the View class this cell sends output to.
*
* @var string
*/
public $viewClass = 'Cake\View\View';
/**
* The theme name that will be used to render.
*
* @var string
*/
public $theme;
/**
* These properties can be set directly on Cell and passed to the View as options.
*
* @var array
* @see \Cake\View\View
*/
protected $_validViewOptions = [
'viewVars', 'helpers', 'viewPath', 'plugin', 'theme'
];
/**
* List of valid options (constructor's fourth arguments)
* Override this property in subclasses to whitelist
* which options you want set as properties in your Cell.
*
* @var array
*/
protected $_validCellOptions = [];
/**
* Constructor.
*
* @param \Cake\Network\Request $request the request to use in the cell
* @param \Cake\Network\Response $response the response to use in the cell
* @param \Cake\Event\EventManager $eventManager then eventManager to bind events to
* @param array $cellOptions cell options to apply
*/
public function __construct(Request $request = null, Response $response = null,
EventManager $eventManager = null, array $cellOptions = []) {
$this->eventManager($eventManager);
$this->request = $request;
$this->response = $response;
$this->modelFactory('Table', ['Cake\ORM\TableRegistry', 'get']);
foreach ($this->_validCellOptions as $var) {
if (isset($cellOptions[$var])) {
$this->{$var} = $cellOptions[$var];
}
}
}
/**
* Render the cell.
*
* @param string $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 void
* @throws \Cake\View\Error\MissingCellViewException When a MissingViewException is raised during rendering.
*/
public function render($template = null) {
if ($template !== null && strpos($template, '/') === false) {
$template = Inflector::underscore($template);
}
if ($template === null) {
$template = $this->template;
}
$this->View = $this->createView();
$this->View->layout = false;
$className = explode('\\', get_class($this));
$className = array_pop($className);
$name = substr($className, 0, strpos($className, 'Cell'));
$this->View->subDir = 'Cell' . DS . $name;
try {
return $this->View->render($template);
} catch (MissingViewException $e) {
throw new MissingCellViewException(['file' => $template, 'name' => $name]);
}
}
/**
* 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
*/
public function __toString() {
try {
return $this->render();
} catch (\Exception $e) {
trigger_error('Could not render cell - ' . $e->getMessage(), E_USER_WARNING);
return '';
}
}
/**
* Debug info.
*
* @return void
*/
public function __debugInfo() {
return [
'plugin' => $this->plugin,
'template' => $this->template,
'viewClass' => $this->viewClass,
'request' => $this->request,
'response' => $this->response,
];
}
}
<?php
/**
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @since 3.0.0
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace Cake\View;
use Cake\Core\App;
use Cake\Utility\Inflector;
use Cake\Utility\Hash;
/**
* Provides cell() method for usage in Controller and View classes.
*
*/
trait CellTrait {
/**
* Renders the given cell.
*
* Example:
*
* {{{
* // Taxonomy\View\Cell\TagCloudCell::smallList()
* $cell = $this->cell('Taxonomy.TagCloud::smallList', ['limit' => 10]);
*
* // App\View\Cell\TagCloudCell::smallList()
* $cell = $this->cell('TagCloud::smallList', ['limit' => 10]);
* }}}
*
* The `display` action will be used by default when no action is provided:
*
* {{{
* // Taxonomy\View\Cell\TagCloudCell::display()
* $cell = $this->cell('Taxonomy.TagCloud');
* }}}
*
* Cells are not rendered until they are echoed.
*
* @param string $cell You must indicate both cell name, and optionally a cell action. e.g.: `TagCloud::smallList`
* will invoke `View\Cell\TagCloudCell::smallList()`, `display` action will be invoked by default when none is provided.
* @param array $data Additional arguments for cell method. e.g.:
* `cell('TagCloud::smallList', ['a1' => 'v1', 'a2' => 'v2'])` maps to `View\Cell\TagCloud::smallList(v1, v2)`
* @param array $options Options for Cell's constructor
* @return \Cake\View\Cell The cell instance
* @throws \Cake\View\Error\MissingCellException If Cell class was not found.
* @throws \BadMethodCallException If Cell class does not specified cell action.
*/
public function cell($cell, $data = [], $options = []) {
$parts = explode('::', $cell);
if (count($parts) == 2) {
list($pluginAndCell, $action) = [$parts[0], $parts[1]];
} else {
list($pluginAndCell, $action) = [$parts[0], 'display'];
}
list($plugin, $cellName) = pluginSplit($pluginAndCell);
$className = App::className($pluginAndCell, 'View/Cell', 'Cell');
if (!$className) {
throw new Error\MissingCellException(array('className' => $pluginAndCell . 'Cell'));
}
$cellInstance = new $className($this->request, $this->response, $this->eventManager(), $options);
$cellInstance->template = Inflector::underscore($action);
$cellInstance->plugin = !empty($plugin) ? $plugin : null;
$cellInstance->theme = !empty($this->theme) ? $this->theme : null;
//merge view helpers with cell helpers
//maybe very dirty solution
if(isset($this->helpers)&&is_array($this->helpers)){
$cellInstance->helpers = Hash::merge($this->helpers, $cellInstance->helpers);
}
$length = count($data);
if ($length) {
$data = array_values($data);
}
try {
$reflect = new \ReflectionMethod($cellInstance, $action);
$reflect->invokeArgs($cellInstance, $data);
return $cellInstance;
} catch (\ReflectionException $e) {
throw new \BadMethodCallException(sprintf(
'Class %s does not have a "%s" method.',
$className,
$action
));
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment