mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
Added HTTPResponse object, to encapsulate Controller responses for aid testing and other 'quirky' uses of Controllers
git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/trunk@40390 467b73ca-7a2a-4603-9d3b-597d59a354a9
This commit is contained in:
parent
801b94b3bf
commit
8a0688aa5d
@ -88,7 +88,7 @@ class ContentController extends Controller {
|
||||
if($getVars) $url = "./?" . http_build_query($getVars);
|
||||
else $url = "./";
|
||||
Director::redirect($url);
|
||||
die();
|
||||
return;
|
||||
}
|
||||
|
||||
singleton('SiteTree')->extend('contentcontrollerInit', $this);
|
||||
|
@ -23,8 +23,8 @@ class ContentNegotiator {
|
||||
}
|
||||
|
||||
|
||||
static function process($content) {
|
||||
if(self::$disabled) return $content;
|
||||
static function process(HTTPResponse $response) {
|
||||
if(self::$disabled) return;
|
||||
|
||||
$mimes = array(
|
||||
"xhtml" => "application/xhtml+xml",
|
||||
@ -56,35 +56,39 @@ class ContentNegotiator {
|
||||
}
|
||||
|
||||
$negotiator = new ContentNegotiator();
|
||||
return $negotiator->$chosenFormat($content);
|
||||
$negotiator->$chosenFormat( $response );
|
||||
}
|
||||
|
||||
function xhtml($content) {
|
||||
function xhtml(HTTPResponse $response) {
|
||||
$content = $response->getBody();
|
||||
|
||||
// Only serve "pure" XHTML if the XML header is present
|
||||
if(substr($content,0,5) == '<' . '?xml' /*|| $_REQUEST['ajax']*/ ) {
|
||||
header("Content-type: application/xhtml+xml; charset=" . self::$encoding);
|
||||
header("Vary: Accept");
|
||||
if(substr($content,0,5) == '<' . '?xml' ) {
|
||||
$response->addHeader("Content-type", "application/xhtml+xml; charset=" . self::$encoding);
|
||||
$response->addHeader("Vary" , "Accept");
|
||||
|
||||
$content = str_replace(' ',' ', $content);
|
||||
$content = str_replace('<br>','<br />', $content);
|
||||
$content = eregi_replace('(<img[^>]*[^/>])>','\\1/>', $content);
|
||||
return $content;
|
||||
|
||||
$response->setBody($content);
|
||||
|
||||
} else {
|
||||
return $this->html($content);
|
||||
return $this->html($response);
|
||||
}
|
||||
}
|
||||
function html($content) {
|
||||
if(!headers_sent()) {
|
||||
header("Content-type: text/html; charset=" . self::$encoding);
|
||||
header("Vary: Accept");
|
||||
}
|
||||
function html(HTTPResponse $response) {
|
||||
$response->addHeader("Content-type", "text/html; charset=" . self::$encoding);
|
||||
$response->addHeader("Vary", "Accept");
|
||||
|
||||
$content = $response->getBody();
|
||||
|
||||
$content = ereg_replace("<\\?xml[^>]+\\?>\n?",'',$content);
|
||||
$content = str_replace(array('/>','xml:lang','application/xhtml+xml'),array('>','lang','text/html'), $content);
|
||||
$content = ereg_replace('<!DOCTYPE[^>]+>', '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">', $content);
|
||||
$content = ereg_replace('<html xmlns="[^"]+"','<html ', $content);
|
||||
|
||||
return $content;
|
||||
|
||||
$response->setBody($content);
|
||||
}
|
||||
|
||||
protected static $disabled;
|
||||
|
@ -19,6 +19,11 @@ class Controller extends ViewableData {
|
||||
protected static $currentController;
|
||||
|
||||
protected $basicAuthEnabled = true;
|
||||
|
||||
/**
|
||||
* The HTTPResponse object that the controller returns
|
||||
*/
|
||||
protected $response;
|
||||
|
||||
function setURLParams($urlParams) {
|
||||
$this->urlParams = $urlParams;
|
||||
@ -38,14 +43,20 @@ class Controller extends ViewableData {
|
||||
protected $baseInitCalled = false;
|
||||
function run($requestParams) {
|
||||
if(isset($_GET['debug_profile'])) Profiler::mark("Controller", "run");
|
||||
|
||||
Controller::$currentController = $this;
|
||||
|
||||
$this->response = new HTTPResponse();
|
||||
$this->requestParams = $requestParams;
|
||||
|
||||
$this->action = isset($this->urlParams['Action']) ? str_replace("-","_",$this->urlParams['Action']) : "index";
|
||||
|
||||
// Init
|
||||
$this->baseInitCalled = false;
|
||||
$this->init();
|
||||
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;
|
||||
|
||||
// Look at the action variables for forms
|
||||
foreach($this->requestParams as $paramName => $paramVal) {
|
||||
@ -93,7 +104,7 @@ class Controller extends ViewableData {
|
||||
// disregard validation if a single field is called
|
||||
if(!isset($_REQUEST['action_callfieldmethod'])) {
|
||||
$valid = $form->beforeProcessing();
|
||||
if(!$valid) exit();
|
||||
if(!$valid) return $this->response;
|
||||
}
|
||||
|
||||
// If the action wasnt' set, choose the default on the form.
|
||||
@ -143,6 +154,7 @@ class Controller extends ViewableData {
|
||||
if(isset($_GET['debug_controller'])) Debug::show("Found function $funcName on the $this->class controller");
|
||||
|
||||
if(isset($_GET['debug_profile'])) Profiler::mark("$this->class::$funcName (controller action)");
|
||||
|
||||
$result = $this->$funcName($this->urlParams);
|
||||
if(isset($_GET['debug_profile'])) Profiler::unmark("$this->class::$funcName (controller action)");
|
||||
|
||||
@ -163,14 +175,17 @@ class Controller extends ViewableData {
|
||||
|
||||
$result = $viewer->process($extended);
|
||||
}
|
||||
|
||||
$this->response->setBody($result);
|
||||
|
||||
if($result) $result = ContentNegotiator::process($result);
|
||||
if($result) ContentNegotiator::process($this->response);
|
||||
|
||||
// Set up HTTP cache headers
|
||||
HTTP::add_cache_headers();
|
||||
HTTP::add_cache_headers($this->response);
|
||||
|
||||
if(isset($_GET['debug_profile'])) Profiler::unmark("Controller", "run");
|
||||
return $result;
|
||||
|
||||
return $this->response;
|
||||
}
|
||||
|
||||
function defaultAction($action) {
|
||||
@ -234,8 +249,6 @@ class Controller extends ViewableData {
|
||||
Cookie::set("PastMember", true);
|
||||
DB::query("UPDATE Member SET LastVisited = NOW() WHERE ID = $member->ID", null);
|
||||
}
|
||||
Controller::$currentController = $this;
|
||||
|
||||
|
||||
// This is used to test that subordinate controllers are actually calling parent::init() - a common bug
|
||||
$this->baseInitCalled = true;
|
||||
@ -244,6 +257,13 @@ class Controller extends ViewableData {
|
||||
public static function currentController() {
|
||||
return Controller::$currentController;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current controller
|
||||
*/
|
||||
public static function curr() {
|
||||
return Controller::$currentController;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the member is allowed to do the given action.
|
||||
@ -303,6 +323,19 @@ class Controller extends ViewableData {
|
||||
function PastMember() {
|
||||
return Cookie::get("PastMember") ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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){
|
||||
$url = Director::baseURL() . $url;
|
||||
}
|
||||
|
||||
$this->response->redirect($url);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
|
@ -42,13 +42,17 @@ class Director {
|
||||
function direct($url) {
|
||||
if(isset($_GET['debug_profile'])) Profiler::mark("Director","direct");
|
||||
$controllerObj = Director::getControllerForURL($url);
|
||||
|
||||
if(is_string($controllerObj) && substr($controllerObj,0,9) == 'redirect:') {
|
||||
Director::redirect(substr($controllerObj, 9));
|
||||
|
||||
} else if($controllerObj) {
|
||||
$output = $controllerObj->run(array_merge((array)$_GET, (array)$_POST, (array)$_FILES));
|
||||
$response = $controllerObj->run(array_merge((array)$_GET, (array)$_POST, (array)$_FILES));
|
||||
|
||||
if(isset($_GET['debug_profile'])) Profiler::mark("Outputting to browser");
|
||||
echo $output;
|
||||
$response->output();
|
||||
if(isset($_GET['debug_profile'])) Profiler::unmark("Outputting to browser");
|
||||
|
||||
}
|
||||
if(isset($_GET['debug_profile'])) Profiler::unmark("Director","direct");
|
||||
}
|
||||
@ -158,20 +162,7 @@ class Director {
|
||||
* - if it is just a word without an slashes, then it redirects to another action on the current controller.
|
||||
*/
|
||||
static 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){
|
||||
$url = Director::baseURL() . $url;
|
||||
}
|
||||
if(headers_sent($file, $line)) {
|
||||
echo
|
||||
"<p>Redirecting to <a href=\"$url\" title=\"Please click this link if your browser does not redirect you\">$url... (output started on $file, line $line)</a></p>
|
||||
<meta http-equiv=\"refresh\" content=\"1; url=$url\" />
|
||||
<script type=\"text/javascript\">setTimeout('window.location.href = \"$url\"', 50);</script>";
|
||||
|
||||
} else {
|
||||
header("Location: $url");
|
||||
}
|
||||
die();
|
||||
Controller::curr()->redirect($url);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -9,7 +9,8 @@ class ModelAsController extends Controller implements NestedController {
|
||||
|
||||
public function run($requestParams) {
|
||||
$this->init();
|
||||
return $this->getNestedController()->run($requestParams);
|
||||
$nested = $this->getNestedController();
|
||||
return $nested->run($requestParams);
|
||||
}
|
||||
|
||||
public function init() {
|
||||
|
@ -5,13 +5,17 @@
|
||||
*/
|
||||
class RootURLController extends Controller {
|
||||
protected static $is_at_root = false;
|
||||
|
||||
/**
|
||||
* Marks at that we are actually at the root URL before handing control over to another controller
|
||||
*/
|
||||
function index() {
|
||||
|
||||
public function run($requestParams) {
|
||||
self::$is_at_root = true;
|
||||
Director::direct(self::get_homepage_urlsegment() . '/');
|
||||
|
||||
$controller = new ModelAsController();
|
||||
$controller->setUrlParams(array(
|
||||
'URLSegment' => self::get_homepage_urlsegment(),
|
||||
'Action' => '',
|
||||
));
|
||||
|
||||
return $controller->run($requestParams);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -87,7 +87,6 @@ class RedirectorPage_Controller extends Page_Controller {
|
||||
}
|
||||
|
||||
parent::init();
|
||||
die();
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
@ -637,4 +637,14 @@ class Form extends ViewableData {
|
||||
static function set_current_action($action) {
|
||||
self::$current_action = $action;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// TESTING HELPERS
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function testSubmission($action, $data) {
|
||||
$data['action_' . $action] = true;
|
||||
|
||||
//$this->controller->run()
|
||||
}
|
||||
}
|
||||
|
@ -70,7 +70,7 @@ class Security extends Controller {
|
||||
} else {
|
||||
Director::redirect("Security/login");
|
||||
}
|
||||
exit();
|
||||
return;
|
||||
}
|
||||
|
||||
function LoginForm() {
|
||||
|
Loading…
Reference in New Issue
Block a user