<?php
/**
* LRegistry Class
*
* Managing globals with the registry pattern.
* This class provides lazy loading functionallity. This means it is possible to
* add a callback or class (with arguments) which will be called or instanciated
* when it is being used for the first time.
*
* @version 1.0
* @author Victor Villaverde Laan
* @link http://www.freelancephp.net/php-lazy-registry-class/
* @license MIT license
*/
class LRegistry {
/**
* Singleton pattern
* @var Registry object
*/
private static $_instance = NULL;
/**
* Containing all entries
* @var array
*/
private $_entries = array();
/**
* Default overwrite entries when being set more than once
* @var boolean
*/
private $_default_overwrite = TRUE;
/**
* Private contructer for singleton protection
*/
private final function __construct() {
}
/**
* Private clone method for singleton protection
*/
private final function __clone() {
}
/**
* Get instance of this class
* @return Registry object
*/
public static function get_instance() {
if ( self::$_instance === NULL )
self::$_instance = new LRegistry;
return self::$_instance;
}
/**
* Get value of given key
* @param string $key
* @param boolean $reload reload if class or callback was already loaded
* @return mixed
*/
public static function get( $key, $reload = FALSE ) {
$instance = self::get_instance();
// check if entry exists
if ( ! key_exists( $key, $instance->_entries ) )
$instance->_exception( 'Key "' . $key . '" could not be found.' );
// get current entry
$entry = $instance->_entries[$key];
// check if entry should be loaded or reloaded
if ( ! $entry['loaded'] OR $reload ) {
if ( $entry['type'] == 'class' ) {
// get reflection class
$ref_class = new ReflectionClass( $entry['class'] );
// create instance
$entry['value'] = $ref_class->newInstanceArgs( $entry['args'] );
} else if ( $entry['type'] == 'callback' ) {
// run callback and set return value
$entry['value'] = call_user_func_array( $entry['callback'], $entry['args'] );
} else {
$instance->_exception( 'Type "' . $type . '" is not supported.' );
}
// set (new) value and change "loaded" setting
$instance->_entries[$key]['value'] = $entry['value'];
$instance->_entries[$key]['loaded'] = TRUE;
}
return $entry['value'];
}
/**
* Set value of given key
* @param string $key
* @param mixed $value
* @param boolean $overwrite optional, when set will ignore the default overwrite setting
* @return boolean value was set succesfully
*/
public static function set( $key, $value, $overwrite = NULL ) {
// set normal value settings
$settings = array( 'type' => 'value',
'loaded' => TRUE,
'value' => $value );
return self::get_instance()->_set( $key, $settings, $overwrite );
}
/**
* Set lazy entry of a class. Instance will only be created when entry
* is requested using the get method.
* @param string $key
* @param string $class
* @param array $args
* @param boolean $overwrite optional, when set will ignore the default overwrite setting
* @return boolean value was set succesfully
*/
public static function set_lazy_class( $key, $class, $args = array(), $overwrite = NULL ) {
// set lazy class settings
$settings = array( 'type' => 'class',
'class' => $class,
'args' => $args,
'loaded' => FALSE,
'value' => NULL );
return self::get_instance()->_set( $key, $settings, $overwrite );
}
/**
* Set lazy entry of a callback function.Function will only be called when entry
* is requested using the get method.
* @param string $key
* @param array $callback
* @param array $args
* @param boolean $overwrite optional, when set will ignore the default overwrite setting
* @return boolean value was set succesfully
*/
public static function set_lazy_callback( $key, $callback, $args = array(), $overwrite = NULL ) {
// set lazy callback settings
$settings = array( 'type' => 'callback',
'callback' => $callback,
'args' => $args,
'loaded' => FALSE,
'value' => NULL );
return self::get_instance()->_set( $key, $settings, $overwrite );
}
/**
* Check if given entry exists
* @param string $key
* @return boolean
*/
public static function has( $key ) {
return key_exists( $key, self::get_instance()->_entries );
}
/**
* Check if given (lazy) entry is already loaded
* @param string $key
* @return boolean
*/
public static function is_loaded( $key ) {
return ( self::has( $key ) AND self::get_instance()->_entries[$key]['loaded'] === TRUE );
}
/**
* Remove the given entry
* @param string $key
*/
public static function remove( $key ) {
if ( ! self::has( $key ) )
self::get_instance()->_exception( 'Key "' . $key . '"does not exist.' );
unset( self::get_instance()->_entries[$key] );
}
/**
* Set default overwriting entries when being set more than once.
* @param boolean|NULL $overwrite optional, if empty can be used as a getter
* @return boolean
*/
public static function default_overwrite( $overwrite = NULL ) {
if ( $overwrite !== NULL )
self::get_instance()->_default_overwrite = (bool) $overwrite;
return self::get_instance()->_default_overwrite;
}
/**
* Set value of given key (private use)
* @param string $key
* @param mixed $settings
* @param boolean $overwrite optional, when set will ignore the default overwrite setting
* @return boolean value was set succesfully
*/
protected function _set( $key, $settings, $overwrite = NULL ) {
$instance = self::get_instance();
// check if overwriting is allowed
$overwrite = ( $overwrite === NULL )
? $this->_default_overwrite
: $overwrite;
// check if entry exists and overwriting is allowed
if ( key_exists( $key, $this->_entries ) AND ! $overwrite )
return FALSE;
$this->_entries[$key] = $settings;
return TRUE;
}
/**
* Throw an exception
* @param string $message
*/
protected function _exception( $message ) {
throw new Exception( 'LRegistry: ' . $message );
}
}
/*?> // ommit closing tag, to prevent unwanted whitespace at the end of the parts generated by the included files */