Hello

I like your module, thank you.

But I have a problem with user entity. I have created field with widget "Inline entity form". This field is referenced to user.
I want to create new user, which will be referenced through this field. But in the inline form I see only fields which are added through field API. For example first name and last name. But there are no system fields like name, mail, password. Due the fact that I can't fill these fields, user cannot be created.
Is it bug? How can I create user through inline entity form?

Thanks in advance.

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

eugene.ilyin created an issue. See original summary.

bojanz’s picture

Title: Trouble with creation of user in inline entity form » Add integration for the user entity type
Category: Bug report » Feature request

You can't, there's no integration for users. Someone will need to create an inline form handler for users.

eugene.ilyin’s picture

I can help. I have tried to do it myself but I'm stuck. Maybe you can give me few advice how to start?

eugene.ilyin’s picture

Status: Active » Needs review
StatusFileSize
new2.66 KB

I have implemented integration for user entity type. It's pretty hacky, but I'm restricted in time and I don't see better way.
In any case it works and it helps me.
Maybe it will be useful for somebody.

hydra’s picture

Thx for sharing, this is indeed working!
The code doesn't look bad, but since I'm not (yet) into inline_entity_form I wont't RTBC it. But perhaps a more experienced developer will have a look at it when seeing that this patch is functional.

eugene.ilyin’s picture

I have found that password cannot be saved through user entity inline form due the some features of processing of this field.
I have prepared new patch, which solves this problem.

eugene.ilyin’s picture

Could somebody review my patch?

init90’s picture

Hello:)

I am testing the path, but it does not work on drupal 8.1.3.

eugene.ilyin’s picture

@DovganPavlo, could you explain please, what the problem?

init90’s picture

The button 'Create user' does not work. Error message after material saving:

Fatal error: Cannot create references to/from string offsets nor overloaded objects in /var/www/icareix-web/docroot/core/lib/Drupal/Component/Utility/NestedArray.php on line 155

sokru’s picture

It works, but I hope it gets code review before RTBC.

betoquiroga’s picture

I have the same error than DovganPavlo - #10 - on Drupal 8.1.6

If I fill only the username and password fields, the user is created, but columns are NULL on the database

dawehner’s picture

Issue tags: +Needs tests

I'm wondering whether we could add some little test about this small bit of the functionality?

grimreaper’s picture

Hello,

Thank you very much for the patch.

I just have tested the patch from comment 6 and it works.

But I was not abled to apply the patch using composer. I have inline_entity_form added with Drupal commerce 2.0.0-beta3.

In my use case I will also have to do some alter on the core permissions.

I want to use inline entity form to make a ticketing system where you can buy a ticket for another user. Unfortunately to be able to create a user, the 'administer users' permission is needed which is too much.

When I will have time, I will try to help with the tests to have this feature merged before making the alter for my project.

grimreaper’s picture

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

Hello,

Here is the patch from comment 6 rebased to the last code base.

Before writing test, I found a bug.

Creating the user is OK, but editing this user using inline_entity_form does not work.

It loads the same form for the user creation, an empty form, the user's values are not used.

I will try to remove this bug before writing tests.

EDIT: Also user creation does not work using 'Inline entity form - simple' widget: I got the error "Password field is required." whereas I filled it.

eugene.ilyin’s picture

Status: Needs work » Needs review
StatusFileSize
new6.09 KB

Hello

I've prepared a new patch. It's not ideal and supports only widget "Entity Inline Form - complex". Due the investigation I found that seems there is no good way to implement support of the User entity. The main reason is that some fields of user entity, like name or mail, cannot be loaded as usual fields in EntityFormDisplay->collectRenderDisplay(). They are defined manually in AccountForm.

I've tested this patch with Drupal 8.2

But this functionality is very critical for my project and maybe somebody else will find it useful.
Any reviews are welcome.

grimreaper’s picture

Status: Needs review » Needs work

Hello,

Thanks eugene.ilyin for the patch.

Ok to focus on the "Entity Inline Form - complex" widget.

