#636834 by yched: Fixed field revision data when user has no 'edit' access on the field (with tests).

merge-requests/26/head
Angie Byron 2009-11-20 04:51:27 +00:00
parent 457a109406
commit 9b71489a48
3 changed files with 183 additions and 99 deletions

View File

@ -15,21 +15,13 @@ function field_default_form($obj_type, $object, $field, $instance, $langcode, $i
if ($object) {
list($id, , ) = entity_extract_ids($obj_type, $object);
}
$addition = array();
$field_name = $field['field_name'];
// If the field is not accessible, don't add anything. The field value will
// be left unchanged on update, or considered empty on insert (default value
// will be inserted if applicable).
if (!field_access('edit', $field, $obj_type, $object)) {
return $addition;
}
// Put field information at the top of the form, so that it can be easily
// retrieved.
// Note : widgets and other form handling code should *always* fetch
// field and instance information from $form['#fields'] rather than from
// Note : widgets and other form handling code should *always* fetch field
// and instance information from $form['#fields'] rather than from
// field_info_field(). This lets us build forms for 'variants' of a field,
// for instance on admin screens.
$form['#fields'][$field_name] = array(
@ -42,54 +34,58 @@ function field_default_form($obj_type, $object, $field, $instance, $langcode, $i
$items = field_get_default_value($obj_type, $object, $field, $instance, $langcode);
}
$form_element = array();
$field_elements = array();
// If field module handles multiple values for this form element,
// and we are displaying an individual element, process the multiple value
// form.
if (!isset($get_delta) && field_behaviors_widget('multiple values', $instance) == FIELD_BEHAVIOR_DEFAULT) {
$form_element = field_multiple_value_form($field, $instance, $langcode, $items, $form, $form_state);
}
// If the widget is handling multiple values (e.g Options),
// or if we are displaying an individual element, just get a single form
// element and make it the $delta value.
else {
$delta = isset($get_delta) ? $get_delta : 0;
$function = $instance['widget']['module'] . '_field_widget';
if (function_exists($function)) {
$element = array(
'#object_type' => $instance['object_type'],
'#bundle' => $instance['bundle'],
'#field_name' => $field_name,
'#columns' => array_keys($field['columns']),
'#title' => check_plain(t($instance['label'])),
'#description' => field_filter_xss($instance['description']),
// Only the first widget should be required.
'#required' => $delta == 0 && $instance['required'],
'#delta' => $delta,
);
if ($element = $function($form, $form_state, $field, $instance, $langcode, $items, $delta, $element)) {
// If we're processing a specific delta value for a field where the
// field module handles multiples, set the delta in the result.
// For fields that handle their own processing, we can't make assumptions
// about how the field is structured, just merge in the returned value.
if (field_behaviors_widget('multiple values', $instance) == FIELD_BEHAVIOR_DEFAULT) {
$form_element[$delta] = $element;
}
else {
$form_element = $element;
if (field_access('edit', $field, $obj_type, $object)) {
// If field module handles multiple values for this form element, and we
// are displaying an individual element, process the multiple value form.
if (!isset($get_delta) && field_behaviors_widget('multiple values', $instance) == FIELD_BEHAVIOR_DEFAULT) {
$field_elements = field_multiple_value_form($field, $instance, $langcode, $items, $form, $form_state);
}
// If the widget is handling multiple values (e.g Options), or if we are
// displaying an individual element, just get a single form element and
// make it the $delta value.
else {
$delta = isset($get_delta) ? $get_delta : 0;
$function = $instance['widget']['module'] . '_field_widget';
if (function_exists($function)) {
$element = array(
'#object_type' => $instance['object_type'],
'#bundle' => $instance['bundle'],
'#field_name' => $field_name,
'#columns' => array_keys($field['columns']),
'#title' => check_plain(t($instance['label'])),
'#description' => field_filter_xss($instance['description']),
// Only the first widget should be required.
'#required' => $delta == 0 && $instance['required'],
'#delta' => $delta,
);
if ($element = $function($form, $form_state, $field, $instance, $langcode, $items, $delta, $element)) {
// If we're processing a specific delta value for a field where the
// field module handles multiples, set the delta in the result.
// For fields that handle their own processing, we can't make
// assumptions about how the field is structured, just merge in the
// returned element.
if (field_behaviors_widget('multiple values', $instance) == FIELD_BEHAVIOR_DEFAULT) {
$field_elements[$delta] = $element;
}
else {
$field_elements = $element;
}
}
}
}
}
if ($form_element) {
// Add the field form element as a child keyed by language code to match the
// field data structure: $object->{$field_name}[$langcode][$delta][$column].
// The '#language' key can be used to access the field's form element when
// $langcode is unknown. The #weight property is inherited from the field's
// form element.
// Also aid in theming of field widgets by rendering a classified container.
if ($field_elements) {
// Add the field form element as a child keyed by language code to match
// the field data structure:
// $object->{$field_name}[$langcode][$delta][$column].
// The '#language' key can be used to access the field's form element
// when $langcode is unknown. The #weight property is inherited from the
// field's form element.
// Also aid in theming of field widgets by rendering a classified
// container.
$addition[$field_name] = array(
'#type' => 'container',
'#attributes' => array(
@ -102,11 +98,26 @@ function field_default_form($obj_type, $object, $field, $instance, $langcode, $i
'#tree' => TRUE,
'#weight' => $instance['widget']['weight'],
'#language' => $langcode,
$langcode => $form_element,
$langcode => $field_elements,
);
$form['#fields'][$field_name]['form_path'] = array($field_name);
}
else {
// The field is not accessible, or the widget did not return anything. Make
// sure the items are available in the submitted form values.
foreach ($items as $delta => $item) {
$field_elements[$delta] = array(
'#type' => 'value',
'#value' => $item,
);
}
$addition[$field_name] = array(
'#tree' => TRUE,
'#language' => $langcode,
$langcode => $field_elements,
);
}
$form['#fields'][$field_name]['form_path'] = array($field_name);
return $addition;
}
@ -122,6 +133,7 @@ function field_default_form($obj_type, $object, $field, $instance, $langcode, $i
function field_multiple_value_form($field, $instance, $langcode, $items, &$form, &$form_state) {
$field_name = $field['field_name'];
// Determine the number of widgets to display.
switch ($field['cardinality']) {
case FIELD_CARDINALITY_UNLIMITED:
$filled_items = field_set_empty($field, $items);
@ -141,20 +153,8 @@ function field_multiple_value_form($field, $instance, $langcode, $items, &$form,
$title = check_plain(t($instance['label']));
$description = field_filter_xss(t($instance['description']));
$wrapper_id = str_replace('_', '-', $field_name) . '-wrapper';
$form_element = array(
'#theme' => 'field_multiple_value_form',
'#field_name' => $field['field_name'],
'#cardinality' => $field['cardinality'],
'#title' => $title,
'#required' => $instance['required'],
'#description' => $description,
'#prefix' => '<div id="' . $wrapper_id . '">',
'#suffix' => '</div>',
'#max_delta' => $max,
);
$wrapper_id = drupal_html_class($field_name) . '-wrapper';
$field_elements = array();
$function = $instance['widget']['module'] . '_field_widget';
if (function_exists($function)) {
@ -186,34 +186,47 @@ function field_multiple_value_form($field, $instance, $langcode, $items, &$form,
'#weight' => 100,
);
}
$form_element[$delta] = $element;
$field_elements[$delta] = $element;
}
}
// Add 'add more' button, if not working with a programmed form.
if ($field['cardinality'] == FIELD_CARDINALITY_UNLIMITED && empty($form_state['programmed'])) {
$form_element['add_more'] = array(
'#type' => 'submit',
'#name' => $field_name . '_add_more',
'#value' => t('Add another item'),
'#attributes' => array('class' => array('field-add-more-submit')),
// Submit callback for disabled JavaScript.
'#submit' => array('field_add_more_submit'),
'#ajax' => array(
'callback' => 'field_add_more_js',
'wrapper' => $wrapper_id,
'method' => 'replace',
'effect' => 'fade',
),
// The field_add_more_submit() and field_add_more_js() handlers will
// find the relevant field using those entries.
'#field_name' => $field_name,
'#language' => $langcode,
if ($field_elements) {
$field_elements += array(
'#theme' => 'field_multiple_value_form',
'#field_name' => $field['field_name'],
'#cardinality' => $field['cardinality'],
'#title' => $title,
'#required' => $instance['required'],
'#description' => $description,
'#prefix' => '<div id="' . $wrapper_id . '">',
'#suffix' => '</div>',
'#max_delta' => $max,
);
// Add 'add more' button, if not working with a programmed form.
if ($field['cardinality'] == FIELD_CARDINALITY_UNLIMITED && empty($form_state['programmed'])) {
$field_elements['add_more'] = array(
'#type' => 'submit',
'#name' => $field_name . '_add_more',
'#value' => t('Add another item'),
'#attributes' => array('class' => array('field-add-more-submit')),
// Submit callback for disabled JavaScript.
'#submit' => array('field_add_more_submit'),
'#ajax' => array(
'callback' => 'field_add_more_js',
'wrapper' => $wrapper_id,
'method' => 'replace',
'effect' => 'fade',
),
// The field_add_more_submit() and field_add_more_js() handlers will
// find the relevant field using those entries.
'#field_name' => $field_name,
'#language' => $langcode,
);
}
}
}
return $form_element;
return $field_elements;
}
/**

View File

@ -1592,6 +1592,65 @@ class FieldFormTestCase extends FieldTestCase {
$this->assertNoField("$this->field_name[$langcode][" . ($delta + 1) . '][value]', 'No extraneous widget is displayed');
}
/**
* Tests fields with no 'edit' access.
*/
function testFieldFormAccess() {
// Create a "regular" field.
$field = $this->field_single;
$field_name = $field['field_name'];
$instance = $this->instance;
$instance['field_name'] = $field_name;
field_create_field($field);
field_create_instance($instance);
// Create a field with no edit access - see field_test_field_access().
$field_no_access = array(
'field_name' => 'field_no_edit_access',
'type' => 'test_field',
);
$field_name_no_access = $field_no_access['field_name'];
$instance_no_access = array(
'field_name' => $field_name_no_access,
'object_type' => 'test_entity',
'bundle' => 'test_bundle',
'default_value' => array(0 => array('value' => 99)),
);
field_create_field($field_no_access);
field_create_instance($instance_no_access);
$langcode = FIELD_LANGUAGE_NONE;
// Display creation form.
$this->drupalGet('test-entity/add/test-bundle');
$this->assertNoFieldByName("{$field_name_no_access}[$langcode][0][value]", '', t('Widget is not displayed if field access is denied.'));
// Create entity.
$edit = array("{$field_name}[$langcode][0][value]" => 1);
$this->drupalPost(NULL, $edit, t('Save'));
preg_match('|test-entity/(\d+)/edit|', $this->url, $match);
$id = $match[1];
// Check that the default value was saved.
$entity = field_test_entity_test_load($id);
$this->assertEqual($entity->{$field_name_no_access}[$langcode][0]['value'], 99, t('Default value was saved for the field with no edit access.'));
$this->assertEqual($entity->{$field_name}[$langcode][0]['value'], 1, t('Entered value vas saved for the field with edit access.'));
// Create a new revision.
$edit = array("{$field_name}[$langcode][0][value]" => 2, 'revision' => TRUE);
$this->drupalPost('test-entity/' . $id . '/edit', $edit, t('Save'));
// Check that the new revision has the expected values.
$entity = field_test_entity_test_load($id);
$this->assertEqual($entity->{$field_name_no_access}[$langcode][0]['value'], 99, t('New revision has the expected value for the field with no edit access.'));
$this->assertEqual($entity->{$field_name}[$langcode][0]['value'], 2, t('New revision has the expected value for the field with edit access.'));
// Check that the revision is also saved in the revisions table.
$entity = field_test_entity_test_load($id, $entity->ftvid);
$this->assertEqual($entity->{$field_name_no_access}[$langcode][0]['value'], 99, t('New revision has the expected value for the field with no edit access.'));
$this->assertEqual($entity->{$field_name}[$langcode][0]['value'], 2, t('New revision has the expected value for the field with edit access.'));
}
/**
* Execute a POST request on a AHAH callback.
*

View File

@ -49,6 +49,15 @@ function field_test_menu() {
return $items;
}
/**
* Implements hook_field_access().
*/
function field_test_field_access($op, $field, $obj_type, $object, $account) {
if ($field['field_name'] == "field_no_{$op}_access") {
return FALSE;
}
return TRUE;
}
/**
*
@ -312,7 +321,7 @@ function field_test_entity_add($fttype) {
$fttype = str_replace('-', '_', $fttype);
$entity = (object)array('fttype' => $fttype);
drupal_set_title(t('Create test_entity @bundle', array('@bundle' => $fttype)), PASS_THROUGH);
return drupal_get_form('field_test_entity_form', $entity);
return drupal_get_form('field_test_entity_form', $entity, TRUE);
}
function field_test_entity_edit($entity) {
@ -323,7 +332,7 @@ function field_test_entity_edit($entity) {
/**
* Form to set the value of fields attached to our entity.
*/
function field_test_entity_form($form, &$form_state, $entity) {
function field_test_entity_form($form, &$form_state, $entity, $add = FALSE) {
if (isset($form_state['test_entity'])) {
$entity = $form_state['test_entity'] + (array)$entity;
}
@ -340,13 +349,15 @@ function field_test_entity_form($form, &$form_state, $entity) {
$form['#builder_function'] = 'field_test_entity_form_submit_builder';
field_attach_form('test_entity', $entity, $form, $form_state);
$form['revision'] = array(
'#access' => user_access('administer field_test content'),
'#type' => 'checkbox',
'#title' => t('Create new revision'),
'#default_value' => FALSE,
'#weight' => 100,
);
if (!$add) {
$form['revision'] = array(
'#access' => user_access('administer field_test content'),
'#type' => 'checkbox',
'#title' => t('Create new revision'),
'#default_value' => FALSE,
'#weight' => 100,
);
}
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Save'),
@ -391,6 +402,7 @@ function field_test_entity_form_submit($form, &$form_state) {
*/
function field_test_entity_form_submit_builder($form, &$form_state) {
$entity = field_test_create_stub_entity($form_state['values']['ftid'], $form_state['values']['ftvid'], $form_state['values']['fttype']);
$entity->revision = !empty($form_state['values']['revision']);
field_attach_submit('test_entity', $entity, $form, $form_state);
$form_state['test_entity'] = (array)$entity;