pickles/classes/Module.php
2013-09-08 18:30:14 -04:00

458 lines
10 KiB
PHP

<?php
/**
* Module Class File for PICKLES
*
* PHP version 5
*
* Licensed under The MIT License
* Redistribution of these files must retain the above copyright notice.
*
* @author Josh Sherman <pickles@joshtronic.com>
* @copyright Copyright 2007-2013, Josh Sherman
* @license http://www.opensource.org/licenses/mit-license.html
* @package PICKLES
* @link https://github.com/joshtronic/pickles
*/
/**
* Module Class
*
* This is a parent class that all PICKLES modules should be extending. Each
* module can specify it's own meta data and whether or not a user must be
* properly authenticated to view the page. Currently any pages without a
* template are treated as pages being requested via AJAX and the return will
* be JSON encoded. In the future this may need to be changed out for logic
* that allows the requested module to specify what display type(s) it can use.
*/
class Module extends Object
{
/**
* Cache Object
*
* @access protected
* @var object
*/
protected $cache = null;
/**
* Database Object
*
* @access protected
* @var object
*/
protected $db = null;
/**
* Fluid or Fixed?
*
* @access protected
* @var boolean
*/
protected $fluid = false;
/**
* Page Title
*
* @access protected
* @var string, null by default
*/
protected $title = null;
/**
* Meta Description
*
* @access protected
* @var string, null by default
*/
protected $description = null;
/**
* Meta Keywords (comma separated)
*
* @access protected
* @var string, null by default
*/
protected $keywords = null;
/**
* Secure
*
* Whether or not the page should be loaded via SSL.
*
* @access protected
* @var boolean, null by default
*/
protected $secure = null;
/**
* Private
*
* Whether or not the page can be accessed directly.
*
* @access protected
* @var boolean, false by default
*/
protected $private = false;
/**
* Security Settings
*
* @access protected
* @var boolean, null by default
*/
protected $security = null;
/**
* Session
*
* Whether or not a session should be established.
*
* @access protected
* @var boolean, null by default
*/
protected $session = null;
/**
* AJAX
*
* Whether or not the module is being called via AJAX. This determines if
* errors should be returned as JSON or if it should use the Error class
* which can be interrogated from within a template.
*
* @access protected
* @var boolean, false (not AJAX) by default
*/
protected $ajax = false;
/**
* Method
*
* Request methods that are allowed to access the module.
*
* @access protected
* @var string or array, null by default
*/
protected $method = null;
/**
* Validate
*
* Variables to validate.
*
* @access protected
* @var array, null by default
*/
protected $validate = null;
/**
* Hash
*
* Whether or not to validate the security hash. Boolean true will indicate
* using the name of the module as the hash, a string value will use the
* value instead.
*
* @access protected
* @var string or boolean, null by default
*/
protected $hash = null;
/**
* Default Display Engine
*
* Defaults to PHP but could be set to JSON, XML or RSS. Value is
* overwritten by the config value if not set by the module.
*
* @access protected
* @var string, null by default
*/
protected $engine = DISPLAY_PHP;
/**
* Default Template
*
* Defaults to null but could be set to any valid template basename. The
* value is overwritten by the config value if not set by the module. The
* display engine determines what the file extension should be.
*
* @access protected
* @var string, 'index' by default
*/
protected $template = 'index';
/**
* Return
*
* Array that is returned to the template in the case of the module not
* returning anything itself. This is somewhat of a one way trip as you
* cannot get the variable unless you reference the return array explicitly
* $this->return['variable']
*
* @access protected
* @var array
*/
protected $return = array();
/**
* Constructor
*
* The constructor does nothing by default but can be passed a boolean
* variable to tell it to automatically run the __default() method. This is
* typically used when a module is called outside of the scope of the
* controller (the registration page calls the login page in this manner.
*
* @param boolean $autorun optional flag to autorun __default()
* @param boolean $valiate optional flag to disable input validation during autorun
*/
public function __construct($autorun = false, $validate = true)
{
parent::__construct();
$this->cache = Cache::getInstance();
$this->db = Database::getInstance();
if ($autorun === true)
{
if ($validate === true)
{
$errors = $this->__validate();
if ($errors !== false)
{
exit('Errors encountered, this is a @todo for form validation when calling modules from inside of modules');
}
}
$this->__default();
}
}
/**
* Default "Magic" Method
*
* This function is overloaded by the module. The __default() method is
* where you want to place any code that needs to be executed at runtime.
* The reason the code isn't in the constructor is because the module must
* be instantiated before the code is executed so that the controller
* script is aware of the authentication requirements.
*/
public function __default()
{
}
/**
* Magic Setter Method
*
* Places the variables that are being modified in the return array that is
* returned if nothing is returned by the module itself. This also prohibits
* the direct modification of module variables which could cause issues.
*
* @param string $name name of the variable to be set
* @param mixed $value value of the variable to be set
*/
public function __set($name, $value)
{
$this->return[$name] = $value;
}
/**
* Magic Getter Method
*
* Attempts to load the module variable. If it's not set, will attempt to
* load from the config.
*
* @param string $name name of the variable requested
* @return mixed value of the variable or boolean false
*/
public function __get($name)
{
if (!isset($this->$name))
{
if (isset($this->config->pickles[$name]))
{
$this->$name = $this->config->pickles[$name];
}
else
{
$this->$name = false;
}
}
return $this->$name;
}
/**
* Sets the Request
*
* @param array $request data to be loaded into the request variable
* @return boolean whether or not the assignment was successful
*/
public function setRequest($request)
{
$backtrace = debug_backtrace();
if ($backtrace[1]['class'] == 'Controller')
{
$this->request = $request;
return true;
}
else
{
throw new Exception('Only Controller can perform setRequest()');
}
}
/**
* Validate
*/
public function __validate()
{
$errors = array();
if ($this->validate !== false)
{
switch (strtoupper($this->method))
{
case 'GET': $global = &$_GET; break;
case 'POST': $global = &$_POST; break;
default: $global = &$_REQUEST; break;
}
foreach ($this->validate as $variable => $rules)
{
if (!is_array($rules))
{
$variable = $rules;
$rules = true;
}
if (isset($global[$variable]) && !String::isEmpty($global[$variable]))
{
$value = $global[$variable];
if (is_array($rules))
{
foreach ($rules as $rule => $message)
{
$rule = explode(':', $rule);
switch (strtolower($rule[0]))
{
// @todo case 'alpha':
// @todo case 'alphanumeric':
// @todo case 'date':
// {{{ Checks using filter_var()
case 'filter':
if (count($rule) < 2)
{
throw new Exception('Invalid validation rule, expected: "validate:boolean|email|float|int|ip|regex|url".');
}
else
{
switch (strtolower($rule[1]))
{
case 'boolean':
case 'email':
case 'float':
case 'int':
case 'ip':
case 'regex':
case 'url':
$filter = constant('FILTER_VALIDATE_' . strtoupper($rule[1]));
break;
default:
throw new Exception('Invalid filter, expecting boolean, email, float, int, ip, regex or url.');
break;
}
if (!filter_var($value, $filter))
{
$errors[] = $message;
}
}
break;
// }}}
// {{{ Checks using strlen()
case 'length':
if (count($rule) < 3)
{
throw new Exception('Invalid validation rule, expected: "length:<|<=|==|!=|>=|>:integer".');
}
else
{
if (!filter_var($rule[2], FILTER_VALIDATE_INT))
{
throw new Exception('Invalid length value, expecting an integer.');
}
else
{
$length = strlen($value);
switch ($rule[1])
{
case '<': $valid = $length < $rule[2]; break;
case '<=': $valid = $length <= $rule[2]; break;
case '==': $valid = $length == $rule[2]; break;
case '!=': $valid = $length != $rule[2]; break;
case '>=': $valid = $length >= $rule[2]; break;
case '>': $valid = $length > $rule[2]; break;
default:
throw new Exception('Invalid operator, expecting <, <=, ==, !=, >= or >.');
break;
}
if ($valid === true)
{
$errors[] = $message;
}
}
}
break;
// }}}
// @todo case 'range':
// {{{ Checks using preg_match()
case 'regex':
if (count($rule) < 3)
{
throw new Exception('Invalid validation rule, expected: "regex:is|not:string".');
}
else
{
if ((strtolower($rule[1]) == 'not' && !preg_match($rule[2], $value)) || preg_match($rule[2], $value))
{
$errors[] = $message;
}
}
break;
// }}}
}
}
}
}
else
{
$errors[] = 'The ' . $variable . ' field is required.';
}
}
}
return $errors == array() ? false : $errors;
}
}
?>