. */ abstract class Staple_Controller { protected $openMethods = array(); protected $accessLevels = array(); protected $open = false; /** * * The $view property holds the view object for the controller. * @var Staple_View */ public $view; /** * Holds and instance of a Staple Layout object. * @var Staple_Layout */ public $layout; /** * * Controller constructor creates an instance of Staple_View and saves it in the $view * property. It then calls the overridable method _start() for additional boot time * procedures. */ public function __construct() { //Set default access levels $methods = get_class_methods(get_class($this)); foreach($methods as $acMeth) { if(substr($acMeth, 0,1) != '_') { $this->accessLevels[$acMeth] = 1; } } //Create a view object $this->view = new Staple_View(); //Assign the default layout to the controller, if specified in config. $settings = Staple_Config::get('layout'); if(array_key_exists('default', $settings)) { if($settings['default'] != '') { $this->_setLayout($settings['default']); $pageSettings = Staple_Config::get('page'); if(array_key_exists('title', $pageSettings)) { $this->layout->setTitle($pageSettings['title']); } } } } /** * * Enter description here ... */ public function __wakeup() { $methods = get_class_methods(get_class($this)); foreach($methods as $acMeth) { if(substr($acMeth, 0,1) != '_') { if(!array_key_exists($acMeth, $this->accessLevels)) { $this->accessLevels[$acMeth] = 1; } } } //Erase the view and start from scratch $this->view = new Staple_View(); //Reset the view inside the layout if($this->layout instanceof Staple_Layout) $this->layout->setView($this->view); } /** * Overridable and empty method allows for additional boot time procedures. * This method is called by the front controller. */ public function _start() { } /** * The default action on any controller must be defined. */ abstract public function index(); /*----------------------------------------Auth Functions----------------------------------------*/ /** * Returns a boolean true or false whether the method requires authentication * before being dispatched from the front controller. * @param string $method * @return bool */ public function _auth($method) { $method = (string)$method; if(!ctype_alnum($method)) { throw new Exception('Authentication Validation Error', Staple_Error::AUTH_ERROR); } else { if(method_exists($this,$method)) { //Is the controller completely open? if($this->open === true) { return true; } elseif(array_search($method, $this->openMethods) !== FALSE) //Is the requested method open? { return true; } elseif(Staple_Auth::get()->isAuthed() && Staple_Auth::get()->getAuthLevel() >= $this->_authLevel($method)) //Does the authed user have the required access level? { return true; } } else { throw new Exception('Authentication Validation Error', Staple_Error::AUTH_ERROR); } } return false; } /** * * Returns the access level required for this method. * @param string | array $method * @throws Exception */ public function _authLevel($method) { $method = (string)$method; if(!ctype_alnum($method)) { throw new Exception('Authentication Validation Error: Invalid Method', Staple_Error::AUTH_ERROR); } else { if(method_exists($this,$method)) { if(array_key_exists($method, $this->accessLevels) === true) { return (int)$this->accessLevels[$method]; } else { //return default auth level if non assigned. return 1; //throw new Exception('Authentication Validation Error: No Auth Level', Staple_Error::AUTH_ERROR); } } else { throw new Exception('Authentication Validation Error: Method Not Found', Staple_Error::AUTH_ERROR); } } return 1; } /** * * Replaces the default permission level with the specified permission level. All method * specific access levels will be overwritten. This should be called in controller startup. * @param int $level */ protected function _requiredControllerAccessLevel($level) { $methods = get_class_methods(get_class($this)); foreach($methods as $acMeth) { if(substr($acMeth, 0,1) != '_') { $this->accessLevels[$acMeth] = (int)$level; } } $this->openMethods = array(); } /** * Specifies the required access level for the specified action. This should be called * in the Controller startup. * @param string $for * @param int $level * @throws Exception */ protected function _requiredActionAccessLevel($for,$level) { $level = (int)$level; $for = (string)$for; if(!ctype_alnum($for)) { throw new Exception('Cannot change method permissions.', Staple_Error::AUTH_ERROR); } else { if(method_exists($this, $for)) { if($level < 0) { throw new Exception('Cannot change method permissions.', Staple_Error::AUTH_ERROR); } else { if($level == 0) { $this->_openMethod($for); if(array_key_exists($for, $this->accessLevels)) { unset($this->accessLevels[$for]); } } else { $this->accessLevels[$for] = $level; } } } else { throw new Exception('Cannot change method permissions on a non-existant method.', Staple_Error::AUTH_ERROR); } } } /** * Sent a string it allows one method to be accessed without authentication. When sent * an array, it allows all the values method names without authentication. * @param string | array $method * @throws Exception * @return bool */ protected function _openMethod($method) { if(is_array($method)) { foreach($method as $mName) { if(!ctype_alnum($mName)) { throw new Exception('Cannot change method permissions.', Staple_Error::AUTH_ERROR); } else { if(array_search($mName, $this->openMethods) === false) { $this->openMethods[] = $mName; $this->accessLevels[$mName] = 0; } } } return true; } else { if(!ctype_alnum($method)) { throw new Exception('Cannot change method permissions.', Staple_Error::AUTH_ERROR); } else { if(array_search($method, $this->openMethods) === false) { $this->openMethods[] = $method; $this->accessLevels[$method] = 0; return true; } } } return false; } /** * This function opens the entire controller to be accessed without authentication. */ protected function _openAll() { $methods = get_class_methods(get_class($this)); foreach($methods as $acMeth) { if(substr($acMeth, 0,1) != '_') { $this->accessLevels[$acMeth] = 0; } } $this->open = true; } /*----------------------------------------Layout Functions----------------------------------------*/ /** * * Sets up a new layout object and associates the controllers view with the layout. Accepts a * string name for the layout to load. * @param string $layout */ public function _setLayout($layout) { $this->layout = new Staple_Layout($layout); $this->layout->setView($this->view); } /** * Removes the layout object from the controller. */ public function _removeLayout() { $this->layout = NULL; } /*----------------------------------------Helpers----------------------------------------*/ /** * * This function accepts a routing string to redirect the application internally. A * redirect of this sort clears the output buffer and redraws the header, proceeding * as if the redirected controller/action was called directly. * @param mixed $to */ protected function _redirect($to) { Staple_Main::get()->redirect($to); $this->view->noRender(); } /** * * If an array is supplied, a link is created to a controller/action. If a string is * supplied, a file link is specified. * @param string | array $link * @param array $get */ protected function _link($link,array $get = array()) { return Staple_Link::get($link,$get); } /** * @see Staple_View::escape() * @param string $estring * @param boolean $strip */ public static function _escape($estring, $strip = false) { return Staple_View::escape($estring,$strip); } }