While converting https://www.drupal.org/project/restrict_by_ip to D8, I found a bug that occurs when you add a form field to the user registration form with hook_form_alter() and try to access the form value in hook_user_insert(). In D7, the additional form values are available in the $edit parameter of hook_user_insert(). In D8, the additional form values are not available in the $account parameter of hook_user_insert().
The following change records describe how to convert hook_user_insert():
https://www.drupal.org/node/2294409
https://www.drupal.org/node/1554986
The form alter doesn't change:
function MODULE_form_user_register_form_alter(&$form, $form_state) {
$form['some_extra_field'] = array(
'#type' => 'hidden',
'#value' => 'querty',
);
}
D7 hook_user_insert():
function MODULE_user_insert(&$edit, $account, $category) {
if (isset($edit['some_extra_field'])) {
// Do something here.
}
}
D8 hook_user_insert():
function MODULE_user_insert($account) {
if (isset($account->some_extra_field)) {
// Do something here.
}
}
The problem is that $account->some_extra_field doesn't exist. I inspected the $account object in PHPStorm and didn't find the additional form values anywhere.
| Comment | File | Size | Author |
|---|---|---|---|
| #2 | 2563697-2.patch | 761 bytes | rocketeerbkw |
Comments
Comment #2
rocketeerbkw commentedHere's a patch that fixed it for me, but I need some help from testbot.
Comment #3
rocketeerbkw commentedTests passed!
$entity->set()looks like it only works for saving Field API values. But if you look at__set()onDrupal\Core\Entity\ContentEntityBaseyou'll see it already handles setting values for fields or, if no fields match, setting it directly on the object. This makes__get()able to retrieve the value off the object when it's used inhook_user_insert().I also tested loading the user entity after all the hooks are done, in a different part of the system.
$account->some_extra_fieldwas not available so it's not being saved as extra data, just being persisted tohook_user_insert().Comment #4
rocketeerbkw commentedThis is a soft blocker for https://www.drupal.org/project/restrict_by_ip. It breaks an admin only convenience when adding a user, but won't keep the module from working as intended.
I'm not sure how to write a simpletest that checks the interaction between two hook functions. If someone can help with methodology, I can write the tests.
Comment #5
berdirYes, this is by design.
You can either use an entity_builder callback or just store your value through a submit callback.
See menu_ui_form_node_form_alter() + its submit callback menu_ui_form_node_form_submit() or menu_ui_form_node_type_form_alter() and the entity builder menu_ui_form_node_type_form_builder() for examples.
Entities are typed, defined objects. We no longer put arbitrary stuff on them.
Comment #6
rocketeerbkw commentedI needed the data from the form I added to the registration field AND the final users ID to do what I needed.
It turns out that the user ID is available in a submit callback after all. You can get the entity from
$form_state:$user = $form_state->getFormObject()->getEntity();