mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
Updated controller model so that sessions are linked to controllers, and current-controller is represented as a stack
git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/trunk@40424 467b73ca-7a2a-4603-9d3b-597d59a354a9
This commit is contained in:
parent
9b045b61db
commit
9c80282dfd
@ -3,6 +3,14 @@
|
||||
/**
|
||||
* Handles all manipulation of the session.
|
||||
*
|
||||
* The static methods are used to manipulate the currently active controller's session.
|
||||
* The instance methods are used to manipulate a particular session. There can be more than one of these created.
|
||||
*
|
||||
* In order to support things like testing, the session is associated with a particular Controller. In normal usage, this is loaded from
|
||||
* and saved to the regular PHP session, but for things like static-page-generation and unit-testing, you can create multiple Controllers,
|
||||
* each with their own session.
|
||||
*
|
||||
* The instance object is basically just a way of manipulating a set of nested maps, and isn't specific to session data.
|
||||
* This class is currently really basic and could do with a more well-thought-out implementation
|
||||
*
|
||||
* $session->myVar = 'XYZ' would be fine, as would Session::data->myVar. What about the equivalent
|
||||
@ -15,10 +23,41 @@
|
||||
*/
|
||||
class Session {
|
||||
public static function set($name, $val) {
|
||||
return Controller::curr()->getSession()->inst_set($name, $val);
|
||||
}
|
||||
public static function addToArray($name, $val) {
|
||||
return Controller::curr()->getSession()->inst_addToArray($name, $val);
|
||||
}
|
||||
public static function get($name) {
|
||||
return Controller::curr()->getSession()->inst_get($name);
|
||||
}
|
||||
public static function clear($name) {
|
||||
return Controller::curr()->getSession()->inst_clear($name);
|
||||
}
|
||||
public static function getAll() {
|
||||
return Controller::curr()->getSession()->inst_getAll($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Session data
|
||||
*/
|
||||
protected $data = array();
|
||||
|
||||
/**
|
||||
* Create a new session object, with the given starting data
|
||||
* @param $data Can be an array of data (such as $_SESSION) or another Session object to clone.
|
||||
*/
|
||||
function __construct($data) {
|
||||
if($data instanceof Session) $data = $data->inst_getAll();
|
||||
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
public function inst_set($name, $val) {
|
||||
$names = explode('.', $name);
|
||||
|
||||
// We still want to do this even if we have strict path checking for legacy code
|
||||
$var = &$_SESSION;
|
||||
$var = &$this->data;
|
||||
|
||||
foreach($names as $n) {
|
||||
$var = &$var[$n];
|
||||
@ -27,11 +66,11 @@ class Session {
|
||||
$var = $val;
|
||||
}
|
||||
|
||||
public static function addToArray($name, $val) {
|
||||
public function inst_addToArray($name, $val) {
|
||||
$names = explode('.', $name);
|
||||
|
||||
// We still want to do this even if we have strict path checking for legacy code
|
||||
$var = &$_SESSION;
|
||||
$var = &$this->data;
|
||||
|
||||
foreach($names as $n) {
|
||||
$var = &$var[$n];
|
||||
@ -40,14 +79,14 @@ class Session {
|
||||
$var[] = $val;
|
||||
}
|
||||
|
||||
public static function get($name) {
|
||||
public function inst_get($name) {
|
||||
$names = explode('.', $name);
|
||||
|
||||
if(!isset($_SESSION)) {
|
||||
if(!isset($this->data)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$var = $_SESSION;
|
||||
$var = $this->data;
|
||||
|
||||
foreach($names as $n) {
|
||||
if(!isset($var[$n])) {
|
||||
@ -59,11 +98,11 @@ class Session {
|
||||
return $var;
|
||||
}
|
||||
|
||||
public static function clear($name) {
|
||||
public function inst_clear($name) {
|
||||
$names = explode('.', $name);
|
||||
|
||||
// We still want to do this even if we have strict path checking for legacy code
|
||||
$var = &$_SESSION;
|
||||
$var = &$this->data;
|
||||
|
||||
foreach($names as $n) {
|
||||
$var = &$var[$n];
|
||||
@ -72,8 +111,8 @@ class Session {
|
||||
$var = null;
|
||||
}
|
||||
|
||||
public static function getAll() {
|
||||
return $_SESSION;
|
||||
public function inst_getAll() {
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -16,7 +16,16 @@ class Controller extends ViewableData {
|
||||
|
||||
protected $action;
|
||||
|
||||
protected static $currentController;
|
||||
/**
|
||||
* The {@link Session} object for this controller
|
||||
*/
|
||||
protected $session;
|
||||
|
||||
/**
|
||||
* Stack of current controllers.
|
||||
* Controller::$controller_stack[0] is the current controller.
|
||||
*/
|
||||
protected static $controller_stack = array();
|
||||
|
||||
protected $basicAuthEnabled = true;
|
||||
|
||||
@ -43,7 +52,7 @@ class Controller extends ViewableData {
|
||||
protected $baseInitCalled = false;
|
||||
function run($requestParams) {
|
||||
if(isset($_GET['debug_profile'])) Profiler::mark("Controller", "run");
|
||||
Controller::$currentController = $this;
|
||||
$this->pushCurrent();
|
||||
|
||||
$this->response = new HTTPResponse();
|
||||
$this->requestParams = $requestParams;
|
||||
@ -56,7 +65,10 @@ class Controller extends ViewableData {
|
||||
if(!$this->baseInitCalled) user_error("init() method on class '$this->class' doesn't call Controller::init(). Make sure that you have parent::init() included.", E_USER_WARNING);
|
||||
|
||||
// If we had a redirection or something, halt processing.
|
||||
if($this->response->isFinished()) return $this->response;
|
||||
if($this->response->isFinished()) {
|
||||
$this->popCurrent();
|
||||
return $this->response;
|
||||
}
|
||||
|
||||
// Look at the action variables for forms
|
||||
foreach($this->requestParams as $paramName => $paramVal) {
|
||||
@ -104,7 +116,10 @@ class Controller extends ViewableData {
|
||||
// disregard validation if a single field is called
|
||||
if(!isset($_REQUEST['action_callfieldmethod'])) {
|
||||
$valid = $form->beforeProcessing();
|
||||
if(!$valid) return $this->response;
|
||||
if(!$valid) {
|
||||
$this->popCurrent();
|
||||
return $this->response;
|
||||
}
|
||||
}
|
||||
|
||||
// If the action wasnt' set, choose the default on the form.
|
||||
@ -185,6 +200,7 @@ class Controller extends ViewableData {
|
||||
|
||||
if(isset($_GET['debug_profile'])) Profiler::unmark("Controller", "run");
|
||||
|
||||
$this->popCurrent();
|
||||
return $this->response;
|
||||
}
|
||||
|
||||
@ -255,14 +271,18 @@ class Controller extends ViewableData {
|
||||
}
|
||||
|
||||
public static function currentController() {
|
||||
return Controller::$currentController;
|
||||
return self::curr();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current controller
|
||||
*/
|
||||
public static function curr() {
|
||||
return Controller::$currentController;
|
||||
if(Controller::$controller_stack) {
|
||||
return Controller::$controller_stack[0];
|
||||
} else {
|
||||
user_error("No current controller available", E_USER_WARNING);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -324,10 +344,31 @@ class Controller extends ViewableData {
|
||||
return Cookie::get("PastMember") ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pushes this controller onto the stack of current controllers.
|
||||
* This means that any redirection, session setting, or other things that rely on Controller::curr() will now write to this
|
||||
* controller object.
|
||||
*/
|
||||
function pushCurrent() {
|
||||
array_unshift(self::$controller_stack, $this);
|
||||
// Create a new session object
|
||||
if(!$this->session) $this->session = new Session(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pop this controller off the top of the stack.
|
||||
*/
|
||||
function popCurrent() {
|
||||
if($this == self::$controller_stack[0]) {
|
||||
array_shift(self::$controller_stack);
|
||||
} else {
|
||||
user_error("popCurrent called on $this->Controller controller, but it wasn't at the top of the stack", E_USER_WARNING);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle redirection
|
||||
*/
|
||||
|
||||
function redirect($url) {
|
||||
// Attach site-root to relative links, if they have a slash in them
|
||||
if(substr($url,0,4) != "http" && $url[0] != "/" && strpos($url,'/') !== false){
|
||||
@ -336,6 +377,21 @@ class Controller extends ViewableData {
|
||||
|
||||
$this->response->redirect($url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Session object representing this Controller's session
|
||||
*/
|
||||
function getSession() {
|
||||
return $this->session;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Session object.
|
||||
*/
|
||||
function setSession(Session $session) {
|
||||
$this->session = $session;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
|
@ -43,15 +43,19 @@ class Director {
|
||||
if(isset($_GET['debug_profile'])) Profiler::mark("Director","direct");
|
||||
$controllerObj = Director::getControllerForURL($url);
|
||||
|
||||
// Load the session into the controller
|
||||
$controllerObj->setSession(new Session($_SESSION));
|
||||
|
||||
if(is_string($controllerObj) && substr($controllerObj,0,9) == 'redirect:') {
|
||||
Director::redirect(substr($controllerObj, 9));
|
||||
|
||||
} else if($controllerObj) {
|
||||
$response = $controllerObj->run(array_merge((array)$_GET, (array)$_POST, (array)$_FILES));
|
||||
|
||||
if(isset($_GET['debug_profile'])) Profiler::mark("Outputting to browser");
|
||||
// Save the updated session back
|
||||
$_SESSION = $controllerObj->getSession()->inst_getAll();
|
||||
|
||||
$response->output();
|
||||
if(isset($_GET['debug_profile'])) Profiler::unmark("Outputting to browser");
|
||||
|
||||
}
|
||||
if(isset($_GET['debug_profile'])) Profiler::unmark("Director","direct");
|
||||
|
Loading…
Reference in New Issue
Block a user