%PDF- %PDF-
| Direktori : /home1/lightco1/public_html/lightingrepublic.com.au/libraries/koowa/controller/ |
| Current File : //home1/lightco1/public_html/lightingrepublic.com.au/libraries/koowa/controller/abstract.php |
<?php
/**
* @version $Id$
* @package Koowa_Controller
* @copyright Copyright (C) 2007 - 2012 Johan Janssens. All rights reserved.
* @license GNU GPLv3 <http://www.gnu.org/licenses/gpl.html>
* @link http://www.nooku.org
*/
/**
* Abstract Controller Class
*
* Note: Concrete controllers must have a singular name
*
* @author Johan Janssens <johan@nooku.org>
* @package Koowa_Controller
* @uses KMixinClass
* @uses KCommandChain
*/
abstract class KControllerAbstract extends KObject
{
/**
* Array of class methods to call for a given action.
*
* @var array
*/
protected $_action_map = array();
/**
* The class actions
*
* @var array
*/
protected $_actions;
/**
* Has the controller been dispatched
*
* @var boolean
*/
protected $_dispatched;
/**
* The request information
*
* @var array
*/
protected $_request = null;
/**
* List of behaviors
*
* Associative array of behaviors, where key holds the behavior identifier string
* and the value is an identifier object.
*
* @var array
*/
protected $_behaviors = array();
/**
* Constructor.
*
* @param object An optional KConfig object with configuration options.
*/
public function __construct( KConfig $config = null)
{
//If no config is passed create it
if(!isset($config)) $config = new KConfig();
parent::__construct($config);
//Set the dispatched state
$this->_dispatched = $config->dispatched;
// Mixin the command chain
$this->mixin(new KMixinCommandchain($config->append(array('mixer' => $this))));
//Set the request
$this->setRequest((array) KConfig::unbox($config->request));
// Set the table behaviors
if(!empty($config->behaviors)) {
$this->addBehavior($config->behaviors);
}
}
/**
* Initializes the default configuration for the object
*
* Called from {@link __construct()} as a first step of object instantiation.
*
* @param object An optional KConfig object with configuration options.
* @return void
*/
protected function _initialize(KConfig $config)
{
$config->append(array(
'command_chain' => new KCommandChain(),
'dispatch_events' => true,
'enable_callbacks' => true,
'dispatched' => false,
'request' => null,
'behaviors' => array(),
));
parent::_initialize($config);
}
/**
* Has the controller been dispatched
*
* @return boolean Returns true if the controller has been dispatched
*/
public function isDispatched()
{
return $this->_dispatched;
}
/**
* Execute an action by triggering a method in the derived class.
*
* @param string The action to execute
* @param object A command context object
* @return mixed|false The value returned by the called method, false in error case.
* @throws KControllerException
*/
public function execute($action, KCommandContext $context)
{
$action = strtolower($action);
//Update the context
$context->action = $action;
$context->caller = $this;
//Find the mapped action
if (isset( $this->_action_map[$action] )) {
$command = $this->_action_map[$action];
} else {
$command = $action;
}
//Execute the action
if($this->getCommandChain()->run('before.'.$command, $context) !== false)
{
$method = '_action'.ucfirst($command);
if(!method_exists($this, $method))
{
//Lazy mix behaviors
if(!isset($this->_mixed_methods[$method]))
{
foreach($this->getBehaviors() as $behavior) {
$this->mixin($behavior);
}
}
if(isset($this->_mixed_methods[$command])) {
$context->result = $this->_mixed_methods[$command]->execute('action.'.$command, $context);
} else {
throw new KControllerException("Can't execute '$command', method: '$method' does not exist");
}
}
else $context->result = $this->$method($context);
$this->getCommandChain()->run('after.'.$command, $context);
}
//Handle exceptions
if($context->getError() instanceof KException)
{
//@TODO : Move header handling into a response object
if($context->headers)
{
foreach($context->headers as $name => $value) {
header($name.' : '.$value);
}
}
throw $context->getError();
}
return $context->result;
}
/**
* Gets the available actions in the controller.
*
* @return array Array[i] of action names.
*/
public function getActions($reload = false)
{
if(!$this->_actions || $reload)
{
$this->_actions = array();
foreach($this->getMethods() as $method)
{
if(substr($method, 0, 7) == '_action') {
$this->_actions[] = strtolower(substr($method, 7));
}
}
foreach($this->_behaviors as $behavior)
{
foreach($behavior->getMethods() as $method)
{
if(substr($method, 0, 7) == '_action') {
$this->_actions[] = strtolower(substr($method, 7));
}
}
}
$this->_actions = array_unique(array_merge($this->_actions, array_keys($this->_action_map)));
}
return $this->_actions;
}
/**
* Get the request information
*
* @return KConfig A KConfig object with request information
*/
public function getRequest()
{
return $this->_request;
}
/**
* Set the request information
*
* @param array An associative array of request information
* @return KControllerBread
*/
public function setRequest(array $request)
{
$this->_request = new KConfig();
foreach($request as $key => $value) {
$this->$key = $value;
}
return $this;
}
/**
* Check if a behavior exists
*
* @param string The name of the behavior
* @return boolean TRUE if the behavior exists, FALSE otherwise
*/
public function hasBehavior($behavior)
{
return isset($this->_behaviors[$behavior]);
}
/**
* Add one or more behaviors to the controller
*
* @param array Array of one or more behaviors to add.
* @return KControllerAbstract
*/
public function addBehavior($behaviors)
{
$behaviors = (array) KConfig::unbox($behaviors);
foreach($behaviors as $behavior)
{
if (!($behavior instanceof KControllerBehaviorInterface)) {
$behavior = $this->getBehavior($behavior);
} else {
$behavior->setMixer($this);
}
//Add the behaviors
$this->_behaviors[$behavior->getIdentifier()->name] = $behavior;
if($this->getCommandChain()->enqueue($behavior)) {
$this->_actions = null; //reset the actions
}
}
return $this;
}
/**
* Get a behavior by identifier
*
* @return KControllerBehaviorAbstract
*/
public function getBehavior($behavior, $config = array())
{
if(!($behavior instanceof KServiceIdentifier))
{
//Create the complete identifier if a partial identifier was passed
if(is_string($behavior) && strpos($behavior, '.') === false )
{
$identifier = clone $this->getIdentifier();
$identifier->path = array('controller', 'behavior');
$identifier->name = $behavior;
}
else $identifier = $this->getIdentifier($behavior);
}
if(!isset($this->_behaviors[$identifier->name]))
{
$behavior = $this->getService($identifier, array_merge($config, array('mixer' => $this)));
//Check the behavior interface
if(!($behavior instanceof KControllerBehaviorInterface)) {
throw new KControllerBehaviorException("Controller behavior $identifier does not implement KControllerBehaviorInterface");
}
}
else $behavior = $this->_behaviors[$identifier->name];
return $behavior;
}
/**
* Gets the behaviors of the table
*
* @return array An asscociate array of table behaviors, keys are the behavior names
*/
public function getBehaviors()
{
return $this->_behaviors;
}
/**
* Register (map) an action to a method in the class.
*
* @param string The action.
* @param string The name of the method in the derived class to perform
* for this action.
* @return KControllerAbstract
*/
public function registerActionAlias( $alias, $action )
{
$alias = strtolower( $alias );
if ( !in_array($alias, $this->getActions()) ) {
$this->_action_map[$alias] = $action;
}
//Force reload of the actions
$this->getActions(true);
return $this;
}
/**
* Set a request properties
*
* @param string The property name.
* @param mixed The property value.
*/
public function __set($property, $value)
{
$this->_request->$property = $value;
}
/**
* Get a request property
*
* @param string The property name.
* @return string The property value.
*/
public function __get($property)
{
$result = null;
if(isset($this->_request->$property)) {
$result = $this->_request->$property;
}
return $result;
}
/**
* Execute a controller action by it's name.
*
* Function is also capable of checking is a behavior has been mixed succesfully
* using is[Behavior] function. If the behavior exists the function will return
* TRUE, otherwise FALSE.
*
* @param string Method name
* @param array Array containing all the arguments for the original call
* @see execute()
*/
public function __call($method, $args)
{
//Handle action alias method
if(in_array($method, $this->getActions()))
{
//Get the data
$data = !empty($args) ? $args[0] : array();
//Create a context object
if(!($data instanceof KCommandContext))
{
$context = $this->getCommandContext();
$context->data = $data;
$context->result = false;
}
else $context = $data;
//Execute the action
return $this->execute($method, $context);
}
//Check if a behavior is mixed
$parts = KInflector::explode($method);
if($parts[0] == 'is' && isset($parts[1]))
{
//Lazy mix behaviors
$behavior = strtolower($parts[1]);
if(!isset($this->_mixed_methods[$method]))
{
if($this->hasBehavior($behavior))
{
$this->mixin($this->getBehavior($behavior));
return true;
}
return false;
}
return true;
}
return parent::__call($method, $args);
}
}