ENHANCEMENT GridField passes in context for canCreate

This commit is contained in:
Aaron Carlino 2017-05-09 09:15:09 +12:00 committed by Damian Mooyman
parent c99ed2d262
commit afd1575267
3 changed files with 141 additions and 8 deletions

View File

@ -3,6 +3,8 @@
namespace SilverStripe\Forms\GridField; namespace SilverStripe\Forms\GridField;
use SilverStripe\Control\Controller; use SilverStripe\Control\Controller;
use SilverStripe\ORM\DataObject;
use SilverStripe\ORM\RelationList;
use SilverStripe\View\ArrayData; use SilverStripe\View\ArrayData;
use SilverStripe\View\SSViewer; use SilverStripe\View\SSViewer;
@ -35,9 +37,16 @@ class GridFieldAddNewButton implements GridField_HTMLProvider
public function getHTMLFragments($gridField) public function getHTMLFragments($gridField)
{ {
$singleton = singleton($gridField->getModelClass()); $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()) { if (!$singleton->canCreate(null, $context)) {
return array(); return [];
} }
if (!$this->buttonName) { 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)); $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'), 'NewLink' => Controller::join_links($gridField->Link('item'), 'new'),
'ButtonName' => $this->buttonName, 'ButtonName' => $this->buttonName,
)); ]);
$templates = SSViewer::get_templates_by_class($this, '', __CLASS__); $templates = SSViewer::get_templates_by_class($this, '', __CLASS__);
return array( return [
$this->targetFragment => $data->renderWith($templates), $this->targetFragment => $data->renderWith($templates),
); ];
} }
} }

View File

@ -80,11 +80,11 @@ class HasManyList extends RelationList
// Validate foreignID // Validate foreignID
if (!$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; return;
} }
if (is_array($foreignID)) { 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; return;
} }

View File

@ -0,0 +1,124 @@
<?php
namespace SilverStripe\Forms\Tests\GridField;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\Dev\SapphireTest;
use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\Form;
use SilverStripe\Forms\GridField\GridField;
use SilverStripe\Forms\GridField\GridFieldAddNewButton;
use SilverStripe\Forms\GridField\GridFieldConfig;
use SilverStripe\Forms\Tests\GridField\GridFieldDetailFormTest\Person;
use SilverStripe\Forms\Tests\GridField\GridFieldDetailFormTest\PeopleGroup;
use SilverStripe\Forms\Tests\GridField\GridFieldDetailFormTest\Category;
use SilverStripe\Forms\Tests\GridField\GridFieldDetailFormTest\TestController;
use SilverStripe\ORM\SS_List;
class GridFieldAddNewButtonTest extends SapphireTest
{
protected static $fixture_file = 'GridFieldDetailFormTest.yml';
protected static $extra_dataobjects = [
Person::class,
PeopleGroup::class,
Category::class,
];
public function setUp()
{
parent::setUp();
Injector::nest();
}
public function tearDown()
{
parent::tearDown();
Injector::unnest();
}
public function testButtonPassesParentContextToSingletonWhenRelationListIsUsed()
{
$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) 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;
}
}