Here are my manual testing scenarios, as an administrator:
- creation of a user : OK
- edit of a user : OK (It works now thanks)
- start filling a user, reload the page with "f5" : KO, inline entity form does not load the right form.
- save a user form with error like a required field : KO, no error highlighted and then inline entity form is broken, it does not load the right form.

grimreaper’s picture

Status: Needs work » Needs review
StatusFileSize
new10.96 KB

Here is a patch to add some config for automated testing.

2 content types:
- one for multi value field on user reference with complex widget
- one for single value user reference with simple widget

I also note that some other test config have uuid in the config files. Should I make a patch in another issue to remove its?

Status: Needs review » Needs work
grimreaper’s picture

Removing a path field that adds a dependency on the path module.

grimreaper’s picture

Here is a beginning of tests for user integration. Currently it only checks if fields are here.

There are two patches:
- one with the test and the config only which should fail
- one with the test and the config and the patch from eugene.ilyin should be ok.

I added a text field on the user entity.

Status: Needs review » Needs work
grimreaper’s picture

Status: Needs work » Needs review
StatusFileSize
new26.93 KB

Here is a patch with another test that checks user creation and edition.

Note that the check in case of form error is commented as it does not work yet.

dmsmidt’s picture

Status: Needs review » Needs work

Great work so far!

I manually tested using a different form view mode in which I hid "fields" like "Timezone". However they are still displayed in the IEF.

Also as mentioned in #17, validation is broken.

And it seems that the values of all non-fieldapi fields are stored in a wrong structure in $form_state['values'].
For example 'roles' are in ' $form_state->values['roles']' but they should reside in: '$form_state->values['field_your_user_reference_field']['form']['inline_entity_form']['entities'][0]['form']['roles']'.

The following logic results in wrong '#array_parents' and '#parents' for all elements and child elements.

    $form = \Drupal::service('entity.form_builder')
      ->getForm($entity, 'default');
    $keys = ['account', 'contact', 'language', 'timezone'];
    foreach ($keys as $key) {
      if (!empty($form[$key])) {
        $entity_form[$key] = $form[$key];
      }
    }
nebel54’s picture

+++ b/src/Form/UserInlineForm.php
@@ -0,0 +1,149 @@
+  public static function submitCleanFormState(&$entity_form, FormStateInterface $form_state) {
+    ...
+    if (\Drupal::service('module_handler')->moduleExists('contact')) {
+      ...
+      if ($entity->id()) {
+        \Drupal::service('user.data')
+          ->set('contact', $entity->id(), 'enabled', $contact);
+      }
+      parent::submitCleanFormState($entity_form, $form_state);
+    }
+  }

It looks like

parent::submitCleanFormState($entity_form, $form_state);

got accidently into the if statement for the contact module here. It should be after it, to get the cleanup done.

dpi’s picture

grimreaper’s picture

Hello,

Thanks @Nebel54 for seing that. I changed that in the patch.

@dmsmidt: thanks for testing. For me when I remove the timezone field it works, I don't see it anymore in inline entity form.

Thanks for pointing the problem of #parents, #array_parents. I tried to analyze the target structure but I didn't managed to get it working and the form is still not reloaded in case of error, the ajax simply fails.

brayfe’s picture

Thanks for the awesome module and the work on the patch! The patch in #27 does exactly what I need it to (allows an admin to create a new user with custom fields while filling out an order for that user). There is a small problem I found, but it won't prevent me from using the patched module. I had created some custom field logic using the State API within a hook_form_alter for the 'user_form', however, the custom code states aren't reflected when I load the form using this module. It also isn't running the custom validate code for the same form. Please let me know if I can help provide more context or code to help resolve this issue.

rezk2ll’s picture

how can i install this patch on 7 ?

robpowell’s picture

@grimreaper curious, why not use array_map for this use case?

