Problem
Field_collection_item_access() has some weirdness in it right now. $Op is defined and re-defined inside of it (removing all but view and update values for entity access), the code doesn't follow a consistent standard in setting variables, and calls to it usually set the $op 'edit' value to 'update' in a ternary, just to re-set, and re-re-set it inside the function.
Solution
Field_collection_item_access() should take the $op value as is, and do all needed manipulation inside the function itself. That way no special knowledge is needed to call the function, and if we decide to change the default 'edit' operation value to 'update', we can change the manipulation code in one place -- the function -- instead of having to touch all of the function calls themselves.
Updated code. This should be backwards compatible with all current function calls, in case a third party is still calling it with the ternary setting 'edit' to 'update':
function field_collection_item_access($op, FieldCollectionItemEntity $item = NULL, $account = NULL) {
if (user_access('administer field collections', $account)) {
return TRUE;
}
if (!isset($item)) {
return FALSE;
}
$field = field_info_field($item->field_name);
// Entity access takes 'view', 'update', 'create' or 'delete' operations.
if ($op == 'edit') {
$op = 'update';
}
// Field access takes only 'view' or 'edit' operations.
$field_op = $op == 'view' ? 'view' : 'edit';
// Access is determined by the entity and field containing the reference.
return entity_access($op, $item->hostEntityType(), $item->hostEntity(), $account) && field_access($field_op, $field, $item->hostEntityType(), $item->hostEntity(), $account);
}
Remaining Tasks
I'll write a patch that adds the above code and revises all of the function calls.
If you see a horrible flaw in my suggestion, please let me know.
| Comment | File | Size | Author |
|---|---|---|---|
| #10 | field_collection-item_access-1688114-10.patch | 3.21 KB | RobW |
| #8 | field_collection-item_access-1688114-8.patch | 2.59 KB | RobW |
| #1 | field_collection-item_access-1688114-1.patch | 2.59 KB | RobW |
Comments
Comment #1
RobW commentedPatch. I've only casually tested, so needs a closer look.
Comment #3
RobW commentedAlso, if anyone can explain what
FieldCollectionItemEntitywith no comma after it is doing in the args... looks almost like an accidental paste, but has been in dev releases for a little while.Comment #4
RobW commented#1: field_collection-item_access-1688114-1.patch queued for re-testing.
Comment #6
RobW commentedDon't know why this is failing, applies fine and seems to work for me.
Comment #7
RobW commentedComment #8
RobW commentedRe-rolled for the latest dev.
Comment #9.0
(not verified) commentedadded formatting, made language more specific
Comment #9.1
RobW commentedYou know, just editing.
Comment #10
RobW commentedAh, ok, I learned how to use simpletest. Behold the green!
Comment #11
fagohm, I don't think that adding even more possible $op makes it any better. At least the function signature of field-collection is now sane, so let's better keep it that way.
However, what we could do is introducing a field-access wrapper function that does that edit -> update conversion for checking access on field collection *fields*.
Comment #12
RobW commentedThe main problem I see with the access check as it stands is it's being called with a ternary. You should be able to check field access without doing any logic in the function call.
The way I've set it up allows all possible ops for
field_accessandentity_access, since we're checking both infield_collection_item_access. If you'd prefer to restrict the values to just add, edit, and delete, I'm into it; I'd just like to see the logic being used in the ternary pulled inside of the function.Can you explain the idea behind a
field_accesswrapper function?Comment #13
RobW commentedActually, in this patch there's no code specifically targeting anything besides add, edit, and delete. If you want to accept only those, we can just edit the comments.
Thinking about targeting ops a little more, using the ternary turns any op argument besides "view" into "edit". It might be better to change this to:
I don't think it really matters; if you use a random string for the op link, entity access will return false (since it transforms the ops specifically, any non "view-add-edit-delete" string gets through). Just bringing it up for the hell of it.
Comment #14
fagoWe cannot only accept "add, edit, and delete", because the other operations are pre-defined for entities by the entity module (and the common $ops for entities) anyway. The mapping that has to happen for field collection exists because field-access and entity access use different $ops.
>Can you explain the idea behind a field_access wrapper function?
Sure. We could stay with the current entity-$ops for field_collection_item_access(), but add field_collection_field_access() which accepts the field $ops, so the ugly ternary check can live in there and is not necessary in the calling code anymore.
Comment #15
RobW commentedThe patch rewrites
field_collection_item_accessas a big wrapper function for bothentity_accessandfield_access. I'm not sure when there would be a need to check the field access for a field collection field without also checking the entity access for the field collection item, so I don't know if it's a good idea to add a separate function wrap that by itself.I think we might be trying to say the same things but with different words. If you can tell me what operations field
collection_item_accessshould take as arguments, I'll code it up.Comment #15.0
RobW commentedI should read twice and edit once...