mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-09-17 23:16:04 +02:00
commit
7a8b4a7f63
5
_config/cookie.yml
Normal file
5
_config/cookie.yml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
Name: cookie
|
||||||
|
---
|
||||||
|
Injector:
|
||||||
|
Cookie_Backend: CookieJar
|
@ -14,17 +14,12 @@ class Cookie {
|
|||||||
private static $report_errors = true;
|
private static $report_errors = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string cookie class
|
* Fetch the current instance of the cookie backend
|
||||||
|
*
|
||||||
|
* @return Cookie_Backend The cookie backend
|
||||||
*/
|
*/
|
||||||
static $cookie_class = 'Cookie';
|
|
||||||
|
|
||||||
private static $inst = null;
|
|
||||||
|
|
||||||
public static function get_inst() {
|
public static function get_inst() {
|
||||||
if(is_null(self::$inst)) {
|
return Injector::inst()->get('Cookie_Backend');
|
||||||
self::$inst = new self::$cookie_class();
|
|
||||||
}
|
|
||||||
return self::$inst;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -41,105 +36,37 @@ class Cookie {
|
|||||||
public static function set($name, $value, $expiry = 90, $path = null, $domain = null, $secure = false,
|
public static function set($name, $value, $expiry = 90, $path = null, $domain = null, $secure = false,
|
||||||
$httpOnly = true
|
$httpOnly = true
|
||||||
) {
|
) {
|
||||||
return self::get_inst()->inst_set($name, $value, $expiry, $path, $domain, $secure, $httpOnly);
|
return self::get_inst()->set($name, $value, $expiry, $path, $domain, $secure, $httpOnly);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a cookie variable.
|
* Get the cookie value by name
|
||||||
*
|
*
|
||||||
* @param string
|
* @param string $name The name of the cookie to get
|
||||||
* @return mixed
|
* @param boolean $includeUnsent Include cookies we've yet to send when fetching values
|
||||||
*/
|
|
||||||
public static function get($name) {
|
|
||||||
return self::get_inst()->inst_get($name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string
|
|
||||||
* @param string
|
|
||||||
* @param string
|
|
||||||
*/
|
|
||||||
public static function force_expiry($name, $path = null, $domain = null) {
|
|
||||||
return self::get_inst()->inst_force_expiry($name, $path, $domain);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated 3.2 Use "Cookie.report_errors" config setting instead
|
|
||||||
* @param bool
|
|
||||||
*/
|
|
||||||
public static function set_report_errors($reportErrors) {
|
|
||||||
Deprecation::notice('3.2', 'Use "Cookie.report_errors" config setting instead');
|
|
||||||
self::get_inst()->inst_set_report_errors($reportErrors);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated 3.2 Use "Cookie.report_errors" config setting instead
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public static function report_errors() {
|
|
||||||
Deprecation::notice('3.2', 'Use "Cookie.report_errors" config setting instead');
|
|
||||||
return self::get_inst()->inst_report_errors();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set a cookie variable
|
|
||||||
*
|
*
|
||||||
* @param string $name The variable name
|
* @return string|null The cookie value or null if unset
|
||||||
* @param mixed $value The variable value.
|
|
||||||
* @param int $expiry The expiry time, in days. Defaults to 90.
|
|
||||||
* @param string $path See http://php.net/set_session
|
|
||||||
* @param string $domain See http://php.net/set_session
|
|
||||||
* @param boolean $secure See http://php.net/set_session
|
|
||||||
* @param boolean $httpOnly See http://php.net/set_session
|
|
||||||
*/
|
*/
|
||||||
protected function inst_set($name, $value, $expiry = 90, $path = null,
|
public static function get($name, $includeUnsent = true) {
|
||||||
$domain = null, $secure = false, $httpOnly = true
|
return self::get_inst()->get($name, $includeUnsent);
|
||||||
) {
|
}
|
||||||
if(!headers_sent($file, $line)) {
|
|
||||||
$expiry = $expiry > 0 ? time()+(86400*$expiry) : $expiry;
|
/**
|
||||||
$path = ($path) ? $path : Director::baseURL();
|
* Get all the cookies
|
||||||
setcookie($name, $value, $expiry, $path, $domain, $secure, $httpOnly);
|
*
|
||||||
$_COOKIE[$name] = $value;
|
* @param boolean $includeUnsent Include cookies we've yet to send
|
||||||
} else {
|
* @return array All the cookies
|
||||||
if(Config::inst()->get('Cookie', 'report_errors')) {
|
*/
|
||||||
user_error("Cookie '$name' can't be set. The site started outputting content at line $line in $file",
|
public static function get_all($includeUnsent = true) {
|
||||||
E_USER_WARNING);
|
return self::get_inst()->getAll($includeUnsent);
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string
|
* @param string
|
||||||
* @return mixed
|
* @param string
|
||||||
*/
|
|
||||||
protected function inst_get($name) {
|
|
||||||
return isset($_COOKIE[$name]) ? $_COOKIE[$name] : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string
|
* @param string
|
||||||
*/
|
*/
|
||||||
protected function inst_force_expiry($name, $path = null, $domain = null) {
|
public static function force_expiry($name, $path = null, $domain = null, $secure = false, $httpOnly = true) {
|
||||||
if(!headers_sent($file, $line)) {
|
return self::get_inst()->forceExpiry($name, $path, $domain, $secure, $httpOnly);
|
||||||
self::set($name, null, -20, $path, $domain);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated 3.2 Use the "Cookie.report_errors" config setting instead
|
|
||||||
* @param bool
|
|
||||||
*/
|
|
||||||
protected function inst_set_report_errors($reportErrors) {
|
|
||||||
Deprecation::notice('3.2', 'Use the "Cookie.report_errors" config setting instead');
|
|
||||||
Config::inst()->update('Cookie', 'report_errors', $reportErrors);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated 3.2 Use the "Cookie.report_errors" config setting instead
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
protected function inst_report_errors() {
|
|
||||||
Deprecation::notice('3.2', 'Use the "Cookie.report_errors" config setting instead');
|
|
||||||
return Config::inst()->get('Cookie', 'report_errors');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
157
control/CookieJar.php
Normal file
157
control/CookieJar.php
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A default backend for the setting and getting of cookies
|
||||||
|
*
|
||||||
|
* This backend allows one to better test Cookie setting and seperate cookie
|
||||||
|
* handling from the core
|
||||||
|
*
|
||||||
|
* @todo Create a config array for defaults (eg: httpOnly, secure, path, domain, expiry)
|
||||||
|
* @todo A getter for cookies that haven't been sent to the browser yet
|
||||||
|
* @todo Tests / a way to set the state without hacking with $_COOKIE
|
||||||
|
* @todo Store the meta information around cookie setting (path, domain, secure, etc)
|
||||||
|
*/
|
||||||
|
class CookieJar implements Cookie_Backend {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hold the cookies that were existing at time of instatiation (ie: The ones
|
||||||
|
* sent to PHP by the browser)
|
||||||
|
*
|
||||||
|
* @var array Existing cookies sent by the browser
|
||||||
|
*/
|
||||||
|
protected $existing = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hold the current cookies (ie: a mix of those that were sent to us and we
|
||||||
|
* have set without the ones we've cleared)
|
||||||
|
*
|
||||||
|
* @var array The state of cookies once we've sent the response
|
||||||
|
*/
|
||||||
|
protected $current = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hold any NEW cookies that were set by the appliation and will be sent
|
||||||
|
* in the next response
|
||||||
|
*
|
||||||
|
* @var array New cookies set by the application
|
||||||
|
*/
|
||||||
|
protected $new = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When creating the backend we want to store the existing cookies in our
|
||||||
|
* "existing" array. This allows us to distinguish between cookies we recieved
|
||||||
|
* or we set ourselves (and didn't get from the browser)
|
||||||
|
*
|
||||||
|
* @param array $cookies The existing cookies to load into the cookie jar.
|
||||||
|
* Omit this to default to $_COOKIE
|
||||||
|
*/
|
||||||
|
public function __construct($cookies = array()) {
|
||||||
|
$this->current = $this->existing = func_num_args()
|
||||||
|
? ($cookies ?: array()) // Convert empty values to blank arrays
|
||||||
|
: $_COOKIE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a cookie
|
||||||
|
*
|
||||||
|
* @param string $name The name of the cookie
|
||||||
|
* @param string $value The value for the cookie to hold
|
||||||
|
* @param int $expiry The number of days until expiry; 0 indicates a cookie valid for the current session
|
||||||
|
* @param string $path The path to save the cookie on (falls back to site base)
|
||||||
|
* @param string $domain The domain to make the cookie available on
|
||||||
|
* @param boolean $secure Can the cookie only be sent over SSL?
|
||||||
|
* @param boolean $httpOnly Prevent the cookie being accessible by JS
|
||||||
|
*/
|
||||||
|
public function set($name, $value, $expiry = 90, $path = null, $domain = null, $secure = false, $httpOnly = true) {
|
||||||
|
//are we setting or clearing a cookie? false values are reserved for clearing cookies (see PHP manual)
|
||||||
|
$clear = false;
|
||||||
|
if ($value === false || $value === '' || $expiry < 0) {
|
||||||
|
$clear = true;
|
||||||
|
$value = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//expiry === 0 is a special case where we set a cookie for the current user session
|
||||||
|
if ($expiry !== 0) {
|
||||||
|
//don't do the maths if we are clearing
|
||||||
|
$expiry = $clear ? -1 : SS_Datetime::now()->Format('U') + (86400 * $expiry);
|
||||||
|
}
|
||||||
|
//set the path up
|
||||||
|
$path = $path ? $path : Director::baseURL();
|
||||||
|
//send the cookie
|
||||||
|
$this->outputCookie($name, $value, $expiry, $path, $domain, $secure, $httpOnly);
|
||||||
|
//keep our variables in check
|
||||||
|
if ($clear) {
|
||||||
|
unset ($this->new[$name], $this->current[$name]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$this->new[$name] = $this->current[$name] = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the cookie value by name
|
||||||
|
*
|
||||||
|
* @param string $name The name of the cookie to get
|
||||||
|
* @param boolean $includeUnsent Include cookies we've yet to send when fetching values
|
||||||
|
*
|
||||||
|
* @return string|null The cookie value or null if unset
|
||||||
|
*/
|
||||||
|
public function get($name, $includeUnsent = true) {
|
||||||
|
$cookies = $includeUnsent ? $this->current : $this->existing;
|
||||||
|
if (isset($cookies[$name])) {
|
||||||
|
return $cookies[$name];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all the cookies
|
||||||
|
*
|
||||||
|
* @param boolean $includeUnsent Include cookies we've yet to send
|
||||||
|
* @return array All the cookies
|
||||||
|
*/
|
||||||
|
public function getAll($includeUnsent = true) {
|
||||||
|
return $includeUnsent ? $this->current : $this->existing;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Force the expiry of a cookie by name
|
||||||
|
*
|
||||||
|
* @param string $name The name of the cookie to expire
|
||||||
|
* @param string $path The path to save the cookie on (falls back to site base)
|
||||||
|
* @param string $domain The domain to make the cookie available on
|
||||||
|
* @param boolean $secure Can the cookie only be sent over SSL?
|
||||||
|
* @param boolean $httpOnly Prevent the cookie being accessible by JS
|
||||||
|
*/
|
||||||
|
public function forceExpiry($name, $path = null, $domain = null, $secure = false, $httpOnly = true) {
|
||||||
|
$this->set($name, false, -1, $path, $domain, $secure, $httpOnly);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The function that actually sets the cookie using PHP
|
||||||
|
*
|
||||||
|
* @see http://uk3.php.net/manual/en/function.setcookie.php
|
||||||
|
*
|
||||||
|
* @param string $name The name of the cookie
|
||||||
|
* @param string|array $value The value for the cookie to hold
|
||||||
|
* @param int $expiry The number of days until expiry
|
||||||
|
* @param string $path The path to save the cookie on (falls back to site base)
|
||||||
|
* @param string $domain The domain to make the cookie available on
|
||||||
|
* @param boolean $secure Can the cookie only be sent over SSL?
|
||||||
|
* @param boolean $httpOnly Prevent the cookie being accessible by JS
|
||||||
|
* @return boolean If the cookie was set or not; doesn't mean it's accepted by the browser
|
||||||
|
*/
|
||||||
|
protected function outputCookie(
|
||||||
|
$name, $value, $expiry = 90, $path = null, $domain = null, $secure = false, $httpOnly = true
|
||||||
|
) {
|
||||||
|
// if headers aren't sent, we can set the cookie
|
||||||
|
if(!headers_sent($file, $line)) {
|
||||||
|
return setcookie($name, $value, $expiry, $path, $domain, $secure, $httpOnly);
|
||||||
|
} else if(Config::inst()->get('Cookie', 'report_errors')) {
|
||||||
|
throw new LogicException(
|
||||||
|
"Cookie '$name' can't be set. The site started outputting content at line $line in $file"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
61
control/Cookie_Backend.php
Normal file
61
control/Cookie_Backend.php
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Cookie_Backend interface for use with `Cookie::$inst`.
|
||||||
|
*
|
||||||
|
* See Cookie_DefaultBackend and Cookie
|
||||||
|
*/
|
||||||
|
interface Cookie_Backend {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When creating the backend we want to store the existing cookies in our
|
||||||
|
* "existing" array. This allows us to distinguish between cookies we recieved
|
||||||
|
* or we set ourselves (and didn't get from the browser)
|
||||||
|
*
|
||||||
|
* @param array $cookies The existing cookies to load into the cookie jar
|
||||||
|
*/
|
||||||
|
public function __construct($cookies = array());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a cookie
|
||||||
|
*
|
||||||
|
* @param string $name The name of the cookie
|
||||||
|
* @param string $value The value for the cookie to hold
|
||||||
|
* @param int $expiry The number of days until expiry
|
||||||
|
* @param string $path The path to save the cookie on (falls back to site base)
|
||||||
|
* @param string $domain The domain to make the cookie available on
|
||||||
|
* @param boolean $secure Can the cookie only be sent over SSL?
|
||||||
|
* @param boolean $httpOnly Prevent the cookie being accessible by JS
|
||||||
|
*/
|
||||||
|
public function set($name, $value, $expiry = 90, $path = null, $domain = null, $secure = false, $httpOnly = true);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the cookie value by name
|
||||||
|
*
|
||||||
|
* @param string $name The name of the cookie to get
|
||||||
|
* @param boolean $includeUnsent Include cookies we've yet to send when fetching values
|
||||||
|
*
|
||||||
|
* @return string|null The cookie value or null if unset
|
||||||
|
*/
|
||||||
|
public function get($name, $includeUnsent = true);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all the cookies
|
||||||
|
*
|
||||||
|
* @param boolean $includeUnsent Include cookies we've yet to send
|
||||||
|
* @return array All the cookies
|
||||||
|
*/
|
||||||
|
public function getAll($includeUnsent = true);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Force the expiry of a cookie by name
|
||||||
|
*
|
||||||
|
* @param string $name The name of the cookie to expire
|
||||||
|
* @param string $path The path to save the cookie on (falls back to site base)
|
||||||
|
* @param string $domain The domain to make the cookie available on
|
||||||
|
* @param boolean $secure Can the cookie only be sent over SSL?
|
||||||
|
* @param boolean $httpOnly Prevent the cookie being accessible by JS
|
||||||
|
*/
|
||||||
|
public function forceExpiry($name, $path = null, $domain = null, $secure = false, $httpOnly = true);
|
||||||
|
|
||||||
|
}
|
@ -207,17 +207,18 @@ class Director implements TemplateGlobalProvider {
|
|||||||
* GET otherwise. Overwritten by $postVars['_method'] if present.
|
* GET otherwise. Overwritten by $postVars['_method'] if present.
|
||||||
* @param string $body The HTTP body
|
* @param string $body The HTTP body
|
||||||
* @param array $headers HTTP headers with key-value pairs
|
* @param array $headers HTTP headers with key-value pairs
|
||||||
* @param array $cookies to populate $_COOKIE
|
* @param array|Cookie_Backend $cookies to populate $_COOKIE
|
||||||
* @param HTTP_Request $request The {@see HTTP_Request} object generated as a part of this request
|
* @param HTTP_Request $request The {@see HTTP_Request} object generated as a part of this request
|
||||||
* @return SS_HTTPResponse
|
* @return SS_HTTPResponse
|
||||||
*
|
*
|
||||||
* @uses getControllerForURL() The rule-lookup logic is handled by this.
|
* @uses getControllerForURL() The rule-lookup logic is handled by this.
|
||||||
* @uses Controller::run() Controller::run() handles the page logic for a Director::direct() call.
|
* @uses Controller::run() Controller::run() handles the page logic for a Director::direct() call.
|
||||||
*/
|
*/
|
||||||
public static function test($url, $postVars = null, $session = null, $httpMethod = null, $body = null,
|
public static function test($url, $postVars = null, $session = array(), $httpMethod = null, $body = null,
|
||||||
$headers = null, $cookies = null, &$request = null) {
|
$headers = array(), $cookies = array(), &$request = null) {
|
||||||
|
|
||||||
Config::nest();
|
Config::nest();
|
||||||
|
Injector::nest();
|
||||||
|
|
||||||
// These are needed so that calling Director::test() doesnt muck with whoever is calling it.
|
// These are needed so that calling Director::test() doesnt muck with whoever is calling it.
|
||||||
// Really, it's some inappropriate coupling and should be resolved by making less use of statics
|
// Really, it's some inappropriate coupling and should be resolved by making less use of statics
|
||||||
@ -227,6 +228,9 @@ class Director implements TemplateGlobalProvider {
|
|||||||
if(!$httpMethod) $httpMethod = ($postVars || is_array($postVars)) ? "POST" : "GET";
|
if(!$httpMethod) $httpMethod = ($postVars || is_array($postVars)) ? "POST" : "GET";
|
||||||
|
|
||||||
if(!$session) $session = Injector::inst()->create('Session', array());
|
if(!$session) $session = Injector::inst()->create('Session', array());
|
||||||
|
$cookieJar = $cookies instanceof Cookie_Backend
|
||||||
|
? $cookies
|
||||||
|
: Injector::inst()->createWithArgs('Cookie_Backend', array($cookies ?: array()));
|
||||||
|
|
||||||
// Back up the current values of the superglobals
|
// Back up the current values of the superglobals
|
||||||
$existingRequestVars = isset($_REQUEST) ? $_REQUEST : array();
|
$existingRequestVars = isset($_REQUEST) ? $_REQUEST : array();
|
||||||
@ -241,6 +245,29 @@ class Director implements TemplateGlobalProvider {
|
|||||||
Config::inst()->update('Cookie', 'report_errors', false);
|
Config::inst()->update('Cookie', 'report_errors', false);
|
||||||
Requirements::set_backend(new Requirements_Backend());
|
Requirements::set_backend(new Requirements_Backend());
|
||||||
|
|
||||||
|
// Set callback to invoke prior to return
|
||||||
|
$onCleanup = function() use(
|
||||||
|
$existingRequestVars, $existingGetVars, $existingPostVars, $existingSessionVars,
|
||||||
|
$existingCookies, $existingServer, $existingRequirementsBackend, $oldStage
|
||||||
|
) {
|
||||||
|
// Restore the superglobals
|
||||||
|
$_REQUEST = $existingRequestVars;
|
||||||
|
$_GET = $existingGetVars;
|
||||||
|
$_POST = $existingPostVars;
|
||||||
|
$_SESSION = $existingSessionVars;
|
||||||
|
$_COOKIE = $existingCookies;
|
||||||
|
$_SERVER = $existingServer;
|
||||||
|
|
||||||
|
Requirements::set_backend($existingRequirementsBackend);
|
||||||
|
|
||||||
|
// These are needed so that calling Director::test() doesnt muck with whoever is calling it.
|
||||||
|
// Really, it's some inappropriate coupling and should be resolved by making less use of statics
|
||||||
|
Versioned::reading_stage($oldStage);
|
||||||
|
|
||||||
|
Injector::unnest(); // Restore old CookieJar, etc
|
||||||
|
Config::unnest();
|
||||||
|
};
|
||||||
|
|
||||||
if (strpos($url, '#') !== false) {
|
if (strpos($url, '#') !== false) {
|
||||||
$url = substr($url, 0, strpos($url, '#'));
|
$url = substr($url, 0, strpos($url, '#'));
|
||||||
}
|
}
|
||||||
@ -269,7 +296,8 @@ class Director implements TemplateGlobalProvider {
|
|||||||
$_GET = (array)$getVars;
|
$_GET = (array)$getVars;
|
||||||
$_POST = (array)$postVars;
|
$_POST = (array)$postVars;
|
||||||
$_SESSION = $session ? $session->inst_getAll() : array();
|
$_SESSION = $session ? $session->inst_getAll() : array();
|
||||||
$_COOKIE = (array) $cookies;
|
$_COOKIE = $cookieJar->getAll(false);
|
||||||
|
Injector::inst()->registerService($cookieJar, 'Cookie_Backend');
|
||||||
$_SERVER['REQUEST_URI'] = Director::baseURL() . $urlWithQuerystring;
|
$_SERVER['REQUEST_URI'] = Director::baseURL() . $urlWithQuerystring;
|
||||||
|
|
||||||
$request = new SS_HTTPRequest($httpMethod, $url, $getVars, $postVars, $body);
|
$request = new SS_HTTPRequest($httpMethod, $url, $getVars, $postVars, $body);
|
||||||
@ -280,7 +308,7 @@ class Director implements TemplateGlobalProvider {
|
|||||||
$model = DataModel::inst();
|
$model = DataModel::inst();
|
||||||
$output = Injector::inst()->get('RequestProcessor')->preRequest($request, $session, $model);
|
$output = Injector::inst()->get('RequestProcessor')->preRequest($request, $session, $model);
|
||||||
if ($output === false) {
|
if ($output === false) {
|
||||||
// @TODO Need to NOT proceed with the request in an elegant manner
|
$onCleanup();
|
||||||
throw new SS_HTTPResponse_Exception(_t('Director.INVALID_REQUEST', 'Invalid request'), 400);
|
throw new SS_HTTPResponse_Exception(_t('Director.INVALID_REQUEST', 'Invalid request'), 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -300,25 +328,12 @@ class Director implements TemplateGlobalProvider {
|
|||||||
|
|
||||||
$output = Injector::inst()->get('RequestProcessor')->postRequest($request, $result, $model);
|
$output = Injector::inst()->get('RequestProcessor')->postRequest($request, $result, $model);
|
||||||
if ($output === false) {
|
if ($output === false) {
|
||||||
|
$onCleanup();
|
||||||
throw new SS_HTTPResponse_Exception("Invalid response");
|
throw new SS_HTTPResponse_Exception("Invalid response");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Restore the superglobals
|
// Return valid response
|
||||||
$_REQUEST = $existingRequestVars;
|
$onCleanup();
|
||||||
$_GET = $existingGetVars;
|
|
||||||
$_POST = $existingPostVars;
|
|
||||||
$_SESSION = $existingSessionVars;
|
|
||||||
$_COOKIE = $existingCookies;
|
|
||||||
$_SERVER = $existingServer;
|
|
||||||
|
|
||||||
Requirements::set_backend($existingRequirementsBackend);
|
|
||||||
|
|
||||||
// These are needed so that calling Director::test() doesnt muck with whoever is calling it.
|
|
||||||
// Really, it's some inappropriate coupling and should be resolved by making less use of statics
|
|
||||||
Versioned::reading_stage($oldStage);
|
|
||||||
|
|
||||||
Config::unnest();
|
|
||||||
|
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -395,18 +395,11 @@ class Session {
|
|||||||
public function inst_destroy($removeCookie = true) {
|
public function inst_destroy($removeCookie = true) {
|
||||||
if(session_id()) {
|
if(session_id()) {
|
||||||
if($removeCookie) {
|
if($removeCookie) {
|
||||||
$path = Config::inst()->get('Session', 'cookie_path');
|
$path = Config::inst()->get('Session', 'cookie_path') ?: Director::baseURL();
|
||||||
if(!$path) $path = Director::baseURL();
|
|
||||||
$domain = Config::inst()->get('Session', 'cookie_domain');
|
$domain = Config::inst()->get('Session', 'cookie_domain');
|
||||||
$secure = Config::inst()->get('Session', 'cookie_secure');
|
$secure = Config::inst()->get('Session', 'cookie_secure');
|
||||||
|
|
||||||
if($domain) {
|
Cookie::force_expiry(session_name(), $path, $domain, $secure, true);
|
||||||
Cookie::set(session_name(), '', null, $path, $domain, $secure, true);
|
|
||||||
} else {
|
|
||||||
Cookie::set(session_name(), '', null, $path, null, $secure, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
unset($_COOKIE[session_name()]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
session_destroy();
|
session_destroy();
|
||||||
|
@ -746,6 +746,7 @@ class Injector {
|
|||||||
* @deprecated since 3.1.1
|
* @deprecated since 3.1.1
|
||||||
*/
|
*/
|
||||||
public function registerNamedService($name, $service) {
|
public function registerNamedService($name, $service) {
|
||||||
|
Deprecation::notice('3.1.1', 'registerNamedService is deprecated, use registerService instead');
|
||||||
return $this->registerService($service, $name);
|
return $this->registerService($service, $name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -882,4 +883,4 @@ class Injector {
|
|||||||
public function createWithArgs($name, $constructorArgs) {
|
public function createWithArgs($name, $constructorArgs) {
|
||||||
return $this->get($name, false, $constructorArgs);
|
return $this->get($name, false, $constructorArgs);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -12,6 +12,11 @@ class TestSession {
|
|||||||
* @var Session
|
* @var Session
|
||||||
*/
|
*/
|
||||||
private $session;
|
private $session;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var Cookie_Backend
|
||||||
|
*/
|
||||||
|
private $cookies;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var SS_HTTPResponse
|
* @var SS_HTTPResponse
|
||||||
@ -36,6 +41,7 @@ class TestSession {
|
|||||||
|
|
||||||
public function __construct() {
|
public function __construct() {
|
||||||
$this->session = Injector::inst()->create('Session', array());
|
$this->session = Injector::inst()->create('Session', array());
|
||||||
|
$this->cookies = Injector::inst()->create('Cookie_Backend');
|
||||||
$this->controller = new Controller();
|
$this->controller = new Controller();
|
||||||
$this->controller->setSession($this->session);
|
$this->controller->setSession($this->session);
|
||||||
$this->controller->pushCurrent();
|
$this->controller->pushCurrent();
|
||||||
@ -62,8 +68,15 @@ class TestSession {
|
|||||||
public function get($url, $session = null, $headers = null, $cookies = null) {
|
public function get($url, $session = null, $headers = null, $cookies = null) {
|
||||||
$headers = (array) $headers;
|
$headers = (array) $headers;
|
||||||
if($this->lastUrl && !isset($headers['Referer'])) $headers['Referer'] = $this->lastUrl;
|
if($this->lastUrl && !isset($headers['Referer'])) $headers['Referer'] = $this->lastUrl;
|
||||||
$this->lastResponse
|
$this->lastResponse = Director::test(
|
||||||
= Director::test($url, null, $session ? $session : $this->session, null, null, $headers, $cookies);
|
$url,
|
||||||
|
null,
|
||||||
|
$session ?: $this->session,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
$headers,
|
||||||
|
$cookies ?: $this->cookies
|
||||||
|
);
|
||||||
$this->lastUrl = $url;
|
$this->lastUrl = $url;
|
||||||
if(!$this->lastResponse) user_error("Director::test($url) returned null", E_USER_WARNING);
|
if(!$this->lastResponse) user_error("Director::test($url) returned null", E_USER_WARNING);
|
||||||
return $this->lastResponse;
|
return $this->lastResponse;
|
||||||
@ -84,8 +97,15 @@ class TestSession {
|
|||||||
public function post($url, $data, $headers = null, $session = null, $body = null, $cookies = null) {
|
public function post($url, $data, $headers = null, $session = null, $body = null, $cookies = null) {
|
||||||
$headers = (array) $headers;
|
$headers = (array) $headers;
|
||||||
if($this->lastUrl && !isset($headers['Referer'])) $headers['Referer'] = $this->lastUrl;
|
if($this->lastUrl && !isset($headers['Referer'])) $headers['Referer'] = $this->lastUrl;
|
||||||
$this->lastResponse
|
$this->lastResponse = Director::test(
|
||||||
= Director::test($url, $data, $session ? $session : $this->session, null, $body, $headers, $cookies);
|
$url,
|
||||||
|
$data,
|
||||||
|
$session ?: $this->session,
|
||||||
|
null,
|
||||||
|
$body,
|
||||||
|
$headers,
|
||||||
|
$cookies ?: $this->cookies
|
||||||
|
);
|
||||||
$this->lastUrl = $url;
|
$this->lastUrl = $url;
|
||||||
if(!$this->lastResponse) user_error("Director::test($url) returned null", E_USER_WARNING);
|
if(!$this->lastResponse) user_error("Director::test($url) returned null", E_USER_WARNING);
|
||||||
return $this->lastResponse;
|
return $this->lastResponse;
|
||||||
|
117
docs/en/reference/cookies.md
Normal file
117
docs/en/reference/cookies.md
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
# Cookies
|
||||||
|
|
||||||
|
## Accessing and Manipulating Cookies
|
||||||
|
|
||||||
|
Cookies can be set/get/expired using the `Cookie` class and its static methods
|
||||||
|
|
||||||
|
setting:
|
||||||
|
|
||||||
|
:::php
|
||||||
|
Cookie::set('CookieName', 'CookieValue');
|
||||||
|
|
||||||
|
getting:
|
||||||
|
|
||||||
|
:::php
|
||||||
|
Cookie::get('CookieName'); //returns null if not set or the value if set
|
||||||
|
|
||||||
|
expiring / removing / clearing:
|
||||||
|
|
||||||
|
:::php
|
||||||
|
Cookie::force_expiry('CookieName');
|
||||||
|
|
||||||
|
## The `Cookie_Backend`
|
||||||
|
|
||||||
|
The `Cookie` class manipulates and sets cookies using a `Cookie_Backend`. The backend is in charge of the logic
|
||||||
|
that fetches, sets and expires cookies. By default we use a the `CookieJar` backend which uses PHP's
|
||||||
|
[setcookie](http://www.php.net/manual/en/function.setcookie.php) function.
|
||||||
|
|
||||||
|
The `CookieJar` keeps track of cookies that have been set by the current process as well as those that were recieved
|
||||||
|
from the browser.
|
||||||
|
|
||||||
|
By default the `Cookie` class will load the `$_COOKIE` superglobal into the `Cookie_Backend`. If you want to change
|
||||||
|
the initial state of the `Cookie_Backend` you can load your own backend into the `CookieJar` service registered with
|
||||||
|
the `Injector`.
|
||||||
|
|
||||||
|
eg:
|
||||||
|
|
||||||
|
:::php
|
||||||
|
$myCookies = array(
|
||||||
|
'cookie1' => 'value1',
|
||||||
|
);
|
||||||
|
|
||||||
|
$newBackend = new CookieJar($myCookies);
|
||||||
|
|
||||||
|
Injector::inst()->registerService($newBackend, 'Cookie_Backend');
|
||||||
|
|
||||||
|
Cookie::get('cookie1'); //will return 'value1'
|
||||||
|
|
||||||
|
### Resetting the Cookie_Backend state
|
||||||
|
|
||||||
|
Assuming that your application hasn't messed around with the `$_COOKIE` superglobal, you can reset the state of your
|
||||||
|
`Cookie_Backend` by simply unregistering the `CookieJar` service with `Injector`. Next time you access `Cookie` it'll
|
||||||
|
create a new service for you using the `$_COOKIE` superglobal.
|
||||||
|
|
||||||
|
eg:
|
||||||
|
|
||||||
|
:::php
|
||||||
|
Injector::inst()->unregisterNamedObject('Cookie_Backend');
|
||||||
|
|
||||||
|
Cookie::get('cookiename'); // will return $_COOKIE['cookiename'] if set
|
||||||
|
|
||||||
|
|
||||||
|
Alternatively, if you know that the superglobal has been changed (or you aren't sure it hasn't) you can attempt to use
|
||||||
|
the current `CookieJar` service to tell you what it was like when it was registered.
|
||||||
|
|
||||||
|
eg:
|
||||||
|
|
||||||
|
:::php
|
||||||
|
//store the cookies that were loaded into the `CookieJar`
|
||||||
|
$recievedCookie = Cookie::get_inst()->getAll(false);
|
||||||
|
|
||||||
|
//set a new `CookieJar`
|
||||||
|
Injector::inst()->registerService(new CookieJar($recievedCookie), 'CookieJar');
|
||||||
|
|
||||||
|
|
||||||
|
### Using your own Cookie_Backend
|
||||||
|
|
||||||
|
If you need to implement your own Cookie_Backend you can use the injector system to force a different class to be used.
|
||||||
|
|
||||||
|
example:
|
||||||
|
|
||||||
|
:::yml
|
||||||
|
---
|
||||||
|
Name: mycookie
|
||||||
|
After: '#cookie'
|
||||||
|
---
|
||||||
|
Injector:
|
||||||
|
Cookie_Backend:
|
||||||
|
class: MyCookieJar
|
||||||
|
|
||||||
|
To be a valid backend your class must implement the `Cookie_Backend` interface.
|
||||||
|
|
||||||
|
## Advanced Usage
|
||||||
|
|
||||||
|
### Sent vs Received Cookies
|
||||||
|
|
||||||
|
Sometimes it's useful to be able to tell if a cookie was set by the process (thus will be sent to the browser) or if it
|
||||||
|
came from the browser as part of the request.
|
||||||
|
|
||||||
|
Using the `Cookie_Backend` we can do this like such:
|
||||||
|
|
||||||
|
:::php
|
||||||
|
Cookie::set('CookieName', 'CookieVal');
|
||||||
|
|
||||||
|
Cookie::get('CookieName'); //gets the cookie as we set it
|
||||||
|
|
||||||
|
//will return the cookie as it was when it was sent in the request
|
||||||
|
Cookie::get('CookieName', false);
|
||||||
|
|
||||||
|
|
||||||
|
### Accessing all the cookies at once
|
||||||
|
|
||||||
|
One can also access all of the cookies in one go using the `Cookie_Backend`
|
||||||
|
|
||||||
|
:::php
|
||||||
|
Cookie::get_inst()->getAll(); //returns all the cookies including ones set during the current process
|
||||||
|
|
||||||
|
Cookie::get_inst()->getAll(false); //returns all the cookies in the request
|
@ -162,8 +162,8 @@ class DB {
|
|||||||
Cookie::set("alternativeDatabaseName", base64_encode($encrypted), 0, null, null, false, true);
|
Cookie::set("alternativeDatabaseName", base64_encode($encrypted), 0, null, null, false, true);
|
||||||
Cookie::set("alternativeDatabaseNameIv", base64_encode($iv), 0, null, null, false, true);
|
Cookie::set("alternativeDatabaseNameIv", base64_encode($iv), 0, null, null, false, true);
|
||||||
} else {
|
} else {
|
||||||
Cookie::set("alternativeDatabaseName", null, 0, null, null, false, true);
|
Cookie::force_expiry("alternativeDatabaseName", null, null, false, true);
|
||||||
Cookie::set("alternativeDatabaseNameIv", null, 0, null, null, false, true);
|
Cookie::force_expiry("alternativeDatabaseNameIv", null, null, false, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1032,15 +1032,13 @@ class Versioned extends DataExtension implements TemplateGlobalProvider {
|
|||||||
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
|
// clear the cookie if it's set
|
||||||
if(!empty($_COOKIE['bypassStaticCache'])) {
|
if(Cookie::get('bypassStaticCache')) {
|
||||||
Cookie::set('bypassStaticCache', null, 0, null, null, false, true /* httponly */);
|
Cookie::force_expiry('bypassStaticCache', null, null, false, true /* httponly */);
|
||||||
unset($_COOKIE['bypassStaticCache']);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// set the cookie if it's cleared
|
// set the cookie if it's cleared
|
||||||
if(empty($_COOKIE['bypassStaticCache'])) {
|
if(!Cookie::get('bypassStaticCache')) {
|
||||||
Cookie::set('bypassStaticCache', '1', 0, null, null, false, true /* httponly */);
|
Cookie::set('bypassStaticCache', '1', 0, null, null, false, true /* httponly */);
|
||||||
$_COOKIE['bypassStaticCache'] = 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -394,7 +394,6 @@ class Member extends DataObject implements TemplateGlobalProvider {
|
|||||||
Cookie::set('alc_enc', $this->ID . ':' . $token, 90, null, null, null, true);
|
Cookie::set('alc_enc', $this->ID . ':' . $token, 90, null, null, null, true);
|
||||||
} else {
|
} else {
|
||||||
$this->RememberLoginToken = null;
|
$this->RememberLoginToken = null;
|
||||||
Cookie::set('alc_enc', null);
|
|
||||||
Cookie::force_expiry('alc_enc');
|
Cookie::force_expiry('alc_enc');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -489,7 +488,6 @@ class Member extends DataObject implements TemplateGlobalProvider {
|
|||||||
$this->extend('memberLoggedOut');
|
$this->extend('memberLoggedOut');
|
||||||
|
|
||||||
$this->RememberLoginToken = null;
|
$this->RememberLoginToken = null;
|
||||||
Cookie::set('alc_enc', null); // // Clear the Remember Me cookie
|
|
||||||
Cookie::force_expiry('alc_enc');
|
Cookie::force_expiry('alc_enc');
|
||||||
|
|
||||||
// Switch back to live in order to avoid infinite loops when
|
// Switch back to live in order to avoid infinite loops when
|
||||||
|
135
tests/control/CookieJarTest.php
Normal file
135
tests/control/CookieJarTest.php
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Testing CookieJar
|
||||||
|
*
|
||||||
|
* Testing the CookieJar acts as expected and keeps track of Cookies it is loaded
|
||||||
|
* with as well as new cookies that are set during the running of an application
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class CookieJarTest extends SapphireTest {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test that the construction argument is stored and returned as expected
|
||||||
|
*/
|
||||||
|
public function testConstruct() {
|
||||||
|
|
||||||
|
//some default cookies to load
|
||||||
|
$defaultCookies = array(
|
||||||
|
'cookie1' => 1,
|
||||||
|
'cookie2' => 'cookies',
|
||||||
|
'cookie3' => 'test',
|
||||||
|
);
|
||||||
|
|
||||||
|
$cookieJar = new CookieJar($defaultCookies);
|
||||||
|
|
||||||
|
//make sure all the "recieved" cookies are as expected
|
||||||
|
$this->assertEquals($defaultCookies, $cookieJar->getAll(false));
|
||||||
|
|
||||||
|
//make sure there are no "phantom" cookies
|
||||||
|
$this->assertEquals($defaultCookies, $cookieJar->getAll(true));
|
||||||
|
|
||||||
|
//check an empty array is accepted
|
||||||
|
$cookieJar = new CookieJar(array());
|
||||||
|
$this->assertEmpty($cookieJar->getAll(false));
|
||||||
|
|
||||||
|
|
||||||
|
//check no argument is accepted
|
||||||
|
$cookieJar = new CookieJar();
|
||||||
|
$this->assertEmpty($cookieJar->getAll(false));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test that we can set and get cookies
|
||||||
|
*/
|
||||||
|
public function testSetAndGet() {
|
||||||
|
$cookieJar = new CookieJar();
|
||||||
|
|
||||||
|
$this->assertEmpty($cookieJar->get('testCookie'));
|
||||||
|
|
||||||
|
//set a test cookie
|
||||||
|
$cookieJar->set('testCookie', 'testVal');
|
||||||
|
|
||||||
|
//make sure it was set
|
||||||
|
$this->assertEquals('testVal', $cookieJar->get('testCookie'));
|
||||||
|
|
||||||
|
//make sure we can distinguise it from ones that were "existing"
|
||||||
|
$this->assertEmpty($cookieJar->get('testCookie', false));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test that we can distinguish between vars that were loaded on instantiation
|
||||||
|
* and those added later
|
||||||
|
*/
|
||||||
|
public function testExistingVersusNew() {
|
||||||
|
//load with a cookie
|
||||||
|
$cookieJar = new CookieJar(array(
|
||||||
|
'cookieExisting' => 'i woz here',
|
||||||
|
));
|
||||||
|
|
||||||
|
//set a new cookie
|
||||||
|
$cookieJar->set('cookieNew', 'i am new');
|
||||||
|
|
||||||
|
//check we can fetch new and old cookie values
|
||||||
|
$this->assertEquals('i woz here', $cookieJar->get('cookieExisting'));
|
||||||
|
$this->assertEquals('i woz here', $cookieJar->get('cookieExisting', false));
|
||||||
|
$this->assertEquals('i am new', $cookieJar->get('cookieNew'));
|
||||||
|
//there should be no original value for the new cookie
|
||||||
|
$this->assertEmpty($cookieJar->get('cookieNew', false));
|
||||||
|
|
||||||
|
//change the existing cookie, can we fetch the new and old value
|
||||||
|
$cookieJar->set('cookieExisting', 'i woz changed');
|
||||||
|
|
||||||
|
$this->assertEquals('i woz changed', $cookieJar->get('cookieExisting'));
|
||||||
|
$this->assertEquals('i woz here', $cookieJar->get('cookieExisting', false));
|
||||||
|
|
||||||
|
//check we can get all cookies
|
||||||
|
$this->assertEquals(array(
|
||||||
|
'cookieExisting' => 'i woz changed',
|
||||||
|
'cookieNew' => 'i am new',
|
||||||
|
), $cookieJar->getAll());
|
||||||
|
|
||||||
|
//check we can get all original cookies
|
||||||
|
$this->assertEquals(array(
|
||||||
|
'cookieExisting' => 'i woz here',
|
||||||
|
), $cookieJar->getAll(false));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check we can remove cookies and we can access their original values
|
||||||
|
*/
|
||||||
|
public function testForceExpiry() {
|
||||||
|
//load an existing cookie
|
||||||
|
$cookieJar = new CookieJar(array(
|
||||||
|
'cookieExisting' => 'i woz here',
|
||||||
|
));
|
||||||
|
|
||||||
|
//make sure it's available
|
||||||
|
$this->assertEquals('i woz here', $cookieJar->get('cookieExisting'));
|
||||||
|
|
||||||
|
//remove the cookie
|
||||||
|
$cookieJar->forceExpiry('cookieExisting');
|
||||||
|
|
||||||
|
//check it's gone
|
||||||
|
$this->assertEmpty($cookieJar->get('cookieExisting'));
|
||||||
|
|
||||||
|
//check we can get it's original value
|
||||||
|
$this->assertEquals('i woz here', $cookieJar->get('cookieExisting', false));
|
||||||
|
|
||||||
|
|
||||||
|
//check we can add a new cookie and remove it and it doesn't leave any phantom values
|
||||||
|
$cookieJar->set('newCookie', 'i am new');
|
||||||
|
|
||||||
|
//check it's set by not recieved
|
||||||
|
$this->assertEquals('i am new', $cookieJar->get('newCookie'));
|
||||||
|
$this->assertEmpty($cookieJar->get('newCookie', false));
|
||||||
|
|
||||||
|
//remove it
|
||||||
|
$cookieJar->forceExpiry('newCookie');
|
||||||
|
|
||||||
|
//check it's neither set nor reveived
|
||||||
|
$this->assertEmpty($cookieJar->get('newCookie'));
|
||||||
|
$this->assertEmpty($cookieJar->get('newCookie', false));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
188
tests/control/CookieTest.php
Normal file
188
tests/control/CookieTest.php
Normal file
@ -0,0 +1,188 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
class CookieTest extends SapphireTest {
|
||||||
|
|
||||||
|
private $cookieInst;
|
||||||
|
|
||||||
|
public function setUp() {
|
||||||
|
parent::setUp();
|
||||||
|
Injector::nest();
|
||||||
|
Injector::inst()->registerService(new CookieJar($_COOKIE), 'Cookie_Backend');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function tearDown() {
|
||||||
|
//restore the cookie_backend
|
||||||
|
Injector::unnest();
|
||||||
|
parent::tearDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check a new cookie inst will be loaded with the superglobal by default
|
||||||
|
*/
|
||||||
|
public function testCheckNewInstTakesSuperglobal() {
|
||||||
|
//store the superglobal state
|
||||||
|
$existingCookies = $_COOKIE;
|
||||||
|
|
||||||
|
//set a mock state for the superglobal
|
||||||
|
$_COOKIE = array(
|
||||||
|
'cookie1' => 1,
|
||||||
|
'cookie2' => 'cookies',
|
||||||
|
'cookie3' => 'test',
|
||||||
|
);
|
||||||
|
|
||||||
|
Injector::inst()->unregisterNamedObject('Cookie_Backend');
|
||||||
|
|
||||||
|
$this->assertEquals($_COOKIE['cookie1'], Cookie::get('cookie1'));
|
||||||
|
$this->assertEquals($_COOKIE['cookie2'], Cookie::get('cookie2'));
|
||||||
|
$this->assertEquals($_COOKIE['cookie3'], Cookie::get('cookie3'));
|
||||||
|
|
||||||
|
//for good measure check the CookieJar hasn't stored anything extra
|
||||||
|
$this->assertEquals($_COOKIE, Cookie::get_inst()->getAll(false));
|
||||||
|
|
||||||
|
//restore the superglobal state
|
||||||
|
$_COOKIE = $existingCookies;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check we don't mess with super globals when manipulating cookies
|
||||||
|
*
|
||||||
|
* State should be managed sperately to the super global
|
||||||
|
*/
|
||||||
|
public function testCheckSuperglobalsArentTouched() {
|
||||||
|
|
||||||
|
//store the current state
|
||||||
|
$before = $_COOKIE;
|
||||||
|
|
||||||
|
//change some cookies
|
||||||
|
Cookie::set('cookie', 'not me');
|
||||||
|
Cookie::force_expiry('cookie2');
|
||||||
|
|
||||||
|
//assert it hasn't changed
|
||||||
|
$this->assertEquals($before, $_COOKIE);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check we can actually change a backend
|
||||||
|
*/
|
||||||
|
public function testChangeBackend() {
|
||||||
|
|
||||||
|
Cookie::set('test', 'testvalue');
|
||||||
|
|
||||||
|
$this->assertEquals('testvalue', Cookie::get('test'));
|
||||||
|
|
||||||
|
Injector::inst()->registerService(new CookieJar(array()), 'Cookie_Backend');
|
||||||
|
|
||||||
|
$this->assertEmpty(Cookie::get('test'));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check we can actually get the backend inst out
|
||||||
|
*/
|
||||||
|
public function testGetInst() {
|
||||||
|
|
||||||
|
$inst = new CookieJar(array('test' => 'testvalue'));
|
||||||
|
|
||||||
|
Injector::inst()->registerService($inst, 'Cookie_Backend');
|
||||||
|
|
||||||
|
$this->assertEquals($inst, Cookie::get_inst());
|
||||||
|
|
||||||
|
$this->assertEquals('testvalue', Cookie::get('test'));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test that we can set and get cookies
|
||||||
|
*/
|
||||||
|
public function testSetAndGet() {
|
||||||
|
$this->assertEmpty(Cookie::get('testCookie'));
|
||||||
|
|
||||||
|
//set a test cookie
|
||||||
|
Cookie::set('testCookie', 'testVal');
|
||||||
|
|
||||||
|
//make sure it was set
|
||||||
|
$this->assertEquals('testVal', Cookie::get('testCookie'));
|
||||||
|
|
||||||
|
//make sure we can distinguise it from ones that were "existing"
|
||||||
|
$this->assertEmpty(Cookie::get('testCookie', false));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test that we can distinguish between vars that were loaded on instantiation
|
||||||
|
* and those added later
|
||||||
|
*/
|
||||||
|
public function testExistingVersusNew() {
|
||||||
|
//load with a cookie
|
||||||
|
$cookieJar = new CookieJar(array(
|
||||||
|
'cookieExisting' => 'i woz here',
|
||||||
|
));
|
||||||
|
Injector::inst()->registerService($cookieJar, 'Cookie_Backend');
|
||||||
|
|
||||||
|
//set a new cookie
|
||||||
|
Cookie::set('cookieNew', 'i am new');
|
||||||
|
|
||||||
|
//check we can fetch new and old cookie values
|
||||||
|
$this->assertEquals('i woz here', Cookie::get('cookieExisting'));
|
||||||
|
$this->assertEquals('i woz here', Cookie::get('cookieExisting', false));
|
||||||
|
$this->assertEquals('i am new', Cookie::get('cookieNew'));
|
||||||
|
//there should be no original value for the new cookie
|
||||||
|
$this->assertEmpty(Cookie::get('cookieNew', false));
|
||||||
|
|
||||||
|
//change the existing cookie, can we fetch the new and old value
|
||||||
|
Cookie::set('cookieExisting', 'i woz changed');
|
||||||
|
|
||||||
|
$this->assertEquals('i woz changed', Cookie::get('cookieExisting'));
|
||||||
|
$this->assertEquals('i woz here', Cookie::get('cookieExisting', false));
|
||||||
|
|
||||||
|
//check we can get all cookies
|
||||||
|
$this->assertEquals(array(
|
||||||
|
'cookieExisting' => 'i woz changed',
|
||||||
|
'cookieNew' => 'i am new',
|
||||||
|
), Cookie::get_all());
|
||||||
|
|
||||||
|
//check we can get all original cookies
|
||||||
|
$this->assertEquals(array(
|
||||||
|
'cookieExisting' => 'i woz here',
|
||||||
|
), Cookie::get_all(false));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check we can remove cookies and we can access their original values
|
||||||
|
*/
|
||||||
|
public function testForceExpiry() {
|
||||||
|
//load an existing cookie
|
||||||
|
$cookieJar = new CookieJar(array(
|
||||||
|
'cookieExisting' => 'i woz here',
|
||||||
|
));
|
||||||
|
Injector::inst()->registerService($cookieJar, 'Cookie_Backend');
|
||||||
|
|
||||||
|
//make sure it's available
|
||||||
|
$this->assertEquals('i woz here', Cookie::get('cookieExisting'));
|
||||||
|
|
||||||
|
//remove the cookie
|
||||||
|
Cookie::force_expiry('cookieExisting');
|
||||||
|
|
||||||
|
//check it's gone
|
||||||
|
$this->assertEmpty(Cookie::get('cookieExisting'));
|
||||||
|
|
||||||
|
//check we can get it's original value
|
||||||
|
$this->assertEquals('i woz here', Cookie::get('cookieExisting', false));
|
||||||
|
|
||||||
|
|
||||||
|
//check we can add a new cookie and remove it and it doesn't leave any phantom values
|
||||||
|
Cookie::set('newCookie', 'i am new');
|
||||||
|
|
||||||
|
//check it's set by not recieved
|
||||||
|
$this->assertEquals('i am new', Cookie::get('newCookie'));
|
||||||
|
$this->assertEmpty(Cookie::get('newCookie', false));
|
||||||
|
|
||||||
|
//remove it
|
||||||
|
Cookie::force_expiry('newCookie');
|
||||||
|
|
||||||
|
//check it's neither set nor reveived
|
||||||
|
$this->assertEmpty(Cookie::get('newCookie'));
|
||||||
|
$this->assertEmpty(Cookie::get('newCookie', false));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -240,6 +240,7 @@ class DirectorTest extends SapphireTest {
|
|||||||
unset($_SESSION['isLive']);
|
unset($_SESSION['isLive']);
|
||||||
unset($_GET['isTest']);
|
unset($_GET['isTest']);
|
||||||
unset($_GET['isDev']);
|
unset($_GET['isDev']);
|
||||||
|
$_SESSION = $_SESSION ?: array();
|
||||||
|
|
||||||
// Test isDev=1
|
// Test isDev=1
|
||||||
$_GET['isDev'] = '1';
|
$_GET['isDev'] = '1';
|
||||||
@ -271,8 +272,13 @@ class DirectorTest extends SapphireTest {
|
|||||||
$_POST = array('somekey' => 'postvalue');
|
$_POST = array('somekey' => 'postvalue');
|
||||||
$_COOKIE = array('somekey' => 'cookievalue');
|
$_COOKIE = array('somekey' => 'cookievalue');
|
||||||
|
|
||||||
|
$cookies = Injector::inst()->createWithArgs(
|
||||||
|
'Cookie_Backend',
|
||||||
|
array(array('somekey' => 'sometestcookievalue'))
|
||||||
|
);
|
||||||
|
|
||||||
$getresponse = Director::test('errorpage?somekey=sometestgetvalue', array('somekey' => 'sometestpostvalue'),
|
$getresponse = Director::test('errorpage?somekey=sometestgetvalue', array('somekey' => 'sometestpostvalue'),
|
||||||
null, null, null, null, array('somekey' => 'sometestcookievalue'));
|
null, null, null, null, $cookies);
|
||||||
|
|
||||||
$this->assertEquals('getvalue', $_GET['somekey'],
|
$this->assertEquals('getvalue', $_GET['somekey'],
|
||||||
'$_GET reset to original value after Director::test()');
|
'$_GET reset to original value after Director::test()');
|
||||||
@ -288,7 +294,16 @@ class DirectorTest extends SapphireTest {
|
|||||||
foreach(array('return%sValue', 'returnRequestValue', 'returnCookieValue') as $testfunction) {
|
foreach(array('return%sValue', 'returnRequestValue', 'returnCookieValue') as $testfunction) {
|
||||||
$url = 'DirectorTestRequest_Controller/' . sprintf($testfunction, ucfirst($method))
|
$url = 'DirectorTestRequest_Controller/' . sprintf($testfunction, ucfirst($method))
|
||||||
. '?' . http_build_query($fixture);
|
. '?' . http_build_query($fixture);
|
||||||
$getresponse = Director::test($url, $fixture, null, strtoupper($method), null, null, $fixture);
|
|
||||||
|
$getresponse = Director::test(
|
||||||
|
$url,
|
||||||
|
$fixture,
|
||||||
|
null,
|
||||||
|
strtoupper($method),
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
Injector::inst()->createWithArgs('Cookie_Backend', array($fixture))
|
||||||
|
);
|
||||||
|
|
||||||
$this->assertInstanceOf('SS_HTTPResponse', $getresponse, 'Director::test() returns SS_HTTPResponse');
|
$this->assertInstanceOf('SS_HTTPResponse', $getresponse, 'Director::test() returns SS_HTTPResponse');
|
||||||
$this->assertEquals($fixture['somekey'], $getresponse->getBody(), 'Director::test() ' . $testfunction);
|
$this->assertEquals($fixture['somekey'], $getresponse->getBody(), 'Director::test() ' . $testfunction);
|
||||||
|
@ -558,7 +558,7 @@ class InjectorTest extends SapphireTest {
|
|||||||
$injector = new Injector();
|
$injector = new Injector();
|
||||||
$service = new stdClass();
|
$service = new stdClass();
|
||||||
|
|
||||||
$injector->registerNamedService('NamedService', $service);
|
$injector->registerService($service, 'NamedService');
|
||||||
$this->assertEquals($service, $injector->get('NamedService'));
|
$this->assertEquals($service, $injector->get('NamedService'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user