This patch adds field locking support. It adds a locked column to the content_node_fields table and prevents locked fields from being added to content types, removed from content types, or having their configuration changed... Although it does allow fields to be re ordered and the display settings to be changed.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

yched’s picture

When we discussed locked fields at the data API sprint and / or in mail discussions with Karen and Eaton, we concluded that labels and widget type should also be changeable - maybe even everything that's instance-level.
Locked meaning : you can't change the nature of the field or do anything that alters its db storage (shared status, multiplicity, db columns)
With the approach in this patch, what's locked or not locked is a matter of where it sits in the UI. It currently "happens" that weight, fieldgrouping and display settings are set outside the field configure form, and so they are not locked, but that is just a consequence of the current organization of the UI.

Aside from this, only able to do a cursory review for now - sorry about that.

- hook_schema table definition is not altered with the new column
- technically, a locked field is not an 'extra field' (non cck 'field') - If we gray out locked fields, then we'd better rename #extra_field to something else.
- a single
if (!isset($type['fields'][$field['field_name']]) && !$field['locked']) {
would be more legible than

-    if (!isset($type['fields'][$field['field_name']]))
+    if (isset($type['fields'][$field['field_name']])) continue;
+    if ($field['locked']) continue;

- there's a typo in the validation error message : 'becuase it is locked' :-)

Aside

KarenS’s picture

Right, I think we all concluded it would be very heavy-handed to not even allow the label to be changed. One idea to make this work was to make 'locked' an array of the parts that are locked rather than a single on/off value. That makes the code more complex, of course, since you would presumably present the field edit screen, then use the locked array to show form elements for the unlocked values. The locked values would then either just be hidden fields, or display their values, or just add 'disabled' to those form elements (probably the easiest way to do this).

I'm working on Date and Calendar patches right now, so don't have much time to help with this, but let me know if you want anything and I'll try to swing back by this.

KarenS’s picture

There's another way to approach the locked elements, and I this is just off the top of my head so I don't know if it's a good or bad way to do it. Instead of storing lock information in the field, what about making a hook_field_lock() where any module could intervene to lock parts of a field or keep it off of the field list in the UI? Then any module could intervene in any field to lock a value, even if the field was created by the UI. Might be more flexible.

KarenS’s picture

Thinking more about #3 -- content module could then use hook_lock to prevent users from changing things that would alter the field database structure, something we talked about needing as we move fields into core.

dopry’s picture

FileSize
5.89 KB

@yched: I think I can address your issues... the conditional should actually be an || not an &&.
for the UI issues, yeah locking will need to happen at a UI level... any attempts at an API level will fail, we can't control db_query. So of course if UI changes... we need to change how the locking interacts with the UI.

re: per field vs per field_instance

we need to resolve the interchangable use of field and field_instance in CCK before that can be properly implemented... Which involves unique constructors for both fields and field_instances, renaming some variable here and there to make it more obvious which is being used in a particular case, and altering the field data model to make instance and global field data easily identifiable or altering the loaders to make sure settings are inherited from field or field_instance as necessary.

re: heavy handedness vs painting the bike shed.

Module developers need this functionality now. I think we can expect them to expose UI as necessary. Lets not hold it up with over engineering and squabbling over possibly necessary UI and practice some KISS here. The people who will be using this feature are module developers and install profile developers. I think they are perfectly capable of writing their own UI's to the configurable field features they want to expose.. They're even willing to, see drewish and dmitrig01.

eaton’s picture

I don't really have problems with locking the widget and label, at least in this iteration. While the ideal is always complete and total control, the biggest benefit of this patch is to allow modules to implement 'hard-coded' nodetypes, and use CCK fields to do it without the risk of everything blowing up. This functionality could certainly be refined going forward, but I think that there's a strong case to be made for only allowing ordering/formatter changes at first...

drewish’s picture

subscribing, i'm really looking forward to this. this + the field crud functions mean that i could ditch a big chuck of custom code from several of my modules. the thing i don't want to open up though is users screwing up the fields then asking for support. get it in locked down and then lets look at opening it back up.

yched’s picture

Right, we can always fine-tune what exactly gets locked later on.

Thanks dopry for updating the patch. Gave it a (short) run, looks ok to me.

Last nitpick :
- content_update_6004(), although trivial, could use a PHPdoc (all other update function have one)
- I don't get why return ''; is needed in _content_admin_field_add_existing_submit()
- can we avoid if (...) return;, if (...) continue; one-liners ?
The latter could be written

foreach ($fields as $field) {
  if (!isset($type['fields'][$field['field_name']]) && !$field['locked']) {
    $options[$field['field_name']] = t($field['widget']['label']) .' ('. $field['field_name'] .')';
  }
}

instead of

foreach ($fields as $field) {
  if (isset($type['fields'][$field['field_name']]) || $field['locked']) continue;
  $options[$field['field_name']] = t($field['widget']['label']) .' ('. $field['field_name'] .')';
}

(that's what I meant with && / || ...)

drewish’s picture

yched’s picture

heh - I had long forgotten that name...

yched’s picture

Also, the patch in #5 incorrectly removes the needed colspan=3 for the 'name' cell on non-cck fields (the descriptions could be long, and since the rest of the cells are empty we claim their screen estate)

yched’s picture

This should go in RC5, and RC5 shouldn't wait too long, so I'll try to update and commit shortly if dopry doesn't beat me to it.

yched’s picture

Status: Needs review » Fixed
FileSize
6.52 KB

I committed the attached patch.

Anyone feels like writing tests for this ?

dopry’s picture

/me swallows his obscene fear of nesting and lives with it.

write test cases... what are you crazy?

yched’s picture

FYI : http://drupal.org/node/297915#comment-975434
'locked' fields generate no settings form, and thus cannot be exported with content_copy's macros...
I removed them form the list of fields to be exported.

We need to find out how we want locked fields to behave wrt content_copy - I'm not sure they *should* be exportable / importable, actually.

Anonymous’s picture

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for two weeks with no activity.