+    // Invoke all specified builders for copying form values to entity fields.
+    if (isset($entity_form['#entity_builders'])) {
+      foreach ($entity_form['#entity_builders'] as $function) {
+        call_user_func_array($function, [
+          $entity->getEntityTypeId(),
+          $entity,
+          &$entity_form,
+          &$form_state,
+        ]);
+      }
+    }

My thoughts are that's what array_map is made to do.

I can't tell if this is the validation bug brought up earlier but I cannot save the node my user inline_entity_form is on

Really excited about this functionality, it would be great to get this ticket in before the 1 year anny. :D

rakesh.gectcr’s picture

rakesh.gectcr’s picture

Thank you everyone,
Amazing work so far, I am having a humble request while applying patch Kindly add the interdiff file, so that others who is looking to review or to work, life will be easy.... :)

kolin’s picture

This will now respect any hook_form_user_register_form implementations.

kolin’s picture

dylan donkersgoed’s picture

I'm having the same issue as robpowell in #30. It looks like the fields in the account subform are being wiped out and the password field specifically complains about validation errors.

dylan donkersgoed’s picture

Not quite there yet but I think this is an improvement. It does it in a bit of a convoluted way but this patch gets both the entity fields and the form fields and successfully saves the entity for the simple widget. Unfortunately it isn't actually saving the *reference* to the entity properly yet.

kolin’s picture

I've just tried out #36

Previously with #33 Clicking "Create User" in the inline form would create the user correctly and replace the inline form with the correct preview of the user. But validation didn't work.

With #36 this seems to be the opposite. Validation works but the form doesn't change.

I'll have another look at this tonight and see if I can figure out how to get both working.

attisan’s picture

any progress on this?

asherry’s picture

This helps me out immensely, thank you all so much for you work!

Two issues I'm having with it:
- I'm not sure why the alter for form_user_register_form is being invoked manually, I would imagine that would automatically be called if you set the #form_mode to 'register'. In my case it's creating a weird loop, because I'm trying to embed the user form on a profile module entity form. With form_user_register_form_alter being called, the profile module is then automatically attaching an inline form to the existing inline form.

- I'm trying to get this working with just a form element, and it seems like in the copyFormValuesToEntity function there is:

    $field_values = $form_state->getValues();
    $account_values = $subform_state->getValues()['account'];

If I set my element to #tree => TRUE, then the $account_values is properly populated, but $field_values is not. If it is #tree => FALSE, then the reverse. Am I missing something?

Here is my element so far:

    $entity = $form_state->getFormObject()->getEntity()->uid->entity;
    $form['account'] = [
      '#type' => 'inline_entity_form',
      '#entity_type' => 'user',
      '#form_mode' => 'customer',
      '#save_entity' => TRUE,
      '#default_value' => $entity,
      '#op' => 'edit',
      '#tree' => TRUE,
    ];

    // This is copied from the entity_browser module.
    $form['#submit'][] = ['Drupal\inline_entity_form\ElementSubmit', 'trigger'];
    $form['actions']['submit']['#ief_submit_trigger']  = TRUE;
    $form['actions']['submit']['#ief_submit_trigger_all'] = TRUE;
cjsmith87’s picture

Any progress on this? I really need this feature for my production site

netw3rker’s picture

It looks like the primary issue here is that the username, pass, mail, and other fields are not widget based fields that are defined in the entity field properties. Worse, these two types of definitions are created in two different types of forms (form objects from a controller, and classic form arrays). This patch makes a good attempt at bringing the fields from one to the other, but they just aren't designed to do that, and issues like validation are not preserved.

It occurred to me that this would be solved if there were a patch to core that provided these fields as proper entity fields. If that exists then the native entity handling for IEF would work just fine without the need for this patch.

After some digging, i found: https://www.drupal.org/project/drupal/issues/2227381 which applies formatters and widgets to those fields.

Once I applied that patch, I did not need the patch in this issue, and the user fields appear, and validate as expected.

Hope this helps!

geek-merlin’s picture

It looks like this patch contains a lot of unrelated changes that may or may not make sense, but prevent an effective review.

philltran’s picture

