Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion src/EditRegistration/Type.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ class Type extends AbstractType
use TypeHasCategoriesElementTrait;

public const ELEMENT_CATEGORIES = 'categories';
protected CategoryRepositoryInterface $categoryRepository;

public function __construct(CategoryRepositoryInterface $categoryRepository)
{
Expand All @@ -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.
Expand Down
11 changes: 1 addition & 10 deletions src/EditRegistration/TypeHasCategoriesElementTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
16 changes: 14 additions & 2 deletions src/StartRegistration/Type.php
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand All @@ -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);
Expand All @@ -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);
}
));
Expand Down
28 changes: 28 additions & 0 deletions tests/StartRegistration/TypeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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()
{
Expand Down
Loading