Right now the profile form shown during registration hardcoded in profile_form_user_register_form_alter().

Nowadays Profile module provides a computed field on the user for each profile type, and uses that to render profiles on the various user pages. We should follow the same approach for user forms, by moving the profile_form_user_register_form_alter() logic to a field widget.

This has multiple benefits:
- You can re-arrange the profile forms on the user's "Manage Form Display" page.
- You can manage profiles on other user form modes as well.

CommentFileSizeAuthor
#50 interdiff_49-50.txt1004 bytesjsacksick
#50 2750059-50-register-widget.patch24.2 KBjsacksick
#49 interdiff_48-49.txt537 bytesjsacksick
#49 2750059-49-register-widget.patch23.94 KBjsacksick
#48 interdiff_47-48.txt21.75 KBjsacksick
#48 2750059-48-register-widget.patch23.98 KBjsacksick
#47 2750059-47-register-widget.patch23.53 KBbojanz
#46 interdiff_45-46.txt1 KBjsacksick
#46 2750059-46-register-widget.patch24.96 KBjsacksick
#45 interdiff_44-45.txt8.18 KBjsacksick
#45 2750059-45-register-widget.patch25.23 KBjsacksick
#44 2750059-44-register-widget.patch23.01 KBbojanz
#42 profile_2750059-41.patch23.48 KBjsacksick
#40 interdiff_38-39.txt4.84 KBjsacksick
#39 profile_2750059-39.patch22.06 KBjsacksick
#38 interdiff_36-38.txt3.33 KBjsacksick
#38 profile_2750059-38.patch20.29 KBjsacksick
#36 interdiff_34-36.txt4.89 KBjsacksick
#36 profile_2750059-36.patch18.64 KBjsacksick
#34 profile_2750059-34.patch17.74 KBjsacksick
#24 profile-2750059-24-manage_form_display.patch3.29 KBsimon georges
#21 profile_manage_form_display-2750059-21.patch3.27 KBimclean
#19 profile-2750059-19-manage-form-display.patch2.33 KBgeek-merlin
#17 profile-2750059-17-manage-form-display.patch4.61 KBgeek-merlin
#15 profile-2750059-15-manage-form-display.patch2.75 KBgeek-merlin
#13 profile-2750059-13-manage-form-display.patch3.33 KBgeek-merlin
#10 user_edit_form-2750059-10.patch1.31 KBmaaty388
#9 user_edit_form-2750059-9.patch1.54 KBmichiellucas
#6 profile_fields_to_appear_on_account_form-2750059-8.x-1.x-dev.patch1.61 KBguttenbergovitz
#3 updated file- profile.module.zip1.58 KBabhaysaraf
updated- profile.module.zip1.61 KBabhaysaraf

Comments

abhaysaraf created an issue. See original summary.

nedjo’s picture

Title: Patch: Profile fields to appear on MANAGE FORM of ACCOUNT SETTINGS » Profile fields to appear on manage form of account settings
Priority: Major » Normal
Status: Needs review » Needs work

Thanks for submitting your suggestion.

Please see documentation on patches for how to produce a patch file in unified diff format. If you give your file a .patch extension, you'll be able to attach it in a form that's much easier to review.

Also, it helps a lot if you provide details about what issue you're addressing and exactly why you're proposing the specific changes. See the issue summary template.

Some quick comments:

	-   $weight = 90;
+   //Abhay: Commented all $weight variable present in this function
	+   //$weight = 90;

No need to put your user name here. If something isn't needed you should simply delete it in a patch rather than commenting out. But presumably there's a reason for the weighting, so if you're removing it it's important to explain why (in the issue summary).

Again, thanks for contributing!

abhaysaraf’s picture

Issue summary: View changes
StatusFileSize
new1.58 KB
abhaysaraf’s picture

I have updated the file with proper reasons of removing $weight from the profile.module file.
I used a web tool to quickly prepare diff file, and username at the code comment(which was actually for my internal debugging) has wrongly appeared in the file and has been removed.

Also, next time I will take care of all the suggestions you mentioned. Thanks.

dakala’s picture

@abhaysaraf: Please see https://www.drupal.org/patch for how to create a patch as @nedjo has suggested. It's a file with .patch extension that should be attached to this issue.

guttenbergovitz’s picture

made a patch out of the file but it doesn't seem to work...

mglaman’s picture

Title: Profile fields to appear on manage form of account settings » Profile fields to appear on manage form display for account settings

Okay, I see. The problem here is that the injected fields are not on the form display and they can't be moved around in relation to the normal fields on the form.

