Drupal: Debugging, Field Permissions, and Field Collections, Oh My!

I was just assigned a little bug in which a field is visible for users to add values to, but they can’t see the field to edit existing values. The following is a walkthrough of how I do a typical debug and the interesting results I found for this particular bug.

The first thing I did was try to reproduce the scenario. The field in question is in a Field Collection (the replacement for Drupal 6’s multigroup functionality) in the user’s profile. I verified that I could indeed add a value and save the user profile, but that the field was not visible when going back to that user profile’s edit screen. The next step was to make sure a value had even been correctly saved. I logged in as root and viewed the user’s profile edit page. Sure enough, the form held a field collection item with the correct value. I also verified this in a devel dump.

Ok, so the problem is that the field is not visible. The next step was to dump the value of $form in this particular form’s hook_form_FORM_ID_alter(). I saw that the #access attribute for this field was set to FALSE when the original viewer was looking at the form. Ok, so something was hiding the field. A quick grep across the codebase turned up no mention of the field name.

At this point, I was pretty sure it was something wonky with the Field Permissions contrib module that we’re using to provide more granular access to fields with less custom code. The first thing I did was to view the field’s config and verify that indeed it was set to custom permissions and that the type of user I tested with was correctly allowed access to edit existing values. Ok, so that wasn’t it; if it had to do with this module then it was something happening in the code itself. I opened up field_permissions.module and scrolled through till I found a likely starting point: hook_field_access().

Starting from that function, using logic and strategically placed dumps, I dug through the layers of functions until I reached _field_permissions_entity_is_owned_by_account(). The code in this function is a simple comparison: does the acted upon entity have a uid, and if so, does the acting user’s uid match the acted upon entity’s uid? If so, the function returns TRUE and the acting user has access to the field, and vice versa. I dpm()‘d both the $account and $entity and here’s where it got funny. Evidently entities of type FieldCollectionItem don’t have a uid property. This means the comparison was false, and the acting user was not granted access to edit the field.

Ok, simple enough. What’s the solution? To play nice with other modules, the Field Collection module should add a uid property to its entities, even if it’s redundant with the node/user entity that owns each FieldCollectionItem entity. As for my specific case, since this field is only displayed in the user’s profile edit form, and only that user and our staff roles have access to the edit form, it’s easiest to just set the #access property of that field in the $form structure back to TRUE, with a note summarizing why the hack is there.