Discussing #571654: Revert node titles as fields brought up the fact that our 'display' API not in too good shape.
We currently have 3 functions : field_attach_view(), field_display_field(), field_format().
field_attach_view($obj_type, $object, $build_mode, $langcode)
Builds a render array for the fully themed fields (field.tpl.php, with label and multiple values) of a given object *in a given build mode, using the display options specified on the 'Display Fields' UI screens for the corresponding field instances*.
Use case: simple 'object view' in a given context (build mode)
Works fine, except rendering the array has been identified as rather slow, without obvious room for optimisation so far. See #438570: Field API conversion leads to lots of expensive function calls
Additionally, we have two API helper functions that are currently in an intermediate state, more or less direct ports from CCK D6, not up to date with latest D7 commits.
field_display_field($obj_type, $object, $field, $instance, $build_mode)
Builds a render array for a single, fully themed field (field.tpl.php, with label and multiple values) of a given object, *allowing you to specify the display settings to use* (by hacking the $instance and $build_mode params). Was introduced for Panels in CCK D6.
Sample use cases: single field in a block or a Panel component (display settings are specified within the panel settings).
TODO:
- the signature has poor DX, could probably use a simpler ($obj_type, $object, $field_name, $display_settings)
- needs to be adapted for TF (which language to display ?),
- needs to be updated with field_attach_prepare_view() (introduced in #493314: Add multiple hook for formatters)
field_format($obj_type, $object, $field, $item, $formatter_type, $formatter_settings)
Runs a single field value through a formatter (no label, no multiple values).
Sample use cases:
- custom node theming (although using granular render() should be much easier in D7, it doesn't fill all use cases)
- Views (multiple values are displayed separately, Views takes care of the label, display settings are specified within the View field settings)
TODO:
- unify signature with field_display_field : ($obj_type, $object, $field_name, $item, $display_settings)
?
- not impacted by TF (caller provides the actual $item to be displayed)
- needs to be updated with field_attach_prepare_view() (introduced in #493314: Add multiple hook for formatters)
- probably needs to return a render array instead of a HTML string
field_display_field() is possibly not an absolute requirement in core, but it's a bit touchy and tedious to leave for every contrib/custom module that needs it to reimplement. Having it in CCK allowed for better sync regarding code changes, but that's not so true now that we're in core.
field_format(), OTOH, is IMO a requirement, at least for templates compatibility.
It's also possible that code reuse could be enhanced, both functions currently need to duplicate some logic taken care of during the 'regular' field_attach_view() workflow (field access check, language logic, hook invocations...)
Comment | File | Size | Author |
---|---|---|---|
#42 | field_view_value.patch | 14.57 KB | yched |
#36 | field_view_value.patch | 14.55 KB | yched |
#35 | field_view_value.patch | 14.55 KB | yched |
#24 | fix-broken-drupal.patch | 526 bytes | David_Rothstein |
#18 | field_view_field-612894-18.patch | 19.38 KB | yched |
Comments
Comment #1
yched CreditAttribution: yched commentedClosed #491640: move field_view_field() to _field_invoke() single-field mode as 'won't fix' in the light of the above.
Comment #2
plachI repeat a question I made in #571654: Revert node titles as fields as here is more in topic: wouldn't making
field_attach_view()
work in single-field mode makefield_display_field()
useless?Comment #3
yched CreditAttribution: yched commentedsee my OP: field_attach_view() will take display settings saved in the $instance definition in the db. The intent of field_display_field() is to provide display settings on-the-fly, independently of whatever existing build modes or what's stored in the $instance definition. When displaying a field in a Panel pane, you want to specify the display settings within the Pane config screen, not in field UI 'Manage Display'.
Comment #4
plachOk, now it's clear. IMO the code shared between f_a_view() and f_display_field() is going to be so much that unifying them could be a good thing. Would it be so bad to add in the $options passed to f_a_v() the possiblity to pass a display settings data structure and make it work in single-field mode? In this scenario f_d_f() might become a simple wrapper just setting a couple of options, like _field_invoke_default().
Comment #5
plachIMO to proceed with this one we need to start from #571654-23: Revert node titles as fields.
Comment #6
yched CreditAttribution: yched commentedAttached patch tackles field_view_field().
API changes:
- field_view_field() is gone (was broken anyway), renamed to field_build_field() since it returns a renderable array.
(see patch for the full PHPdoc)
- hook_field_formatter_prepare_view() receives an array of display settings instead of previously a build mode for which they had to extract the display settings in $instance['display'][$build_mode] themselves.
Should affect very little existing code (rare hook). Only core implementation (taxonomy) didn't even use that param.
Internal changes:
- field_default_* functions involved in the 'display' workflow can accept a build_mode or (new) an array of custom display settings. Impacts field_default_prepare_view(), field_default_view().
- code in _field_info_prepare_instance() that massages 'display' settings for the current execution context factored out to a new _field_info_prepare_instance_display() helper. For consistency, same logic applied for widgets: new _field_info_prepare_instance_widget().
- fixes _field_invoke_multiple(), the $options param is not supposed to be passed to the invoked hooks. _field_invoke() doesn't do this.
Comment #8
yched CreditAttribution: yched commentedTypo in the new _field_info_prepare_instance_widget(). That one should pass.
Comment #9
yched CreditAttribution: yched commentedEasier tracking.
Comment #10
yched CreditAttribution: yched commentedRerolled + added some tests.
Comment #11
moshe weitzman CreditAttribution: moshe weitzman commentedLooks great.
Comment #12
yched CreditAttribution: yched commentedRerolled after the various formatter API refactorings.
The needed API changes to allow displaying a field using one-off custom display settings have been rolled in #652834: Field formatters as render arrays, so no additional API change here.
Also, reverted the renaming of field_view_field() to field_build_field(), as per the general direction in #658364: Does build/view/formatter terminology make sense?. Field API consistently uses 'view'.
Re moshe #11
1. I'd tend to agree, but core is currently much more consistent on 'renderable arrays'.
2. The explanation is given in the PHPdoc for _field_info_prepare_instance(): " Since the instance was last saved or updated, a number of things might have changed: widgets or formatters disabled, new settings expected, new build modes added...". I'm not sure it's worth repeating, those are internal helper functions.
3. Indeed. removed that hunk.
Comment #13
yched CreditAttribution: yched commentedOops 80 lines wrap.
Comment #14
yched CreditAttribution: yched commentedFixed duplicate call to field_info_field() in field_view_field().
Comment #15
sunSorry. I only found those minor issues. And I was quite surprised to find those even... yched, yched... XD
Aside from that, this patch looks RTBC.
Wrong list indentation. (second line should align with start of first line)
Please revert. :)
s/needs/need/
Strange wrapping here, just remove the wrapping.
Duplicate newline.
This review is powered by Dreditor.
Comment #16
yched CreditAttribution: yched commentedAh, yes, I must be tired :-p.
Updated patch.
Note this patch only deals with field_view_field() (return render array for fully themed 'field' with all values).
field_format() (apply a formatter on a single field value) is still TODO (doesn't have to go in in the same commit, though).
Comment #17
sunI pretend to have not seen this.
Hm... is this alter hook mismatch desired? Backwards compatibility?
(off-topic) This triggers the question whether 'full' shouldn't be 'default' in reality... not to be discussed here.
tumtetumm... I also didn't see this.
I'm on crack. Are you, too?
Comment #18
yched CreditAttribution: yched commentedLOL.
1) and 4) fixed.
Desired, because we want 3rd party modules to do the same alterations on one-off field displays than when a full object is rendered through field_attach_view().
I've been wondering this for quite a while. Technically I agree - then again: I'm not sure it should be the same as 'full'.
Do we want users to see 'Default' instead of 'Full node' when they want to configure the fields display for the main node page ?
Different issue indeed. Right now this patch is consistent on that aspect with what currently happens when a displaying a build mode the user has not configured yet - see
// Fallback to 'full' display settings for unspecified build modes
in _field_info_prepare_instance() .Comment #19
yched CreditAttribution: yched commentedAdded a comment about hook_field_attach_view_alter()
Comment #20
Dries CreditAttribution: Dries commentedThis looks like an important clean-up, and inspecting the code didn't yield any red flags. Committed to CVS HEAD. Thanks.
Comment #21
yched CreditAttribution: yched commentedThks Dries. As per #16, reopening for the 2nd part - field_format().
re sun #17: "This triggers the question whether 'full' shouldn't be 'default' in reality". Opened #664544: Clean-up entity build/view modes
Comment #22
cburschkaThis patch has introduced a parsing error on line 362 of field.info.inc, caused by a missing slash in front of a phpdoc section; setting to NW.
Comment #23
cburschkaSlipped.
Comment #24
David_Rothstein CreditAttribution: David_Rothstein commentedJust came across the same problem.
Comment #25
carlos8f CreditAttribution: carlos8f commented@David_Rothstein: beat me to it by a few seconds :)
Comment #26
Dries CreditAttribution: Dries commentedCommitted to CVS HEAD. Thanks!
Comment #27
yched CreditAttribution: yched commentedOops. Sorry 'bout that. We sure miss the bot :-p.
Back to active for the remaining task.
Comment #28
sun.core CreditAttribution: sun.core commentedWhat's the "remaining task", and, can that be critical? :) Separate issue, perhaps?
Comment #29
yched CreditAttribution: yched commentedCritical as in "the current field_format() function is just a pile of code that simply doesn't work".
Comment #30
catchRe-titling.
Comment #31
webchickLOL :)
Could you re-title it again with some kind of an indication on how someone so-inclined could help?
Comment #32
catch@webchick - it's described in the opening post, I don't think a one sentence description can describe that any better than the current one.
Comment #33
yched CreditAttribution: yched commentedI have some code, will try to polish and post a patch asap. Tough week ahead.
Comment #34
chx CreditAttribution: chx commentedCan someone remind me why do we need field_format if field_view_field works..?
Comment #35
yched CreditAttribution: yched commentedSorry for not chiming in earlier, RL struck hard the last couple weeks.
field_view_field() returns a render array for a fully themed field ('#theme' => 'field'), with wrapping HTML, label, multiple values and RDF data - just like you'd find in a displayed node. Views (at least in D6) only displays individual field values, and takes care of the wrapping HTML and label display using its own mechanisms.
Also, theme('field') adds a non-negligible overhead vs. simply displaying a formatted field value. This was battled for months in #438570: Field API conversion leads to lots of expensive function calls and #659788: [meta issue] theme('field') is too slow, which is inhibiting its more widespread use; effulgentsia mitigated this in a awesome way in #652246: Optimize theme('field') and use it for comment body, but the cost is not negligible still.
So saying 'render this field, just hide the label', when all you want is just to run a given field value through a given formatter, is very unefficient. Would make a noticeable difference on a View displaying 10 entities with possibly 10 "field values" each.
However, it is doable to rely on field_view_field() to generate the render array for the whole field, and just grab the subpart we need, containing the render array for the specific value we want, as returned by the formatter. We reuse (not-so-simple) code, and the time spent in generating the wrapping array is negligible.
Attached patch does that
+ renames the function from field_format() (D7 only, never worked) to field_view_value(), for consistency with field_view_field()
+ adds tests for the function.
This field_view_value() won't give you the RDF wrapping, BTW. I'm not sure how Views wants to behave regarding RDF output, but I don't think it can afford the overhead of a full field theme "just" to get RDF data. IMO Views will need to add RDF data on its own (it will probably need to find a generic, Field + non-Field way to do so, I guess)
Comment #36
yched CreditAttribution: yched commentedfix coding style
Comment #37
catchThis looks great. There's no API change, yched's explanation makes sense as to the distinction, tests pass, code looks good.
Comment #38
plach@yched: is
field_view_value()
language-agnostic, isn't it? I suppose I don't need to update #657972: Make field fallback logic actually reusable to reflect the latest changes here, right?Comment #39
plachIs this correct or was this meant to be
$output['#access'] = $elements['#access']
?Powered by Dreditor.
Comment #40
catchwhoah missed that one, whatever it's supposed to be, it can't be that.
Comment #41
yched CreditAttribution: yched commented#access : indeed :-). Fixed.
re @plach #39: $item param in field_view_value() is already a value in a given language (e.g taken from some $entity->field_foo[$some_lang][$some_delta]). The $langcode param is there as a hint, because some formatters need to know the language of the value being rendered, and this is not available in the $item itself. So, yes, in a sense it's language agnostic.
Yet the code internally sticks the $item in a fake $cloned object to call field_view_field(), and thus relies on field_multilingual_available_languages() to determine the $langcode that will be used down the line in _field_invoke(). Whatever #657972: Make field fallback logic actually reusable refactors around there will need to be reflected here.
Comment #42
yched CreditAttribution: yched commentedforgot the fixed patch.
Comment #44
plach#42: field_view_value.patch queued for re-testing.
Comment #45
plachGreen. Setting back to RTBC.
Comment #46
yched CreditAttribution: yched commentedLooks like Dries committed this earlier tonight.
Comment #47
plachUpdated #657972-39: Make field fallback logic actually reusable to handle
field_view_value()
.Comment #49
Gábor HojtsyLooks like this was not documented in the upgrade guide, although the previous comments mentioned D6 code was using this function.
Comment #50
catchComment #51
yched CreditAttribution: yched commentedWell, the upgrade guide doesn't mention any of the CCK D6 API funcs that have changed names while moving to fields.module D7...
Comment #52
Gábor HojtsyOk, well, if that is something to discover personally for everyone, then this does not need documentation either.
Comment #53
catchProbably this needs to go in http://drupal.org/node/443536, with a link from update/6/7
There may be a point where we want to document 7-7 API changes on the overview page, I'd think at least from beta would be good, but that needs its own issue IMO.
Comment #54
plachJust a notice: I linked the translatable fields documentation from the D6/D7 upgrade guide as it's a completely new bunch of code that needs to be taken into account when upgrading modules. I'd say this applies to many other parts of the Field API code including this one.
Anyway, I ain't sure yched wants to document this himself so unassigning.
Comment #55
jhodgdonupdating tag to new scheme for the upgrade guides
Comment #56
mcfilms CreditAttribution: mcfilms commented_field_info_prepare_instance_widget() was throwing errors in RC1 and continues to do so in RC1. If I clear the cache I get:
Notice: Undefined index: module in _field_info_prepare_instance_widget() (line 385 of /home/everlast/public_html/take5/modules/field/field.info.inc).
This is not a D6 to D7 upgrade. It is a site built on drupal 7.0-beta2 and upgraded twice.
Comment #57
yched CreditAttribution: yched commented@mcfilms : This is not related to the current thread. Could you open a separate issue ?
+ marking as 'fixed'.
This does not belong to the 6/7 upgrade page, the field_view_field() function had no equivalent in core D6.
Comment #58
jhodgdonIt was marked as update guide because of #53 and #54. Are those wrong?
Comment #59
mcfilms CreditAttribution: mcfilms commented@yched
I have done as you suggested and opened a new issue at:
http://drupal.org/node/1001060
There aren't too may issues with _field_info_prepare_instance_widget() and I noted that a patch for this was presented here and thought this may be the culprit.
Comment #60
jhodgdonSo... Somewhere up there, someone (#53, catch) said this might need to go into the Field API pages in the Handbook. Has that been done?
http://drupal.org/node/443536
Adding the generic Needs Doc tag until that question is resolved. Agreed this doesn't need to be in the 6/7 upgrade guide, as that guide does not cover how to upgrade from contrib (CCK) to core.
Comment #61
antiorario CreditAttribution: antiorario commentedIt seems to me that, in its current state, field_views_value() doesn't work. Please check out http://drupal.org/node/1017850#comment-4528334 and following comment for a possible solution.Never mind that.