content_field_form() does (simplified):

$element = $widget_function($form, $form_state, $field, $items, $delta);
$defaults = array(
  '#required' => $get_delta > 0 ? FALSE : $field['required'],
  '#columns'  => array_keys($field['columns']),
  '#title' => $title,
  '#description' => $description,
  '#delta' => $delta,
  '#field_name' => $field['field_name'],
  '#type_name' => $field['type_name'],
);
$form_element = array_merge($element, $defaults);

This array_merge() means that defaults value will override anything that is set by the widget function. I think this should be changed in a simple += operation, so that widgets can implement some special treatment for those fields. For example: define a field that have a special title or a special definition depending on the form.

Comments

Crell’s picture

As someone doing totally weird things with widgets right now, I am totally +1 on this change. Let the widget author win if they know what they're doing.

yched’s picture

Category: bug » feature
Status: Active » Postponed (maintainer needs more info)

Let the widget author win if they know what they're doing.
Hm,, actually 2 years of handling CCK queue and pulling hairs trying to figure out weird bug reports, possibly related to field modules I'm not extensively familiar with, really tend to make me go for the opposite - enforce consistency, provide safeguards, and open up only what's strictly required...

In this specific case, enforcing our own values is definitely the intended behavior. Most of those values (columns, delta, field_name...) are required for internal reasons and making them freely changeable would open the door for unpredictible portions of hell breaking loose.
For the others (description, title...), I guess this could be discussed, but that would be a case-by-case battle, and would need to be backed with good use cases :-)

So, changing to 'feat. request', and 'needs more info'...

Crell’s picture

OK, here's my use case:

I am (as we speak, actually) working on a custom widget for text fields. This widget is like a normal text field but provides an autocomplete callback and other "suggestion" functionality that is organic groups-sensitive. Another feature that it needs is to be able to set the label of the widget per-OG. That is, when applied to page nodes in OG A its label is "Topic", but when applied to page nodes in OG B its label is "Location".

This is a port to CCK of a custom D5 module I had written. I'm moving it to CCK because doing so seems easier than trying to get a straight port working, because it's being all kinda weird. :-) I figure letting CCK do the hard work makes more sense.

If there's some better solution than form alter already, I'm open to that, too.

markus_petrux’s picture

One possible approach could be changing the code in content_field_form() to enforce critical attributes only, but still let the widget author win for attributes such as #title, #description, ... ¿? ...so there would be += and array_merge, not just one or the other.

yched’s picture

Crell : I hate to ask, but isn't this just a case of the label being different in two dufferent content types ? CCK lets you do that already, the label is a 'per content type' property (although the UI currently doesn't make this really clear)

Crell’s picture

@yched: No, it's not different by content type. It's different based on the Group node that is the active Group context. So a Foo node that is attached to Group node A will have a label "Location" while a Foo node that is attached to Group node B will have a label "Topic".

markus_petrux’s picture

The following would allow the widget win for just a few attributes that are not specially critical.

$modifiable_defaults = array(
  '#title' => $title,
  '#description' => $description,
);
$forced_defaults = array(
  '#required' => $get_delta > 0 ? FALSE : $field['required'],
  '#columns'  => array_keys($field['columns']),
  '#delta' => $delta,
  '#field_name' => $field['field_name'],
  '#type_name' => $field['type_name'],
);
$form_element = array_merge($modifiable_defaults, $element, $forced_defaults);