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 CreditAttribution: rocketeerbkw commentedHere's a patch that fixed it for me, but I need some help from testbot.
Comment #3
rocketeerbkw CreditAttribution: rocketeerbkw commentedTests passed!
$entity->set()
looks like it only works for saving Field API values. But if you look at__set()
onDrupal\Core\Entity\ContentEntityBase
you'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_field
was not available so it's not being saved as extra data, just being persisted tohook_user_insert()
.Comment #4
rocketeerbkw CreditAttribution: 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 CreditAttribution: 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();