<?
/**
* superGlobals library
*
* Transparently injects into superglobal or global variable with keeping all functionality of regular
* array, but extending it with type casting and URI parsing.
*
* Usage:
*
* superGlobal::db($instance);
*
* Set DB instance for all DB-related operations.
*
* superGlobal::memcached($instance)
*
* Set Memcache instance to enable built-in cache
*
* superGlobal::inject($array|$string);
*
* Inject superGlobal functionality into global or superglobal variable.
* If additional parameters passed with registerParam or registerSQLParam overlaps already existing
* parameters in array, initial value will be stored in parameter array, which is accessible as
* $array['array:param'].
*
* If passed variable contains string, it will be stored as URI for future parsing by registerParam or
* registerSQLParam methods.
*
* superGlobal::registerParam('name', 'callback');
* superGlobal::registerParam('name', array(values));
*
* Inject into $_GET (if was not injected previously), then parse URI parameters into all of injected global arrays
* and only $_GET superglobal array, so if URI string parameter (REQUEST_URI for $_GET or manually provided for
* other arrays) contains parameter from values array provided or provided callback function will return something
* different from false, this piece will be stored in resulting array with name key.
*
* superGlobal::registerParam('type:name', 'callback');
* superGlobal::registerParam('type:name', array(values));
*
* Same as previous example, except URI parameter will be additionally casted into provided type.
*
* superGlobal::registerSQLParam('name', 'table', 'field');
* superGlobal::registerSQLParam('type:name', 'table', 'field');
*
* List of possible values for parameter will be fetched from SQL table 'table' from field 'field'.
* (DB abstraction instance should be provided and getCol method should be implemented)
*
* superGlobal::registerParam('name', 'callback', $array);
* superGlobal::registerSQLParam('name', 'table', 'field', $array);
*
* Register param into only one array. Also allows to inject parameters into superglobal arrays different
* from $_GET.
*
* After injecting it provides several casting methods for all of array variables, which should be defined in
* requesting variable name and separated from it by semicolon:
*
* Fetch variable as boolean (returns boolean):
* $_SUPERGLOBAL['bool:key']
*
* Fetch variable as integer (returns integer):
* $_SUPERGLOBAL['int:key']
*
* Fetch variable as float (returns float):
* $_SUPERGLOBAL['float:key']
*
* Fetch variable as regular string (returns string):
* $_SUPERGLOBAL['string:key']
*
* Fetch variable as array (returns array):
* $_SUPERGLOBAL['array:key']
*
* Fetch variable as IP address (IPv6 or IPv4) (returns string):
* $_SUPERGLOBAL['ip:key']
*
* Fetch variable as IP address (IPv4 or IPv6), only from public networks (returns string):
* $_SUPERGLOBAL['ippub:key']
*
* Fetch variable as IP address (only IPv4) (returns string):
* $_SUPERGLOBAL['ipv4:key']
*
* Fetch variable as IP address (only IPv6) (returns string):
* $_SUPERGLOBAL['ipv6:key']
*
* Fetch variable as regular expression (returns string):
* $_SUPERGLOBAL['regexp:key']
*
* Fetch variable as correct URL (returns string):
* $_SUPERGLOBAL['url:key']
*
* Fetch variable as URL encoded string (returns string):
* $_SUPERGLOBAL['encode:key']
*
* Fetch variable as HTML escaped string (returns string):
* $_SUPERGLOBAL['escape:key']
*
* Fetch variable as regular object (returns object):
* $_SUPERGLOBAL['object:key']
*
* Fetch variable as SQL escaped string (returns string):
* $_SUPERGLOBAL['sql:key']
*
* It is possible to pass function name callback as casting method, for example, next will return trimmed
* value of $_SUPERGLOBAL['key'].
* $_SUPERGLOBAL['trim:key']
*
* Also, it is possible to pass multiple casting methods, which is useful for array processing, next will return an
* array with all matching values for $_SUPERGLOBAL['key'] casted to float and then cos() function applied.
* $_SUPERGLOBAL['array:float:cos:key']
*
* May throw exceptions (Exception $e) with codes:
* 1: Trying to directly create an instance of class
* 100: DB driver is not set or method missing
* 200: There is no filter.so installed
* 300: Callback or casting (if enabled) exception
* 400: Trying to register variable that is not global
* 500: Incorrect use of registerParam or registerSQLParam functions
* 600: Memcache exception
*
* License
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file license.txt.
* It is also available through the world-wide-web at this URL:
* http://ics.net.ua/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to hide@address.com so we can send you a copy immediately.
*
* @package superGlobals
* @author Max S. Yarchevsky
* @license http://ics.net.ua/license/new-bsd New BSD License
* @version 1.133
*/
/**
* Helper class to inject into superglobal.
* Provides value casting and URL string parsing.
* Should not be called directly.
*
* @uses ArrayAccess
* @uses Iterator
* @uses Countable
* @package superGlobals
* @author Max S. Yarchevsky
* @license New BSD License
* @version 1.133
*/
class requestCaster extends superGlobal implements ArrayAccess, Iterator, Countable
{
/**
* Storage of params found from URL or passed from request
*
* @var array
*/
private $storage;
/**
* Array of possible param values
*
* @var array
*/
private $values;
/**
* If param need additional casting, callback function or type should be stored here
*
* @var array
*/
private $castCallbacks;
/**
* Data types and regular expressions for variable casting
*
* @var array
*/
private static $castMethods;
/**
* Unparsed values that left after last iteration
*
* @var array
*/
private $unParsed;
/**
* General class contructor. Should not be called directly.
*
* @param array $params Array data to merge into instance
* @param string $URI Uniform resource identifier string to parse values from
* @return boolean|void
*/
public function __construct(array &$params, $URI = false)
{
// Define casting methods
if (!is_array(self::$castMethods))
{
self::$castMethods = array(
// Possible variable types for filtering
'varTypes' => array(
// Boolean type. Can be false|true|1|0
'bool' => array(
'filter' => FILTER_VALIDATE_BOOLEAN,
'options' => FILTER_NULL_ON_FAILURE,
'cast' => 'bool'
),
// Integer type
'int' => array(
'filter' => FILTER_SANITIZE_NUMBER_INT,
'options' => FILTER_NULL_ON_FAILURE,
'cast' => 'int'
),
// Float type
'float' => array(
'filter' => FILTER_SANITIZE_NUMBER_FLOAT,
'options' => FILTER_NULL_ON_FAILURE + FILTER_FLAG_ALLOW_FRACTION + FILTER_FLAG_ALLOW_SCIENTIFIC,
'cast' => 'float'
),
// Regular string
'string' => array(
'filter' => FILTER_SANITIZE_STRING,
'options' => FILTER_NULL_ON_FAILURE,
'cast' => 'string'
),
// Regular array
'array' => array(
'cast' => 'array'
),
// IP address (IPv4 or IPv6)
'ip' => array(
'filter' => FILTER_VALIDATE_IP,
'options' => FILTER_NULL_ON_FAILURE,
'cast' => 'string'
),
// IP address (IPv4 or IPv6), only from public networks
'ippub' => array(
'filter' => FILTER_VALIDATE_IP,
'options' => FILTER_NULL_ON_FAILURE + FILTER_FLAG_NO_PRIV_RANGE,
'cast' => 'string'
),
// IP address (only IPv4)
'ipv4' => array(
'filter' => FILTER_VALIDATE_IP,
'options' => FILTER_NULL_ON_FAILURE + FILTER_FLAG_IPV4,
'cast' => 'string'
),
// IP address (only IPv6)
'ipv6' => array(
'filter' => FILTER_VALIDATE_IP,
'options' => FILTER_NULL_ON_FAILURE + FILTER_FLAG_IPV6,
'cast' => 'string'
),
// Regular expression
'regexp' => array(
'filter' => FILTER_VALIDATE_REGEXP,
'options' => FILTER_NULL_ON_FAILURE,
'cast' => 'string'
),
// Uniform resource locator
'url' => array(
'filter' => FILTER_SANITIZE_URL,
'options' => FILTER_NULL_ON_FAILURE,
'cast' => 'string'
),
// URL encoded string
'encode' => array(
'filter' => FILTER_SANITIZE_ENCODED,
'options' => FILTER_NULL_ON_FAILURE + FILTER_FLAG_ENCODE_LOW + FILTER_FLAG_ENCODE_HIGH,
'cast' => 'string'
),
// HTML escaped string
'escape' => array(
'filter' => FILTER_SANITIZE_SPECIAL_CHARS,
'options' => FILTER_NULL_ON_FAILURE + FILTER_FLAG_STRIP_LOW,
'cast' => 'string'
),
// Regular object
'object' => array(
'cast' => 'object'
)
),
// Built-in cast functions
'callback' => array(
'sql' => 'castEscape'
)
);
}
// If no params got for initial launch we'll use empty array for init
$this->storage = is_array($params) ? $params : array();
$this->unParsed = ($URI) ? explode("/", substr(parse_url($URI,PHP_URL_PATH), 1)) : array();
// Prepare params got from array
foreach ($this->storage as $k => $v)
{
$this->values[$k] = array();
$this->storage[$k] = array('value' => $v);
}
// Init system arrays
$this->castCallbacks = array();
$params = &$this;
}
/**
* Checks if value need to be casted before return
*
* @param string reference $param Asked superglobal key reference
* @return void
*/
private function checkCast(&$param)
{
if (strpos($param,':') != false)
{
$cast = explode(':',$param);
$param = array_pop($cast);
$this->castCallbacks[$param] = $cast;
}
}
/**
* Returns string escaped for DB driver
*
* @param string $value String to escape
* @return string Escaped string
*/
private function castEscape($value)
{
// Check DB initialized
if (!parent::$mdb || !method_exists(parent::$mdb,'escape'))
{
if (parent::$throwExceptionOnCast)
{
throw new Exception('DB driver is not set or escape method missing, cannot escape as SQL correctly', 100);
}
return mysql_escape_string($value);
}
// Get DB driver instance from parent
return parent::$mdb->escape($value);
}
/**
* Throw an exception if cast failed
*
* @param mixed $value Casted value
* @return mixed Casted value
*/
private function checkCastValue($value, $exception)
{
if (null === $value && parent::$throwExceptionOnCast)
{
throw new Exception($exception, 300);
}
return $value;
}
/**
* Returns filter options for casting method
*
* @param string $method Filter method
* @return int Filter parameters
*/
private function getCastOptions($method)
{
return isset(self::$castMethods['varTypes'][$method]['options']) ?
self::$castMethods['varTypes'][$method]['options'] : FILTER_FLAG_NONE;
}
/**
* Value casting by type or function callback
*
* @param mixed $value Parameter value
* @param string|array $callback Cast type or function callback
* @return mixed Casting result
*/
private function castValue($value, $callback)
{
// If we have additional parameters passed for callback as array we should separate them from main filter
if (is_array($callback))
{
$shifted = array_shift($callback);
$additionalCast = count($callback) > 0 ? $callback : false;
$callback = $shifted;
}
else
{
$additionalCast = false;
}
// Generate memcached key and check for parsed value for it
if ($memKey = array($value,$callback,$additionalCast) && $cached = $this->memcache($memKey))
{
return $cached;
}
// If we only need to cast type
if (array_key_exists($callback, self::$castMethods['varTypes']))
{
// If type casting failed return null, else return casted variable
if (isset(self::$castMethods['varTypes'][$callback]['filter']))
{
// Check for filters available
if (!function_exists('filter_list'))
{
throw new Exception('There are no filters available because filter.so is missing', 200);
}
$value = filter_var($value, self::$castMethods['varTypes'][$callback]['filter'], $this->getCastOptions($callback));
}
// Check for cast needed
if (isset(self::$castMethods['varTypes'][$callback]['cast']) && !empty($value))
{
$value = settype($value,self::$castMethods['varTypes'][$callback]['cast']) ? $value : null;
}
// Additional nulling of empty
if (empty($value))
{
$value = null;
}
// If we have additional casting parameters
if ($additionalCast)
{
if (is_array($value))
{
// If we have array
foreach ($additionalCast as $castMethod)
{
/*/ Use faster way of casting
if (array_key_exists($castMethod, self::$castMethods['varTypes']))
{
$value = filter_var_array($value, self::$castMethods['varTypes'][$castMethod]['filter'] + $this->getCastOptions($castMethod));
var_dump($value);
}
else
{*/
// Use recursion. Slow but it works anyway.
// Some versions of PHP (for ex., current stable debian 5.2.0.8) do not support int as second parameter
// for filter_var_array. Even more, it do not support arrays with numeric keys as input for filtering.
// I can create associative array for storage (absolutely useless), but i think there is an idiotic way to
// also copy such array with all values set to array, which should contain filter method and filter options
// separated from each other.
foreach ($value as &$v)
{
$v = $this->castValue($v, $castMethod);
}
}
}
else
{
// Prevent passing null into callback functions
if (null !== $value)
{
// Maybe we'll need to use casting twice. I'm not sure, so i'll include here some piece of recursion
foreach ($additionalCast as $castMethod)
{
$value = $this->castValue($value, $castMethod);
}
}
}
}
// Cache value processing result
$this->memcache($memKey, $value);
return $this->checkCastValue($value, 'Value casting to '.$callback.' data type failed');
}
// Also we should try built-in cast functions
// We do not cache it when used alone because in some situations callback result may
// differ for same value.
// Please note, called with variable casting it will be cached.
if (array_key_exists($callback, self::$castMethods['callback']) && method_exists($this, self::$castMethods['callback'][$callback]))
{
$method = self::$castMethods['callback'][$callback];
return $this->checkCastValue($this->$method($value), 'Value casting by '.$callback.' built-in cast failed');
}
// Else, if we need to make a callback
// We do not cache it when used alone because in some situations callback result may
// differ for same value.
// Please note, called with variable casting it will be cached.
if (function_exists($callback))
{
return $this->checkCastValue($callback($value), 'Value casting by "'.$callback.'" function failed');
}
throw new Exception('Value casting callback function "'.$callback.'" do not exist', 300);
return $value;
}
/**
* Add new URL parameter from DB column
*
* @param string $param Url parameter key
* @param string $table Table to fetch from
* @param string $field Field containing possible values for parameter
* @return void|false
*/
public function addSQLParam($param, $table, $field)
{
// Check for casting request
$this->checkCast($param);
// Keep previously passed parameter into values array
if (array_key_exists($param,$this->storage))
{
$this->storage[$param] = array('array' => array($this->storage[$param]['value']));
}
if ($cached = $this->memcache(array($param, $table, $field)))
{
$this->values[$param] = $cached;
return;
}
// Check DB initialized and methods implemented
if (!parent::$mdb || (!method_exists(parent::$mdb,'getCol') && !method_exists(parent::$mdb,'getOne')))
{
throw new Exception('DB driver is not set or getCol method missing, cannot add parameter from DB', 100);
return false;
}
// Select method
if (method_exists(parent::$mdb,'getCol'))
{
$values = parent::$mdb->getCol('select DISTINCT '.$field.' from '.$table);
}
else
{
$values = explode(',',parent::$mdb->getOne('select GROUP_CONCAT( DISTINCT '.$field.' SEPARATOR ",") from '.$table));
}
$this->memcache(array($param, $table, $field), $values);
// Get DB driver instance from parent
$this->values[$param] = $values;
}
/**
* Add new URL parameter as array of values or callback function
*
* @param string $param Url parameter key
* @param mixed $value Array of possible values or string containing callback function name
*/
public function addParam($param, $value)
{
// Check for casting request
$this->checkCast($param);
// Keep previously passed parameter into values array
if (array_key_exists($param,$this->storage))
{
$this->storage[$param] = array('array' => array($this->storage[$param]['value']));
}
$this->values[$param] = $value;
}
/**
* Returns matching value for key, adding it into array of found values.
*
* @param string $key Url parameter key
* @return string
*/
private function parseValue($key)
{
// Check for key existance
if (!array_key_exists($key, $this->values) && !array_key_exists($key, $this->storage))
{
return false;
}
// Check for callback
$callback = (!is_array($this->values[$key])) ? $this->values[$key] : false;
// Check for previously found key
if (array_key_exists($key, $this->storage) && isset($this->storage[$key]['value']))
{
return $this->storage[$key]['value'];
}
// Init array of passed values
if (!isset($this->storage[$key]['array']))
{
$this->storage[$key]['array'] = array();
}
// If we have item in cache
if ($cached = $this->memcache(array($this->unParsed, $callback)))
{
$this->storage[$key] = $cached;
}
else
{
// Iterate params and find if param is defined
foreach ($this->unParsed as $k => $v)
{
// Are qe using callback or an array ?
$condition = ($callback) ? $this->castValue($v, $callback) : in_array($v, $this->values[$key]);
// We found it
if ($condition)
{
// Cast value if callback present, else just store
$this->storage[$key]['value'] = array_key_exists($key,$this->castCallbacks) ? $this->castValue($v,$this->castCallbacks[$key]) : $v;
// Add value into array of passed values, should be distinct
if (!in_array($this->storage[$key]['value'], $this->storage[$key]['array']));
{
$this->storage[$key]['array'][] = $this->storage[$key]['value'];
}
}
}
}
// Do not return from cycle to prevent multiple params for one key. We get only last one.
return isset($this->storage[$key]['value']) ? $this->storage[$key]['value'] : null;
}
/**
* Does offset exist ?
*
* @param string|int $key
* @return bool
*/
public function offsetExists($key)
{
return (bool)$this->parseValue($key);
}
/**
* Retrieve by offset
*
* @param string|int $key
* @return mixed
*/
public function offsetGet($key)
{
// Check for runtime casting
$cast = false;
if (strpos($key,':') != false)
{
$cast = explode(':',$key);
$key = array_pop($cast);
}
// Get value
$value = $this->parseValue($key);
// If array casting passed, but we do not hold an array as value, we need to return array of all input for key
if ($cast[0] == 'array' && !is_array($value))
{
$value = $this->storage[$key]['array'];
}
return $cast ? $this->castValue($value, $cast) : $this->parseValue($key);
}
/**
* Set value by offset
*
* @param string $key
* @param mixed $value
* @return void
*/
public function offsetSet($key, $value)
{
$this->storage[$key]['value'] = $value;
}
/**
* Unset value by offset
*
* @param string $key
* @return void
*/
public function offsetUnset($key)
{
unset($key);
}
/**
* How many items are present
*
* @return int
*/
public function count()
{
return count($this->values);
}
/**
* Get current value
*
* @return array
*/
public function current()
{
$current = key($this->values);
return $this->parseValue($current);
}
/**
* Get next item
*
* @return void
*/
public function next()
{
next($this->values);
}
/**
* Get current key
*
* @return string|int
*/
public function key()
{
return key($this->values);
}
/**
* Rewind to first value in collection
*
* @return void
*/
public function rewind()
{
reset($this->values);
}
/**
* Is item valid ?
*
* @return bool
*/
public function valid()
{
return (bool) $this->current();
}
/**
* Serialize current state
*
* @return array
*/
public function __sleep()
{
return array('params', 'storage', 'unParsed', 'castCallbacks', 'castMethods');
}
/**
* Store value into memcache by key or get value for key
*
* @param string|array $key Key for object in memcached
* @param string[optional] $value Value to set for key
* @return mixed Value from memcached server or boolean of request result
*/
private function memcache($key, $value = false)
{
// If we have memcache instance
if(parent::$memcached)
{
// Prevent whitespaces or non-string keys
$key = md5(serialize($key));
// Set value if passed
if($value)
{
return parent::$memcached->set($key, $value, 0, parent::$memcacheTimeout);
}
// Try to get value
return parent::$memcached->get($key);
}
return false;
}
/**
* Magic method, used here to generate URI representation of parameters
*
* @return string URI string
*/
public function __toString()
{
$return = array();
$returnstr = array();
// Iterate self to get all of params
foreach ($this as $k => $v)
{
if (empty($this->values[$k]))
// If it is not registered variable process it as usual $_GET
{
$return[] = $k.'='.$v;
}
else
// If we already found it we can return it as a part of URI
{
foreach ($this->storage[$k]['array'] as $v)
{
// Don't duplicate
if (!in_array($v,$returnstr))
{
$returnstr[] = $v;
}
}
}
}
return implode('/',$returnstr).(!empty($return) ? '?'.implode('&',$return) : '');
}
}
/**
* Worker class for transparent managing of superglobal arrays
*
* @uses requestCaster
* @package superGlobals
* @author Max S. Yarchevsky
* @license New BSD License
* @version 1.133
*/
class superGlobal
{
/**
* Singleton instance of self
*
* @var object
*/
private static $instance;
/**
* DB abstraction instance.
*
* @var object
*/
protected static $mdb = false;
/**
* Should we throw an exception on value cast failure or just return null ?
*
* @var boolean
*/
protected static $throwExceptionOnCast = false;
/**
* Timeout for memcached cache
*
* @var int
*/
protected static $memcacheTimeout = 300;
/**
* Memcache instance.
*
* @var object
*/
protected static $memcached = false;
/**
* Instances of superglobal replacers
*
* @var array
*/
protected static $superglobals = array();
/**
* Creates singleton for class
*
* @return object
*/
private static function singleton()
{
// Still did not initialized ?
if (!is_object(self::$instance))
{
self::$instance = new superGlobal();
self::$instance->injectInto('_GET');
}
return self::$instance;
}
/**
* Sets DB abstraction instance for all of superglobals
*
* @param object $DB DB abstraction instance
* @return void
*/
public static function db(&$DB)
{
self::$mdb = &$DB;
}
/**
* Sets Memcache instance for all of superglobals
*
* @param object $memcache Memcache instance
* @param int $timeout Memcache keep timeout
* @return void
*/
public static function memcached(&$memcache, $timeout = 300)
{
self::$memcached = &$memcache;
self::$memcacheTimeout = $timeout;
}
/**
* Inject requestCaster into variable (only for internal calls)
* Useful because sometimes we use instance of class to call it
*
* @param string $variable Array name to inject
* @return void
*/
private function injectInto($variable)
{
$globs = array(
'_GET' => $_GET,
'_POST' => $_POST,
'_COOKIE' => $_COOKIE,
'_SERVER' => $_SERVER,
'_REQUEST' => $_REQUEST,
);
if (isset($_SESSION))
{
$globs['_SESSION'] = &$_SESSION;
}
// Is a superglobal
if(array_key_exists($variable,$globs))
{
// Check if we already injected variable
// If we did there is no need to create new object
if(!array_key_exists($variable,self::$superglobals))
{
// Parse URL only into _GET
self::$superglobals[$variable] = ($variable == '_GET') ?
// Create instance of requestCaster
new requestCaster($globs[$variable], $_SERVER['REQUEST_URI']) : new requestCaster($globs[$variable]);
}
// We need to do so because superglobals should be accessed directly (bug ?)
switch ($variable)
{
case '_GET': $_GET = &self::$superglobals[$variable]; break;
case '_POST': $_POST = &self::$superglobals[$variable]; break;
case '_COOKIE': $_COOKIE = &self::$superglobals[$variable]; break;
case '_SERVER': $_SERVER = &self::$superglobals[$variable]; break;
case '_SESSION': $_SESSION = &self::$superglobals[$variable]; break;
case '_REQUEST': $_REQUEST = &self::$superglobals[$variable]; break;
}
// Exit from function
return;
}
// Variable is not superglobal, so we should check if it is at least global
global $$variable;
// Check for consistency
if (!isset($$variable) || (!is_array($$variable) && !is_string($$variable)))
{
throw new Exception('Only global or superglobal variable may be passed as a place to inject requestCaster into it', 400);
}
// Check if we already injected variable
// If we did there is no need to create new object
if(!array_key_exists($variable,self::$superglobals))
{
// We need to pass string contents of variable as URI, if given
self::$superglobals[$variable] = is_array($$variable) ?
// Create requestCaster instance
new requestCaster($$variable) : new requestCaster(array(), $$variable);
}
// Inject into it
$$variable = &self::$superglobals[$variable];
}
/**
* Inject requestCaster into variable
*
* @param string $superglobal Superglobal name
*/
public static function inject($superglobal)
{
self::$instance->injectInto($superglobal);
}
/**
* General class contructor
*
* @return boolean|void
*/
public function __construct()
{
// Maybe we'll try to create class manually.. But we should not.
if (is_object(self::$instance))
{
throw new Exception('You can\'t directly create instance of class requestCaster', 1);
}
}
/**
* Add new URL parameter from DB column
*
* @param string $param Url parameter key
* @param string $table Table to fetch from
* @param string $field Field containing possible values for parameter
* @param string[optional] $array Global array variable name to register into
* @return void
*/
public static function registerSQLParam($param, $table, $field, $array = false)
{
self::singleton()->register('sql', $param, array('table' => $table, 'field' => $field), $array);
}
/**
* Add new URL parameter as array of values or callback function
*
* @param string $param Url parameter key
* @param mixed $value Array of possible values or string containing callback function name
* @param string[optional] $array Global array variable name to register into
* @return void
*/
public static function registerParam($param, $value, $array = false)
{
self::singleton()->register('array', $param, array('value' => $value), $array);
}
/**
* Add new URL parameter from array or DB
*
* @param string $type Type of registering. Can be 'db' or 'array'
* @param string $param Url parameter key
* @param array $options Options for registering. Should contain 'value' array or 'table' and 'field' strings
* @param string[optional] $array Global array variable name to register into
*/
private function register($type, $param, $options, $array = false)
{
// It's useless to register params into these arrays. Believe me.
$forbiddenArrays = array('_POST', '_COOKIE', '_SERVER', '_SESSION', '_REQUEST');
// Make sure that we have worker instance
self::singleton();
// If we need to register parameter into known array
if ($array)
{
// Try to inject into array if it is not present
if (!array_key_exists($array,self::$superglobals))
{
self::singleton()->injectInto($array);
}
// We need to check for array presence again
if (!isset(self::$superglobals[$array]))
{
throw new Exception('Requested array '.$array.' do not exists, so parameter '.$param.' cannot be registered', 400);
return;
}
// Proxy to requestCaster functions of given array, depending on parameter type
if ($type == 'sql' && isset($options['table']) && isset($options['field']))
{
self::$superglobals[$array]->addSQLParam($param, $options['table'], $options['field']);
return;
}
if ($type == 'array' && isset($options['value']) && is_array($options['value']))
{
self::$superglobals[$array]->addParam($param, $options['value']);
return;
}
// We did not got nor correct sql nor correct array options set
throw new Exception('Incorrect use of superGlobal::register* functions set', 500);
return;
}
// Register parameter into each of global arrays
foreach (array_keys(self::$superglobals) as $k)
{
// If array is not in forbidden list
if(!in_array($k,$forbiddenArrays))
{
// Proxy to requestCaster functions of given array, depending on parameter type
if ($type == 'sql' && isset($options['table']) && isset($options['field']))
{
self::$superglobals[$k]->addSQLParam($param, $options['table'], $options['field']);
return;
}
if ($type == 'array' && isset($options['value']) && isset($options['value']))
{
self::$superglobals[$k]->addParam($param, $options['value']);
return;
}
// We did not got nor correct sql nor correct array options set
throw new Exception('Incorrect use of superGlobal::register* function set', 500);
return;
}
}
}
/**
* Enable or disable exceptions on casting errors
*
* @param boolean[optional] $enable Use false to disable such exceptions back
* @return void
*/
public static function enableCastExceptions($enable = true)
{
self::$throwExceptionOnCast = $enable;
}
}
?>