diff --git a/composer.json b/composer.json index 4c064d1..c5f4a06 100644 --- a/composer.json +++ b/composer.json @@ -37,6 +37,7 @@ "symfony/validator": "~5.0", "symfony/yaml": "~5.0", "symfony/security-csrf": "~5.0", - "phpunit/phpunit": "^7" + "phpunit/phpunit": "^7", + "doctrine/collections": "^1.6" } } diff --git a/features/interactive.feature b/features/interactive.feature index 688f2ec..42bd9bd 100644 --- a/features/interactive.feature +++ b/features/interactive.feature @@ -202,6 +202,35 @@ Feature: It is possible to interactively fill in a form from the CLI [name] => Jelmer """ + Scenario: Form Type with ArrayCollection + When I run the command "form:array_collection_form_addresses" and I provide as input + | Input | + | y | + | foo | + | y | + | bar | + | n | + And the output should contain + """ + Matthias\SymfonyConsoleForm\Tests\Model\Addresses Object + ( + [addresses] => Doctrine\Common\Collections\ArrayCollection Object + ( + [elements:Doctrine\Common\Collections\ArrayCollection:private] => Array + ( + [0] => Matthias\SymfonyConsoleForm\Tests\Form\Data\Address Object + ( + [street] => foo + ) + [1] => Matthias\SymfonyConsoleForm\Tests\Form\Data\Address Object + ( + [street] => bar + ) + ) + ) + ) + """ + Scenario: Remove an address from pre filled collection of blocked addresses When I run the command "form:blocked_addresses" and I provide as input | Input | diff --git a/src/Bridge/Interaction/CollectionInteractor.php b/src/Bridge/Interaction/CollectionInteractor.php index 813ee6c..e58940b 100644 --- a/src/Bridge/Interaction/CollectionInteractor.php +++ b/src/Bridge/Interaction/CollectionInteractor.php @@ -50,33 +50,42 @@ public function interactWith( throw new CanNotInteractWithForm('Expected a "collection" form'); } - if (!$form->getConfig()->getOption('allow_add') && empty($form->getData())) { + $config = $form->getConfig(); + $data = $form->getData() ?: $config->getEmptyData(); + + if (!$config->getOption('allow_add') && empty($data)) { throw new FormNotReadyForInteraction( 'The "collection" form should have the option "allow_add" or have existing entries' ); } + if (!is_iterable($data)) { + throw new FormNotReadyForInteraction( + 'The "collection" form must be iterable' + ); + } + $this->printHeader($form, $output); $submittedData = []; - $prototype = $form->getConfig()->getAttribute('prototype'); + $prototype = $config->getAttribute('prototype'); $originalData = $prototype->getData(); $askIfEntryNeedsToBeSubmitted = function ($entryNumber) use ($helperSet, $input, $output) { return $this->askIfExistingEntryShouldBeAdded($helperSet, $input, $output, $entryNumber); }; - foreach ((array) $form->getData() as $key => $entryData) { + foreach ($data as $key => $entryData) { $this->printEditEntryHeader($key, $output); $prototype->setData($entryData); $submittedEntry = $this->formInteractor->interactWith($prototype, $helperSet, $input, $output); - if (!$form->getConfig()->getOption('allow_delete') || $askIfEntryNeedsToBeSubmitted($key)) { + if (!$config->getOption('allow_delete') || $askIfEntryNeedsToBeSubmitted($key)) { $submittedData[] = $submittedEntry; } } - if ($form->getConfig()->getOption('allow_add')) { + if ($config->getOption('allow_add')) { // reset the prototype $prototype->setData($originalData); $key = count($submittedData) - 1; diff --git a/test/Command/PrintFormDataCommand.php b/test/Command/PrintFormDataCommand.php index cc197ce..13efed9 100644 --- a/test/Command/PrintFormDataCommand.php +++ b/test/Command/PrintFormDataCommand.php @@ -12,13 +12,17 @@ protected function execute(InputInterface $input, OutputInterface $output): int { $formData = $this->formData(); - $printData = array_map(function ($data) { - if ($data instanceof \DateTime) { - return $data->format(\DateTime::ISO8601); - } + if (is_iterable($formData)) { + $printData = array_map(function ($data) { + if ($data instanceof \DateTime) { + return $data->format(\DateTime::ISO8601); + } - return $data; - }, (array)$formData); + return $data; + }, (array)$formData); + } else { + $printData = $formData; + } $output->write(print_r($printData, true)); diff --git a/test/Form/AddressType.php b/test/Form/AddressType.php index da5f16e..c5a9d84 100644 --- a/test/Form/AddressType.php +++ b/test/Form/AddressType.php @@ -5,6 +5,7 @@ use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\Extension\Core\Type\TextType; use Symfony\Component\Form\FormBuilderInterface; +use Symfony\Component\Form\FormInterface; use Symfony\Component\OptionsResolver\OptionsResolver; use Matthias\SymfonyConsoleForm\Tests\Form\Data\Address; @@ -27,6 +28,9 @@ public function configureOptions(OptionsResolver $resolver) $resolver->setDefaults( [ 'data_class' => Address::class, + 'empty_data' => function () { + return new Address(''); + } ] ); } diff --git a/test/Form/AddressesType.php b/test/Form/AddressesType.php new file mode 100644 index 0000000..ac25997 --- /dev/null +++ b/test/Form/AddressesType.php @@ -0,0 +1,31 @@ +add( + 'addresses', + CollectionType::class, + [ + 'entry_type' => AddressType::class, + 'allow_add' => true, + 'empty_data' => new ArrayCollection() + ] + ); + } + + public function configureOptions(OptionsResolver $resolver) + { + $resolver->setDefault('data_class', Addresses::class); + } +} diff --git a/test/Model/Addresses.php b/test/Model/Addresses.php new file mode 100644 index 0000000..290999f --- /dev/null +++ b/test/Model/Addresses.php @@ -0,0 +1,15 @@ +addresses = new ArrayCollection(); + } +} diff --git a/test/config.yml b/test/config.yml index 264324b..90cf1c3 100644 --- a/test/config.yml +++ b/test/config.yml @@ -34,6 +34,14 @@ services: tags: - { name: console.command } + array_collection_form_addresses: + class: Matthias\SymfonyConsoleForm\Tests\Command\PrintFormDataCommand + arguments: + - Matthias\SymfonyConsoleForm\Tests\Form\AddressesType + - array_collection_form_addresses + tags: + - { name: console.command } + blocked_addresses_command: class: Matthias\SymfonyConsoleForm\Tests\Command\PrintFormDataCommand arguments: