mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
ENHANCEMENT Session::start() now only called when there is changed
session data to be saved, and started on Director::direct() when there is a cookie (or request var) containing the current PHP session name.
This commit is contained in:
parent
bd6ca59558
commit
f63d137d49
@ -94,6 +94,8 @@ class Director implements TemplateGlobalProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Load the session into the controller
|
// Load the session into the controller
|
||||||
|
if(!isset($_SESSION) && (isset($_COOKIE[session_name()]) || isset($_REQUEST[session_name()]))) Session::start();
|
||||||
|
|
||||||
$session = new Session(isset($_SESSION) ? $_SESSION : null);
|
$session = new Session(isset($_SESSION) ? $_SESSION : null);
|
||||||
|
|
||||||
$result = Director::handleRequest($req, $session, $model);
|
$result = Director::handleRequest($req, $session, $model);
|
||||||
|
@ -102,6 +102,17 @@ class Session {
|
|||||||
|
|
||||||
protected $changedData = array();
|
protected $changedData = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start PHP session, then create a new Session object with the given start 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;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cookie domain, for example 'www.php.net'.
|
* Cookie domain, for example 'www.php.net'.
|
||||||
*
|
*
|
||||||
@ -176,17 +187,6 @@ class Session {
|
|||||||
return self::$session_store_path;
|
return self::$session_store_path;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provide an <code>array</code> of rules specifing timeouts for IPv4 address ranges or
|
* Provide an <code>array</code> of rules specifing timeouts for IPv4 address ranges or
|
||||||
* individual IPv4 addresses. The key is an IP address or range and the value is the time
|
* individual IPv4 addresses. The key is an IP address or range and the value is the time
|
||||||
@ -301,10 +301,12 @@ class Session {
|
|||||||
$diffVar = &$diffVar[$n];
|
$diffVar = &$diffVar[$n];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if($var !== $val) {
|
||||||
$var = $val;
|
$var = $val;
|
||||||
$diffVar = $val;
|
$diffVar = $val;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function inst_addToArray($name, $val) {
|
public function inst_addToArray($name, $val) {
|
||||||
$names = explode('.', $name);
|
$names = explode('.', $name);
|
||||||
@ -355,13 +357,21 @@ class Session {
|
|||||||
$diffVar = &$this->changedData;
|
$diffVar = &$this->changedData;
|
||||||
|
|
||||||
foreach($names as $n) {
|
foreach($names as $n) {
|
||||||
|
// don't clear a record that doesn't exist
|
||||||
|
if(!isset($var[$n])) return;
|
||||||
$var = &$var[$n];
|
$var = &$var[$n];
|
||||||
|
}
|
||||||
|
|
||||||
|
// only loop to find data within diffVar if var is proven to exist in the above loop
|
||||||
|
foreach($names as $n) {
|
||||||
$diffVar = &$diffVar[$n];
|
$diffVar = &$diffVar[$n];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if($var !== null) {
|
||||||
$var = null;
|
$var = null;
|
||||||
$diffVar = null;
|
$diffVar = null;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function inst_clearAll() {
|
public function inst_clearAll() {
|
||||||
if($this->data && is_array($this->data)) {
|
if($this->data && is_array($this->data)) {
|
||||||
@ -380,8 +390,11 @@ class Session {
|
|||||||
* Only save the changes, so that anyone manipulating $_SESSION directly doesn't get burned.
|
* Only save the changes, so that anyone manipulating $_SESSION directly doesn't get burned.
|
||||||
*/
|
*/
|
||||||
public function inst_save() {
|
public function inst_save() {
|
||||||
|
if($this->changedData) {
|
||||||
|
if(!isset($_SESSION)) Session::start();
|
||||||
$this->recursivelyApply($this->changedData, $_SESSION);
|
$this->recursivelyApply($this->changedData, $_SESSION);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Recursively apply the changes represented in $data to $dest.
|
* Recursively apply the changes represented in $data to $dest.
|
||||||
@ -398,6 +411,14 @@ class Session {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the changed data, for debugging purposes.
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function inst_changedData() {
|
||||||
|
return $this->changedData;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the appropriate form message in session, with type. This will be shown once,
|
* Sets the appropriate form message in session, with type. This will be shown once,
|
||||||
* for the form specified.
|
* for the form specified.
|
||||||
|
4
main.php
4
main.php
@ -59,9 +59,7 @@ if (version_compare(phpversion(), '5.3.2', '<')) {
|
|||||||
/**
|
/**
|
||||||
* Include SilverStripe's core code
|
* Include SilverStripe's core code
|
||||||
*/
|
*/
|
||||||
require_once("core/Core.php");
|
require_once('core/Core.php');
|
||||||
|
|
||||||
Session::start();
|
|
||||||
|
|
||||||
// IIS will sometimes generate this.
|
// IIS will sometimes generate this.
|
||||||
if(!empty($_SERVER['HTTP_X_ORIGINAL_URL'])) {
|
if(!empty($_SERVER['HTTP_X_ORIGINAL_URL'])) {
|
||||||
|
@ -791,9 +791,17 @@ class Versioned extends DataExtension {
|
|||||||
|
|
||||||
if(!headers_sent() && !Director::is_cli()) {
|
if(!headers_sent() && !Director::is_cli()) {
|
||||||
if(Versioned::current_stage() == 'Live') {
|
if(Versioned::current_stage() == 'Live') {
|
||||||
|
// clear the cookie if it's set
|
||||||
|
if(!empty($_COOKIE['bypassStaticCache'])) {
|
||||||
Cookie::set('bypassStaticCache', null, 0, null, null, false, true /* httponly */);
|
Cookie::set('bypassStaticCache', null, 0, null, null, false, true /* httponly */);
|
||||||
|
unset($_COOKIE['bypassStaticCache']);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// set the cookie if it's cleared
|
||||||
|
if(empty($_COOKIE['bypassStaticCache'])) {
|
||||||
Cookie::set('bypassStaticCache', '1', 0, null, null, false, true /* httponly */);
|
Cookie::set('bypassStaticCache', '1', 0, null, null, false, true /* httponly */);
|
||||||
|
$_COOKIE['bypassStaticCache'] = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -55,9 +55,6 @@ class SecurityToken extends Object implements TemplateGlobalProvider {
|
|||||||
*/
|
*/
|
||||||
function __construct($name = null) {
|
function __construct($name = null) {
|
||||||
$this->name = ($name) ? $name : self::get_default_name();
|
$this->name = ($name) ? $name : self::get_default_name();
|
||||||
// only regenerate if the token isn't already set in the session
|
|
||||||
if(!$this->getValue()) $this->setValue($this->generate());
|
|
||||||
|
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,7 +129,15 @@ class SecurityToken extends Object implements TemplateGlobalProvider {
|
|||||||
* @return String
|
* @return String
|
||||||
*/
|
*/
|
||||||
function getValue() {
|
function getValue() {
|
||||||
return Session::get($this->getName());
|
$value = Session::get($this->getName());
|
||||||
|
|
||||||
|
// only regenerate if the token isn't already set in the session
|
||||||
|
if(!$value) {
|
||||||
|
$value = $this->generate();
|
||||||
|
$this->setValue($value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -45,6 +45,30 @@ class SessionTest extends SapphireTest {
|
|||||||
$this->assertEquals($session, array('Test' => 'Test', 'Test-2' => 'Test-2'));
|
$this->assertEquals($session, array('Test' => 'Test', 'Test-2' => 'Test-2'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check that changedData isn't populated with junk when clearing non-existent entries.
|
||||||
|
*/
|
||||||
|
function testClearElementThatDoesntExist() {
|
||||||
|
$s = new Session(array('something' => array('does' => 'exist')));
|
||||||
|
|
||||||
|
$s->inst_clear('something.doesnt.exist');
|
||||||
|
$this->assertEquals(array(), $s->inst_changedData());
|
||||||
|
|
||||||
|
$s->inst_set('something-else', 'val');
|
||||||
|
$s->inst_clear('something-new');
|
||||||
|
$this->assertEquals(array('something-else' => 'val'), $s->inst_changedData());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check that changedData is populated with clearing data.
|
||||||
|
*/
|
||||||
|
function testClearElementThatDoesExist() {
|
||||||
|
$s = new Session(array('something' => array('does' => 'exist')));
|
||||||
|
|
||||||
|
$s->inst_clear('something.does');
|
||||||
|
$this->assertEquals(array('something' => array('does' => null)), $s->inst_changedData());
|
||||||
|
}
|
||||||
|
|
||||||
function testNonStandardPath(){
|
function testNonStandardPath(){
|
||||||
Session::set_session_store_path(realpath(dirname($_SERVER['DOCUMENT_ROOT']) . '/../session'));
|
Session::set_session_store_path(realpath(dirname($_SERVER['DOCUMENT_ROOT']) . '/../session'));
|
||||||
Session::start();
|
Session::start();
|
||||||
|
Loading…
Reference in New Issue
Block a user