diff --git a/core/modules/field/field.module b/core/modules/field/field.module index 2ea923858b8..8e16741b510 100644 --- a/core/modules/field/field.module +++ b/core/modules/field/field.module @@ -454,6 +454,14 @@ function field_entity_field_info($entity_type) { return $property_info; } +/** + * Implements hook_field_widget_info_alter(). + */ +function field_field_widget_info_alter(&$info) { + // Add the Hidden widget to all field types. + $info['hidden']['field_types'] = array_keys(field_info_field_types()); +} + /** * Applies language fallback rules to the fields attached to the given entity. * diff --git a/core/modules/field/lib/Drupal/field/Plugin/Type/LegacyDiscoveryDecorator.php b/core/modules/field/lib/Drupal/field/Plugin/Type/LegacyDiscoveryDecorator.php index 43aad820e8b..1f94d7ca2f4 100644 --- a/core/modules/field/lib/Drupal/field/Plugin/Type/LegacyDiscoveryDecorator.php +++ b/core/modules/field/lib/Drupal/field/Plugin/Type/LegacyDiscoveryDecorator.php @@ -67,6 +67,9 @@ abstract class LegacyDiscoveryDecorator implements DiscoveryInterface { unset($definition['behaviors']['default value']); } + // Legacy widgets also need a plugin id. + $definition['id'] = $plugin_id; + $definitions[$plugin_id] = $definition; } } diff --git a/core/modules/field/lib/Drupal/field/Plugin/field/widget/HiddenWidget.php b/core/modules/field/lib/Drupal/field/Plugin/field/widget/HiddenWidget.php new file mode 100644 index 00000000000..d2ff3cbfd6d --- /dev/null +++ b/core/modules/field/lib/Drupal/field/Plugin/field/widget/HiddenWidget.php @@ -0,0 +1,34 @@ +assertFieldValues($entity_1, 'field_unlimited', LANGUAGE_NOT_SPECIFIED, array(3, 2)); $this->assertFieldValues($entity_2, 'field_unlimited', LANGUAGE_NOT_SPECIFIED, array(13, 14, 15)); } + + /** + * Tests the Hidden widget. + */ + function testFieldFormHiddenWidget() { + $this->field = $this->field_single; + $this->field_name = $this->field['field_name']; + $this->instance['field_name'] = $this->field_name; + $this->instance['widget']['type'] = 'hidden'; + $this->instance['default_value'] = array(0 => array('value' => 99)); + field_create_field($this->field); + field_create_instance($this->instance); + $langcode = LANGUAGE_NOT_SPECIFIED; + + // Display the entity creation form. + $this->drupalGet('test-entity/add/test_bundle'); + + // Create an entity and test that the default value is assigned correctly to + // the field that uses the hidden widget. + $this->assertNoField("{$this->field_name}[$langcode][0][value]", 'The hidden widget is not displayed'); + $this->drupalPost(NULL, array(), t('Save')); + preg_match('|test-entity/manage/(\d+)/edit|', $this->url, $match); + $id = $match[1]; + $this->assertRaw(t('test_entity @id has been created.', array('@id' => $id)), 'Entity was created'); + $entity = field_test_entity_test_load($id); + $this->assertEqual($entity->{$this->field_name}[$langcode][0]['value'], 99, 'Default value was saved'); + + // Update the instance to remove the default value and switch to the + // default widget. + $this->instance['default_value'] = NULL; + $this->instance['widget']['type'] = 'test_field_widget'; + field_update_instance($this->instance); + + // Display edit form. + $this->drupalGet('test-entity/manage/' . $id . '/edit'); + $this->assertFieldByName("{$this->field_name}[$langcode][0][value]", 99, 'Widget is displayed with the correct default value'); + + // Update the entity. + $value = mt_rand(1, 127); + $edit = array("{$this->field_name}[$langcode][0][value]" => $value); + $this->drupalPost(NULL, $edit, t('Save')); + $this->assertRaw(t('test_entity @id has been updated.', array('@id' => $id)), 'Entity was updated'); + entity_get_controller('test_entity')->resetCache(array($id)); + $entity = field_test_entity_test_load($id); + $this->assertEqual($entity->{$this->field_name}[$langcode][0]['value'], $value, 'Field value was updated'); + + // Update the instance and switch to the Hidden widget again. + $this->instance['widget']['type'] = 'hidden'; + field_update_instance($this->instance); + + // Create a new revision. + $edit = array('revision' => TRUE); + $this->drupalPost('test-entity/manage/' . $id . '/edit', $edit, t('Save')); + + // Check that the expected value has been carried over to the new revision. + entity_get_controller('test_entity')->resetCache(array($id)); + $entity = field_test_entity_test_load($id); + $this->assertEqual($entity->{$this->field_name}[$langcode][0]['value'], $value, 'New revision has the expected value for the field with the Hidden widget'); + } } diff --git a/core/modules/field_ui/field_ui.admin.inc b/core/modules/field_ui/field_ui.admin.inc index 31b4c39b6a4..d58cc60e730 100644 --- a/core/modules/field_ui/field_ui.admin.inc +++ b/core/modules/field_ui/field_ui.admin.inc @@ -691,6 +691,10 @@ function field_ui_widget_type_form_submit($form, &$form_state) { try { field_update_instance($instance); drupal_set_message(t('Changed the widget for field %label.', array('%label' => $instance['label']))); + + if ($instance['required'] && empty($instance['default_value']) && empty($instance['default_value_function']) && $instance['widget']['type'] == 'field_hidden') { + drupal_set_message(t('Field %label is required and uses the "hidden" widget. You might want to configure a default value.', array('%label' => $instance['label'])), 'warning'); + } } catch (Exception $e) { drupal_set_message(t('There was a problem changing the widget for field %label.', array('%label' => $instance['label'])), 'error'); @@ -934,6 +938,19 @@ function field_ui_default_value_widget($field, $instance, &$form, &$form_state) $instance['required'] = FALSE; $instance['description'] = ''; + // Adjust the instance definition to use the default widget of this field type + // instead of the hidden widget. + if ($instance['widget']['type'] == 'field_hidden') { + $field_type = field_info_field_types($field['type']); + $default_widget = field_info_widget_types($field_type['default_widget']); + + $instance['widget'] = array( + 'type' => $default_widget['id'], + 'settings' => $default_widget['settings'], + 'weight' => 0, + ); + } + // Insert the widget. Since we do not use the "official" instance definition, // the whole flow cannot use field_invoke_method(). $items = (array) $instance['default_value']; @@ -1013,6 +1030,10 @@ function field_ui_field_edit_form_submit($form, &$form_state) { drupal_set_message(t('Saved %label configuration.', array('%label' => $instance['label']))); + if ($instance['required'] && empty($instance['default_value']) && empty($instance['default_value_function']) && $instance['widget']['type'] == 'field_hidden') { + drupal_set_message(t('Field %label is required and uses the "hidden" widget. You might want to configure a default value.', array('%label' => $instance['label'])), 'warning'); + } + $form_state['redirect'] = field_ui_next_destination($instance['entity_type'], $instance['bundle']); }