From 61ed3ce3c529a2f204a5d3414278ecc03ad9583d Mon Sep 17 00:00:00 2001 From: Christian Beeznest Date: Wed, 8 Jan 2025 18:32:20 -0500 Subject: [PATCH] User: Improve profile form, visibility, editability, and extra fields handling - refs BT#22325 --- .../Controller/AccountController.php | 12 ++- src/CoreBundle/Form/ExtraFieldType.php | 2 + src/CoreBundle/Form/ProfileType.php | 96 ++++++++++--------- .../Settings/ProfileSettingsSchema.php | 26 ++++- 4 files changed, 82 insertions(+), 54 deletions(-) diff --git a/src/CoreBundle/Controller/AccountController.php b/src/CoreBundle/Controller/AccountController.php index 2e922fcde3..820fe89b8a 100644 --- a/src/CoreBundle/Controller/AccountController.php +++ b/src/CoreBundle/Controller/AccountController.php @@ -53,10 +53,12 @@ class AccountController extends BaseController $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { - $illustration = $form['illustration']->getData(); - if ($illustration) { - $illustrationRepo->deleteIllustration($user); - $illustrationRepo->addIllustration($user, $user, $illustration); + if ($form->has('illustration')) { + $illustration = $form['illustration']->getData(); + if ($illustration) { + $illustrationRepo->deleteIllustration($user); + $illustrationRepo->addIllustration($user, $user, $illustration); + } } $showTermsIfProfileCompleted = ('true' === $settingsManager->getSetting('show_terms_if_profile_completed')); @@ -72,7 +74,7 @@ class AccountController extends BaseController } return $this->render('@ChamiloCore/Account/edit.html.twig', [ - 'form' => $form, + 'form' => $form->createView(), 'user' => $user, ]); } diff --git a/src/CoreBundle/Form/ExtraFieldType.php b/src/CoreBundle/Form/ExtraFieldType.php index decef3bda3..44734d1545 100644 --- a/src/CoreBundle/Form/ExtraFieldType.php +++ b/src/CoreBundle/Form/ExtraFieldType.php @@ -79,12 +79,14 @@ class ExtraFieldType extends AbstractType $variable = $extraField->getVariable(); $value = $data[$extraField->getVariable()] ?? null; + $isEditable = $extraField->isChangeable(); $defaultOptions = [ 'label' => $text, 'required' => false, 'by_reference' => false, 'mapped' => false, 'data' => $value, + 'attr' => $isEditable ? [] : ['readonly' => true, 'class' => 'readonly-field'], ]; // @todo validate data. diff --git a/src/CoreBundle/Form/ProfileType.php b/src/CoreBundle/Form/ProfileType.php index 85cbf2054e..cb99eb95f0 100644 --- a/src/CoreBundle/Form/ProfileType.php +++ b/src/CoreBundle/Form/ProfileType.php @@ -11,13 +11,10 @@ use Chamilo\CoreBundle\Form\Type\IllustrationType; use Chamilo\CoreBundle\Repository\LanguageRepository; use Chamilo\CoreBundle\Settings\SettingsManager; use Symfony\Component\Form\AbstractType; -use Symfony\Component\Form\Extension\Core\Type\BirthdayType; use Symfony\Component\Form\Extension\Core\Type\EmailType; use Symfony\Component\Form\Extension\Core\Type\LocaleType; -use Symfony\Component\Form\Extension\Core\Type\TextareaType; use Symfony\Component\Form\Extension\Core\Type\TextType; use Symfony\Component\Form\Extension\Core\Type\TimezoneType; -use Symfony\Component\Form\Extension\Core\Type\UrlType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\OptionsResolver\OptionsResolver; @@ -37,56 +34,61 @@ class ProfileType extends AbstractType public function buildForm(FormBuilderInterface $builder, array $options): void { + $changeableOptions = $this->settingsManager->getSetting('profile.changeable_options') ?? []; + $visibleOptions = $this->settingsManager->getSetting('profile.visible_options') ?? []; $languages = array_flip($this->languageRepository->getAllAvailableToArray()); - $builder - ->add('firstname', TextType::class, ['label' => 'Firstname', 'required' => true]) - ->add('lastname', TextType::class, ['label' => 'Lastname', 'required' => true]) - ->add('email', EmailType::class, ['label' => 'Email', 'required' => true]) - // ->add('official_code', TextType::class) - // ->add('groups') - ->add('locale', LocaleType::class, [ - // 'preferred_choices' => ['en', 'fr_FR', 'es_ES', 'pt', 'nl'], + $fieldsMap = [ + 'name' => ['field' => 'firstname', 'type' => TextType::class, 'label' => 'Firstname'], + 'officialcode' => ['field' => 'official_code', 'type' => TextType::class, 'label' => 'Official Code'], + 'email' => ['field' => 'email', 'type' => EmailType::class, 'label' => 'Email'], + 'picture' => [ + 'field' => 'illustration', + 'type' => IllustrationType::class, + 'label' => 'Picture', + 'mapped' => false + ], + 'login' => ['field' => 'login', 'type' => TextType::class, 'label' => 'Login'], + 'password' => ['field' => 'password', 'type' => TextType::class, 'label' => 'Password'], + 'language' => [ + 'field' => 'locale', + 'type' => LocaleType::class, + 'label' => 'Language', 'choices' => $languages, - 'choice_loader' => null, - ]) - /*->add( 'dateOfBirth', - BirthdayType::class, - [ - 'label' => 'form.label_date_of_birth', - 'required' => false, - 'widget' => 'single_text', - ] - ) - ->add( - 'biography', - TextareaType::class, - [ - 'label' => 'form.label_biography', - 'required' => false, - ] - )*/ - /*->add('locale', 'locale', array( - 'label' => 'form.label_locale', - 'required' => false, - ))*/ - ; + ], + 'phone' => ['field' => 'phone', 'type' => TextType::class, 'label' => 'Phone Number'], + 'theme' => ['field' => 'theme', 'type' => TextType::class, 'label' => 'Theme'], + ]; - if ('true' === $this->settingsManager->getSetting('use_users_timezone')) { - $builder - ->add('timezone', TimezoneType::class, ['label' => 'Timezone', 'required' => true]) - ; + foreach ($fieldsMap as $key => $fieldConfig) { + if (in_array($key, $visibleOptions)) { + $isEditable = in_array($key, $changeableOptions); + $builder->add( + $fieldConfig['field'], + $fieldConfig['type'], + array_merge( + [ + 'label' => $fieldConfig['label'], + 'required' => false, + 'attr' => !$isEditable ? ['readonly' => true] : [], + ], + isset($fieldConfig['choices']) ? ['choices' => $fieldConfig['choices']] : [] + ) + ); + } } - $builder - ->add('phone', TextType::class, ['label' => 'Phone number', 'required' => false]) - ->add( - 'illustration', - IllustrationType::class, - ['label' => 'Picture', 'required' => false, 'mapped' => false] - ) - // ->add('website', UrlType::class, ['label' => 'Website', 'required' => false]) - ; + if ('true' === $this->settingsManager->getSetting('use_users_timezone') && in_array('timezone', $visibleOptions)) { + $builder->add( + 'timezone', + TimezoneType::class, + [ + 'label' => 'Timezone', + 'required' => true, + 'attr' => !in_array('timezone', $changeableOptions) ? ['readonly' => true] : [], + ] + ); + } $builder->add('extra_fields', ExtraFieldType::class, ['mapped' => false]); } diff --git a/src/CoreBundle/Settings/ProfileSettingsSchema.php b/src/CoreBundle/Settings/ProfileSettingsSchema.php index 551a501a15..5b9bf7aa6b 100644 --- a/src/CoreBundle/Settings/ProfileSettingsSchema.php +++ b/src/CoreBundle/Settings/ProfileSettingsSchema.php @@ -59,15 +59,21 @@ class ProfileSettingsSchema extends AbstractSettingsSchema 'career_diagram_legend' => 'false', 'career_diagram_disclaimer' => 'false', 'linkedin_organization_id' => 'false', + 'visible_options' => [], ] ) ->setTransformer( 'changeable_options', new ArrayToIdentifierTransformer() ) + ->setTransformer( + 'visible_options', + new ArrayToIdentifierTransformer() + ) ; $allowedTypes = [ 'changeable_options' => ['array'], + 'visible_options' => ['array'], 'account_valid_duration' => ['string'], ]; $this->setMultipleAllowedTypes($allowedTypes, $builder); @@ -90,9 +96,25 @@ class ProfileSettingsSchema extends AbstractSettingsSchema 'Password' => 'password', 'Language' => 'language', 'Phone' => 'phone', - // 'openid' => 'openid', 'Theme' => 'theme', - // 'apikeys' => 'apikeys', + ], + ] + ) + ->add( + 'visible_options', + ChoiceType::class, + [ + 'multiple' => true, + 'choices' => [ + 'Name' => 'name', + 'Official code' => 'officialcode', + 'E-mail' => 'email', + 'Picture' => 'picture', + 'Login' => 'login', + 'Password' => 'password', + 'Language' => 'language', + 'Phone' => 'phone', + 'Theme' => 'theme', ], ] )