diff --git a/core/includes/entity.inc b/core/includes/entity.inc index c0e97d2..aea51fc 100644 --- a/core/includes/entity.inc +++ b/core/includes/entity.inc @@ -812,7 +812,7 @@ function entity_get_form_display($entity_type, $bundle, $form_mode = 'default') * @param \Drupal\Core\Entity\EntityInterface $entity * The entity for which the form is being rendered. * @param string $form_mode - * The form mode being rendered. + * The form mode being rendered. * * @return \Drupal\entity\Plugin\Core\Entity\EntityFormDisplay * The form display object that should be used to render the entity form. diff --git a/core/lib/Drupal/Core/Entity/EntityFormController.php b/core/lib/Drupal/Core/Entity/EntityFormController.php index 796c1f2..6a761a9 100644 --- a/core/lib/Drupal/Core/Entity/EntityFormController.php +++ b/core/lib/Drupal/Core/Entity/EntityFormController.php @@ -107,7 +107,6 @@ public function form(array $form, array &$form_state, EntityInterface $entity) { // If the form did not specify otherwise, default to keeping the existing // language of the entity or defaulting to the site default language for // new entities. - $entity = $entity->getBCEntity(); $form['langcode'] = array( '#type' => 'value', '#value' => !$entity->isNew() ? $entity->langcode : language_default()->langcode, diff --git a/core/lib/Drupal/Core/Entity/EntityFormControllerNG.php b/core/lib/Drupal/Core/Entity/EntityFormControllerNG.php index 6b106c6..334f07a 100644 --- a/core/lib/Drupal/Core/Entity/EntityFormControllerNG.php +++ b/core/lib/Drupal/Core/Entity/EntityFormControllerNG.php @@ -23,11 +23,34 @@ class EntityFormControllerNG extends EntityFormController { * Overrides EntityFormController::form(). */ public function form(array $form, array &$form_state, EntityInterface $entity) { - parent::form($form, $form_state, $entity); + // @todo Exploit the Field API to generate the default widgets for the + // entity properties. + $info = $entity->entityInfo(); + if (!empty($info['fieldable'])) { + // Get the entity_form_display object for this form mode (operation). + $form_display = entity_get_render_form_display($entity, $this->operation); + + // Let modules alter the form display. + $form_display_context = array( + 'entity_type' => $entity->entityType(), + 'bundle' => $entity->bundle(), + 'form_mode' => $this->operation, + ); + drupal_alter('entity_form_display', $form_display, $form_display_context); + + // Persist the altered form display in $form_state so we can use it during + // validation and submit. + $form_state['form_display'] = $form_display; - // The only difference between this method and its parent seems to be this - // 'langcode' form element, so unset it. - unset($form['langcode']); + field_attach_form($entity->getBCEntity(), $form, $form_state, $this->getFormLangcode($form_state)); + + // Assign the weights configured in the form display. + foreach ($form_display->getComponents() as $name => $options) { + if (isset($form[$name])) { + $form[$name]['#weight'] = $options['weight']; + } + } + } return $form; } diff --git a/core/modules/field/field.attach.inc b/core/modules/field/field.attach.inc index 0fe5114..04c231e 100644 --- a/core/modules/field/field.attach.inc +++ b/core/modules/field/field.attach.inc @@ -1124,7 +1124,13 @@ function field_attach_form_validate(EntityInterface $entity, $form, &$form_state */ function field_attach_extract_form_values(EntityInterface $entity, $form, &$form_state, array $options = array()) { // Extract field values from submitted values. - $form_display = $form_state['form_display']; + if (isset($form_state['form_display'])) { + $form_display = $form_state['form_display']; + } + else { + // @todo Remove this hack when http://drupal.org/node/1856556 is fixed. + $form_display = $form_state['form_display'] = entity_get_form_display($entity->entityType(), $entity->entityType()); + } field_invoke_method('extractFormValues', _field_invoke_widget_target($form_display), $entity, $form, $form_state, $options); // Let other modules act on submitting the entity. diff --git a/core/modules/field/lib/Drupal/field/Plugin/Core/Entity/FieldInstance.php b/core/modules/field/lib/Drupal/field/Plugin/Core/Entity/FieldInstance.php index b732c22..0270374 100644 --- a/core/modules/field/lib/Drupal/field/Plugin/Core/Entity/FieldInstance.php +++ b/core/modules/field/lib/Drupal/field/Plugin/Core/Entity/FieldInstance.php @@ -393,6 +393,11 @@ public function delete($field_cleanup = TRUE) { // hook_field_delete_instance(). $module_handler->invokeAll('field_delete_instance', array($this)); + // Remove the instance from the entity form displays. + if ($form_display = entity_load('entity_form_display', $this->entity_type . '.' . $this->bundle . '.default')) { + $form_display->removeComponent($this->field_name)->save(); + } + // Delete the field itself if we just deleted its last instance. if ($field_cleanup && count($field->getBundles()) == 0) { $field->delete(); diff --git a/core/modules/field/lib/Drupal/field/Tests/FieldAttachOtherTest.php b/core/modules/field/lib/Drupal/field/Tests/FieldAttachOtherTest.php index 1ec87cf..e2b9cad 100644 --- a/core/modules/field/lib/Drupal/field/Tests/FieldAttachOtherTest.php +++ b/core/modules/field/lib/Drupal/field/Tests/FieldAttachOtherTest.php @@ -437,6 +437,7 @@ function testFieldAttachForm() { // When generating form for all fields. $form = array(); $form_state = form_state_defaults(); + $form_state['form_display'] = entity_get_form_display($entity_type, $this->instance['bundle']); field_attach_form($entity, $form, $form_state); $this->assertEqual($form[$this->field_name][$langcode]['#title'], $this->instance['label'], "First field's form title is {$this->instance['label']}"); @@ -454,6 +455,7 @@ function testFieldAttachForm() { $options = array('field_name' => $this->field_name_2); $form = array(); $form_state = form_state_defaults(); + $form_state['form_display'] = entity_get_form_display($entity_type, $this->instance['bundle']); field_attach_form($entity, $form, $form_state, NULL, $options); $this->assertFalse(isset($form[$this->field_name]), 'The first field does not exist in the form'); @@ -477,6 +479,7 @@ function testFieldAttachExtractFormValues() { // Build the form for all fields. $form = array(); $form_state = form_state_defaults(); + $form_state['form_display'] = entity_get_form_display($entity_type, $this->instance['bundle']); field_attach_form($entity_init, $form, $form_state); // Simulate incoming values. diff --git a/core/modules/field/lib/Drupal/field/Tests/FieldUnitTestBase.php b/core/modules/field/lib/Drupal/field/Tests/FieldUnitTestBase.php index 201ef34..d8d12b7 100644 --- a/core/modules/field/lib/Drupal/field/Tests/FieldUnitTestBase.php +++ b/core/modules/field/lib/Drupal/field/Tests/FieldUnitTestBase.php @@ -76,7 +76,6 @@ function createFieldWithInstance($suffix = '') { entity_get_form_display('test_entity', 'test_bundle') ->setComponent($this->$field_name, array( 'type' => 'test_field_widget', - 'label' => 'Test Field', 'settings' => array( 'test_widget_setting' => $this->randomName(), ) diff --git a/core/modules/field/lib/Drupal/field/Tests/FormTest.php b/core/modules/field/lib/Drupal/field/Tests/FormTest.php index d684f7f..0f42718 100644 --- a/core/modules/field/lib/Drupal/field/Tests/FormTest.php +++ b/core/modules/field/lib/Drupal/field/Tests/FormTest.php @@ -456,6 +456,7 @@ function testFieldFormAccess() { $form = array(); $form_state = form_state_defaults(); + $form_state['form_display'] = entity_get_form_display($entity_type, $this->instance['bundle']); field_attach_form($entity, $form, $form_state); $this->assertEqual($form[$field_name_no_access][$langcode][0]['value']['#entity_type'], $entity_type, 'The correct entity type is set in the field structure.'); diff --git a/core/modules/field/tests/modules/field_test/field_test.entity.inc b/core/modules/field/tests/modules/field_test/field_test.entity.inc index d5b5e57..8e3e1ff 100644 --- a/core/modules/field/tests/modules/field_test/field_test.entity.inc +++ b/core/modules/field/tests/modules/field_test/field_test.entity.inc @@ -227,6 +227,7 @@ function field_test_entity_nested_form($form, &$form_state, $entity_1, $entity_2 '#value' => $entity_1->$key, ); } + $form_state['form_display'] = entity_get_form_display($entity_1->entityType(), $entity_1->bundle()); field_attach_form($entity_1, $form, $form_state); // Second entity. @@ -243,6 +244,7 @@ function field_test_entity_nested_form($form, &$form_state, $entity_1, $entity_2 '#value' => $entity_2->$key, ); } + $form_state['form_display'] = entity_get_form_display($entity_1->entityType(), $entity_1->bundle()); field_attach_form($entity_2, $form['entity_2'], $form_state); $form['save'] = array( diff --git a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityFormTest.php b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityFormTest.php index fbbd131..69f879e 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityFormTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityFormTest.php @@ -46,6 +46,20 @@ function testFormCRUD() { } /** + * Tests hook_entity_form_display_alter(). + * + * @see entity_test_entity_form_display_alter() + */ + function testEntityFormDisplayAlter() { + $this->drupalGet('entity_test/add'); + $this->assertNoField('field_test_text[' . LANGUAGE_NOT_SPECIFIED . '][0][value]', 'The hidden field is not displayed'); + + $this->drupalGet('entity_test_mul/add'); + $altered_field = $this->xpath('//input[@name="field_test_text[und][0][value]" and @size="42"]'); + $this->assertTrue(count($altered_field) === 1, 'The altered field has the correct size value.'); + } + + /** * Executes the form CRUD tests for the given entity type. * * @param string $entity_type diff --git a/core/modules/system/tests/modules/entity_test/entity_test.module b/core/modules/system/tests/modules/entity_test/entity_test.module index 80f1b39..aedb91b 100644 --- a/core/modules/system/tests/modules/entity_test/entity_test.module +++ b/core/modules/system/tests/modules/entity_test/entity_test.module @@ -6,6 +6,7 @@ */ use Drupal\Core\Entity\EntityInterface; +use Drupal\entity\Plugin\Core\Entity\EntityFormDisplay; /** * Filter that limits test entity list to revisable ones. @@ -310,3 +311,23 @@ function entity_test_entity_field_access_alter(array &$grants, array $context) { $grants[':default'] = FALSE; } } + +/** + * Implements hook_entity_form_display_alter(). + */ +function entity_test_entity_form_display_alter(EntityFormDisplay $form_display, $context) { + // Hide a field on the entity_test form. + if ($context['entity_type'] == 'entity_test') { + $form_display->setComponent('field_test_text', array( + 'type' => 'hidden', + )); + } + + // Make the field_test_text field 42 characters for entity_test_mul. + if ($context['entity_type'] == 'entity_test_mul') { + if ($component_options = $form_display->getComponent('field_test_text')) { + $component_options['settings']['size'] = 42; + $form_display->setComponent('field_test_text', $component_options); + } + } +}