+++ b/profile.module
@@ -128,6 +128,16 @@ function profile_entity_extra_field_info() {
+    //Profile fields to appear on MANAGE FORM of ACCOUNT SETTINGS
+    //Account Settings Page: admin/config/people/accounts/form-display

@@ -194,7 +204,9 @@ function profile_form_field_config_edit_form_submit(array $form, FormStateInterf
+  //Commented all $weight variable present in this function;
+  //Since, it always make Profile type fields appear at the bottom of user registration page
+  //$weight = 90;

Need spaces after //

Also.. the latter half can just be removed.

michiellucas’s picture

Priority: Normal » Critical

This is still a problem, on user/%/edit pages the profile fields are not shown.

michiellucas’s picture

StatusFileSize
new1.54 KB

I created a patch that uses a form_alter (like the user register) to add the profile fields to the edit form with the active profile types prefilled.

maaty388’s picture

StatusFileSize
new1.31 KB

I made some code style fixes :)

jwilson3’s picture

There's a related issue #2946670: Add computed {$profile_type}_profiles fields to users, use them to render profile data on the user profile which takes an approach written by Matt for another ticket to get the injected profile field working on the "Manage Display" tab of user entity.

geek-merlin’s picture

Wow, this issue looks quite confused to me. The only reasonable approach is #6 and no form alter is needed then.

geek-merlin’s picture

Status: Needs work » Needs review
StatusFileSize
new3.33 KB

Patch flying in that worksforme.

Status: Needs review » Needs work

The last submitted patch, 13: profile-2750059-13-manage-form-display.patch, failed testing. View results

geek-merlin’s picture

Status: Needs work » Needs review
StatusFileSize
new2.75 KB

Ups, missed some leftovers. Here we go.

Status: Needs review » Needs work

The last submitted patch, 15: profile-2750059-15-manage-form-display.patch, failed testing. View results

geek-merlin’s picture

StatusFileSize
new4.61 KB

Ah, i adjusted the form keys to use a allowed namespace, thus fixed tests.

geek-merlin’s picture

OK, it looks like in the test, without a configured user form display, the form does not appear. What is to be expected if the patch succeeds. Will fix the test later.

geek-merlin’s picture

Status: Needs work » Needs review
StatusFileSize
new2.33 KB

Let's move the form key namespace fix to a followup. Added a needed cache reset on profile type save.

imclean’s picture

With this patch the profile now appears in "manage form display" at /admin/config/people/accounts/form-display but this doesn't affect the user edit form ("user_form"). #9 mentioned this and while it might seem like a separate fix, it means the form display modes only apply to the user registration form and not the user edit form, which is a bit confusing.

The profile currently appears as a separate tab on the user edit form but this doesn't reflect the user account settings.

imclean’s picture

This combines #9 with #19 to provide consistency between the user edit and create forms.

zenimagine’s picture

I am lost with all these question and different patch.

I used this patch that will work :

https://www.drupal.org/project/profile/issues/2946670#comment-12640613

Now I deleted it and applied the patch #21

But you can not get the ID of the profile.

There is even more formatting options for the field.

I used in the twig of my template :

<article{{ attributes.addClass('user--comment') }}>

  {{ content.user_picture }}
  {{ user.label }}

  <div class="bs-field-link">
    <a href="/profile/{{ content.personnel_profiles.0 }}" title="{{ user.label }}"></a>
  </div>

</article>

But it does not work anymore with this patch. How can I get the profile ID ?

With the old patch, it works :

https://www.drupal.org/project/profile/issues/2946670#comment-12640613

simon georges’s picture

Status: Needs review » Needs work

The patch in #21 is incorrect because the extra-field bit is not inside the foreach, and therefore generates 500 errors when installing the module.

simon georges’s picture

Status: Needs work » Needs review
StatusFileSize
new3.29 KB

This should be the correct patch. Credits to previous contributors, I just moved the code at the right place.

lee luyanda’s picture

Thanks to all contributors of this feature patch it worked for me here https://www.hookupndate.com before it my custom profile registration fields showed below the email field and username field now I have control.

grn’s picture

Yes, thank you all. It's a very nice feature. I was just wondering if this patch could have anything to do with this bug: https://www.drupal.org/project/multiple_registration/issues/3036696

Thanks!

amourow’s picture

When profile specified for Allowed roles in /admin/config/people/profiles/manage/[profile_name]
The profile form show in user edit form anyway even it is not an allowed role.

For example, there are profile_a and profile_b,
and profile_a allowed role_a to have this profile,
while profile_b only allowed role_b to have it.

However, both profile_a and profile_b show in the user edit form.

bojanz’s picture

Title: Profile fields to appear on manage form display for account settings » Allow profile fields to appear on the user "manage form display" screen
Priority: Critical » Major

There is no such thing as a critical feature request.

scottsawyer’s picture

@amourow, I think you are correct, there should be a check in the form alter that checks whether the current user has permission to update the profile before it is displayed.

In the patch in #24:

+/**
+ * Implements hook_form_FORM_ID_alter().
+ */
+function profile_form_user_form_alter(&$form, FormStateInterface $form_state, $form_id) {
+  // user_register_form is also called by this form alter.
+  if ($form_id != 'user_form') {
+    return;
+  }
+
+  // Add the profile values to the $form_state so the form_alter of register picks this up.
+  $account = $form_state->getFormObject()->getEntity();
+
+  /** @var \Drupal\profile\ProfileStorage $profileStorage */
+  $profileStorage = \Drupal::service('entity_type.manager')
+    ->getStorage('profile');
+
+  // Load in all the profiles for this user and add it to the form state.
+  /** @var ProfileType[] $profile_types */
+  $profile_types = ProfileType::loadMultiple();
+  foreach ($profile_types as $profile_type) {
+    if ($profile_type->getRegistration() === TRUE) {
+      /** @var Profile $profile */
+      $profile = $profileStorage->loadDefaultByUser($account, $profile_type->id());
+      $property = ['profiles', $profile_type->id()];
+      // Attach profile entity form.
+      $form_state->set($property, $profile);
+    }
+  }
+
+  // Add profile module form alter of user register.
+  profile_form_user_register_form_alter($form, $form_state);
+}

Possibly do something like this:

/**
 * Implements hook_form_FORM_ID_alter().
 */
function profile_form_user_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  // user_register_form is also called by this form alter.
  if ($form_id != 'user_form') {
    return;
  }

  // Add the profile values to the $form_state so the form_alter of register picks this up.
  $account = $form_state->getFormObject()->getEntity();

  // Get the current user.
  $user = \Drupal::currentUser();

  /** @var \Drupal\profile\ProfileStorage $profileStorage */
  $profileStorage = \Drupal::service('entity_type.manager')
    ->getStorage('profile');

  // Load in all the profiles for this user and add it to the form state.
  /** @var ProfileType[] $profile_types */
  $profile_types = ProfileType::loadMultiple();
  foreach ($profile_types as $profile_type) {
    // First, check if the current $user has permission to update the $profile_type
    if ($user->hasPermission('update any ' . $profile_type->id()) || $user->hasPermission('update own ' . $profile_type->id())) {
      if ($profile_type->getRegistration() === TRUE) {
        /** @var Profile $profile */
        $profile = $profileStorage->loadDefaultByUser($account, $profile_type->id());
        $property = ['profiles', $profile_type->id()];
        // Attach profile entity form.
        $form_state->set($property, $profile);
      }
    }
  }

  // Add profile module form alter of user register.
  profile_form_user_register_form_alter($form, $form_state);
}

