From e6ace1d40fd6a8faba3880dd7dec72cc63931de0 Mon Sep 17 00:00:00 2001 From: Maxiloud <61539540+maxime-urbanski@users.noreply.github.com> Date: Wed, 22 Oct 2025 16:14:23 +0200 Subject: [PATCH] Feat/optimisation user account (#773) * removed place registration on front page * phone field is mandatory * added address verification on a product demand * fix test --- fixtures/test/user.yaml | 2 +- .../Admin/AbstractUserCrudController.php | 2 +- .../Security/AccountCreateController.php | 2 + .../Security/AccountCreateStep2FormType.php | 43 ++++----------- src/Form/Type/User/EditProfileFormType.php | 3 +- .../Security/AccountCreateStep2Command.php | 4 ++ .../AccountCreateStep2CommandHandler.php | 7 +++ .../components/product/_calendar.html.twig | 39 +++++++++----- templates/components/product/_modal.html.twig | 13 +++-- templates/pages/register/step2.html.twig | 9 ++-- .../AccountCreateActionStep2PlaceTest.php | 53 ------------------- ...untCreateActionStep2UserInvitationTest.php | 3 +- .../AccountCreateActionStep2UserTest.php | 3 +- .../Integration/Doctrine/UserManagerTest.php | 1 + .../AccountCreateStep2CommandHandlerTest.php | 7 +++ .../Repository/UserRepositoryTest.php | 1 + .../security/account_create/security.fr.xlf | 5 ++ .../pages/account/index/messages.fr.xlf | 2 +- 18 files changed, 87 insertions(+), 112 deletions(-) delete mode 100644 tests/Functional/Controller/Security/AccountCreateActionStep2PlaceTest.php diff --git a/fixtures/test/user.yaml b/fixtures/test/user.yaml index ea3b449..0ea60d5 100644 --- a/fixtures/test/user.yaml +++ b/fixtures/test/user.yaml @@ -88,7 +88,6 @@ App\Entity\User: name: 'APES compte lieu' address: '@address_region_hauts_de_france' schedule: '9h30 - 17h30' - phoneNumber: null createdAt: # —— Users ————————————————————————————————————————————————————————————————— @@ -170,6 +169,7 @@ App\Entity\User: firstname: lastname: address: null + phoneNumber: '+33600000000' avatar: 'a9a9bf49-24e4-4b3e-bdbd-86808c32939e.jpg' # user with an address and a preferred category set diff --git a/src/Controller/Admin/AbstractUserCrudController.php b/src/Controller/Admin/AbstractUserCrudController.php index 4fa5f6e..26f7c2f 100755 --- a/src/Controller/Admin/AbstractUserCrudController.php +++ b/src/Controller/Admin/AbstractUserCrudController.php @@ -342,7 +342,7 @@ abstract class AbstractUserCrudController extends AbstractCrudController impleme ->setFormType(PhoneNumberType::class) ->setFormTypeOptions([ 'format' => PhoneNumberFormat::INTERNATIONAL, - 'required' => false, + 'required' => true, ]) ->setHelp($i18prefix.'.field.phone.help') ; diff --git a/src/Controller/Security/AccountCreateController.php b/src/Controller/Security/AccountCreateController.php index 966f362..371708a 100644 --- a/src/Controller/Security/AccountCreateController.php +++ b/src/Controller/Security/AccountCreateController.php @@ -8,6 +8,7 @@ use App\Controller\FlashTrait; use App\Controller\i18nTrait; use App\Controller\User\MyAccountAction; use App\Entity\User; +use App\Enum\User\UserType; use App\Exception\UserConfirmationTokenExpiredException; use App\Exception\UserNotFoundException; use App\Form\Type\Security\AccountCreateStep1FormType; @@ -105,6 +106,7 @@ final class AccountCreateController extends AbstractController if ($form->isSubmitted() && $form->isValid()) { /** @var User $user */ $user = $form->getData(); + $user->setType(UserType::USER); $this->commandBus->dispatch(new AccountCreateStep2Command($user)); $this->security->login($user); // auto-log the user diff --git a/src/Form/Type/Security/AccountCreateStep2FormType.php b/src/Form/Type/Security/AccountCreateStep2FormType.php index 94e677b..0ed465c 100755 --- a/src/Form/Type/Security/AccountCreateStep2FormType.php +++ b/src/Form/Type/Security/AccountCreateStep2FormType.php @@ -5,11 +5,10 @@ declare(strict_types=1); namespace App\Form\Type\Security; use App\Entity\User; -use App\Enum\User\UserType; +use libphonenumber\PhoneNumberFormat; +use Misd\PhoneNumberBundle\Form\Type\PhoneNumberType; use Symfony\Component\Form\AbstractType; -use Symfony\Component\Form\CallbackTransformer; use Symfony\Component\Form\Extension\Core\Type\CheckboxType; -use Symfony\Component\Form\Extension\Core\Type\ChoiceType; use Symfony\Component\Form\Extension\Core\Type\PasswordType; use Symfony\Component\Form\Extension\Core\Type\RepeatedType; use Symfony\Component\Form\Extension\Core\Type\SubmitType; @@ -27,19 +26,6 @@ final class AccountCreateStep2FormType extends AbstractType public function buildForm(FormBuilderInterface $builder, array $options): void { $builder - ->add('type', ChoiceType::class, [ - 'label' => 'account_create_action.account_type', - 'label_attr' => ['class' => 'text-black fw-light'], - 'choices' => UserType::getForFront(), - 'choice_attr' => function () { - return [ - 'data-controller' => 'account', - 'data-action' => 'click->account#choosenType', - ]; - }, - 'expanded' => true, - ]) - ->add('firstname', TextType::class, [ 'label' => 'account_create_action.firsname', 'label_attr' => ['class' => 'text-black fw-light required'], @@ -60,14 +46,14 @@ final class AccountCreateStep2FormType extends AbstractType 'required' => false, ]) - ->add('name', TextType::class, [ - 'label' => 'account_create_action.name', - 'label_attr' => ['class' => 'text-black fw-light required'], - 'attr' => [ - 'class' => 'form-control-sm input-name', - 'placeholder' => 'account_create_action.name.placeholder', - ], - 'required' => false, + ->add('phone', PhoneNumberType::class, [ + 'label' => 'account_create_action.phone', + 'label_attr' => ['class' => 'text-black fs-6 fw-normal'], + 'widget' => PhoneNumberType::WIDGET_COUNTRY_CHOICE, + 'format' => PhoneNumberFormat::INTERNATIONAL, + 'country_display_emoji_flag' => true, + 'preferred_country_choices' => ['FR'], + 'required' => true, ]) ->add('plainPassword', RepeatedType::class, [ @@ -118,15 +104,6 @@ final class AccountCreateStep2FormType extends AbstractType 'attr' => ['class' => 'btn btn-primary btn-sm'], ]) ; - - $builder->get('type')->addModelTransformer(new CallbackTransformer( - function (?UserType $enumToString) { - return $enumToString === null ? '' : $enumToString->value; - }, - function (string $stringToEnum) { - return UserType::from($stringToEnum); - } - )); } public function configureOptions(OptionsResolver $resolver): void diff --git a/src/Form/Type/User/EditProfileFormType.php b/src/Form/Type/User/EditProfileFormType.php index 6e5ee39..8009ddf 100644 --- a/src/Form/Type/User/EditProfileFormType.php +++ b/src/Form/Type/User/EditProfileFormType.php @@ -50,8 +50,9 @@ final class EditProfileFormType extends AbstractType 'label_attr' => ['class' => 'text-black fs-6 fw-normal'], 'format' => PhoneNumberFormat::INTERNATIONAL, 'widget' => PhoneNumberType::WIDGET_COUNTRY_CHOICE, + 'country_display_emoji_flag' => true, 'preferred_country_choices' => ['FR'], - 'required' => false, + 'required' => true, ]) ->add('smsNotifications', CheckboxType::class, [ diff --git a/src/Message/Command/Security/AccountCreateStep2Command.php b/src/Message/Command/Security/AccountCreateStep2Command.php index e3fb6dd..f666698 100755 --- a/src/Message/Command/Security/AccountCreateStep2Command.php +++ b/src/Message/Command/Security/AccountCreateStep2Command.php @@ -7,6 +7,7 @@ namespace App\Message\Command\Security; use App\Entity\User; use App\Enum\User\UserType; use App\MessageHandler\Command\Security\AccountCreateStep2CommandHandler; +use libphonenumber\PhoneNumber; use Symfony\Component\Uid\Uuid; use Webmozart\Assert\Assert; @@ -22,6 +23,7 @@ final class AccountCreateStep2Command public ?string $firstname = null; public ?string $name = null; public string $plainPassword; + public PhoneNumber $phone; public function __construct(User $user) { @@ -33,5 +35,7 @@ final class AccountCreateStep2Command $this->name = $user->getName(); Assert::stringNotEmpty($user->getPlainPassword()); $this->plainPassword = $user->getPlainPassword(); + Assert::notNull($user->phone); + $this->phone = $user->phone; } } diff --git a/src/MessageHandler/Command/Security/AccountCreateStep2CommandHandler.php b/src/MessageHandler/Command/Security/AccountCreateStep2CommandHandler.php index 564df19..e3c199f 100644 --- a/src/MessageHandler/Command/Security/AccountCreateStep2CommandHandler.php +++ b/src/MessageHandler/Command/Security/AccountCreateStep2CommandHandler.php @@ -9,6 +9,8 @@ use App\Entity\User; use App\Enum\User\UserType; use App\Message\Command\Security\AccountCreateStep2Command; use App\Repository\UserRepository; +use libphonenumber\PhoneNumberFormat; +use libphonenumber\PhoneNumberUtil; use Symfony\Component\Messenger\Attribute\AsMessageHandler; use Webmozart\Assert\Assert; @@ -47,6 +49,11 @@ final class AccountCreateStep2CommandHandler throw new \UnexpectedValueException('This hanlder can only create users or places.'); } + $phoneObjectToString = PhoneNumberUtil::getInstance()->format( + $message->phone, + PhoneNumberFormat::E164 + ); + $user->setPhoneNumber($phoneObjectToString); $this->userManager->updatePassword($user->setPlainPassword($message->plainPassword)); $this->userManager->finalizeAccountCreateStep2($user); $this->userManager->save($user, true); diff --git a/templates/components/product/_calendar.html.twig b/templates/components/product/_calendar.html.twig index cd07aeb..30776e0 100644 --- a/templates/components/product/_calendar.html.twig +++ b/templates/components/product/_calendar.html.twig @@ -1,6 +1,7 @@ {% set is_product_owner = product.owner == app.user %} -
+
{{ title }}
@@ -71,22 +72,36 @@
{% endif %}
-
- {% if actionNeeded %} + {% if actionNeeded %}
{% if app.user is null or is_granted('borrow', product) %} - + {% if app.user and app.user.address is null %} + {% include 'components/product/_modal.html.twig' with { + menu_action: false, + page_type: 'article', + button: 'templates.components.product.calendar.service_request'|trans, + title: 'templates.pages.account.index.no-address-title'|trans, + message: 'templates.pages.account.index.no-address-message'|trans({ + '%product%': product.type.isObject ? 'objet' : 'service' + }), + action: 'templates.pages.account.product.list.no-address-add'|trans + } %} + {% else %} + + {% endif %} {% else %} {{ form_widget(form.submit) }} {% endif %} diff --git a/templates/components/product/_modal.html.twig b/templates/components/product/_modal.html.twig index 59cc0b5..af89057 100644 --- a/templates/components/product/_modal.html.twig +++ b/templates/components/product/_modal.html.twig @@ -1,7 +1,14 @@ {% if menu_action is defined and menu_action == true %} {{ button }} + data-bs-toggle="modal" + data-bs-target="#modalAddAddress">{{ button }} +{% elseif menu_action is defined and menu_action == false and page_type == 'article' %} + {% else %}
diff --git a/templates/pages/register/step2.html.twig b/templates/pages/register/step2.html.twig index 3f0e1db..f6851bf 100644 --- a/templates/pages/register/step2.html.twig +++ b/templates/pages/register/step2.html.twig @@ -31,7 +31,6 @@ {{ form_start(form, {attr: {novalidate: true}}) }} - {{ form_row(form.type) }}
{{ form_label(form.firstname) }} {{ form_widget(form.firstname) }} @@ -40,10 +39,10 @@ {{ form_widget(form.lastname) }} {{ form_errors(form.lastname) }}
-
- {{ form_label(form.name) }} - {{ form_widget(form.name) }} - {{ form_errors(form.name) }} +
+ {{ form_label(form.phone) }} + {{ form_widget(form.phone) }} + {{ form_errors(form.phone) }}
{% include 'components/form/_password_visibility.html.twig' with { diff --git a/tests/Functional/Controller/Security/AccountCreateActionStep2PlaceTest.php b/tests/Functional/Controller/Security/AccountCreateActionStep2PlaceTest.php deleted file mode 100644 index 1988ca5..0000000 --- a/tests/Functional/Controller/Security/AccountCreateActionStep2PlaceTest.php +++ /dev/null @@ -1,53 +0,0 @@ -request('GET', self::ROUTE.TestReference::USER_13_CONFIRMATION_TOKEN); - self::assertResponseRedirects(); - $client->followRedirect(); - self::assertResponseIsSuccessful(); - self::assertSelectorTextContains('body', 'app.controller.security.account_create_controller.step2.user_confirmation_token_expired.warning'); - } - - public function testFormSubmitPlaceSuccess(): void - { - $client = self::createClient(); - $crawler = $client->request('GET', self::ROUTE.TestReference::USER_12_CONFIRMATION_TOKEN); - $form = $crawler->selectButton('account_create_step2_form_submit')->form(); - - $password = ByteString::fromRandom(13); - $client->submit($form, [ - $form->getName().'[type]' => 'place', - $form->getName().'[name]' => 'My Association', - $form->getName().'[plainPassword][first]' => $password, - $form->getName().'[plainPassword][second]' => $password, - $form->getName().'[gdpr]' => 1, - ]); - self::assertResponseRedirects(); - $client->followRedirect(); - self::assertResponseIsSuccessful(); - } -} diff --git a/tests/Functional/Controller/Security/AccountCreateActionStep2UserInvitationTest.php b/tests/Functional/Controller/Security/AccountCreateActionStep2UserInvitationTest.php index 599b2b7..1b18bff 100644 --- a/tests/Functional/Controller/Security/AccountCreateActionStep2UserInvitationTest.php +++ b/tests/Functional/Controller/Security/AccountCreateActionStep2UserInvitationTest.php @@ -33,11 +33,12 @@ final class AccountCreateActionStep2UserInvitationTest extends WebTestCase $password = ByteString::fromRandom(13); $client->submit($form, [ - $form->getName().'[type]' => 'user', $form->getName().'[firstname]' => 'Foo', $form->getName().'[lastname]' => 'Bar', $form->getName().'[plainPassword][first]' => $password, $form->getName().'[plainPassword][second]' => $password, + $form->getName().'[phone][country]' => 'FR', + $form->getName().'[phone][number]' => '602030405', $form->getName().'[gdpr]' => 1, ]); self::assertResponseRedirects(); diff --git a/tests/Functional/Controller/Security/AccountCreateActionStep2UserTest.php b/tests/Functional/Controller/Security/AccountCreateActionStep2UserTest.php index f52c464..2683211 100644 --- a/tests/Functional/Controller/Security/AccountCreateActionStep2UserTest.php +++ b/tests/Functional/Controller/Security/AccountCreateActionStep2UserTest.php @@ -40,11 +40,12 @@ final class AccountCreateActionStep2UserTest extends WebTestCase $password = ByteString::fromRandom(13); $client->submit($form, [ - $form->getName().'[type]' => 'user', $form->getName().'[firstname]' => 'Foo', $form->getName().'[lastname]' => 'Bar', $form->getName().'[plainPassword][first]' => $password, $form->getName().'[plainPassword][second]' => $password, + $form->getName().'[phone][country]' => 'FR', + $form->getName().'[phone][number]' => '602030405', $form->getName().'[gdpr]' => 1, ]); self::assertResponseRedirects(); diff --git a/tests/Integration/Doctrine/UserManagerTest.php b/tests/Integration/Doctrine/UserManagerTest.php index 86cb1ee..2666b7e 100644 --- a/tests/Integration/Doctrine/UserManagerTest.php +++ b/tests/Integration/Doctrine/UserManagerTest.php @@ -26,6 +26,7 @@ final class UserManagerTest extends KernelTestCase $user = new User(); $user->setEmail(ByteString::fromRandom(6)->toString().'@example.com'); + $user->setPhoneNumber('+33600000000'); $user->setPassword('foo'); $userManager->save($user, true); diff --git a/tests/Integration/MessageHandler/Security/AccountCreateStep2CommandHandlerTest.php b/tests/Integration/MessageHandler/Security/AccountCreateStep2CommandHandlerTest.php index eca8563..f255cee 100644 --- a/tests/Integration/MessageHandler/Security/AccountCreateStep2CommandHandlerTest.php +++ b/tests/Integration/MessageHandler/Security/AccountCreateStep2CommandHandlerTest.php @@ -10,6 +10,7 @@ use App\Message\Command\Security\AccountCreateStep2Command; use App\MessageHandler\Command\Security\AccountCreateStep2CommandHandler; use App\Tests\TestReference; use Hautelook\AliceBundle\PhpUnit\RefreshDatabaseTrait; +use libphonenumber\PhoneNumberUtil; use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; use Symfony\Component\Uid\Uuid; @@ -25,11 +26,17 @@ final class AccountCreateStep2CommandHandlerTest extends KernelTestCase $this->expectException(\UnexpectedValueException::class); $this->expectExceptionMessage('This hanlder can only create users or places'); + $user = (new User()) ->setId(Uuid::fromString(TestReference::USER_17)) ->setType(UserType::ADMIN) ->setPlainPassword('foo') ; + + $phoneUtil = PhoneNumberUtil::getInstance(); + $phone = $phoneUtil->parse('+33602030405', 'FR'); + $user->phone = $phone; + $message = new AccountCreateStep2Command($user); $handler($message); } diff --git a/tests/Integration/Repository/UserRepositoryTest.php b/tests/Integration/Repository/UserRepositoryTest.php index 841e347..ecf5e43 100644 --- a/tests/Integration/Repository/UserRepositoryTest.php +++ b/tests/Integration/Repository/UserRepositoryTest.php @@ -30,6 +30,7 @@ final class UserRepositoryTest extends KernelTestCase $user = new User(); $user->setEmail(ByteString::fromRandom(6)->toString().'@example.com'); + $user->setPhoneNumber('+33600000000'); $user->setPassword('foo'); $repo->save($user, true); $count = $repo->count([]); diff --git a/translations/security/account_create/security.fr.xlf b/translations/security/account_create/security.fr.xlf index 39821d5..a5ed764 100644 --- a/translations/security/account_create/security.fr.xlf +++ b/translations/security/account_create/security.fr.xlf @@ -75,6 +75,11 @@ 8 caractères minimun + + account_create_action.phone + Numéro de téléphone + + account_create_action.gdpr J’ai lu et j’accepte les Conditions Générales d'Utilisation
]]> diff --git a/translations/templates/pages/account/index/messages.fr.xlf b/translations/templates/pages/account/index/messages.fr.xlf index cafb149..da0aa22 100644 --- a/translations/templates/pages/account/index/messages.fr.xlf +++ b/translations/templates/pages/account/index/messages.fr.xlf @@ -74,7 +74,7 @@ templates.pages.account.index.no-address-message - Pour pouvoir créer un %product%, commencez par remplir votre adresse. + Pour pouvoir créer ou emprunter un %product%, commencez par remplir votre adresse.