I'm using a custom multistep form on a node with several date fields spread over multiple steps.
To hide the date fields which should not be visible on certain steps, I use #access=FALSE (just like any other field though).
$form[$field]['#access'] = FALSE;
The outcome is that all date fields are not saved at the end of the multistep form (on node_save)...
A quick and dirty hack is to hide the date fields with HTML instead of using the #access variable.
$form[$field]['#prefix'] = '<div style="display:none;">';
$form[$field]['#suffix'] = '</div>';
However, this little hack causes other functionality not to work properly, for example prefilling the #default_value of a date field using the value of a date field of a previous step.
The following ticket describes possibly related bug: #1144074: does not play well with multistep / does not validate correctly when #access=false
Comment | File | Size | Author |
---|---|---|---|
#20 | date-handle_field_access_false-1267434-20.patch | 541 bytes | Ronino |
|
Comments
Comment #1
seddonym CreditAttribution: seddonym commentedRenamed the issue from 'Dates not saved by #access=FALSE on multistep forms' as it's a more generic issue.
To reproduce:
- Create a date field and add to a node type.
- In a module, set the #access to user_access('administer nodes') on that date field using hook_form_alter().
- Logged in as a user with administer nodes permission (user 1), create a node and fill in the value of the date field.
- Logged in as a user without administer nodes permission (user 2), edit the node and save.
- Edit the node again as user 1, the value has been wiped.
This issue happens regardless of which widget is used.
(I'm having this issue with the latest development version.)
Comment #2
joverDidn't knew the problem was so general, but it seems to be correct (so new issue title is better).
Comment #3
seddonym CreditAttribution: seddonym commentedFor module developers, there's a fairly simple workaround. This isn't working code, just to give an idea:
Comment #4
joverI guess this workaround will only work for normal forms, not for multistep forms...
The date values must stay in the $form_state variable, they should only be accessible on one step of the multistep form.
Comment #5
j0rd CreditAttribution: j0rd commentedSame problem on a single step form for me. Completely breaking my website as I keep a date field as expiry for paid nodes.
User edits and saves his node, in my system, now he's no longer paid for it.
Gonna have some unhappy people on my site with this one :)
Comment #6
j0rd CreditAttribution: j0rd commentedI believe this is caused by a bi-product of this
#408770: #access of date_combo fields prevents validation
http://drupal.org/node/408770#comment-1818564
Also for those looking for information related to #access = FALSE and $form_state['input'] vs. $form_state['values'] take a look at the documentation here: http://api.drupal.org/api/drupal/includes--form.inc/function/form_builder/7
Comment #7
KarenS CreditAttribution: KarenS commentedA problem that only happens when you do something like create a multi-step form is not a critical bug that makes the module unusable.
When you set #access to false on *any* field you should also be setting #value for that field (move whatever is in #default_value to #value), because the form api won't be processing the value normally.
That may be all that is needed.
Comment #8
das-peter CreditAttribution: das-peter commentedI think this is the similar issue like here #1178716-27: Translating node deletes date field entry
Work on patch is in progress.
Comment #9
KarenS CreditAttribution: KarenS commentedSee the issues in #1178716: Translating node deletes date field entry, which also was setting #access to false. When that issue is marked fixed it should mean that all the #access issues are fixed.
Comment #10
ben_chad CreditAttribution: ben_chad commentedSorry to resurrect an old bug, but I can confirm this is still an issue in 7.x-2.6. I've double-checked as per #7 that #value and #default_value are set. I'm currently getting around the problem with CSS.
Comment #11
wwedding CreditAttribution: wwedding commentedIs it still a problem if you try using the latest dev version?
Comment #12
ben_chad CreditAttribution: ben_chad commentedNo, that sorts it.
Comment #13
mariusdiacu CreditAttribution: mariusdiacu commentedI have the same problem. I've set #access to false to a date field and updating to dev version did not fix the problem. I've cleared all caches and run and updb and still nothing.
Comment #14
wwedding CreditAttribution: wwedding commentedThe way the Date field interacts with the Form API and Field API isn't quite how it should be, so there are certainly still some underlying issues until someone refactors things substantially. My best advice is to use the workaround indicated, especially considering there hasn't been active development on the 7.x branch since 2012.
Comment #15
sylwester CreditAttribution: sylwester commentedthis still persists in 2.8 and the latest dev as well
Comment #16
leendertdb CreditAttribution: leendertdb as a volunteer commentedI'm aware this is an old issue, but we stumbled upon this one today. We are using the field_permissions contrib module, which allows you to specify certain user roles to view/edit a field. For users that do not have the correct permissions, the fields "#access" property will be set to FALSE.
What happened in our case was that after a user with limited permissions edited a node, all hidden field dates were emptied resulting in corrupted data.
I have backtraced the issue to the following code in "./date_popup/date_popup.module":
This if comparison checks if the date field is hidden, and if so, stops executing the validate function which normally takes care of converting a date field array to a string value. When we changed the code above to the following, it worked:
Seemed like even though the form element was not rendered, the element itself in hook_node_presave() still contained the date array value, which is not a correct value for the database. So when it tries to insert the array, it errors and simply considers it as an empty string.
The code change above makes sure that it only stops executing the validate function if the form element is hidden AND it is a string. If it is an array, it will keep on executing making sure the array is converted to a string value (what normally always happens when the form element is actually rendered).
Comment #17
leendertdb CreditAttribution: leendertdb as a volunteer commentedUpdating status to "Needs review". I was unable to create a patch at the moment, but perhaps someone else could do that after verifying the fix above works.
Comment #18
kingandy CreditAttribution: kingandy commentedThe code I'm looking at has that
if (date_hidden_element($element))
immediately followed by anif (is_string($element['#value']))
, so I don't think adding it to the first logic will have any effect. This seems to have been in place since at least 7.x-2.1 (2012). @leeendertdb, are you on the 1.x branch? It seems like this may already have been implemented.TBH the #access=false seems to prevent the field from being validated at all (which seems reasonable) so I don't think the problem is in the validation function.
I'm still seeing this behaviour in the 7.x-2.10 release (under Drupal 7.54). We're manually applying #access=false, and the save function is producing a second null-null date range in the field (thankfully retaining the original from-to values in delta 0).
Comment #19
deepakaryan1988Any solution for this guys?
Comment #20
Ronino CreditAttribution: Ronino as a volunteer commentedkingandy wrote in #18:
I am using the field_permissions module (that basically sets #access to FALSE on configured fields) to restrict access to some date fields and I have found that for those fields, like described above, an extra field item with a NULL value is saved on the first node update (leading to some side effects for me). On the second one it's removed, recreated on the third and so on.
Fortunately, "real" field items never get deleted though.
I have found date_field_widget_form() to be the culprit as it temporarily saves an empty string #date_items for those fields which later gets converted to and saved as that NULL value item (only date_combo_validate() processes those items). I am not sure where exactly that conversion takes place, but the issue doesn't occur for me anymore after setting an empty array instead.
The attached patch fixes it for me.
Comment #21
steinmb CreditAttribution: steinmb as a volunteer commentedComment #22
DamienMcKennaI'm committing #20 on the simple basis that the fallback value should be an array.
I created #3010073: Add test coverage for #access=FALSE on field change to handle the test coverage.
Comment #24
DamienMcKenna