MINOR Added per-record canView, canDelete, canCreate and canEdit checks on gridfield and gridfield components #6890

This commit is contained in:
Stig Lindqvist 2012-03-08 13:58:53 +13:00
parent f86e53bad8
commit 8b2213d56c
11 changed files with 253 additions and 11 deletions

View File

@ -384,8 +384,11 @@ class GridField extends FormField {
if($total > 0) {
$rows = array();
foreach($list as $idx => $record) {
if(!$record->canView()) {
continue;
}
$rowContent = '';
foreach($columns as $column) {
foreach($this->getColumns() as $column) {
$colContent = $this->getColumnContent($record, $column);
// A return value of null means this columns should be skipped altogether.
if($colContent === null) continue;
@ -409,8 +412,10 @@ class GridField extends FormField {
$rows[] = $row;
}
$content['body'] = implode("\n", $rows);
} else { //display a message when the grid field is empty
}
// Display a message when the grid field is empty
if(!(isset($content['body']) && $content['body'])) {
$content['body'] = $this->createTag(
'tr',
array("class" => 'ss-gridfield-item ss-gridfield-no-items'),

View File

@ -69,6 +69,9 @@ class GridFieldDeleteAction implements GridField_ColumnProvider, GridField_Actio
* @return string - the HTML for the column
*/
public function getColumnContent($gridField, $record, $columnName) {
if(!$record->canDelete()) {
return;
}
$field = Object::create('GridField_FormAction',
$gridField,
'DeleteRecord'.$record->ID,
@ -96,6 +99,9 @@ class GridFieldDeleteAction implements GridField_ColumnProvider, GridField_Actio
$id = $arguments['RecordID'];
// Always deletes a record. Use GridFieldRelationDelete to detach it from the current relationship.
$item = $gridField->getList()->byID($id);
if(!$item->canDelete()) {
throw new ValidationException(_t('GridFieldAction_Delete.DeletePermissionsFailure',"No delete permissions"),0);
}
if(!$item) return;
$item->delete();
}

View File

@ -72,6 +72,9 @@ class GridFieldEditAction implements GridField_ColumnProvider {
* @return string - the HTML for the column
*/
public function getColumnContent($gridField, $record, $columnName) {
if(!$record->canEdit()){
return;
}
$data = new ArrayData(array(
'Link' => Controller::join_links($gridField->Link('item'), $record->ID, 'edit')
));

View File

@ -16,9 +16,20 @@
*/
class GridFieldTitle implements GridField_HTMLProvider {
/**
*
* @var bool
*/
protected $newEnabled = true;
/**
*
* @var type
*/
protected $gridField = null;
function getHTMLFragments($gridField) {
public function getHTMLFragments( $gridField) {
$this->gridField = $gridField;
return array(
'header' => $gridField->customise(array(
'NewLink' => Controller::join_links($gridField->Link('item'), 'new'),
@ -31,7 +42,14 @@ class GridFieldTitle implements GridField_HTMLProvider {
* Returns whether or not the "add new" button will appear when rendering this DataGrid title
* @return bool
*/
function getNewEnabled() {
public function getNewEnabled() {
if($this->gridField) {
$model = singleton($this->gridField->getModelClass());
if(!$model->canCreate()) {
return false;
}
}
return $this->newEnabled;
}
@ -39,9 +57,7 @@ class GridFieldTitle implements GridField_HTMLProvider {
* Enable or disable the "add new" button to add new DataGrid object instances
* @param $enabled
*/
function setNewEnabled($enabled) {
public function setNewEnabled($enabled) {
$this->newEnabled = $enabled;
}
}
?>

View File

@ -417,6 +417,34 @@ class GridFieldTest extends SapphireTest {
$this->setExpectedException('LogicException');
$field->FieldHolder();
}
/**
* @covers GridField::FieldHolder
*/
public function testCanViewOnlyOddIDs() {
$this->logInWithPermission();
$list = new ArrayList(array(
new GridFieldTest_Permissions(array("ID" => 1, "Email" => "ongi.schwimmer@example.org", 'Name' => 'Ongi Schwimmer')),
new GridFieldTest_Permissions(array("ID" => 2, "Email" => "klaus.lozenge@example.org", 'Name' => 'Klaus Lozenge')),
new GridFieldTest_Permissions(array("ID" => 3, "Email" => "otto.fischer@example.org", 'Name' => 'Otto Fischer'))
));
$config = new GridFieldConfig();
$config->addComponent(new GridFieldDefaultColumns());
$obj = new GridField('testfield', 'testfield', $list, $config);
$form = new Form(new Controller(), 'mockform', new FieldList(array($obj)), new FieldList());
$content = new CSSContentParser($obj->FieldHolder());
$members = $content->getBySelector('.ss-gridfield-item tr');
$this->assertEquals(2, count($members));
$this->assertEquals((string)$members[0]->td[0], 'Ongi Schwimmer', 'First object Name should be Ongi Schwimmer');
$this->assertEquals((string)$members[0]->td[1], 'ongi.schwimmer@example.org', 'First object Email should be ongi.schwimmer@example.org');
$this->assertEquals((string)$members[1]->td[0], 'Otto Fischer', 'Second object Name should be Otto Fischer');
$this->assertEquals((string)$members[1]->td[1], 'otto.fischer@example.org', 'Second object Email should be otto.fischer@example.org');
}
}
class GridFieldTest_Component implements GridField_ColumnProvider, GridField_ActionProvider, TestOnly{
@ -473,7 +501,6 @@ class GridFieldTest_Player extends DataObject implements TestOnly {
static $belongs_many_many = array('Teams' => 'GridFieldTest_Team');
}
class GridFieldTest_HTMLFragments implements GridField_HTMLProvider, TestOnly{
function __construct($fragments) {
$this->fragments = $fragments;
@ -482,4 +509,22 @@ class GridFieldTest_HTMLFragments implements GridField_HTMLProvider, TestOnly{
function getHTMLFragments($gridField) {
return $this->fragments;
}
}
class GridFieldTest_Permissions extends DataObject implements TestOnly {
public static $db = array(
'Name' => 'Varchar',
'Email' => 'Varchar',
);
public static $summary_fields = array(
'Name',
'Email'
);
public function canView($member = null) {
// Only records with odd numbers are viewable
if(!($this->ID % 2)){ return false; }
return true;
}
}

View File

@ -0,0 +1,18 @@
GridFieldAction_Delete_Team:
team1:
Name: Team 1
City: Cologne
team2:
Name: Team 2
City: Wellington
team3:
Name: Team 3
City: Auckland
GridFieldAction_Edit_Team:
team1:
Name: Team 1
City: Cologne
team2:
Name: Team 2
City: Wellington

View File

@ -0,0 +1,78 @@
<?php
class GridFieldDeleteActionTest extends SapphireTest {
/** @var ArrayList */
protected $list;
/** @var GridField */
protected $gridField;
/** @var Form */
protected $form;
/** @var string */
public static $fixture_file = 'sapphire/tests/forms/gridfield/GridFieldActionTest.yml';
/** @var array */
protected $extraDataObjects = array('GridFieldAction_Delete_Team', 'GridFieldAction_Edit_Team');
public function setUp() {
parent::setUp();
$this->list = new DataList('GridFieldAction_Delete_Team');
$config = GridFieldConfig::create()->addComponent(new GridFieldDeleteAction());
$this->gridField = new GridField('testfield', 'testfield', $this->list, $config);
$this->form = new Form(new Controller(), 'mockform', new FieldList(array($this->gridField)), new FieldList());
}
public function testDontShowDeleteButtons() {
if(Member::currentUser()) { Member::currentUser()->logOut(); }
$content = new CSSContentParser($this->gridField->FieldHolder());
// Check that there are content
$this->assertEquals(4, count($content->getBySelector('.ss-gridfield-item')));
// Make sure that there are no delete buttons
$this->assertEmpty($content->getBySelector('.gridfield-button-delete'), 'Delete buttons should not show when not logged in.');
}
public function testShowDeleteButtonsWithAdminPermission() {
$this->logInWithPermission('ADMIN');
$content = new CSSContentParser($this->gridField->FieldHolder());
$deleteButtons = $content->getBySelector('.gridfield-button-delete');
$this->assertEquals(3, count($deleteButtons), 'Delete buttons should show when logged in.');
}
public function testDeleteActionWithoutCorrectPermission() {
if(Member::currentUser()) { Member::currentUser()->logOut(); }
$this->setExpectedException('ValidationException');
$stateID = 'testGridStateActionField';
Session::set($stateID, array('grid'=>'', 'actionName'=>'deleterecord','args'=>array('RecordID'=>1)));
$request = new SS_HTTPRequest('POST', 'url', array(), array('action_gridFieldAlterAction?StateID='.$stateID=>true));
$this->gridField->gridFieldAlterAction(array('StateID'=>$stateID), $this->form, $request);
$this->assertEquals(3, $this->list->count(), 'User should\'t be able to delete records without correct permissions.');
}
public function testDeleteActionWithAdminPermission() {
$this->logInWithPermission('ADMIN');
$stateID = 'testGridStateActionField';
Session::set($stateID, array('grid'=>'', 'actionName'=>'deleterecord','args'=>array('RecordID'=>1)));
$request = new SS_HTTPRequest('POST', 'url', array(), array('action_gridFieldAlterAction?StateID='.$stateID=>true));
$this->gridField->gridFieldAlterAction(array('StateID'=>$stateID), $this->form, $request);
$this->assertEquals(2, $this->list->count(), 'User should be able to delete records with ADMIN permission.');
}
}
class GridFieldAction_Delete_Team extends DataObject implements TestOnly {
static $db = array(
'Name' => 'Varchar',
'City' => 'Varchar'
);
public function canView($member = null) {
return true;
}
public function canDelete($member = null) {
return parent::canDelete($member);
}
}

View File

@ -0,0 +1,55 @@
<?php
class GridFieldEditActionTest extends SapphireTest {
/** @var ArrayList */
protected $list;
/** @var GridField */
protected $gridField;
/** @var Form */
protected $form;
/** @var string */
public static $fixture_file = 'sapphire/tests/forms/gridfield/GridFieldActionTest.yml';
/** @var array */
protected $extraDataObjects = array('GridFieldAction_Delete_Team', 'GridFieldAction_Edit_Team');
public function setUp() {
parent::setUp();
$this->list = new DataList('GridFieldAction_Edit_Team');
$config = GridFieldConfig::create()->addComponent(new GridFieldEditAction());
$this->gridField = new GridField('testfield', 'testfield', $this->list, $config);
$this->form = new Form(new Controller(), 'mockform', new FieldList(array($this->gridField)), new FieldList());
}
public function testDontShowEditLinks() {
if(Member::currentUser()) { Member::currentUser()->logOut(); }
$content = new CSSContentParser($this->gridField->FieldHolder());
// Check that there are content
$this->assertEquals(3, count($content->getBySelector('.ss-gridfield-item')));
// Make sure that there are no edit links
$this->assertEmpty($content->getBySelector('.edit-link'), 'Edit links should not show when not logged in.');
}
public function testShowEditLinksWithAdminPermission() {
$this->logInWithPermission('ADMIN');
$content = new CSSContentParser($this->gridField->FieldHolder());
$editLinks = $content->getBySelector('.edit-link');
$this->assertEquals(2, count($editLinks), 'Edit links should show when logged in.');
}
}
class GridFieldAction_Edit_Team extends DataObject implements TestOnly {
static $db = array(
'Name' => 'Varchar',
'City' => 'Varchar'
);
public function canView($member = null) {
return true;
}
}

View File

@ -10,6 +10,7 @@ class GridFieldPopupFormsTest extends FunctionalTest {
function testAddForm() {
$this->logInWithPermission('ADMIN');
$group = DataList::create('GridFieldPopupFormsTest_PeopleGroup')
->filter('Name', 'My Group')
->First();
@ -45,6 +46,7 @@ class GridFieldPopupFormsTest extends FunctionalTest {
}
function testEditForm() {
$this->logInWithPermission('ADMIN');
$group = DataList::create('GridFieldPopupFormsTest_PeopleGroup')
->filter('Name', 'My Group')
->First();

View File

@ -37,6 +37,7 @@ class GridFieldRelationAddTest extends FunctionalTest {
}
function testAdd() {
$this->logInWithPermission('ADMIN');
$team1 = $this->objFromFixture('GridFieldTest_Team', 'team1');
$team2 = $this->objFromFixture('GridFieldTest_Team', 'team2');

View File

@ -3,6 +3,7 @@ class GridFieldTitleTest extends SapphireTest {
public function testGridTitleAddNewEnabled() {
$this->logInWithPermission('ADMIN');
//construct a fake form field to render out the grid field within it
$config = new GridFieldConfig();
$config->addComponent($titleField = new GridFieldTitle());
@ -17,6 +18,7 @@ class GridFieldTitleTest extends SapphireTest {
}
public function testGridTitleAddNewDisabled() {
$this->logInWithPermission('ADMIN');
//construct a fake form field to render out the grid field within it
$config = new GridFieldConfig();
$config->addComponent($titleField = new GridFieldTitle());
@ -29,5 +31,16 @@ class GridFieldTitleTest extends SapphireTest {
$html = $form->forTemplate();
$this->assertNotContains('data-icon="add"', $html,"HTML does not contain the 'add new' button");
}
}
?>
public function testGridTitleAddNewWithoutPermission() {
if(Member::currentUser()) { Member::currentUser()->logOut(); }
$config = new GridFieldConfig();
$config->addComponent($titleField = new GridFieldTitle());
$grid = new GridField('TestField', 'Test Field', new DataList('Company'),$config);
$fields = new FieldList(new TabSet("Root",$tabMain = new Tab('Main',$grid)));
$form = new Form(Controller::curr(), "TestForm", $fields, new FieldList());
$html = $form->forTemplate();
$this->assertNotContains('data-icon="add"', $html, "HTML should not contain the 'add new' button");
}
}