Re-rolled the #27 patch against latest dev branch.

While the now user saves with roles, we need to add logic to save user status and language.

Changing
$entity = $entity_form['#entity']; to $entity = \Drupal\user\Entity\User::create(); and using 'register' form display ($form = \Drupal::service('entity.form_builder')->getForm($entity, 'register');) makes the username and password field appear. Previously, the username field was set with type of hidden causing the field to be ... uh hidden.

philltran’s picture

yassersamman’s picture

Tested #44
The fields do appear. but still having issues with the password field.
Submitting the form clears Roles, Email, Username and Password fields along side the password validation failure. it seems that values aren't reaching the parent class properly.
The error is raised in EntityInlineForm
inside entityFormValidate, when calling form_display->validateFormValues($entity, $entity_form, $form_state);

cjsmith87’s picture

Coming back to this 2 years later, is there any progress on this issue? It is a great module but really need to be able to use it with users

spleshka’s picture

I started from the ideas defined in #36, but as it usually happens ended up rewriting it all :) The most notable difference between #36 and my patch is that I use standard buildEntity() method from in \Drupal\user\RegisterForm to populate user entity fields. It covers more use cases than #36. What the patch still does not do is executing RegisterForm::submitForm and RegisterForm::save (which handles things like sending email notifications, etc), because it was outside of the scope for my use case (I use Entity Browser to handle the form). I believe that if someone will have a use case for user creation flow with Inline Entity Form only then adding those submit handles should be pretty straight forward.

I'm not changing the status of the issue because the work is still needed to provide full integration with Inline Entity Form, but hopefully it'll be a good reference for someone else to complete the task.

lalop’s picture

I've an issue with patch from #47 when using an other form mode then the default one.

Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException: The "user" entity type did not specify a "inline_form" form class. in Drupal\Core\Entity\EntityTypeManager->getFormObject() (line 211 of core/lib/Drupal/Core/Entity/EntityTypeManager.php).

afagioli’s picture

Feedback on patch #47

On submit:

