#636834 by yched: Fixed field revision data when user has no 'edit' access on the field (with tests).
parent
457a109406
commit
9b71489a48
|
@ -15,21 +15,13 @@ function field_default_form($obj_type, $object, $field, $instance, $langcode, $i
|
||||||
if ($object) {
|
if ($object) {
|
||||||
list($id, , ) = entity_extract_ids($obj_type, $object);
|
list($id, , ) = entity_extract_ids($obj_type, $object);
|
||||||
}
|
}
|
||||||
$addition = array();
|
|
||||||
|
|
||||||
$field_name = $field['field_name'];
|
$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
|
// Put field information at the top of the form, so that it can be easily
|
||||||
// retrieved.
|
// retrieved.
|
||||||
// Note : widgets and other form handling code should *always* fetch
|
// Note : widgets and other form handling code should *always* fetch field
|
||||||
// field and instance information from $form['#fields'] rather than from
|
// and instance information from $form['#fields'] rather than from
|
||||||
// field_info_field(). This lets us build forms for 'variants' of a field,
|
// field_info_field(). This lets us build forms for 'variants' of a field,
|
||||||
// for instance on admin screens.
|
// for instance on admin screens.
|
||||||
$form['#fields'][$field_name] = array(
|
$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);
|
$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,
|
if (field_access('edit', $field, $obj_type, $object)) {
|
||||||
// and we are displaying an individual element, process the multiple value
|
// If field module handles multiple values for this form element, and we
|
||||||
// form.
|
// are displaying an individual element, process the multiple value form.
|
||||||
if (!isset($get_delta) && field_behaviors_widget('multiple values', $instance) == FIELD_BEHAVIOR_DEFAULT) {
|
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);
|
$field_elements = field_multiple_value_form($field, $instance, $langcode, $items, $form, $form_state);
|
||||||
}
|
}
|
||||||
// If the widget is handling multiple values (e.g Options),
|
// If the widget is handling multiple values (e.g Options), or if we are
|
||||||
// or if we are displaying an individual element, just get a single form
|
// displaying an individual element, just get a single form element and
|
||||||
// element and make it the $delta value.
|
// make it the $delta value.
|
||||||
else {
|
else {
|
||||||
$delta = isset($get_delta) ? $get_delta : 0;
|
$delta = isset($get_delta) ? $get_delta : 0;
|
||||||
$function = $instance['widget']['module'] . '_field_widget';
|
$function = $instance['widget']['module'] . '_field_widget';
|
||||||
if (function_exists($function)) {
|
if (function_exists($function)) {
|
||||||
$element = array(
|
$element = array(
|
||||||
'#object_type' => $instance['object_type'],
|
'#object_type' => $instance['object_type'],
|
||||||
'#bundle' => $instance['bundle'],
|
'#bundle' => $instance['bundle'],
|
||||||
'#field_name' => $field_name,
|
'#field_name' => $field_name,
|
||||||
'#columns' => array_keys($field['columns']),
|
'#columns' => array_keys($field['columns']),
|
||||||
'#title' => check_plain(t($instance['label'])),
|
'#title' => check_plain(t($instance['label'])),
|
||||||
'#description' => field_filter_xss($instance['description']),
|
'#description' => field_filter_xss($instance['description']),
|
||||||
// Only the first widget should be required.
|
// Only the first widget should be required.
|
||||||
'#required' => $delta == 0 && $instance['required'],
|
'#required' => $delta == 0 && $instance['required'],
|
||||||
'#delta' => $delta,
|
'#delta' => $delta,
|
||||||
);
|
);
|
||||||
if ($element = $function($form, $form_state, $field, $instance, $langcode, $items, $delta, $element)) {
|
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
|
// If we're processing a specific delta value for a field where the
|
||||||
// field module handles multiples, set the delta in the result.
|
// field module handles multiples, set the delta in the result.
|
||||||
// For fields that handle their own processing, we can't make assumptions
|
// For fields that handle their own processing, we can't make
|
||||||
// about how the field is structured, just merge in the returned value.
|
// assumptions about how the field is structured, just merge in the
|
||||||
if (field_behaviors_widget('multiple values', $instance) == FIELD_BEHAVIOR_DEFAULT) {
|
// returned element.
|
||||||
$form_element[$delta] = $element;
|
if (field_behaviors_widget('multiple values', $instance) == FIELD_BEHAVIOR_DEFAULT) {
|
||||||
}
|
$field_elements[$delta] = $element;
|
||||||
else {
|
}
|
||||||
$form_element = $element;
|
else {
|
||||||
|
$field_elements = $element;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($form_element) {
|
if ($field_elements) {
|
||||||
// Add the field form element as a child keyed by language code to match the
|
// Add the field form element as a child keyed by language code to match
|
||||||
// field data structure: $object->{$field_name}[$langcode][$delta][$column].
|
// the field data structure:
|
||||||
// The '#language' key can be used to access the field's form element when
|
// $object->{$field_name}[$langcode][$delta][$column].
|
||||||
// $langcode is unknown. The #weight property is inherited from the field's
|
// The '#language' key can be used to access the field's form element
|
||||||
// form element.
|
// when $langcode is unknown. The #weight property is inherited from the
|
||||||
// Also aid in theming of field widgets by rendering a classified container.
|
// field's form element.
|
||||||
|
// Also aid in theming of field widgets by rendering a classified
|
||||||
|
// container.
|
||||||
$addition[$field_name] = array(
|
$addition[$field_name] = array(
|
||||||
'#type' => 'container',
|
'#type' => 'container',
|
||||||
'#attributes' => array(
|
'#attributes' => array(
|
||||||
|
@ -102,11 +98,26 @@ function field_default_form($obj_type, $object, $field, $instance, $langcode, $i
|
||||||
'#tree' => TRUE,
|
'#tree' => TRUE,
|
||||||
'#weight' => $instance['widget']['weight'],
|
'#weight' => $instance['widget']['weight'],
|
||||||
'#language' => $langcode,
|
'#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;
|
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) {
|
function field_multiple_value_form($field, $instance, $langcode, $items, &$form, &$form_state) {
|
||||||
$field_name = $field['field_name'];
|
$field_name = $field['field_name'];
|
||||||
|
|
||||||
|
// Determine the number of widgets to display.
|
||||||
switch ($field['cardinality']) {
|
switch ($field['cardinality']) {
|
||||||
case FIELD_CARDINALITY_UNLIMITED:
|
case FIELD_CARDINALITY_UNLIMITED:
|
||||||
$filled_items = field_set_empty($field, $items);
|
$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']));
|
$title = check_plain(t($instance['label']));
|
||||||
$description = field_filter_xss(t($instance['description']));
|
$description = field_filter_xss(t($instance['description']));
|
||||||
|
$wrapper_id = drupal_html_class($field_name) . '-wrapper';
|
||||||
$wrapper_id = str_replace('_', '-', $field_name) . '-wrapper';
|
$field_elements = array();
|
||||||
|
|
||||||
$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,
|
|
||||||
);
|
|
||||||
|
|
||||||
$function = $instance['widget']['module'] . '_field_widget';
|
$function = $instance['widget']['module'] . '_field_widget';
|
||||||
if (function_exists($function)) {
|
if (function_exists($function)) {
|
||||||
|
@ -186,34 +186,47 @@ function field_multiple_value_form($field, $instance, $langcode, $items, &$form,
|
||||||
'#weight' => 100,
|
'#weight' => 100,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
$form_element[$delta] = $element;
|
$field_elements[$delta] = $element;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add 'add more' button, if not working with a programmed form.
|
if ($field_elements) {
|
||||||
if ($field['cardinality'] == FIELD_CARDINALITY_UNLIMITED && empty($form_state['programmed'])) {
|
$field_elements += array(
|
||||||
$form_element['add_more'] = array(
|
'#theme' => 'field_multiple_value_form',
|
||||||
'#type' => 'submit',
|
'#field_name' => $field['field_name'],
|
||||||
'#name' => $field_name . '_add_more',
|
'#cardinality' => $field['cardinality'],
|
||||||
'#value' => t('Add another item'),
|
'#title' => $title,
|
||||||
'#attributes' => array('class' => array('field-add-more-submit')),
|
'#required' => $instance['required'],
|
||||||
// Submit callback for disabled JavaScript.
|
'#description' => $description,
|
||||||
'#submit' => array('field_add_more_submit'),
|
'#prefix' => '<div id="' . $wrapper_id . '">',
|
||||||
'#ajax' => array(
|
'#suffix' => '</div>',
|
||||||
'callback' => 'field_add_more_js',
|
'#max_delta' => $max,
|
||||||
'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,
|
|
||||||
);
|
);
|
||||||
|
// 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1592,6 +1592,65 @@ class FieldFormTestCase extends FieldTestCase {
|
||||||
$this->assertNoField("$this->field_name[$langcode][" . ($delta + 1) . '][value]', 'No extraneous widget is displayed');
|
$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.
|
* Execute a POST request on a AHAH callback.
|
||||||
*
|
*
|
||||||
|
|
|
@ -49,6 +49,15 @@ function field_test_menu() {
|
||||||
return $items;
|
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);
|
$fttype = str_replace('-', '_', $fttype);
|
||||||
$entity = (object)array('fttype' => $fttype);
|
$entity = (object)array('fttype' => $fttype);
|
||||||
drupal_set_title(t('Create test_entity @bundle', array('@bundle' => $fttype)), PASS_THROUGH);
|
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) {
|
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.
|
* 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'])) {
|
if (isset($form_state['test_entity'])) {
|
||||||
$entity = $form_state['test_entity'] + (array)$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';
|
$form['#builder_function'] = 'field_test_entity_form_submit_builder';
|
||||||
field_attach_form('test_entity', $entity, $form, $form_state);
|
field_attach_form('test_entity', $entity, $form, $form_state);
|
||||||
|
|
||||||
$form['revision'] = array(
|
if (!$add) {
|
||||||
'#access' => user_access('administer field_test content'),
|
$form['revision'] = array(
|
||||||
'#type' => 'checkbox',
|
'#access' => user_access('administer field_test content'),
|
||||||
'#title' => t('Create new revision'),
|
'#type' => 'checkbox',
|
||||||
'#default_value' => FALSE,
|
'#title' => t('Create new revision'),
|
||||||
'#weight' => 100,
|
'#default_value' => FALSE,
|
||||||
);
|
'#weight' => 100,
|
||||||
|
);
|
||||||
|
}
|
||||||
$form['submit'] = array(
|
$form['submit'] = array(
|
||||||
'#type' => 'submit',
|
'#type' => 'submit',
|
||||||
'#value' => t('Save'),
|
'#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) {
|
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 = 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);
|
field_attach_submit('test_entity', $entity, $form, $form_state);
|
||||||
|
|
||||||
$form_state['test_entity'] = (array)$entity;
|
$form_state['test_entity'] = (array)$entity;
|
||||||
|
|
Loading…
Reference in New Issue