Skip to content

Commit

Permalink
Added new feature View Cells
Browse files Browse the repository at this point in the history
  • Loading branch information
quickapps committed Apr 16, 2014
1 parent 98d4209 commit 5b85a7e
Show file tree
Hide file tree
Showing 14 changed files with 563 additions and 19 deletions.
21 changes: 2 additions & 19 deletions src/Controller/Controller.php
Expand Up @@ -27,6 +27,7 @@
use Cake\ORM\TableRegistry;
use Cake\Routing\RequestActionTrait;
use Cake\Routing\Router;
use Cake\Utility\CellTrait;
use Cake\Utility\Inflector;
use Cake\Utility\MergeVariablesTrait;
use Cake\Utility\ModelAwareTrait;
Expand Down Expand Up @@ -78,6 +79,7 @@
*/
class Controller extends Object implements EventListener {

use CellTrait;
use MergeVariablesTrait;
use ModelAwareTrait;
use RequestActionTrait;
Expand Down Expand Up @@ -723,23 +725,4 @@ public function beforeRedirect(Event $event, $url, $status = null, $exit = true)
public function afterFilter(Event $event) {
}

/**
* Constructs the view class instance based on controller properties.
* Controller stashes view variables and view configuration options in the absence of an
* instantiated view to set them on, and passes them to the View constructor here.
*
* @param string $viewClass Optional namespaced class name of the View class to instantiate.
* @return View
*/
public function createView($viewClass = null) {
if ($viewClass === null) {
$viewClass = $this->viewClass;
if ($this->viewClass !== 'View') {
list($plugin, $viewClass) = pluginSplit($viewClass, true);
$viewClass = App::classname($viewClass, 'View', 'View');
}
}
$viewOptions = array_intersect_key(get_object_vars($this), array_flip($this->_validViewOptions));
return new $viewClass($this->request, $this->response, $this->getEventManager(), $viewOptions);
}
}
84 changes: 84 additions & 0 deletions src/Utility/CellTrait.php
@@ -0,0 +1,84 @@
<?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\Utility;

use Cake\Core\App;
use Cake\Utility\Inflector;
use Cake\View\Error;

/**
* 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
*/
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->getEventManager(), $options);
$cellInstance->action = Inflector::underscore($action);
$cellInstance->plugin = !empty($plugin) ? $plugin : null;
$length = count($data);

if ($length) {
$data = array_values($data);
}

call_user_func_array([$cellInstance, $action], $data);

return $cellInstance;
}

}
21 changes: 21 additions & 0 deletions src/Utility/ViewVarsTrait.php
Expand Up @@ -13,6 +13,8 @@
*/
namespace Cake\Utility;

use Cake\Core\App;

/**
* Provides the set() method for collecting template context.
*
Expand All @@ -29,6 +31,24 @@ trait ViewVarsTrait {
*/
public $viewVars = [];

/**
* Constructs the view class instance based on object properties.
*
* @param string $viewClass Optional namespaced class name of the View class to instantiate.
* @return View
*/
public function createView($viewClass = null) {
if ($viewClass === null) {
$viewClass = $this->viewClass;
if ($this->viewClass !== 'View') {
list($plugin, $viewClass) = pluginSplit($viewClass, true);
$viewClass = App::classname($viewClass, 'View', 'View');
}
}
$viewOptions = array_intersect_key(get_object_vars($this), array_flip($this->_validViewOptions));
return new $viewClass($this->request, $this->response, $this->getEventManager(), $viewOptions);
}

/**
* Saves a variable for use inside a template.
*
Expand All @@ -49,4 +69,5 @@ public function set($name, $val = null) {
}
$this->viewVars = $data + $this->viewVars;
}

}
191 changes: 191 additions & 0 deletions src/View/Cell.php
@@ -0,0 +1,191 @@
<?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\Event\EventManager;
use Cake\Network\Request;
use Cake\Network\Response;
use Cake\Utility\Inflector;
use Cake\Utility\ModelAwareTrait;
use Cake\Utility\ViewVarsTrait;

/**
* Cell base.
*
*/
abstract class Cell {

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 action that was invoked.
*
* Action name will be inflected to get the template name when rendering.
*
* @var string
*/
public $action;

/**
* 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';

/**
* Instance of the Cake\Event\EventManager this cell is using
* to dispatch inner events.
*
* @var \Cake\Event\EventManager
*/
protected $_eventManager = null;

/**
* These properties are settable directly on Cell and passed to the View as options.
*
* @var array
* @see \Cake\View\View
*/
protected $_validViewOptions = [
'viewVars', 'helpers', 'viewPath', 'plugin',
];

/**
* List of valid options (constructor's fourth arguments)
*
* @var array
*/
protected $_validCellOptions = [];

/**
* Constructor.
*
* @param \Cake\Network\Request $request
* @param \Cake\Network\Response $response
* @param \Cake\Event\EventManager $eventManager
* @param array $cellOptions
*/
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];
}
}
}

/**
* Rendering method.
*
* @param string $action 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
*/
public function render($action = null) {
if ($action !== null) {
$this->action = $action;
}

return $this->__toString();
}

/**
* Magic method.
*
* Starts the rendering process when Cell is echoed.
*
* @return string Rendered cell
*/
public function __toString() {
$this->View = $this->createView();

$this->View->layout = false;
$className = explode('\\', get_class($this));
$className = array_pop($className);
$this->View->subDir = 'Cell' . DS . substr($className, 0, strpos($className, 'Cell'));

return $this->View->render(Inflector::underscore($this->action));
}

/**
* Debug info.
*
* @return void
*/
public function __debugInfo() {
return [
'plugin' => $this->plugin,
'action' => $this->action,
'viewClass' => $this->viewClass,
'request' => $this->request,
'response' => $this->response,
];
}

/**
* Returns the Cake\Event\EventManager manager instance for this cell.
*
* You can use this instance to register any new listeners or callbacks to the
* cell events, or create your own events and trigger them at will.
*
* @return \Cake\Event\EventManager
*/
public function getEventManager() {
if (empty($this->_eventManager)) {
$this->_eventManager = new EventManager();
}
return $this->_eventManager;
}

}
27 changes: 27 additions & 0 deletions src/View/Error/MissingCellException.php
@@ -0,0 +1,27 @@
<?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\Error;

use Cake\Error\Exception;

/**
* Used when a cell class file cannot be found.
*
*/
class MissingCellException extends Exception {

protected $_messageTemplate = 'Cell class "%s" is missing.';

}

0 comments on commit 5b85a7e

Please sign in to comment.