diff --git a/core/includes/entity.api.php b/core/includes/entity.api.php index a56c1ef..591a2b0 100644 --- a/core/includes/entity.api.php +++ b/core/includes/entity.api.php @@ -510,6 +510,27 @@ function hook_entity_display_alter(\Drupal\entity\Plugin\Core\Entity\EntityDispl } /** + * Alters the settings used for displaying an entity form. + * + * @param \Drupal\entity\Plugin\Core\Entity\EntityFormDisplay $form_display + * The entity_form_display object that will be used to display the entity form + * components. + * @param array $context + * An associative array containing: + * - entity_type: The entity type, e.g., 'node' or 'user'. + * - bundle: The bundle, e.g., 'page' or 'article'. + * - form_mode: The form mode, e.g. 'default', 'profile', 'register'... + */ +function hook_entity_form_display_alter(\Drupal\entity\Plugin\Core\Entity\EntityFormDisplay $form_display, array $context) { + // Hide the 'user_picture' field from the register form. + if ($context['entity_type'] == 'user' && $context['form_mode'] == 'register') { + $form_display->setComponent('user_picture', array( + 'type' => 'hidden', + )); + } +} + +/** * Define custom entity properties. * * @param string $entity_type diff --git a/core/includes/entity.inc b/core/includes/entity.inc index edee557..c0e97d2 100644 --- a/core/includes/entity.inc +++ b/core/includes/entity.inc @@ -717,7 +717,7 @@ function entity_get_display($entity_type, $bundle, $view_mode) { * @return \Drupal\entity\Plugin\Core\Entity\EntityDisplay * The display object that should be used to render the entity. * - * @see entity_get_render_display(). + * @see entity_get_display(). */ function entity_get_render_display(EntityInterface $entity, $view_mode) { $entity_type = $entity->entityType(); @@ -796,6 +796,44 @@ function entity_get_form_display($entity_type, $bundle, $form_mode = 'default') } /** + * Returns the entity_form_display object used to render an entity form. + * + * Depending on the configuration of the form mode for the bundle, this can be + * either the display object associated to the form mode, or the 'default' + * display. + * + * This function should only be used internally when rendering an entity form. + * When assigning suggested form display options for a component in a given form + * mode, entity_get_form_display() should be used instead, in order to avoid + * inadvertently modifying the output of other form modes that might happen to + * use the 'default' form display too. Those options will then be effectively + * applied only if the form mode is configured to use them. + * + * @param \Drupal\Core\Entity\EntityInterface $entity + * The entity for which the form is being rendered. + * @param string $form_mode + * 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. + * + * @see entity_get_form_display(). + */ +function entity_get_render_form_display(EntityInterface $entity, $form_mode) { + $entity_type = $entity->entityType(); + $bundle = $entity->bundle(); + + // @todo Form modes don't have custom settings yet, so always use the default + // form mode for now. + $render_form_mode = 'default'; + + $form_display = entity_get_form_display($entity_type, $bundle, $render_form_mode); + $form_display->originalMode = $form_mode; + + return $form_display; +} + +/** * Generic access callback for entity pages. * * @param \Drupal\Core\Entity\EntityInterface $entity diff --git a/core/lib/Drupal/Core/Entity/EntityFormController.php b/core/lib/Drupal/Core/Entity/EntityFormController.php index 6d2c9fb..796c1f2 100644 --- a/core/lib/Drupal/Core/Entity/EntityFormController.php +++ b/core/lib/Drupal/Core/Entity/EntityFormController.php @@ -78,12 +78,36 @@ public function form(array $form, array &$form_state, EntityInterface $entity) { // 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; + field_attach_form($entity, $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']; + } + } } + if (!isset($form['langcode'])) { // 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 ef9bc89..6b106c6 100644 --- a/core/lib/Drupal/Core/Entity/EntityFormControllerNG.php +++ b/core/lib/Drupal/Core/Entity/EntityFormControllerNG.php @@ -23,12 +23,12 @@ class EntityFormControllerNG extends EntityFormController { * Overrides EntityFormController::form(). */ public function form(array $form, array &$form_state, EntityInterface $entity) { - // @todo Exploit the Field API to generate the default widgets for the - // entity fields. - $info = $entity->entityInfo(); - if (!empty($info['fieldable'])) { - field_attach_form($entity->getBCEntity(), $form, $form_state, $this->getFormLangcode($form_state)); - } + parent::form($form, $form_state, $entity); + + // The only difference between this method and its parent seems to be this + // 'langcode' form element, so unset it. + unset($form['langcode']); + return $form; } diff --git a/core/modules/datetime/lib/Drupal/datetime/Plugin/field/widget/DatetimeDatelistWidget.php b/core/modules/datetime/lib/Drupal/datetime/Plugin/field/widget/DatetimeDatelistWidget.php index 366a4c4..1c5cac3 100644 --- a/core/modules/datetime/lib/Drupal/datetime/Plugin/field/widget/DatetimeDatelistWidget.php +++ b/core/modules/datetime/lib/Drupal/datetime/Plugin/field/widget/DatetimeDatelistWidget.php @@ -46,13 +46,11 @@ class DateTimeDatelistWidget extends WidgetBase { * The field instance to which the widget is associated. * @param array $settings * The widget settings. - * @param int $weight - * The widget weight. */ - public function __construct($plugin_id, array $plugin_definition, FieldInstance $instance, array $settings, $weight) { + public function __construct($plugin_id, array $plugin_definition, FieldInstance $instance, array $settings) { // Identify the function used to set the default value. $instance['default_value_function'] = $this->defaultValueFunction(); - parent::__construct($plugin_id, $plugin_definition, $instance, $settings, $weight); + parent::__construct($plugin_id, $plugin_definition, $instance, $settings); } /** diff --git a/core/modules/datetime/lib/Drupal/datetime/Plugin/field/widget/DatetimeDefaultWidget.php b/core/modules/datetime/lib/Drupal/datetime/Plugin/field/widget/DatetimeDefaultWidget.php index d51bac4..683ae6e 100644 --- a/core/modules/datetime/lib/Drupal/datetime/Plugin/field/widget/DatetimeDefaultWidget.php +++ b/core/modules/datetime/lib/Drupal/datetime/Plugin/field/widget/DatetimeDefaultWidget.php @@ -40,13 +40,11 @@ class DateTimeDefaultWidget extends WidgetBase { * The field instance to which the widget is associated. * @param array $settings * The widget settings. - * @param int $weight - * The widget weight. */ - public function __construct($plugin_id, array $plugin_definition, FieldInstance $instance, array $settings, $weight) { + public function __construct($plugin_id, array $plugin_definition, FieldInstance $instance, array $settings) { // Identify the function used to set the default value. $instance['default_value_function'] = $this->defaultValueFunction(); - parent::__construct($plugin_id, $plugin_definition, $instance, $settings, $weight); + parent::__construct($plugin_id, $plugin_definition, $instance, $settings); } /** diff --git a/core/modules/field/field.api.php b/core/modules/field/field.api.php index 9be355e..eaa5019 100644 --- a/core/modules/field/field.api.php +++ b/core/modules/field/field.api.php @@ -21,7 +21,6 @@ * in a #pre_render callback added by field_attach_form() and * field_attach_view(). * - * @see _field_extra_fields_pre_render() * @see hook_field_extra_fields_alter() * * @return array diff --git a/core/modules/field/field.attach.inc b/core/modules/field/field.attach.inc index 0a373d1..0fe5114 100644 --- a/core/modules/field/field.attach.inc +++ b/core/modules/field/field.attach.inc @@ -705,15 +705,15 @@ function _field_invoke_get_instances($entity_type, $bundle, $options) { * * Used to invoke methods on an instance's widget. * - * @param \Drupal\entity\Plugin\Core\Entity\EntityFormDisplay $entity_form_display + * @param \Drupal\entity\Plugin\Core\Entity\EntityFormDisplay $form_display * An EntityFormDisplay object. * * @return callable $target_function * A 'target function' for field_invoke_method(). */ -function _field_invoke_widget_target($entity_form_display) { - return function ($instance) use ($entity_form_display) { - return $entity_form_display->getWidget($instance['field_name']); +function _field_invoke_widget_target($form_display) { + return function ($instance) use ($form_display) { + return $form_display->getWidget($instance['field_name']); }; } @@ -825,18 +825,19 @@ function _field_invoke_widget_target($entity_form_display) { * @see field_form_set_state() */ function field_attach_form(EntityInterface $entity, &$form, &$form_state, $langcode = NULL, array $options = array()) { + // Enable BC if necessary. + $entity = $entity->getBCEntity(); + // Set #parents to 'top-level' by default. $form += array('#parents' => array()); - // Get the entity_form_display object for this bundle. - $entity_form_display = entity_get_form_display($entity->entityType(), $entity->bundle()); + // Get the entity_form_display object for this form. + $form_display = $form_state['form_display']; // If no language is provided use the default site language. $options['langcode'] = field_valid_language($langcode); - $form += (array) field_invoke_method('form', _field_invoke_widget_target($entity_form_display), $entity, $form, $form_state, $options); + $form += (array) field_invoke_method('form', _field_invoke_widget_target($form_display), $entity, $form, $form_state, $options); - // Add custom weight handling. - $form['#pre_render'][] = '_field_extra_fields_pre_render'; $form['#entity_type'] = $entity->entityType(); $form['#bundle'] = $entity->bundle(); @@ -1098,8 +1099,8 @@ function field_attach_form_validate(EntityInterface $entity, $form, &$form_state field_form_set_state($form['#parents'], $field_name, $langcode, $form_state, $field_state); } } - $entity_form_display = entity_get_form_display($entity->entityType(), $entity->bundle()); - field_invoke_method('flagErrors', _field_invoke_widget_target($entity_form_display), $entity, $form, $form_state, $options); + $form_display = $form_state['form_display']; + field_invoke_method('flagErrors', _field_invoke_widget_target($form_display), $entity, $form, $form_state, $options); } } @@ -1123,8 +1124,8 @@ 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. - $entity_form_display = entity_get_form_display($entity->entityType(), $entity->bundle()); - field_invoke_method('extractFormValues', _field_invoke_widget_target($entity_form_display), $entity, $form, $form_state, $options); + $form_display = $form_state['form_display']; + field_invoke_method('extractFormValues', _field_invoke_widget_target($form_display), $entity, $form, $form_state, $options); // Let other modules act on submitting the entity. // Avoid module_invoke_all() to let $form_state be taken by reference. diff --git a/core/modules/field/field.module b/core/modules/field/field.module index 5f774ad..42146a8 100644 --- a/core/modules/field/field.module +++ b/core/modules/field/field.module @@ -645,23 +645,6 @@ function field_view_mode_settings($entity_type, $bundle) { } /** - * Pre-render callback: Adjusts weights and visibility of non-field elements. - */ -function _field_extra_fields_pre_render($elements) { - $entity_type = $elements['#entity_type']; - $bundle = $elements['#bundle']; - - $extra_fields = field_info_extra_fields($entity_type, $bundle, 'form'); - foreach ($extra_fields as $name => $settings) { - if (isset($elements[$name])) { - $elements[$name]['#weight'] = $settings['weight']; - } - } - - return $elements; -} - -/** * Clears the field info and field data caches. */ function field_cache_clear() { diff --git a/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetBase.php b/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetBase.php index fccbd1a..ab0d945 100644 --- a/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetBase.php +++ b/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetBase.php @@ -39,13 +39,6 @@ protected $settings; /** - * The widget weight. - * - * @var int - */ - protected $weight; - - /** * Constructs a WidgetBase object. * * @param array $plugin_id @@ -56,16 +49,13 @@ * The field instance to which the widget is associated. * @param array $settings * The widget settings. - * @param int $weight - * The widget weight. */ - public function __construct($plugin_id, array $plugin_definition, FieldInstance $instance, array $settings, $weight) { + public function __construct($plugin_id, array $plugin_definition, FieldInstance $instance, array $settings) { parent::__construct(array(), $plugin_id, $plugin_definition); $this->instance = $instance; $this->field = field_info_field($instance['field_name']); $this->settings = $settings; - $this->weight = $weight; } /** @@ -140,7 +130,6 @@ public function form(EntityInterface $entity, $langcode, array $items, array &$f 'field-widget-' . drupal_html_class($this->getPluginId()), ), ), - '#weight' => $this->weight, ); // Populate the 'array_parents' information in $form_state['field'] after diff --git a/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetFactory.php b/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetFactory.php index 392ef5e..9b14e85 100644 --- a/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetFactory.php +++ b/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetFactory.php @@ -20,6 +20,6 @@ class WidgetFactory extends DefaultFactory { public function createInstance($plugin_id, array $configuration) { $plugin_definition = $this->discovery->getDefinition($plugin_id); $plugin_class = static::getPluginClass($plugin_id, $plugin_definition); - return new $plugin_class($plugin_id, $plugin_definition, $configuration['instance'], $configuration['settings'], $configuration['weight']); + return new $plugin_class($plugin_id, $plugin_definition, $configuration['instance'], $configuration['settings']); } } diff --git a/core/modules/options/lib/Drupal/options/Plugin/field/widget/OptionsWidgetBase.php b/core/modules/options/lib/Drupal/options/Plugin/field/widget/OptionsWidgetBase.php index 40f24df..94ae0cb 100644 --- a/core/modules/options/lib/Drupal/options/Plugin/field/widget/OptionsWidgetBase.php +++ b/core/modules/options/lib/Drupal/options/Plugin/field/widget/OptionsWidgetBase.php @@ -36,8 +36,8 @@ /** * {@inheritdoc} */ - public function __construct($plugin_id, array $plugin_definition, FieldInstance $instance, array $settings, $weight) { - parent::__construct($plugin_id, $plugin_definition, $instance, $settings, $weight); + public function __construct($plugin_id, array $plugin_definition, FieldInstance $instance, array $settings) { + parent::__construct($plugin_id, $plugin_definition, $instance, $settings); // Reset internal pointer since we're dealing with objects now. reset($this->field['columns']); diff --git a/core/modules/telephone/lib/Drupal/telephone/Tests/TelephoneFieldTest.php b/core/modules/telephone/lib/Drupal/telephone/Tests/TelephoneFieldTest.php index b705db4..0d5aa47 100644 --- a/core/modules/telephone/lib/Drupal/telephone/Tests/TelephoneFieldTest.php +++ b/core/modules/telephone/lib/Drupal/telephone/Tests/TelephoneFieldTest.php @@ -64,18 +64,15 @@ function testTelephoneField() { 'label' => 'Telephone Number', 'entity_type' => 'node', 'bundle' => 'article', - 'widget' => array( - 'type' => 'telephone_default', - 'settings' => array( - 'placeholder' => '123-456-7890', - ), - ), ); field_create_instance($instance); entity_get_form_display('node', 'article', 'default') ->setComponent('field_telephone', array( 'type' => 'telephone_default', + 'settings' => array( + 'placeholder' => '123-456-7890', + ), )) ->save();