Posted by jonhattan on June 13, 2010 at 10:03am
10 followers
| Project: | Content Profile |
| Version: | 6.x-1.x-dev |
| Component: | User registration module |
| Category: | bug report |
| Priority: | normal |
| Assigned: | Unassigned |
| Status: | closed (works as designed) |
| Issue tags: | SQL flexifield geo after_build #after_build form form_add |
Issue Summary
#after_build is not added in content_profile_registration_add_profile_form(). This can produce unexpected missing functionality provided by other modules defining form wide #after_build operations, as conditional_fields. Related issue: #795324: Latest 2.x-dev not compatible with content profile?.
| Attachment | Size |
|---|---|
| content_profile_registration_after_build.patch | 994 bytes |
Comments
#1
Here's another patch with a working solution.
Note this patch is part of a solution to another issue that is stalled - #621346-3: Validate Multigroup (CCK3) Fields on User Registration Form
#2
Patch in #1 did not work for me (using conditional fields on Content Profile in the registration form). I got it working with this: https://drupal.org/node/795324#comment-2981146
#3
That's impossible to do it right in general. CP only cares about the CCK field forms, any additions won't be in.
#4
Patch in #1 did work for me to get conditional fields to work on the main registration page.
#5
I spent forever chasing down a problem with a geocode field.
Finally, I discovered that this user registration module doesn't honour the #after_build callbacks.
The normal sequence to build a form includes:
drupal_prepare_form
drupal_process_form
process_form calls formbuilder,
formbuilder runs the #after_build callbacks.
It's not uncommon for a contributed module to implement a field's functionality using an #after_build callback.
This user registration module works as follows;
- It uses a hook_form_alter to alter user_register form.
- Inside that hook, it partially creates a bunch of node-form types, copies parts of them back to the user_register form, and then throws the form_nodes away.
Because drupal_process_form doesn't get called on each node_form, the #after_build callbacks don't get called either.
Depending on how the contributed module works, you may be grabbing the field, but not grabbing all it's functionality.
So what's the solution
- should this module know how to play nice with the fields that it's grabbing?
- should other fields know about this module, and know that they need to stick a callback not only on user_node forms, but also user_register forms?
- should this module say "I only support this set {} of field types" (if so, then the fields shouldn't show up on admin/content/node-type/profile-personal/profile)
In my humble opinion, if you're going to interfere with the form building process in this manner, then it's your reponsability to make sure that the #after_build functions are called. Perhaps you shoud also have a peek at the form_builder() function itself, and see if there's any other important work that you need to replicate.
regarding the patches:
content_profile_registration_after_build.patch
- This patch fails, because of the way += works when the two arrays have matching keys. Consider the following:
before:
"$form['#after_build']" Array [1]
0 wysiwyg_process_form
"$node_form['#after_build']" Array [4]
0 climbing_partner_after_build
1 _flexifield_theme_node_form
2 geocode_widget_set_form_value
3 wysiwyg_process_form
after:
"$form['#after_build']" Array [1]
0 wysiwyg_process_form
1 _flexifield_theme_node_form
2 geocode_widget_set_form_value
3 wysiwyg_process_form
patch from comment 1
This patch looks like it will get the correct set of values into the callback array, but the order will be a little strange. Not sure if the order is important or not.
my patch
+ // add the callbacks
+ foreach (array('#after_build') as $type) {
+ $form[$type] = array_merge($form[$type], array_diff($node_form[$type], $form[$type]));
+ }
+
// Add in further callbacks needed, if not yet done.
#6
#7
I confirmed that this issue can also prevent flexifield from working correctly.
My intial symptom only involved geo, so I initially patched the code with something like this:
sites/all/modules/content_profile/modules/content_profile_registration.module:
// Add in the new form elements into $form.
$form += array('#field_info' => array());
$form['#field_info'] += $node_form['#field_info'];
$form += $form_add;
+ // add the geo callback, if needed
+ $form_add += array('#after_build' => array());
+ $form += array('#after_build' => array());
+ if ( ( in_array('geocode_widget_set_form_value', $form_add['#after_build']))
+ && (!in_array('geocode_widget_set_form_value', $form['#after_build']))) {
+ $form['#after_build'][] = 'geocode_widget_set_form_value';
+ }
Later, after we fixed a non-related configuration issue with flexifield, we started getting SQL errors on user reg form submission. The SQL query in question involved flexifield. I remembered that flexifield also wanted an after_build callback, (see post #5) so I altered my patchwork, and that solved the flexifield SQL problem.
// Add in the new form elements into $form.
$form += array('#field_info' => array());
$form['#field_info'] += $node_form['#field_info'];
$form += $form_add;
+ // patch to add in all afterbuild functions
+ foreach (array('#after_build') as $type) {
+ $form += array($type => array());
+ $form_add += array($type => array());
+ $form[$type] = array_merge($form[$type], array_diff($node_form[$type], $form[$type]));
+ }
In case your wondering, the rational for using the foreach loop, is just in case someone else identifies another array inside $form_add that needs to get merged into $form. You can re-patch as follows:
foreach (array('#after_build', '#whatever') as $type) {
#8
I'm seeing a similar problem with the Location module. With Content Profile Registration enabled a user cannot enter their location on registration. It won't save to the database. The patches aren't working for me.
#9
The patch in #1 worked for me, getting conditional fields to work on registration pages. Thanks!
#10
I agree with the comments in #5. Here is a patch. seems to work for me.
#11
Patch looks good (maybe the comment should start with an uppercase A to match the other comments in this function, but that's minor and I won't reroll for that, otherwise I couldn't RTBC the pach ;-)).
The array approach seems reasonable too, as maybe #pre_render could be moved there in another issue, which would allow the use of cck's ordering without needing to reimplement it in content profile)
#12
I have the same Problem, but in my case cck private fields don't work after a failed validation of the Registration form. Also none of the patches work for me...
#13
@#12 : Do you mean functionnality provided by http://drupal.org/project/cck_private_fields ? If you do, then, it's quite unlikely to be the same problem, as this module doesn't use #after_build at all. Which would also explains why no patches in this issue fixes your problem: it's a different one...
#14
Ok, then thats another Problem. I will start a new issue for that.
I have got a Problem with the Avatar Selection Module too, only when Content Profiles Registration Page ist active.
#15
I don't think adding in #after_build callbacks is a good thing when we are just taking over some fields of the form. The callbacks expect a node form, what is not here so they could fail.
In case, the module is configured to take over the whole form, I think the callbacks should have been already taken over.