* @version $Id$
*/
class MVCLite_View_Helper_Registry
{
/**
* Array of available helpers.
*
* It contains already created helpers.
*
* @var array
*/
private $_helpers = array();
/**
* Instance of the registry.
*
* @var MVCLite_View_Helper_Registry
*/
private static $_instance;
/**
* Stores the paths where the helpers can lay.
*
*
* $array = array(
* 'Prefix_Of_This_Helper_' => '/usr/local/www/app/various/helpers/',
* 'MVCLite_View_Helper_' => MVCLITE_LIB . 'MVCLite/View/Helper/'
* );
*
*
* The key is the prefix for the specified object, following example
* will show:
*
*
* /usr/local/www/app/various/helpers/Foobar.php
* // contains the class Prefix_Of_This_Helper_Foobar.
*
*
* @var array
*/
private $_paths = array();
/**
* The constructor is hidden since this class is a singleton.
*
* It configures the registry by adding a new path for view-helpers.
*/
private function __construct ()
{
$this->addPath(
substr(__CLASS__, 0, strrpos(__CLASS__, '_') + 1),
dirname(__FILE__)
);
}
/**
* Returns the name of a helper which fits to that name.
*
* Firstly it checks for classes that probably exist and
* fit to the given helper-name. Thereafter the paths
* are checked. When a helper in the paths match, it
* is included and thereafter the name of the class
* is returned.
* If no helper matches an MVCLite_View_Helper_Exception will
* be thrown.
*
* @param string $name name of the helper to check
* @return string
* @throws MVCLite_View_Helper_Exception
*/
private function _checkHelper ($name)
{
foreach(array_keys($this->_paths) as $prefix)
{
if(class_exists($prefix . $name, false))
{
return $prefix . $name;
}
}
foreach($this->_paths as $prefix => $path)
{
if(file_exists($path . $name . '.php'))
{
require_once $path . $name . '.php';
return $prefix . $name;
}
}
throw new MVCLite_View_Helper_Exception('Helper "' . $name . '" not found');
}
/**
* Returns the formatted helper-name.
*
* @param string $name name of a helper
* @return string
*/
private function _format ($name)
{
return ucfirst($name);
}
/**
* Adds a new path to the internal path-array.
*
* You should be careful with the prefix, do not forget the
* "_", since this is an error often done.
*
* @param string $prefix prefix for the classes in that path
* @param string $path path where the helpers reside
* @return MVCLite_View_Helper_Registry
*/
public function addPath ($prefix, $path)
{
$this->_paths[$prefix] = realpath($path). '/';
return $this;
}
/**
* Calls a helper with the specified arguments.
*
* @param string $helper name of the helper to call
* @param array $arguments arguments specified for the call
* @return mixed
* @throws MVCLite_View_Helper_Exception
*/
public function call ($helper, array $arguments = array())
{
$obj = $this->loadHelper($helper);
$method = strtolower($helper);
if(!$arguments)
{
return $obj->$method();
}
return call_user_func_array(array($obj, $method), $arguments);
}
/**
* Returns a helper.
*
* If the helper does not exist, a MVCLite_View_Helper_Exception
* will be thrown.
*
* @param string $name name of the helper
* @return MVCLite_View_Helper_Abstract
* @throws MVCLite_View_Helper_Exception
*/
public function getHelper ($name)
{
$name = $this->_format($name);
if($this->helperExists($name))
{
return $this->_helpers[$name];
}
throw new MVCLite_View_Helper_Exception(
'The helper "' . $name . '" does not exist'
);
}
/**
* This method returns a registry object.
*
* @return MVCLite_View_Helper_Registry
*/
public static function getInstance ()
{
if(self::$_instance == null)
{
self::$_instance = new self();
}
return self::$_instance;
}
/**
* Returns the path corresponding to the prefix.
*
* @param string
* @return string
*/
public function getPath ($prefix)
{
if(!isset($this->_paths[$prefix]))
{
return '';
}
return $this->_paths[$prefix];
}
/**
* Returns true if the helper already exists in the registry.
*
* @param string $name name of the helper
* @return boolean
*/
public function helperExists ($name)
{
return (isset($this->_helpers[$this->_format($name)]));
}
/**
* Loads a helper and returns its instance.
*
* If an instance already exists, it is returned instead of
* creating a new one. When a helper with that name could
* not be loaded, a "MVCLite_View_Helper_Exception" will
* be thrown.
*
* @param string $name name of the helper
* @return MVCLite_View_Helper_Abstract
* @throws MVCLite_View_Helper_Exception
*/
public function loadHelper ($name)
{
$name = $this->_format($name);
try
{
return $this->getHelper($name);
}
catch (MVCLite_View_Helper_Exception $e)
{
;
}
$class = $this->_checkHelper($name);
$result = new $class();
if($result instanceof MVCLite_View_Helper_Abstract)
{
$this->_helpers[$name] = $result;
return $result;
}
throw new MVCLite_View_Helper_Exception(
'The helper with the classname "' . $class . '" does not extend the abstract ' .
'helper-class.'
);
}
/**
* Removes a path using the specified prefix.
*
* @param string $prefix prefix of the path to remove
* @return MVCLite_View_Helper_Registry
*/
public function removePath ($prefix)
{
if(isset($this->_paths[$prefix]))
{
unset($this->_paths[$prefix]);
}
return $this;
}
/**
* Replaces the old paths array with a new one.
*
* @param array $array new path-array
* @return MVCLite_View_Helper_Registry
*/
public function setPath (array $array)
{
$this->_paths = $array;
return $this;
}
}
?>