diff --git a/src/Forms/GridField/GridFieldAddNewButton.php b/src/Forms/GridField/GridFieldAddNewButton.php index f554be101..2cc167b43 100644 --- a/src/Forms/GridField/GridFieldAddNewButton.php +++ b/src/Forms/GridField/GridFieldAddNewButton.php @@ -3,6 +3,8 @@ namespace SilverStripe\Forms\GridField; use SilverStripe\Control\Controller; +use SilverStripe\ORM\DataObject; +use SilverStripe\ORM\RelationList; use SilverStripe\View\ArrayData; use SilverStripe\View\SSViewer; @@ -35,9 +37,16 @@ class GridFieldAddNewButton implements GridField_HTMLProvider public function getHTMLFragments($gridField) { $singleton = singleton($gridField->getModelClass()); + $context = []; + if ($gridField->getList() instanceof RelationList) { + $record = $gridField->getForm()->getRecord(); + if ($record && $record instanceof DataObject) { + $context['Parent'] = $record; + } + } - if (!$singleton->canCreate()) { - return array(); + if (!$singleton->canCreate(null, $context)) { + return []; } if (!$this->buttonName) { @@ -46,14 +55,14 @@ class GridFieldAddNewButton implements GridField_HTMLProvider $this->buttonName = _t('SilverStripe\\Forms\\GridField\\GridField.Add', 'Add {name}', array('name' => $objectName)); } - $data = new ArrayData(array( + $data = new ArrayData([ 'NewLink' => Controller::join_links($gridField->Link('item'), 'new'), 'ButtonName' => $this->buttonName, - )); + ]); $templates = SSViewer::get_templates_by_class($this, '', __CLASS__); - return array( + return [ $this->targetFragment => $data->renderWith($templates), - ); + ]; } } diff --git a/src/ORM/HasManyList.php b/src/ORM/HasManyList.php index bc4f61758..df0ec55a8 100644 --- a/src/ORM/HasManyList.php +++ b/src/ORM/HasManyList.php @@ -80,11 +80,11 @@ class HasManyList extends RelationList // Validate foreignID if (!$foreignID) { - user_error("ManyManyList::add() can't be called until a foreign ID is set", E_USER_WARNING); + user_error("HasManyList::add() can't be called until a foreign ID is set", E_USER_WARNING); return; } if (is_array($foreignID)) { - user_error("ManyManyList::add() can't be called on a list linked to mulitple foreign IDs", E_USER_WARNING); + user_error("HasManyList::add() can't be called on a list linked to mulitple foreign IDs", E_USER_WARNING); return; } diff --git a/tests/php/Forms/GridField/GridFieldAddNewButtonTest.php b/tests/php/Forms/GridField/GridFieldAddNewButtonTest.php new file mode 100644 index 000000000..e538f812d --- /dev/null +++ b/tests/php/Forms/GridField/GridFieldAddNewButtonTest.php @@ -0,0 +1,124 @@ +objFromFixture(PeopleGroup::class, 'group'); + $list = $group->People(); + $this->mockSingleton(Person::class) + ->expects($this->once()) + ->method('canCreate') + ->with( + $this->anything(), + $this->callback(function ($arg) use ($group) { + return isset($arg['Parent']) && $arg['Parent']->ID == $group->ID; + }) + ); + + $this->mockButtonFragments($list, $group); + } + + public function testButtonPassesNoParentContextToSingletonWhenRelationListIsNotUsed() + { + $group = $this->objFromFixture(PeopleGroup::class, 'group'); + $this->mockSingleton(Person::class) + ->expects($this->once()) + ->method('canCreate') + ->with( + $this->anything(), + $this->callback(function ($arg) { + return !isset($arg['Parent']); + }) + ); + + $this->mockButtonFragments(Person::get(), $group); + } + + public function testButtonPassesNoParentContextToSingletonWhenNoParentRecordExists() + { + $group = $this->objFromFixture(PeopleGroup::class, 'group'); + $list = $group->People(); + + $this->mockSingleton(Person::class) + ->expects($this->once()) + ->method('canCreate') + ->with( + $this->anything(), + $this->callback(function ($arg) { + return !isset($arg['Parent']); + }) + ); + + $this->mockButtonFragments($list, null); + } + + protected function mockButtonFragments(SS_List $list, $parent = null) + { + $form = Form::create( + new TestController(), + 'test', + FieldList::create( + $fakeGrid = GridField::create( + 'dummy', + 'dummy', + $list, + new GridFieldConfig( + $button = new GridFieldAddNewButton() + ) + ) + ), + FieldList::create() + ); + if ($parent) { + $form->loadDataFrom($parent); + } + + $button->getHTMLFragments($fakeGrid); + } + + protected function mockSingleton($class) + { + $mock = $this->getMockBuilder($class) + ->setMethods(['canCreate']) + ->getMock(); + Injector::inst()->registerService($mock, $class); + + return $mock; + } +}