diff --git a/src/EditRegistration/Type.php b/src/EditRegistration/Type.php index ef36e6f..c7940f8 100644 --- a/src/EditRegistration/Type.php +++ b/src/EditRegistration/Type.php @@ -12,6 +12,7 @@ class Type extends AbstractType use TypeHasCategoriesElementTrait; public const ELEMENT_CATEGORIES = 'categories'; + protected CategoryRepositoryInterface $categoryRepository; public function __construct(CategoryRepositoryInterface $categoryRepository) { @@ -20,7 +21,11 @@ public function __construct(CategoryRepositoryInterface $categoryRepository) public function buildForm(FormBuilderInterface $builder, array $options): void { - $this->addCategoriesElementToForm($builder, false); + $choices = $this->categoryRepository->findVisible(); + + if (\count($choices) > 1) { + $this->addCategoriesElementToForm($builder, $choices, false); + } // We need at least one element in addition to the categories above, so that Symfony recognizes the form being // submitted even if no categories where chosen. diff --git a/src/EditRegistration/TypeHasCategoriesElementTrait.php b/src/EditRegistration/TypeHasCategoriesElementTrait.php index cc061aa..4f7a204 100644 --- a/src/EditRegistration/TypeHasCategoriesElementTrait.php +++ b/src/EditRegistration/TypeHasCategoriesElementTrait.php @@ -5,20 +5,11 @@ use Symfony\Component\Form\Extension\Core\Type\ChoiceType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Validator\Constraints\Choice; -use Webfactory\NewsletterRegistrationBundle\Entity\CategoryRepositoryInterface; trait TypeHasCategoriesElementTrait { - protected CategoryRepositoryInterface $categoryRepository; - - protected function addCategoriesElementToForm(FormBuilderInterface $builder, bool $recipientHasToChooseAtLeastOne) + protected function addCategoriesElementToForm(FormBuilderInterface $builder, array $choices, bool $recipientHasToChooseAtLeastOne): void { - // add category choices, if there is more than one - $choices = $this->categoryRepository->findVisible(); - if (\count($choices) < 2) { - return; - } - $constraints = []; if (true === $recipientHasToChooseAtLeastOne) { $constraints[] = new Choice(choices: $choices, multiple: true, min: 1); diff --git a/src/StartRegistration/Type.php b/src/StartRegistration/Type.php index 4efaa33..74a40d3 100644 --- a/src/StartRegistration/Type.php +++ b/src/StartRegistration/Type.php @@ -19,6 +19,7 @@ class Type extends AbstractType public const ELEMENT_HONEYPOT = 'url'; protected PendingOptInFactoryInterface $pendingOptInFactory; + protected CategoryRepositoryInterface $categoryRepository; public function __construct(CategoryRepositoryInterface $categoryRepository, PendingOptInFactoryInterface $pendingOptInFactory) { @@ -30,7 +31,11 @@ public function buildForm(FormBuilderInterface $builder, array $options): void { $builder->add(static::ELEMENT_EMAIL_ADDRESS, EmailAddressType::class); - $this->addCategoriesElementToForm($builder, true); + $choices = $this->categoryRepository->findVisible(); + + if (\count($choices) > 1) { + $this->addCategoriesElementToForm($builder, $choices, true); + } // fake field for spam protection $builder->add(static::ELEMENT_HONEYPOT, HoneypotType::class); @@ -47,7 +52,14 @@ function (?PendingOptInInterface $pendingOptIn): array { static::ELEMENT_CATEGORIES => $pendingOptIn->getCategories(), ]; }, - function (array $formData) use ($that): ?PendingOptInInterface { + function (array $formData) use ($that, $choices): ?PendingOptInInterface { + if (!isset($formData[self::ELEMENT_CATEGORIES]) && 1 === \count($choices)) { + // if the field 'categories' is not in the form because you could choose only one anyway, we need to + // set that one category here. + $singleCategory = $choices[0]; + $formData[self::ELEMENT_CATEGORIES] = [$singleCategory]; + } + return $that->pendingOptInFactory->fromRegistrationFormData($formData); } )); diff --git a/tests/StartRegistration/TypeTest.php b/tests/StartRegistration/TypeTest.php index 02dad28..9bc6d2b 100644 --- a/tests/StartRegistration/TypeTest.php +++ b/tests/StartRegistration/TypeTest.php @@ -240,6 +240,34 @@ function (array $formData) { $this->assertEquals($pendingOptIn, $form->getData()); } + #[Test] + public function provides_PendingOptIn_with_single_category_auto_assigned_when_only_one_exists(): void + { + $this->setUpOneCategory(); + + $pendingOptIn = new PendingOptIn(null, new EmailAddress('webfactory@example.com', 'secret'), [$this->category1]); + $this->pendingOptInFactory + ->method('fromRegistrationFormData') + ->with( + $this->callback( + function (array $formData) { + return \array_key_exists(StartRegistrationType::ELEMENT_CATEGORIES, $formData) + && $formData[StartRegistrationType::ELEMENT_CATEGORIES] === [$this->category1]; + } + ) + ) + ->willReturn($pendingOptIn); + + $form = $this->factory->create(StartRegistrationType::class); + $form->submit([ + StartRegistrationType::ELEMENT_EMAIL_ADDRESS => 'webfactory@example.com', + StartRegistrationType::ELEMENT_HONEYPOT => '', + ]); + + $this->assertTrue($form->isValid()); + $this->assertEquals($pendingOptIn, $form->getData()); + } + #[Test] public function provides_PendingOptIn_if_submitted_with_valid_data_and_category_choices() {