So, basically get the current user, and check if they have update permission before added to the form. Though, I am thinking this might require some massaging of profile_form_user_registration_form(). Should we also be checking for 'create' and 'delete' permissions?

Thoughts?

scottsawyer’s picture

Hm, thinking about this a bit more, if we need the $profiles to be passed to profile_form_user_registration_form_alter, we might need to set it up a bit differently.

/**
 * Implements hook_form_FORM_ID_alter().
 */
function profile_form_user_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  // user_register_form is also called by this form alter.
  if ($form_id != 'user_form') {
    return;
  }

  // Add the profile values to the $form_state so the form_alter of register picks this up.
  $account = $form_state->getFormObject()->getEntity();

  // Get the current user.
  $user = \Drupal::currentUser();

  /** @var \Drupal\profile\ProfileStorage $profileStorage */
  $profileStorage = \Drupal::service('entity_type.manager')
    ->getStorage('profile');

  // Load in all the profiles for this user and add it to the form state.
  /** @var ProfileType[] $profile_types */
  $profile_types = ProfileType::loadMultiple();
  foreach ($profile_types as $profile_type) {
      if ($profile_type->getRegistration() === TRUE) {
        /** @var Profile $profile */
        $profile = $profileStorage->loadDefaultByUser($account, $profile_type->id());
        $property = ['profiles', $profile_type->id()];
        // Attach profile entity form.
        // create a version of $form_state that will pass directly to profile_form_user_registration_form_alter.
        $registration_form_state = $form_state;
        $registration_form_state->set($property, $profile);
        // First, check if the current $user has permission to update the $profile_type
        if ($user->hasPermission('update any ' . $profile_type->id()) || $user->hasPermission('update own ' . $profile_type->id())) {
          $form_state = $registration_form_state;
        }
      }
    }
  }

  // Add profile module form alter of user register.
  profile_form_user_register_form_alter($form, $registration_form_state);
}

