Closed (fixed)
Project:
Drupal core
Version:
7.x-dev
Component:
field_ui.module
Priority:
Normal
Category:
Bug report
Assigned:
Reporter:
Created:
15 Mar 2010 at 00:42 UTC
Updated:
11 Apr 2010 at 11:10 UTC
Jump to comment: Most recent file
Comments
Comment #2
yched commentedjust subscribe for today :-(
Comment #3
yched commentedSee #614030-24: Cannot edit fields for taxonomy terms for an explanation on why $bundle arg in menu loaders are not usable :-(.
Comment #4
yched commentedThis is the crux of the issue :
You cannot use $bundle_name, because the same menu path will possibly be redefined for several bundles, thus only the $bundle_name for the last iteration of the 'foreach bundles' loop will be considered. You need to use $bundle_arg (the numeric position of the %bundle placeholder in the base $path).
Problem : in menu 'loader' callbacks, placeholders come as raw elements from the URL, not as 'elements as translated by the previous loader callbacks that have run for the path'. See #614030-3: Cannot edit fields for taxonomy terms
In short : field_ui_menu_load() won't receive a 'bundle name' it can understand, only the string that is in the path.
Powered by Dreditor.
Comment #5
sunHm. Not sure whether I'm able to follow you. :-/
In the meantime, #744258: admin/structure/taxonomy paths have to use machine_name, not vid contains an almost ready patch.
Does this mean we need to move back #617562: Remove underscore-to-dash conversion in path arguments for content types to D7? (I'd love to have a reason for that ;)
Comment #6
yched commentedPut a dsm($bundle_name) at the top of your field_ui_menu_load() func.
Then visit admin/structure/types/manage/article/fields/body (*article*)
You'll see that the func never receives 'article', but rather 'page'.
Node 'article' and 'page' bundles both set 'admin/structure/types/manage/%node_type' as their $entity_info['bundles'][$bundle_name]['admin']['path'].
Side note : Field API allows each bundle to specify its own admin path, even though in most cases it will be the same path (with a placeholder) for all bundles in a given entity type, because IIRC, when this code was written, node-type admin paths were precisely not using a placeholder for the node type, but separate menu items with hardcoded strings.
So the
foreach ($info['bundles'] as $bundle_name => $bundle_info) {loop in field_ui_menu() in fact redefines the *same* $items["admin/structure/types/manage/%node_type/fields/%field_ui_menu/..."] menu items several times for node bundles. So'load arguments' => array($entity_type, $bundle_name),in your patch just keeps the $bundle_name of the last loop iteration.The 'load argument' needs to be the index of the placeholder ($bundle_arg), so that the menu loader receives the actual string in the requested path.
But :
field_ui_menu_load() will then receive $bundle_name as "the string present in the path", not as "the $node_type object loaded by the node_type_load() menu loader that has previously run for the %node_type placeholder" : menu loaders don't learn from each other - sad. Field API doesn't know how to turn this string into a 'bundle name' it understands. Meaning : field_ui_menu_loader() currently cannot deal with bundles and instances.
After replacing $bundle_arg with $bundle_arg in your patch, visiting the edit page of a field on a taxonomy term brings a 404, because field_ui_menu_load() returns FALSE.
Bottomline is : having a module handle menu items built by appending to paths handled by a different module is a *pain*.
It's all a question of what constraints we deem reasonable to put on fieldable entities :
- your admin paths need to be the same menu item for all of your bundles, using a placeholder
- the actual menu path needs to contain the exact bundle name understood by Field API - problem : we already know this won't be the case for comments.
Comment #7
sunIf that's all needed to make you happy... only implemented for "$path/fields/%field_ui_menu" for now, because I have no idea how you thought of that object being used.
Comment #9
sunNo happy yched? :(
Comment #10
yched commentedYes, sorry, my time in front of the keyboard is really limited currently :-/.
Hard to follow, but #7 should work indeed. But then :
should be
Comment #11
yched commented[edited the snippet in my previous comment]
Comment #12
sunDid I mention that I love you? :)
Fully working patch + extensive docs to provide some reasoning.
Comment #13
yched commentedW00t ! So much love :-)
Great comments. Will try to actually test later today (er, tonight).
Why ? Is this for admin_menu ? Is this the only item that needs an explicit weight ?
147 critical left. Go review some!
Comment #14
sunThe weight is for the (usually last) "Delete" local task. Apparently, yes, those local tasks are not displayed currently - though I'm not really sure why that is. (separate issue)
Removed stale debug code, fixed comments and variable names ($bundle is not an "object"), and also: Moved comment_menu_alter() below comment_menu(), as I didn't recognize that it even exists... at the very bottom of the file...
Comment #15
yched commentedre #14: Those local tasks below $path/fields/%field_ui_menu (/edit, /field-settings, /widget-type, /delete) are in fact not displayed as 'local tabs'. They use MENU_LOCAL_TASK because it looks like the only way that those pages (e.g admin/structure/types/manage/article/fields/body/widget-type) keep the breadcrumb and primary tabs as 'context' - cf screenshots in #614030-12: Cannot edit fields for taxonomy terms to see what I mean.
I don't even understand how or why this use of MENU_LOCAL_TASK does the trick (I think it was quicksketch who wrote it that way when he worked on #516138: Move CCK HEAD in core), but I do know that any other way I tried fails...
So, as far as the current core Field UI is concerned, weights don't matter on those - could be different with admin_menu, though.
As for the patch :
- if $path/fields/%field_ui_menu uses a 'title callback', we can remove the manual drupal_set_title() in the page callback (field_ui_field_settings_form())
- why don't the other paths use a 'title callback' ? (the corresponding page callbacks also have a manual drupal_set_title() that can be removed if moving to a callback)
Other than that, RTBC for me.
Comment #16
yched commentedAdditional thoughts :
- Since you proved that field_ui_menu_load() can in fact receive and understand $bundles, then IMO it makes more sense to have it return an $instance rather than a $field. Those menu paths identify an (entity type + bundle + field name) triple, meaning : an instance. Plus getting a $field if you have an $instance is easy, but not the other way around.
- Then we don't need the $entity_type and $bundle_arg in 'title arguments' and 'page arguments', only $field_position (renamed $instance_position, I guess). The corresponding callbacks just receive an $instance instead of ($entity_type, $bundle, $field)
Comment #17
sunDone in attached patch.
Note, however: Is $instance['label'] already localized? I've slapped a t() on it + also took over the fallback to the (non-localized) field name if label is empty.
Comlicated area. The title callback is both used for the - here invisible (but not in admin_menu) - local tasks ("tabs"), but also for the page title when requesting that particular page.
For the common parent item, the field instance, we want the actual field label to appear both in menu link trees, but also as page title.
The dependent local tasks (edit, settings, widget, delete) are static and should not change (compare to node/%/edit, node/%/delete tabs).
Ugh, I already feared that you'd say that ;) - that basically means to revert the changes of #614030: Cannot edit fields for taxonomy terms, no?
Not sure about that. One important detail to keep in mind is: while we can pass additional arguments to menu loader functions, we can't make menu loader functions generate additional arguments that are passed to subsequent access/page/title/etc callbacks.
In other words, $instance is... - oh, now I get you. :) When reverting the changes of #614030, then our menu loader no longer returns a $field, but an $instance. Hence, all callbacks that specify $bundle_arg as callback argument will receive $instance in that place.
Comment #18
yched commentedYes, I changed from returning an $instance to returning a $field in #614030: Cannot edit fields for taxonomy terms just because I couldn't find a way to have the menu loader deal with bundles. You just made the loader smarter, so we can go back to the $instance.
Or rather : callback just need to specify $index_of_the_field_placeholder argument, and will receive an $instance, that contains all the other info (entitty type, bundle, field name). They don't need $bundle_arg and $entity_type as arguments.
Localisation : no, labels are not translated. Grey area, there's an issue about this somewhere :-(.
!empty($instance['label']) ? t($instance['label']) : $instance['field_name'];Actually, I don't think I see a case where $instance['label'] would be empty. That's a remnant from a previous state of the code, possibly D6, dunno for sure. I'd say we can ditch that fallback and fix later if it breaks.
Comment #19
yched commentedAs per #16-#18, updated patch builds on #14
- reverts the menu loader to return an $instance,
- adjusts 'page arguments' and 'title arguments', as well as the corresponding callbacks, accordingly.
Comment #20
yched commentedRerolled after #707724: Call them entities instead of objects ('object_type' -> 'entity_type')
Comment #21
sunAwesome! Sorry, I got sick the other day, which threw me off from the keyboard.
Comment #22
dries commentedCommitted to CVS HEAD. Thanks.