diff --git a/core/includes/entity.api.php b/core/includes/entity.api.php index 3f39e75..4135390 100644 --- a/core/includes/entity.api.php +++ b/core/includes/entity.api.php @@ -97,16 +97,8 @@ function hook_entity_view_mode_info_alter(&$view_modes) { * - admin: An array of information that allows Field UI pages to attach * themselves to the existing administration pages for the bundle. * Elements: - * - path: the path of the bundle's main administration page, as defined - * in hook_menu(). If the path includes a placeholder for the bundle, - * the 'bundle argument', 'bundle helper' and 'real path' keys below - * are required. - * - bundle argument: The position of the placeholder in 'path', if any. * - real path: The actual path (no placeholder) of the bundle's main * administration page. This will be used to generate links. - * - access callback: As in hook_menu(). 'user_access' will be assumed if - * no value is provided. - * - access arguments: As in hook_menu(). * - translatable: (optional) A boolean value specifying whether this bundle * has translation support enabled. Defaults to FALSE. * @@ -510,6 +502,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 c2c97c4..66c9470 100644 --- a/core/includes/entity.inc +++ b/core/includes/entity.inc @@ -688,7 +688,7 @@ function entity_get_display($entity_type, $bundle, $view_mode) { $display = entity_create('entity_display', array( 'targetEntityType' => $entity_type, 'bundle' => $bundle, - 'viewMode' => $view_mode, + 'mode' => $view_mode, )); } @@ -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(); @@ -730,12 +730,102 @@ function entity_get_render_display(EntityInterface $entity, $view_mode) { $render_view_mode = !empty($view_mode_settings[$view_mode]['custom_settings']) ? $view_mode : 'default'; $display = entity_get_display($entity_type, $bundle, $render_view_mode); - $display->originalViewMode = $view_mode; + $display->originalMode = $view_mode; return $display; } /** + * Returns the entity_form_display object associated to a bundle and form mode. + * + * The function reads the entity_form_display object from the current + * configuration, or returns a ready-to-use empty one if configuration entry + * exists yet for this bundle and form mode. This streamlines manipulation of + * EntityFormDisplay objects by always returning a consistent object that + * reflects the current state of the configuration. + * + * Example usage: + * - Set the 'body' field to be displayed with the 'text_textarea_with_summary' + * widget and the 'field_image' field to be hidden on article nodes in the + * 'default' form mode. + * @code + * entity_get_form_display('node', 'article', 'default') + * ->setComponent('body', array( + * 'type' => 'text_textarea_with_summary', + * 'weight' => 1, + * )) + * ->setComponent('field_image', array( + * 'type' => 'hidden', + * )) + * ->save(); + * @endcode + * + * @param string $entity_type + * The entity type. + * @param string $bundle + * The bundle. + * @param string $form_mode + * (optional) The form mode. Defaults to 'default'. + * + * @todo Make the $form_mode parameter non-optional by introducing the form + * modes concept. + * + * @return \Drupal\entity\Plugin\Core\Entity\EntityFormDisplay + * The EntityFormDisplay object associated to the form mode. + */ +function entity_get_form_display($entity_type, $bundle, $form_mode = 'default') { + // Try loading the entity from configuration. + $entity_form_display = entity_load('entity_form_display', $entity_type . '.' . $bundle . '.' . $form_mode); + + // If not found, create a fresh entity object. We do not preemptively create + // new EntityFormDisplay configuration entries for each existing entity type + // and bundle whenever a new form mode becomes available. Instead, + // configuration entries are only created when a EntityFormDisplay object is + // explicitly configured and saved. + if (!$entity_form_display) { + $entity_form_display = entity_create('entity_form_display', array( + 'targetEntityType' => $entity_type, + 'bundle' => $bundle, + 'mode' => $form_mode, + )); + } + + return $entity_form_display; +} + +/** + * Returns the entity_form_display object used to render an entity form. + * + * 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 just return the display + // for the form mode that was requested. + $form_display = entity_get_form_display($entity_type, $bundle, $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/Annotation/EntityType.php b/core/lib/Drupal/Core/Entity/Annotation/EntityType.php index 0487d03..50b604c 100644 --- a/core/lib/Drupal/Core/Entity/Annotation/EntityType.php +++ b/core/lib/Drupal/Core/Entity/Annotation/EntityType.php @@ -194,6 +194,27 @@ class EntityType extends Plugin { public $bundle_keys; /** + * The base router path for the entity type's field administration page. + * + * If the entity type has a bundle, include {bundle} in the path. + * + * For example, the node entity type specifies + * "admin/structure/types/manage/{bundle}" as its base field admin path. + * + * @var string (optional) + */ + public $route_base_path; + + /** + * The prefix for the bundles of this entity type. + * + * For example, the comment bundle is prefixed with 'comment_node_'. + * + * @var string (optional) + */ + public $bundle_prefix; + + /** * The base menu router path to which the entity admin user interface responds. * * It can be used to generate UI links and to attach additional router items diff --git a/core/lib/Drupal/Core/Entity/EntityFormController.php b/core/lib/Drupal/Core/Entity/EntityFormController.php index 6d2c9fb..2332d06 100644 --- a/core/lib/Drupal/Core/Entity/EntityFormController.php +++ b/core/lib/Drupal/Core/Entity/EntityFormController.php @@ -74,12 +74,35 @@ protected function init(array &$form_state, EntityInterface $entity) { * @see Drupal\Core\Entity\EntityFormController::build() */ public function form(array $form, array &$form_state, EntityInterface $entity) { + // Get the entity_form_display object for this form. + $form_display = entity_get_render_form_display($entity, 'default'); + + // 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; + // @todo Exploit the Field API to generate the default widgets for the // entity properties. $info = $entity->entityInfo(); if (!empty($info['fieldable'])) { 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 diff --git a/core/lib/Drupal/Core/Entity/EntityFormControllerNG.php b/core/lib/Drupal/Core/Entity/EntityFormControllerNG.php index ef9bc89..f80bd5c 100644 --- a/core/lib/Drupal/Core/Entity/EntityFormControllerNG.php +++ b/core/lib/Drupal/Core/Entity/EntityFormControllerNG.php @@ -23,12 +23,35 @@ class EntityFormControllerNG extends EntityFormController { * Overrides EntityFormController::form(). */ public function form(array $form, array &$form_state, EntityInterface $entity) { + // Get the entity_form_display object for this form. + $form_display = entity_get_render_form_display($entity, 'default'); + + // 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; + // @todo Exploit the Field API to generate the default widgets for the - // entity fields. + // entity properties. $info = $entity->entityInfo(); if (!empty($info['fieldable'])) { 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/block/block.install b/core/modules/block/block.install index 01c5779..bb9806e 100644 --- a/core/modules/block/block.install +++ b/core/modules/block/block.install @@ -259,11 +259,19 @@ function block_update_8008() { 'entity_type' => 'custom_block', 'bundle' => 'basic', 'label' => 'Block body', - 'widget' => array('type' => 'text_textarea_with_summary'), 'settings' => array('display_summary' => FALSE), ); _update_7000_field_create_instance($body_field, $instance); + module_load_install('entity'); + // Assign form settings for the 'default' form mode. + $form_display = _update_8000_entity_get_form_display('custom_block', 'basic', 'default'); + $form_display->set('content.user_picture', array( + 'type' => 'text_textarea_with_summary', + )) + ->save(); + update_config_manifest_add('entity.form_display', array($form_display->get('id'))); + // Initialize state for future calls. $sandbox['last'] = 0; $sandbox['count'] = 0; diff --git a/core/modules/block/custom_block/custom_block.module b/core/modules/block/custom_block/custom_block.module index ff637f6..83e740d 100644 --- a/core/modules/block/custom_block/custom_block.module +++ b/core/modules/block/custom_block/custom_block.module @@ -187,9 +187,7 @@ function custom_block_entity_bundle_info() { $bundles['custom_block'][$config->get('id')] = array( 'label' => $config->get('label'), 'admin' => array( - 'path' => 'admin/structure/custom-blocks/manage/%', 'real path' => 'admin/structure/custom-blocks/manage/' . $config->get('id'), - 'bundle argument' => 4, ), ); } @@ -235,11 +233,17 @@ function custom_block_add_body_field($block_type_id, $label = 'Block body') { 'entity_type' => 'custom_block', 'bundle' => $block_type_id, 'label' => $label, - 'widget' => array('type' => 'text_textarea_with_summary'), 'settings' => array('display_summary' => FALSE), ); $instance = field_create_instance($instance); + // Assign widget settings for the 'default' form mode. + entity_get_form_display('custom_block', $block_type_id, 'default') + ->setComponent('block_body', array( + 'type' => 'text_textarea_with_summary', + )) + ->save(); + // Assign display settings for 'default' view mode. entity_get_display('custom_block', $block_type_id, 'default') ->setComponent('block_body', array( diff --git a/core/modules/block/custom_block/lib/Drupal/custom_block/Plugin/Core/Entity/CustomBlock.php b/core/modules/block/custom_block/lib/Drupal/custom_block/Plugin/Core/Entity/CustomBlock.php index 63f5e82..f4ac93a 100644 --- a/core/modules/block/custom_block/lib/Drupal/custom_block/Plugin/Core/Entity/CustomBlock.php +++ b/core/modules/block/custom_block/lib/Drupal/custom_block/Plugin/Core/Entity/CustomBlock.php @@ -31,6 +31,7 @@ * }, * base_table = "custom_block", * revision_table = "custom_block_revision", + * route_base_path = "admin/structure/custom-blocks/manage/{bundle}", * menu_base_path = "block/%custom_block", * fieldable = TRUE, * translatable = TRUE, diff --git a/core/modules/block/custom_block/lib/Drupal/custom_block/Tests/CustomBlockFieldTest.php b/core/modules/block/custom_block/lib/Drupal/custom_block/Tests/CustomBlockFieldTest.php index 8d49349..c62f4a7 100644 --- a/core/modules/block/custom_block/lib/Drupal/custom_block/Tests/CustomBlockFieldTest.php +++ b/core/modules/block/custom_block/lib/Drupal/custom_block/Tests/CustomBlockFieldTest.php @@ -77,17 +77,18 @@ public function testBlockFields() { 'settings' => array( 'title' => DRUPAL_OPTIONAL, ), - 'widget' => array( - 'type' => 'link_default', - ), - ); - $display_options = array( - 'type' => 'link', - 'label' => 'hidden', ); field_create_instance($this->instance); + entity_get_form_display('custom_block', 'link', 'default') + ->setComponent($this->field['field_name'], array( + 'type' => 'link_default', + )) + ->save(); entity_get_display('custom_block', 'link', 'default') - ->setComponent($this->field['field_name'], $display_options) + ->setComponent($this->field['field_name'], array( + 'type' => 'link', + 'label' => 'hidden', + )) ->save(); // Create a block. diff --git a/core/modules/block/custom_block/lib/Drupal/custom_block/Tests/CustomBlockTypeTest.php b/core/modules/block/custom_block/lib/Drupal/custom_block/Tests/CustomBlockTypeTest.php index eee184a..35f4b98 100644 --- a/core/modules/block/custom_block/lib/Drupal/custom_block/Tests/CustomBlockTypeTest.php +++ b/core/modules/block/custom_block/lib/Drupal/custom_block/Tests/CustomBlockTypeTest.php @@ -99,7 +99,7 @@ public function testCustomBlockTypeEditing() { $this->assertEqual(url('block/add/basic', array('absolute' => TRUE)), $this->getUrl(), 'Original machine name was used in URL.'); // Remove the body field. - $this->drupalPost('admin/structure/custom-blocks/manage/basic/fields/block_body/delete', array(), t('Delete')); + $this->drupalPost('admin/structure/custom-blocks/manage/basic/fields/custom_block.basic.block_body/delete', array(), t('Delete')); // Resave the settings for this type. $this->drupalPost('admin/structure/custom-blocks/manage/basic', array(), t('Save')); // Check that the body field doesn't exist. diff --git a/core/modules/comment/comment.module b/core/modules/comment/comment.module index 5690c72..78c50b0 100644 --- a/core/modules/comment/comment.module +++ b/core/modules/comment/comment.module @@ -119,14 +119,6 @@ function comment_entity_bundle_info() { // have to be extracted manually from the bundle name. 'node bundle' => $type, 'admin' => array( - // Place the Field UI paths for comments one level below the - // corresponding paths for nodes, so that they appear in the same set - // of local tasks. Note that the paths use a different placeholder name - // and thus a different menu loader callback, so that Field UI page - // callbacks get a comment bundle name from the node type in the URL. - // See comment_node_type_load() and comment_menu_alter(). - 'path' => 'admin/structure/types/manage/%comment_node_type/comment', - 'bundle argument' => 4, 'real path' => 'admin/structure/types/manage/' . $type . '/comment', ), ); @@ -301,10 +293,10 @@ function comment_menu_alter(&$items) { // Adjust the Field UI tabs on admin/structure/types/manage/[node-type]. // See comment_entity_bundle_info(). - $items['admin/structure/types/manage/%comment_node_type/comment/fields']['title'] = 'Comment fields'; - $items['admin/structure/types/manage/%comment_node_type/comment/fields']['weight'] = 3; - $items['admin/structure/types/manage/%comment_node_type/comment/display']['title'] = 'Comment display'; - $items['admin/structure/types/manage/%comment_node_type/comment/display']['weight'] = 4; + $items['admin/structure/types/manage/%/comment/fields']['title'] = 'Comment fields'; + $items['admin/structure/types/manage/%/comment/fields']['weight'] = 3; + $items['admin/structure/types/manage/%/comment/display']['title'] = 'Comment display'; + $items['admin/structure/types/manage/%/comment/display']['weight'] = 4; } /** @@ -389,6 +381,15 @@ function _comment_body_field_create($info) { 'required' => TRUE, ); field_create_instance($instance); + + // Assign widget settings for the 'default' form mode. + entity_get_form_display('comment', 'comment_node_' . $info->type, 'default') + ->setComponent('comment_body', array( + 'type' => 'text_textarea', + )) + ->save(); + + // Assign display settings for the 'default' view mode. entity_get_display('comment', 'comment_node_' . $info->type, 'default') ->setComponent('comment_body', array( 'label' => 'hidden', diff --git a/core/modules/comment/lib/Drupal/comment/Plugin/Core/Entity/Comment.php b/core/modules/comment/lib/Drupal/comment/Plugin/Core/Entity/Comment.php index b57c74f..a45eb3f 100644 --- a/core/modules/comment/lib/Drupal/comment/Plugin/Core/Entity/Comment.php +++ b/core/modules/comment/lib/Drupal/comment/Plugin/Core/Entity/Comment.php @@ -34,6 +34,8 @@ * fieldable = TRUE, * translatable = TRUE, * static_cache = FALSE, + * route_base_path = "admin/structure/types/manage/{bundle}/comment", + * bundle_prefix = "comment_node_", * entity_keys = { * "id" = "cid", * "bundle" = "node_type", diff --git a/core/modules/comment/lib/Drupal/comment/Tests/CommentFieldsTest.php b/core/modules/comment/lib/Drupal/comment/Tests/CommentFieldsTest.php index a29db8c..c92d2ab 100644 --- a/core/modules/comment/lib/Drupal/comment/Tests/CommentFieldsTest.php +++ b/core/modules/comment/lib/Drupal/comment/Tests/CommentFieldsTest.php @@ -107,7 +107,7 @@ function testCommentFormat() { // Disable text processing for comments. $this->drupalLogin($this->admin_user); $edit = array('instance[settings][text_processing]' => 0); - $this->drupalPost('admin/structure/types/manage/article/comment/fields/comment_body', $edit, t('Save settings')); + $this->drupalPost('admin/structure/types/manage/article/comment/fields/comment.comment_node_article.comment_body', $edit, t('Save settings')); // Post a comment without an explicit subject. $this->drupalLogin($this->web_user); diff --git a/core/modules/contact/contact.module b/core/modules/contact/contact.module index e134ccc..c3e6fae 100644 --- a/core/modules/contact/contact.module +++ b/core/modules/contact/contact.module @@ -179,9 +179,7 @@ function contact_entity_bundle_info() { $bundles['contact_message'][$config->get('id')] = array( 'label' => $config->get('label'), 'admin' => array( - 'path' => 'admin/structure/contact/manage/%contact_category', 'real path' => 'admin/structure/contact/manage/' . $config->get('id'), - 'bundle argument' => 4, 'access arguments' => array('administer contact forms'), ), ); diff --git a/core/modules/datetime/datetime.module b/core/modules/datetime/datetime.module index 79905f8..b545c36 100644 --- a/core/modules/datetime/datetime.module +++ b/core/modules/datetime/datetime.module @@ -134,9 +134,7 @@ function datetime_field_settings_form($field, $instance, $has_data) { * Implements hook_field_instance_settings_form(). */ function datetime_field_instance_settings_form($field, $instance) { - $widget = $instance['widget']; $settings = $instance['settings']; - $widget_settings = $instance['widget']['settings']; $form['default_value'] = array( '#type' => 'select', 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..f0d60fe 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 @@ -36,23 +36,12 @@ class DateTimeDatelistWidget extends WidgetBase { /** - * Constructs a DateTimeDatelist Widget object. - * - * @param array $plugin_id - * The plugin_id for the widget. - * @param array $plugin_definition - * The plugin implementation definition. - * @param \Drupal\field\Plugin\Core\Entity\FieldInstance $instance - * The field instance to which the widget is associated. - * @param array $settings - * The widget settings. - * @param int $weight - * The widget weight. + * {@inheritdoc} */ - 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..f0c45c0 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 @@ -30,23 +30,12 @@ class DateTimeDefaultWidget extends WidgetBase { /** - * Constructs a DateTimeDefault Widget object. - * - * @param array $plugin_id - * The plugin_id for the widget. - * @param array $plugin_definition - * The plugin implementation definition. - * @param \Drupal\field\Plugin\Core\Entity\FieldInstance $instance - * The field instance to which the widget is associated. - * @param array $settings - * The widget settings. - * @param int $weight - * The widget weight. + * {@inheritdoc} */ - 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/Tests/DatetimeFieldTest.php b/core/modules/datetime/lib/Drupal/datetime/Tests/DatetimeFieldTest.php index bb3bddf..ac3f4a3 100644 --- a/core/modules/datetime/lib/Drupal/datetime/Tests/DatetimeFieldTest.php +++ b/core/modules/datetime/lib/Drupal/datetime/Tests/DatetimeFieldTest.php @@ -57,14 +57,17 @@ function setUp() { 'field_name' => $this->field['field_name'], 'entity_type' => 'test_entity', 'bundle' => 'test_bundle', - 'widget' => array( - 'type' => 'datetime_default', - ), 'settings' => array( 'default_value' => 'blank', ), )); + entity_get_form_display($this->instance['entity_type'], $this->instance['bundle'], 'default') + ->setComponent($this->field['field_name'], array( + 'type' => 'datetime_default', + )) + ->save(); + $this->display_options = array( 'type' => 'datetime_default', 'label' => 'hidden', @@ -217,17 +220,16 @@ function testDatelistWidget() { field_update_field($this->field); // Change the widget to a datelist widget. - $increment = 1; - $date_order = 'YMD'; - $time_type = '12'; - - $this->instance['widget']['type'] = 'datetime_datelist'; - $this->instance['widget']['settings'] = array( - 'increment' => $increment, - 'date_order' => $date_order, - 'time_type' => $time_type, - ); - field_update_instance($this->instance); + entity_get_form_display($this->instance['entity_type'], $this->instance['bundle'], 'default') + ->setComponent($this->instance['field_name'], array( + 'type' => 'datetime_datelist', + 'settings' => array( + 'increment' => 1, + 'date_order' => 'YMD', + 'time_type' => '12', + ), + )) + ->save(); field_cache_clear(); // Display creation form. diff --git a/core/modules/edit/lib/Drupal/edit/Tests/EditTestBase.php b/core/modules/edit/lib/Drupal/edit/Tests/EditTestBase.php index d3737bb..30aec3f 100644 --- a/core/modules/edit/lib/Drupal/edit/Tests/EditTestBase.php +++ b/core/modules/edit/lib/Drupal/edit/Tests/EditTestBase.php @@ -70,13 +70,16 @@ function createFieldWithInstance($field_name, $type, $cardinality, $label, $inst 'description' => $label, 'weight' => mt_rand(0, 127), 'settings' => $instance_settings, - 'widget' => array( + ); + field_create_instance($this->$instance); + + entity_get_form_display('entity_test', 'entity_test', 'default') + ->setComponent($field_name, array( 'type' => $widget_type, 'label' => $label, 'settings' => $widget_settings, - ), - ); - field_create_instance($this->$instance); + )) + ->save(); entity_get_display('entity_test', 'entity_test', 'default') ->setComponent($field_name, array( diff --git a/core/modules/email/lib/Drupal/email/Tests/EmailFieldTest.php b/core/modules/email/lib/Drupal/email/Tests/EmailFieldTest.php index c719c97..dbb2bed 100644 --- a/core/modules/email/lib/Drupal/email/Tests/EmailFieldTest.php +++ b/core/modules/email/lib/Drupal/email/Tests/EmailFieldTest.php @@ -54,14 +54,18 @@ function testEmailField() { 'field_name' => $this->field['field_name'], 'entity_type' => 'test_entity', 'bundle' => 'test_bundle', - 'widget' => array( + ); + field_create_instance($this->instance); + + // Create a form display for the default form mode. + entity_get_form_display('test_entity', 'test_bundle', 'default') + ->setComponent($this->field['field_name'], array( 'type' => 'email_default', 'settings' => array( 'placeholder' => 'example@example.com', ), - ), - ); - field_create_instance($this->instance); + )) + ->save(); // Create a display for the full view mode. entity_get_display('test_entity', 'test_bundle', 'full') ->setComponent($this->field['field_name'], array( diff --git a/core/modules/email/lib/Drupal/email/Tests/EmailItemTest.php b/core/modules/email/lib/Drupal/email/Tests/EmailItemTest.php index def99f1..1555b8d 100644 --- a/core/modules/email/lib/Drupal/email/Tests/EmailItemTest.php +++ b/core/modules/email/lib/Drupal/email/Tests/EmailItemTest.php @@ -44,11 +44,15 @@ public function setUp() { 'entity_type' => 'entity_test', 'field_name' => 'field_email', 'bundle' => 'entity_test', - 'widget' => array( - 'type' => 'email_default', - ), ); field_create_instance($this->instance); + + // Create a form display for the default form mode. + entity_get_form_display('entity_test', 'entity_test', 'default') + ->setComponent('field_email', array( + 'type' => 'email_default', + )) + ->save(); } /** diff --git a/core/modules/entity/entity.install b/core/modules/entity/entity.install index 2e1efd7..af2aba1 100644 --- a/core/modules/entity/entity.install +++ b/core/modules/entity/entity.install @@ -37,7 +37,46 @@ function _update_8000_entity_get_display($entity_type, $bundle, $view_mode) { 'uuid' => $uuid->generate(), 'targetEntityType' => $entity_type, 'bundle' => $bundle, - 'viewMode' => $view_mode, + 'mode' => $view_mode, + 'content' => array(), + ); + foreach ($properties as $key => $value) { + $config->set($key, $value); + } + return $config; +} + +/** + * Returns the raw configuration object for an EntityFormDisplay entity. + * + * The function returns the existing configuration entry if it exists, or + * creates a fresh structure. + * + * @param string $entity_type + * The entity type. + * @param string $bundle + * The bundle name. + * @param string $form_mode + * The form mode. + * + * @return \Drupal\Core\Config\Config + * The configuration object. + */ +function _update_8000_entity_get_form_display($entity_type, $bundle, $form_mode) { + $id = $entity_type . '.' . $bundle . '.' . $form_mode; + $config = config("entity.form_display.$id"); + if ($config->get()) { + return $config; + } + + // Initialize a fresh structure. + $uuid = new Uuid(); + $properties = array( + 'id' => $id, + 'uuid' => $uuid->generate(), + 'targetEntityType' => $entity_type, + 'bundle' => $bundle, + 'mode' => $form_mode, 'content' => array(), ); foreach ($properties as $key => $value) { diff --git a/core/modules/entity/entity.module b/core/modules/entity/entity.module index 8fca683..7a9c8a8 100644 --- a/core/modules/entity/entity.module +++ b/core/modules/entity/entity.module @@ -14,20 +14,33 @@ * Implements hook_entity_bundle_rename(). */ function entity_entity_bundle_rename($entity_type, $bundle_old, $bundle_new) { - $entity_info = entity_get_info('entity_display'); - // Rename entity displays. + $entity_info = entity_get_info('entity_display'); if ($bundle_old !== $bundle_new) { $ids = config_get_storage_names_with_prefix('entity.display.' . $entity_type . '.' . $bundle_old); foreach ($ids as $id) { $id = ConfigStorageController::getIDFromConfigName($id, $entity_info['config_prefix']); $display = entity_load('entity_display', $id); - $new_id = $entity_type . '.' . $bundle_new . '.' . $display->viewMode; + $new_id = $entity_type . '.' . $bundle_new . '.' . $display->mode; $display->id = $new_id; $display->bundle = $bundle_new; $display->save(); } } + + // Rename entity form displays. + $entity_info = entity_get_info('entity_form_display'); + if ($bundle_old !== $bundle_new) { + $ids = config_get_storage_names_with_prefix('entity.form_display.' . $entity_type . '.' . $bundle_old); + foreach ($ids as $id) { + $id = ConfigStorageController::getIDFromConfigName($id, $entity_info['config_prefix']); + $form_display = entity_load('entity_form_display', $id); + $new_id = $entity_type . '.' . $bundle_new . '.' . $form_display->mode; + $form_display->id = $new_id; + $form_display->bundle = $bundle_new; + $form_display->save(); + } + } } /** @@ -42,4 +55,11 @@ function entity_entity_bundle_delete($entity_type, $bundle) { $id = ConfigStorageController::getIDFromConfigName($id, $entity_info['config_prefix']); } entity_delete_multiple('entity_display', $ids); + + // Remove entity form displays of the deleted bundle. + $ids = config_get_storage_names_with_prefix('entity.form_display.' . $entity_type . '.' . $bundle); + foreach ($ids as &$id) { + $id = ConfigStorageController::getIDFromConfigName($id, $entity_info['config_prefix']); + } + entity_delete_multiple('entity_form_display', $ids); } diff --git a/core/modules/entity/lib/Drupal/entity/Plugin/Core/Entity/EntityDisplay.php b/core/modules/entity/lib/Drupal/entity/EntityDisplayBase.php similarity index 65% copy from core/modules/entity/lib/Drupal/entity/Plugin/Core/Entity/EntityDisplay.php copy to core/modules/entity/lib/Drupal/entity/EntityDisplayBase.php index af01eb4..88d25a6 100644 --- a/core/modules/entity/lib/Drupal/entity/Plugin/Core/Entity/EntityDisplay.php +++ b/core/modules/entity/lib/Drupal/entity/EntityDisplayBase.php @@ -2,34 +2,18 @@ /** * @file - * Contains \Drupal\entity\Plugin\Core\Entity\EntityDisplay. + * Contains \Drupal\entity\EntityDisplayBase. */ -namespace Drupal\entity\Plugin\Core\Entity; +namespace Drupal\entity; use Drupal\Core\Config\Entity\ConfigEntityBase; -use Drupal\Core\Entity\Annotation\EntityType; -use Drupal\Core\Annotation\Translation; /** - * Configuration entity that contains display options for all components of a - * rendered entity in a given view mode.. - * - * @EntityType( - * id = "entity_display", - * label = @Translation("Entity display"), - * module = "entity", - * controllers = { - * "storage" = "Drupal\Core\Config\Entity\ConfigStorageController" - * }, - * config_prefix = "entity.display", - * entity_keys = { - * "id" = "id", - * "uuid" = "uuid" - * } - * ) + * Base class for config entity types that store configuration for entity forms + * and displays. */ -class EntityDisplay extends ConfigEntityBase { +abstract class EntityDisplayBase extends ConfigEntityBase { /** * Unique ID for the config entity. @@ -60,11 +44,11 @@ class EntityDisplay extends ConfigEntityBase { public $bundle; /** - * View mode to be displayed. + * View or form mode to be displayed. * * @var string */ - public $viewMode; + public $mode; /** * List of component display options, keyed by component name. @@ -74,19 +58,33 @@ class EntityDisplay extends ConfigEntityBase { protected $content = array(); /** - * The original view mode that was requested (case of view modes being - * configured to fall back to the 'default' display). + * The original view or form mode that was requested (case of view/form modes + * being configured to fall back to the 'default' display). * * @var string */ - public $originalViewMode; + public $originalMode; /** - * The formatter objects used for this display, keyed by field name. + * The plugin objects used for this display, keyed by field name. * * @var array */ - protected $formatters = array(); + protected $plugins = array(); + + /** + * Context in which this entity will be used (e.g. 'display', 'form'). + * + * @var string + */ + protected $displayContext; + + /** + * The plugin manager used by this entity type. + * + * @var \Drupal\Component\Plugin\PluginManagerBase + */ + protected $pluginManager; /** * Overrides \Drupal\Core\Config\Entity\ConfigEntityBase::__construct(). @@ -96,19 +94,28 @@ public function __construct(array $values, $entity_type) { // currently produces invalid entities with a NULL bundle in some cases. // Add the validity checks back when http://drupal.org/node/1856556 is // fixed. - // if (!isset($values['targetEntityType']) || !isset($values['bundle']) || !isset($values['viewMode'])) { - // throw new \InvalidArgumentException('Missing required properties for an EntiyDisplay entity.'); + // if (!isset($values['targetEntityType']) || !isset($values['bundle']) || !isset($values['mode'])) { + // throw new \InvalidArgumentException('Missing required properties for an EntityDisplay entity.'); // } + + // A plugin manager and a context type needs to be set by extending classes. + if (!isset($this->pluginManager)) { + throw new \RuntimeException('Missing plugin manager.'); + } + if (!isset($this->displayContext)) { + throw new \RuntimeException('Missing display context type.'); + } + parent::__construct($values, $entity_type); - $this->originalViewMode = $this->viewMode; + $this->originalMode = $this->mode; } /** * Overrides \Drupal\Core\Entity\Entity::id(). */ public function id() { - return $this->targetEntityType . '.' . $this->bundle . '.' . $this->viewMode; + return $this->targetEntityType . '.' . $this->bundle . '.' . $this->mode; } /** @@ -131,7 +138,7 @@ public function getExportProperties() { 'uuid', 'targetEntityType', 'bundle', - 'viewMode', + 'mode', 'content', ); $properties = array(); @@ -142,20 +149,20 @@ public function getExportProperties() { } /** - * Creates a duplicate of the EntityDisplay object on a different view mode. + * Creates a duplicate object on a different form or view mode. * * The new object necessarily has the same $targetEntityType and $bundle - * properties than the original one. + * properties as the original one. * - * @param $view_mode - * The view mode for the new object. + * @param string $mode + * The form or view mode for the new object. * - * @return \Drupal\entity\Plugin\Core\Entity\EntityDisplay + * @return \Drupal\entity\EntityDisplayBase * The new object. */ - public function createCopy($view_mode) { + public function createCopy($mode) { $display = $this->createDuplicate(); - $display->viewMode = $display->originalViewMode = $view_mode; + $display->mode = $display->originalMode = $mode; return $display; } @@ -188,7 +195,7 @@ public function getComponents() { */ public function getComponent($name) { // We always store 'extra fields', whether they are visible or hidden. - $extra_fields = field_info_extra_fields($this->targetEntityType, $this->bundle, 'display'); + $extra_fields = field_info_extra_fields($this->targetEntityType, $this->bundle, $this->displayContext); if (isset($extra_fields[$name])) { // If we have explicit settings, return an array or NULL depending on // visibility. @@ -229,8 +236,8 @@ public function getComponent($name) { * @param array $options * The display options. * - * @return \Drupal\entity\Plugin\Core\Entity\EntityDisplay - * The EntityDisplay object. + * @return \Drupal\entity\EntityDisplayBase + * The EntityDisplayBase object. */ public function setComponent($name, array $options = array()) { // If no weight specified, make sure the field sinks at the bottom. @@ -241,14 +248,14 @@ public function setComponent($name, array $options = array()) { if ($instance = field_info_instance($this->targetEntityType, $name, $this->bundle)) { $field = field_info_field($instance['field_name']); - $options = drupal_container()->get('plugin.manager.field.formatter')->prepareConfiguration($field['type'], $options); + $options = $this->pluginManager->prepareConfiguration($field['type'], $options); - // Clear the persisted formatter, if any. - unset($this->formatters[$name]); + // Clear the persisted plugin, if any. + unset($this->plugins[$name]); } // We always store 'extra fields', whether they are visible or hidden. - $extra_fields = field_info_extra_fields($this->targetEntityType, $this->bundle, 'display'); + $extra_fields = field_info_extra_fields($this->targetEntityType, $this->bundle, $this->displayContext); if (isset($extra_fields[$name])) { $options['visible'] = TRUE; } @@ -264,11 +271,11 @@ public function setComponent($name, array $options = array()) { * @param string $name * The name of the component. * - * @return \Drupal\entity\Plugin\Core\Entity\EntityDisplay - * The EntityDisplay object. + * @return \Drupal\entity\EntityDisplayBase + * The EntityDisplayBase object. */ public function removeComponent($name) { - $extra_fields = field_info_extra_fields($this->targetEntityType, $this->bundle, 'display'); + $extra_fields = field_info_extra_fields($this->targetEntityType, $this->bundle, $this->displayContext); if (isset($extra_fields[$name])) { // 'Extra fields' are exposed in hooks and can appear at any given time. // Therefore we store extra fields that are explicitly being hidden, so @@ -280,7 +287,7 @@ public function removeComponent($name) { } else { unset($this->content[$name]); - unset($this->formatters[$name]); + unset($this->plugins[$name]); } return $this; @@ -304,44 +311,9 @@ public function getHighestWeight() { } // Let other modules feedback about their own additions. - $weights = array_merge($weights, module_invoke_all('field_info_max_weight', $this->targetEntityType, $this->bundle, $this->viewMode)); + $weights = array_merge($weights, module_invoke_all('field_info_max_weight', $this->targetEntityType, $this->bundle, $this->displayContext, $this->mode)); return $weights ? max($weights) : NULL; } - /** - * Returns the Formatter plugin for a field. - * - * @param string $field_name - * The field name. - * - * @return \Drupal\field\Plugin\Type\Formatter\FormatterInterface - * If the field is not hidden, the Formatter plugin to use for rendering - * it. - */ - public function getFormatter($field_name) { - if (isset($this->formatters[$field_name])) { - return $this->formatters[$field_name]; - } - - // Instantiate the formatter object from the stored display properties. - if ($configuration = $this->getComponent($field_name)) { - $instance = field_info_instance($this->targetEntityType, $field_name, $this->bundle); - $formatter = drupal_container()->get('plugin.manager.field.formatter')->getInstance(array( - 'instance' => $instance, - 'view_mode' => $this->originalViewMode, - // No need to prepare, defaults have been merged in setComponent(). - 'prepare' => FALSE, - 'configuration' => $configuration - )); - } - else { - $formatter = NULL; - } - - // Persist the formatter object. - $this->formatters[$field_name] = $formatter; - return $formatter; - } - } diff --git a/core/modules/entity/lib/Drupal/entity/Plugin/Core/Entity/EntityDisplay.php b/core/modules/entity/lib/Drupal/entity/Plugin/Core/Entity/EntityDisplay.php index af01eb4..05754d9 100644 --- a/core/modules/entity/lib/Drupal/entity/Plugin/Core/Entity/EntityDisplay.php +++ b/core/modules/entity/lib/Drupal/entity/Plugin/Core/Entity/EntityDisplay.php @@ -7,13 +7,13 @@ namespace Drupal\entity\Plugin\Core\Entity; -use Drupal\Core\Config\Entity\ConfigEntityBase; use Drupal\Core\Entity\Annotation\EntityType; use Drupal\Core\Annotation\Translation; +use Drupal\entity\EntityDisplayBase; /** * Configuration entity that contains display options for all components of a - * rendered entity in a given view mode.. + * rendered entity in a given view mode. * * @EntityType( * id = "entity_display", @@ -29,284 +29,16 @@ * } * ) */ -class EntityDisplay extends ConfigEntityBase { +class EntityDisplay extends EntityDisplayBase { /** - * Unique ID for the config entity. - * - * @var string - */ - public $id; - - /** - * Unique UUID for the config entity. - * - * @var string - */ - public $uuid; - - /** - * Entity type to be displayed. - * - * @var string - */ - public $targetEntityType; - - /** - * Bundle to be displayed. - * - * @var string - */ - public $bundle; - - /** - * View mode to be displayed. - * - * @var string - */ - public $viewMode; - - /** - * List of component display options, keyed by component name. - * - * @var array - */ - protected $content = array(); - - /** - * The original view mode that was requested (case of view modes being - * configured to fall back to the 'default' display). - * - * @var string - */ - public $originalViewMode; - - /** - * The formatter objects used for this display, keyed by field name. - * - * @var array - */ - protected $formatters = array(); - - /** - * Overrides \Drupal\Core\Config\Entity\ConfigEntityBase::__construct(). + * Overrides \Drupal\entity\EntityDisplayBase::__construct(). */ public function __construct(array $values, $entity_type) { - // @todo See http://drupal.org/node/1825044#comment-6847792: contact.module - // currently produces invalid entities with a NULL bundle in some cases. - // Add the validity checks back when http://drupal.org/node/1856556 is - // fixed. - // if (!isset($values['targetEntityType']) || !isset($values['bundle']) || !isset($values['viewMode'])) { - // throw new \InvalidArgumentException('Missing required properties for an EntiyDisplay entity.'); - // } - parent::__construct($values, $entity_type); - - $this->originalViewMode = $this->viewMode; - } - - /** - * Overrides \Drupal\Core\Entity\Entity::id(). - */ - public function id() { - return $this->targetEntityType . '.' . $this->bundle . '.' . $this->viewMode; - } - - /** - * Overrides \Drupal\config\ConfigEntityBase::save(). - */ - public function save() { - // Build an ID if none is set. - if (empty($this->id)) { - $this->id = $this->id(); - } - return parent::save(); - } - - /** - * Overrides \Drupal\config\ConfigEntityBase::getExportProperties(); - */ - public function getExportProperties() { - $names = array( - 'id', - 'uuid', - 'targetEntityType', - 'bundle', - 'viewMode', - 'content', - ); - $properties = array(); - foreach ($names as $name) { - $properties[$name] = $this->get($name); - } - return $properties; - } - - /** - * Creates a duplicate of the EntityDisplay object on a different view mode. - * - * The new object necessarily has the same $targetEntityType and $bundle - * properties than the original one. - * - * @param $view_mode - * The view mode for the new object. - * - * @return \Drupal\entity\Plugin\Core\Entity\EntityDisplay - * The new object. - */ - public function createCopy($view_mode) { - $display = $this->createDuplicate(); - $display->viewMode = $display->originalViewMode = $view_mode; - return $display; - } - - /** - * Gets the display options for all components. - * - * @return array - * The array of display options, keyed by component name. - */ - public function getComponents() { - $result = array(); - foreach ($this->content as $name => $options) { - if (!isset($options['visible']) || $options['visible'] === TRUE) { - unset($options['visible']); - $result[$name] = $options; - } - } - return $result; - } - - /** - * Gets the display options set for a component. - * - * @param string $name - * The name of the component. - * - * @return array|null - * The display options for the component, or NULL if the component is not - * displayed. - */ - public function getComponent($name) { - // We always store 'extra fields', whether they are visible or hidden. - $extra_fields = field_info_extra_fields($this->targetEntityType, $this->bundle, 'display'); - if (isset($extra_fields[$name])) { - // If we have explicit settings, return an array or NULL depending on - // visibility. - if (isset($this->content[$name])) { - if ($this->content[$name]['visible']) { - return array( - 'weight' => $this->content[$name]['weight'], - ); - } - else { - return NULL; - } - } - - // If no explicit settings for the extra field, look at the default - // visibility in its definition. - $definition = $extra_fields[$name]; - if (!isset($definition['visible']) || $definition['visible'] == TRUE) { - return array( - 'weight' => $definition['weight'] - ); - } - else { - return NULL; - } - } - - if (isset($this->content[$name])) { - return $this->content[$name]; - } - } - - /** - * Sets the display options for a component. - * - * @param string $name - * The name of the component. - * @param array $options - * The display options. - * - * @return \Drupal\entity\Plugin\Core\Entity\EntityDisplay - * The EntityDisplay object. - */ - public function setComponent($name, array $options = array()) { - // If no weight specified, make sure the field sinks at the bottom. - if (!isset($options['weight'])) { - $max = $this->getHighestWeight(); - $options['weight'] = isset($max) ? $max + 1 : 0; - } + $this->pluginManager = \Drupal::service('plugin.manager.field.formatter'); + $this->displayContext = 'display'; - if ($instance = field_info_instance($this->targetEntityType, $name, $this->bundle)) { - $field = field_info_field($instance['field_name']); - $options = drupal_container()->get('plugin.manager.field.formatter')->prepareConfiguration($field['type'], $options); - - // Clear the persisted formatter, if any. - unset($this->formatters[$name]); - } - - // We always store 'extra fields', whether they are visible or hidden. - $extra_fields = field_info_extra_fields($this->targetEntityType, $this->bundle, 'display'); - if (isset($extra_fields[$name])) { - $options['visible'] = TRUE; - } - - $this->content[$name] = $options; - - return $this; - } - - /** - * Sets a component to be hidden. - * - * @param string $name - * The name of the component. - * - * @return \Drupal\entity\Plugin\Core\Entity\EntityDisplay - * The EntityDisplay object. - */ - public function removeComponent($name) { - $extra_fields = field_info_extra_fields($this->targetEntityType, $this->bundle, 'display'); - if (isset($extra_fields[$name])) { - // 'Extra fields' are exposed in hooks and can appear at any given time. - // Therefore we store extra fields that are explicitly being hidden, so - // that we can differenciate with those that are simply not configured - // yet. - $this->content[$name] = array( - 'visible' => FALSE, - ); - } - else { - unset($this->content[$name]); - unset($this->formatters[$name]); - } - - return $this; - } - - /** - * Returns the highest weight of the components in the display. - * - * @return int|null - * The highest weight of the components in the display, or NULL if the - * display is empty. - */ - public function getHighestWeight() { - $weights = array(); - - // Collect weights for the components in the display. - foreach ($this->content as $options) { - if (isset($options['weight'])) { - $weights[] = $options['weight']; - } - } - - // Let other modules feedback about their own additions. - $weights = array_merge($weights, module_invoke_all('field_info_max_weight', $this->targetEntityType, $this->bundle, $this->viewMode)); - - return $weights ? max($weights) : NULL; + parent::__construct($values, $entity_type); } /** @@ -320,16 +52,16 @@ public function getHighestWeight() { * it. */ public function getFormatter($field_name) { - if (isset($this->formatters[$field_name])) { - return $this->formatters[$field_name]; + if (isset($this->plugins[$field_name])) { + return $this->plugins[$field_name]; } // Instantiate the formatter object from the stored display properties. if ($configuration = $this->getComponent($field_name)) { $instance = field_info_instance($this->targetEntityType, $field_name, $this->bundle); - $formatter = drupal_container()->get('plugin.manager.field.formatter')->getInstance(array( + $formatter = $this->pluginManager->getInstance(array( 'instance' => $instance, - 'view_mode' => $this->originalViewMode, + 'view_mode' => $this->originalMode, // No need to prepare, defaults have been merged in setComponent(). 'prepare' => FALSE, 'configuration' => $configuration @@ -340,7 +72,7 @@ public function getFormatter($field_name) { } // Persist the formatter object. - $this->formatters[$field_name] = $formatter; + $this->plugins[$field_name] = $formatter; return $formatter; } diff --git a/core/modules/entity/lib/Drupal/entity/Plugin/Core/Entity/EntityFormDisplay.php b/core/modules/entity/lib/Drupal/entity/Plugin/Core/Entity/EntityFormDisplay.php new file mode 100644 index 0000000..c69ed33 --- /dev/null +++ b/core/modules/entity/lib/Drupal/entity/Plugin/Core/Entity/EntityFormDisplay.php @@ -0,0 +1,97 @@ +pluginManager = \Drupal::service('plugin.manager.field.widget'); + $this->displayContext = 'form'; + + parent::__construct($values, $entity_type); + } + + /** + * Returns the Widget plugin for a field. + * + * @param string $field_name + * The field name. + * + * @return \Drupal\field\Plugin\Type\Widget\WidgetInterface|null + * A Widget plugin or NULL if the field does not exist. + */ + public function getWidget($field_name) { + if (isset($this->plugins[$field_name])) { + return $this->plugins[$field_name]; + } + + // Instantiate the widget object from the stored display properties. + if ($configuration = $this->getComponent($field_name)) { + $instance = field_info_instance($this->targetEntityType, $field_name, $this->bundle); + $widget = $this->pluginManager->getInstance(array( + 'instance' => $instance, + 'form_mode' => $this->originalMode, + // No need to prepare, defaults have been merged in setComponent(). + 'prepare' => FALSE, + 'configuration' => $configuration + )); + } + else { + $widget = NULL; + } + + // Persist the widget object. + $this->plugins[$field_name] = $widget; + return $widget; + } + + /** + * {@inheritdoc} + */ + public function serialize() { + // Only store the definition, not external objects or derived data. + $data = $this->getExportProperties() + array('entityType' => $this->entityType()); + return serialize($data); + } + + /** + * {@inheritdoc} + */ + public function unserialize($serialized) { + $data = unserialize($serialized); + $entity_type = $data['entityType']; + unset($data['entityType']); + $this->__construct($data, $entity_type); + } + +} diff --git a/core/modules/entity/lib/Drupal/entity/Tests/EntityDisplayTest.php b/core/modules/entity/lib/Drupal/entity/Tests/EntityDisplayTest.php index 11f6da7..f846594 100644 --- a/core/modules/entity/lib/Drupal/entity/Tests/EntityDisplayTest.php +++ b/core/modules/entity/lib/Drupal/entity/Tests/EntityDisplayTest.php @@ -36,7 +36,7 @@ public function testEntityDisplayCRUD() { $display = entity_create('entity_display', array( 'targetEntityType' => 'entity_test', 'bundle' => 'entity_test', - 'viewMode' => 'default', + 'mode' => 'default', )); $expected = array(); @@ -81,7 +81,7 @@ public function testEntityDisplayCRUD() { $new_display = entity_load('entity_display', $new_display->id()); $this->assertEqual($new_display->targetEntityType, $display->targetEntityType); $this->assertEqual($new_display->bundle, $display->bundle); - $this->assertEqual($new_display->viewMode, 'other_view_mode'); + $this->assertEqual($new_display->mode, 'other_view_mode'); $this->assertEqual($new_display->getComponents(), $display->getComponents()); } @@ -112,7 +112,7 @@ public function testExtraFieldComponent() { $display = entity_create('entity_display', array( 'targetEntityType' => 'entity_test', 'bundle' => 'entity_test', - 'viewMode' => 'default', + 'mode' => 'default', )); // Check that the default visibility taken into account for extra fields @@ -136,7 +136,7 @@ public function testFieldComponent() { $display = entity_create('entity_display', array( 'targetEntityType' => 'entity_test', 'bundle' => 'entity_test', - 'viewMode' => 'default', + 'mode' => 'default', )); // Create a field and an instance. diff --git a/core/modules/entity/lib/Drupal/entity/Tests/EntityFormDisplayTest.php b/core/modules/entity/lib/Drupal/entity/Tests/EntityFormDisplayTest.php new file mode 100644 index 0000000..f30b69c --- /dev/null +++ b/core/modules/entity/lib/Drupal/entity/Tests/EntityFormDisplayTest.php @@ -0,0 +1,121 @@ + 'Entity form display configuration entities', + 'description' => 'Tests the entity form display configuration entities.', + 'group' => 'Entity API', + ); + } + + protected function setUp() { + parent::setUp(); + $this->installConfig(array('field')); + } + + /** + * Tests entity_get_form_display(). + */ + public function testEntityGetFromDisplay() { + // Check that entity_get_form_display() returns a fresh object when no + // configuration entry exists. + $form_display = entity_get_form_display('entity_test', 'entity_test', 'default'); + $this->assertTrue($form_display->isNew()); + + // Add some components and save the display. + $form_display->setComponent('component_1', array('weight' => 10)) + ->save(); + + // Check that entity_get_form_display() returns the correct object. + $form_display = entity_get_form_display('entity_test', 'entity_test', 'default'); + $this->assertFalse($form_display->isNew()); + $this->assertEqual($form_display->id, 'entity_test.entity_test.default'); + $this->assertEqual($form_display->getComponent('component_1'), array('weight' => 10)); + } + + /** + * Tests the behavior of a field component within an EntityFormDisplay object. + */ + public function testFieldComponent() { + $this->enableModules(array('field_sql_storage', 'field_test')); + + $form_display = entity_create('entity_form_display', array( + 'targetEntityType' => 'entity_test', + 'bundle' => 'entity_test', + 'mode' => 'default', + )); + + // Create a field and an instance. + $field = array( + 'field_name' => 'test_field', + 'type' => 'test_field' + ); + field_create_field($field); + $instance = array( + 'field_name' => $field['field_name'], + 'entity_type' => 'entity_test', + 'bundle' => 'entity_test', + ); + field_create_instance($instance); + + // Check that providing no options results in default values being used. + $form_display->setComponent($field['field_name']); + $field_type_info = field_info_field_types($field['type']); + $default_widget = $field_type_info['default_widget']; + $default_settings = field_info_widget_settings($default_widget); + $expected = array( + 'weight' => 0, + 'type' => $default_widget, + 'settings' => $default_settings, + ); + $this->assertEqual($form_display->getComponent($field['field_name']), $expected); + + // Check that the getWidget() method returns the correct widget plugin. + $widget = $form_display->getWidget($field['field_name']); + $this->assertEqual($widget->getPluginId(), $default_widget); + $this->assertEqual($widget->getSettings(), $default_settings); + + // Check that the widget is statically persisted, by assigning an + // arbitrary property and reading it back. + $random_value = $this->randomString(); + $widget->randomValue = $random_value; + $widget = $form_display->getWidget($field['field_name']); + $this->assertEqual($widget->randomValue, $random_value ); + + // Check that changing the definition creates a new widget. + $form_display->setComponent($field['field_name'], array( + 'type' => 'field_test_multiple', + )); + $widget = $form_display->getWidget($field['field_name']); + $this->assertEqual($widget->getPluginId(), 'test_field_widget'); + $this->assertFalse(isset($widget->randomValue)); + + // Check that specifying an unknown widget (e.g. case of a disabled module) + // gets stored as is in the display, but results in the default widget being + // used. + $form_display->setComponent($field['field_name'], array( + 'type' => 'unknown_widget', + )); + $options = $form_display->getComponent($field['field_name']); + $this->assertEqual($options['type'], 'unknown_widget'); + $widget = $form_display->getWidget($field['field_name']); + $this->assertEqual($widget->getPluginId(), $default_widget); + } + +} diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/EntityReferenceAutocomplete.php b/core/modules/entity_reference/lib/Drupal/entity_reference/EntityReferenceAutocomplete.php index b3fe3a0..6168bea 100644 --- a/core/modules/entity_reference/lib/Drupal/entity_reference/EntityReferenceAutocomplete.php +++ b/core/modules/entity_reference/lib/Drupal/entity_reference/EntityReferenceAutocomplete.php @@ -75,7 +75,8 @@ public function getMatches($field, $instance, $entity_type, $entity_id = '', $pr if (isset($string)) { // Get an array of matching entities. - $match_operator = !empty($instance['widget']['settings']['match_operator']) ? $instance['widget']['settings']['match_operator'] : 'CONTAINS'; + $widget = entity_get_form_display($instance['entity_type'], $instance['bundle'], 'default')->getComponent($instance['field_name']); + $match_operator = !empty($widget['settings']['match_operator']) ? $widget['settings']['match_operator'] : 'CONTAINS'; $entity_labels = $handler->getReferencableEntities($string, $match_operator, 10); // Loop through the entities and convert them into autocomplete output. diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceAutoCreateTest.php b/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceAutoCreateTest.php index 99ebe15..ace6f5d 100644 --- a/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceAutoCreateTest.php +++ b/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceAutoCreateTest.php @@ -66,6 +66,12 @@ function setUp() { ); field_create_instance($instance); + + entity_get_form_display('node', $referencing->type, 'default') + ->setComponent('test_field', array( + 'type' => 'entity_reference_autocomplete', + )) + ->save(); } /** diff --git a/core/modules/field/field.api.php b/core/modules/field/field.api.php index 5ba15c9..01d72aa 100644 --- a/core/modules/field/field.api.php +++ b/core/modules/field/field.api.php @@ -21,10 +21,9 @@ * 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 + * @return array * A nested array of 'pseudo-field' elements. Each list is nested within the * following keys: entity type, bundle name, context (either 'form' or * 'display'). The keys are the name of the elements as appearing in the @@ -33,8 +32,7 @@ * - label: The human readable name of the element. * - description: A short description of the element contents. * - weight: The default weight of the element. - * - visible: The default visibility of the element. Only for 'display' - * context. + * - visible: The default visibility of the element. * - edit: (optional) String containing markup (normally a link) used as the * element's 'edit' operation in the administration interface. Only for * 'form' context. @@ -784,38 +782,6 @@ function hook_field_widget_WIDGET_TYPE_form_alter(&$element, &$form_state, $cont } /** - * Alters the widget properties of a field instance before it gets displayed. - * - * Note that instead of hook_field_widget_properties_alter(), which is called - * for all fields on all entity types, - * hook_field_widget_properties_ENTITY_TYPE_alter() may be used to alter widget - * properties for fields on a specific entity type only. - * - * This hook is called once per field per added or edit entity. If the result - * of the hook involves reading from the database, it is highly recommended to - * statically cache the information. - * - * @param array $widget_properties - * The instance's widget properties. - * @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'. - * - field: The field that the widget belongs to. - * - instance: The instance of the field. - * - * @see hook_field_widget_properties_ENTITY_TYPE_alter() - */ -function hook_field_widget_properties_alter(array &$widget_properties, array $context) { - // Change a widget's type according to the time of day. - $field = $context['field']; - if ($context['entity_type'] == 'node' && $field['field_name'] == 'field_foo') { - $time = date('H'); - $widget_properties['type'] = $time < 12 ? 'widget_am' : 'widget_pm'; - } -} - -/** * @} End of "defgroup field_widget". */ @@ -1819,21 +1785,24 @@ function hook_field_storage_pre_update(\Drupal\Core\Entity\EntityInterface $enti * Field API takes care of fields and 'extra_fields'. This hook is intended for * third-party modules adding other entity components (e.g. field_group). * - * @param $entity_type + * @param string $entity_type * The type of entity; e.g. 'node' or 'user'. - * @param $bundle + * @param string $bundle * The bundle name. - * @param $context - * The context for which the maximum weight is requested. Either 'form', or - * the name of a view mode. - * @return + * @param string $context + * The context for which the maximum weight is requested. Either 'form' or + * 'display'. + * @param string $context_mode + * The view or form mode name. + * + * @return int * The maximum weight of the entity's components, or NULL if no components * were found. */ -function hook_field_info_max_weight($entity_type, $bundle, $context) { +function hook_field_info_max_weight($entity_type, $bundle, $context, $context_mode) { $weights = array(); - foreach (my_module_entity_additions($entity_type, $bundle, $context) as $addition) { + foreach (my_module_entity_additions($entity_type, $bundle, $context, $context_mode) as $addition) { $weights[] = $addition['weight']; } @@ -1841,38 +1810,6 @@ function hook_field_info_max_weight($entity_type, $bundle, $context) { } /** - * Alters the widget properties of a field instance on a given entity type - * before it gets displayed. - * - * Modules can implement hook_field_widget_properties_ENTITY_TYPE_alter() to - * alter the widget properties for fields on a specific entity type, rather than - * implementing hook_field_widget_properties_alter(). - * - * This hook is called once per field per displayed widget entity. If the result - * of the hook involves reading from the database, it is highly recommended to - * statically cache the information. - * - * @param array $widget_properties - * The instance's widget properties. - * @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'. - * - field: The field that the widget belongs to. - * - instance: The instance of the field. - * - * @see hook_field_widget_properties_alter() - */ -function hook_field_widget_properties_ENTITY_TYPE_alter(array &$widget_properties, array $context) { - // Change a widget's type according to the time of day. - $field = $context['field']; - if ($field['field_name'] == 'field_foo') { - $time = date('H'); - $widget_properties['type'] = $time < 12 ? 'widget_am' : 'widget_pm'; - } -} - -/** * @} End of "addtogroup field_storage". */ diff --git a/core/modules/field/field.attach.inc b/core/modules/field/field.attach.inc index cde15f4..b508454 100644 --- a/core/modules/field/field.attach.inc +++ b/core/modules/field/field.attach.inc @@ -8,6 +8,7 @@ use Drupal\field\FieldValidationException; use Drupal\Core\Entity\EntityInterface; use Drupal\entity\Plugin\Core\Entity\EntityDisplay; +use Drupal\entity\Plugin\Core\Entity\EntityFormDisplay; /** * @defgroup field_storage Field Storage API @@ -705,12 +706,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 $form_display + * An EntityFormDisplay object. + * * @return callable $target_function * A 'target function' for field_invoke_method(). */ -function _field_invoke_widget_target() { - return function ($instance) { - return $instance->getWidget(); +function _field_invoke_widget_target($form_display) { + return function ($instance) use ($form_display) { + return $form_display->getWidget($instance['field_name']); }; } @@ -825,12 +829,13 @@ function field_attach_form(EntityInterface $entity, &$form, &$form_state, $langc // Set #parents to 'top-level' by default. $form += array('#parents' => array()); + // 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, $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(); @@ -1092,7 +1097,8 @@ function field_attach_form_validate(EntityInterface $entity, $form, &$form_state field_form_set_state($form['#parents'], $field_name, $langcode, $form_state, $field_state); } } - field_invoke_method('flagErrors', _field_invoke_widget_target(), $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); } } @@ -1116,7 +1122,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. - field_invoke_method('extractFormValues', _field_invoke_widget_target(), $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. @@ -1432,7 +1439,7 @@ function field_attach_view(EntityInterface $entity, EntityDisplay $display, $lan $entity = $entity->getNGEntity(); // Let other modules alter the renderable array. - $view_mode = $display->originalViewMode; + $view_mode = $display->originalMode; $context = array( 'entity' => $entity, 'view_mode' => $view_mode, diff --git a/core/modules/field/field.info.inc b/core/modules/field/field.info.inc index 38edcdb..d4b439e 100644 --- a/core/modules/field/field.info.inc +++ b/core/modules/field/field.info.inc @@ -130,20 +130,23 @@ function _field_info_collate_types_reset() { /** * Determines the behavior of a widget with respect to an operation. * - * @param $op - * The name of the operation. Currently supported: 'default value', 'multiple - * values'. - * @param $instance + * @param string $op + * The name of the operation. Currently supported: 'default_value', + * 'multiple_values'. + * @param array $instance * The field instance array. * - * @return + * @return int * One of these values: * - FIELD_BEHAVIOR_NONE: Do nothing for this operation. * - FIELD_BEHAVIOR_CUSTOM: Use the widget's callback function. * - FIELD_BEHAVIOR_DEFAULT: Use field.module default behavior. */ function field_behaviors_widget($op, $instance) { - $info = field_info_widget_types($instance['widget']['type']); + $info = array(); + if ($component = entity_get_form_display($instance['entity_type'], $instance['bundle'], 'default')->getComponent($instance['field_name'])) { + $info = field_info_widget_types($component['type']); + } return isset($info[$op]) ? $info[$op] : FIELD_BEHAVIOR_DEFAULT; } @@ -478,40 +481,6 @@ function field_info_extra_fields($entity_type, $bundle, $context) { } /** - * Returns the maximum weight of all the components in a form entity. - * - * This includes fields, 'extra_fields', and other components added by - * third-party modules (e.g. field_group). - * - * @param $entity_type - * The type of entity; e.g. 'node' or 'user'. - * @param $bundle - * The bundle name. - * - * @return - * The maximum weight of the entity's components, or NULL if no components - * were found. - */ -function field_info_max_weight($entity_type, $bundle) { - $weights = array(); - - // Collect weights for fields. - foreach (field_info_instances($entity_type, $bundle) as $instance) { - $weights[] = $instance['widget']['weight']; - } - // Collect weights for extra fields. - foreach (field_info_extra_fields($entity_type, $bundle, 'form') as $extra) { - $weights[] = $extra['weight']; - } - - // Let other modules feedback about their own additions. - $weights = array_merge($weights, module_invoke_all('field_info_max_weight', $entity_type, $bundle, 'form')); - $max_weight = $weights ? max($weights) : NULL; - - return $max_weight; -} - -/** * Returns a field type's default settings. * * @param $type diff --git a/core/modules/field/field.install b/core/modules/field/field.install index dcf2b38..dc20e25 100644 --- a/core/modules/field/field.install +++ b/core/modules/field/field.install @@ -250,12 +250,12 @@ function field_update_8001() { } /** - * Migrate all instance display settings to configuration. + * Migrate all instance widget and display settings to configuration. * * @ingroup config_upgrade */ function field_update_8002() { - $displays = array(); + $form_displays = $displays = array(); module_load_install('entity'); $query = db_select('field_config_instance', 'fc')->fields('fc'); @@ -266,28 +266,46 @@ function field_update_8002() { // Skip field instances that were created directly with the new API earlier // in the upgrade path. - if (!isset($data['display'])) { + if (!isset($data['widget']) && !isset($data['display'])) { continue; } - foreach ($data['display'] as $view_mode => $display_options) { - // Determine name and create initial entry in the $displays array if it - // does not exist yet. - $display_id = $record->entity_type . '.' . $record->bundle . '.' . $view_mode; - if (!isset($displays[$display_id])) { - $displays[$display_id] = _update_8000_entity_get_display($record->entity_type, $record->bundle, $view_mode); + // Migrate 'widget' settings. + if (isset($data['widget'])) { + $widget_options = $data['widget']; + // Determine name and create initial entry in the $form_displays array. + $form_display_id = $record->entity_type . '.' . $record->bundle . '.default'; + if (!isset($form_displays[$form_display_id])) { + $form_displays[$form_display_id] = _update_8000_entity_get_form_display($record->entity_type, $record->bundle, 'default'); } - // The display object does not store hidden fields. - if ($display_options['type'] != 'hidden') { - // We do not need the 'module' key anymore. - unset($display_options['module']); - $displays[$display_id]->set("content.$record->field_name", $display_options); + // We do not need the 'module' key anymore. + unset($widget_options['module']); + $form_displays[$form_display_id]->set("content.$record->field_name", $widget_options); + } + + // Migrate 'display' settings. + if (isset($data['display'])) { + foreach ($data['display'] as $view_mode => $display_options) { + // Determine name and create initial entry in the $displays array if it + // does not exist yet. + $display_id = $record->entity_type . '.' . $record->bundle . '.' . $view_mode; + if (!isset($displays[$display_id])) { + $displays[$display_id] = _update_8000_entity_get_display($record->entity_type, $record->bundle, $view_mode); + } + + // The display object does not store hidden fields. + if ($display_options['type'] != 'hidden') { + // We do not need the 'module' key anymore. + unset($display_options['module']); + $displays[$display_id]->set("content.$record->field_name", $display_options); + } } } - // Remove the 'display' key and save the record back into the table. - unset($data['display']); + // Remove the 'widget' and 'display' keys and save the record back into the + // table. + unset($data['display'], $data['widget']); db_update('field_config_instance') ->condition('id', $record->id) ->fields(array( @@ -302,8 +320,26 @@ function field_update_8002() { $variables = array_map('unserialize', db_query("SELECT name, value FROM {variable} WHERE name LIKE '%field_bundle_settings_%'")->fetchAllKeyed()); foreach ($variables as $variable_name => $variable_value) { if (preg_match('/field_bundle_settings_(.*)__(.*)/', $variable_name, $matches)) { + $variable_needs_update = FALSE; $entity_type = $matches[1]; $bundle = $matches[2]; + + if (isset($variable_value['extra_fields']['form'])) { + foreach ($variable_value['extra_fields']['form'] as $field_name => $field_settings) { + // Determine name and create initial entry in the $form_displays + // array if it does not exist yet. + $form_display_id = $entity_type . '.' . $bundle . '.default'; + if (!isset($form_displays[$form_display_id])) { + $form_displays[$form_display_id] = _update_8000_entity_get_form_display($entity_type, $bundle, 'default'); + } + $form_displays[$form_display_id]->set("content.$field_name", $field_settings); + } + + // Remove the old entry. + unset($variable_value['extra_fields']['form']); + $variable_needs_update = TRUE; + } + if (isset($variable_value['extra_fields']['display'])) { foreach ($variable_value['extra_fields']['display'] as $field_name => $field_settings) { foreach ($field_settings as $view_mode => $display_options) { @@ -322,16 +358,26 @@ function field_update_8002() { $new_options['weight'] = $display_options['weight']; } $displays[$display_id]->set("content.$field_name", $new_options); - - // Remove the old entry. - unset($variable_value['extra_fields']['display']); - variable_set($variable_name, $variable_value); } } + + // Remove the old entry. + unset($variable_value['extra_fields']['display']); + $variable_needs_update = TRUE; + } + + if ($variable_needs_update) { + variable_set($variable_name, $variable_value); } } } + // Save the form displays to configuration. + foreach ($form_displays as $config) { + $config->save(); + } + update_config_manifest_add('entity.form_display', array_keys($form_displays)); + // Save the displays to configuration. foreach ($displays as $config) { $config->save(); @@ -437,7 +483,6 @@ function field_update_8003() { 'default_value' => isset($record['data']['default_value']) ? $record['data']['default_value'] : array(), 'default_value_function' => isset($record['data']['default_value_function']) ? $record['data']['default_value_function'] : '', 'settings' => $record['data']['settings'], - 'widget' => $record['data']['widget'], 'status' => 1, 'langcode' => 'und', ); diff --git a/core/modules/field/field.module b/core/modules/field/field.module index 8f459a3..dfcc39d 100644 --- a/core/modules/field/field.module +++ b/core/modules/field/field.module @@ -603,10 +603,6 @@ function field_bundle_settings($entity_type, $bundle, $settings = NULL) { $settings = variable_get('field_bundle_settings_' . $entity_type . '__' . $bundle, array()); $settings += array( 'view_modes' => array(), - 'extra_fields' => array(), - ); - $settings['extra_fields'] += array( - 'form' => array(), ); return $settings; @@ -649,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/Core/Entity/FieldInstance.php b/core/modules/field/lib/Drupal/field/Plugin/Core/Entity/FieldInstance.php index 4c66575..176641f 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 @@ -171,24 +171,6 @@ class FieldInstance extends ConfigEntityBase implements \ArrayAccess, \Serializa public $default_value_function = ''; /** - * The widget definition. - * - * An array of key/value pairs identifying the Form API input widget for - * the field when used by this bundle. - * - type: (string) The plugin ID of the widget, such as text_textfield. - * - settings: (array) A sub-array of key/value pairs of settings. The keys - * and default values are defined by the widget plugin in the 'settings' - * entry of its "plugin definition" (typycally plugin class annotations). - * - weight: (float) The weight of the widget relative to the other - * elements in entity edit forms. - * - module: (string, read-only) The name of the module that provides the - * widget plugin. - * - * @var array - */ - public $widget = array(); - - /** * Flag indicating whether the instance is deleted. * * The delete() method marks the instance as "deleted" and removes the @@ -211,13 +193,6 @@ class FieldInstance extends ConfigEntityBase implements \ArrayAccess, \Serializa protected $field; /** - * The widget plugin used for this instance. - * - * @var \Drupal\field\Plugin\Type\Widget\WidgetInterface - */ - protected $widgetPlugin; - - /** * Flag indicating whether the bundle name can be renamed or not. * * @var bool @@ -301,7 +276,6 @@ public function getExportProperties() { 'default_value', 'default_value_function', 'settings', - 'widget', ); $properties = array(); foreach ($names as $name) { @@ -366,22 +340,6 @@ public function save() { // Set the default instance settings. $this->settings += $field_type_info['instance_settings']; - // Set the default widget and settings. - $this->widget += array( - 'type' => $field_type_info['default_widget'], - 'settings' => array(), - ); - // Get the widget module and settings from the widget type. - if ($widget_type_info = \Drupal::service('plugin.manager.field.widget')->getDefinition($this->widget['type'])) { - $this->widget['module'] = $widget_type_info['module']; - $this->widget['settings'] += $widget_type_info['settings']; - } - // If no weight is specified, make sure the field sinks to the bottom. - if (!isset($this->widget['weight'])) { - $max_weight = field_info_max_weight($this->entity_type, $this->bundle, 'form'); - $this->widget['weight'] = isset($max_weight) ? $max_weight + 1 : 0; - } - // Save the configuration. $result = parent::save(); field_cache_clear(); @@ -429,6 +387,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->id)->save(); + } + // Delete the field itself if we just deleted its last instance. if ($field_cleanup && count($this->field->getBundles()) == 0) { $this->field->delete(); @@ -447,39 +410,6 @@ public function getField() { } /** - * Returns the Widget plugin for the instance. - * - * @return Drupal\field\Plugin\Type\Widget\WidgetInterface - * The Widget plugin to be used for the instance. - */ - public function getWidget() { - if (empty($this->widgetPlugin)) { - $widget_properties = $this->widget; - - // Let modules alter the widget properties. - $context = array( - 'entity_type' => $this->entity_type, - 'bundle' => $this->bundle, - 'field' => $this->field, - 'instance' => $this, - ); - // Invoke hook_field_widget_properties_alter() and - // hook_field_widget_properties_ENTITY_TYPE_alter(). - drupal_alter(array('field_widget_properties', 'field_widget_properties_' . $this->entity_type), $widget_properties, $context); - - $options = array( - 'instance' => $this, - 'type' => $widget_properties['type'], - 'settings' => $widget_properties['settings'], - 'weight' => $widget_properties['weight'], - ); - $this->widgetPlugin = \Drupal::service('plugin.manager.field.widget')->getInstance($options); - } - - return $this->widgetPlugin; - } - - /** * Allows a bundle to be renamed. * * Renaming a bundle on the instance is allowed when an entity's bundle 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 64c83a2..89c212a 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/field/lib/Drupal/field/Plugin/Type/Widget/WidgetPluginManager.php b/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetPluginManager.php index 6cbad1f..d412a0d 100644 --- a/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetPluginManager.php +++ b/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetPluginManager.php @@ -45,30 +45,79 @@ public function __construct(\Traversable $namespaces) { } /** - * Overrides Drupal\Component\Plugin\PluginManagerBase::getInstance(). + * Overrides PluginManagerBase::getInstance(). + * + * @param array $options + * An array with the following key/value pairs: + * - instance: (FieldInstance) The field instance. + * - form_mode: (string) The form mode. + * - prepare: (bool, optional) Whether default values should get merged in + * the 'configuration' array. Defaults to TRUE. + * - configuration: (array) the configuration for the widget. The + * following key value pairs are allowed, and are all optional if + * 'prepare' is TRUE: + * - type: (string) The widget to use. Defaults to the + * 'default_widget' for the field type, specified in + * hook_field_info(). The default widget will also be used if the + * requested widget is not available. + * - settings: (array) Settings specific to the widget. Each setting + * defaults to the default value specified in the widget definition. + * + * @return \Drupal\field\Plugin\Type\Widget\WidgetInterface + * A Widget object. */ public function getInstance(array $options) { + $configuration = $options['configuration']; $instance = $options['instance']; - $type = $options['type']; - - $definition = $this->getDefinition($type); $field = field_info_field($instance['field_name']); + // Fill in default configuration if needed. + if (!isset($options['prepare']) || $options['prepare'] == TRUE) { + $configuration = $this->prepareConfiguration($field['type'], $configuration); + } + + $plugin_id = $configuration['type']; + // Switch back to default widget if either: // - $type_info doesn't exist (the widget type is unknown), // - the field type is not allowed for the widget. + $definition = $this->getDefinition($configuration['type']); if (!isset($definition['class']) || !in_array($field['type'], $definition['field_types'])) { // Grab the default widget for the field type. $field_type_definition = field_info_field_types($field['type']); - $type = $field_type_definition['default_widget']; + $plugin_id = $field_type_definition['default_widget']; } - $configuration = array( + $configuration += array( 'instance' => $instance, - 'settings' => $options['settings'], - 'weight' => $options['weight'], ); - return $this->createInstance($type, $configuration); + return $this->createInstance($plugin_id, $configuration); } + /** + * Merges default values for widget configuration. + * + * @param string $field_type + * The field type. + * @param array $configuration + * An array of widget configuration. + * + * @return array + * The display properties with defaults added. + */ + public function prepareConfiguration($field_type, array $configuration) { + // Fill in defaults for missing properties. + $configuration += array( + 'settings' => array(), + ); + // If no widget is specified, use the default widget. + if (!isset($configuration['type'])) { + $field_type = field_info_field_types($field_type); + $configuration['type'] = $field_type['default_widget']; + } + // Fill in default settings values for the widget. + $configuration['settings'] += field_info_widget_settings($configuration['type']); + + return $configuration; + } } diff --git a/core/modules/field/lib/Drupal/field/Plugin/views/field/Field.php b/core/modules/field/lib/Drupal/field/Plugin/views/field/Field.php index 2e91a31..83a07eb 100644 --- a/core/modules/field/lib/Drupal/field/Plugin/views/field/Field.php +++ b/core/modules/field/lib/Drupal/field/Plugin/views/field/Field.php @@ -432,20 +432,8 @@ function fakeFieldInstance($formatter, $formatter_settings) { 'entity_type' => 'views_fake', 'bundle' => 'views_fake', - // Use the default field settings for settings and widget. + // Use the default field settings. 'settings' => field_info_instance_settings($field['type']), - 'widget' => array( - 'type' => $field_type['default_widget'], - 'settings' => array(), - ), - - // Build a dummy display mode. - 'display' => array( - '_custom' => array( - 'type' => $formatter, - 'settings' => $formatter_settings, - ), - ), // Set the other fields to their default values. 'required' => FALSE, diff --git a/core/modules/field/lib/Drupal/field/Tests/BulkDeleteTest.php b/core/modules/field/lib/Drupal/field/Tests/BulkDeleteTest.php index ca414bc..7ff4ff9 100644 --- a/core/modules/field/lib/Drupal/field/Tests/BulkDeleteTest.php +++ b/core/modules/field/lib/Drupal/field/Tests/BulkDeleteTest.php @@ -117,9 +117,6 @@ function setUp() { 'field_name' => $field['field_name'], 'entity_type' => $this->entity_type, 'bundle' => $bundle, - 'widget' => array( - 'type' => 'test_field_widget', - ) ); $this->instances[] = field_create_instance($instance); } diff --git a/core/modules/field/lib/Drupal/field/Tests/CrudTest.php b/core/modules/field/lib/Drupal/field/Tests/CrudTest.php index 9ee6019..fe141d0 100644 --- a/core/modules/field/lib/Drupal/field/Tests/CrudTest.php +++ b/core/modules/field/lib/Drupal/field/Tests/CrudTest.php @@ -284,9 +284,6 @@ function testDeleteField() { 'field_name' => $this->field['field_name'], 'entity_type' => 'test_entity', 'bundle' => 'test_bundle', - 'widget' => array( - 'type' => 'test_field_widget', - ), ); field_create_instance($this->instance_definition); $this->another_instance_definition = $this->instance_definition; diff --git a/core/modules/field/lib/Drupal/field/Tests/FieldAccessTest.php b/core/modules/field/lib/Drupal/field/Tests/FieldAccessTest.php index 86f1f34..b63d48d 100644 --- a/core/modules/field/lib/Drupal/field/Tests/FieldAccessTest.php +++ b/core/modules/field/lib/Drupal/field/Tests/FieldAccessTest.php @@ -46,9 +46,6 @@ function setUp() { 'field_name' => $this->field['field_name'], 'entity_type' => 'node', 'bundle' => $this->content_type, - 'widget' => array( - 'type' => 'text_textfield', - ), ); field_create_instance($this->instance); diff --git a/core/modules/field/lib/Drupal/field/Tests/FieldAttachOtherTest.php b/core/modules/field/lib/Drupal/field/Tests/FieldAttachOtherTest.php index 1ec87cf..4bc03be 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'], 'default'); 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'], 'default'); 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'], 'default'); field_attach_form($entity_init, $form, $form_state); // Simulate incoming values. diff --git a/core/modules/field/lib/Drupal/field/Tests/FieldAttachStorageTest.php b/core/modules/field/lib/Drupal/field/Tests/FieldAttachStorageTest.php index 38499c8..b9e87c7 100644 --- a/core/modules/field/lib/Drupal/field/Tests/FieldAttachStorageTest.php +++ b/core/modules/field/lib/Drupal/field/Tests/FieldAttachStorageTest.php @@ -495,11 +495,7 @@ function testEntityDeleteBundle() { 'label' => $this->randomName() . '_label', 'description' => $this->randomName() . '_description', 'weight' => mt_rand(0, 127), - // test_field has no instance settings - 'widget' => array( - 'type' => 'test_field_widget', - 'settings' => array( - 'size' => mt_rand(0, 255)))); + ); field_create_instance($instance); // Save an entity with data for both fields diff --git a/core/modules/field/lib/Drupal/field/Tests/FieldInfoTest.php b/core/modules/field/lib/Drupal/field/Tests/FieldInfoTest.php index 122d14c..dd093d5 100644 --- a/core/modules/field/lib/Drupal/field/Tests/FieldInfoTest.php +++ b/core/modules/field/lib/Drupal/field/Tests/FieldInfoTest.php @@ -79,11 +79,7 @@ function testFieldInfo() { 'label' => $this->randomName(), 'description' => $this->randomName(), 'weight' => mt_rand(0, 127), - // test_field has no instance settings - 'widget' => array( - 'type' => 'test_field_widget', - 'settings' => array( - 'test_setting' => 999))); + ); field_create_instance($instance); $info = entity_get_info('test_entity'); @@ -181,12 +177,6 @@ function testInstancePrepare() { // Check that all expected instance settings are in place. $field_type = field_info_field_types($field_definition['type']); $this->assertEqual($instance['settings'], $field_type['instance_settings'] , 'All expected instance settings are present.'); - - // Check that the default widget is used and expected settings are in place. - $widget = $instance->getWidget(); - $this->assertIdentical($widget->getPluginId(), $field_type['default_widget'], 'Unavailable widget replaced with default widget.'); - $widget_type = $widget->getDefinition(); - $this->assertIdentical($widget->getSettings(), $widget_type['settings'] , 'All expected widget settings are present.'); } /** diff --git a/core/modules/field/lib/Drupal/field/Tests/FieldInstanceCrudTest.php b/core/modules/field/lib/Drupal/field/Tests/FieldInstanceCrudTest.php index 2455a31..5f9578a 100644 --- a/core/modules/field/lib/Drupal/field/Tests/FieldInstanceCrudTest.php +++ b/core/modules/field/lib/Drupal/field/Tests/FieldInstanceCrudTest.php @@ -55,17 +55,14 @@ function testCreateFieldInstance() { $config = \Drupal::config('field.instance.' . $instance->id())->get(); $field_type = field_info_field_types($this->field['type']); - $widget_type = field_info_widget_types($field_type['default_widget']); // Check that default values are set. $this->assertEqual($config['required'], FALSE, 'Required defaults to false.'); $this->assertIdentical($config['label'], $this->instance_definition['field_name'], 'Label defaults to field name.'); $this->assertIdentical($config['description'], '', 'Description defaults to empty string.'); - $this->assertIdentical($config['widget']['type'], $field_type['default_widget'], 'Default widget has been written.'); // Check that default settings are set. $this->assertEqual($config['settings'], $field_type['instance_settings'] , 'Default instance settings have been written.'); - $this->assertIdentical($config['widget']['settings'], $widget_type['settings'] , 'Default widget settings have been written.'); // Guarantee that the field/bundle combination is unique. try { @@ -147,26 +144,12 @@ function testUpdateFieldInstance() { $instance['label'] = $this->randomName(); $instance['description'] = $this->randomName(); $instance['settings']['test_instance_setting'] = $this->randomName(); - $instance['widget']['settings']['test_widget_setting'] =$this->randomName(); - $instance['widget']['weight']++; field_update_instance($instance); $instance_new = field_read_instance('test_entity', $this->instance_definition['field_name'], $this->instance_definition['bundle']); $this->assertEqual($instance['required'], $instance_new['required'], '"required" change is saved'); $this->assertEqual($instance['label'], $instance_new['label'], '"label" change is saved'); $this->assertEqual($instance['description'], $instance_new['description'], '"description" change is saved'); - $this->assertEqual($instance['widget']['settings']['test_widget_setting'], $instance_new['widget']['settings']['test_widget_setting'], 'Widget setting change is saved'); - $this->assertEqual($instance['widget']['weight'], $instance_new['widget']['weight'], 'Widget weight change is saved'); - - // Check that changing the widget type updates the default settings. - $instance = field_read_instance('test_entity', $this->instance_definition['field_name'], $this->instance_definition['bundle']); - $instance['widget']['type'] = 'test_field_widget_multiple'; - field_update_instance($instance); - - $instance_new = field_read_instance('test_entity', $this->instance_definition['field_name'], $this->instance_definition['bundle']); - $this->assertEqual($instance['widget']['type'], $instance_new['widget']['type'] , 'Widget type change is saved.'); - $settings = field_info_widget_settings($instance_new['widget']['type']); - $this->assertIdentical($settings, array_intersect_key($instance_new['widget']['settings'], $settings) , 'Widget type change updates default settings.'); // TODO: test failures. } diff --git a/core/modules/field/lib/Drupal/field/Tests/FieldUnitTestBase.php b/core/modules/field/lib/Drupal/field/Tests/FieldUnitTestBase.php index 223e0ac..7b1b9b1 100644 --- a/core/modules/field/lib/Drupal/field/Tests/FieldUnitTestBase.php +++ b/core/modules/field/lib/Drupal/field/Tests/FieldUnitTestBase.php @@ -69,15 +69,17 @@ function createFieldWithInstance($suffix = '') { 'settings' => array( 'test_instance_setting' => $this->randomName(), ), - 'widget' => array( + ); + field_create_instance($this->$instance); + + entity_get_form_display('test_entity', 'test_bundle', 'default') + ->setComponent($this->$field_name, array( 'type' => 'test_field_widget', - 'label' => 'Test Field', 'settings' => array( 'test_widget_setting' => $this->randomName(), ) - ) - ); - field_create_instance($this->$instance); + )) + ->save(); } /** diff --git a/core/modules/field/lib/Drupal/field/Tests/FormTest.php b/core/modules/field/lib/Drupal/field/Tests/FormTest.php index b0a830d..0f42718 100644 --- a/core/modules/field/lib/Drupal/field/Tests/FormTest.php +++ b/core/modules/field/lib/Drupal/field/Tests/FormTest.php @@ -43,13 +43,6 @@ function setUp() { 'settings' => array( 'test_instance_setting' => $this->randomName(), ), - 'widget' => array( - 'type' => 'test_field_widget', - 'label' => 'Test Field', - 'settings' => array( - 'test_widget_setting' => $this->randomName(), - ) - ) ); } @@ -59,6 +52,9 @@ function testFieldFormSingle() { $this->instance['field_name'] = $this->field_name; field_create_field($this->field); field_create_instance($this->instance); + entity_get_form_display($this->instance['entity_type'], $this->instance['bundle'], 'default') + ->setComponent($this->field_name) + ->save(); $langcode = LANGUAGE_NOT_SPECIFIED; // Display creation form. @@ -125,6 +121,9 @@ function testFieldFormDefaultValue() { $this->instance['default_value'] = array(array('value' => $default)); field_create_field($this->field); field_create_instance($this->instance); + entity_get_form_display($this->instance['entity_type'], $this->instance['bundle'], 'default') + ->setComponent($this->field_name) + ->save(); $langcode = LANGUAGE_NOT_SPECIFIED; // Display creation form. @@ -149,6 +148,9 @@ function testFieldFormSingleRequired() { $this->instance['required'] = TRUE; field_create_field($this->field); field_create_instance($this->instance); + entity_get_form_display($this->instance['entity_type'], $this->instance['bundle'], 'default') + ->setComponent($this->field_name) + ->save(); $langcode = LANGUAGE_NOT_SPECIFIED; // Submit with missing required value. @@ -187,6 +189,9 @@ function testFieldFormUnlimited() { $this->instance['field_name'] = $this->field_name; field_create_field($this->field); field_create_instance($this->instance); + entity_get_form_display($this->instance['entity_type'], $this->instance['bundle'], 'default') + ->setComponent($this->field_name) + ->save(); $langcode = LANGUAGE_NOT_SPECIFIED; // Display creation form -> 1 widget. @@ -267,6 +272,9 @@ function testFieldFormMultivalueWithRequiredRadio() { $this->instance['field_name'] = $this->field_name; field_create_field($this->field); field_create_instance($this->instance); + entity_get_form_display($this->instance['entity_type'], $this->instance['bundle'], 'default') + ->setComponent($this->field_name) + ->save(); $langcode = LANGUAGE_NOT_SPECIFIED; // Add a required radio field. @@ -282,11 +290,13 @@ function testFieldFormMultivalueWithRequiredRadio() { 'entity_type' => 'test_entity', 'bundle' => 'test_bundle', 'required' => TRUE, - 'widget' => array( - 'type' => 'options_buttons', - ), ); field_create_instance($instance); + entity_get_form_display($instance['entity_type'], $instance['bundle'], 'default') + ->setComponent($instance['field_name'], array( + 'type' => 'options_buttons', + )) + ->save(); // Display creation form. $this->drupalGet('test-entity/add/test_bundle'); @@ -309,6 +319,9 @@ function testFieldFormJSAddMore() { $this->instance['field_name'] = $this->field_name; field_create_field($this->field); field_create_instance($this->instance); + entity_get_form_display($this->instance['entity_type'], $this->instance['bundle'], 'default') + ->setComponent($this->field_name) + ->save(); $langcode = LANGUAGE_NOT_SPECIFIED; // Display creation form -> 1 widget. @@ -366,9 +379,13 @@ function testFieldFormMultipleWidget() { $this->field = $this->field_multiple; $this->field_name = $this->field['field_name']; $this->instance['field_name'] = $this->field_name; - $this->instance['widget']['type'] = 'test_field_widget_multiple'; field_create_field($this->field); field_create_instance($this->instance); + entity_get_form_display($this->instance['entity_type'], $this->instance['bundle'], 'default') + ->setComponent($this->field_name, array( + 'type' => 'test_field_widget_multiple', + )) + ->save(); $langcode = LANGUAGE_NOT_SPECIFIED; // Display creation form. @@ -408,6 +425,9 @@ function testFieldFormAccess() { $instance['field_name'] = $field_name; field_create_field($field); field_create_instance($instance); + entity_get_form_display($this->instance['entity_type'], $this->instance['bundle'], 'default') + ->setComponent($field_name) + ->save(); // Create a field with no edit access - see field_test_field_access(). $field_no_access = array( @@ -423,6 +443,9 @@ function testFieldFormAccess() { ); field_create_field($field_no_access); field_create_instance($instance_no_access); + entity_get_form_display($instance_no_access['entity_type'], $instance_no_access['bundle'], 'default') + ->setComponent($field_name_no_access) + ->save(); $langcode = LANGUAGE_NOT_SPECIFIED; @@ -433,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.'); @@ -479,9 +503,15 @@ function testNestedFieldForm() { $this->instance['field_name'] = 'field_single'; $this->instance['label'] = 'Single field'; field_create_instance($this->instance); + entity_get_form_display($this->instance['entity_type'], $this->instance['bundle'], 'default') + ->setComponent($this->instance['field_name']) + ->save(); $this->instance['field_name'] = 'field_unlimited'; $this->instance['label'] = 'Unlimited field'; field_create_instance($this->instance); + entity_get_form_display($this->instance['entity_type'], $this->instance['bundle'], 'default') + ->setComponent($this->instance['field_name']) + ->save(); // Create two entities. $entity_1 = field_test_create_entity(1, 1); @@ -585,10 +615,14 @@ 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); + entity_get_form_display($this->instance['entity_type'], $this->instance['bundle'], 'default') + ->setComponent($this->instance['field_name'], array( + 'type' => 'hidden', + )) + ->save(); $langcode = LANGUAGE_NOT_SPECIFIED; // Display the entity creation form. @@ -607,8 +641,12 @@ function testFieldFormHiddenWidget() { // 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); + entity_get_form_display($this->instance['entity_type'], $this->instance['bundle'], 'default') + ->setComponent($this->instance['field_name'], array( + 'type' => 'test_field_widget', + )) + ->save(); // Display edit form. $this->drupalGet('test-entity/manage/' . $id . '/edit'); @@ -623,9 +661,12 @@ function testFieldFormHiddenWidget() { $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); + // Update the form display and switch to the Hidden widget again. + entity_get_form_display($this->instance['entity_type'], $this->instance['bundle'], 'default') + ->setComponent($this->instance['field_name'], array( + 'type' => 'hidden', + )) + ->save(); // Create a new revision. $edit = array('revision' => TRUE); diff --git a/core/modules/field/lib/Drupal/field/Tests/ShapeItemTest.php b/core/modules/field/lib/Drupal/field/Tests/ShapeItemTest.php index 2628256..4e92d7e 100644 --- a/core/modules/field/lib/Drupal/field/Tests/ShapeItemTest.php +++ b/core/modules/field/lib/Drupal/field/Tests/ShapeItemTest.php @@ -43,9 +43,6 @@ public function setUp() { 'entity_type' => 'entity_test', 'field_name' => 'field_shape', 'bundle' => 'entity_test', - 'widget' => array( - 'type' => 'test_field_widget', - ), ); field_create_instance($this->instance); } diff --git a/core/modules/field/lib/Drupal/field/Tests/TestItemTest.php b/core/modules/field/lib/Drupal/field/Tests/TestItemTest.php index 198be2a..c8ff8fa 100644 --- a/core/modules/field/lib/Drupal/field/Tests/TestItemTest.php +++ b/core/modules/field/lib/Drupal/field/Tests/TestItemTest.php @@ -43,9 +43,6 @@ public function setUp() { 'entity_type' => 'entity_test', 'field_name' => 'field_test', 'bundle' => 'entity_test', - 'widget' => array( - 'type' => 'test_field_widget', - ), ); field_create_instance($this->instance); } diff --git a/core/modules/field/lib/Drupal/field/Tests/TranslationWebTest.php b/core/modules/field/lib/Drupal/field/Tests/TranslationWebTest.php index 40447f1..a32cc81 100644 --- a/core/modules/field/lib/Drupal/field/Tests/TranslationWebTest.php +++ b/core/modules/field/lib/Drupal/field/Tests/TranslationWebTest.php @@ -53,6 +53,10 @@ function setUp() { field_create_instance($instance); $this->instance = field_read_instance('test_entity', $this->field_name, 'test_bundle'); + entity_get_form_display($this->entity_type, 'test_bundle', 'default') + ->setComponent($this->field_name) + ->save(); + for ($i = 0; $i < 3; ++$i) { $language = new Language(array( 'langcode' => 'l' . $i, 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..ac0905c 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(), 'default'); 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(), 'default'); field_attach_form($entity_2, $form['entity_2'], $form_state); $form['save'] = array( diff --git a/core/modules/field/tests/modules/field_test/field_test.module b/core/modules/field/tests/modules/field_test/field_test.module index 4ecd1a9..b715224 100644 --- a/core/modules/field/tests/modules/field_test/field_test.module +++ b/core/modules/field/tests/modules/field_test/field_test.module @@ -196,36 +196,18 @@ function field_test_field_attach_view_alter(&$output, $context) { } /** - * Implements hook_field_widget_properties_alter(). - */ -function field_test_field_widget_properties_alter(&$widget, $context) { - // Make the alter_test_text field 42 characters for nodes and comments. - if (in_array($context['entity_type'], array('node', 'comment')) && ($context['field']['field_name'] == 'alter_test_text')) { - $widget['settings']['size'] = 42; - } -} - -/** - * Implements hook_field_widget_properties_ENTITY_TYPE_alter(). - */ -function field_test_field_widget_properties_user_alter(&$widget, $context) { - // Always use buttons for the alter_test_options field on user forms. - if ($context['field']['field_name'] == 'alter_test_options') { - $widget['type'] = 'options_buttons'; - } -} - -/** * Implements hook_field_widget_form_alter(). */ function field_test_field_widget_form_alter(&$element, &$form_state, $context) { + $instance = $context['instance']; + $entity_form_display = entity_get_form_display($instance['entity_type'], $instance['bundle'], 'default'); switch ($context['field']['field_name']) { case 'alter_test_text': - drupal_set_message('Field size: ' . $context['instance']->getWidget()->getSetting('size')); + drupal_set_message('Field size: ' . $entity_form_display->getWidget($context['field']['field_name'])->getSetting('size')); break; case 'alter_test_options': - drupal_set_message('Widget type: ' . $context['instance']->getWidget()->getPluginId()); + drupal_set_message('Widget type: ' . $entity_form_display->getWidget($context['field']['field_name'])->getPluginId()); break; } // Set a message if this is for the form displayed to set default value for diff --git a/core/modules/field/tests/modules/field_test_config/config/field.instance.test_entity.test_bundle.field_test_import.yml b/core/modules/field/tests/modules/field_test_config/config/field.instance.test_entity.test_bundle.field_test_import.yml index 4817a77..a179a55 100644 --- a/core/modules/field/tests/modules/field_test_config/config/field.instance.test_entity.test_bundle.field_test_import.yml +++ b/core/modules/field/tests/modules/field_test_config/config/field.instance.test_entity.test_bundle.field_test_import.yml @@ -11,10 +11,4 @@ default_value_function: '' settings: text_processing: '0' user_register_form: false -widget: - weight: '-2' - type: text_textfield - module: text - settings: - size: '60' field_type: text diff --git a/core/modules/field/tests/modules/field_test_config/staging/field.instance.test_entity.test_bundle.field_test_import_staging.yml b/core/modules/field/tests/modules/field_test_config/staging/field.instance.test_entity.test_bundle.field_test_import_staging.yml index 2e4229d..f751ad5 100644 --- a/core/modules/field/tests/modules/field_test_config/staging/field.instance.test_entity.test_bundle.field_test_import_staging.yml +++ b/core/modules/field/tests/modules/field_test_config/staging/field.instance.test_entity.test_bundle.field_test_import_staging.yml @@ -12,10 +12,4 @@ default_value_function: '' settings: text_processing: '0' user_register_form: '0' -widget: - type: text_textfield - weight: '-3' - settings: - size: '60' - module: text field_type: text diff --git a/core/modules/field_ui/field_ui.admin.inc b/core/modules/field_ui/field_ui.admin.inc index 2d7e7ca..a456e7a 100644 --- a/core/modules/field_ui/field_ui.admin.inc +++ b/core/modules/field_ui/field_ui.admin.inc @@ -5,10 +5,6 @@ * Administrative interface for custom field type creation. */ -use Drupal\field\Plugin\Core\Entity\FieldInstance; -use Drupal\field_ui\FieldOverview; -use Drupal\field_ui\DisplayOverview; - /** * Page callback: Lists all defined fields for quick reference. * @@ -292,31 +288,6 @@ function theme_field_ui_table($variables) { } /** - * Returns the built and processed 'Manage fields' form of a bundle. - * - * The resulting form allows fields and pseudo-fields to be re-ordered. - * - * @param string $entity_type - * The entity type for the fieldable entity. - * @param string $bundle - * The bundle for the fieldable entity. - * - * @return - * The processed form for the given entity type and bundle. - * - * @see field_ui_menu() - * @see Drupal\field_ui\FieldOverview::validate() - * @see Drupal\field_ui\FieldOverview::submit() - * @ingroup forms - */ -function field_ui_field_overview($entity_type, $bundle) { - $bundle = field_extract_bundle($entity_type, $bundle); - field_ui_inactive_message($entity_type, $bundle); - - return drupal_get_form(new FieldOverview($entity_type, $bundle)); -} - -/** * Render API callback: Checks if a field machine name is taken. * * @param $value @@ -335,33 +306,6 @@ function _field_ui_field_name_exists($value) { } /** - * Returns the built and processed 'Manage display' form of a bundle. - * - * The resulting form allows fields and pseudo-fields to be re-ordered. - * - * @param string $entity_type - * The entity type for the fieldable entity. - * @param string $bundle - * The bundle for the fieldable entity. - * @param string $view_mode - * The view mode for the fieldable entity. - * - * @return - * The processed form for the given entity type and bundle. - * - * @see field_ui_menu() - * @see field_ui_display_overview_multistep_submit() - * @see Drupal\field_ui\DisplayOverview::submit() - * @ingroup forms - */ -function field_ui_display_overview($entity_type, $bundle, $view_mode) { - $bundle = field_extract_bundle($entity_type, $bundle); - field_ui_inactive_message($entity_type, $bundle); - - return drupal_get_form(new DisplayOverview($entity_type, $bundle, $view_mode)); -} - -/** * Returns an array of field_type options. */ function field_ui_field_type_options() { @@ -472,12 +416,13 @@ function field_ui_existing_field_options($entity_type, $bundle) { && !field_info_instance($entity_type, $field['field_name'], $bundle) && (empty($field['entity_types']) || in_array($entity_type, $field['entity_types'])) && empty($field_types[$field['type']]['no_ui'])) { + $widget = entity_get_form_display($instance['entity_type'], $instance['bundle'], 'default')->getComponent($instance['field_name']); $info[$instance['field_name']] = array( 'type' => $field['type'], 'type_label' => $field_types[$field['type']]['label'], 'field' => $field['field_name'], 'label' => $instance['label'], - 'widget_type' => $instance['widget']['type'], + 'widget_type' => $widget['type'], ); } } @@ -488,552 +433,6 @@ function field_ui_existing_field_options($entity_type, $bundle) { } /** - * Form constructor for the field settings edit page. - * - * @see field_ui_menu() - * @see field_ui_field_settings_form_submit() - * @ingroup forms - */ -function field_ui_field_settings_form($form, &$form_state, $instance) { - $bundle = $instance['bundle']; - $entity_type = $instance['entity_type']; - $field = field_info_field($instance['field_name']); - $form['#field'] = $field; - $form['#entity_type'] = $entity_type; - $form['#bundle'] = $bundle; - - drupal_set_title($instance['label']); - - $description = '

' . t('These settings apply to the %field field everywhere it is used. These settings impact the way that data is stored in the database and cannot be changed once data has been created.', array('%field' => $instance['label'])) . '

'; - - // Create a form structure for the field values. - $form['field'] = array( - '#prefix' => $description, - '#tree' => TRUE, - ); - - // See if data already exists for this field. - // If so, prevent changes to the field settings. - $has_data = field_has_data($field); - if ($has_data) { - $form['field']['#prefix'] = '
' . t('There is data for this field in the database. The field settings can no longer be changed.') . '
' . $form['field']['#prefix']; - } - - // Build the configurable field values. - $cardinality = $field['cardinality']; - $form['field']['container'] = array( - // We can't use the container element because it doesn't support the title - // or description properties. - '#type' => 'item', - '#field_prefix' => '
', - '#field_suffix' => '
', - '#title' => t('Maximum number of values users can enter'), - ); - $form['field']['container']['cardinality'] = array( - '#type' => 'select', - '#options' => drupal_map_assoc(range(1, 5)) + array(FIELD_CARDINALITY_UNLIMITED => t('Unlimited')) + array('other' => t('More')), - '#default_value' => ($cardinality < 6) ? $cardinality : 'other', - ); - // @todo Convert when http://drupal.org/node/1207060 gets in. - $form['field']['container']['cardinality_other'] = array( - '#type' => 'number', - '#default_value' => $cardinality > 5 ? $cardinality : 6, - '#min' => 1, - '#title' => t('Custom value'), - '#title_display' => 'invisible', - '#states' => array( - 'visible' => array( - ':input[name="field[container][cardinality]"]' => array('value' => 'other'), - ), - ), - ); - if (field_behaviors_widget('multiple values', $instance) == FIELD_BEHAVIOR_DEFAULT) { - $form['field']['container']['#description'] = t('%unlimited will provide an %add-more button so users can add as many values as they like.', array( - '%unlimited' => t('Unlimited'), - '%add-more' => t('Add another item'), - )); - } - - // Build the non-configurable field values. - $form['field']['field_name'] = array('#type' => 'value', '#value' => $field['field_name']); - $form['field']['type'] = array('#type' => 'value', '#value' => $field['type']); - $form['field']['module'] = array('#type' => 'value', '#value' => $field['module']); - $form['field']['active'] = array('#type' => 'value', '#value' => $field['active']); - - // Add settings provided by the field module. The field module is - // responsible for not returning settings that cannot be changed if - // the field already has data. - $form['field']['settings'] = array( - '#weight' => 10, - ); - $additions = module_invoke($field['module'], 'field_settings_form', $field, $instance, $has_data); - if (is_array($additions)) { - $form['field']['settings'] += $additions; - } - - $form['actions'] = array('#type' => 'actions'); - $form['actions']['submit'] = array('#type' => 'submit', '#value' => t('Save field settings')); - return $form; -} - -/** - * Form validation handler for field_ui_field_edit_form(). - * - * @see field_ui_field_settings_form_submit(). - */ -function field_ui_field_settings_form_validate($form, &$form_state) { - // Validate field cardinality. - $cardinality = $form_state['values']['field']['container']['cardinality']; - $cardinality_other = $form_state['values']['field']['container']['cardinality_other']; - if ($cardinality == 'other' && empty($cardinality_other)) { - form_error($form['field']['container']['cardinality_other'], t('Number of values is required.')); - } -} - -/** - * Form submission handler for field_ui_field_settings_form(). - */ -function field_ui_field_settings_form_submit($form, &$form_state) { - $form_values = $form_state['values']; - $field_values = $form_values['field']; - - // Save field cardinality. - $cardinality = $field_values['container']['cardinality']; - $cardinality_other = $field_values['container']['cardinality_other']; - $cardinality_other = $form_state['values']['field']['container']['cardinality_other']; - if ($cardinality == 'other') { - $cardinality = $cardinality_other; - } - $field_values['cardinality'] = $cardinality; - unset($field_values['container']); - - // Merge incoming form values into the existing field. - $field = field_info_field($field_values['field_name']); - foreach ($field_values as $key => $value) { - $field[$key] = $value; - } - - $entity_type = $form['#entity_type']; - $bundle = $form['#bundle']; - $instance = field_info_instance($entity_type, $field['field_name'], $bundle); - - // Update the field. - try { - field_update_field($field); - drupal_set_message(t('Updated field %label field settings.', array('%label' => $instance['label']))); - $form_state['redirect'] = field_ui_next_destination($entity_type, $bundle); - } - catch (Exception $e) { - drupal_set_message(t('Attempt to update field %label failed: %message.', array('%label' => $instance['label'], '%message' => $e->getMessage())), 'error'); - } -} - -/** - * Form constructor for the widget selection form. - * - * @see field_ui_menu() - * @see field_ui_widget_type_form_submit() - * @ingroup forms - */ -function field_ui_widget_type_form($form, &$form_state, FieldInstance $instance) { - drupal_set_title($instance['label']); - - $bundle = $instance['bundle']; - $entity_type = $instance['entity_type']; - $field_name = $instance['field_name']; - - $field = field_info_field($field_name); - $bundles = entity_get_bundles(); - $bundle_label = $bundles[$entity_type][$bundle]['label']; - - $form = array( - '#bundle' => $bundle, - '#entity_type' => $entity_type, - '#field_name' => $field_name, - ); - - $form['widget_type'] = array( - '#type' => 'select', - '#title' => t('Widget type'), - '#required' => TRUE, - '#options' => field_ui_widget_type_options($field['type']), - '#default_value' => $instance->getWidget()->getPluginId(), - '#description' => t('The type of form element you would like to present to the user when creating this field in the %type type.', array('%type' => $bundle_label)), - ); - - $form['actions'] = array('#type' => 'actions'); - $form['actions']['submit'] = array('#type' => 'submit', '#value' => t('Continue')); - - $form['#validate'] = array(); - $form['#submit'] = array('field_ui_widget_type_form_submit'); - - return $form; -} - -/** - * Form submission handler for field_ui_widget_type_form(). - */ -function field_ui_widget_type_form_submit($form, &$form_state) { - $form_values = $form_state['values']; - $bundle = $form['#bundle']; - $entity_type = $form['#entity_type']; - $field_name = $form['#field_name']; - - // Retrieve the stored instance settings to merge with the incoming values. - $instance = field_read_instance($entity_type, $field_name, $bundle); - - // Set the right module information. - $widget_type = field_info_widget_types($form_values['widget_type']); - $widget_module = $widget_type['module']; - - $instance['widget']['type'] = $form_values['widget_type']; - $instance['widget']['module'] = $widget_module; - - 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'); - } - - $form_state['redirect'] = field_ui_next_destination($entity_type, $bundle); -} - -/** - * Form constructor for removing a field instance from a bundle. - * - * @see field_ui_menu() - * @see field_ui_field_delete_form_submit() - * @ingroup forms - */ -function field_ui_field_delete_form($form, &$form_state, $instance) { - $bundle = $instance['bundle']; - $entity_type = $instance['entity_type']; - $field = field_info_field($instance['field_name']); - - $admin_path = field_ui_bundle_admin_path($entity_type, $bundle); - - $form['entity_type'] = array('#type' => 'value', '#value' => $entity_type); - $form['bundle'] = array('#type' => 'value', '#value' => $bundle); - $form['field_name'] = array('#type' => 'value', '#value' => $field['field_name']); - - $output = confirm_form($form, - t('Are you sure you want to delete the field %field?', array('%field' => $instance['label'])), - $admin_path . '/fields', - t('If you have any content left in this field, it will be lost. This action cannot be undone.'), - t('Delete'), t('Cancel'), - 'confirm' - ); - - if ($field['locked']) { - unset($output['actions']['submit']); - $output['description']['#markup'] = t('This field is locked and cannot be deleted.'); - } - - return $output; -} - -/** - * Form submission handler for field_ui_field_delete_form(). - * - * Removes a field instance from a bundle. If the field has no more instances, - * it will be marked as deleted too. - */ -function field_ui_field_delete_form_submit($form, &$form_state) { - $form_values = $form_state['values']; - $field_name = $form_values['field_name']; - $bundle = $form_values['bundle']; - $entity_type = $form_values['entity_type']; - - $field = field_info_field($field_name); - $instance = field_info_instance($entity_type, $field_name, $bundle); - $bundles = entity_get_bundles(); - $bundle_label = $bundles[$entity_type][$bundle]['label']; - - if (!empty($bundle) && $field && !$field['locked'] && $form_values['confirm']) { - field_delete_instance($instance); - drupal_set_message(t('The field %field has been deleted from the %type content type.', array('%field' => $instance['label'], '%type' => $bundle_label))); - } - else { - drupal_set_message(t('There was a problem removing the %field from the %type content type.', array('%field' => $instance['label'], '%type' => $bundle_label)), 'error'); - } - - $admin_path = field_ui_bundle_admin_path($entity_type, $bundle); - $form_state['redirect'] = field_ui_get_destinations(array($admin_path . '/fields')); - - // Fields are purged on cron. However field module prevents disabling modules - // when field types they provided are used in a field until it is fully - // purged. In the case that a field has minimal or no content, a single call - // to field_purge_batch() will remove it from the system. Call this with a - // low batch limit to avoid administrators having to wait for cron runs when - // removing instances that meet this criteria. - field_purge_batch(10); -} - -/** - * Form constructor for the field instance settings form. - * - * @see field_ui_menu() - * @see field_ui_field_edit_form_validate() - * @see field_ui_field_edit_form_submit() - * @see field_ui_field_edit_form_delete_submit() - * @ingroup forms - */ -function field_ui_field_edit_form($form, &$form_state, $instance) { - $bundle = $instance['bundle']; - $entity_type = $instance['entity_type']; - $field = field_info_field($instance['field_name']); - $bundles = entity_get_bundles(); - - drupal_set_title(t('%instance settings for %bundle', array( - '%instance' => $instance['label'], - '%bundle' => $bundles[$entity_type][$bundle]['label'], - )), PASS_THROUGH); - - $form['#field'] = $field; - $form['#instance'] = $instance; - // Create an arbitrary entity object (used by the 'default value' widget). - $ids = (object) array('entity_type' => $instance['entity_type'], 'bundle' => $instance['bundle'], 'entity_id' => NULL); - $form['#entity'] = _field_create_entity_from_ids($ids); - $form['#entity']->field_ui_default_value = TRUE; - - if (!empty($field['locked'])) { - $form['locked'] = array( - '#markup' => t('The field %field is locked and cannot be edited.', array('%field' => $instance['label'])), - ); - return $form; - } - - $widget_type = field_info_widget_types($instance['widget']['type']); - - // Create a form structure for the instance values. - $form['instance'] = array( - '#tree' => TRUE, - ); - - // Build the non-configurable instance values. - $form['instance']['field_name'] = array( - '#type' => 'value', - '#value' => $instance['field_name'], - ); - $form['instance']['entity_type'] = array( - '#type' => 'value', - '#value' => $entity_type, - ); - $form['instance']['bundle'] = array( - '#type' => 'value', - '#value' => $bundle, - ); - $form['instance']['widget']['weight'] = array( - '#type' => 'value', - '#value' => !empty($instance['widget']['weight']) ? $instance['widget']['weight'] : 0, - ); - - // Build the configurable instance values. - $form['instance']['label'] = array( - '#type' => 'textfield', - '#title' => t('Label'), - '#default_value' => !empty($instance['label']) ? $instance['label'] : $field['field_name'], - '#required' => TRUE, - '#weight' => -20, - ); - - $form['instance']['description'] = array( - '#type' => 'textarea', - '#title' => t('Help text'), - '#default_value' => !empty($instance['description']) ? $instance['description'] : '', - '#rows' => 5, - '#description' => t('Instructions to present to the user below this field on the editing form.
Allowed HTML tags: @tags', array('@tags' => _field_filter_xss_display_allowed_tags())) . '
' . t('This field supports tokens.'), - '#weight' => -10, - ); - - $form['instance']['required'] = array( - '#type' => 'checkbox', - '#title' => t('Required field'), - '#default_value' => !empty($instance['required']), - '#weight' => -5, - ); - - // Build the widget component of the instance. - $form['instance']['widget']['type'] = array( - '#type' => 'value', - '#value' => $instance['widget']['type'], - ); - - // Add additional field instance settings from the field module. - $additions = module_invoke($field['module'], 'field_instance_settings_form', $field, $instance, $form_state); - if (is_array($additions)) { - $form['instance']['settings'] = $additions; - $form['instance']['settings']['#weight'] = 10; - } - - // Add widget settings for the widget type. - $additions = $instance->getWidget()->settingsForm($form, $form_state); - $form['instance']['widget']['settings'] = $additions ? $additions : array('#type' => 'value', '#value' => array()); - $form['instance']['widget']['#weight'] = 20; - - // Add handling for default value if not provided by any other module. - if (field_behaviors_widget('default_value', $instance) == FIELD_BEHAVIOR_DEFAULT && empty($instance['default_value_function'])) { - $form['instance']['default_value_widget'] = field_ui_default_value_widget($field, $instance, $form, $form_state); - } - - $form['actions'] = array('#type' => 'actions'); - $form['actions']['submit'] = array( - '#type' => 'submit', - '#value' => t('Save settings') - ); - $form['actions']['delete'] = array( - '#type' => 'submit', - '#value' => t('Delete field'), - '#submit' => array('field_ui_field_edit_form_delete_submit'), - ); - return $form; -} - -/** - * Form submission handler for 'Delete' button in field_ui_field_edit_form(). - */ -function field_ui_field_edit_form_delete_submit($form, &$form_state) { - $destination = array(); - if (isset($_GET['destination'])) { - $destination = drupal_get_destination(); - unset($_GET['destination']); - } - $instance = $form['#instance']; - $form_state['redirect'] = array('admin/structure/types/manage/' . $instance['bundle'] . '/fields/' . $instance['field_name'] . '/delete', array('query' => $destination)); -} - -/** - * Builds the default value widget for a given field instance. - */ -function field_ui_default_value_widget($field, $instance, &$form, &$form_state) { - $field_name = $field['field_name']; - $entity = $form['#entity']; - - $element = array( - '#type' => 'details', - '#title' => t('Default value'), - '#tree' => TRUE, - '#description' => t('The default value for this field, used when creating new content.'), - // Stick to an empty 'parents' on this form in order not to breaks widgets - // that do not use field_widget_[field|instance]() and still access - // $form_state['field'] directly. - '#parents' => array(), - ); - - // Adjust the instance definition used for the form element. We want a - // non-required input and no description. - $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(); - if (!empty($instance['default_value'])) { - $items = (array) $instance['default_value']; - } - $element += $instance->getWidget()->form($entity, LANGUAGE_NOT_SPECIFIED, $items, $element, $form_state); - - return $element; -} - -/** - * Form validation handler for field_ui_field_edit_form(). - * - * @see field_ui_field_edit_form_submit(). - */ -function field_ui_field_edit_form_validate($form, &$form_state) { - // Take the incoming values as the $instance definition, so that the 'default - // value' gets validated using the instance settings being submitted. - $instance = $form['#instance']; - $field_name = $instance['field_name']; - $entity = $form['#entity']; - - if (isset($form['instance']['default_value_widget'])) { - $element = $form['instance']['default_value_widget']; - - // Extract the 'default value'. - $items = array(); - $instance->getWidget()->extractFormValues($entity, LANGUAGE_NOT_SPECIFIED, $items, $element, $form_state); - - // Grab the field definition from $form_state. - $field_state = field_form_get_state($element['#parents'], $field_name, LANGUAGE_NOT_SPECIFIED, $form_state); - $field = $field_state['field']; - - // Validate the value. - $errors = array(); - $function = $field['module'] . '_field_validate'; - if (function_exists($function)) { - $function(NULL, $field, $instance, LANGUAGE_NOT_SPECIFIED, $items, $errors); - } - - // Report errors. - if (isset($errors[$field_name][LANGUAGE_NOT_SPECIFIED])) { - // Store reported errors in $form_state. - $field_state['errors'] = $errors[$field_name][LANGUAGE_NOT_SPECIFIED]; - field_form_set_state($element['#parents'], $field_name, LANGUAGE_NOT_SPECIFIED, $form_state, $field_state); - - // Assign reported errors to the correct form element. - $instance->getWidget()->flagErrors($entity, LANGUAGE_NOT_SPECIFIED, $items, $element, $form_state); - } - } -} - -/** - * Form submission handler for field_ui_field_edit_form(). - * - * @see field_ui_field_edit_form_validate(). - */ -function field_ui_field_edit_form_submit($form, &$form_state) { - $instance = $form['#instance']; - $field = $form['#field']; - $entity = $form['#entity']; - - // Handle the default value. - if (isset($form['instance']['default_value_widget'])) { - $element = $form['instance']['default_value_widget']; - - // Extract field values. - $items = array(); - $instance->getWidget()->extractFormValues($entity, LANGUAGE_NOT_SPECIFIED, $items, $element, $form_state); - - $instance['default_value'] = $items ? $items : NULL; - } - - // Merge incoming values into the instance. - foreach ($form_state['values']['instance'] as $key => $value) { - $instance[$key] = $value; - } - field_update_instance($instance); - - 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']); -} - -/** * Extracts next redirect path from an array of multiple destinations. * * @see field_ui_next_destination() diff --git a/core/modules/field_ui/field_ui.module b/core/modules/field_ui/field_ui.module index a0f29e3..c8943c9 100644 --- a/core/modules/field_ui/field_ui.module +++ b/core/modules/field_ui/field_ui.module @@ -65,128 +65,73 @@ function field_ui_menu() { // Create tabs for all possible bundles. foreach (entity_get_info() as $entity_type => $entity_info) { - if ($entity_info['fieldable']) { - foreach (entity_get_bundles($entity_type) as $bundle_name => $bundle_info) { - if (isset($bundle_info['admin'])) { - // Extract path information from the bundle. - $path = $bundle_info['admin']['path']; - // Different bundles can appear on the same path (e.g. %node_type and - // %comment_node_type). To allow field_ui_instance_load() to extract - // the actual bundle object from the translated menu router path - // arguments, we need to identify the argument position of the bundle - // name string ('bundle argument') and pass that position to the menu - // loader. The position needs to be casted into a string; otherwise it - // would be replaced with the bundle name string. - if (isset($bundle_info['admin']['bundle argument'])) { - $bundle_arg = $bundle_info['admin']['bundle argument']; - $bundle_pos = (string) $bundle_arg; - } - else { - $bundle_arg = $bundle_name; - $bundle_pos = '0'; - } - // This is the position of the %field_ui_instance placeholder in the - // items below. - $field_position = count(explode('/', $path)) + 1; - - // User access check to be done against the permission to edit - // fields or the display per entity type. - $access_fields = array( - 'access callback' => 'user_access', - 'access arguments' => array('administer ' . $entity_type . ' fields'), - ); - $access_display = array( - 'access callback' => 'user_access', - 'access arguments' => array('administer ' . $entity_type . ' display'), - ); + if ($entity_info['fieldable'] && isset($entity_info['route_base_path'])) { + // Extract path information from the entity type. + $path = $entity_info['route_base_path']; + $default_path = preg_replace('/{' . DRUPAL_PHP_FUNCTION_PATTERN . '}/', '%', $path); + // This is the position of the %field_ui_instance placeholder in the + // items below. + $field_position = count(explode('/', $path)) + 1; - $items["$path/fields"] = array( - 'title' => 'Manage fields', - 'page callback' => 'field_ui_field_overview', - 'page arguments' => array($entity_type, $bundle_arg), - 'type' => MENU_LOCAL_TASK, - 'weight' => 1, - 'file' => 'field_ui.admin.inc', - ) + $access_fields; - $items["$path/fields/%field_ui_instance"] = array( - 'load arguments' => array($entity_type, $bundle_arg, $bundle_pos, '%map'), - 'title callback' => 'field_ui_instance_title', - 'title arguments' => array($field_position), - 'page callback' => 'drupal_get_form', - 'page arguments' => array('field_ui_field_edit_form', $field_position), - 'file' => 'field_ui.admin.inc', - ) + $access_fields; - $items["$path/fields/%field_ui_instance/edit"] = array( - 'load arguments' => array($entity_type, $bundle_arg, $bundle_pos, '%map'), - 'title' => 'Edit', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('field_ui_field_edit_form', $field_position), - 'type' => MENU_DEFAULT_LOCAL_TASK, - 'file' => 'field_ui.admin.inc', - ) + $access_fields; - $items["$path/fields/%field_ui_instance/field-settings"] = array( - 'load arguments' => array($entity_type, $bundle_arg, $bundle_pos, '%map'), - 'title' => 'Field settings', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('field_ui_field_settings_form', $field_position), - 'type' => MENU_LOCAL_TASK, - 'file' => 'field_ui.admin.inc', - ) + $access_fields; - $items["$path/fields/%field_ui_instance/widget-type"] = array( - 'load arguments' => array($entity_type, $bundle_arg, $bundle_pos, '%map'), - 'title' => 'Widget type', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('field_ui_widget_type_form', $field_position), - 'type' => MENU_LOCAL_TASK, - 'file' => 'field_ui.admin.inc', - ) + $access_fields; - $items["$path/fields/%field_ui_instance/delete"] = array( - 'load arguments' => array($entity_type, $bundle_arg, $bundle_pos, '%map'), - 'title' => 'Delete', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('field_ui_field_delete_form', $field_position), - 'type' => MENU_VISIBLE_IN_BREADCRUMB, - 'weight' => 10, - 'file' => 'field_ui.admin.inc', - ) + $access_fields; + $items["$path/fields"] = array( + 'title' => 'Manage fields', + 'type' => MENU_LOCAL_TASK, + 'route_name' => "field_ui.overview.$entity_type", + 'weight' => 1, + ); + $items["$path/fields/%"] = array( + 'title callback' => 'field_ui_instance_title', + 'title arguments' => array($field_position), + 'route_name' => "field_ui.instance_edit.$entity_type", + ); + $items["$default_path/fields/%/edit"] = array( + 'title' => 'Edit', + 'type' => MENU_DEFAULT_LOCAL_TASK, + ); + $items["$path/fields/%/field-settings"] = array( + 'title' => 'Field settings', + 'type' => MENU_LOCAL_TASK, + 'route_name' => "field_ui.settings.$entity_type", + ); + $items["$path/fields/%/widget-type"] = array( + 'title' => 'Widget type', + 'type' => MENU_LOCAL_TASK, + 'route_name' => "field_ui.widget_type.$entity_type", + ); + $items["$path/fields/%/delete"] = array( + 'title' => 'Delete', + 'type' => MENU_VISIBLE_IN_BREADCRUMB, + 'route_name' => "field_ui.delete.$entity_type", + 'weight' => 10, + ); - // 'Manage display' tab. - $items["$path/display"] = array( - 'title' => 'Manage display', - 'page callback' => 'field_ui_display_overview', - 'page arguments' => array($entity_type, $bundle_arg, 'default'), - 'type' => MENU_LOCAL_TASK, - 'weight' => 2, - 'file' => 'field_ui.admin.inc', - ) + $access_display; + // 'Manage display' tab. + $items["$path/display"] = array( + 'title' => 'Manage display', + 'type' => MENU_LOCAL_TASK, + 'route_name' => "field_ui.display_overview.$entity_type", + 'weight' => 2, + ); - // View modes secondary tabs. - // The same base $path for the menu item (with a placeholder) can be - // used for all bundles of a given entity type; but depending on - // administrator settings, each bundle has a different set of view - // modes available for customisation. So we define menu items for all - // view modes, and use an access callback to determine which ones are - // actually visible for a given bundle. - $weight = 0; - $view_modes = array('default' => array('label' => t('Default'))) + entity_get_view_modes($entity_type); - foreach ($view_modes as $view_mode => $view_mode_info) { - $items["$path/display/$view_mode"] = array( - 'title' => $view_mode_info['label'], - 'page callback' => 'field_ui_display_overview', - 'page arguments' => array($entity_type, $bundle_arg, $view_mode), - // The access callback needs to check both the current 'custom - // display' setting for the view mode, and the overall access - // rules for the bundle admin pages. - 'access callback' => '_field_ui_view_mode_menu_access', - 'access arguments' => array($entity_type, $bundle_arg, $view_mode, $access_display['access arguments'][0]), - 'type' => ($view_mode == 'default' ? MENU_DEFAULT_LOCAL_TASK : MENU_LOCAL_TASK), - 'file' => 'field_ui.admin.inc', - ); - if ($view_mode != 'default') { - $items["$path/display/$view_mode"]['weight'] = $weight++; - } - } - } + // View modes secondary tabs. + // The same base $path for the menu item (with a placeholder) can be + // used for all bundles of a given entity type; but depending on + // administrator settings, each bundle has a different set of view + // modes available for customisation. So we define menu items for all + // view modes, and use an access callback to determine which ones are + // actually visible for a given bundle. + $items["$default_path/display/default"] = array( + 'title' => t('Default'), + 'type' => MENU_DEFAULT_LOCAL_TASK, + ); + $weight = 0; + foreach (entity_get_view_modes($entity_type) as $view_mode => $view_mode_info) { + $items["$path/display/$view_mode"] = array( + 'title' => $view_mode_info['label'], + 'type' => MENU_LOCAL_TASK, + 'weight' => $weight++, + 'route_name' => "field_ui.display_overview.$entity_type.$view_mode", + ); } } } @@ -267,25 +212,8 @@ function field_ui_instance_load($field_name, $entity_type, $bundle_name, $bundle * @see field_ui_menu() */ function field_ui_instance_title($instance) { - return $instance['label']; -} - -/** - * Access callback: Checks access for the 'view mode display settings' pages. - * - * @see field_ui_menu() - */ -function _field_ui_view_mode_menu_access($entity_type, $bundle, $view_mode, $permission) { - // First, determine visibility according to the 'use custom display' - // setting for the view mode. - $bundle = field_extract_bundle($entity_type, $bundle); - $view_mode_settings = field_view_mode_settings($entity_type, $bundle); - $visibility = ($view_mode == 'default') || !empty($view_mode_settings[$view_mode]['custom_settings']); - - // Then, determine access according to the $permission parameter. - if ($visibility) { - return user_access($permission); - } + $entity = entity_load('field_instance', $instance); + return $entity->label(); } /** diff --git a/core/modules/field_ui/field_ui.services.yml b/core/modules/field_ui/field_ui.services.yml new file mode 100644 index 0000000..cfc1214 --- /dev/null +++ b/core/modules/field_ui/field_ui.services.yml @@ -0,0 +1,10 @@ +services: + field_ui.subscriber: + class: Drupal\field_ui\Routing\RouteSubscriber + arguments: ['@plugin.manager.entity'] + tags: + - { name: event_subscriber } + access_check.field_ui.view_mode: + class: Drupal\field_ui\Access\ViewModeAccessCheck + tags: + - { name: access_check } diff --git a/core/modules/field_ui/lib/Drupal/field_ui/Access/ViewModeAccessCheck.php b/core/modules/field_ui/lib/Drupal/field_ui/Access/ViewModeAccessCheck.php new file mode 100644 index 0000000..640ae84 --- /dev/null +++ b/core/modules/field_ui/lib/Drupal/field_ui/Access/ViewModeAccessCheck.php @@ -0,0 +1,43 @@ +getRequirements()); + } + + /** + * {@inheritdoc} + */ + public function access(Route $route, Request $request) { + if ($entity_type = $request->attributes->get('entity_type')) { + $bundle = $request->attributes->get('bundle'); + $view_mode = $request->attributes->get('view_mode'); + + $view_mode_settings = field_view_mode_settings($entity_type, $bundle); + $visibility = ($view_mode == 'default') || !empty($view_mode_settings[$view_mode]['custom_settings']); + if ($visibility) { + $permission = $route->getRequirement('_field_ui_view_mode_access'); + return user_access($permission); + } + } + } + +} diff --git a/core/modules/field_ui/lib/Drupal/field_ui/DisplayOverview.php b/core/modules/field_ui/lib/Drupal/field_ui/DisplayOverview.php index 7ee40f4..ddc8ac0 100644 --- a/core/modules/field_ui/lib/Drupal/field_ui/DisplayOverview.php +++ b/core/modules/field_ui/lib/Drupal/field_ui/DisplayOverview.php @@ -41,12 +41,15 @@ public function getFormID() { /** * Implements \Drupal\Core\Form\FormInterface::buildForm(). */ - public function buildForm(array $form, array &$form_state) { + public function buildForm(array $form, array &$form_state, $entity_type = NULL, $bundle = NULL, $view_mode = NULL) { + parent::buildForm($form, $form_state, $entity_type, $bundle); + + $this->mode = (isset($view_mode) ? $view_mode : 'default'); // Gather type information. $instances = field_info_instances($this->entity_type, $this->bundle); $field_types = field_info_field_types(); $extra_fields = field_info_extra_fields($this->entity_type, $this->bundle, 'display'); - $entity_display = entity_get_display($this->entity_type, $this->bundle, $this->view_mode); + $entity_display = entity_get_display($this->entity_type, $this->bundle, $this->mode); $form_state += array( 'formatter_settings_edit' => NULL, @@ -55,7 +58,7 @@ public function buildForm(array $form, array &$form_state) { $form += array( '#entity_type' => $this->entity_type, '#bundle' => $this->bundle, - '#view_mode' => $this->view_mode, + '#view_mode' => $this->mode, '#fields' => array_keys($instances), '#extra' => array_keys($extra_fields), ); @@ -173,7 +176,7 @@ public function buildForm(array $form, array &$form_state) { if ($display_options && $display_options['type'] != 'hidden') { $formatter = drupal_container()->get('plugin.manager.field.formatter')->getInstance(array( 'instance' => $instance, - 'view_mode' => $this->view_mode, + 'view_mode' => $this->mode, 'configuration' => $display_options )); } @@ -206,7 +209,7 @@ public function buildForm(array $form, array &$form_state) { 'formatter' => $formatter, 'field' => $field, 'instance' => $instance, - 'view_mode' => $this->view_mode, + 'view_mode' => $this->mode, 'form' => $form, ); drupal_alter('field_formatter_settings_form', $settings_form, $form_state, $context); @@ -258,7 +261,7 @@ public function buildForm(array $form, array &$form_state) { 'formatter' => $formatter, 'field' => $field, 'instance' => $instance, - 'view_mode' => $this->view_mode, + 'view_mode' => $this->mode, ); drupal_alter('field_formatter_settings_summary', $summary, $context); @@ -342,7 +345,7 @@ public function buildForm(array $form, array &$form_state) { $form['fields'] = $table; // Custom display settings. - if ($this->view_mode == 'default') { + if ($this->mode == 'default') { $view_modes = entity_get_view_modes($this->entity_type); // Only show the settings if there is more than one view mode. if (count($view_modes) > 1) { @@ -411,7 +414,7 @@ public function buildForm(array $form, array &$form_state) { */ public function submitForm(array &$form, array &$form_state) { $form_values = $form_state['values']; - $display = entity_get_display($this->entity_type, $this->bundle, $this->view_mode); + $display = entity_get_display($this->entity_type, $this->bundle, $this->mode); // Collect data for 'regular' fields. foreach ($form['#fields'] as $field_name) { @@ -466,7 +469,7 @@ public function submitForm(array &$form, array &$form_state) { $display->save(); // Handle the 'view modes' checkboxes if present. - if ($this->view_mode == 'default' && !empty($form_values['view_modes_custom'])) { + if ($this->mode == 'default' && !empty($form_values['view_modes_custom'])) { $entity_info = entity_get_info($this->entity_type); $view_modes = entity_get_view_modes($this->entity_type); $bundle_settings = field_bundle_settings($this->entity_type, $this->bundle); diff --git a/core/modules/field_ui/lib/Drupal/field_ui/FieldOverview.php b/core/modules/field_ui/lib/Drupal/field_ui/FieldOverview.php index c17bfb2..b786aaf 100644 --- a/core/modules/field_ui/lib/Drupal/field_ui/FieldOverview.php +++ b/core/modules/field_ui/lib/Drupal/field_ui/FieldOverview.php @@ -15,16 +15,6 @@ class FieldOverview extends OverviewBase { /** - * Overrides Drupal\field_ui\OverviewBase::__construct(). - */ - public function __construct($entity_type, $bundle, $view_mode = NULL) { - $this->entity_type = $entity_type; - $this->bundle = $bundle; - $this->view_mode = 'form'; - $this->adminPath = field_ui_bundle_admin_path($this->entity_type, $this->bundle); - } - - /** * Implements Drupal\field_ui\OverviewBase::getRegions(). */ public function getRegions() { @@ -52,7 +42,10 @@ public function getFormID() { /** * Implements \Drupal\Core\Form\FormInterface::buildForm(). */ - public function buildForm(array $form, array &$form_state) { + public function buildForm(array $form, array &$form_state, $entity_type = NULL, $bundle = NULL, $form_mode = NULL) { + parent::buildForm($form, $form_state, $entity_type, $bundle); + + $this->mode = (isset($form_mode) ? $form_mode : 'default'); // When displaying the form, make sure the list of fields is up-to-date. if (empty($form_state['post'])) { field_info_cache_clear(); @@ -63,6 +56,7 @@ public function buildForm(array $form, array &$form_state) { $field_types = field_info_field_types(); $widget_types = field_info_widget_types(); $extra_fields = field_info_extra_fields($this->entity_type, $this->bundle, 'form'); + $entity_form_display = entity_get_form_display($this->entity_type, $this->bundle, $this->mode); $form += array( '#entity_type' => $this->entity_type, @@ -94,7 +88,8 @@ public function buildForm(array $form, array &$form_state) { // Fields. foreach ($instances as $name => $instance) { $field = field_info_field($instance['field_name']); - $admin_field_path = $this->adminPath . '/fields/' . $instance['field_name']; + $widget_configuration = $entity_form_display->getComponent($instance['field_name']); + $admin_field_path = $this->adminPath . '/fields/' . $instance->id(); $table[$name] = array( '#attributes' => array('class' => array('draggable', 'tabledrag-leaf')), '#row_type' => 'field', @@ -106,7 +101,7 @@ public function buildForm(array $form, array &$form_state) { '#type' => 'textfield', '#title' => t('Weight for @title', array('@title' => $instance['label'])), '#title_display' => 'invisible', - '#default_value' => $instance['widget']['weight'], + '#default_value' => $widget_configuration['weight'], '#size' => 3, '#attributes' => array('class' => array('field-weight')), ), @@ -137,7 +132,7 @@ public function buildForm(array $form, array &$form_state) { ), 'widget_type' => array( '#type' => 'link', - '#title' => $widget_types[$instance['widget']['type']]['label'], + '#title' => $widget_types[$widget_configuration['type']]['label'], '#href' => $admin_field_path . '/widget-type', '#options' => array('attributes' => array('title' => t('Change widget type.'))), ), @@ -212,7 +207,7 @@ public function buildForm(array $form, array &$form_state) { } // Additional row: add new field. - $max_weight = field_info_max_weight($this->entity_type, $this->bundle, 'form'); + $max_weight = $entity_form_display->getHighestWeight(); $field_type_options = field_ui_field_type_options(); $widget_type_options = field_ui_widget_type_options(NULL, TRUE); if ($field_type_options && $widget_type_options) { @@ -528,27 +523,29 @@ protected function validateAddExisting(array $form, array &$form_state) { */ public function submitForm(array &$form, array &$form_state) { $form_values = $form_state['values']['fields']; + $entity_form_display = entity_get_form_display($this->entity_type, $this->bundle, $this->mode); - $bundle_settings = field_bundle_settings($this->entity_type, $this->bundle); + // Collect data for 'regular' fields. + foreach ($form['#fields'] as $field_name) { + $options = $entity_form_display->getComponent($field_name); + $options['weight'] = $form_values[$field_name]['weight']; - // Update field weights. - foreach ($form_values as $key => $values) { - if (in_array($key, $form['#fields'])) { - $instance = field_read_instance($this->entity_type, $key, $this->bundle); - $instance['widget']['weight'] = $values['weight']; - field_update_instance($instance); - } - elseif (in_array($key, $form['#extra'])) { - $bundle_settings['extra_fields']['form'][$key]['weight'] = $values['weight']; - } + $entity_form_display->setComponent($field_name, $options); + } + + // Collect data for 'extra' fields. + foreach ($form['#extra'] as $field_name) { + $entity_form_display->setComponent($field_name, array( + 'weight' => $form_values[$field_name]['weight'], + )); } - field_bundle_settings($this->entity_type, $this->bundle, $bundle_settings); + // Save the form display. + $entity_form_display->save(); $destinations = array(); // Create new field. - $field = array(); if (!empty($form_values['_add_new_field']['field_name'])) { $values = $form_values['_add_new_field']; @@ -562,16 +559,22 @@ public function submitForm(array &$form, array &$form_state) { 'entity_type' => $this->entity_type, 'bundle' => $this->bundle, 'label' => $values['label'], - 'widget' => array( - 'type' => $values['widget_type'], - 'weight' => $values['weight'], - ), ); // Create the field and instance. try { - field_create_field($field); - field_create_instance($instance); + $this->entityManager->getStorageController('field_entity')->create($field)->save(); + $new_instance = $this->entityManager->getStorageController('field_instance')->create($instance); + $new_instance->save(); + + // Make sure the field is displayed in the 'default' form mode (using + // the configured widget and default settings). + entity_get_form_display($this->entity_type, $this->bundle, 'default') + ->setComponent($field['field_name'], array( + 'type' => $values['widget_type'], + 'weight' => $values['weight'], + )) + ->save(); // Make sure the field is displayed in the 'default' view mode (using // default formatter and settings). It stays hidden for other view @@ -582,13 +585,13 @@ public function submitForm(array &$form, array &$form_state) { // Always show the field settings step, as the cardinality needs to be // configured for new fields. - $destinations[] = $this->adminPath. '/fields/' . $field['field_name'] . '/field-settings'; - $destinations[] = $this->adminPath . '/fields/' . $field['field_name']; + $destinations[] = $this->adminPath. '/fields/' . $new_instance->id() . '/field-settings'; + $destinations[] = $this->adminPath . '/fields/' . $new_instance->id(); // Store new field information for any additional submit handlers. $form_state['fields_added']['_add_new_field'] = $field['field_name']; } - catch (Exception $e) { + catch (\Exception $e) { drupal_set_message(t('There was a problem creating field %label: !message', array('%label' => $instance['label'], '!message' => $e->getMessage())), 'error'); } } @@ -606,14 +609,20 @@ public function submitForm(array &$form, array &$form_state) { 'entity_type' => $this->entity_type, 'bundle' => $this->bundle, 'label' => $values['label'], - 'widget' => array( - 'type' => $values['widget_type'], - 'weight' => $values['weight'], - ), ); try { - field_create_instance($instance); + $new_instance = $this->entityManager->getStorageController('field_instance')->create($instance); + $new_instance->save(); + + // Make sure the field is displayed in the 'default' form mode (using + // the configured widget and default settings). + entity_get_form_display($this->entity_type, $this->bundle, 'default') + ->setComponent($field['field_name'], array( + 'type' => $values['widget_type'], + 'weight' => $values['weight'], + )) + ->save(); // Make sure the field is displayed in the 'default' view mode (using // default formatter and settings). It stays hidden for other view @@ -622,11 +631,11 @@ public function submitForm(array &$form, array &$form_state) { ->setComponent($field['field_name']) ->save(); - $destinations[] = $this->adminPath . '/fields/' . $instance['field_name']; + $destinations[] = $this->adminPath . '/fields/' . $new_instance->id(); // Store new field information for any additional submit handlers. $form_state['fields_added']['_add_existing_field'] = $instance['field_name']; } - catch (Exception $e) { + catch (\Exception $e) { drupal_set_message(t('There was a problem creating field instance %label: @message.', array('%label' => $instance['label'], '@message' => $e->getMessage())), 'error'); } } diff --git a/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldDeleteForm.php b/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldDeleteForm.php new file mode 100644 index 0000000..6b20911 --- /dev/null +++ b/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldDeleteForm.php @@ -0,0 +1,92 @@ + $this->instance->label())); + } + + /** + * {@inheritdoc} + */ + protected function getConfirmText() { + return t('Delete'); + } + + /** + * {@inheritdoc} + */ + protected function getCancelPath() { + return field_ui_bundle_admin_path($this->instance->entity_type, $this->instance->bundle) . '/fields'; + } + + /** + * {@inheritdoc} + */ + public function buildForm(array $form, array &$form_state, FieldInstance $field_instance = NULL) { + $this->instance = $form_state['instance'] = $field_instance; + + return parent::buildForm($form, $form_state); + } + + /** + * {@inheritdoc} + */ + public function submitForm(array &$form, array &$form_state) { + form_load_include($form_state, 'inc', 'field_ui', 'field_ui.admin'); + + $field = $this->instance->getField(); + $bundles = entity_get_bundles(); + $bundle_label = $bundles[$this->instance->entity_type][$this->instance->bundle]['label']; + + if ($field && !$field['locked']) { + $this->instance->delete(TRUE); + drupal_set_message(t('The field %field has been deleted from the %type content type.', array('%field' => $this->instance->label(), '%type' => $bundle_label))); + } + else { + drupal_set_message(t('There was a problem removing the %field from the %type content type.', array('%field' => $this->instance->label(), '%type' => $bundle_label)), 'error'); + } + + $admin_path = field_ui_bundle_admin_path($this->instance->entity_type, $this->instance->bundle); + $form_state['redirect'] = field_ui_get_destinations(array($admin_path . '/fields')); + + // Fields are purged on cron. However field module prevents disabling modules + // when field types they provided are used in a field until it is fully + // purged. In the case that a field has minimal or no content, a single call + // to field_purge_batch() will remove it from the system. Call this with a + // low batch limit to avoid administrators having to wait for cron runs when + // removing instances that meet this criteria. + field_purge_batch(10); + } + +} diff --git a/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldInstanceEditForm.php b/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldInstanceEditForm.php new file mode 100644 index 0000000..8717b93 --- /dev/null +++ b/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldInstanceEditForm.php @@ -0,0 +1,306 @@ +widgetManager = $widget_manager; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('plugin.manager.field.widget') + ); + } + + /** + * {@inheritdoc} + */ + public function getFormID() { + return 'field_ui_field_edit_form'; + } + + /** + * {@inheritdoc} + */ + public function buildForm(array $form, array &$form_state, FieldInstance $field_instance = NULL) { + $this->instance = $form_state['instance'] = $field_instance; + + $bundle = $this->instance['bundle']; + $entity_type = $this->instance['entity_type']; + $field = Field::fieldInfo()->getField($this->instance['field_name']); + $entity_form_display = entity_get_form_display($entity_type, $bundle, 'default'); + $bundles = entity_get_bundles(); + + drupal_set_title(t('%instance settings for %bundle', array( + '%instance' => $this->instance->label(), + '%bundle' => $bundles[$entity_type][$bundle]['label'], + )), PASS_THROUGH); + + $form['#field'] = $field; + $form['#entity_form_display'] = $entity_form_display; + // Create an arbitrary entity object (used by the 'default value' widget). + $ids = (object) array('entity_type' => $this->instance['entity_type'], 'bundle' => $this->instance['bundle'], 'entity_id' => NULL); + $form['#entity'] = _field_create_entity_from_ids($ids); + $form['#entity']->field_ui_default_value = TRUE; + + if (!empty($field['locked'])) { + $form['locked'] = array( + '#markup' => t('The field %field is locked and cannot be edited.', array('%field' => $this->instance->label())), + ); + return $form; + } + + // Create a form structure for the instance values. + $form['instance'] = array( + '#tree' => TRUE, + ); + + // Build the non-configurable instance values. + $form['instance']['field_name'] = array( + '#type' => 'value', + '#value' => $this->instance['field_name'], + ); + $form['instance']['entity_type'] = array( + '#type' => 'value', + '#value' => $entity_type, + ); + $form['instance']['bundle'] = array( + '#type' => 'value', + '#value' => $bundle, + ); + + // Build the configurable instance values. + $form['instance']['label'] = array( + '#type' => 'textfield', + '#title' => t('Label'), + '#default_value' => $this->instance->label() ?: $field['field_name'], + '#required' => TRUE, + '#weight' => -20, + ); + + $form['instance']['description'] = array( + '#type' => 'textarea', + '#title' => t('Help text'), + '#default_value' => !empty($this->instance['description']) ? $this->instance['description'] : '', + '#rows' => 5, + '#description' => t('Instructions to present to the user below this field on the editing form.
Allowed HTML tags: @tags', array('@tags' => _field_filter_xss_display_allowed_tags())) . '
' . t('This field supports tokens.'), + '#weight' => -10, + ); + + $form['instance']['required'] = array( + '#type' => 'checkbox', + '#title' => t('Required field'), + '#default_value' => !empty($this->instance['required']), + '#weight' => -5, + ); + + // Add additional field instance settings from the field module. + $additions = \Drupal::moduleHandler()->invoke($field['module'], 'field_instance_settings_form', array($field, $this->instance, $form_state)); + if (is_array($additions)) { + $form['instance']['settings'] = $additions; + $form['instance']['settings']['#weight'] = 10; + } + + // Add widget settings for the widget type. + $additions = $entity_form_display->getWidget($this->instance->getField()->id)->settingsForm($form, $form_state); + $form['instance']['widget']['settings'] = $additions ?: array('#type' => 'value', '#value' => array()); + $form['instance']['widget']['#weight'] = 20; + + // Add handling for default value if not provided by any other module. + if (field_behaviors_widget('default_value', $this->instance) == FIELD_BEHAVIOR_DEFAULT && empty($this->instance['default_value_function'])) { + $form['instance']['default_value_widget'] = $this->getDefaultValueWidget($field, $form, $form_state); + } + + $form['actions'] = array('#type' => 'actions'); + $form['actions']['submit'] = array( + '#type' => 'submit', + '#value' => t('Save settings') + ); + $form['actions']['delete'] = array( + '#type' => 'submit', + '#value' => t('Delete field'), + '#submit' => array(array($this, 'delete')), + ); + return $form; + } + + /** + * {@inheritdoc} + */ + public function validateForm(array &$form, array &$form_state) { + // Take the incoming values as the $this->instance definition, so that the 'default + // value' gets validated using the instance settings being submitted. + $field_name = $this->instance['field_name']; + $entity = $form['#entity']; + $entity_form_display = $form['#entity_form_display']; + + if (isset($form['instance']['default_value_widget'])) { + $element = $form['instance']['default_value_widget']; + + // Extract the 'default value'. + $items = array(); + $entity_form_display->getWidget($this->instance->getField()->id)->extractFormValues($entity, LANGUAGE_NOT_SPECIFIED, $items, $element, $form_state); + + // Grab the field definition from $form_state. + $field_state = field_form_get_state($element['#parents'], $field_name, LANGUAGE_NOT_SPECIFIED, $form_state); + $field = $field_state['field']; + + // Validate the value. + $errors = array(); + $function = $field['module'] . '_field_validate'; + if (function_exists($function)) { + $function(NULL, $field, $this->instance, LANGUAGE_NOT_SPECIFIED, $items, $errors); + } + + // Report errors. + if (isset($errors[$field_name][LANGUAGE_NOT_SPECIFIED])) { + // Store reported errors in $form_state. + $field_state['errors'] = $errors[$field_name][LANGUAGE_NOT_SPECIFIED]; + field_form_set_state($element['#parents'], $field_name, LANGUAGE_NOT_SPECIFIED, $form_state, $field_state); + + // Assign reported errors to the correct form element. + $entity_form_display->getWidget($this->instance->getField()->id)->flagErrors($entity, LANGUAGE_NOT_SPECIFIED, $items, $element, $form_state); + } + } + } + + /** + * {@inheritdoc} + */ + public function submitForm(array &$form, array &$form_state) { + form_load_include($form_state, 'inc', 'field_ui', 'field_ui.admin'); + $entity = $form['#entity']; + $entity_form_display = $form['#entity_form_display']; + + // Handle the default value. + if (isset($form['instance']['default_value_widget'])) { + $element = $form['instance']['default_value_widget']; + + // Extract field values. + $items = array(); + $entity_form_display->getWidget($this->instance->getField()->id)->extractFormValues($entity, LANGUAGE_NOT_SPECIFIED, $items, $element, $form_state); + + $this->instance['default_value'] = $items ? $items : NULL; + } + + // Handle widget settings. + $options = $entity_form_display->getComponent($this->instance->getField()->id); + $options['settings'] = $form_state['values']['instance']['widget']['settings']; + $entity_form_display->setComponent($this->instance->getField()->id, $options)->save(); + unset($form_state['values']['instance']['widget']); + + // Merge incoming values into the instance. + foreach ($form_state['values']['instance'] as $key => $value) { + $this->instance[$key] = $value; + } + $this->instance->save(); + + drupal_set_message(t('Saved %label configuration.', array('%label' => $this->instance->label()))); + + if ($this->instance['required'] && empty($this->instance['default_value']) && empty($this->instance['default_value_function']) && $this->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' => $this->instance['label'])), 'warning'); + } + + $form_state['redirect'] = field_ui_next_destination($this->instance['entity_type'], $this->instance['bundle']); + } + + /** + * Redirects to the field instance deletion form. + */ + public function delete(array &$form, array &$form_state) { + $destination = array(); + if (isset($_GET['destination'])) { + $destination = drupal_get_destination(); + unset($_GET['destination']); + } + $form_state['redirect'] = array('admin/structure/types/manage/' . $this->instance['bundle'] . '/fields/' . $this->instance->id() . '/delete', array('query' => $destination)); + } + + /** + * Builds the default value widget for a given field instance. + */ + protected function getDefaultValueWidget($field, array &$form, &$form_state) { + $entity = $form['#entity']; + $entity_form_display = $form['#entity_form_display']; + + $element = array( + '#type' => 'details', + '#title' => t('Default value'), + '#tree' => TRUE, + '#description' => t('The default value for this field, used when creating new content.'), + // Stick to an empty 'parents' on this form in order not to breaks widgets + // that do not use field_widget_[field|instance]() and still access + // $form_state['field'] directly. + '#parents' => array(), + ); + + // Adjust the instance definition used for the form element. We want a + // non-required input and no description. + $this->instance['required'] = FALSE; + $this->instance['description'] = ''; + + // Adjust the instance definition to use the default widget of this field type + // instead of the hidden widget. + if ($this->instance['widget']['type'] == 'field_hidden') { + $field_type = field_info_field_types($field['type']); + $default_widget = $this->widgetManager->getDefinition($field_type['default_widget']); + + $this->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(); + if (!empty($this->instance['default_value'])) { + $items = (array) $this->instance['default_value']; + } + $element += $entity_form_display->getWidget($this->instance->getField()->id)->form($entity, LANGUAGE_NOT_SPECIFIED, $items, $element, $form_state); + + return $element; + } + +} diff --git a/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldSettingsForm.php b/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldSettingsForm.php new file mode 100644 index 0000000..bfc20ce --- /dev/null +++ b/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldSettingsForm.php @@ -0,0 +1,162 @@ +instance = $form_state['instance'] = $field_instance; + $field = $this->instance->getField(); + $form['#field'] = $field; + + drupal_set_title($this->instance->label()); + + $description = '

' . t('These settings apply to the %field field everywhere it is used. These settings impact the way that data is stored in the database and cannot be changed once data has been created.', array('%field' => $this->instance->label())) . '

'; + + // Create a form structure for the field values. + $form['field'] = array( + '#prefix' => $description, + '#tree' => TRUE, + ); + + // See if data already exists for this field. + // If so, prevent changes to the field settings. + $has_data = field_has_data($field); + if ($has_data) { + $form['field']['#prefix'] = '
' . t('There is data for this field in the database. The field settings can no longer be changed.') . '
' . $form['field']['#prefix']; + } + + // Build the configurable field values. + $cardinality = $field['cardinality']; + $form['field']['container'] = array( + // We can't use the container element because it doesn't support the title + // or description properties. + '#type' => 'item', + '#field_prefix' => '
', + '#field_suffix' => '
', + '#title' => t('Maximum number of values users can enter'), + ); + $form['field']['container']['cardinality'] = array( + '#type' => 'select', + '#options' => drupal_map_assoc(range(1, 5)) + array(FIELD_CARDINALITY_UNLIMITED => t('Unlimited')) + array('other' => t('More')), + '#default_value' => ($cardinality < 6) ? $cardinality : 'other', + ); + // @todo Convert when http://drupal.org/node/1207060 gets in. + $form['field']['container']['cardinality_other'] = array( + '#type' => 'number', + '#default_value' => $cardinality > 5 ? $cardinality : 6, + '#min' => 1, + '#title' => t('Custom value'), + '#title_display' => 'invisible', + '#states' => array( + 'visible' => array( + ':input[name="field[container][cardinality]"]' => array('value' => 'other'), + ), + ), + ); + if (field_behaviors_widget('multiple_values', $this->instance) == FIELD_BEHAVIOR_DEFAULT) { + $form['field']['container']['#description'] = t('%unlimited will provide an %add-more button so users can add as many values as they like.', array( + '%unlimited' => t('Unlimited'), + '%add-more' => t('Add another item'), + )); + } + + // Build the non-configurable field values. + $form['field']['field_name'] = array('#type' => 'value', '#value' => $field['field_name']); + $form['field']['type'] = array('#type' => 'value', '#value' => $field['type']); + $form['field']['module'] = array('#type' => 'value', '#value' => $field['module']); + $form['field']['active'] = array('#type' => 'value', '#value' => $field['active']); + + // Add settings provided by the field module. The field module is + // responsible for not returning settings that cannot be changed if + // the field already has data. + $form['field']['settings'] = array( + '#weight' => 10, + ); + $additions = \Drupal::moduleHandler()->invoke($field['module'], 'field_settings_form', array($field, $this->instance, $has_data)); + if (is_array($additions)) { + $form['field']['settings'] += $additions; + } + + $form['actions'] = array('#type' => 'actions'); + $form['actions']['submit'] = array('#type' => 'submit', '#value' => t('Save field settings')); + return $form; + } + + /** + * {@inheritdoc} + */ + public function validateForm(array &$form, array &$form_state) { + // Validate field cardinality. + $cardinality = $form_state['values']['field']['container']['cardinality']; + $cardinality_other = $form_state['values']['field']['container']['cardinality_other']; + if ($cardinality == 'other' && empty($cardinality_other)) { + form_error($form['field']['container']['cardinality_other'], t('Number of values is required.')); + } + } + + /** + * {@inheritdoc} + */ + public function submitForm(array &$form, array &$form_state) { + form_load_include($form_state, 'inc', 'field_ui', 'field_ui.admin'); + $form_values = $form_state['values']; + $field_values = $form_values['field']; + + // Save field cardinality. + $cardinality = $field_values['container']['cardinality']; + $cardinality_other = $field_values['container']['cardinality_other']; + $cardinality_other = $form_state['values']['field']['container']['cardinality_other']; + if ($cardinality == 'other') { + $cardinality = $cardinality_other; + } + $field_values['cardinality'] = $cardinality; + unset($field_values['container']); + + // Merge incoming form values into the existing field. + $field = Field::fieldInfo()->getField($field_values['field_name']); + foreach ($field_values as $key => $value) { + $field[$key] = $value; + } + + // Update the field. + try { + $field->save(); + drupal_set_message(t('Updated field %label field settings.', array('%label' => $this->instance->label()))); + $form_state['redirect'] = field_ui_next_destination($this->instance->entity_type, $this->instance->bundle); + } + catch (Exception $e) { + drupal_set_message(t('Attempt to update field %label failed: %message.', array('%label' => $this->instance->label(), '%message' => $e->getMessage())), 'error'); + } + } + +} diff --git a/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldWidgetTypeForm.php b/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldWidgetTypeForm.php new file mode 100644 index 0000000..636c683 --- /dev/null +++ b/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldWidgetTypeForm.php @@ -0,0 +1,137 @@ +widgetManager = $widget_manager; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('plugin.manager.field.widget') + ); + } + + /** + * {@inheritdoc} + */ + public function getFormID() { + return 'field_ui_widget_type_form'; + } + + /** + * {@inheritdoc} + */ + public function buildForm(array $form, array &$form_state, FieldInstance $field_instance = NULL) { + $this->instance = $form_state['instance'] = $field_instance; + form_load_include($form_state, 'inc', 'field_ui', 'field_ui.admin'); + drupal_set_title($this->instance['label']); + + $bundle = $this->instance['bundle']; + $entity_type = $this->instance['entity_type']; + $field_name = $this->instance['field_name']; + + $entity_form_display = entity_get_form_display($entity_type, $bundle, 'default'); + $field = Field::fieldInfo()->getField($field_name); + $bundles = entity_get_bundles(); + $bundle_label = $bundles[$entity_type][$bundle]['label']; + + $form = array( + '#bundle' => $bundle, + '#entity_type' => $entity_type, + '#field_name' => $field_name, + '#instance' => $this->instance, + ); + + $form['widget_type'] = array( + '#type' => 'select', + '#title' => t('Widget type'), + '#required' => TRUE, + '#options' => field_ui_widget_type_options($field['type']), + '#default_value' => $entity_form_display->getWidget($field_name)->getPluginId(), + '#description' => t('The type of form element you would like to present to the user when creating this field in the %type type.', array('%type' => $bundle_label)), + ); + + $form['actions'] = array('#type' => 'actions'); + $form['actions']['submit'] = array('#type' => 'submit', '#value' => t('Continue')); + + return $form; + } + + /** + * {@inheritdoc} + */ + public function validateForm(array &$form, array &$form_state) { + } + + /** + * {@inheritdoc} + */ + public function submitForm(array &$form, array &$form_state) { + $form_values = $form_state['values']; + $bundle = $form['#bundle']; + $entity_type = $form['#entity_type']; + $field_name = $form['#field_name']; + $instance = $form['#instance']; + + $entity_form_display = entity_get_form_display($entity_type, $bundle, 'default') + ->setComponent($field_name, array( + 'type' => $form_values['widget_type'], + )); + + try { + $entity_form_display->save(); + 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'); + } + + $form_state['redirect'] = field_ui_next_destination($entity_type, $bundle); + } + +} diff --git a/core/modules/field_ui/lib/Drupal/field_ui/OverviewBase.php b/core/modules/field_ui/lib/Drupal/field_ui/OverviewBase.php index 5a76dc1..c306141 100644 --- a/core/modules/field_ui/lib/Drupal/field_ui/OverviewBase.php +++ b/core/modules/field_ui/lib/Drupal/field_ui/OverviewBase.php @@ -7,12 +7,15 @@ namespace Drupal\field_ui; +use Symfony\Component\DependencyInjection\ContainerInterface; use Drupal\Core\Form\FormInterface; +use Drupal\Core\ControllerInterface; +use Drupal\Core\Entity\EntityManager; /** * Abstract base class for Field UI overview forms. */ -abstract class OverviewBase implements FormInterface { +abstract class OverviewBase implements FormInterface, ControllerInterface { /** * The name of the entity type. @@ -29,11 +32,11 @@ protected $bundle = ''; /** - * The entity view mode. + * The entity view or form mode. * * @var string */ - protected $view_mode = ''; + protected $mode = ''; /** * The admin path of the overview page. @@ -43,20 +46,43 @@ protected $adminPath = NULL; /** - * Constructs the overview object for a entity type, bundle and view mode. + * The entity manager. * - * @param string $entity_type - * The entity type. - * @param string $bundle - * The bundle for the entity of entity_type. - * @param string $view_mode - * (optional) The view mode for the entity which takes a string or - * "default". + * @var \Drupal\Core\Entity\EntityManager */ - public function __construct($entity_type, $bundle, $view_mode = NULL) { + protected $entityManager; + + /** + * Constructs a new OverviewBase. + * + * @param \Drupal\Core\Entity\EntityManager $entity_manager + * The entity manager. + */ + public function __construct(EntityManager $entity_manager) { + $this->entityManager = $entity_manager; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('plugin.manager.entity') + ); + } + + /** + * {@inheritdoc} + */ + public function buildForm(array $form, array &$form_state, $entity_type = NULL, $bundle = NULL) { + $entity_info = $this->entityManager->getDefinition($entity_type); + if (!empty($entity_info['bundle_prefix'])) { + $bundle = $entity_info['bundle_prefix'] . $bundle; + } + + form_load_include($form_state, 'inc', 'field_ui', 'field_ui.admin'); $this->entity_type = $entity_type; $this->bundle = $bundle; - $this->view_mode = (isset($view_mode) ? $view_mode : 'default'); $this->adminPath = field_ui_bundle_admin_path($this->entity_type, $this->bundle); } diff --git a/core/modules/field_ui/lib/Drupal/field_ui/Routing/RouteSubscriber.php b/core/modules/field_ui/lib/Drupal/field_ui/Routing/RouteSubscriber.php new file mode 100644 index 0000000..94e7b09 --- /dev/null +++ b/core/modules/field_ui/lib/Drupal/field_ui/Routing/RouteSubscriber.php @@ -0,0 +1,116 @@ +manager = $manager; + } + + /** + * {@inheritdoc} + */ + public static function getSubscribedEvents() { + $events[RoutingEvents::DYNAMIC] = 'routes'; + return $events; + } + + /** + * Adds routes for the Field UI. + */ + public function routes(RouteBuildEvent $event) { + $collection = $event->getRouteCollection(); + foreach ($this->manager->getDefinitions() as $entity_type => $entity_info) { + if ($entity_info['fieldable'] && isset($entity_info['route_base_path'])) { + $path = $entity_info['route_base_path']; + + $route = new Route( + "$path/fields/{field_instance}", + array('_form' => '\Drupal\field_ui\Form\FieldInstanceEditForm'), + array('_permission' => 'administer ' . $entity_type . ' fields') + ); + $collection->add("field_ui.instance_edit.$entity_type", $route); + + $route = new Route( + "$path/fields/{field_instance}/widget-type", + array('_form' => '\Drupal\field_ui\Form\FieldWidgetTypeForm'), + array('_permission' => 'administer ' . $entity_type . ' fields') + ); + $collection->add("field_ui.widget_type.$entity_type", $route); + + $route = new Route( + "$path/fields/{field_instance}/field-settings", + array('_form' => '\Drupal\field_ui\Form\FieldSettingsForm'), + array('_permission' => 'administer ' . $entity_type . ' fields') + ); + $collection->add("field_ui.settings.$entity_type", $route); + + $route = new Route( + "$path/fields/{field_instance}/delete", + array('_form' => '\Drupal\field_ui\Form\FieldDeleteForm'), + array('_permission' => 'administer ' . $entity_type . ' fields') + ); + $collection->add("field_ui.delete.$entity_type", $route); + + // If the entity type has no bundles, use the entity type. + $defaults['entity_type'] = $entity_type; + if (empty($entity_info['entity_keys']['bundle'])) { + $defaults['bundle'] = $entity_type; + } + $route = new Route( + "$path/fields", + array('_form' => '\Drupal\field_ui\FieldOverview') + $defaults, + array('_permission' => 'administer ' . $entity_type . ' fields') + ); + $collection->add("field_ui.overview.$entity_type", $route); + + $route = new Route( + "$path/display", + array('_form' => '\Drupal\field_ui\DisplayOverview') + $defaults, + array('_permission' => 'administer ' . $entity_type . ' display') + ); + $collection->add("field_ui.display_overview.$entity_type", $route); + + foreach (entity_get_view_modes($entity_type) as $view_mode => $view_mode_info) { + $route = new Route( + "$path/display/$view_mode", + array( + '_form' => '\Drupal\field_ui\DisplayOverview', + 'view_mode' => $view_mode, + ) + $defaults, + array('_field_ui_view_mode_access' => 'administer ' . $entity_type . ' display')); + $collection->add("field_ui.display_overview.$entity_type.$view_mode", $route); + } + } + } + } + +} diff --git a/core/modules/field_ui/lib/Drupal/field_ui/Tests/AlterTest.php b/core/modules/field_ui/lib/Drupal/field_ui/Tests/AlterTest.php deleted file mode 100644 index 016b9d0..0000000 --- a/core/modules/field_ui/lib/Drupal/field_ui/Tests/AlterTest.php +++ /dev/null @@ -1,112 +0,0 @@ - 'Widget customization', - 'description' => 'Test custom field widget hooks and callbacks on field administration pages.', - 'group' => 'Field UI', - ); - } - - function setUp() { - parent::setUp(); - - // Create Article node type. - $this->drupalCreateContentType(array('type' => 'page', 'name' => 'Basic page')); - $this->drupalCreateContentType(array('type' => 'article', 'name' => 'Article')); - - // Create test user. - $admin_user = $this->drupalCreateUser(array('access content', 'administer content types', 'administer node fields', 'administer users', 'administer user fields')); - $this->drupalLogin($admin_user); - } - - /** - * Tests hook_field_widget_properties_alter() on the default field widget. - * - * @see field_test_field_widget_properties_alter() - * @see field_test_field_widget_properties_user_alter() - * @see field_test_field_widget_form_alter() - */ - function testDefaultWidgetPropertiesAlter() { - // Create the alter_test_text field and an instance on article nodes. - field_create_field(array( - 'field_name' => 'alter_test_text', - 'type' => 'text', - )); - $instance = array( - 'field_name' => 'alter_test_text', - 'entity_type' => 'node', - 'bundle' => 'article', - 'widget' => array( - 'type' => 'text_textfield', - 'size' => 60, - ), - ); - field_create_instance($instance); - - // Test that field_test_field_widget_properties_alter() sets the size to - // 42 and that field_test_field_widget_form_alter() reports the correct - // size when the form is displayed. - $this->drupalGet('admin/structure/types/manage/article/fields/alter_test_text'); - $this->assertText('Field size: 42', 'Altered field size is found in hook_field_widget_form_alter().'); - // Test that hook_field_widget_form_alter() registers this is the default - // value form and sets a message. - $this->assertText('From hook_field_widget_form_alter(): Default form is true.', 'Default value form detected in hook_field_widget_form_alter().'); - - // Create the alter_test_options field. - field_create_field(array( - 'field_name' => 'alter_test_options', - 'type' => 'list_text' - )); - // Create instances on users and page nodes. - $instance = array( - 'field_name' => 'alter_test_options', - 'entity_type' => 'user', - 'bundle' => 'user', - 'widget' => array( - 'type' => 'options_select', - ) - ); - field_create_instance($instance); - $instance = array( - 'field_name' => 'alter_test_options', - 'entity_type' => 'node', - 'bundle' => 'page', - 'widget' => array( - 'type' => 'options_select', - ) - ); - field_create_instance($instance); - - // Test that field_test_field_widget_properties_user_alter() replaces - // the widget and that field_test_field_widget_form_alter() reports the - // correct widget name when the form is displayed. - $this->drupalGet('admin/config/people/accounts/fields/alter_test_options'); - $this->assertText('Widget type: options_buttons', 'Widget type is altered for users in hook_field_widget_form_alter().'); - - // Test that the widget is not altered on page nodes. - $this->drupalGet('admin/structure/types/manage/page/fields/alter_test_options'); - $this->assertText('Widget type: options_select', 'Widget type is not altered for pages in hook_field_widget_form_alter().'); - } -} diff --git a/core/modules/field_ui/lib/Drupal/field_ui/Tests/ManageFieldsTest.php b/core/modules/field_ui/lib/Drupal/field_ui/Tests/ManageFieldsTest.php index cbc132f..bcd5d9e 100644 --- a/core/modules/field_ui/lib/Drupal/field_ui/Tests/ManageFieldsTest.php +++ b/core/modules/field_ui/lib/Drupal/field_ui/Tests/ManageFieldsTest.php @@ -52,6 +52,10 @@ function setUp() { 'bundle' => 'article', ); field_create_instance($instance); + + entity_get_form_display('node', 'article', 'default') + ->setComponent('field_' . $vocabulary->id()) + ->save(); } /** @@ -123,8 +127,9 @@ function createField() { * Tests editing an existing field. */ function updateField() { + $instance_id = 'node.' . $this->type . '.' . $this->field_name; // Go to the field edit page. - $this->drupalGet('admin/structure/types/manage/' . $this->type . '/fields/' . $this->field_name . '/field-settings'); + $this->drupalGet('admin/structure/types/manage/' . $this->type . '/fields/' . $instance_id . '/field-settings'); // Populate the field settings with new settings. $string = 'updated dummy test string'; @@ -134,7 +139,7 @@ function updateField() { $this->drupalPost(NULL, $edit, t('Save field settings')); // Go to the field instance edit page. - $this->drupalGet('admin/structure/types/manage/' . $this->type . '/fields/' . $this->field_name); + $this->drupalGet('admin/structure/types/manage/' . $this->type . '/fields/' . $instance_id); $edit = array( 'instance[settings][test_instance_setting]' => $string, 'instance[widget][settings][test_widget_setting]' => $string, @@ -176,7 +181,7 @@ function addExistingField() { * numeric value. That is tested already in FormTest::testNumber(). */ function cardinalitySettings() { - $field_edit_path = 'admin/structure/types/manage/article/fields/body/field-settings'; + $field_edit_path = 'admin/structure/types/manage/article/fields/node.article.body/field-settings'; // Assert the cardinality other field cannot be empty when cardinality is // set to other. @@ -234,7 +239,10 @@ function assertFieldSettings($bundle, $field_name, $string = 'dummy test string' // Assert instance and widget settings. $instance = field_info_instance($entity_type, $field_name, $bundle); $this->assertTrue($instance['settings']['test_instance_setting'] == $string, 'Field instance settings were found.'); - $this->assertTrue($instance['widget']['settings']['test_widget_setting'] == $string, 'Field widget settings were found.'); + + // Assert widget settings. + $widget_configuration = entity_get_form_display($entity_type, $bundle, 'default')->getComponent($field_name); + $this->assertTrue($widget_configuration['settings']['test_widget_setting'] == $string, 'Field widget settings were found.'); } /** @@ -253,10 +261,14 @@ function testDefaultValue() { 'entity_type' => 'node', 'bundle' => $this->type, ); - field_create_instance($instance); + $instance = field_create_instance($instance); + + entity_get_form_display('node', $this->type, 'default') + ->setComponent($field_name) + ->save(); $langcode = LANGUAGE_NOT_SPECIFIED; - $admin_path = 'admin/structure/types/manage/' . $this->type . '/fields/' . $field_name; + $admin_path = 'admin/structure/types/manage/' . $this->type . '/fields/' . $instance->id(); $element_id = "edit-$field_name-$langcode-0-value"; $element_name = "{$field_name}[$langcode][0][value]"; $this->drupalGet($admin_path); @@ -271,6 +283,7 @@ function testDefaultValue() { $edit = array($element_name => '1'); $this->drupalPost($admin_path, $edit, t('Save settings')); $this->assertText("Saved $field_name configuration", 'The form was successfully submitted.'); + field_info_cache_clear(); $instance = field_info_instance('node', $field_name, $this->type); $this->assertEqual($instance['default_value'], array(array('value' => 1)), 'The default value was correctly saved.'); @@ -287,8 +300,11 @@ function testDefaultValue() { $this->assertEqual($instance['default_value'], NULL, 'The default value was correctly saved.'); // Change the widget to TestFieldWidgetNoDefault. - $instance['widget']['type'] = 'test_field_widget_no_default'; - field_update_instance($instance); + entity_get_form_display($instance['entity_type'], $instance['bundle'], 'default') + ->setComponent($field_name, array( + 'type' => 'test_field_widget_no_default', + )) + ->save(); $this->drupalGet($admin_path); $this->assertNoFieldById($element_id, '', t('No default value was possible for widget that disables default value.')); @@ -320,7 +336,7 @@ function testDeleteField() { $this->fieldUIAddExistingField($bundle_path2, $edit2); // Delete the first instance. - $this->fieldUIDeleteField($bundle_path1, $this->field_name, $this->field_label, $this->type); + $this->fieldUIDeleteField($bundle_path1, "node.$this->type.$this->field_name", $this->field_label, $this->type); // Reset the fields info. field_info_cache_clear(); @@ -330,7 +346,7 @@ function testDeleteField() { $this->assertNotNull(field_info_field($this->field_name), 'Field was not deleted.'); // Delete the second instance. - $this->fieldUIDeleteField($bundle_path2, $this->field_name, $this->field_label, $type_name2); + $this->fieldUIDeleteField($bundle_path2, "node.$type_name2.$this->field_name", $this->field_label, $type_name2); // Reset the fields info. field_info_cache_clear(); @@ -358,9 +374,11 @@ function testHiddenFields() { 'bundle' => $this->type, 'entity_type' => 'node', 'label' => t('Hidden field'), - 'widget' => array('type' => 'test_field_widget'), ); field_create_instance($instance); + entity_get_form_display('node', $this->type, 'default') + ->setComponent($field_name) + ->save(); $this->assertTrue(field_read_instance('node', $field_name, $this->type), format_string('An instance of the field %field was created programmatically.', array('%field' => $field_name))); // Check that the newly added instance appears on the 'Manage Fields' @@ -412,12 +430,12 @@ function testDuplicateFieldName() { */ function testWidgetChange() { $url_fields = 'admin/structure/types/manage/article/fields'; - $url_tags_widget = $url_fields . '/field_tags/widget-type'; + $url_tags_widget = $url_fields . '/node.article.field_tags/widget-type'; // Check that the field_tags field currently uses the 'options_select' // widget. - $instance = field_info_instance('node', 'field_tags', 'article'); - $this->assertEqual($instance['widget']['type'], 'options_select'); + $entity_form_display = entity_get_form_display('node', 'article', 'default')->getComponent('field_tags'); + $this->assertEqual($entity_form_display['type'], 'options_select'); // Check that the "Manage fields" page shows the correct widget type. $this->drupalGet($url_fields); @@ -441,8 +459,8 @@ function testWidgetChange() { // Check that the field uses the newly set widget. field_cache_clear(); - $instance = field_info_instance('node', 'field_tags', 'article'); - $this->assertEqual($instance['widget']['type'], 'options_buttons'); + $widget_configuration = entity_get_form_display('node', 'article', 'default')->getComponent('field_tags'); + $this->assertEqual($widget_configuration['type'], 'options_buttons'); // Go to the 'Widget type' form and check that the correct widget is // selected. @@ -463,7 +481,7 @@ function testDeleteTaxonomyField() { $this->fieldUIAddNewField($bundle_path, $edit1); // Delete the field. - $this->fieldUIDeleteField($bundle_path, $this->field_name, $this->field_label, 'Tags'); + $this->fieldUIDeleteField($bundle_path, "taxonomy_term.tags.$this->field_name", $this->field_label, 'Tags'); // Reset the fields info. field_info_cache_clear(); diff --git a/core/modules/file/file.field.inc b/core/modules/file/file.field.inc index de03e50..59d068b 100644 --- a/core/modules/file/file.field.inc +++ b/core/modules/file/file.field.inc @@ -451,7 +451,6 @@ function file_field_widget_process($element, &$form_state, $form) { $field = field_widget_field($element, $form_state); $instance = field_widget_instance($element, $form_state); - $settings = $instance['widget']['settings']; $element['#theme'] = 'file_widget'; diff --git a/core/modules/file/lib/Drupal/file/Tests/FileFieldTestBase.php b/core/modules/file/lib/Drupal/file/Tests/FileFieldTestBase.php index 8cff731..ac2f428 100644 --- a/core/modules/file/lib/Drupal/file/Tests/FileFieldTestBase.php +++ b/core/modules/file/lib/Drupal/file/Tests/FileFieldTestBase.php @@ -102,14 +102,16 @@ function attachFileField($name, $entity_type, $bundle, $instance_settings = arra 'bundle' => $bundle, 'required' => !empty($instance_settings['required']), 'settings' => array(), - 'widget' => array( - 'type' => 'file_generic', - 'settings' => array(), - ), ); $instance['settings'] = array_merge($instance['settings'], $instance_settings); - $instance['widget']['settings'] = array_merge($instance['widget']['settings'], $widget_settings); field_create_instance($instance); + + entity_get_form_display($entity_type, $bundle, 'default') + ->setComponent($name, array( + 'type' => 'file_generic', + 'settings' => $widget_settings, + )) + ->save(); } /** @@ -118,9 +120,14 @@ function attachFileField($name, $entity_type, $bundle, $instance_settings = arra function updateFileField($name, $type_name, $instance_settings = array(), $widget_settings = array()) { $instance = field_info_instance('node', $name, $type_name); $instance['settings'] = array_merge($instance['settings'], $instance_settings); - $instance['widget']['settings'] = array_merge($instance['widget']['settings'], $widget_settings); field_update_instance($instance); + + entity_get_form_display($instance['entity_type'], $instance['bundle'], 'default') + ->setComponent($instance['field_name'], array( + 'settings' => $widget_settings, + )) + ->save(); } /** diff --git a/core/modules/file/lib/Drupal/file/Tests/FileFieldWidgetTest.php b/core/modules/file/lib/Drupal/file/Tests/FileFieldWidgetTest.php index 041e166..8268999 100644 --- a/core/modules/file/lib/Drupal/file/Tests/FileFieldWidgetTest.php +++ b/core/modules/file/lib/Drupal/file/Tests/FileFieldWidgetTest.php @@ -205,12 +205,13 @@ function testPrivateFileSetting() { $type_name = 'article'; $field_name = strtolower($this->randomName()); $this->createFileField($field_name, $type_name); + $instance = field_info_instance('node', $field_name, $type_name); $test_file = $this->getTestFile('text'); // Change the field setting to make its files private, and upload a file. $edit = array('field[settings][uri_scheme]' => 'private'); - $this->drupalPost("admin/structure/types/manage/$type_name/fields/$field_name/field-settings", $edit, t('Save field settings')); + $this->drupalPost("admin/structure/types/manage/$type_name/fields/$instance->id/field-settings", $edit, t('Save field settings')); $nid = $this->uploadNodeFile($test_file, $field_name, $type_name); $node = node_load($nid, TRUE); $node_file = file_load($node->{$field_name}[LANGUAGE_NOT_SPECIFIED][0]['fid']); @@ -222,12 +223,12 @@ function testPrivateFileSetting() { // Ensure we can't change 'uri_scheme' field settings while there are some // entities with uploaded files. - $this->drupalGet("admin/structure/types/manage/$type_name/fields/$field_name/field-settings"); + $this->drupalGet("admin/structure/types/manage/$type_name/fields/$instance->id/field-settings"); $this->assertFieldByXpath('//input[@id="edit-field-settings-uri-scheme-public" and @disabled="disabled"]', 'public', t('Upload destination setting disabled.')); // Delete node and confirm that setting could be changed. node_delete($nid); - $this->drupalGet("admin/structure/types/manage/$type_name/fields/$field_name/field-settings"); + $this->drupalGet("admin/structure/types/manage/$type_name/fields/$instance->id/field-settings"); $this->assertFieldByXpath('//input[@id="edit-field-settings-uri-scheme-public" and not(@disabled)]', 'public', t('Upload destination setting enabled.')); } diff --git a/core/modules/forum/forum.install b/core/modules/forum/forum.install index 1bc6915..8d15b06 100644 --- a/core/modules/forum/forum.install +++ b/core/modules/forum/forum.install @@ -84,12 +84,16 @@ function forum_enable() { 'label' => $vocabulary->name, 'bundle' => 'forum', 'required' => TRUE, - 'widget' => array( - 'type' => 'options_select', - ), ); field_create_instance($instance); + // Assign form display settings for the 'default' form mode. + entity_get_form_display('node', 'forum', 'default') + ->setComponent('taxonomy_forums', array( + 'type' => 'options_select', + )) + ->save(); + // Assign display settings for the 'default' and 'teaser' view modes. entity_get_display('node', 'forum', 'default') ->setComponent('taxonomy_forums', array( diff --git a/core/modules/hal/lib/Drupal/hal/Tests/NormalizerTestBase.php b/core/modules/hal/lib/Drupal/hal/Tests/NormalizerTestBase.php index b40bffa..2d73a24 100644 --- a/core/modules/hal/lib/Drupal/hal/Tests/NormalizerTestBase.php +++ b/core/modules/hal/lib/Drupal/hal/Tests/NormalizerTestBase.php @@ -30,7 +30,7 @@ * * @var array */ - public static $modules = array('entity_test', 'entity_reference', 'field', 'field_sql_storage', 'hal', 'language', 'rest', 'serialization', 'system', 'text', 'user'); + public static $modules = array('entity', 'entity_test', 'entity_reference', 'field', 'field_sql_storage', 'hal', 'language', 'rest', 'serialization', 'system', 'text', 'user'); /** * The mock serializer. diff --git a/core/modules/image/lib/Drupal/image/ImageStyleStorageController.php b/core/modules/image/lib/Drupal/image/ImageStyleStorageController.php index 4bbbbde..97766b5 100644 --- a/core/modules/image/lib/Drupal/image/ImageStyleStorageController.php +++ b/core/modules/image/lib/Drupal/image/ImageStyleStorageController.php @@ -76,7 +76,7 @@ protected function replaceImageStyle(ImageStyle $style) { $instances = field_read_instances(); // Loop through all fields searching for image fields. foreach ($instances as $instance) { - if ($instance['widget']['module'] == 'image') { + if ($instance->getField()->type == 'image') { $view_modes = entity_get_view_modes($instance['entity_type']); $view_modes = array('default') + array_keys($view_modes); foreach ($view_modes as $view_mode) { @@ -92,9 +92,12 @@ protected function replaceImageStyle(ImageStyle $style) { ->save(); } } - if ($instance['widget']['settings']['preview_image_style'] == $style->getOriginalID()) { - $instance['widget']['settings']['preview_image_style'] = $style->id(); - field_update_instance($instance); + $entity_form_display = entity_get_form_display($instance['entity_type'], $instance['bundle'], 'default'); + $widget_configuration = $entity_form_display->getComponent($instance['field_name']); + if ($widget_configuration['settings']['preview_image_style'] == $style->getOriginalID()) { + $widget_options['settings']['preview_image_style'] = $style->id(); + $entity_form_display->setComponent($instance['field_name'], $widget_options) + ->save(); } } } diff --git a/core/modules/image/lib/Drupal/image/Tests/ImageFieldDefaultImagesTest.php b/core/modules/image/lib/Drupal/image/Tests/ImageFieldDefaultImagesTest.php index a30b7ed..52d9c18 100644 --- a/core/modules/image/lib/Drupal/image/Tests/ImageFieldDefaultImagesTest.php +++ b/core/modules/image/lib/Drupal/image/Tests/ImageFieldDefaultImagesTest.php @@ -65,16 +65,20 @@ function testDefaultImages() { 'settings' => array( 'default_image' => array($default_images['instance2']->fid), ), - 'widget' => $instance['widget'], ); field_create_instance($instance2); - $instance2 = field_info_instance('node', $field_name, 'page'); + + $widget_settings = entity_get_form_display($instance['entity_type'], $instance['bundle'], 'default')->getComponent($instance['field_name']); + entity_get_form_display('node', 'page', 'default') + ->setComponent($field['field_name'], $widget_settings) + ->save(); + entity_get_display('node', 'page', 'default') ->setComponent($field['field_name']) ->save(); // Confirm the defaults are present on the article field settings form. - $this->drupalGet("admin/structure/types/manage/article/fields/$field_name/field-settings"); + $this->drupalGet("admin/structure/types/manage/article/fields/$instance->id/field-settings"); $this->assertFieldByXpath( '//input[@name="field[settings][default_image][fids]"]', $default_images['field']->fid, @@ -84,7 +88,7 @@ function testDefaultImages() { ) ); // Confirm the defaults are present on the article field edit form. - $this->drupalGet("admin/structure/types/manage/article/fields/$field_name"); + $this->drupalGet("admin/structure/types/manage/article/fields/$instance->id"); $this->assertFieldByXpath( '//input[@name="instance[settings][default_image][fids]"]', $default_images['instance']->fid, @@ -95,7 +99,7 @@ function testDefaultImages() { ); // Confirm the defaults are present on the page field settings form. - $this->drupalGet("admin/structure/types/manage/page/fields/$field_name/field-settings"); + $this->drupalGet("admin/structure/types/manage/page/fields/$instance->id/field-settings"); $this->assertFieldByXpath( '//input[@name="field[settings][default_image][fids]"]', $default_images['field']->fid, @@ -105,7 +109,7 @@ function testDefaultImages() { ) ); // Confirm the defaults are present on the page field edit form. - $this->drupalGet("admin/structure/types/manage/page/fields/$field_name"); + $this->drupalGet("admin/structure/types/manage/page/fields/$instance2->id"); $this->assertFieldByXpath( '//input[@name="instance[settings][default_image][fids]"]', $default_images['instance2']->fid, @@ -144,7 +148,7 @@ function testDefaultImages() { field_update_field($field); // Confirm that the new default is used on the article field settings form. - $this->drupalGet("admin/structure/types/manage/article/fields/$field_name/field-settings"); + $this->drupalGet("admin/structure/types/manage/article/fields/$instance->id/field-settings"); $this->assertFieldByXpath( '//input[@name="field[settings][default_image][fids]"]', $default_images['field_new']->fid, @@ -180,7 +184,7 @@ function testDefaultImages() { // Confirm the new field instance default is used on the article field // admin form. - $this->drupalGet("admin/structure/types/manage/article/fields/$field_name"); + $this->drupalGet("admin/structure/types/manage/article/fields/$instance->id"); $this->assertFieldByXpath( '//input[@name="instance[settings][default_image][fids]"]', $default_images['instance_new']->fid, @@ -218,7 +222,7 @@ function testDefaultImages() { field_update_instance($instance); // Confirm the article field instance default has been removed. - $this->drupalGet("admin/structure/types/manage/article/fields/$field_name"); + $this->drupalGet("admin/structure/types/manage/article/fields/$instance->id"); $this->assertFieldByXpath( '//input[@name="instance[settings][default_image][fids]"]', '', diff --git a/core/modules/image/lib/Drupal/image/Tests/ImageFieldDisplayTest.php b/core/modules/image/lib/Drupal/image/Tests/ImageFieldDisplayTest.php index ad92165..5342547 100644 --- a/core/modules/image/lib/Drupal/image/Tests/ImageFieldDisplayTest.php +++ b/core/modules/image/lib/Drupal/image/Tests/ImageFieldDisplayTest.php @@ -226,7 +226,7 @@ function testImageFieldDefaultImage() { $edit = array( 'files[field_settings_default_image]' => drupal_realpath($images[0]->uri), ); - $this->drupalPost("admin/structure/types/manage/article/fields/$field_name/field-settings", $edit, t('Save field settings')); + $this->drupalPost("admin/structure/types/manage/article/fields/node.article.$field_name/field-settings", $edit, t('Save field settings')); // Clear field info cache so the new default image is detected. field_info_cache_clear(); $field = field_info_field($field_name); @@ -254,7 +254,7 @@ function testImageFieldDefaultImage() { $edit = array( 'field[settings][default_image][fids]' => 0, ); - $this->drupalPost("admin/structure/types/manage/article/fields/$field_name/field-settings", $edit, t('Save field settings')); + $this->drupalPost("admin/structure/types/manage/article/fields/node.article.$field_name/field-settings", $edit, t('Save field settings')); // Clear field info cache so the new default image is detected. field_info_cache_clear(); $field = field_info_field($field_name); @@ -267,7 +267,7 @@ function testImageFieldDefaultImage() { $edit = array( 'files[field_settings_default_image]' => drupal_realpath($images[1]->uri), ); - $this->drupalPost('admin/structure/types/manage/article/fields/' . $private_field_name . '/field-settings', $edit, t('Save field settings')); + $this->drupalPost('admin/structure/types/manage/article/fields/node.article.' . $private_field_name . '/field-settings', $edit, t('Save field settings')); // Clear field info cache so the new default image is detected. field_info_cache_clear(); diff --git a/core/modules/image/lib/Drupal/image/Tests/ImageFieldTestBase.php b/core/modules/image/lib/Drupal/image/Tests/ImageFieldTestBase.php index 5a4e20e..508c9bc 100644 --- a/core/modules/image/lib/Drupal/image/Tests/ImageFieldTestBase.php +++ b/core/modules/image/lib/Drupal/image/Tests/ImageFieldTestBase.php @@ -85,16 +85,17 @@ function createImageField($name, $type_name, $field_settings = array(), $instanc 'required' => !empty($instance_settings['required']), 'description' => !empty($instance_settings['description']) ? $instance_settings['description'] : '', 'settings' => array(), - 'widget' => array( - 'type' => 'image_image', - 'settings' => array(), - ), ); $instance['settings'] = array_merge($instance['settings'], $instance_settings); - $instance['widget']['settings'] = array_merge($instance['widget']['settings'], $widget_settings); - $field_instance = field_create_instance($instance); + entity_get_form_display('node', $type_name, 'default') + ->setComponent($field['field_name'], array( + 'type' => 'image_image', + 'settings' => $widget_settings, + )) + ->save(); + entity_get_display('node', $type_name, 'default') ->setComponent($field['field_name']) ->save(); diff --git a/core/modules/image/lib/Drupal/image/Tests/ImageItemTest.php b/core/modules/image/lib/Drupal/image/Tests/ImageItemTest.php index 7f863cf..709073d 100644 --- a/core/modules/image/lib/Drupal/image/Tests/ImageItemTest.php +++ b/core/modules/image/lib/Drupal/image/Tests/ImageItemTest.php @@ -53,9 +53,6 @@ public function setUp() { 'entity_type' => 'entity_test', 'field_name' => 'image_test', 'bundle' => 'entity_test', - 'widget' => array( - 'type' => 'image_image', - ), ); field_create_instance($instance); file_unmanaged_copy(DRUPAL_ROOT . '/core/misc/druplicon.png', 'public://example.jpg'); diff --git a/core/modules/link/lib/Drupal/link/Tests/LinkFieldTest.php b/core/modules/link/lib/Drupal/link/Tests/LinkFieldTest.php index f28bcc2..0a6dc0b 100644 --- a/core/modules/link/lib/Drupal/link/Tests/LinkFieldTest.php +++ b/core/modules/link/lib/Drupal/link/Tests/LinkFieldTest.php @@ -56,14 +56,16 @@ function testURLValidation() { 'settings' => array( 'title' => DRUPAL_DISABLED, ), - 'widget' => array( + ); + field_create_instance($this->instance); + entity_get_form_display('test_entity', 'test_bundle', 'default') + ->setComponent($this->field['field_name'], array( 'type' => 'link_default', 'settings' => array( 'placeholder_url' => 'http://example.com', ), - ), - ); - field_create_instance($this->instance); + )) + ->save(); entity_get_display('test_entity', 'test_bundle', 'full') ->setComponent($this->field['field_name'], array( 'type' => 'link', @@ -125,15 +127,17 @@ function testLinkTitle() { 'settings' => array( 'title' => DRUPAL_OPTIONAL, ), - 'widget' => array( + ); + field_create_instance($this->instance); + entity_get_form_display('test_entity', 'test_bundle', 'default') + ->setComponent($this->field['field_name'], array( 'type' => 'link_default', 'settings' => array( 'placeholder_url' => 'http://example.com', 'placeholder_title' => 'Enter a title for this link', ), - ), - ); - field_create_instance($this->instance); + )) + ->save(); entity_get_display('test_entity', 'test_bundle', 'full') ->setComponent($this->field['field_name'], array( 'type' => 'link', @@ -238,15 +242,17 @@ function testLinkFormatter() { 'settings' => array( 'title' => DRUPAL_OPTIONAL, ), - 'widget' => array( - 'type' => 'link_default', - ), ); $display_options = array( 'type' => 'link', 'label' => 'hidden', ); field_create_instance($this->instance); + entity_get_form_display('test_entity', 'test_bundle', 'default') + ->setComponent($this->field['field_name'], array( + 'type' => 'link_default', + )) + ->save(); entity_get_display('test_entity', 'test_bundle', 'full') ->setComponent($this->field['field_name'], $display_options) ->save(); @@ -376,15 +382,17 @@ function testLinkSeparateFormatter() { 'settings' => array( 'title' => DRUPAL_OPTIONAL, ), - 'widget' => array( - 'type' => 'link_default', - ), ); $display_options = array( 'type' => 'link_separate', 'label' => 'hidden', ); field_create_instance($this->instance); + entity_get_form_display('test_entity', 'test_bundle', 'default') + ->setComponent($this->field['field_name'], array( + 'type' => 'link_default', + )) + ->save(); entity_get_display('test_entity', 'test_bundle', 'full') ->setComponent($this->field['field_name'], $display_options) ->save(); diff --git a/core/modules/link/lib/Drupal/link/Tests/LinkItemTest.php b/core/modules/link/lib/Drupal/link/Tests/LinkItemTest.php index e59e403..eb40cbc 100644 --- a/core/modules/link/lib/Drupal/link/Tests/LinkItemTest.php +++ b/core/modules/link/lib/Drupal/link/Tests/LinkItemTest.php @@ -44,9 +44,6 @@ public function setUp() { 'entity_type' => 'entity_test', 'field_name' => 'field_test', 'bundle' => 'entity_test', - 'widget' => array( - 'type' => 'link_default', - ), ); field_create_instance($this->instance); } diff --git a/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkStorageController.php b/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkStorageController.php index de04d97..dd4ffcc 100644 --- a/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkStorageController.php +++ b/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkStorageController.php @@ -81,7 +81,10 @@ protected function attachLoad(&$menu_links, $load_revision = FALSE) { if ($routes) { $route_objects = drupal_container()->get('router.route_provider')->getRoutesByNames($routes); foreach ($routes as $entity_id => $route) { - $menu_links[$entity_id]->setRouteObject($route_objects[$route]); + // Not all stored routes will be valid on load. + if (isset($route_objects[$route])) { + $menu_links[$entity_id]->setRouteObject($route_objects[$route]); + } } } diff --git a/core/modules/node/lib/Drupal/node/Plugin/Core/Entity/Node.php b/core/modules/node/lib/Drupal/node/Plugin/Core/Entity/Node.php index 856d2be..68befd4 100644 --- a/core/modules/node/lib/Drupal/node/Plugin/Core/Entity/Node.php +++ b/core/modules/node/lib/Drupal/node/Plugin/Core/Entity/Node.php @@ -44,6 +44,7 @@ * bundle_keys = { * "bundle" = "type" * }, + * route_base_path = "admin/structure/types/manage/{bundle}", * permission_granularity = "bundle" * ) */ diff --git a/core/modules/node/lib/Drupal/node/Plugin/views/wizard/Node.php b/core/modules/node/lib/Drupal/node/Plugin/views/wizard/Node.php index 4f868f7..644fbcf 100644 --- a/core/modules/node/lib/Drupal/node/Plugin/views/wizard/Node.php +++ b/core/modules/node/lib/Drupal/node/Plugin/views/wizard/Node.php @@ -278,9 +278,10 @@ protected function build_filters(&$form, &$form_state) { $tag_fields = array(); foreach ($bundles as $bundle) { foreach (field_info_instances($this->entity_type, $bundle) as $instance) { + $widget = entity_get_form_display($instance['entity_type'], $instance['bundle'], 'default')->getComponent($instance['field_name']); // We define "tag-like" taxonomy fields as ones that use the // "Autocomplete term widget (tagging)" widget. - if ($instance['widget']['type'] == 'taxonomy_autocomplete') { + if ($widget['type'] == 'taxonomy_autocomplete') { $tag_fields[] = $instance['field_name']; } } diff --git a/core/modules/node/lib/Drupal/node/Tests/MultiStepNodeFormBasicOptionsTest.php b/core/modules/node/lib/Drupal/node/Tests/MultiStepNodeFormBasicOptionsTest.php index 7ee1e85..465a492 100644 --- a/core/modules/node/lib/Drupal/node/Tests/MultiStepNodeFormBasicOptionsTest.php +++ b/core/modules/node/lib/Drupal/node/Tests/MultiStepNodeFormBasicOptionsTest.php @@ -54,16 +54,14 @@ function testMultiStepNodeFormBasicOptions() { 'settings' => array( 'text_processing' => TRUE, ), - 'widget' => array( - 'type' => 'text_textfield', - ), - 'display' => array( - 'full' => array( - 'type' => 'text_default', - ), - ), ); field_create_instance($this->instance); + entity_get_form_display('node', 'page', 'default') + ->setComponent($this->field_name, array( + 'type' => 'text_textfield', + )) + ->save(); + $langcode = LANGUAGE_NOT_SPECIFIED; $edit = array( diff --git a/core/modules/node/lib/Drupal/node/Tests/NodeAccessFieldTest.php b/core/modules/node/lib/Drupal/node/Tests/NodeAccessFieldTest.php index 0db0bda..9c9c52e 100644 --- a/core/modules/node/lib/Drupal/node/Tests/NodeAccessFieldTest.php +++ b/core/modules/node/lib/Drupal/node/Tests/NodeAccessFieldTest.php @@ -48,6 +48,9 @@ public function setUp() { entity_get_display('node', 'page', 'default') ->setComponent($this->field_name) ->save(); + entity_get_form_display('node', 'page', 'default') + ->setComponent($this->field_name) + ->save(); } /** @@ -75,7 +78,7 @@ function testNodeAccessAdministerField() { $default = 'Sometimes words have two meanings'; $edit["{$this->field_name}[$langcode][0][value]"] = $default; $this->drupalPost( - "admin/structure/types/manage/page/fields/{$this->field_name}", + "admin/structure/types/manage/page/fields/node.page.{$this->field_name}", $edit, t('Save settings') ); diff --git a/core/modules/node/lib/Drupal/node/Tests/NodeTypeTest.php b/core/modules/node/lib/Drupal/node/Tests/NodeTypeTest.php index 64fa105..6a5b5f6 100644 --- a/core/modules/node/lib/Drupal/node/Tests/NodeTypeTest.php +++ b/core/modules/node/lib/Drupal/node/Tests/NodeTypeTest.php @@ -121,7 +121,7 @@ function testNodeTypeEditing() { $this->assertRaw('Body', 'Body field was found.'); // Remove the body field. - $this->drupalPost('admin/structure/types/manage/bar/fields/body/delete', array(), t('Delete')); + $this->drupalPost('admin/structure/types/manage/bar/fields/node.bar.body/delete', array(), t('Delete')); // Resave the settings for this type. $this->drupalPost('admin/structure/types/manage/bar', array(), t('Save content type')); // Check that the body field doesn't exist. diff --git a/core/modules/node/lib/Drupal/node/Tests/PagePreviewTest.php b/core/modules/node/lib/Drupal/node/Tests/PagePreviewTest.php index 28b04cd..ebe6fc1 100644 --- a/core/modules/node/lib/Drupal/node/Tests/PagePreviewTest.php +++ b/core/modules/node/lib/Drupal/node/Tests/PagePreviewTest.php @@ -76,20 +76,26 @@ function setUp() { 'field_name' => $this->field_name, 'entity_type' => 'node', 'bundle' => 'page', - 'widget' => array( - 'type' => 'options_select', - ), - // Hide on full display but render on teaser. - 'display' => array( - 'default' => array( - 'type' => 'hidden', - ), - 'teaser' => array( - 'type' => 'taxonomy_term_reference_link', - ), - ), ); field_create_instance($this->instance); + + entity_get_form_display('node', 'page', 'default') + ->setComponent($this->field['field_name'], array( + 'type' => 'options_select', + )) + ->save(); + + // Hide on full display but render on teaser. + entity_get_display('node', 'page', 'default') + ->setComponent($this->field['field_name'], array( + 'type' => 'hidden', + )) + ->save(); + entity_get_display('node', 'page', 'teaser') + ->setComponent($this->field['field_name'], array( + 'type' => 'taxonomy_term_reference_link', + )) + ->save(); } /** diff --git a/core/modules/node/node.module b/core/modules/node/node.module index 8f9f17f..9c62cb5 100644 --- a/core/modules/node/node.module +++ b/core/modules/node/node.module @@ -219,9 +219,7 @@ function node_entity_bundle_info() { $bundles['node'][$type] = array( 'label' => $name, 'admin' => array( - 'path' => 'admin/structure/types/manage/%node_type', 'real path' => 'admin/structure/types/manage/' . $type, - 'bundle argument' => 4, ), ); } @@ -579,11 +577,17 @@ function node_add_body_field($type, $label = 'Body') { 'entity_type' => 'node', 'bundle' => $type->type, 'label' => $label, - 'widget' => array('type' => 'text_textarea_with_summary'), 'settings' => array('display_summary' => TRUE), ); $instance = field_create_instance($instance); + // Assign widget settings for the 'default' form mode. + entity_get_form_display('node', $type->type, 'default') + ->setComponent($field['field_name'], array( + 'type' => 'text_textarea_with_summary', + )) + ->save(); + // Assign display settings for the 'default' and 'teaser' view modes. entity_get_display('node', $type->type, 'default') ->setComponent($field['field_name'], array( diff --git a/core/modules/number/lib/Drupal/number/Tests/NumberFieldTest.php b/core/modules/number/lib/Drupal/number/Tests/NumberFieldTest.php index aa6c06e..d0b98ac 100644 --- a/core/modules/number/lib/Drupal/number/Tests/NumberFieldTest.php +++ b/core/modules/number/lib/Drupal/number/Tests/NumberFieldTest.php @@ -57,16 +57,21 @@ function testNumberDecimalField() { 'field_name' => $this->field['field_name'], 'entity_type' => 'test_entity', 'bundle' => 'test_bundle', - 'widget' => array( + ); + field_create_instance($this->instance); + + entity_get_form_display('test_entity', 'test_bundle', 'default') + ->setComponent($this->field['field_name'], array( 'type' => 'number', 'settings' => array( 'placeholder' => '0.00' ), - ), - ); - field_create_instance($this->instance); + )) + ->save(); entity_get_display('test_entity', 'test_bundle', 'default') - ->setComponent($this->field['field_name']) + ->setComponent($this->field['field_name'], array( + 'type' => 'number_decimal', + )) ->save(); // Display creation form. diff --git a/core/modules/number/lib/Drupal/number/Tests/NumberItemTest.php b/core/modules/number/lib/Drupal/number/Tests/NumberItemTest.php index a0fc778..fa7e0fa 100644 --- a/core/modules/number/lib/Drupal/number/Tests/NumberItemTest.php +++ b/core/modules/number/lib/Drupal/number/Tests/NumberItemTest.php @@ -45,9 +45,6 @@ public function setUp() { 'entity_type' => 'entity_test', 'field_name' => 'field_' . $type, 'bundle' => 'entity_test', - 'widget' => array( - 'type' => 'number', - ), ); field_create_instance($this->instance[$type]); } 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/options/lib/Drupal/options/Tests/OptionsDynamicValuesTest.php b/core/modules/options/lib/Drupal/options/Tests/OptionsDynamicValuesTest.php index 4065b7d..4e97dbe 100644 --- a/core/modules/options/lib/Drupal/options/Tests/OptionsDynamicValuesTest.php +++ b/core/modules/options/lib/Drupal/options/Tests/OptionsDynamicValuesTest.php @@ -40,11 +40,14 @@ function setUp() { 'entity_type' => 'test_entity', 'bundle' => 'test_bundle', 'required' => TRUE, - 'widget' => array( - 'type' => 'options_select', - ), ); $this->instance = field_create_instance($this->instance); + entity_get_form_display('test_entity', 'test_bundle', 'default') + ->setComponent($this->field_name, array( + 'type' => 'options_select', + )) + ->save(); + $this->test = array( 'id' => mt_rand(1, 10), // Make sure this does not equal the ID so that diff --git a/core/modules/options/lib/Drupal/options/Tests/OptionsFieldTest.php b/core/modules/options/lib/Drupal/options/Tests/OptionsFieldTest.php index 11ab663..02179d6 100644 --- a/core/modules/options/lib/Drupal/options/Tests/OptionsFieldTest.php +++ b/core/modules/options/lib/Drupal/options/Tests/OptionsFieldTest.php @@ -50,11 +50,13 @@ function setUp() { 'field_name' => $this->field_name, 'entity_type' => 'entity_test', 'bundle' => 'entity_test', - 'widget' => array( - 'type' => 'options_buttons', - ), ); $this->instance = field_create_instance($this->instance); + entity_get_form_display('entity_test', 'entity_test', 'default') + ->setComponent($this->field_name, array( + 'type' => 'options_buttons', + )) + ->save(); } /** @@ -114,11 +116,13 @@ function testUpdateAllowedValues() { 'field_name' => $this->field_name, 'entity_type' => 'entity_test', 'bundle' => 'entity_test', - 'widget' => array( - 'type' => 'options_buttons', - ), ); field_create_instance($this->instance); + entity_get_form_display('entity_test', 'entity_test', 'default') + ->setComponent($this->field_name, array( + 'type' => 'options_buttons', + )) + ->save(); $entity = entity_create('entity_test', array()); $form = entity_get_form($entity); $this->assertTrue(!empty($form[$this->field_name][$langcode][1]), 'Option 1 exists'); diff --git a/core/modules/options/lib/Drupal/options/Tests/OptionsFieldUITest.php b/core/modules/options/lib/Drupal/options/Tests/OptionsFieldUITest.php index 11f6035..12fe379 100644 --- a/core/modules/options/lib/Drupal/options/Tests/OptionsFieldUITest.php +++ b/core/modules/options/lib/Drupal/options/Tests/OptionsFieldUITest.php @@ -223,6 +223,10 @@ function testOptionsAllowedValuesBoolean() { ); $this->drupalPost($this->admin_path, $edit, t('Save field settings')); $this->assertRaw(t('Updated field %label field settings.', array('%label' => $this->field_name))); + + // Clear field cache. + field_info_cache_clear(); + // Test the allowed_values on the field settings form. $this->drupalGet($this->admin_path); $this->assertFieldByName('on', $on, t("The 'On' value is stored correctly.")); @@ -266,7 +270,9 @@ protected function createOptionsField($type) { ); field_create_instance($instance); - $this->admin_path = 'admin/structure/types/manage/' . $this->type . '/fields/' . $this->field_name . '/field-settings'; + entity_get_form_display('node', $this->type, 'default')->setComponent($this->field_name)->save(); + + $this->admin_path = 'admin/structure/types/manage/' . $this->type . '/fields/node.' . $this->type . '.' . $this->field_name . '/field-settings'; } /** diff --git a/core/modules/options/lib/Drupal/options/Tests/OptionsWidgetsTest.php b/core/modules/options/lib/Drupal/options/Tests/OptionsWidgetsTest.php index 78efa3e..cbb3c7f 100644 --- a/core/modules/options/lib/Drupal/options/Tests/OptionsWidgetsTest.php +++ b/core/modules/options/lib/Drupal/options/Tests/OptionsWidgetsTest.php @@ -81,11 +81,14 @@ function testRadioButtons() { 'field_name' => $this->card_1['field_name'], 'entity_type' => 'test_entity', 'bundle' => 'test_bundle', - 'widget' => array( - 'type' => 'options_buttons', - ), ); $instance = field_create_instance($instance); + entity_get_form_display('test_entity', 'test_bundle', 'default') + ->setComponent($this->card_1['field_name'], array( + 'type' => 'options_buttons', + )) + ->save(); + $langcode = LANGUAGE_NOT_SPECIFIED; // Create an entity. @@ -135,11 +138,14 @@ function testCheckBoxes() { 'field_name' => $this->card_2['field_name'], 'entity_type' => 'test_entity', 'bundle' => 'test_bundle', - 'widget' => array( - 'type' => 'options_buttons', - ), ); $instance = field_create_instance($instance); + entity_get_form_display('test_entity', 'test_bundle', 'default') + ->setComponent($this->card_2['field_name'], array( + 'type' => 'options_buttons', + )) + ->save(); + $langcode = LANGUAGE_NOT_SPECIFIED; // Create an entity. @@ -223,11 +229,14 @@ function testSelectListSingle() { 'entity_type' => 'test_entity', 'bundle' => 'test_bundle', 'required' => TRUE, - 'widget' => array( - 'type' => 'options_select', - ), ); $instance = field_create_instance($instance); + entity_get_form_display('test_entity', 'test_bundle', 'default') + ->setComponent($this->card_1['field_name'], array( + 'type' => 'options_select', + )) + ->save(); + $langcode = LANGUAGE_NOT_SPECIFIED; // Create an entity. @@ -319,11 +328,14 @@ function testSelectListMultiple() { 'field_name' => $this->card_2['field_name'], 'entity_type' => 'test_entity', 'bundle' => 'test_bundle', - 'widget' => array( - 'type' => 'options_select', - ), ); $instance = field_create_instance($instance); + entity_get_form_display('test_entity', 'test_bundle', 'default') + ->setComponent($this->card_2['field_name'], array( + 'type' => 'options_select', + )) + ->save(); + $langcode = LANGUAGE_NOT_SPECIFIED; // Create an entity. @@ -436,11 +448,14 @@ function testOnOffCheckbox() { 'field_name' => $this->bool['field_name'], 'entity_type' => 'test_entity', 'bundle' => 'test_bundle', - 'widget' => array( - 'type' => 'options_onoff', - ), ); $instance = field_create_instance($instance); + entity_get_form_display('test_entity', 'test_bundle', 'default') + ->setComponent($this->bool['field_name'], array( + 'type' => 'options_onoff', + )) + ->save(); + $langcode = LANGUAGE_NOT_SPECIFIED; // Create an entity. @@ -487,15 +502,17 @@ function testOnOffCheckbox() { 'field_name' => $this->bool['field_name'], 'entity_type' => 'node', 'bundle' => 'page', - 'widget' => array( - 'type' => 'options_onoff', - 'module' => 'options', - ), ); field_create_instance($instance); + entity_get_form_display('node', 'page', 'default') + ->setComponent($this->bool['field_name'], array( + 'type' => 'options_onoff', + )) + ->save(); + // Go to the edit page and check if the default settings works as expected - $fieldEditUrl = 'admin/structure/types/manage/page/fields/bool'; + $fieldEditUrl = 'admin/structure/types/manage/page/fields/node.page.bool'; $this->drupalGet($fieldEditUrl); $this->assertText( diff --git a/core/modules/rdf/lib/Drupal/rdf/Tests/RdfaMarkupTest.php b/core/modules/rdf/lib/Drupal/rdf/Tests/RdfaMarkupTest.php index 6f99dae..5d917a4 100644 --- a/core/modules/rdf/lib/Drupal/rdf/Tests/RdfaMarkupTest.php +++ b/core/modules/rdf/lib/Drupal/rdf/Tests/RdfaMarkupTest.php @@ -117,6 +117,12 @@ function testAttributesInMarkupFile() { 'bundle' => $bundle_name, ); field_create_instance($instance); + + entity_get_form_display('node', $bundle_name, 'default') + ->setComponent($field_name, array( + 'type' => 'file_generic', + )) + ->save(); entity_get_display('node', $bundle_name, 'teaser') ->setComponent($field_name, array( 'type' => 'file_default', diff --git a/core/modules/simpletest/lib/Drupal/simpletest/Tests/DrupalUnitTestBaseTest.php b/core/modules/simpletest/lib/Drupal/simpletest/Tests/DrupalUnitTestBaseTest.php index 2379193..242bcd6 100644 --- a/core/modules/simpletest/lib/Drupal/simpletest/Tests/DrupalUnitTestBaseTest.php +++ b/core/modules/simpletest/lib/Drupal/simpletest/Tests/DrupalUnitTestBaseTest.php @@ -229,7 +229,7 @@ function testEnableModulesFixedList() { $display = entity_create('entity_display', array( 'targetEntityType' => 'entity_test', 'bundle' => 'entity_test', - 'viewMode' => 'default', + 'mode' => 'default', )); $field = array( 'field_name' => 'test_field', diff --git a/core/modules/system/lib/Drupal/system/Tests/Ajax/MultiFormTest.php b/core/modules/system/lib/Drupal/system/Tests/Ajax/MultiFormTest.php index c9e7b6d..d3ba0b7 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Ajax/MultiFormTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Ajax/MultiFormTest.php @@ -46,6 +46,9 @@ function setUp() { 'bundle' => 'page', ); field_create_instance($instance); + entity_get_form_display('node', 'page', 'default') + ->setComponent($field_name, array('type' => 'text_default')) + ->save(); // Login a user who can create 'page' nodes. $this->web_user = $this->drupalCreateUser(array('create page content')); 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..78ce17d 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,17 @@ function testFormCRUD() { } /** + * Tests hook_entity_form_display_alter(). + * + * @see entity_test_entity_form_display_alter() + */ + function testEntityFormDisplayAlter() { + $this->drupalGet('entity_test/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/lib/Drupal/system/Tests/Entity/EntityUnitTestBase.php b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityUnitTestBase.php index 41918d3..4da3b21 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityUnitTestBase.php +++ b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityUnitTestBase.php @@ -19,7 +19,7 @@ * * @var array */ - public static $modules = array('user', 'system', 'field', 'text', 'field_sql_storage', 'entity_test'); + public static $modules = array('entity', 'user', 'system', 'field', 'text', 'field_sql_storage', 'entity_test'); public function setUp() { parent::setUp(); diff --git a/core/modules/system/lib/Drupal/system/Tests/Entity/FieldAccessTest.php b/core/modules/system/lib/Drupal/system/Tests/Entity/FieldAccessTest.php index a460b6f..b00bfea 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Entity/FieldAccessTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Entity/FieldAccessTest.php @@ -19,7 +19,7 @@ class FieldAccessTest extends DrupalUnitTestBase { * * @var array */ - public static $modules = array('entity_test', 'field', 'field_sql_storage', 'system', 'text', 'user'); + public static $modules = array('entity', 'entity_test', 'field', 'field_sql_storage', 'system', 'text', 'user'); /** * Holds the currently active global user ID that initiated the test run. diff --git a/core/modules/system/lib/Drupal/system/Tests/Form/ArbitraryRebuildTest.php b/core/modules/system/lib/Drupal/system/Tests/Form/ArbitraryRebuildTest.php index 1604063..f049ac8 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Form/ArbitraryRebuildTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Form/ArbitraryRebuildTest.php @@ -42,16 +42,21 @@ function setUp() { field_create_field($field); $instance = array( - 'entity_type' => 'node', + 'entity_type' => 'user', 'field_name' => 'test_multiple', - 'bundle' => 'page', + 'bundle' => 'user', 'label' => 'Test a multiple valued field', - 'widget' => array( - 'type' => 'text_textfield', - 'weight' => 0, + 'settings' => array( + 'user_register_form' => TRUE, ), ); field_create_instance($instance); + entity_get_form_display('user', 'user', 'default') + ->setComponent('test_multiple', array( + 'type' => 'text_textfield', + 'weight' => 0, + )) + ->save(); } /** diff --git a/core/modules/system/lib/Drupal/system/Tests/Form/RebuildTest.php b/core/modules/system/lib/Drupal/system/Tests/Form/RebuildTest.php index 3c0c0c5..8e9f649 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Form/RebuildTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Form/RebuildTest.php @@ -83,6 +83,9 @@ function testPreserveFormActionAfterAJAX() { 'bundle' => 'page', ); field_create_instance($instance); + entity_get_form_display('node', 'page', 'default') + ->setComponent($field_name, array('type' => 'text_test')) + ->save(); // Log in a user who can create 'page' nodes. $this->web_user = $this->drupalCreateUser(array('create page content')); diff --git a/core/modules/system/lib/Drupal/system/Tests/Menu/BreadcrumbTest.php b/core/modules/system/lib/Drupal/system/Tests/Menu/BreadcrumbTest.php index 6ebcfda..d583098 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Menu/BreadcrumbTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Menu/BreadcrumbTest.php @@ -146,11 +146,11 @@ function testBreadCrumbs() { $trail += array( "admin/structure/types/manage/$type/fields" => t('Manage fields'), ); - $this->assertBreadcrumb("admin/structure/types/manage/$type/fields/body", $trail); + $this->assertBreadcrumb("admin/structure/types/manage/$type/fields/node.$type.body", $trail); $trail += array( - "admin/structure/types/manage/$type/fields/body" => t('Body'), + "admin/structure/types/manage/$type/fields/node.$type.body" => t('Body'), ); - $this->assertBreadcrumb("admin/structure/types/manage/$type/fields/body/widget-type", $trail); + $this->assertBreadcrumb("admin/structure/types/manage/$type/fields/node.$type.body/widget-type", $trail); // Verify Filter text format administration breadcrumbs. $filter_formats = filter_formats(); diff --git a/core/modules/system/lib/Drupal/system/Tests/Upgrade/FieldUpgradePathTest.php b/core/modules/system/lib/Drupal/system/Tests/Upgrade/FieldUpgradePathTest.php index 0936aa5..621f114 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Upgrade/FieldUpgradePathTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Upgrade/FieldUpgradePathTest.php @@ -88,6 +88,45 @@ public function testEntityDisplayUpgrade() { } /** + * Tests upgrade of entity form displays. + */ + public function testEntityFormDisplayUpgrade() { + $this->assertTrue($this->performUpgrade(), 'The upgrade was completed successfully.'); + + // Check that the configuration entries were created. + $form_display = config('entity.form_display.node.article.default')->get(); + $this->assertTrue(!empty($form_display)); + + // Check that manifest entries for the 'article' node type were correctly + // created. + $manifest = config('manifest.entity.form_display'); + $data = $manifest->get(); + $this->assertEqual($data['node.article.default'], array('name' => 'entity.form_display.node.article.default')); + + // Check that the 'body' field is configured as expected. + $expected = array( + 'type' => 'text_textarea_with_summary', + 'weight' => -4, + 'settings' => array( + 'rows' => '20', + 'summary_rows' => '5', + ), + ); + $this->assertEqual($form_display['content']['body'], $expected); + + // Check that the display key in the instance data was removed. + $body_instance = field_info_instance('node', 'body', 'article'); + $this->assertTrue(!isset($body_instance['widget'])); + + // Check that the 'title' extra field is configured as expected. + $expected = array( + 'weight' => -5, + 'visible' => 1, + ); + $this->assertEqual($form_display['content']['title'], $expected); + } + + /** * Tests migration of field and instance definitions to config. */ function testFieldUpgradeToConfig() { @@ -150,15 +189,6 @@ function testFieldUpgradeToConfig() { 'text_processing' => 1, 'user_register_form' => FALSE, ), - 'widget' => array( - 'type' => 'text_textarea_with_summary', - 'module' => 'text', - 'settings' => array( - 'rows' => 20, - 'summary_rows' => 5, - ), - 'weight' => -4, - ), 'status' => 1, 'langcode' => 'und', )); diff --git a/core/modules/system/tests/modules/entity_test/entity_test.install b/core/modules/system/tests/modules/entity_test/entity_test.install index 3465e8c..f7b8726 100644 --- a/core/modules/system/tests/modules/entity_test/entity_test.install +++ b/core/modules/system/tests/modules/entity_test/entity_test.install @@ -30,12 +30,12 @@ function entity_test_install() { 'field_name' => 'field_test_text', 'bundle' => $entity_type, 'label' => 'Test text-field', - 'widget' => array( - 'type' => 'text_textfield', - 'weight' => 0, - ), ); field_create_instance($instance); + + entity_get_form_display($entity_type, $entity_type, 'default') + ->setComponent('field_test_text', array('type' => 'text_text')) + ->save(); } } 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 673ab67..2836d17 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. @@ -379,3 +380,16 @@ 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) { + // Make the field_test_text field 42 characters for entity_test_mul. + if ($context['entity_type'] == 'entity_test') { + if ($component_options = $form_display->getComponent('field_test_text')) { + $component_options['settings']['size'] = 42; + $form_display->setComponent('field_test_text', $component_options); + } + } +} diff --git a/core/modules/system/tests/upgrade/drupal-7.field.database.php b/core/modules/system/tests/upgrade/drupal-7.field.database.php index 9434c7c..baa5027 100644 --- a/core/modules/system/tests/upgrade/drupal-7.field.database.php +++ b/core/modules/system/tests/upgrade/drupal-7.field.database.php @@ -28,7 +28,12 @@ ), ), 'extra_fields' => array( - 'form' => array(), + 'form' => array( + 'title' => array( + 'weight' => -5, + 'visible' => 1, + ), + ), 'display' => array( 'language' => array( 'default' => array( diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/Core/Entity/Term.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/Core/Entity/Term.php index db9e033..2daaebb 100644 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/Core/Entity/Term.php +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/Core/Entity/Term.php @@ -43,6 +43,7 @@ * "bundle" = "vid" * }, * menu_base_path = "taxonomy/term/%taxonomy_term", + * route_base_path = "admin/structure/taxonomy/{bundle}", * permission_granularity = "bundle" * ) */ diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/RssTest.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/RssTest.php index ca775e9..d4be486 100644 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/RssTest.php +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/RssTest.php @@ -53,11 +53,13 @@ function setUp() { 'field_name' => 'taxonomy_' . $this->vocabulary->id(), 'bundle' => 'article', 'entity_type' => 'node', - 'widget' => array( - 'type' => 'options_select', - ), ); field_create_instance($this->instance); + entity_get_form_display('node', 'article', 'default') + ->setComponent($field['field_name'], array( + 'type' => 'options_select', + )) + ->save(); entity_get_display('node', 'article', 'default') ->setComponent('taxonomy_' . $this->vocabulary->id(), array( 'type' => 'taxonomy_term_reference_link', diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TaxonomyTermReferenceItemTest.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TaxonomyTermReferenceItemTest.php index abb5893..77b9b1c 100644 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TaxonomyTermReferenceItemTest.php +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TaxonomyTermReferenceItemTest.php @@ -60,9 +60,6 @@ public function setUp() { 'entity_type' => 'entity_test', 'field_name' => 'field_test_taxonomy', 'bundle' => 'entity_test', - 'widget' => array( - 'type' => 'options_select', - ), ); field_create_instance($instance); $this->term = entity_create('taxonomy_term', array( diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermFieldMultipleVocabularyTest.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermFieldMultipleVocabularyTest.php index 4f71f53..d6a23c5 100644 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermFieldMultipleVocabularyTest.php +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermFieldMultipleVocabularyTest.php @@ -63,11 +63,13 @@ function setUp() { 'field_name' => $this->field_name, 'entity_type' => 'test_entity', 'bundle' => 'test_bundle', - 'widget' => array( - 'type' => 'options_select', - ), ); field_create_instance($this->instance); + entity_get_form_display('test_entity', 'test_bundle', 'default') + ->setComponent($this->field_name, array( + 'type' => 'options_select', + )) + ->save(); entity_get_display('test_entity', 'test_bundle', 'full') ->setComponent($this->field_name, array( 'type' => 'taxonomy_term_reference_link', diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermFieldTest.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermFieldTest.php index 363d326..70efba3 100644 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermFieldTest.php +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermFieldTest.php @@ -58,11 +58,13 @@ function setUp() { 'field_name' => $this->field_name, 'entity_type' => 'test_entity', 'bundle' => 'test_bundle', - 'widget' => array( - 'type' => 'options_select', - ), ); field_create_instance($this->instance); + entity_get_form_display('test_entity', 'test_bundle', 'default') + ->setComponent($this->field_name, array( + 'type' => 'options_select', + )) + ->save(); entity_get_display('test_entity', 'test_bundle', 'full') ->setComponent($this->field_name, array( 'type' => 'taxonomy_term_reference_link', diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermIndexTest.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermIndexTest.php index 237f4b4..ab19453 100644 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermIndexTest.php +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermIndexTest.php @@ -49,11 +49,13 @@ function setUp() { 'field_name' => $this->field_name_1, 'bundle' => 'article', 'entity_type' => 'node', - 'widget' => array( - 'type' => 'options_select', - ), ); field_create_instance($this->instance_1); + entity_get_form_display('node', 'article', 'default') + ->setComponent($this->field_name_1, array( + 'type' => 'options_select', + )) + ->save(); entity_get_display('node', 'article', 'default') ->setComponent($this->field_name_1, array( 'type' => 'taxonomy_term_reference_link', @@ -79,11 +81,13 @@ function setUp() { 'field_name' => $this->field_name_2, 'bundle' => 'article', 'entity_type' => 'node', - 'widget' => array( - 'type' => 'options_select', - ), ); field_create_instance($this->instance_2); + entity_get_form_display('node', 'article', 'default') + ->setComponent($this->field_name_2, array( + 'type' => 'options_select', + )) + ->save(); entity_get_display('node', 'article', 'default') ->setComponent($this->field_name_2, array( 'type' => 'taxonomy_term_reference_link', diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermTest.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermTest.php index 705ff60..a545f72 100644 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermTest.php +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermTest.php @@ -45,11 +45,13 @@ function setUp() { 'field_name' => 'taxonomy_' . $this->vocabulary->id(), 'bundle' => 'article', 'entity_type' => 'node', - 'widget' => array( - 'type' => 'options_select', - ), ); field_create_instance($this->instance); + entity_get_form_display('node', 'article', 'default') + ->setComponent('taxonomy_' . $this->vocabulary->id(), array( + 'type' => 'options_select', + )) + ->save(); entity_get_display('node', 'article', 'default') ->setComponent($this->instance['field_name'], array( 'type' => 'taxonomy_term_reference_link', @@ -142,13 +144,14 @@ function testTaxonomyNode() { function testNodeTermCreationAndDeletion() { // Enable tags in the vocabulary. $instance = $this->instance; - $instance['widget'] = array( - 'type' => 'taxonomy_autocomplete', - 'settings' => array( - 'placeholder' => 'Start typing here.', - ), - ); - field_update_instance($instance); + entity_get_form_display($instance['entity_type'], $instance['bundle'], 'default') + ->setComponent($instance['field_name'], array( + 'type' => 'taxonomy_autocomplete', + 'settings' => array( + 'placeholder' => 'Start typing here.', + ), + )) + ->save(); $terms = array( 'term1' => $this->randomName(), 'term2' => $this->randomName(), @@ -506,8 +509,11 @@ function testTaxonomyGetTermByName() { function testReSavingTags() { // Enable tags in the vocabulary. $instance = $this->instance; - $instance['widget'] = array('type' => 'taxonomy_autocomplete'); - field_update_instance($instance); + entity_get_form_display($instance['entity_type'], $instance['bundle'], 'default') + ->setComponent($instance['field_name'], array( + 'type' => 'taxonomy_autocomplete', + )) + ->save(); // Create a term and a node using it. $term = $this->createTerm($this->vocabulary); diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TokenReplaceTest.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TokenReplaceTest.php index 0a45dd2..2d3657e 100644 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TokenReplaceTest.php +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TokenReplaceTest.php @@ -46,11 +46,13 @@ function setUp() { 'field_name' => 'taxonomy_' . $this->vocabulary->id(), 'bundle' => 'article', 'entity_type' => 'node', - 'widget' => array( - 'type' => 'options_select', - ), ); field_create_instance($this->instance); + entity_get_form_display('node', 'article', 'default') + ->setComponent('taxonomy_' . $this->vocabulary->id(), array( + 'type' => 'options_select', + )) + ->save(); entity_get_display('node', 'article', 'default') ->setComponent('taxonomy_' . $this->vocabulary->id(), array( 'type' => 'taxonomy_term_reference_link', diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/Views/TaxonomyTestBase.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/Views/TaxonomyTestBase.php index 6de1b17..e71cf97 100644 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/Views/TaxonomyTestBase.php +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/Views/TaxonomyTestBase.php @@ -100,13 +100,16 @@ protected function mockStandardInstall() { 'entity_type' => 'node', 'label' => 'Tags', 'bundle' => 'article', - 'widget' => array( - 'type' => 'taxonomy_autocomplete', - 'weight' => -4, - ), ); field_create_instance($instance); + entity_get_form_display('node', 'article', 'default') + ->setComponent($instance['field_name'], array( + 'type' => 'taxonomy_autocomplete', + 'weight' => -4, + )) + ->save(); + entity_get_display('node', 'article', 'default') ->setComponent($instance['field_name'], array( 'type' => 'taxonomy_term_reference_link', diff --git a/core/modules/taxonomy/taxonomy.module b/core/modules/taxonomy/taxonomy.module index 2c50edb..e10e9ea 100644 --- a/core/modules/taxonomy/taxonomy.module +++ b/core/modules/taxonomy/taxonomy.module @@ -128,9 +128,7 @@ function taxonomy_entity_bundle_info() { $bundles['taxonomy_term'][$id] = array( 'label' => $config->get('name'), 'admin' => array( - 'path' => 'admin/structure/taxonomy/%taxonomy_vocabulary', 'real path' => 'admin/structure/taxonomy/' . $id, - 'bundle argument' => 3, ), ); } diff --git a/core/modules/telephone/lib/Drupal/telephone/Tests/TelephoneFieldTest.php b/core/modules/telephone/lib/Drupal/telephone/Tests/TelephoneFieldTest.php index 1bec98f..0d5aa47 100644 --- a/core/modules/telephone/lib/Drupal/telephone/Tests/TelephoneFieldTest.php +++ b/core/modules/telephone/lib/Drupal/telephone/Tests/TelephoneFieldTest.php @@ -64,14 +64,17 @@ function testTelephoneField() { 'label' => 'Telephone Number', 'entity_type' => 'node', 'bundle' => 'article', - 'widget' => array( + ); + field_create_instance($instance); + + entity_get_form_display('node', 'article', 'default') + ->setComponent('field_telephone', array( 'type' => 'telephone_default', 'settings' => array( 'placeholder' => '123-456-7890', ), - ), - ); - field_create_instance($instance); + )) + ->save(); entity_get_display('node', 'article', 'default') ->setComponent('field_telephone', array( diff --git a/core/modules/telephone/lib/Drupal/telephone/Tests/TelephoneItemTest.php b/core/modules/telephone/lib/Drupal/telephone/Tests/TelephoneItemTest.php index 35012b3..d809161 100644 --- a/core/modules/telephone/lib/Drupal/telephone/Tests/TelephoneItemTest.php +++ b/core/modules/telephone/lib/Drupal/telephone/Tests/TelephoneItemTest.php @@ -44,9 +44,6 @@ public function setUp() { 'entity_type' => 'entity_test', 'field_name' => 'field_test', 'bundle' => 'entity_test', - 'widget' => array( - 'type' => 'telephone_default', - ), ); field_create_instance($this->instance); } diff --git a/core/modules/text/lib/Drupal/text/Tests/Formatter/TextPlainUnitTest.php b/core/modules/text/lib/Drupal/text/Tests/Formatter/TextPlainUnitTest.php index 7126384..3ec2d22 100644 --- a/core/modules/text/lib/Drupal/text/Tests/Formatter/TextPlainUnitTest.php +++ b/core/modules/text/lib/Drupal/text/Tests/Formatter/TextPlainUnitTest.php @@ -61,9 +61,6 @@ function setUp() { 'text_processing' => FALSE, ); - $this->widget_type = 'text_textarea'; - $this->widget_settings = array(); - $this->formatter_type = 'text_plain'; $this->formatter_settings = array(); @@ -80,10 +77,6 @@ function setUp() { 'field_name' => $this->field_name, 'label' => $this->randomName(), 'settings' => $this->instance_settings, - 'widget' => array( - 'type' => $this->widget_type, - 'settings' => $this->widget_settings, - ), ); $this->instance = field_create_instance($this->instance); diff --git a/core/modules/text/lib/Drupal/text/Tests/TextFieldTest.php b/core/modules/text/lib/Drupal/text/Tests/TextFieldTest.php index f8c585b..e12553f 100644 --- a/core/modules/text/lib/Drupal/text/Tests/TextFieldTest.php +++ b/core/modules/text/lib/Drupal/text/Tests/TextFieldTest.php @@ -62,14 +62,8 @@ function testTextFieldValidation() { 'field_name' => $this->field['field_name'], 'entity_type' => 'test_entity', 'bundle' => 'test_bundle', - 'widget' => array( - 'type' => 'text_textfield', - ), ); field_create_instance($this->instance); - entity_get_display('test_entity', 'test_bundle', 'default') - ->setComponent($this->field['field_name']) - ->save(); // Test valid and invalid values with field_attach_validate(). $entity = field_test_create_entity(); @@ -111,14 +105,16 @@ function _testTextfieldWidgets($field_type, $widget_type) { 'settings' => array( 'text_processing' => TRUE, ), - 'widget' => array( + ); + field_create_instance($this->instance); + entity_get_form_display('test_entity', 'test_bundle', 'default') + ->setComponent($this->field_name, array( 'type' => $widget_type, 'settings' => array( 'placeholder' => 'A placeholder on ' . $widget_type, ), - ), - ); - field_create_instance($this->instance); + )) + ->save(); entity_get_display('test_entity', 'test_bundle', 'full') ->setComponent($this->field_name) ->save(); @@ -174,11 +170,13 @@ function _testTextfieldWidgetsFormatted($field_type, $widget_type) { 'settings' => array( 'text_processing' => TRUE, ), - 'widget' => array( - 'type' => $widget_type, - ), ); field_create_instance($this->instance); + entity_get_form_display('test_entity', 'test_bundle', 'default') + ->setComponent($this->field_name, array( + 'type' => $widget_type, + )) + ->save(); entity_get_display('test_entity', 'test_bundle', 'full') ->setComponent($this->field_name) ->save(); diff --git a/core/modules/text/lib/Drupal/text/Tests/TextTranslationTest.php b/core/modules/text/lib/Drupal/text/Tests/TextTranslationTest.php index 9aff558..b8b5656 100644 --- a/core/modules/text/lib/Drupal/text/Tests/TextTranslationTest.php +++ b/core/modules/text/lib/Drupal/text/Tests/TextTranslationTest.php @@ -63,7 +63,7 @@ function setUp() { function testTextField() { // Disable text processing for body. $edit = array('instance[settings][text_processing]' => 0); - $this->drupalPost('admin/structure/types/manage/article/fields/body', $edit, t('Save settings')); + $this->drupalPost('admin/structure/types/manage/article/fields/node.article.body', $edit, t('Save settings')); // Login as translator. $this->drupalLogin($this->translator); @@ -92,7 +92,7 @@ function testTextField() { function testTextFieldFormatted() { // Make node body multiple. $edit = array('field[container][cardinality]' => -1); - $this->drupalPost('admin/structure/types/manage/article/fields/body/field-settings', $edit, t('Save field settings')); + $this->drupalPost('admin/structure/types/manage/article/fields/node.article.body/field-settings', $edit, t('Save field settings')); $this->drupalGet('node/add/article'); $this->assertFieldByXPath("//input[@name='body_add_more']", t('Add another item'), 'Body field cardinality set to multiple.'); diff --git a/core/modules/translation_entity/lib/Drupal/translation_entity/Tests/EntityTranslationSyncImageTest.php b/core/modules/translation_entity/lib/Drupal/translation_entity/Tests/EntityTranslationSyncImageTest.php index 61f93cf..aa9c626 100644 --- a/core/modules/translation_entity/lib/Drupal/translation_entity/Tests/EntityTranslationSyncImageTest.php +++ b/core/modules/translation_entity/lib/Drupal/translation_entity/Tests/EntityTranslationSyncImageTest.php @@ -69,10 +69,6 @@ protected function setupTestFields() { 'field_name' => $this->fieldName, 'bundle' => $this->entityType, 'label' => 'Test translatable image field', - 'widget' => array( - 'type' => 'image_image', - 'weight' => 0, - ), 'settings' => array( 'translation_sync' => array( 'file' => FALSE, diff --git a/core/modules/translation_entity/lib/Drupal/translation_entity/Tests/EntityTranslationTestBase.php b/core/modules/translation_entity/lib/Drupal/translation_entity/Tests/EntityTranslationTestBase.php index 13e1f59..870321f 100644 --- a/core/modules/translation_entity/lib/Drupal/translation_entity/Tests/EntityTranslationTestBase.php +++ b/core/modules/translation_entity/lib/Drupal/translation_entity/Tests/EntityTranslationTestBase.php @@ -170,12 +170,14 @@ protected function setupTestFields() { 'field_name' => $this->fieldName, 'bundle' => $this->bundle, 'label' => 'Test translatable text-field', - 'widget' => array( - 'type' => 'text_textfield', - 'weight' => 0, - ), ); field_create_instance($instance); + entity_get_form_display($this->entityType, $this->bundle, 'default') + ->setComponent($this->fieldName, array( + 'type' => 'text_textfield', + 'weight' => 0, + )) + ->save(); } /** diff --git a/core/modules/user/lib/Drupal/user/Plugin/Core/Entity/User.php b/core/modules/user/lib/Drupal/user/Plugin/Core/Entity/User.php index 829babc..c609450 100644 --- a/core/modules/user/lib/Drupal/user/Plugin/Core/Entity/User.php +++ b/core/modules/user/lib/Drupal/user/Plugin/Core/Entity/User.php @@ -31,6 +31,7 @@ * default_operation = "profile", * base_table = "users", * uri_callback = "user_uri", + * route_base_path = "admin/config/people/accounts", * label_callback = "user_label", * fieldable = TRUE, * translatable = TRUE, diff --git a/core/modules/user/lib/Drupal/user/Tests/UserRegistrationTest.php b/core/modules/user/lib/Drupal/user/Tests/UserRegistrationTest.php index 38ca376..db649b0 100644 --- a/core/modules/user/lib/Drupal/user/Tests/UserRegistrationTest.php +++ b/core/modules/user/lib/Drupal/user/Tests/UserRegistrationTest.php @@ -209,6 +209,9 @@ function testRegistrationWithUserFields() { 'settings' => array('user_register_form' => FALSE), ); field_create_instance($instance); + entity_get_form_display('user', 'user', 'default') + ->setComponent('test_user_field', array('type' => 'test_field_widget')) + ->save(); // Check that the field does not appear on the registration form. $this->drupalGet('user/register'); diff --git a/core/modules/user/user.install b/core/modules/user/user.install index dca417c..4f22958 100644 --- a/core/modules/user/user.install +++ b/core/modules/user/user.install @@ -335,17 +335,20 @@ function user_install_picture_field() { 'min_resolution' => '', 'default_image' => 0, ), - 'widget' => array( - 'module' => 'image', + ); + field_create_instance($instance); + + // Assign form display settings for the 'default' view mode. + entity_get_form_display('user', 'user', 'default') + ->setComponent('user_picture', array( 'type' => 'image_image', 'settings' => array( 'progress_indicator' => 'throbber', 'preview_image_style' => 'thumbnail', ), 'weight' => -1, - ), - ); - field_create_instance($instance); + )) + ->save(); // Assign display settings for the 'default' and 'compact' view modes. entity_get_display('user', 'user', 'default') @@ -731,29 +734,32 @@ function user_update_8011() { 'min_resolution' => '', 'default_image' => !empty($default_image_fid) ? $default_image_fid : 0, ), - 'widget' => array( - 'module' => 'image', - 'type' => 'image_image', + ); + _update_7000_field_create_instance($field, $instance); + + module_load_install('entity'); + if (update_variable_get('user_pictures', 0)) { + $formatter = 'image'; + $widget = 'image_image'; + } + else { + $formatter = $widget = 'hidden'; + } + + // Assign form settings for the 'default' form mode. + $form_display = _update_8000_entity_get_form_display('user', 'user', 'default'); + $form_display->set('content.user_picture', array( + 'type' => $widget, 'settings' => array( 'progress_indicator' => 'throbber', 'preview_image_style' => 'thumbnail', ), 'weight' => -1, - ), - ); - _update_7000_field_create_instance($field, $instance); - - // Assign display settings for the 'default' and 'compact' view modes. In D7, - // user pictures did not require Image module to work. Image module only - // allowed usage of an image style to format user pictures in the output. - // The 'user_pictures' variable had a global effect on the presence of the - // user picture functionality before. The new user picture image field is - // created regardless of that global setting, which means the field appears - // on the user account form after migration, even if user pictures were - // disabled previously. The picture is only hidden in the output. - $formatter = update_variable_get('user_pictures', 0) ? 'image' : 'hidden'; - module_load_install('entity'); + )) + ->save(); + update_config_manifest_add('entity.form_display', array($form_display->get('id'))); + // Assign display settings for the 'default' and 'compact' view modes. $display = _update_8000_entity_get_display('user', 'user', 'default'); $display->set('content.user_picture', array( 'label' => 'hidden', diff --git a/core/modules/user/user.module b/core/modules/user/user.module index 09e745a..d664899 100644 --- a/core/modules/user/user.module +++ b/core/modules/user/user.module @@ -2533,7 +2533,7 @@ function user_block_user_action(&$entity, $context = array()) { * field instance' form. */ function user_form_field_ui_field_edit_form_alter(&$form, &$form_state, $form_id) { - $instance = $form['#instance']; + $instance = $form_state['instance']; if ($instance['entity_type'] == 'user') { $form['instance']['settings']['user_register_form'] = array( diff --git a/core/modules/views/lib/Drupal/views/Tests/DefaultViewsTest.php b/core/modules/views/lib/Drupal/views/Tests/DefaultViewsTest.php index 126e62d..ad440dc 100644 --- a/core/modules/views/lib/Drupal/views/Tests/DefaultViewsTest.php +++ b/core/modules/views/lib/Drupal/views/Tests/DefaultViewsTest.php @@ -77,16 +77,8 @@ protected function setUp() { 'field_name' => $this->field_name, 'entity_type' => 'node', 'bundle' => 'page', - 'widget' => array( - 'type' => 'options_select', - ), ); field_create_instance($this->instance); - entity_get_display('node', 'page', 'full') - ->setComponent($this->field_name, array( - 'type' => 'taxonomy_term_reference_link', - )) - ->save(); // Create a time in the past for the archive. $time = time() - 3600; diff --git a/core/modules/views/lib/Drupal/views/Tests/Wizard/TaggedWithTest.php b/core/modules/views/lib/Drupal/views/Tests/Wizard/TaggedWithTest.php index 7c150dc..f1a06a3 100644 --- a/core/modules/views/lib/Drupal/views/Tests/Wizard/TaggedWithTest.php +++ b/core/modules/views/lib/Drupal/views/Tests/Wizard/TaggedWithTest.php @@ -74,12 +74,15 @@ function setUp() { 'field_name' => 'field_views_testing_tags', 'entity_type' => 'node', 'bundle' => $this->node_type_with_tags->type, - 'widget' => array( - 'type' => 'taxonomy_autocomplete', - ), ); field_create_instance($this->tag_instance); + entity_get_form_display('node', $this->node_type_with_tags->type, 'default') + ->setComponent('field_views_testing_tags', array( + 'type' => 'taxonomy_autocomplete', + )) + ->save(); + entity_get_display('node', $this->node_type_with_tags->type, 'default') ->setComponent('field_views_testing_tags', array( 'type' => 'taxonomy_term_reference_link', @@ -185,6 +188,12 @@ function testTaggedWithByNodeType() { $instance = $this->tag_instance; $instance['bundle'] = $this->node_type_without_tags->type; field_create_instance($instance); + entity_get_form_display('node', $this->node_type_without_tags->type, 'default') + ->setComponent('field_views_testing_tags', array( + 'type' => 'taxonomy_autocomplete', + )) + ->save(); + $view['show[type]'] = $this->node_type_with_tags->type; $this->drupalPost('admin/structure/views/add', $view, t('Update "of type" choice')); $this->assertFieldByXpath($tags_xpath); diff --git a/core/profiles/standard/config/entity.display.node.article.default.yml b/core/profiles/standard/config/entity.display.node.article.default.yml index 7cd3ae0..330de2d 100644 --- a/core/profiles/standard/config/entity.display.node.article.default.yml +++ b/core/profiles/standard/config/entity.display.node.article.default.yml @@ -1,7 +1,7 @@ id: node.article.default targetEntityType: node bundle: article -viewMode: default +mode: default content: body: label: hidden diff --git a/core/profiles/standard/config/entity.display.node.article.teaser.yml b/core/profiles/standard/config/entity.display.node.article.teaser.yml index ae65eb4..44add7e 100644 --- a/core/profiles/standard/config/entity.display.node.article.teaser.yml +++ b/core/profiles/standard/config/entity.display.node.article.teaser.yml @@ -1,7 +1,7 @@ id: node.article.teaser targetEntityType: node bundle: article -viewMode: teaser +mode: teaser content: body: label: hidden diff --git a/core/profiles/standard/config/entity.form_display.node.article.default.yml b/core/profiles/standard/config/entity.form_display.node.article.default.yml new file mode 100644 index 0000000..dcd242e --- /dev/null +++ b/core/profiles/standard/config/entity.form_display.node.article.default.yml @@ -0,0 +1,25 @@ +id: node.article.default +targetEntityType: node +bundle: article +mode: default +content: + body: + type: text_textarea_with_summary + weight: '0' + settings: + rows: '9' + summary_rows: '3' + placeholder: '' + field_tags: + type: taxonomy_autocomplete + weight: '-4' + settings: + size: '60' + autocomplete_path: taxonomy/autocomplete + placeholder: '' + field_image: + type: image_image + settings: + progress_indicator: throbber + preview_image_style: thumbnail + weight: '-1' diff --git a/core/profiles/standard/config/field.instance.node.article.field_image.yml b/core/profiles/standard/config/field.instance.node.article.field_image.yml index 3412036..98bd0e3 100644 --- a/core/profiles/standard/config/field.instance.node.article.field_image.yml +++ b/core/profiles/standard/config/field.instance.node.article.field_image.yml @@ -19,12 +19,5 @@ settings: title_field_required: 0 default_image: 0 user_register_form: false -widget: - type: image_image - settings: - progress_indicator: throbber - preview_image_style: thumbnail - weight: -1 - module: image status: 1 langcode: und diff --git a/core/profiles/standard/config/field.instance.node.article.field_tags.yml b/core/profiles/standard/config/field.instance.node.article.field_tags.yml index bbca298..bb51b39 100644 --- a/core/profiles/standard/config/field.instance.node.article.field_tags.yml +++ b/core/profiles/standard/config/field.instance.node.article.field_tags.yml @@ -9,13 +9,5 @@ default_value: { } default_value_function: '' settings: user_register_form: false -widget: - type: taxonomy_autocomplete - weight: -4 - settings: - size: '60' - autocomplete_path: taxonomy/autocomplete - placeholder: '' - module: taxonomy status: 1 langcode: und