[Form] Made it possible to use models with only either addXxx() or removeXxx()
This commit is contained in:
parent
0914a38e74
commit
d208f4e0de
@ -70,6 +70,13 @@ class MergeCollectionListener implements EventSubscriberInterface
|
||||
public function onBindNormData(FilterDataEvent $event)
|
||||
{
|
||||
$originalData = $event->getForm()->getData();
|
||||
|
||||
// If we are not allowed to change anything, return immediately
|
||||
if (!$this->allowAdd && !$this->allowDelete) {
|
||||
$event->setData($originalData);
|
||||
return;
|
||||
}
|
||||
|
||||
$form = $event->getForm();
|
||||
$data = $event->getData();
|
||||
$parentData = $form->hasParent() ? $form->getParent()->getData() : null;
|
||||
@ -98,14 +105,27 @@ class MergeCollectionListener implements EventSubscriberInterface
|
||||
$adderName = $this->adderPrefix . $singular;
|
||||
$removerName = $this->removerPrefix . $singular;
|
||||
|
||||
if ($reflClass->hasMethod($adderName) && $reflClass->hasMethod($removerName)) {
|
||||
if ($this->allowAdd && $reflClass->hasMethod($adderName)) {
|
||||
$adder = $reflClass->getMethod($adderName);
|
||||
|
||||
if (!$adder->isPublic() || $adder->getNumberOfRequiredParameters() !== 1) {
|
||||
// False alert
|
||||
$adder = null;
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->allowDelete && $reflClass->hasMethod($removerName)) {
|
||||
$remover = $reflClass->getMethod($removerName);
|
||||
|
||||
if ($adder->isPublic() && $adder->getNumberOfRequiredParameters() === 1
|
||||
&& $remover->isPublic() && $remover->getNumberOfRequiredParameters() === 1) {
|
||||
if (!$remover->isPublic() || $remover->getNumberOfRequiredParameters() !== 1) {
|
||||
// False alert
|
||||
$remover = null;
|
||||
}
|
||||
}
|
||||
|
||||
// We found a public, one-parameter add and remove method
|
||||
// When we want to both add and delete, we look for an adder and
|
||||
// remover with the same name
|
||||
if (!($this->allowAdd && !$adder) && !($this->allowDelete && !$remover)) {
|
||||
break;
|
||||
}
|
||||
|
||||
@ -114,7 +134,6 @@ class MergeCollectionListener implements EventSubscriberInterface
|
||||
$remover = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check which items are in $data that are not in $originalData and
|
||||
// vice versa
|
||||
@ -136,15 +155,15 @@ class MergeCollectionListener implements EventSubscriberInterface
|
||||
}
|
||||
}
|
||||
|
||||
if ($adder && $remover) {
|
||||
if ($adder || $remover) {
|
||||
// If methods to add and to remove exist, call them now, if allowed
|
||||
if ($this->allowDelete) {
|
||||
if ($remover) {
|
||||
foreach ($itemsToDelete as $item) {
|
||||
$remover->invoke($parentData, $item);
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->allowAdd) {
|
||||
if ($adder) {
|
||||
foreach ($itemsToAdd as $item) {
|
||||
$adder->invoke($parentData, $item);
|
||||
}
|
||||
|
@ -31,6 +31,16 @@ class MergeCollectionListenerTest_CarCustomPrefix
|
||||
public function barAxis($axis) {}
|
||||
}
|
||||
|
||||
class MergeCollectionListenerTest_CarOnlyAdder
|
||||
{
|
||||
public function addAxis($axis) {}
|
||||
}
|
||||
|
||||
class MergeCollectionListenerTest_CarOnlyRemover
|
||||
{
|
||||
public function removeAxis($axis) {}
|
||||
}
|
||||
|
||||
abstract class MergeCollectionListenerTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
private $dispatcher;
|
||||
@ -177,7 +187,7 @@ abstract class MergeCollectionListenerTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
$newData = 'no array or traversable';
|
||||
$event = new FilterDataEvent($this->form, $newData);
|
||||
$listener = new MergeCollectionListener(false, false);
|
||||
$listener = new MergeCollectionListener(true, false);
|
||||
$listener->onBindNormData($event);
|
||||
}
|
||||
|
||||
@ -225,7 +235,7 @@ abstract class MergeCollectionListenerTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
public function testCallAdderIfAllowAdd()
|
||||
{
|
||||
$parentData = $this->getMock(__CLASS__ . '_Car');
|
||||
$parentData = $this->getMock(__CLASS__ . '_CarOnlyAdder');
|
||||
$parentForm = $this->getForm('car');
|
||||
$parentForm->setData($parentData);
|
||||
$parentForm->add($this->form);
|
||||
@ -313,7 +323,7 @@ abstract class MergeCollectionListenerTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
public function testCallRemoverIfAllowDelete()
|
||||
{
|
||||
$parentData = $this->getMock(__CLASS__ . '_Car');
|
||||
$parentData = $this->getMock(__CLASS__ . '_CarOnlyRemover');
|
||||
$parentForm = $this->getForm('car');
|
||||
$parentForm->setData($parentData);
|
||||
$parentForm->add($this->form);
|
||||
@ -399,6 +409,39 @@ abstract class MergeCollectionListenerTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertEquals($newData, $event->getData());
|
||||
}
|
||||
|
||||
public function testCallAdderAndDeleterIfAllowAll()
|
||||
{
|
||||
$parentData = $this->getMock(__CLASS__ . '_Car');
|
||||
$parentForm = $this->getForm('car');
|
||||
$parentForm->setData($parentData);
|
||||
$parentForm->add($this->form);
|
||||
|
||||
$originalDataArray = array(1 => 'second');
|
||||
$originalData = $this->getData($originalDataArray);
|
||||
$newData = $this->getData(array(0 => 'first'));
|
||||
|
||||
$this->form->setData($originalData);
|
||||
|
||||
$parentData->expects($this->once())
|
||||
->method('addAxis')
|
||||
->with('first');
|
||||
$parentData->expects($this->once())
|
||||
->method('removeAxis')
|
||||
->with('second');
|
||||
|
||||
$event = new FilterDataEvent($this->form, $newData);
|
||||
$listener = new MergeCollectionListener(true, true, true);
|
||||
$listener->onBindNormData($event);
|
||||
|
||||
if (is_object($originalData)) {
|
||||
$this->assertSame($originalData, $event->getData());
|
||||
}
|
||||
|
||||
// The data was not modified directly
|
||||
// Thus it should not be written back into the parent data!
|
||||
$this->assertEquals($this->getData($originalDataArray), $event->getData());
|
||||
}
|
||||
|
||||
public function testCallAccessorsWithCustomPrefixes()
|
||||
{
|
||||
$parentData = $this->getMock(__CLASS__ . '_CarCustomPrefix');
|
||||
|
Reference in New Issue
Block a user