BUGFIX Enabled Link() methods for RecordController and CollectionController, and adjusted url handling to ModelAdmin counterparts to avoid linkage handling problems

BUGFIX Requiring a parentController for RecordController
ENHANCEMENT Custom getViewer() methods to use Page main templates if CollectionController is nested in a ContentController

git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/trunk@63681 467b73ca-7a2a-4603-9d3b-597d59a354a9
This commit is contained in:
Ingo Schommer 2008-10-06 19:29:04 +00:00
parent 6878171375
commit 711de868c9
5 changed files with 225 additions and 142 deletions

View File

@ -21,20 +21,22 @@ abstract class CollectionController extends Controller {
static $url_handlers = array( static $url_handlers = array(
'' => 'index', '' => 'index',
'$Action' => 'handleAction', '$Action' => 'handleActionOrID',
); );
static $page_size = 20; public static $page_size = 20;
static $allowed_actions = array('index','search', 'SearchForm', 'ResultsForm'); static $allowed_actions = array('index','search','add','AddForm','SearchForm','ResultsForm');
/** /**
* @param string $parentController * @param string $parentController
* @param string $modelClass * @param string $modelClass
*/ */
function __construct($parentController = null, $modelClass = null) { function __construct($parentController = null, $modelClass = null) {
if($parentController) $this->parentController = $parent; if($parentController) $this->parentController = $parentController;
if($modelClass) $this->modelClass = $modelClass; if($modelClass) $this->modelClass = $modelClass;
parent::__construct();
} }
function init() { function init() {
@ -51,7 +53,38 @@ abstract class CollectionController extends Controller {
* @return unknown * @return unknown
*/ */
function Link() { function Link() {
die("not implemented yet"); if($this->parentController) {
return Controller::join_links($this->parentController->Link(), "$this->modelClass");
} else {
return Controller::join_links("$this->modelClass");
}
}
/**
* Delegate to different control flow, depending on whether the
* URL parameter is a number (record id) or string (action).
*
* @param unknown_type $request
* @return unknown
*/
function handleActionOrID($request) {
if (is_numeric($request->param('Action'))) {
return $this->handleID($request);
} else {
return $this->handleAction($request);
}
}
/**
* Delegate to the RecordController if a valid numeric ID appears in the URL
* segment.
*
* @param HTTPRequest $request
* @return RecordController
*/
function handleID($request) {
$class = $this->recordControllerClass;
return new $class($this, $request);
} }
/** /**
@ -63,20 +96,6 @@ abstract class CollectionController extends Controller {
return $this->modelClass; return $this->modelClass;
} }
/**
* Delegate to the {@link RecordController} if a valid numeric ID appears in the URL
* segment.
*
* @param HTTPRequest $request
* @return RecordController
*/
function record($request) {
if(!$this->recordControllerClass) return $this->httpError(403);
$class = $this->recordControllerClass;
return new $class($this, $this->modelClass);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////
function index($request) { function index($request) {
@ -144,6 +163,74 @@ abstract class CollectionController extends Controller {
} }
/////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Create a new model record.
*
* @param unknown_type $request
* @return unknown
*/
function add($request) {
if(!singleton($this->modelClass)->canCreate(Member::currentUser())) {
return $this->httpError(403);
}
return $this->render(array(
'Form' => $this->AddForm(),
'SearchForm' => false
));
}
/**
* Returns a form for editing the attached model
*/
public function AddForm() {
$newRecord = new $this->modelClass();
if($newRecord->hasMethod('getAddFormFields')) {
$fields = $newRecord->getAddFormFields();
} else {
$fields = $newRecord->getFormFields();
}
$validator = ($newRecord->hasMethod('getValidator')) ? $newRecord->getValidator() : null;
$actions = new FieldSet(new FormAction("doAdd", "Add"));
$form = new Form($this, "AddForm", $fields, $actions, $validator);
return $form;
}
function doAdd($data, $form, $request) {
if(!singleton($this->modelClass)->canCreate(Member::currentUser())) {
return $this->httpError(403);
}
$className = $this->modelClass;
$model = new $className();
// We write before saveInto, since this will let us save has-many and many-many relationships :-)
$model->write();
$form->saveInto($model);
$model->write();
/*
$form->sessionMessage(
_t('RecordController.SAVESUCCESS','Saved record'),
'good'
);
*/
if($this->canDetailView()) {
Director::redirect(Controller::join_links($this->Link(), $model->ID , 'edit'));
} else {
Director::redirectBack();
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////
/** /**
@ -168,5 +255,28 @@ abstract class CollectionController extends Controller {
public function canDetailView() { public function canDetailView() {
return true; return true;
} }
/**
* If a parentcontroller exists, use its main template,
* and mix in specific collectioncontroller subtemplates.
*/
function getViewer($action) {
if($this->parentController) {
$viewer = $this->parentController->getViewer($action);
$parentClass = $this->class;
$layoutTemplate = null;
while($parentClass != "Controller" && !$layoutTemplate) {
$templates[] = strtok($parentClass,'_') . '_' . $action;
$parentClass = get_parent_class($parentClass);
$layoutTemplate = SSViewer::getTemplateFileByType($parentClass, 'Layout');
}
if($layoutTemplate) $viewer->setTemplateFile('Layout', $layoutTemplate);
return $viewer;
} else {
return parent::getViewer($action);
}
}
} }
?> ?>

View File

@ -4,27 +4,18 @@
* @subpackage control * @subpackage control
*/ */
class RecordController extends Controller { class RecordController extends Controller {
protected $parentController;
protected $modelClass;
protected $currentRecord; protected $currentRecord;
static $allowed_actions = array('add','edit', 'view', 'EditForm', 'ViewForm'); static $allowed_actions = array('edit','view','delete','EditForm','ViewForm','DeleteForm');
static $url_handlers = array( function __construct($parentController, $request) {
'' => 'index', $this->parentController = $parentController;
'add' => 'add', $modelName = $parentController->getModelClass();
'AddForm' => 'AddForm',
'$ID/$Action' => 'handleAction', if(is_numeric($request->latestParam('Action'))) {
); $this->currentRecord = DataObject::get_by_id($this->modelClass, $request->latestParam('Action'));
}
/**
* @param string $parentController
* @param string $modelClass
*/
function __construct($parentController = null, $modelClass = null) {
if($parentController) $this->parentController = $parentController;
if($modelClass) $this->modelClass = $modelClass;
parent::__construct(); parent::__construct();
} }
@ -37,20 +28,12 @@ class RecordController extends Controller {
Requirements::themedCSS('form'); Requirements::themedCSS('form');
} }
function handleAction($request) {
if(is_numeric($request->latestParam('ID'))) {
$this->currentRecord = DataObject::get_by_id($this->modelClass, $request->latestParam('ID'));
}
return parent::handleAction($request);
}
/** /**
* Link fragment - appends the current record ID to the URL. * Link fragment - appends the current record ID to the URL.
* *
*/ */
function Link() { function Link() {
die("not implemented yet"); return Controller::join_links($this->parentController->Link(), "/{$this->currentRecord->ID}");
} }
///////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////
@ -71,7 +54,8 @@ class RecordController extends Controller {
} }
return $this->render(array( return $this->render(array(
'Form' => $this->EditForm() 'Form' => $this->EditForm(),
'ExtraForm' => $this->DeleteForm()
)); ));
} }
@ -85,19 +69,28 @@ class RecordController extends Controller {
$validator = ($this->currentRecord->hasMethod('getValidator')) ? $this->currentRecord->getValidator() : null; $validator = ($this->currentRecord->hasMethod('getValidator')) ? $this->currentRecord->getValidator() : null;
$actions = new FieldSet( $actions = new FieldSet(
new FormAction("doSave", "Save") new FormAction("doEdit", "Save")
); );
if($this->currentRecord->canDelete(Member::currentUser())) {
$actions->push($deleteAction = new FormAction('doDelete', 'Delete'));
$deleteAction->addExtraClass('delete');
}
$form = new Form($this, "EditForm", $fields, $actions, $validator); $form = new Form($this, "EditForm", $fields, $actions, $validator);
$form->loadDataFrom($this->currentRecord); $form->loadDataFrom($this->currentRecord);
return $form; return $form;
} }
public function DeleteForm() {
if(!$this->currentRecord->canDelete(Member::currentUser())) {
return false;
}
$form = new Form($this,
"DeleteForm",
new FieldSet(),
new FieldSet(new ConfirmedFormAction('doDelete', 'Delete'))
);
return $form;
}
/** /**
* Postback action to save a record * Postback action to save a record
@ -107,7 +100,7 @@ class RecordController extends Controller {
* @param HTTPRequest $request * @param HTTPRequest $request
* @return mixed * @return mixed
*/ */
function doSave($data, $form, $request) { function doEdit($data, $form, $request) {
if(!$this->currentRecord->canEdit(Member::currentUser())) { if(!$this->currentRecord->canEdit(Member::currentUser())) {
return $this->httpError(403); return $this->httpError(403);
} }
@ -152,7 +145,7 @@ class RecordController extends Controller {
if(!$this->currentRecord) { if(!$this->currentRecord) {
return $this->httpError(404); return $this->httpError(404);
} }
if(!$this->currentRecord->canDelete(Member::currentUser())) { if(!$this->currentRecord->canView(Member::currentUser())) {
return $this->httpError(403); return $this->httpError(403);
} }
@ -174,60 +167,6 @@ class RecordController extends Controller {
return $form; return $form;
} }
////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Create a new model record.
*
* @param unknown_type $request
* @return unknown
*/
function add($request) {
if(!singleton($this->modelClass)->canCreate(Member::currentUser())) {
return $this->httpError(403);
}
return $this->render(array(
'Form' => $this->AddForm()
));
}
/**
* Returns a form for editing the attached model
*/
public function AddForm() {
$newRecord = new $this->modelClass();
if($newRecord->hasMethod('getAddFormFields')) {
$fields = $newRecord->getAddFormFields();
} else {
$fields = $newRecord->getFormFields();
}
$validator = ($newRecord->hasMethod('getValidator')) ? $newRecord->getValidator() : null;
$actions = new FieldSet(new FormAction("doAdd", "Add"));
$form = new Form($this, "AddForm", $fields, $actions, $validator);
return $form;
}
function doAdd($data, $form, $request) {
if(!singleton($this->modelClass)->canCreate(Member::currentUser())) {
return $this->httpError(403);
}
$className = $this->modelClass;
$model = new $className();
// We write before saveInto, since this will let us save has-many and many-many relationships :-)
$model->write();
$form->saveInto($model);
$model->write();
Director::redirect(Controller::join_links($this->Link(), $model->ID , 'edit'));
}
//////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////
@ -244,5 +183,28 @@ class RecordController extends Controller {
public function ModelNamePlural() { public function ModelNamePlural() {
return singleton($this->modelClass)->i18n_plural_name(); return singleton($this->modelClass)->i18n_plural_name();
} }
/**
* If a parentcontroller exists, use its main template,
* and mix in specific collectioncontroller subtemplates.
*/
function getViewer($action) {
if($this->parentController) {
$viewer = $this->parentController->getViewer($action);
$parentClass = $this->class;
$layoutTemplate = null;
while($parentClass != "Controller" && !$layoutTemplate) {
$templates[] = strtok($parentClass,'_') . '_' . $action;
$parentClass = get_parent_class($parentClass);
$layoutTemplate = SSViewer::getTemplateFileByType($parentClass, 'Layout');
}
if($layoutTemplate) $viewer->setTemplateFile('Layout', $layoutTemplate);
return $viewer;
} else {
return parent::getViewer($action);
}
}
} }
?> ?>

View File

@ -0,0 +1,36 @@
<% if Results %>
<h3><% _t('RESULTS','Results') %></h3>
<ul class="records">
<% control Results %>
<li>
<% if Top.canDetailView %>
<a href="{$Top.Link}/$ID/view">$Title</a>
<% else %>
$Title
<% end_if %>
</li>
<% end_control %>
</ul>
<% else %>
<p class="message"><% _t('NORESULTSFOUND','No records found') %></p>
<% end_if %>
<% if Results.MoreThanOnePage %>
<div id="PageNumbers">
<% if Results.NotFirstPage %>
<a class="prev" href="$Results.PrevLink"><% _t('PREV','Prev') %></a>
<% end_if %>
<span>
<% control Results.Pages %>
<% if CurrentBool %>
$PageNum
<% else %>
<a href="$Link">$PageNum</a>
<% end_if %>
<% end_control %>
</span>
<% if Results.NotLastPage %>
<a class="next" href="$Results.NextLink"><% _t('NEXT','Next') %></a>
<% end_if %>
</div>
<% end_if %>

View File

@ -3,45 +3,18 @@
<h2>$Title</h2> <h2>$Title</h2>
$Form
<% if SearchForm %> <% if SearchForm %>
<h3><% _t('SEARCH','Search') %></h3> <h3><% _t('SEARCH','Search') %></h3>
$SearchForm $SearchForm
<% end_if %> <% end_if %>
<% if Results %> <% include CollectionController_Results %>
<ul class="records">
<% control Results %>
<li>
<% if Top.canDetailView %>
<a href="{$Top.Link}/record/$ID/view">$Title</a>
<% else %>
$Title
<% end_if %>
</li>
<% end_control %>
</ul>
<% else %>
<p class="message"><% _t('NORESULTSFOUND','No records found') %></p>
<% end_if %>
<% if Results.MoreThanOnePage %> <% if canCurrentUserCreate %>
<div id="PageNumbers"> <h3>Add</h3>
<% if Results.NotLastPage %> <a href="$Link/add"><% _t('ADDNEWRECORD','Add new record') %></a>
<a class="next" href="$Results.NextLink"><% _t('NEXT','Next') %></a>
<% end_if %>
<% if Results.NotFirstPage %>
<a class="prev" href="$Results.PrevLink"><% _t('PREV','Prev') %></a>
<% end_if %>
<span>
<% control Results.Pages %>
<% if CurrentBool %>
$PageNum
<% else %>
<a href="$Link">$PageNum</a>
<% end_if %>
<% end_control %>
</span>
</div>
<% end_if %> <% end_if %>
</div> </div>

View File

@ -4,6 +4,8 @@
<h2>$Title</h2> <h2>$Title</h2>
$Form $Form
$ExtraForm
</div> </div>
</div> </div>