I am not sure this is the best way to handle it, I don't like assigning $registration_form_state, then possibly reassigning it to $form_state. I think it will do what we need.

Honestly, I am not sure why we're checking $profile_type->getRegistration() here. Maybe I don't understand how that plays into whether or not a user can edit a profile.

scottsawyer’s picture

Well, the patch doesn't apply to the latest dev (dev-1.x 6ab5cb0). I don't have time to re-roll at the moment.

jonathanshaw’s picture

Issue tags: +Needs reroll
bojanz’s picture

Status: Needs review » Needs work
jsacksick’s picture

Status: Needs work » Needs review
StatusFileSize
new17.74 KB

The attached patch provides a field widget for the computed field that was added as part of #2946670: Add computed {$profile_type}_profiles fields to users, use them to render profile data on the user profile.

There's a post update function that is in charge of placing the computed field on the user "register" form mode if the "Include in user registration form" profile type setting is checked.

The widget should also support editing the default profile.

I added some code to react when the "Include in user registration form" setting is updated. If it's unchecked, the computed field is removed from the form mode, otherwise it's placed at the bottom.

Status: Needs review » Needs work

The last submitted patch, 34: profile_2750059-34.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

jsacksick’s picture

Status: Needs work » Needs review
StatusFileSize
new18.64 KB
new4.89 KB

Status: Needs review » Needs work

The last submitted patch, 36: profile_2750059-36.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

jsacksick’s picture

Status: Needs work » Needs review
StatusFileSize
new20.29 KB
new3.33 KB

Attempt to fix the tests, sorry for the noise.

jsacksick’s picture

StatusFileSize
new22.06 KB

Adding a "form_mode" widget setting and removing the revision log message in preparation for when #2844963: Complete the revision implementation is committed.

jsacksick’s picture

StatusFileSize
new4.84 KB

Attaching the interdiff.

Status: Needs review » Needs work

The last submitted patch, 39: profile_2750059-39.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

jsacksick’s picture

Status: Needs work » Needs review
StatusFileSize
new23.48 KB

Rerolled the patch.

bojanz’s picture

Title: Allow profile fields to appear on the user "manage form display" screen » Move the profile "registration" form to a field widget
Issue summary: View changes
Issue tags: -Needs reroll

Updating title and issue summary.

bojanz’s picture

StatusFileSize
new23.01 KB

Here is a reroll with some small cleanups (such as a rewritten profile_post_update_configure_register_form_mode()).

jsacksick’s picture

StatusFileSize
new25.23 KB
new8.18 KB

I copied the Field group code we had in the form alter... But it doesn't seem to work as expected, but I'm suspecting it to be broken with the current code as well (See screenshot), the fields are rendered outside of the Field groups.

jsacksick’s picture

StatusFileSize
new24.96 KB
new1 KB

Ok, the attached patch fixes the integration with Field Group, I figured out what was causing the issue that also affects the current code.

I removed the function_exists() call and only make use of the #process function (the #pre_render has been marked as deprecated in nov 2017).

bojanz’s picture

StatusFileSize
new23.53 KB

Sone cleanups, as discussed with jsacksick.

jsacksick’s picture

StatusFileSize
new23.98 KB
new21.75 KB

Now storing and retrieving the profiles from $form_state.
Renamed the widget from 'profile_inline' to 'profile_form'.

jsacksick’s picture

StatusFileSize
new23.94 KB
new537 bytes
jsacksick’s picture

StatusFileSize
new24.2 KB
new1004 bytes

When using the widget multiple times, the form #process and #submit callbacks were added twice, the attached patch fixes that.

  • bojanz committed 3be1482 on 8.x-1.x authored by jsacksick
    Issue #2750059 by jsacksick, axel.rutz, bojanz, Simon Georges,...
bojanz’s picture

Status: Needs review » Fixed

Tweaked and committed. Thanks, everyone!

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

ckaotik’s picture

Please excuse me for butting in on a closed issue, but why was the ProfileAccessTest.php file removed in the commit (but not in the patches)?

john10080’s picture

I got 2 out of 2 hunks FAILED -- saving rejects to file 2750059-50-register-widget.patch.rej while applying patch #50. Why?

jonathanshaw’s picture

Becaus the patch has already been committed and there's no point to applying it.

john10080’s picture

But Im not getting form modes in profile manage form display
-You can manage profiles on other user form modes as well. This was stated as benefit from the post T_T

john10080’s picture

To answer my Question, I found the form modes for profile at config > account > form-display then there's the option for add view mode for profile.

My problem now is how can I use the form mode I created in edit profile form? -_-