From ec34a1ddb986750fb86124371789366a559220d1 Mon Sep 17 00:00:00 2001 From: Frank Date: Sat, 4 Jul 2026 20:28:52 +0200 Subject: [PATCH] Add Terms and Conditions and marketing opt-in checkboxes to registration Registration now requires agreeing to the Terms and Conditions and lets users opt in to hear about future projects. The opt-in is persisted on the user via a new marketing_opt_in column (migration included). Co-Authored-By: Claude Sonnet 5 --- migrations/Version20260704160000.php | 26 +++++++++++++++++++ src/Tech/Entity/User.php | 15 +++++++++++ src/Tech/Form/RegistrationFormType.php | 13 ++++++++++ .../tech/registration/register.html.twig | 2 ++ 4 files changed, 56 insertions(+) create mode 100644 migrations/Version20260704160000.php diff --git a/migrations/Version20260704160000.php b/migrations/Version20260704160000.php new file mode 100644 index 0000000..03a6803 --- /dev/null +++ b/migrations/Version20260704160000.php @@ -0,0 +1,26 @@ +addSql('ALTER TABLE `user` ADD marketing_opt_in TINYINT(1) NOT NULL DEFAULT 0'); + } + + public function down(Schema $schema): void + { + $this->addSql('ALTER TABLE `user` DROP marketing_opt_in'); + } +} diff --git a/src/Tech/Entity/User.php b/src/Tech/Entity/User.php index c862ac2..7f12364 100644 --- a/src/Tech/Entity/User.php +++ b/src/Tech/Entity/User.php @@ -39,6 +39,9 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface #[ORM\Column(type: 'boolean')] private bool $isVerified = false; + #[ORM\Column(type: 'boolean')] + private bool $marketingOptIn = false; + public function getId(): ?int { return $this->id; @@ -137,4 +140,16 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface return $this; } + + public function isMarketingOptIn(): bool + { + return $this->marketingOptIn; + } + + public function setMarketingOptIn(bool $marketingOptIn): static + { + $this->marketingOptIn = $marketingOptIn; + + return $this; + } } diff --git a/src/Tech/Form/RegistrationFormType.php b/src/Tech/Form/RegistrationFormType.php index 9f24c6e..daabb19 100644 --- a/src/Tech/Form/RegistrationFormType.php +++ b/src/Tech/Form/RegistrationFormType.php @@ -6,12 +6,14 @@ use App\Tech\Entity\User; use Karser\Recaptcha3Bundle\Form\Recaptcha3Type; use Karser\Recaptcha3Bundle\Validator\Constraints\Recaptcha3; use Symfony\Component\Form\AbstractType; +use Symfony\Component\Form\Extension\Core\Type\CheckboxType; use Symfony\Component\Form\Extension\Core\Type\EmailType; use Symfony\Component\Form\Extension\Core\Type\TextType; use Symfony\Component\Form\Extension\Core\Type\PasswordType; use Symfony\Component\Form\Extension\Core\Type\RepeatedType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\OptionsResolver\OptionsResolver; +use Symfony\Component\Validator\Constraints\IsTrue; use Symfony\Component\Validator\Constraints\Length; use Symfony\Component\Validator\Constraints\NotBlank; @@ -42,6 +44,17 @@ class RegistrationFormType extends AbstractType ), ], ]) + ->add('agreeTerms', CheckboxType::class, [ + 'mapped' => false, + 'label' => 'I agree to the Terms and Conditions', + 'constraints' => [ + new IsTrue(message: 'You must agree to the Terms and Conditions.'), + ], + ]) + ->add('marketingOptIn', CheckboxType::class, [ + 'required' => false, + 'label' => 'Keep me informed about future projects and updates', + ]) ->add('captcha', Recaptcha3Type::class, [ 'constraints' => new Recaptcha3(), 'action_name' => 'registration', diff --git a/templates/tech/registration/register.html.twig b/templates/tech/registration/register.html.twig index db427e9..dec8d99 100644 --- a/templates/tech/registration/register.html.twig +++ b/templates/tech/registration/register.html.twig @@ -9,6 +9,8 @@ {{ form_row(registrationForm.email) }} {{ form_row(registrationForm.username) }} {{ form_row(registrationForm.plainPassword) }} + {{ form_row(registrationForm.agreeTerms) }} + {{ form_row(registrationForm.marketingOptIn) }} {{ form_row(registrationForm.captcha) }}