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
@ -2,7 +2,15 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles all manipulation of the session.
|
* 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
|
* 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
|
* $session->myVar = 'XYZ' would be fine, as would Session::data->myVar. What about the equivalent
|
||||||
@ -15,10 +23,41 @@
|
|||||||
*/
|
*/
|
||||||
class Session {
|
class Session {
|
||||||
public static function set($name, $val) {
|
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);
|
$names = explode('.', $name);
|
||||||
|
|
||||||
// We still want to do this even if we have strict path checking for legacy code
|
// 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) {
|
foreach($names as $n) {
|
||||||
$var = &$var[$n];
|
$var = &$var[$n];
|
||||||
@ -27,11 +66,11 @@ class Session {
|
|||||||
$var = $val;
|
$var = $val;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function addToArray($name, $val) {
|
public function inst_addToArray($name, $val) {
|
||||||
$names = explode('.', $name);
|
$names = explode('.', $name);
|
||||||
|
|
||||||
// We still want to do this even if we have strict path checking for legacy code
|
// 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) {
|
foreach($names as $n) {
|
||||||
$var = &$var[$n];
|
$var = &$var[$n];
|
||||||
@ -40,14 +79,14 @@ class Session {
|
|||||||
$var[] = $val;
|
$var[] = $val;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function get($name) {
|
public function inst_get($name) {
|
||||||
$names = explode('.', $name);
|
$names = explode('.', $name);
|
||||||
|
|
||||||
if(!isset($_SESSION)) {
|
if(!isset($this->data)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
$var = $_SESSION;
|
$var = $this->data;
|
||||||
|
|
||||||
foreach($names as $n) {
|
foreach($names as $n) {
|
||||||
if(!isset($var[$n])) {
|
if(!isset($var[$n])) {
|
||||||
@ -59,11 +98,11 @@ class Session {
|
|||||||
return $var;
|
return $var;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function clear($name) {
|
public function inst_clear($name) {
|
||||||
$names = explode('.', $name);
|
$names = explode('.', $name);
|
||||||
|
|
||||||
// We still want to do this even if we have strict path checking for legacy code
|
// 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) {
|
foreach($names as $n) {
|
||||||
$var = &$var[$n];
|
$var = &$var[$n];
|
||||||
@ -72,8 +111,8 @@ class Session {
|
|||||||
$var = null;
|
$var = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getAll() {
|
public function inst_getAll() {
|
||||||
return $_SESSION;
|
return $this->data;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -15,8 +15,17 @@ class Controller extends ViewableData {
|
|||||||
protected $requestParams;
|
protected $requestParams;
|
||||||
|
|
||||||
protected $action;
|
protected $action;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link Session} object for this controller
|
||||||
|
*/
|
||||||
|
protected $session;
|
||||||
|
|
||||||
protected static $currentController;
|
/**
|
||||||
|
* Stack of current controllers.
|
||||||
|
* Controller::$controller_stack[0] is the current controller.
|
||||||
|
*/
|
||||||
|
protected static $controller_stack = array();
|
||||||
|
|
||||||
protected $basicAuthEnabled = true;
|
protected $basicAuthEnabled = true;
|
||||||
|
|
||||||
@ -43,7 +52,7 @@ class Controller extends ViewableData {
|
|||||||
protected $baseInitCalled = false;
|
protected $baseInitCalled = false;
|
||||||
function run($requestParams) {
|
function run($requestParams) {
|
||||||
if(isset($_GET['debug_profile'])) Profiler::mark("Controller", "run");
|
if(isset($_GET['debug_profile'])) Profiler::mark("Controller", "run");
|
||||||
Controller::$currentController = $this;
|
$this->pushCurrent();
|
||||||
|
|
||||||
$this->response = new HTTPResponse();
|
$this->response = new HTTPResponse();
|
||||||
$this->requestParams = $requestParams;
|
$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(!$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 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
|
// Look at the action variables for forms
|
||||||
foreach($this->requestParams as $paramName => $paramVal) {
|
foreach($this->requestParams as $paramName => $paramVal) {
|
||||||
@ -104,7 +116,10 @@ class Controller extends ViewableData {
|
|||||||
// disregard validation if a single field is called
|
// disregard validation if a single field is called
|
||||||
if(!isset($_REQUEST['action_callfieldmethod'])) {
|
if(!isset($_REQUEST['action_callfieldmethod'])) {
|
||||||
$valid = $form->beforeProcessing();
|
$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.
|
// 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");
|
if(isset($_GET['debug_profile'])) Profiler::unmark("Controller", "run");
|
||||||
|
|
||||||
|
$this->popCurrent();
|
||||||
return $this->response;
|
return $this->response;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -255,14 +271,18 @@ class Controller extends ViewableData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static function currentController() {
|
public static function currentController() {
|
||||||
return Controller::$currentController;
|
return self::curr();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the current controller
|
* Returns the current controller
|
||||||
*/
|
*/
|
||||||
public static function curr() {
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -323,11 +343,32 @@ class Controller extends ViewableData {
|
|||||||
function PastMember() {
|
function PastMember() {
|
||||||
return Cookie::get("PastMember") ? true : false;
|
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
|
* Handle redirection
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function redirect($url) {
|
function redirect($url) {
|
||||||
// Attach site-root to relative links, if they have a slash in them
|
// Attach site-root to relative links, if they have a slash in them
|
||||||
if(substr($url,0,4) != "http" && $url[0] != "/" && strpos($url,'/') !== false){
|
if(substr($url,0,4) != "http" && $url[0] != "/" && strpos($url,'/') !== false){
|
||||||
@ -336,6 +377,21 @@ class Controller extends ViewableData {
|
|||||||
|
|
||||||
$this->response->redirect($url);
|
$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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
?>
|
?>
|
||||||
|
@ -42,16 +42,20 @@ class Director {
|
|||||||
function direct($url) {
|
function direct($url) {
|
||||||
if(isset($_GET['debug_profile'])) Profiler::mark("Director","direct");
|
if(isset($_GET['debug_profile'])) Profiler::mark("Director","direct");
|
||||||
$controllerObj = Director::getControllerForURL($url);
|
$controllerObj = Director::getControllerForURL($url);
|
||||||
|
|
||||||
|
// Load the session into the controller
|
||||||
|
$controllerObj->setSession(new Session($_SESSION));
|
||||||
|
|
||||||
if(is_string($controllerObj) && substr($controllerObj,0,9) == 'redirect:') {
|
if(is_string($controllerObj) && substr($controllerObj,0,9) == 'redirect:') {
|
||||||
Director::redirect(substr($controllerObj, 9));
|
Director::redirect(substr($controllerObj, 9));
|
||||||
|
|
||||||
} else if($controllerObj) {
|
} else if($controllerObj) {
|
||||||
$response = $controllerObj->run(array_merge((array)$_GET, (array)$_POST, (array)$_FILES));
|
$response = $controllerObj->run(array_merge((array)$_GET, (array)$_POST, (array)$_FILES));
|
||||||
|
|
||||||
|
// Save the updated session back
|
||||||
|
$_SESSION = $controllerObj->getSession()->inst_getAll();
|
||||||
|
|
||||||
if(isset($_GET['debug_profile'])) Profiler::mark("Outputting to browser");
|
|
||||||
$response->output();
|
$response->output();
|
||||||
if(isset($_GET['debug_profile'])) Profiler::unmark("Outputting to browser");
|
|
||||||
|
|
||||||
}
|
}
|
||||||
if(isset($_GET['debug_profile'])) Profiler::unmark("Director","direct");
|
if(isset($_GET['debug_profile'])) Profiler::unmark("Director","direct");
|
||||||
|
Loading…
Reference in New Issue
Block a user