diff --git a/src/Forms/GridField/GridFieldDeleteAction.php b/src/Forms/GridField/GridFieldDeleteAction.php index a0b46ff62..51cfa6268 100644 --- a/src/Forms/GridField/GridFieldDeleteAction.php +++ b/src/Forms/GridField/GridFieldDeleteAction.php @@ -64,7 +64,9 @@ class GridFieldDeleteAction implements GridField_ColumnProvider, GridField_Actio */ public function getGroup($gridField, $record, $columnName) { - return GridField_ActionMenuItem::DEFAULT_GROUP; + $field = $this->getRemoveAction($gridField, $record, $columnName); + + return $field ? GridField_ActionMenuItem::DEFAULT_GROUP: null; } /** diff --git a/src/Forms/GridField/GridFieldGroupDeleteAction.php b/src/Forms/GridField/GridFieldGroupDeleteAction.php index 187c8f891..36721002c 100644 --- a/src/Forms/GridField/GridFieldGroupDeleteAction.php +++ b/src/Forms/GridField/GridFieldGroupDeleteAction.php @@ -41,6 +41,22 @@ class GridFieldGroupDeleteAction extends GridFieldDeleteAction return null; } + /** + * Get the ActionMenu group (not related to Member group) + * @param GridField $gridField + * @param DataObject $record + * @param $columnName + * @return null|string + */ + public function getGroup($gridField, $record, $columnName) + { + if (!$this->canUnlink($record)) { + return null; + } + + return parent::getGroup($gridField, $record, $columnName); + } + /** * Handle the actions and apply any changes to the GridField * diff --git a/src/Forms/GridField/GridField_ActionMenu.php b/src/Forms/GridField/GridField_ActionMenu.php index 5c3b07b2f..1dfff1a6d 100644 --- a/src/Forms/GridField/GridField_ActionMenu.php +++ b/src/Forms/GridField/GridField_ActionMenu.php @@ -31,15 +31,21 @@ class GridField_ActionMenu implements GridField_ColumnProvider, GridField_Action return null; } - $schema = array_map(function (GridField_ActionMenuItem $item) use ($gridField, $record, $columnName) { - return [ + $schema = []; + /* @var GridField_ActionMenuItem $item */ + foreach ($items as $item) { + $group = $item->getGroup($gridField, $record, $columnName); + if (!$group) { + continue; + } + $schema[] = [ 'type' => $item instanceof GridField_ActionMenuLink ? 'link' : 'submit', 'title' => $item->getTitle($gridField, $record, $columnName), 'url' => $item instanceof GridField_ActionMenuLink ? $item->getUrl($gridField, $record, $columnName) : null, - 'group' => $item->getGroup($gridField, $record, $columnName), + 'group' => $group, 'data' => $item->getExtraData($gridField, $record, $columnName), ]; - }, $items); + } $templateData = ArrayData::create([ 'Schema' => Convert::raw2json($schema), diff --git a/src/Forms/GridField/GridField_ActionMenuItem.php b/src/Forms/GridField/GridField_ActionMenuItem.php index a4eb9fb26..7f22cc15c 100644 --- a/src/Forms/GridField/GridField_ActionMenuItem.php +++ b/src/Forms/GridField/GridField_ActionMenuItem.php @@ -40,14 +40,15 @@ interface GridField_ActionMenuItem extends GridFieldComponent public function getExtraData($gridField, $record, $columnName); /** - * Gets the group this menu item will belong to + * Gets the group this menu item will belong to. A null value should indicate + * the button should not display. * * @see {@link GridField_ActionMenu->getColumnContent()} * * @param GridField $gridField * @param DataObject $record * - * @return string $group + * @return string|null $group */ public function getGroup($gridField, $record, $columnName); } diff --git a/tests/php/Forms/GridField/GridFieldActionMenuTest.php b/tests/php/Forms/GridField/GridFieldActionMenuTest.php index fa3c28048..d68cc8aa5 100644 --- a/tests/php/Forms/GridField/GridFieldActionMenuTest.php +++ b/tests/php/Forms/GridField/GridFieldActionMenuTest.php @@ -12,6 +12,7 @@ use SilverStripe\Forms\GridField\GridField_ActionMenu; use SilverStripe\Forms\GridField\GridFieldConfig; use SilverStripe\Forms\GridField\GridFieldEditButton; use SilverStripe\Forms\GridField\GridFieldDeleteAction; +use SilverStripe\Forms\Tests\GridField\GridFieldConfigTest\MyActionMenuItemComponent; use SilverStripe\Forms\Tests\GridField\GridFieldTest\Cheerleader; use SilverStripe\Forms\Tests\GridField\GridFieldTest\Permissions; use SilverStripe\Forms\Tests\GridField\GridFieldTest\Player; @@ -84,6 +85,42 @@ class GridFieldActionMenuTest extends SapphireTest ); } + public function testHiddenActionMenuItems() + { + $config = GridFieldConfig::create() + ->addComponent(new MyActionMenuItemComponent(true)) + ->addComponent(new GridFieldDeleteAction()) + ->addComponent($menu = new GridField_ActionMenu()); + $this->gridField->setConfig($config); + + $html = $menu->getColumnContent($this->gridField, new Team(), 'test'); + $content = new CSSContentParser($html); + /* @var \SimpleXMLElement $node */ + $node = $content->getBySelector('.gridfield-actionmenu__container'); + $this->assertNotNull($node); + $this->assertCount(1, $node); + $schema = (string) $node[0]->attributes()['data-schema']; + $json = json_decode($schema, true); + $this->assertCount(2, $json); + + // Now set the component to not display + $config = GridFieldConfig::create() + ->addComponent(new MyActionMenuItemComponent(false)) + ->addComponent(new GridFieldDeleteAction()) + ->addComponent($menu = new GridField_ActionMenu()); + $this->gridField->setConfig($config); + + $html = $menu->getColumnContent($this->gridField, new Team(), 'test'); + $content = new CSSContentParser($html); + /* @var \SimpleXMLElement $node */ + $node = $content->getBySelector('.gridfield-actionmenu__container'); + $this->assertNotNull($node); + $this->assertCount(1, $node); + $schema = (string) $node[0]->attributes()['data-schema']; + $json = json_decode($schema, true); + $this->assertCount(1, $json); + } + public function testShowEditLinksWithAdminPermission() { $this->logInWithPermission('ADMIN'); diff --git a/tests/php/Forms/GridField/GridFieldConfigTest/MyActionMenuItemComponent.php b/tests/php/Forms/GridField/GridFieldConfigTest/MyActionMenuItemComponent.php new file mode 100644 index 000000000..b7de4cbdc --- /dev/null +++ b/tests/php/Forms/GridField/GridFieldConfigTest/MyActionMenuItemComponent.php @@ -0,0 +1,22 @@ +shouldDisplay = $shouldDisplay; + } + + public function getGroup($gridField, $record, $columnName) + { + return $this->shouldDisplay ? GridField_ActionMenuItem::DEFAULT_GROUP : null; + } +} diff --git a/tests/php/Forms/GridField/GridFieldDeleteActionTest.php b/tests/php/Forms/GridField/GridFieldDeleteActionTest.php index dfbabf285..d9758ba37 100644 --- a/tests/php/Forms/GridField/GridFieldDeleteActionTest.php +++ b/tests/php/Forms/GridField/GridFieldDeleteActionTest.php @@ -214,4 +214,20 @@ class GridFieldDeleteActionTest extends SapphireTest $gridField->gridFieldAlterAction(array('StateID'=>$stateID), $this->form, $request); $this->assertEquals(2, $this->list->count(), 'User should be able to delete records with ADMIN permission.'); } + + public function testMenuGroup() + { + $this->logInWithPermission('ADMIN'); + + $config = GridFieldConfig::create()->addComponent($action = new GridFieldDeleteAction(true)); + $gridField = new GridField('testfield', 'testfield', $this->list, $config); + new Form(null, 'mockform', new FieldList(array($gridField)), new FieldList()); + $group = $action->getGroup($gridField, $this->list->first(), 'dummy'); + $this->assertNotNull($group, 'A menu group exists when the user can delete'); + + $this->logOut(); + + $group = $action->getGroup($gridField, $this->list->first(), 'dummy'); + $this->assertNull($group, 'A menu group does not exist when the user cannot delete'); + } } diff --git a/tests/php/Forms/GridField/GridFieldGroupDeleteActionTest.php b/tests/php/Forms/GridField/GridFieldGroupDeleteActionTest.php new file mode 100644 index 000000000..5e445eba4 --- /dev/null +++ b/tests/php/Forms/GridField/GridFieldGroupDeleteActionTest.php @@ -0,0 +1,45 @@ +objFromFixture(Group::class, 'admingroup'); + /* @var Group $othergroup*/ + $othergroup = $this->objFromFixture(Group::class, 'otheradmingroup'); + + /* @var Member $member */ + $member = $this->objFromFixture(Member::class, 'admin'); + Security::setCurrentUser($member); + + $gridField = GridField::create('test'); + Form::create(null, 'dummy', FieldList::create($gridField), FieldList::create()); + + $button = new GridFieldGroupDeleteAction($group->ID); + $actionGroup = $button->getGroup($gridField, $member, 'dummy'); + $column = $button->getColumnContent($gridField, $member, 'dummy'); + $this->assertNotNull($actionGroup, 'The unlink action has a menu group if the member has another admin group'); + $this->assertNotNull($column, 'The unlink action has a column content if the member has another admin group'); + + $member->Groups()->remove($othergroup); + + $actionGroup = $button->getGroup($gridField, $member, 'dummy'); + $column = $button->getColumnContent($gridField, $member, 'dummy'); + $this->assertNull($actionGroup, 'The unlink action has no menu group if the member has no other admin group'); + $this->assertNull($column, 'The unlink action has no column content if the member has no other admin group'); + } +} diff --git a/tests/php/Forms/GridField/GridFieldGroupDeleteActionTest.yml b/tests/php/Forms/GridField/GridFieldGroupDeleteActionTest.yml new file mode 100644 index 000000000..b87a1c99b --- /dev/null +++ b/tests/php/Forms/GridField/GridFieldGroupDeleteActionTest.yml @@ -0,0 +1,18 @@ +'SilverStripe\Security\Group': + admingroup: + Code: admingroup + otheradmingroup: + Code: otheradmingroup +SilverStripe\Security\Member: + admin: + FirstName: Admin + Groups: + - '=>SilverStripe\Security\Group.admingroup' + - '=>SilverStripe\Security\Group.otheradmingroup' +'SilverStripe\Security\Permission': + admincode: + Code: ADMIN + Group: '=>SilverStripe\Security\Group.admingroup' + otheradmincode: + Code: ADMIN + Group: '=>SilverStripe\Security\Group.otheradmingroup' \ No newline at end of file