Merge pull request #3203 from mateusz/remove-global-state

Fetch the nearest Controller instead of relying on global state.
This commit is contained in:
Damian Mooyman 2014-06-13 10:15:19 +12:00
commit 3e29f6b29b
2 changed files with 33 additions and 21 deletions

View File

@ -77,7 +77,10 @@ class GridFieldDetailForm implements GridField_URLHandler {
* @return GridFieldDetailForm_ItemRequest * @return GridFieldDetailForm_ItemRequest
*/ */
public function handleItem($gridField, $request) { public function handleItem($gridField, $request) {
$controller = $gridField->getForm()->Controller(); // Our getController could either give us a true Controller, if this is the top-level GridField.
// It could also give us a RequestHandler in the form of GridFieldDetailForm_ItemRequest if this is a
// nested GridField.
$requestHandler = $gridField->getForm()->getController();
if(is_numeric($request->param('ID'))) { if(is_numeric($request->param('ID'))) {
$record = $gridField->getList()->byId($request->param("ID")); $record = $gridField->getList()->byId($request->param("ID"));
@ -87,7 +90,7 @@ class GridFieldDetailForm implements GridField_URLHandler {
$class = $this->getItemRequestClass(); $class = $this->getItemRequestClass();
$handler = Object::create($class, $gridField, $this, $record, $controller, $this->name); $handler = Object::create($class, $gridField, $this, $record, $requestHandler, $this->name);
$handler->setTemplate($this->template); $handler->setTemplate($this->template);
// if no validator has been set on the GridField and the record has a // if no validator has been set on the GridField and the record has a
@ -226,8 +229,10 @@ class GridFieldDetailForm_ItemRequest extends RequestHandler {
protected $record; protected $record;
/** /**
* This represents the current parent RequestHandler (which does not necessarily need to be a Controller).
* It allows us to traverse the RequestHandler chain upwards to reach the Controller stack.
* *
* @var Controller * @var RequestHandler
*/ */
protected $popupController; protected $popupController;
@ -252,14 +257,14 @@ class GridFieldDetailForm_ItemRequest extends RequestHandler {
* @param GridFIeld $gridField * @param GridFIeld $gridField
* @param GridField_URLHandler $component * @param GridField_URLHandler $component
* @param DataObject $record * @param DataObject $record
* @param Controller $popupController * @param RequestHandler $requestHandler
* @param string $popupFormName * @param string $popupFormName
*/ */
public function __construct($gridField, $component, $record, $popupController, $popupFormName) { public function __construct($gridField, $component, $record, $requestHandler, $popupFormName) {
$this->gridField = $gridField; $this->gridField = $gridField;
$this->component = $component; $this->component = $component;
$this->record = $record; $this->record = $record;
$this->popupController = $popupController; $this->popupController = $requestHandler;
$this->popupFormName = $popupFormName; $this->popupFormName = $popupFormName;
parent::__construct(); parent::__construct();
} }
@ -326,7 +331,7 @@ class GridFieldDetailForm_ItemRequest extends RequestHandler {
$list = $this->gridField->getList(); $list = $this->gridField->getList();
if (empty($this->record)) { if (empty($this->record)) {
$controller = Controller::curr(); $controller = $this->getToplevelController();
$noActionURL = $controller->removeAction($_REQUEST['url']); $noActionURL = $controller->removeAction($_REQUEST['url']);
$controller->getResponse()->removeHeader('Location'); //clear the existing redirect $controller->getResponse()->removeHeader('Location'); //clear the existing redirect
return $controller->redirect($noActionURL, 302); return $controller->redirect($noActionURL, 302);
@ -338,7 +343,7 @@ class GridFieldDetailForm_ItemRequest extends RequestHandler {
$canCreate = $this->record->canCreate(); $canCreate = $this->record->canCreate();
if(!$canView) { if(!$canView) {
$controller = Controller::curr(); $controller = $this->getToplevelController();
// TODO More friendly error // TODO More friendly error
return $controller->httpError(403); return $controller->httpError(403);
} }
@ -398,6 +403,10 @@ class GridFieldDetailForm_ItemRequest extends RequestHandler {
} }
} }
// Caution: API violation. Form expects a Controller, but we are giving it a RequestHandler instead.
// Thanks to this however, we are able to nest GridFields, and also access the initial Controller by
// dereferencing GridFieldDetailForm_ItemRequest->getController() multiple times. See getToplevelController
// below.
$form = new Form( $form = new Form(
$this, $this,
'ItemEditForm', 'ItemEditForm',
@ -451,9 +460,12 @@ class GridFieldDetailForm_ItemRequest extends RequestHandler {
} }
/** /**
* Traverse up nested requests until we reach the first that's not a GridFieldDetailForm_ItemRequest. * Traverse the nested RequestHandlers until we reach something that's not GridFieldDetailForm_ItemRequest.
* The opposite of {@link Controller::curr()}, required because * This allows us to access the Controller responsible for invoking the top-level GridField.
* Controller::$controller_stack is not directly accessible. * This should be equivalent to getting the controller off the top of the controller stack via Controller::curr(),
* but allows us to avoid accessing the global state.
*
* GridFieldDetailForm_ItemRequests are RequestHandlers, and as such they are not part of the controller stack.
* *
* @return Controller * @return Controller
*/ */
@ -486,7 +498,7 @@ class GridFieldDetailForm_ItemRequest extends RequestHandler {
public function doSave($data, $form) { public function doSave($data, $form) {
$new_record = $this->record->ID == 0; $new_record = $this->record->ID == 0;
$controller = Controller::curr(); $controller = $this->getToplevelController();
$list = $this->gridField->getList(); $list = $this->gridField->getList();
if($list instanceof ManyManyList) { if($list instanceof ManyManyList) {
@ -549,11 +561,11 @@ class GridFieldDetailForm_ItemRequest extends RequestHandler {
$form->sessionMessage($message, 'good'); $form->sessionMessage($message, 'good');
if($new_record) { if($new_record) {
return Controller::curr()->redirect($this->Link()); return $controller->redirect($this->Link());
} elseif($this->gridField->getList()->byId($this->record->ID)) { } elseif($this->gridField->getList()->byId($this->record->ID)) {
// Return new view, as we can't do a "virtual redirect" via the CMS Ajax // Return new view, as we can't do a "virtual redirect" via the CMS Ajax
// to the same URL (it assumes that its content is already current, and doesn't reload) // to the same URL (it assumes that its content is already current, and doesn't reload)
return $this->edit(Controller::curr()->getRequest()); return $this->edit($controller->getRequest());
} else { } else {
// Changes to the record properties might've excluded the record from // Changes to the record properties might've excluded the record from
// a filtered list, so return back to the main view if it can't be found // a filtered list, so return back to the main view if it can't be found
@ -574,7 +586,7 @@ class GridFieldDetailForm_ItemRequest extends RequestHandler {
$this->record->delete(); $this->record->delete();
} catch(ValidationException $e) { } catch(ValidationException $e) {
$form->sessionMessage($e->getResult()->message(), 'bad'); $form->sessionMessage($e->getResult()->message(), 'bad');
return Controller::curr()->redirectBack(); return $this->getToplevelController()->redirectBack();
} }
$message = sprintf( $message = sprintf(
@ -592,7 +604,7 @@ class GridFieldDetailForm_ItemRequest extends RequestHandler {
} }
//when an item is deleted, redirect to the parent controller //when an item is deleted, redirect to the parent controller
$controller = Controller::curr(); $controller = $this->getToplevelController();
$controller->getRequest()->addHeader('X-Pjax', 'Content'); // Force a content refresh $controller->getRequest()->addHeader('X-Pjax', 'Content'); // Force a content refresh
return $controller->redirect($this->getBacklink(), 302); //redirect back to admin section return $controller->redirect($this->getBacklink(), 302); //redirect back to admin section

View File

@ -139,7 +139,7 @@ class GridFieldPrintButton implements GridField_HTMLProvider, GridField_ActionPr
*/ */
public function getTitle(GridField $gridField) { public function getTitle(GridField $gridField) {
$form = $gridField->getForm(); $form = $gridField->getForm();
$currentController = Controller::curr(); $currentController = $gridField->getForm()->getController();
$title = ''; $title = '';
if(method_exists($currentController, 'Title')) { if(method_exists($currentController, 'Title')) {