TypeError: key(): Argument #1 ($array) must be of type array, null given in key() (line 362 of /home/a/Public/d9/web/core/modules/user/src/AccountForm.php)
#0 /home/a/Public/d9/web/core/modules/user/src/AccountForm.php(362): key()
#1 /home/a/Public/d9/web/modules/contrib/inline_entity_form/src/Form/UserInlineForm.php(51): Drupal\user\AccountForm->buildEntity()
#2 /home/a/Public/d9/web/modules/contrib/inline_entity_form/src/Form/EntityInlineForm.php(275): Drupal\inline_entity_form\Form\UserInlineForm->buildEntity()
#3 /home/a/Public/d9/web/modules/contrib/inline_entity_form/src/Element/InlineEntityForm.php(180): Drupal\inline_entity_form\Form\EntityInlineForm->entityFormSubmit()
#4 [internal function]: Drupal\inline_entity_form\Element\InlineEntityForm::submitEntityForm()
#5 /home/a/Public/d9/web/modules/contrib/inline_entity_form/src/ElementSubmit.php(109): call_user_func_array()
#6 /home/a/Public/d9/web/modules/contrib/inline_entity_form/src/ElementSubmit.php(86): Drupal\inline_entity_form\ElementSubmit::doSubmit()
#7 [internal function]: Drupal\inline_entity_form\ElementSubmit::trigger()
#8 /home/a/Public/d9/web/core/lib/Drupal/Core/Form/FormSubmitter.php(114): call_user_func_array()
#9 /home/a/Public/d9/web/core/lib/Drupal/Core/Form/FormSubmitter.php(52): Drupal\Core\Form\FormSubmitter->executeSubmitHandlers()
#10 /home/a/Public/d9/web/core/lib/Drupal/Core/Form/FormBuilder.php(592): Drupal\Core\Form\FormSubmitter->doSubmitForm()
#11 /home/a/Public/d9/web/core/lib/Drupal/Core/Form/FormBuilder.php(320): Drupal\Core\Form\FormBuilder->processForm()
#12 /home/a/Public/d9/web/core/lib/Drupal/Core/Controller/FormController.php(73): Drupal\Core\Form\FormBuilder->buildForm()
#13 [internal function]: Drupal\Core\Controller\FormController->getContentResult()
#14 /home/a/Public/d9/web/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php(123): call_user_func_array()
#15 /home/a/Public/d9/web/core/lib/Drupal/Core/Render/Renderer.php(564): Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}()
#16 /home/a/Public/d9/web/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php(124): Drupal\Core\Render\Renderer->executeInRenderContext()
#17 /home/a/Public/d9/web/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php(97): Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->wrapControllerExecutionInRenderContext()
#18 /home/a/Public/d9/vendor/symfony/http-kernel/HttpKernel.php(169): Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}()
#19 /home/a/Public/d9/vendor/symfony/http-kernel/HttpKernel.php(81): Symfony\Component\HttpKernel\HttpKernel->handleRaw()
#20 /home/a/Public/d9/web/core/lib/Drupal/Core/StackMiddleware/Session.php(58): Symfony\Component\HttpKernel\HttpKernel->handle()
#21 /home/a/Public/d9/web/core/lib/Drupal/Core/StackMiddleware/KernelPreHandle.php(48): Drupal\Core\StackMiddleware\Session->handle()
#22 /home/a/Public/d9/web/core/modules/page_cache/src/StackMiddleware/PageCache.php(106): Drupal\Core\StackMiddleware\KernelPreHandle->handle()
#23 /home/a/Public/d9/web/core/modules/page_cache/src/StackMiddleware/PageCache.php(85): Drupal\page_cache\StackMiddleware\PageCache->pass()
#24 /home/a/Public/d9/web/core/lib/Drupal/Core/StackMiddleware/ReverseProxyMiddleware.php(48): Drupal\page_cache\StackMiddleware\PageCache->handle()
#25 /home/a/Public/d9/web/core/lib/Drupal/Core/StackMiddleware/NegotiationMiddleware.php(51): Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle()
#26 /home/a/Public/d9/vendor/stack/builder/src/Stack/StackedHttpKernel.php(23): Drupal\Core\StackMiddleware\NegotiationMiddleware->handle()
#27 /home/a/Public/d9/web/core/lib/Drupal/Core/DrupalKernel.php(709): Stack\StackedHttpKernel->handle()
#28 /home/a/Public/d9/web/index.php(19): Drupal\Core\DrupalKernel->handle()
#29 {main}
jigarius’s picture

While trying the patch in #47, I get the following issues:
* UserInlineForm should use EntityInterface $entity instead of ContentEntityInterface to be compatible with the parent class.
* The inline form works in the "default" form mode but it doesn't work with custom form modes that I've created, say "membership". I get the following error:

Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException: The "user" entity type did not specify a "membership" form class. in Drupal\Core\Entity\EntityTypeManager->getFormObject() (line 207 of core/lib/Drupal/Core/Entity/EntityTypeManager.php).

* Say, you hide the "timezone" field from the registration form. The inline entity form still shows this field even though the form mode is set to "register" correctly.

One more thing to keep in mind is whether the form alter hooks are triggered correctly for the user form. Say, if you're using a module to hide the username field, is that module being able to affect the registration form correctly. Example: auto_username or remove_username

jigarius’s picture

I took a look at the patch 47 and created a PR with some changes. In the end, I got the user creation to work, but for some reason, the newly generated user's ID doesn't get attached to the parent entity's form correctly, i.e. the inline_entity_form elements are not replaced by a nice target_id so the parent form fails to submit.

In patch 47, the "account" element for the user data don't get copied into the User entity because the AccountForm expects a different structure of values in the FormState. I'm starting to think that it might be better to create a simplified version of the user account form for use with the InlineEntityForm instead of involving AccountForm at all.

As for my project, I'll be simplifying this by injecting just: name, mail, pass, status, and the Field API fields, if any. At least it will get the ball rolling for me.