From 226b8ab1836008ecf82345270cef5f05b07ed3f2 Mon Sep 17 00:00:00 2001 From: Oleg Andreyev Date: Fri, 20 Nov 2020 21:35:10 +0200 Subject: [PATCH 1/3] Don't cast form->data to array if it's not iterable --- src/Bridge/Interaction/CollectionInteractor.php | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/Bridge/Interaction/CollectionInteractor.php b/src/Bridge/Interaction/CollectionInteractor.php index 813ee6c..d79ab2b 100644 --- a/src/Bridge/Interaction/CollectionInteractor.php +++ b/src/Bridge/Interaction/CollectionInteractor.php @@ -50,12 +50,19 @@ public function interactWith( throw new CanNotInteractWithForm('Expected a "collection" form'); } - if (!$form->getConfig()->getOption('allow_add') && empty($form->getData())) { + $data = $form->getData(); + if (!$form->getConfig()->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 = []; @@ -66,7 +73,7 @@ public function interactWith( 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); From 86e82c48861e73ec49ed5b5f5feb5aecc16d047f Mon Sep 17 00:00:00 2001 From: Oleg Andreyev Date: Thu, 26 Nov 2020 21:54:01 +0200 Subject: [PATCH 2/3] added test case --- composer.json | 3 +- features/interactive.feature | 29 +++++++++++++++++ .../Interaction/CollectionInteractor.php | 12 ++++--- test/Command/PrintFormDataCommand.php | 16 ++++++---- test/Form/AddressType.php | 1 + test/Form/AddressesType.php | 31 +++++++++++++++++++ test/Model/Addresses.php | 15 +++++++++ test/config.yml | 8 +++++ 8 files changed, 103 insertions(+), 12 deletions(-) create mode 100644 test/Form/AddressesType.php create mode 100644 test/Model/Addresses.php 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 d79ab2b..e58940b 100644 --- a/src/Bridge/Interaction/CollectionInteractor.php +++ b/src/Bridge/Interaction/CollectionInteractor.php @@ -50,8 +50,10 @@ public function interactWith( throw new CanNotInteractWithForm('Expected a "collection" form'); } - $data = $form->getData(); - if (!$form->getConfig()->getOption('allow_add') && empty($data)) { + $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' ); @@ -66,7 +68,7 @@ public function interactWith( $this->printHeader($form, $output); $submittedData = []; - $prototype = $form->getConfig()->getAttribute('prototype'); + $prototype = $config->getAttribute('prototype'); $originalData = $prototype->getData(); $askIfEntryNeedsToBeSubmitted = function ($entryNumber) use ($helperSet, $input, $output) { @@ -78,12 +80,12 @@ public function interactWith( $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..3f3855c 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; 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: From 3f9f4b445af4cc56e49ac227717cdcf09967d4a7 Mon Sep 17 00:00:00 2001 From: Oleg Andreyev Date: Sat, 5 Dec 2020 20:39:11 +0200 Subject: [PATCH 3/3] fixing empty_data option --- test/Form/AddressType.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/Form/AddressType.php b/test/Form/AddressType.php index 3f3855c..c5a9d84 100644 --- a/test/Form/AddressType.php +++ b/test/Form/AddressType.php @@ -28,6 +28,9 @@ public function configureOptions(OptionsResolver $resolver) $resolver->setDefaults( [ 'data_class' => Address::class, + 'empty_data' => function () { + return new Address(''); + } ] ); }