This is weird, and I hope I explain it right...
I have a filefield formatter I've written as part of the Flashy module. For various reasons it is a multi-value formatter. This has led me to an interesting discovery that is manifesting itself as a bug. Specifically, multi-value filefield formatters in views do not work, at least as far as I can tell.
To wit, when using a single-value formatter or multi-value formatter through the normal node page, the $element parameter to the formatter is passed in properly. When loaded through a view. it is not. As near as I can tell, the problem is traced to content_format() in content.module and the filefield_field_sanitize() function.
The $item passed into content_format, either way, looks like this:
array(4) {
["fid"]=>
string(2) "59"
["list"]=>
string(1) "1"
["data"]=>
string(32) "a:1:{s:11:"description";s:0:"";}"
["#delta"]=>
int(0)
}
content_format() then, in the case of a single-value formatter, does this:
$items = array($item);
$function = $field['module'] .'_field';
if (function_exists($function)) {
$function('sanitize', $node, $field, $items, FALSE, FALSE);
}
while for a multi-value formatter it does this:
$items = $item;
$function = $field['module'] .'_field';
if (function_exists($function)) {
$function('sanitize', $node, $field, $items, FALSE, FALSE);
}
Note that $items is therefore different when it's passed into $function('sanitize'), which in this case ends up with filefield_field_sanitize in filefield_field.inc. However, that function is hard-coded to only be able to handle $items as an array, as its first line is:
foreach ($items as $delta => $item) {
It then checks $item['fid'], which won't exist if content_format() passed in the multi-value form, and it will therefore do no sanitizing/loading of the actual data, and then the formatter won't have the necessary data, and there will be a sad trombone playing.
Whatever the code path is for the non-views version, something else is handling that logic so that filefield_field_sanitize() gets the data it's expecting. I didn't bother tracing through that, as those parts of CCK scare me.
So the net result is that filefield_field_sanitize() cannot handle multi-value formatters through views, because CCK is feeding it a different data structure that it is not expecting. Fixing that bug I leave as an exercise for the reader/maintainer. :-)
Comment | File | Size | Author |
---|---|---|---|
#4 | cck-fix-views-multiple-formatters-413792-4.patch | 1.37 KB | yched |
#2 | multivalue-formatter-views.png | 160.44 KB | quicksketch |
Comments
Comment #1
quicksketchI answer your verbose (and excellent) report with equal verbosity. ;)
I don't think FileField's sanitize function is at fault for this problem, it looks like we're somehow not following the documentation for passing in parameters into content_format().
Like you said at first, with either a multivalue formatter or a single value formatter, the $item passed into content_format() is the same, a single file object. However, according to the PHP doc at the top of content_format() the $item variable should already be an array of items if the destination formatter is multivalue:
So $item should already be an array of $file objects, not a single file, and filefield_field_sanitize() shouldn't need to be changed at all.
Now we get into the Views integration. We need to know why CCK isn't getting an array of items and instead is only getting a single item. CCK already has a Views handler "content_handler_field_multiple" which properly calls content_format() with an array of items. My guess is that FileField needs to tell CCK (to tell Views) that FileFields should use the content_handler_field_multiple handler instead of the normal content_handler_field.
That's as far as I can discover currently, I'll take a look at FileField's filefield_field_settings_views_data() function to see if any adjustment needs to be made there.
Comment #2
quicksketchWell, upon further inspection I actually couldn't find anything wrong. In my installation (CCK 2.2, Views 2.3, FileField 3.x dev), everything does receive the proper parameters.
Setup:
- Create a new content type
- Add a multivalue FileField to the type
- Add some nodes with files attached
- Make a new view, add the "Content: [Label of Field] (field_[name_of_field])" field
- Ensure the "Group multiple values" checkbox is checked for this field. This option only shows up if the CCK field is multivalue. See screenshot.
- Select a multivalue formatter from the "Format" drop-down.
I didn't have any multivalue formatters around on my local, so I modified the default file formatter to be multivalue:
Then everything worked as expected. Multiple $file objects were passed into the $item parameter of content_format(), then filefield_field_sanitize(), then finally theme_filefield_formatter_default(). As far as I can tell, everything is working properly.
Comment #3
Crell CreditAttribution: Crell commentedSo after some further investigation with quicksketch, we are now blaming CCK. :-)
Here's the situation as we now see it:
content_format() in fact expects different data depending on whether the field is single or multi-value. However, Views only feeds multiple values to content_format() iff:
1) The field in question is set to multi-value.
2) The field in question is set to "group multiple values" in the view.
If one of those is not the case, then the field is treated as single-value by Views and content_format() is fed incorrect data.
But it's not views per se that's the issue, it appears. In fact, our current working theory is that it's in content_handler_field_multiple::render():
Just because a field isn't grouped doesn't mean that its formatter isn't still expecting grouped data. A group of one is still a group! I don't know why this hasn't come up before, but that's our working theory.
I'm not sure what the proper solution is, other than it being related to enhancing that check above to be smarter about when it should delegate behavior to the single-value rendering handler. How exactly it should do that, I don't know yet.
Comment #4
yched CreditAttribution: yched commentedDoes the attached patch fix it for you ?
Comment #5
Crell CreditAttribution: Crell commentedIt does indeed! Thanks, yched!
Comment #6
yched CreditAttribution: yched commentedCool, committed. Thanks for the detective work !
Comment #8
scottprive CreditAttribution: scottprive commentedUsing Drupal Core 6.20 and CCK 6.x-2.9 I have repeatedly hit this problem: Only the first field of a Multi-value item is output.
The problem persists even if I disable Devel and Themer, and flush all caches.
More precisely I should say - my problem matches this description perfectly, but it may be some other cause. The missing multi-fields are truly missing, as verified by a print_r to disk.
Here's the catch though - this only seems to happen in one content type or one view, once in a while (actually, this is the only content which utilizes multi-value, so it's not clear if it could be systemwide or if there is something "special" about this content and view, which was originally created around March 2009 using older Drupal modules, and the system since upgraded of course).
I am not sure what triggers this bad state for this content, but guess what fixes it for me?
If I change the field label from "Widget Label (fieldname)" to any of the other 2 choices, then save that field, and finally save the view itself. That fixes a particular field's display. (To completely fix all affected fields, I need to repeat the field-label "bump" on all of the fields, then save the View.)
Again, after "bumping" the fields' labels in Views Fields, then Saving the field, the content view will show it is repaired. All instances of the fields display.
Post CCK 2.2 you can still get a problem that has a similar nature.
In any case, if someone else hits this, try my workaround, and if it fixes it for you, please file a new issue.
(I suspect it is just my content or View having become corrupt, and so I'm not sure there is a real issue to file).