diff --git a/core/includes/entity.inc b/core/includes/entity.inc index 702a56e..54d1cbb 100644 --- a/core/includes/entity.inc +++ b/core/includes/entity.inc @@ -105,6 +105,44 @@ function entity_invoke_bundle_hook($hook, $entity_type, $bundle, $bundle_new = N } /** + * Returns the entity form mode info. + * + * @param string|null $entity_type + * The entity type whose form mode info should be returned, or NULL for all + * form mode info. Defaults to NULL. + * + * @return array + * The form mode info for a specific entity type, or all entity types. + */ +function entity_get_form_modes($entity_type = NULL) { + $form_modes = &drupal_static(__FUNCTION__); + if (!$form_modes) { + $langcode = language(Language::TYPE_INTERFACE)->langcode; + if ($cache = cache()->get("entity_form_mode_info:$langcode")) { + $form_modes = $cache->data; + } + else { + $form_modes = array(); + foreach (entity_load_multiple('form_mode') as $form_mode) { + list($form_mode_entity_type, $form_mode_name) = explode('.', $form_mode->id(), 2); + $form_modes[$form_mode_entity_type][$form_mode_name] = (array) $form_mode; + } + drupal_alter('entity_form_mode_info', $form_modes); + cache()->set("entity_form_mode_info:$langcode", $form_modes, CacheBackendInterface::CACHE_PERMANENT, array('entity_info' => TRUE)); + } + } + + if (empty($entity_type)) { + return $form_modes; + } + elseif (isset($form_modes[$entity_type])) { + return $form_modes[$entity_type]; + } + + return array(); +} + +/** * Returns the entity view mode info. * * @param string|null $entity_type @@ -789,9 +827,13 @@ 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); + // Determine the form display to use for rendering this entity form. Depending + // on the configuration of the form mode for this bundle, this will be either + // the form display associated to the form mode, or the 'default' display. + $form_mode_settings = field_form_mode_settings($entity_type, $bundle); + $render_form_mode = !empty($form_mode_settings[$form_mode]['status']) ? $form_mode : 'default'; + + $form_display = entity_get_form_display($entity_type, $bundle, $render_form_mode); $form_display->originalMode = $form_mode; return $form_display; diff --git a/core/lib/Drupal/Core/Entity/EntityFormController.php b/core/lib/Drupal/Core/Entity/EntityFormController.php index 7c5f7ed..03a8851 100644 --- a/core/lib/Drupal/Core/Entity/EntityFormController.php +++ b/core/lib/Drupal/Core/Entity/EntityFormController.php @@ -122,15 +122,13 @@ protected function init(array &$form_state) { $form_state['controller'] = $this; $this->prepareEntity(); - // @todo Allow the usage of different form modes by exposing a hook and the - // UI for them. - $form_display = entity_get_render_form_display($this->entity, 'default'); + $form_display = entity_get_render_form_display($this->entity, $this->getOperation()); // Let modules alter the form display. $form_display_context = array( 'entity_type' => $this->entity->entityType(), 'bundle' => $this->entity->bundle(), - 'form_mode' => 'default', + 'form_mode' => $this->getOperation(), ); \Drupal::moduleHandler()->alter('entity_form_display', $form_display, $form_display_context); @@ -151,12 +149,8 @@ public function form(array $form, array &$form_state) { field_attach_form($entity, $form, $form_state, $this->getFormLangcode($form_state)); } - // Assign the weights configured in the form display. - foreach ($this->getFormDisplay($form_state)->getComponents() as $name => $options) { - if (isset($form[$name])) { - $form[$name]['#weight'] = $options['weight']; - } - } + // Add a process callback so we can assign weights and hide extra fields. + $form['#process'][] = array($this, 'processForm'); if (!isset($form['langcode'])) { // If the form did not specify otherwise, default to keeping the existing @@ -171,6 +165,31 @@ public function form(array $form, array &$form_state) { } /** + * Process callback: assigns weights and hides extra fields. + * + * @see \Drupal\Core\Entity\EntityFormController::form() + */ + public function processForm($element, $form_state, $form) { + // Assign the weights configured in the form display. + $components = $this->getFormDisplay($form_state)->getComponents(); + foreach ($components as $name => $options) { + if (isset($element[$name])) { + $element[$name]['#weight'] = $options['weight']; + } + } + + // Hide extra fields. + $extra_fields = field_info_extra_fields($this->entity->entityType(), $this->entity->bundle(), 'form'); + foreach ($extra_fields as $extra_field => $info) { + if (!isset($components[$extra_field])) { + $element[$extra_field]['#access'] = FALSE; + } + } + + return $element; + } + + /** * Returns the action form element for the current entity form. */ protected function actionsElement(array $form, array &$form_state) { diff --git a/core/lib/Drupal/Core/Entity/EntityFormControllerNG.php b/core/lib/Drupal/Core/Entity/EntityFormControllerNG.php index 0c9dabd..3125d5f 100644 --- a/core/lib/Drupal/Core/Entity/EntityFormControllerNG.php +++ b/core/lib/Drupal/Core/Entity/EntityFormControllerNG.php @@ -31,12 +31,8 @@ public function form(array $form, array &$form_state) { field_attach_form($entity, $form, $form_state, $this->getFormLangcode($form_state)); } - // Assign the weights configured in the form display. - foreach ($this->getFormDisplay($form_state)->getComponents() as $name => $options) { - if (isset($form[$name])) { - $form[$name]['#weight'] = $options['weight']; - } - } + // Add a process callback so we can assign weights and hide extra fields. + $form['#process'][] = array($this, 'processForm'); return $form; } diff --git a/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockTypeListController.php b/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockTypeListController.php index 8ef270c..23f7590 100644 --- a/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockTypeListController.php +++ b/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockTypeListController.php @@ -28,11 +28,17 @@ public function getOperations(EntityInterface $entity) { 'options' => $uri['options'], 'weight' => 15, ); + $operations['manage-form-display'] = array( + 'title' => t('Manage form display'), + 'href' => $uri['path'] . '/form-display', + 'options' => $uri['options'], + 'weight' => 20, + ); $operations['manage-display'] = array( 'title' => t('Manage display'), 'href' => $uri['path'] . '/display', 'options' => $uri['options'], - 'weight' => 20, + 'weight' => 25, ); } return $operations; diff --git a/core/modules/comment/comment.module b/core/modules/comment/comment.module index e309ec7..67e5e36 100644 --- a/core/modules/comment/comment.module +++ b/core/modules/comment/comment.module @@ -279,8 +279,10 @@ function comment_menu_alter(&$items) { // See comment_entity_bundle_info(). $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/form-display']['title'] = 'Comment form'; + $items['admin/structure/types/manage/%/comment/form-display']['weight'] = 4; $items['admin/structure/types/manage/%/comment/display']['title'] = 'Comment display'; - $items['admin/structure/types/manage/%/comment/display']['weight'] = 4; + $items['admin/structure/types/manage/%/comment/display']['weight'] = 5; } /** diff --git a/core/modules/contact/contact.module b/core/modules/contact/contact.module index 78b75f1..3922825 100644 --- a/core/modules/contact/contact.module +++ b/core/modules/contact/contact.module @@ -313,9 +313,9 @@ function contact_mail($key, &$message, $params) { * * Add the enable personal contact form to an individual user's account page. * - * @see user_profile_form() + * @see \Drupal\user\ProfileFormController::form() */ -function contact_form_user_profile_form_alter(&$form, &$form_state) { +function contact_form_user_form_alter(&$form, &$form_state) { $form['contact'] = array( '#type' => 'details', '#title' => t('Contact settings'), diff --git a/core/modules/contact/lib/Drupal/contact/CategoryListController.php b/core/modules/contact/lib/Drupal/contact/CategoryListController.php index a17423b..a3e01e7 100644 --- a/core/modules/contact/lib/Drupal/contact/CategoryListController.php +++ b/core/modules/contact/lib/Drupal/contact/CategoryListController.php @@ -19,6 +19,28 @@ class CategoryListController extends ConfigEntityListController { */ public function getOperations(EntityInterface $entity) { $operations = parent::getOperations($entity); + if (module_exists('field_ui')) { + $uri = $entity->uri(); + $operations['manage-fields'] = array( + 'title' => t('Manage fields'), + 'href' => $uri['path'] . '/fields', + 'options' => $uri['options'], + 'weight' => 11, + ); + $operations['manage-form-display'] = array( + 'title' => t('Manage form display'), + 'href' => $uri['path'] . '/form-display', + 'options' => $uri['options'], + 'weight' => 12, + ); + $operations['manage-display'] = array( + 'title' => t('Manage display'), + 'href' => $uri['path'] . '/display', + 'options' => $uri['options'], + 'weight' => 13, + ); + } + if (!$entity->access('delete')) { unset($operations['delete']); } 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 610f6fd..267f691 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 @@ -188,4 +188,19 @@ function settingsForm(array $form, array &$form_state) { return $element; } + /** + * {@inheritdoc} + */ + public function settingsSummary() { + $summary = array(); + + $summary[] = t('Date part order: !order', array('!order' => $this->getSetting('date_order'))); + if ($this->getFieldSetting('datetime_type') == 'datetime') { + $summary[] = t('Time type: !time_type', array('!time_type' => $this->getSetting('time_type'))); + } + $summary[] = t('Time increments: !increment', array('!increment' => $this->getSetting('increment'))); + + return $summary; + } + } diff --git a/core/modules/edit/lib/Drupal/edit/MetadataGenerator.php b/core/modules/edit/lib/Drupal/edit/MetadataGenerator.php index cecc676..8930ace 100644 --- a/core/modules/edit/lib/Drupal/edit/MetadataGenerator.php +++ b/core/modules/edit/lib/Drupal/edit/MetadataGenerator.php @@ -68,7 +68,7 @@ public function generate(EntityInterface $entity, FieldInstance $instance, $lang } // Early-return if no editor is available. - $formatter_id = entity_get_render_display($entity, $view_mode)->getFormatter($instance['field_name'])->getPluginId(); + $formatter_id = entity_get_render_display($entity, $view_mode)->getRenderer($instance['field_name'])->getPluginId(); $items = $entity->getTranslation($langcode, FALSE)->get($field_name)->getValue(); $editor_id = $this->editorSelector->getEditor($formatter_id, $instance, $items); if (!isset($editor_id)) { diff --git a/core/modules/email/lib/Drupal/email/Plugin/field/widget/EmailDefaultWidget.php b/core/modules/email/lib/Drupal/email/Plugin/field/widget/EmailDefaultWidget.php index 9cd6a99..0e51452 100644 --- a/core/modules/email/lib/Drupal/email/Plugin/field/widget/EmailDefaultWidget.php +++ b/core/modules/email/lib/Drupal/email/Plugin/field/widget/EmailDefaultWidget.php @@ -42,6 +42,23 @@ public function settingsForm(array $form, array &$form_state) { } /** + * {@inheritdoc} + */ + public function settingsSummary() { + $summary = array(); + + $placeholder = $this->getSetting('placeholder'); + if (!empty($placeholder)) { + $summary[] = t('Placeholder: @placeholder', array('@placeholder' => $placeholder)); + } + else { + $summary[] = t('No placeholder'); + } + + return $summary; + } + + /** * Implements Drupal\field\Plugin\Type\Widget\WidgetInterface::formElement(). */ public function formElement(array $items, $delta, array $element, $langcode, array &$form, array &$form_state) { diff --git a/core/modules/entity/lib/Drupal/entity/EntityDisplayBase.php b/core/modules/entity/lib/Drupal/entity/EntityDisplayBase.php index 0a7ff40..99008e2 100644 --- a/core/modules/entity/lib/Drupal/entity/EntityDisplayBase.php +++ b/core/modules/entity/lib/Drupal/entity/EntityDisplayBase.php @@ -163,7 +163,7 @@ public function createCopy($mode) { public function getComponents() { $result = array(); foreach ($this->content as $name => $options) { - if (!isset($options['visible']) || $options['visible'] === TRUE) { + if (!isset($options['visible']) || $options['visible'] == TRUE) { unset($options['visible']); $result[$name] = $options; } diff --git a/core/modules/entity/lib/Drupal/entity/EntityDisplayBaseInterface.php b/core/modules/entity/lib/Drupal/entity/EntityDisplayBaseInterface.php index 42a68c0..06647e7 100644 --- a/core/modules/entity/lib/Drupal/entity/EntityDisplayBaseInterface.php +++ b/core/modules/entity/lib/Drupal/entity/EntityDisplayBaseInterface.php @@ -2,7 +2,7 @@ /** * @file - * Contains \Drupal\entity\Plugin\Core\Entity\EntityDisplayBaseInterface. + * Contains \Drupal\entity\EntityDisplayBaseInterface. */ namespace Drupal\entity; @@ -81,4 +81,15 @@ public function removeComponent($name); */ public function getHighestWeight(); + /** + * Returns the renderer plugin for a field (e.g. widget, formatter). + * + * @param string $field_name + * The field name. + * + * @return \Drupal\field\Plugin\PluginSettingsInterface|null + * A widget or formatter plugin or NULL if the field does not exist. + */ + public function getRenderer($field_name); + } diff --git a/core/modules/entity/lib/Drupal/entity/EntityDisplayInterface.php b/core/modules/entity/lib/Drupal/entity/EntityDisplayInterface.php index ef8a7cb..08d49c0 100644 --- a/core/modules/entity/lib/Drupal/entity/EntityDisplayInterface.php +++ b/core/modules/entity/lib/Drupal/entity/EntityDisplayInterface.php @@ -14,16 +14,4 @@ */ interface EntityDisplayInterface extends EntityDisplayBaseInterface { - /** - * 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); - } diff --git a/core/modules/entity/lib/Drupal/entity/EntityDisplayModeBase.php b/core/modules/entity/lib/Drupal/entity/EntityDisplayModeBase.php new file mode 100644 index 0000000..4fe2c12 --- /dev/null +++ b/core/modules/entity/lib/Drupal/entity/EntityDisplayModeBase.php @@ -0,0 +1,60 @@ +plugins[$field_name])) { return $this->plugins[$field_name]; } 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 index 8c72986..9a3f0a6 100644 --- a/core/modules/entity/lib/Drupal/entity/Plugin/Core/Entity/EntityFormDisplay.php +++ b/core/modules/entity/lib/Drupal/entity/Plugin/Core/Entity/EntityFormDisplay.php @@ -45,7 +45,7 @@ public function __construct(array $values, $entity_type) { /** * {@inheritdoc} */ - public function getWidget($field_name) { + public function getRenderer($field_name) { if (isset($this->plugins[$field_name])) { return $this->plugins[$field_name]; } diff --git a/core/modules/entity/lib/Drupal/entity/Plugin/Core/Entity/EntityFormMode.php b/core/modules/entity/lib/Drupal/entity/Plugin/Core/Entity/EntityFormMode.php new file mode 100644 index 0000000..c539d5e --- /dev/null +++ b/core/modules/entity/lib/Drupal/entity/Plugin/Core/Entity/EntityFormMode.php @@ -0,0 +1,49 @@ +assertEqual($display->getComponent($field['field_name']), $expected); // Check that the getFormatter() method returns the correct formatter plugin. - $formatter = $display->getFormatter($field['field_name']); + $formatter = $display->getRenderer($field['field_name']); $this->assertEqual($formatter->getPluginId(), $default_formatter); $this->assertEqual($formatter->getSettings(), $default_settings); @@ -174,14 +174,14 @@ public function testFieldComponent() { // arbitrary property and reading it back. $random_value = $this->randomString(); $formatter->randomValue = $random_value; - $formatter = $display->getFormatter($field['field_name']); + $formatter = $display->getRenderer($field['field_name']); $this->assertEqual($formatter->randomValue, $random_value); // Check that changing the definition creates a new formatter. $display->setComponent($field['field_name'], array( 'type' => 'field_test_multiple', )); - $formatter = $display->getFormatter($field['field_name']); + $formatter = $display->getRenderer($field['field_name']); $this->assertEqual($formatter->getPluginId(), 'field_test_multiple'); $this->assertFalse(isset($formatter->randomValue)); @@ -193,7 +193,7 @@ public function testFieldComponent() { )); $options = $display->getComponent($field['field_name']); $this->assertEqual($options['type'], 'unknown_formatter'); - $formatter = $display->getFormatter($field['field_name']); + $formatter = $display->getRenderer($field['field_name']); $this->assertEqual($formatter->getPluginId(), $default_formatter); } diff --git a/core/modules/entity/lib/Drupal/entity/Tests/EntityFormDisplayTest.php b/core/modules/entity/lib/Drupal/entity/Tests/EntityFormDisplayTest.php index b92cfbf..54f5611 100644 --- a/core/modules/entity/lib/Drupal/entity/Tests/EntityFormDisplayTest.php +++ b/core/modules/entity/lib/Drupal/entity/Tests/EntityFormDisplayTest.php @@ -87,7 +87,7 @@ public function testFieldComponent() { $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']); + $widget = $form_display->getRenderer($field['field_name']); $this->assertEqual($widget->getPluginId(), $default_widget); $this->assertEqual($widget->getSettings(), $default_settings); @@ -95,14 +95,14 @@ public function testFieldComponent() { // arbitrary property and reading it back. $random_value = $this->randomString(); $widget->randomValue = $random_value; - $widget = $form_display->getWidget($field['field_name']); + $widget = $form_display->getRenderer($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']); + $widget = $form_display->getRenderer($field['field_name']); $this->assertEqual($widget->getPluginId(), 'test_field_widget'); $this->assertFalse(isset($widget->randomValue)); @@ -114,7 +114,7 @@ public function testFieldComponent() { )); $options = $form_display->getComponent($field['field_name']); $this->assertEqual($options['type'], 'unknown_widget'); - $widget = $form_display->getWidget($field['field_name']); + $widget = $form_display->getRenderer($field['field_name']); $this->assertEqual($widget->getPluginId(), $default_widget); } diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/widget/AutocompleteWidgetBase.php b/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/widget/AutocompleteWidgetBase.php index 440b626..c76f4fa 100644 --- a/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/widget/AutocompleteWidgetBase.php +++ b/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/widget/AutocompleteWidgetBase.php @@ -37,16 +37,32 @@ public function settingsForm(array $form, array &$form_state) { '#min' => 1, '#required' => TRUE, ); - $element['placeholder'] = array( '#type' => 'textfield', '#title' => t('Placeholder'), '#default_value' => $this->getSetting('placeholder'), '#description' => t('Text that will be shown inside the field until a value is entered. This hint is usually a sample value or a brief description of the expected format.'), ); + return $element; + } + /** + * {@inheritdoc} + */ + public function settingsSummary() { + $summary = array(); + + $summary[] = t('Autocomplete matching: @match_operator', array('@match_operator' => $this->getSetting('match_operator'))); + $summary[] = t('Textfield size: !size', array('!size' => $this->getSetting('size'))); + $placeholder = $this->getSetting('placeholder'); + if (!empty($placeholder)) { + $summary[] = t('Placeholder: @placeholder', array('@placeholder' => $placeholder)); + } + else { + $summary[] = t('No placeholder'); + } - return $element; + return $summary; } /** diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceAdminTest.php b/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceAdminTest.php index 463a347..db74267 100644 --- a/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceAdminTest.php +++ b/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceAdminTest.php @@ -70,7 +70,6 @@ public function testFieldAdminHandler() { 'fields[_add_new_field][label]' => 'Test label', 'fields[_add_new_field][field_name]' => 'test', 'fields[_add_new_field][type]' => 'entity_reference', - 'fields[_add_new_field][widget_type]' => 'entity_reference_autocomplete', ), t('Save')); // Node should be selected by default. diff --git a/core/modules/field/field.api.php b/core/modules/field/field.api.php index 3535b00..39eb0d7 100644 --- a/core/modules/field/field.api.php +++ b/core/modules/field/field.api.php @@ -32,8 +32,8 @@ * - label: The human readable name of the element. * - description: A short description of the element contents. * - weight: The default weight of the element. - * - visible: (optional) The default visibility of the element. Only for - * 'display' context. Defaults to TRUE. + * - visible: (optional) The default visibility of the element. Defaults to + * TRUE. * - edit: (optional) String containing markup (normally a link) used as the * element's 'edit' operation in the administration interface. Only for * 'form' context. diff --git a/core/modules/field/field.attach.inc b/core/modules/field/field.attach.inc index 7965679..89f92ec 100644 --- a/core/modules/field/field.attach.inc +++ b/core/modules/field/field.attach.inc @@ -714,7 +714,7 @@ function _field_invoke_get_instances($entity_type, $bundle, $options) { */ function _field_invoke_widget_target($form_display) { return function ($instance) use ($form_display) { - return $form_display->getWidget($instance['field_name']); + return $form_display->getRenderer($instance['field_name']); }; } @@ -1398,7 +1398,7 @@ function field_attach_prepare_view($entity_type, array $entities, array $display // the entity display. $target_function = function ($instance) use ($displays) { if (isset($displays[$instance['bundle']])) { - return $displays[$instance['bundle']]->getFormatter($instance['field_name']); + return $displays[$instance['bundle']]->getRenderer($instance['field_name']); } }; field_invoke_method_multiple('prepareView', $target_function, $prepare, $null, $null, $options); @@ -1440,7 +1440,7 @@ function field_attach_view(EntityInterface $entity, EntityDisplay $display, $lan // For each instance, call the view() method on the formatter object handed // by the entity display. $target_function = function ($instance) use ($display) { - return $display->getFormatter($instance['field_name']); + return $display->getRenderer($instance['field_name']); }; $null = NULL; $output = field_invoke_method('view', $target_function, $entity, $null, $null, $options); diff --git a/core/modules/field/field.info.inc b/core/modules/field/field.info.inc index f69649d..e4e0905 100644 --- a/core/modules/field/field.info.inc +++ b/core/modules/field/field.info.inc @@ -31,6 +31,7 @@ */ function field_info_cache_clear() { drupal_static_reset('field_view_mode_settings'); + drupal_static_reset('field_form_mode_settings'); drupal_static_reset('field_available_languages'); // @todo: Remove this when field_attach_*_bundle() bundle management diff --git a/core/modules/field/field.install b/core/modules/field/field.install index 7cfa1f6..b425169 100644 --- a/core/modules/field/field.install +++ b/core/modules/field/field.install @@ -379,6 +379,39 @@ function field_update_8004() { } /** + * Removes the 'user_register_form' setting from field instances and populates + * the user.user.register form display. + */ +function field_update_8005() { + $uuid = new Uuid(); + + $user_default_form_display = Drupal::config('entity.form_display.user.user.default'); + $user_register_config_data = array( + 'id' => 'user.user.register', + 'uuid' => $uuid->generate(), + 'targetEntityType' => 'user', + 'bundle' => 'user', + 'mode' => 'register', + 'content' => array(), + ); + foreach (config_get_storage_names_with_prefix('field.instance') as $config_id) { + $instance_config = Drupal::config($config_id); + if ($instance_config->get('entity_type') == 'user' && $instance_config->get('settings.user_register_form')) { + list(, , $field_id) = explode('.', $instance_config->get('id')); + $user_register_config_data['content'][$field_id] = $user_default_form_display->get('content.' . $field_id); + } + $settings = $instance_config->get('settings'); + unset($settings['user_register_form']); + $instance_config->set('settings', $settings)->save(); + } + + // Save the new 'register' form display. + Drupal::config('entity.form_display.user.user.register') + ->setData($user_register_config_data) + ->save(); +} + +/** * @} End of "addtogroup updates-7.x-to-8.x". * The next series of updates should start at 9000. */ diff --git a/core/modules/field/field.module b/core/modules/field/field.module index 299ada6..8250e21 100644 --- a/core/modules/field/field.module +++ b/core/modules/field/field.module @@ -609,6 +609,7 @@ function field_bundle_settings($entity_type, $bundle, $settings = NULL) { $settings = variable_get('field_bundle_settings_' . $entity_type . '__' . $bundle, array()); $settings += array( 'view_modes' => array(), + 'form_modes' => array(), ); return $settings; @@ -616,6 +617,41 @@ function field_bundle_settings($entity_type, $bundle, $settings = NULL) { } /** + * Returns form mode settings in a given bundle. + * + * @param string $entity_type + * The type of entity; e.g. 'node' or 'user'. + * @param string $bundle + * The bundle name to return form mode settings for. + * + * @return + * An array keyed by form mode, with the following key/value pairs: + * - status: Boolean specifying whether the form mode uses a dedicated set of + * display options (TRUE), or the 'default' options (FALSE). Defaults to + * FALSE. + */ +function field_form_mode_settings($entity_type, $bundle) { + $cache = &drupal_static(__FUNCTION__, array()); + + if (!isset($cache[$entity_type][$bundle])) { + $bundle_settings = field_bundle_settings($entity_type, $bundle); + $settings = $bundle_settings['form_modes']; + // Include form modes for which nothing has been stored yet, but whose + // definition in hook_entity_info_alter() specify they should use custom + // settings by default. + $form_modes = entity_get_form_modes($entity_type); + foreach ($form_modes as $form_mode => $form_mode_info) { + if (!isset($settings[$form_mode]['status']) && $form_mode_info['status']) { + $settings[$form_mode]['status'] = TRUE; + } + } + $cache[$entity_type][$bundle] = $settings; + } + + return $cache[$entity_type][$bundle]; +} + +/** * Returns view mode settings in a given bundle. * * @param $entity_type @@ -800,7 +836,7 @@ function field_view_field(EntityInterface $entity, $field_name, $display_options // Get the formatter object. if (is_string($display_options)) { $view_mode = $display_options; - $formatter = entity_get_render_display($entity, $view_mode)->getFormatter($field_name); + $formatter = entity_get_render_display($entity, $view_mode)->getRenderer($field_name); } else { $view_mode = '_custom'; diff --git a/core/modules/field/lib/Drupal/field/Plugin/Type/Formatter/FormatterPluginManager.php b/core/modules/field/lib/Drupal/field/Plugin/Type/Formatter/FormatterPluginManager.php index 35860eb..4335c31 100644 --- a/core/modules/field/lib/Drupal/field/Plugin/Type/Formatter/FormatterPluginManager.php +++ b/core/modules/field/lib/Drupal/field/Plugin/Type/Formatter/FormatterPluginManager.php @@ -161,4 +161,19 @@ public function getOptions($field_type = NULL) { return $this->formatterOptions; } + /** + * Returns the default settings of a field formatter. + * + * @param string $type + * A field formatter type name. + * + * @return array + * The formatter type's default settings, as provided by the plugin + * definition, or an empty array if type or settings are undefined. + */ + public function getDefaultSettings($type) { + $info = $this->getDefinition($type); + return isset($info['settings']) ? $info['settings'] : array(); + } + } 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 5cf902b..72fefc8 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 @@ -374,6 +374,13 @@ public function settingsForm(array $form, array &$form_state) { } /** + * {@inheritdoc} + */ + public function settingsSummary() { + return array(); + } + + /** * Implements Drupal\field\Plugin\Type\Widget\WidgetInterface::errorElement(). */ public function errorElement(array $element, array $error, array $form, array &$form_state) { diff --git a/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetInterface.php b/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetInterface.php index e00005b..c02c868 100644 --- a/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetInterface.php +++ b/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetInterface.php @@ -38,6 +38,18 @@ public function settingsForm(array $form, array &$form_state); /** + * Returns a short summary for the current widget settings. + * + * If an empty result is returned, the widget is assumed to have no + * configurable settings, and no UI will be provided to display a settings + * form. + * + * @return array + * A short summary of the widget settings. + */ + public function settingsSummary(); + + /** * Returns the form for a single field widget. * * Field widget form elements should be based on the passed-in $element, which 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 eb9cc87..f62dec6 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 @@ -162,4 +162,19 @@ public function getOptions($field_type = NULL) { return $this->widgetOptions; } + /** + * Returns the default settings of a field widget. + * + * @param string $type + * A field widget type name. + * + * @return array + * The widget type's default settings, as provided by the plugin + * definition, or an empty array if type or settings are undefined. + */ + public function getDefaultSettings($type) { + $info = $this->getDefinition($type); + return isset($info['settings']) ? $info['settings'] : array(); + } + } diff --git a/core/modules/field/lib/Drupal/field/Tests/FieldInfoTest.php b/core/modules/field/lib/Drupal/field/Tests/FieldInfoTest.php index dad0e54..bb7c300 100644 --- a/core/modules/field/lib/Drupal/field/Tests/FieldInfoTest.php +++ b/core/modules/field/lib/Drupal/field/Tests/FieldInfoTest.php @@ -24,10 +24,6 @@ function testFieldInfo() { // Test that field_test module's fields, widgets, and formatters show up. $field_test_info = field_test_field_info(); - // We need to account for the existence of user_field_info_alter(). - foreach (array_keys($field_test_info) as $name) { - $field_test_info[$name]['instance_settings']['user_register_form'] = FALSE; - } $info = field_info_field_types(); foreach ($field_test_info as $t_key => $field_type) { foreach ($field_type as $key => $val) { @@ -162,12 +158,10 @@ function testInstancePrepare() { $instance = field_create_instance($instance_definition); // Simulate a stored instance definition missing various settings (e.g. a - // third-party module adding instance or widget settings has been enabled, - // but existing instances do not know the new settings). + // third-party module adding instance settings has been enabled, but + // existing instances do not know the new settings). \Drupal::config('field.instance.' . $instance->id()) ->set('settings', array()) - ->set('widget.type', 'unavailable_widget') - ->set('widget.settings', array()) ->save(); field_info_cache_clear(); @@ -281,10 +275,6 @@ function testFieldMap() { */ function testSettingsInfo() { $info = field_test_field_info(); - // We need to account for the existence of user_field_info_alter(). - foreach (array_keys($info) as $name) { - $info[$name]['instance_settings']['user_register_form'] = FALSE; - } foreach ($info as $type => $data) { $this->assertIdentical(field_info_field_settings($type), $data['settings'], format_string("field_info_field_settings returns %type's field settings", array('%type' => $type))); $this->assertIdentical(field_info_instance_settings($type), $data['instance_settings'], format_string("field_info_field_settings returns %type's field instance settings", array('%type' => $type))); diff --git a/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/field/widget/TestFieldWidget.php b/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/field/widget/TestFieldWidget.php index 293ef18..a2369a5 100644 --- a/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/field/widget/TestFieldWidget.php +++ b/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/field/widget/TestFieldWidget.php @@ -30,7 +30,7 @@ class TestFieldWidget extends WidgetBase { /** - * Implements Drupal\field\Plugin\Type\Widget\WidgetInterface::settingsForm(). + * {@inheritdoc} */ public function settingsForm(array $form, array &$form_state) { $element['test_widget_setting'] = array( @@ -44,7 +44,16 @@ public function settingsForm(array $form, array &$form_state) { } /** - * Implements Drupal\field\Plugin\Type\Widget\WidgetInterface::formElement(). + * {@inheritdoc} + */ + public function settingsSummary() { + $summary = array(); + $summary[] = t('Field test field widget setting: @setting', array('$setting' => $this->getSetting('test_widget_setting'))); + return $summary; + } + + /** + * {@inheritdoc} */ public function formElement(array $items, $delta, array $element, $langcode, array &$form, array &$form_state) { $element += array( @@ -55,7 +64,7 @@ public function formElement(array $items, $delta, array $element, $langcode, arr } /** - * Implements Drupal\field\Plugin\Type\Widget\WidgetInterface::errorElement(). + * {@inheritdoc} */ public function errorElement(array $element, array $error, array $form, array &$form_state) { return $element['value']; diff --git a/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/field/widget/TestFieldWidgetMultiple.php b/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/field/widget/TestFieldWidgetMultiple.php index 95b3cf2..ba2b6a2 100644 --- a/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/field/widget/TestFieldWidgetMultiple.php +++ b/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/field/widget/TestFieldWidgetMultiple.php @@ -31,21 +31,30 @@ class TestFieldWidgetMultiple extends WidgetBase { /** - * Implements Drupal\field\Plugin\Type\Widget\WidgetInterface::settingsForm(). + * {@inheritdoc} */ public function settingsForm(array $form, array &$form_state) { $element['test_field_widget_multiple'] = array( '#type' => 'textfield', '#title' => t('Field test field widget setting'), '#description' => t('A dummy form element to simulate field widget setting.'), - '#default_value' => $this->getSetting('test_widget_setting'), + '#default_value' => $this->getSetting('test_widget_setting_multiple'), '#required' => FALSE, ); return $element; } /** - * Implements Drupal\field\Plugin\Type\Widget\WidgetInterface::formElement(). + * {@inheritdoc} + */ + public function settingsSummary() { + $summary = array(); + $summary[] = t('Field test field widget setting: @setting', array('$setting' => $this->getSetting('test_widget_setting_multiple'))); + return $summary; + } + + /** + * {@inheritdoc} */ public function formElement(array $items, $delta, array $element, $langcode, array &$form, array &$form_state) { $values = array(); @@ -61,7 +70,7 @@ public function formElement(array $items, $delta, array $element, $langcode, arr } /** - * Implements Drupal\field\Plugin\Type\Widget\WidgetInterface::errorElement(). + * {@inheritdoc} */ public function errorElement(array $element, array $error, array $form, array &$form_state) { return $element; diff --git a/core/modules/field_ui/css/field_ui.admin.css b/core/modules/field_ui/css/field_ui.admin.css index cf59695..0eb5d6b 100644 --- a/core/modules/field_ui/css/field_ui.admin.css +++ b/core/modules/field_ui/css/field_ui.admin.css @@ -38,31 +38,31 @@ white-space: nowrap; } -/* 'Manage display' overview */ -.field-ui-overview .field-formatter-summary-cell { +/* 'Manage form display' and 'Manage display' overview */ +.field-ui-overview .field-plugin-summary-cell { line-height: 1em; } -.field-ui-overview .field-formatter-summary { +.field-ui-overview .field-plugin-summary { float: left; font-size: .9em; } -.field-ui-overview .field-formatter-summary-cell .warning { +.field-ui-overview .field-plugin-summary-cell .warning { display: block; float: left; margin-right: .5em; } -.field-ui-overview .field-formatter-settings-edit-wrapper { +.field-ui-overview .field-plugin-settings-edit-wrapper { float: right; } -.field-ui-overview .field-formatter-settings-edit { +.field-ui-overview .field-plugin-settings-edit { float: right; } -.field-ui-overview .field-formatter-settings-editing td { +.field-ui-overview .field-plugin-settings-editing td { vertical-align: top; } -.field-ui-overview .field-formatter-settings-editing .field-formatter-type { +.field-ui-overview .field-plugin-settings-editing .field-plugin-type { display: none; } -.field-ui-overview .field-formatter-settings-edit-form .formatter-name{ +.field-ui-overview .field-plugin-settings-edit-form .plugin-name { font-weight: bold; } diff --git a/core/modules/field_ui/field_ui.api.php b/core/modules/field_ui/field_ui.api.php index b3bf03e..ac78c1d 100644 --- a/core/modules/field_ui/field_ui.api.php +++ b/core/modules/field_ui/field_ui.api.php @@ -119,6 +119,34 @@ function hook_field_formatter_settings_form_alter(&$element, &$form_state, $cont } /** + * Alters the widget settings form. + * + * @param array $element + * Form array. + * @param array $form_state + * The form state of the (entire) configuration form. + * @param array $context + * An associative array with the following elements: + * - formatter: The formatter object. + * - field: The field structure being configured. + * - instance: The instance structure being configured. + * - form_mode: The form mode being configured. + * - form: The (entire) configuration form array. + * + * @see \Drupal\field_ui\FormDisplayOverView. + */ +function hook_field_widget_settings_form_alter(&$element, &$form_state, $context) { + // Add a 'mysetting' checkbox to the settings form for 'foo_field' fields. + if ($context['field']['type'] == 'foo_field') { + $element['mysetting'] = array( + '#type' => 'checkbox', + '#title' => t('My setting'), + '#default_value' => $context['formatter']->getSetting('mysetting'), + ); + } +} + +/** * Alters the field formatter settings summary. * * @param $summary @@ -143,5 +171,29 @@ function hook_field_formatter_settings_summary_alter(&$summary, $context) { } /** + * Alters the field widget settings summary. + * + * @param array $summary + * The summary. + * @param array $context + * An associative array with the following elements: + * - widget: The widget object. + * - field: The field structure being configured. + * - instance: The instance structure being configured. + * - form_mode: The form mode being configured. + * + * @see \Drupal\field_ui\FormDisplayOverView. + */ +function hook_field_widget_settings_summary_alter(&$summary, $context) { + // Append a message to the summary when an instance of foo_field has + // mysetting set to TRUE for the current view mode. + if ($context['field']['type'] == 'foo_field') { + if ($context['widget']->getSetting('mysetting')) { + $summary[] = t('My setting enabled.'); + } + } +} + +/** * @} End of "addtogroup field_types". */ diff --git a/core/modules/field_ui/field_ui.js b/core/modules/field_ui/field_ui.js index 3000cd1..2955bf9 100644 --- a/core/modules/field_ui/field_ui.js +++ b/core/modules/field_ui/field_ui.js @@ -7,108 +7,6 @@ "use strict"; -Drupal.behaviors.fieldUIFieldOverview = { - attach: function (context, settings) { - $(context).find('table#field-overview').once('field-overview', function () { - Drupal.fieldUIFieldOverview.attachUpdateSelects(this, settings); - }); - } -}; - -Drupal.fieldUIFieldOverview = { - /** - * Implements dependent select dropdowns on the 'Manage fields' screen. - */ - attachUpdateSelects: function(table, settings) { - var widgetTypes = settings.fieldWidgetTypes; - var fields = settings.fields; - var $table = $(table); - - // Store the default text of widget selects. - $table.find('.widget-type-select').each(function () { - this.initialValue = this.options[0].text; - }); - - // 'Field type' select updates its 'Widget' select. - $table.find('.field-type-select').each(function () { - var $this = $(this); - this.targetSelect = $this.closest('tr').find('.widget-type-select'); - - $this.bind('change keyup', function () { - var selectedFieldType = this.options[this.selectedIndex].value; - var options = (selectedFieldType in widgetTypes ? widgetTypes[selectedFieldType] : []); - this.targetSelect.fieldUIPopulateOptions(options); - }); - - // Trigger change on initial pageload to get the right widget options - // when field type comes pre-selected (on failed validation). - $this.trigger('change', false); - }); - - // 'Existing field' select updates its 'Widget' select and 'Label' textfield. - $table.find('.field-select').each(function () { - var $this = $(this); - var $tr = $this.closest('tr'); - this.targetSelect = $tr.find('.widget-type-select'); - this.targetTextfield = $tr.find('.label-textfield'); - this.targetTextfield - .data('field_ui_edited', false) - .bind('keyup', function (e) { - $(this).data('field_ui_edited', $(this).val() !== ''); - }); - - $this.bind('change keyup', function (e, updateText) { - updateText = (typeof updateText === 'undefined' ? true : updateText); - var selectedField = this.options[this.selectedIndex].value; - var selectedFieldType = (selectedField in fields ? fields[selectedField].type : null); - var selectedFieldWidget = (selectedField in fields ? fields[selectedField].widget : null); - var options = (selectedFieldType && (selectedFieldType in widgetTypes) ? widgetTypes[selectedFieldType] : []); - this.targetSelect.fieldUIPopulateOptions(options, selectedFieldWidget); - - // Only overwrite the "Label" input if it has not been manually - // changed, or if it is empty. - if (updateText && !this.targetTextfield.data('field_ui_edited')) { - this.targetTextfield.val(selectedField in fields ? fields[selectedField].label : ''); - } - }); - - // Trigger change on initial pageload to get the right widget options - // and label when field type comes pre-selected (on failed validation). - $this.trigger('change', false); - }); - } -}; - -/** - * Populates options in a select input. - */ -jQuery.fn.fieldUIPopulateOptions = function (options, selected) { - return this.each(function () { - var disabled = false; - if (options.length === 0) { - options = [this.initialValue]; - disabled = true; - } - - // If possible, keep the same widget selected when changing field type. - // This is based on textual value, since the internal value might be - // different (options_buttons vs. node_reference_buttons). - var previousSelectedText = this.options[this.selectedIndex].text; - - var html = ''; - for (var value in options) { - if (options.hasOwnProperty(value)) { - // Figure out which value should be selected. The 'selected' param - // takes precedence. - var is_selected = ((typeof selected !== 'undefined' && value === selected) || (typeof selected === 'undefined' && options[value] === previousSelectedText)); - html += ''; - } - } - - $(this).html(html).prop('disabled', disabled); - }); -}; - Drupal.behaviors.fieldUIDisplayOverview = { attach: function (context, settings) { $(context).find('table#field-display-overview').once('field-display-overview', function() { @@ -290,9 +188,9 @@ Drupal.fieldUIDisplayOverview.field = function (row, data) { this.region = data.region; this.tableDrag = data.tableDrag; - // Attach change listener to the 'formatter type' select. - this.$formatSelect = $(row).find('select.field-formatter-type'); - this.$formatSelect.change(Drupal.fieldUIOverview.onChange); + // Attach change listener to the 'plugin type' select. + this.$pluginSelect = $(row).find('select.field-plugin-type'); + this.$pluginSelect.change(Drupal.fieldUIOverview.onChange); return this; }; @@ -302,7 +200,7 @@ Drupal.fieldUIDisplayOverview.field.prototype = { * Returns the region corresponding to the current form values of the row. */ getRegion: function () { - return (this.$formatSelect.val() === 'hidden') ? 'hidden' : 'content'; + return (this.$pluginSelect.val() === 'hidden') ? 'hidden' : 'content'; }, /** @@ -326,7 +224,7 @@ Drupal.fieldUIDisplayOverview.field.prototype = { // When triggered by a row drag, the 'format' select needs to be adjusted // to the new region. - var currentValue = this.$formatSelect.val(); + var currentValue = this.$pluginSelect.val(); var value; // @TODO Check if this couldn't just be like // if (region !== 'hidden') { @@ -334,7 +232,7 @@ Drupal.fieldUIDisplayOverview.field.prototype = { if (currentValue === 'hidden') { // Restore the formatter back to the default formatter. Pseudo-fields do // not have default formatters, we just return to 'visible' for those. - value = (typeof this.defaultFormatter !== 'undefined') ? this.defaultFormatter : this.$formatSelect.find('option').val(); + value = (typeof this.defaultPlugin !== 'undefined') ? this.defaultPlugin : this.$pluginSelect.find('option').val(); } } else { @@ -342,11 +240,11 @@ Drupal.fieldUIDisplayOverview.field.prototype = { } if (typeof value !== 'undefined') { - this.$formatSelect.val(value); + this.$pluginSelect.val(value); } var refreshRows = {}; - refreshRows[this.name] = this.$formatSelect.get(0); + refreshRows[this.name] = this.$pluginSelect.get(0); return refreshRows; } diff --git a/core/modules/field_ui/field_ui.module b/core/modules/field_ui/field_ui.module index d115b7f..15df7ac 100644 --- a/core/modules/field_ui/field_ui.module +++ b/core/modules/field_ui/field_ui.module @@ -96,11 +96,6 @@ function field_ui_menu() { 'type' => MENU_LOCAL_TASK, 'route_name' => "field_ui.field_edit.$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, @@ -108,26 +103,47 @@ function field_ui_menu() { 'weight' => 10, ); + // 'Manage form display' tab. + $items["$path/form-display"] = array( + 'title' => 'Manage form display', + 'type' => MENU_LOCAL_TASK, + 'route_name' => "field_ui.form_display_overview.$entity_type", + 'weight' => 2, + ); + // 'Manage display' tab. $items["$path/display"] = array( 'title' => 'Manage display', 'type' => MENU_LOCAL_TASK, 'route_name' => "field_ui.display_overview.$entity_type", - 'weight' => 2, + 'weight' => 3, ); - // View modes secondary tabs. + // View and form 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 a route requirement to determine which ones are // actually visible for a given bundle. + $items["$default_path/form-display/default"] = array( + 'title' => t('Default'), + 'type' => MENU_DEFAULT_LOCAL_TASK, + ); $items["$default_path/display/default"] = array( 'title' => t('Default'), 'type' => MENU_DEFAULT_LOCAL_TASK, ); $weight = 0; + foreach (entity_get_form_modes($entity_type) as $form_mode => $form_mode_info) { + $items["$path/form-display/$form_mode"] = array( + 'title' => $form_mode_info['label'], + 'type' => MENU_LOCAL_TASK, + 'weight' => $weight++, + 'route_name' => "field_ui.form_display_overview.$entity_type.$form_mode", + ); + } + $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'], @@ -155,6 +171,9 @@ function field_ui_permission() { 'title' => t('%entity_label: Administer fields', array('%entity_label' => $entity_info['label'])), 'restrict access' => TRUE, ); + $permissions['administer ' . $entity_type . ' form display'] = array( + 'title' => t('%entity_label: Administer form display', array('%entity_label' => $entity_info['label'])) + ); $permissions['administer ' . $entity_type . ' display'] = array( 'title' => t('%entity_label: Administer display', array('%entity_label' => $entity_info['label'])) ); diff --git a/core/modules/field_ui/field_ui.services.yml b/core/modules/field_ui/field_ui.services.yml index cfc1214..4c8febe 100644 --- a/core/modules/field_ui/field_ui.services.yml +++ b/core/modules/field_ui/field_ui.services.yml @@ -8,3 +8,7 @@ services: class: Drupal\field_ui\Access\ViewModeAccessCheck tags: - { name: access_check } + access_check.field_ui.forn_mode: + class: Drupal\field_ui\Access\FormModeAccessCheck + 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/FormModeAccessCheck.php similarity index 59% copy from core/modules/field_ui/lib/Drupal/field_ui/Access/ViewModeAccessCheck.php copy to core/modules/field_ui/lib/Drupal/field_ui/Access/FormModeAccessCheck.php index 1ddb8b5..dfbefe7 100644 --- a/core/modules/field_ui/lib/Drupal/field_ui/Access/ViewModeAccessCheck.php +++ b/core/modules/field_ui/lib/Drupal/field_ui/Access/FormModeAccessCheck.php @@ -2,7 +2,7 @@ /** * @file - * Contains \Drupal\field_ui\Access\ViewModeAccessCheck. + * Contains \Drupal\field_ui\Access\FormModeAccessCheck. */ namespace Drupal\field_ui\Access; @@ -14,13 +14,13 @@ /** * Allows access to routes to be controlled by an '_access' boolean parameter. */ -class ViewModeAccessCheck implements AccessCheckInterface { +class FormModeAccessCheck implements AccessCheckInterface { /** * {@inheritdoc} */ public function applies(Route $route) { - return array_key_exists('_field_ui_view_mode_access', $route->getRequirements()); + return array_key_exists('_field_ui_form_mode_access', $route->getRequirements()); } /** @@ -29,12 +29,12 @@ public function applies(Route $route) { 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'); + $form_mode = $request->attributes->get('mode'); - $view_mode_settings = field_view_mode_settings($entity_type, $bundle); - $visibility = ($view_mode == 'default') || !empty($view_mode_settings[$view_mode]['status']); + $form_mode_settings = field_form_mode_settings($entity_type, $bundle); + $visibility = ($form_mode == 'default') || !empty($form_mode_settings[$form_mode]['status']); if ($visibility) { - $permission = $route->getRequirement('_field_ui_view_mode_access'); + $permission = $route->getRequirement('_field_ui_form_mode_access'); return user_access($permission); } } 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 index 1ddb8b5..f82ede6 100644 --- a/core/modules/field_ui/lib/Drupal/field_ui/Access/ViewModeAccessCheck.php +++ b/core/modules/field_ui/lib/Drupal/field_ui/Access/ViewModeAccessCheck.php @@ -29,7 +29,7 @@ public function applies(Route $route) { 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 = $request->attributes->get('mode'); $view_mode_settings = field_view_mode_settings($entity_type, $bundle); $visibility = ($view_mode == 'default') || !empty($view_mode_settings[$view_mode]['status']); 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 e77dfee..841c056 100644 --- a/core/modules/field_ui/lib/Drupal/field_ui/DisplayOverview.php +++ b/core/modules/field_ui/lib/Drupal/field_ui/DisplayOverview.php @@ -7,36 +7,16 @@ namespace Drupal\field_ui; -use Drupal\field_ui\OverviewBase; -use Drupal\Core\Entity\EntityManager; -use Drupal\field\Plugin\Type\Formatter\FormatterPluginManager; +use Drupal\Component\Utility\NestedArray; +use Drupal\Core\Controller\ControllerInterface; +use Drupal\entity\EntityDisplayBaseInterface; +use Drupal\field\FieldInstanceInterface; use Symfony\Component\DependencyInjection\ContainerInterface; /** * Field UI display overview form. */ -class DisplayOverview extends OverviewBase { - - /** - * The formatter plugin manager. - * - * @var \Drupal\field\Plugin\Type\Formatter\FormatterPluginManager - */ - protected $formatterManager; - - /** - * Constructs a new DisplayOverview. - * - * @param \Drupal\Core\Entity\EntityManager $entity_manager - * The entity manager. - * @param \Drupal\field\Plugin\Type\Formatter\FormatterPluginManager $formatter_manager - * The formatter plugin manager. - */ - public function __construct(EntityManager $entity_manager, FormatterPluginManager $formatter_manager) { - parent::__construct($entity_manager); - - $this->formatterManager = $formatter_manager; - } +class DisplayOverview extends DisplayOverviewBase implements ControllerInterface { /** * {@inheritdoc} @@ -49,584 +29,188 @@ public static function create(ContainerInterface $container) { } /** - * Implements Drupal\field_ui\OverviewBase::getRegions(). - */ - public function getRegions() { - return array( - 'content' => array( - 'title' => t('Content'), - 'invisible' => TRUE, - 'message' => t('No field is displayed.') - ), - 'hidden' => array( - 'title' => t('Disabled'), - 'message' => t('No field is hidden.') - ), - ); - } - - /** - * Implements \Drupal\Core\Form\FormInterface::getFormID(). + * {@inheritdoc} */ public function getFormID() { return 'field_ui_display_overview_form'; } /** - * Implements \Drupal\Core\Form\FormInterface::buildForm(). + * {@inheritdoc} */ - 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->mode); - - $form_state += array( - 'formatter_settings_edit' => NULL, - ); - - $form += array( - '#entity_type' => $this->entity_type, - '#bundle' => $this->bundle, - '#view_mode' => $this->mode, - '#fields' => array_keys($instances), - '#extra' => array_keys($extra_fields), - ); - - if (empty($instances) && empty($extra_fields)) { - drupal_set_message(t('There are no fields yet added. You can add new fields on the Manage fields page.', array('@link' => url($this->adminPath . '/fields'))), 'warning'); - return $form; - } - - $table = array( - '#type' => 'field_ui_table', - '#pre_render' => array(array($this, 'tablePreRender')), - '#tree' => TRUE, - '#header' => array( - t('Field'), - t('Weight'), - t('Parent'), - t('Label'), - array('data' => t('Format'), 'colspan' => 3), + protected function buildFieldRow($field_id, FieldInstanceInterface $instance, EntityDisplayBaseInterface $entity_display, array $form, array &$form_state) { + $field_row = parent::buildFieldRow($field_id, $instance, $entity_display, $form, $form_state); + $display_options = $entity_display->getComponent($field_id); + + // Insert the label column. + $label = array( + 'label' => array( + '#type' => 'select', + '#title' => t('Label display for @title', array('@title' => $instance['label'])), + '#title_display' => 'invisible', + '#options' => $this->getFieldLabelOptions(), + '#default_value' => $display_options ? $display_options['label'] : 'above', ), - '#regions' => $this->getRegions(), - '#parent_options' => drupal_map_assoc(array_keys($this->getRegions())), - '#attributes' => array( - 'class' => array('field-ui-overview'), - 'id' => 'field-display-overview', - ), - // Add Ajax wrapper. - '#prefix' => '
', - '#suffix' => '
', - ); - - $field_label_options = array( - 'above' => t('Above'), - 'inline' => t('Inline'), - 'hidden' => '<' . t('Hidden') . '>', ); - $extra_visibility_options = array( - 'visible' => t('Visible'), - 'hidden' => t('Hidden'), - ); - - // Field rows. - foreach ($instances as $name => $instance) { - $field = field_info_field($name); - $display_options = $entity_display->getComponent($name); - - $table[$name] = array( - '#attributes' => array('class' => array('draggable', 'tabledrag-leaf')), - '#row_type' => 'field', - '#region_callback' => array($this, 'getRowRegion'), - '#js_settings' => array( - 'rowHandler' => 'field', - 'defaultFormatter' => $field_types[$field['type']]['default_formatter'], - ), - 'human_name' => array( - '#markup' => check_plain($instance['label']), - ), - 'weight' => array( - '#type' => 'textfield', - '#title' => t('Weight for @title', array('@title' => $instance['label'])), - '#title_display' => 'invisible', - '#default_value' => $display_options ? $display_options['weight'] : '0', - '#size' => 3, - '#attributes' => array('class' => array('field-weight')), - ), - 'parent_wrapper' => array( - 'parent' => array( - '#type' => 'select', - '#title' => t('Label display for @title', array('@title' => $instance['label'])), - '#title_display' => 'invisible', - '#options' => $table['#parent_options'], - '#empty_value' => '', - '#attributes' => array('class' => array('field-parent')), - '#parents' => array('fields', $name, 'parent'), - ), - 'hidden_name' => array( - '#type' => 'hidden', - '#default_value' => $name, - '#attributes' => array('class' => array('field-name')), - ), - ), - 'label' => array( - '#type' => 'select', - '#title' => t('Label display for @title', array('@title' => $instance['label'])), - '#title_display' => 'invisible', - '#options' => $field_label_options, - '#default_value' => $display_options ? $display_options['label'] : 'above', - ), - ); - - $formatter_options = $this->formatterManager->getOptions($field['type']); - $formatter_options['hidden'] = '<' . t('Hidden') . '>'; - $table[$name]['format'] = array( - 'type' => array( - '#type' => 'select', - '#title' => t('Formatter for @title', array('@title' => $instance['label'])), - '#title_display' => 'invisible', - '#options' => $formatter_options, - '#default_value' => $display_options ? $display_options['type'] : 'hidden', - '#parents' => array('fields', $name, 'type'), - '#attributes' => array('class' => array('field-formatter-type')), - ), - 'settings_edit_form' => array(), - ); - - // Check the currently selected formatter, and merge persisted values for - // formatter settings. - if (isset($form_state['values']['fields'][$name]['type'])) { - $display_options['type'] = $form_state['values']['fields'][$name]['type']; - } - if (isset($form_state['formatter_settings'][$name])) { - $display_options['settings'] = $form_state['formatter_settings'][$name]; - } - - // Get the corresponding formatter object. - if ($display_options && $display_options['type'] != 'hidden') { - $formatter = $this->formatterManager->getInstance(array( - 'field_definition' => $instance, - 'view_mode' => $this->mode, - 'configuration' => $display_options - )); - } - else { - $formatter = NULL; - } - // Base button element for the various formatter settings actions. - $base_button = array( - '#submit' => array(array($this, 'multistepSubmit')), - '#ajax' => array( - 'callback' => array($this, 'multistepAjax'), - 'wrapper' => 'field-display-overview-wrapper', - 'effect' => 'fade', - ), - '#field_name' => $name, - ); + $label_position = array_search('plugin', array_keys($field_row)); + $field_row = array_slice($field_row, 0, $label_position, TRUE) + $label + array_slice($field_row, $label_position, count($field_row) - 1, TRUE); - if ($form_state['formatter_settings_edit'] == $name) { - // We are currently editing this field's formatter settings. Display the - // settings form and submit buttons. - $table[$name]['format']['settings_edit_form'] = array(); - - if ($formatter) { - $formatter_type_info = $formatter->getPluginDefinition(); - - // Generate the settings form and allow other modules to alter it. - $settings_form = $formatter->settingsForm($form, $form_state); - $context = array( - 'formatter' => $formatter, - 'field' => $field, - 'instance' => $instance, - 'view_mode' => $this->mode, - 'form' => $form, - ); - drupal_alter('field_formatter_settings_form', $settings_form, $form_state, $context); - - if ($settings_form) { - $table[$name]['format']['#cell_attributes'] = array('colspan' => 3); - $table[$name]['format']['settings_edit_form'] = array( - '#type' => 'container', - '#attributes' => array('class' => array('field-formatter-settings-edit-form')), - '#parents' => array('fields', $name, 'settings_edit_form'), - 'label' => array( - '#markup' => t('Format settings:') . ' ' . $formatter_type_info['label'] . '', - ), - 'settings' => $settings_form, - 'actions' => array( - '#type' => 'actions', - 'save_settings' => $base_button + array( - '#type' => 'submit', - '#name' => $name . '_formatter_settings_update', - '#value' => t('Update'), - '#op' => 'update', - ), - 'cancel_settings' => $base_button + array( - '#type' => 'submit', - '#name' => $name . '_formatter_settings_cancel', - '#value' => t('Cancel'), - '#op' => 'cancel', - // Do not check errors for the 'Cancel' button, but make sure we - // get the value of the 'formatter type' select. - '#limit_validation_errors' => array(array('fields', $name, 'type')), - ), - ), - ); - $table[$name]['#attributes']['class'][] = 'field-formatter-settings-editing'; - } - } - } - else { - $table[$name]['settings_summary'] = array(); - $table[$name]['settings_edit'] = array(); - - if ($formatter) { - // Display a summary of the current formatter settings, and (if the - // summary is not empty) a button to edit them. - $summary = $formatter->settingsSummary(); - - // Allow other modules to alter the summary. - $context = array( - 'formatter' => $formatter, - 'field' => $field, - 'instance' => $instance, - 'view_mode' => $this->mode, - ); - drupal_alter('field_formatter_settings_summary', $summary, $context); - - if (!empty($summary)) { - $table[$name]['settings_summary'] = array( - '#markup' => '
' . implode('
', $summary) . '
', - '#cell_attributes' => array('class' => array('field-formatter-summary-cell')), - ); - $table[$name]['settings_edit'] = $base_button + array( - '#type' => 'image_button', - '#name' => $name . '_formatter_settings_edit', - '#src' => 'core/misc/configure-dark.png', - '#attributes' => array('class' => array('field-formatter-settings-edit'), 'alt' => t('Edit')), - '#op' => 'edit', - // Do not check errors for the 'Edit' button, but make sure we get - // the value of the 'formatter type' select. - '#limit_validation_errors' => array(array('fields', $name, 'type')), - '#prefix' => '
', - '#suffix' => '
', - ); - } - } - } + // Update the (invisible) title of the 'plugin' column. + $field_row['plugin']['#title'] = t('Formatter for @title', array('@title' => $instance['label'])); + if (!empty($field_row['plugin']['settings_edit_form'])) { + $plugin_type_info = $entity_display->getRenderer($field_id)->getPluginDefinition(); + $field_row['plugin']['settings_edit_form']['label']['#markup'] = t('Format settings:') . ' ' . $plugin_type_info['label'] . ''; } - // Non-field elements. - foreach ($extra_fields as $name => $extra_field) { - $display_options = $entity_display->getComponent($name); - - $table[$name] = array( - '#attributes' => array('class' => array('draggable', 'tabledrag-leaf')), - '#row_type' => 'extra_field', - '#region_callback' => array($this, 'getRowRegion'), - '#js_settings' => array('rowHandler' => 'field'), - 'human_name' => array( - '#markup' => check_plain($extra_field['label']), - ), - 'weight' => array( - '#type' => 'textfield', - '#title' => t('Weight for @title', array('@title' => $extra_field['label'])), - '#title_display' => 'invisible', - '#default_value' => $display_options ? $display_options['weight'] : 0, - '#size' => 3, - '#attributes' => array('class' => array('field-weight')), - ), - 'parent_wrapper' => array( - 'parent' => array( - '#type' => 'select', - '#title' => t('Parents for @title', array('@title' => $extra_field['label'])), - '#title_display' => 'invisible', - '#options' => $table['#parent_options'], - '#empty_value' => '', - '#attributes' => array('class' => array('field-parent')), - '#parents' => array('fields', $name, 'parent'), - ), - 'hidden_name' => array( - '#type' => 'hidden', - '#default_value' => $name, - '#attributes' => array('class' => array('field-name')), - ), - ), - 'empty_cell' => array( - '#markup' => ' ', - ), - 'format' => array( - 'type' => array( - '#type' => 'select', - '#title' => t('Visibility for @title', array('@title' => $extra_field['label'])), - '#title_display' => 'invisible', - '#options' => $extra_visibility_options, - '#default_value' => $display_options ? 'visible' : 'hidden', - '#parents' => array('fields', $name, 'type'), - '#attributes' => array('class' => array('field-formatter-type')), - ), - ), - 'settings_summary' => array(), - 'settings_edit' => array(), - ); - } - - $form['fields'] = $table; - - // Custom display settings. - 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) { - $form['modes'] = array( - '#type' => 'details', - '#title' => t('Custom display settings'), - '#collapsed' => TRUE, - ); - // Collect options and default values for the 'Custom display settings' - // checkboxes. - $options = array(); - $default = array(); - $view_mode_settings = field_view_mode_settings($this->entity_type, $this->bundle); - foreach ($view_modes as $view_mode_name => $view_mode_info) { - $options[$view_mode_name] = $view_mode_info['label']; - if (!empty($view_mode_settings[$view_mode_name]['status'])) { - $default[] = $view_mode_name; - } - } - $form['modes']['view_modes_custom'] = array( - '#type' => 'checkboxes', - '#title' => t('Use custom display settings for the following view modes'), - '#options' => $options, - '#default_value' => $default, - ); - } - } + return $field_row; + } - // In overviews involving nested rows from contributed modules (i.e - // field_group), the 'format type' selects can trigger a series of changes - // in child rows. The #ajax behavior is therefore not attached directly to - // the selects, but triggered by the client-side script through a hidden - // #ajax 'Refresh' button. A hidden 'refresh_rows' input tracks the name of - // affected rows. - $form['refresh_rows'] = array('#type' => 'hidden'); - $form['refresh'] = array( - '#type' => 'submit', - '#value' => t('Refresh'), - '#op' => 'refresh_table', - '#submit' => array(array($this, 'multistepSubmit')), - '#ajax' => array( - 'callback' => array($this, 'multistepAjax'), - 'wrapper' => 'field-display-overview-wrapper', - 'effect' => 'fade', - // The button stays hidden, so we hide the Ajax spinner too. Ad-hoc - // spinners will be added manually by the client-side script. - 'progress' => 'none', - ), - '#attributes' => array('class' => array('element-invisible')) + /** + * {@inheritdoc} + */ + protected function buildExtraFieldRow($field_id, $extra_field, $entity_display) { + $extra_field_row = parent::buildExtraFieldRow($field_id, $extra_field, $entity_display); + + // Insert an empty placeholder for the label column. + $label = array( + 'empty_cell' => array( + '#markup' => ' ' + ) ); + $label_position = array_search('plugin', array_keys($extra_field_row)); + $extra_field_row = array_slice($extra_field_row, 0, $label_position, TRUE) + $label + array_slice($extra_field_row, $label_position, count($extra_field_row) - 1, TRUE); - $form['actions'] = array('#type' => 'actions'); - $form['actions']['submit'] = array('#type' => 'submit', '#value' => t('Save')); - - $form['#attached']['library'][] = array('field_ui', 'drupal.field_ui'); - - // Add tabledrag behavior. - $form['#attached']['drupal_add_tabledrag'][] = array('field-display-overview', 'order', 'sibling', 'field-weight'); - $form['#attached']['drupal_add_tabledrag'][] = array('field-display-overview', 'match', 'parent', 'field-parent', 'field-parent', 'field-name'); - - return $form; + return $extra_field_row; } /** - * Overrides \Drupal\field_ui\OverviewBase::submitForm(). + * {@inheritdoc} */ - public function submitForm(array &$form, array &$form_state) { - $form_values = $form_state['values']; - $display = entity_get_display($this->entity_type, $this->bundle, $this->mode); - - // Collect data for 'regular' fields. - foreach ($form['#fields'] as $field_name) { - // Retrieve the stored instance settings to merge with the incoming - // values. - $values = $form_values['fields'][$field_name]; - - if ($values['type'] == 'hidden') { - $display->removeComponent($field_name); - } - else { - // Get formatter settings. They lie either directly in submitted form - // values (if the whole form was submitted while some formatter - // settings were being edited), or have been persisted in $form_state. - $settings = array(); - if (isset($values['settings_edit_form']['settings'])) { - $settings = $values['settings_edit_form']['settings']; - } - elseif (isset($form_state['formatter_settings'][$field_name])) { - $settings = $form_state['formatter_settings'][$field_name]; - } - elseif ($current_options = $display->getComponent($field_name)) { - $settings = $current_options['settings']; - } - - // Only save settings actually used by the selected formatter. - $default_settings = field_info_formatter_settings($values['type']); - $settings = array_intersect_key($settings, $default_settings); - - $display->setComponent($field_name, array( - 'label' => $values['label'], - 'type' => $values['type'], - 'weight' => $values['weight'], - 'settings' => $settings, - )); - } - } - - // Collect data for 'extra' fields. - foreach ($form['#extra'] as $name) { - if ($form_values['fields'][$name]['type'] == 'hidden') { - $display->removeComponent($name); - } - else { - $display->setComponent($name, array( - 'weight' => $form_values['fields'][$name]['weight'], - )); - } - } - - // Save the display. - $display->save(); - - // Handle the 'view modes' checkboxes if present. - 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); - $view_mode_settings = field_view_mode_settings($this->entity_type, $this->bundle); - - foreach ($form_values['view_modes_custom'] as $view_mode => $value) { - if (!empty($value) && empty($view_mode_settings[$view_mode]['status'])) { - // If no display exists for the newly enabled view mode, initialize - // it with those from the 'default' view mode, which were used so - // far. - if (!entity_load('entity_display', $this->entity_type . '.' . $this->bundle . '.' . $view_mode)) { - $display = entity_get_display($this->entity_type, $this->bundle, 'default')->createCopy($view_mode); - $display->save(); - } + protected function getEntityDisplay($mode) { + return entity_get_display($this->entity_type, $this->bundle, $mode); + } - $view_mode_label = $view_modes[$view_mode]['label']; - $path = $this->entityManager->getAdminPath($this->entity_type, $this->bundle) . "/display/$view_mode"; - drupal_set_message(t('The %view_mode mode now uses custom display settings. You might want to configure them.', array('%view_mode' => $view_mode_label, '@url' => url($path)))); - } - $bundle_settings['view_modes'][$view_mode]['status'] = !empty($value); - } + /** + * {@inheritdoc} + */ + protected function getExtraFields() { + return field_info_extra_fields($this->entity_type, $this->bundle, 'display'); + } - // Save updated bundle settings. - field_bundle_settings($this->entity_type, $this->bundle, $bundle_settings); + /** + * {@inheritdoc} + */ + protected function getPlugin($instance, $configuration) { + $plugin = NULL; + + if ($configuration && $configuration['type'] != 'hidden') { + $plugin = $this->pluginManager->getInstance(array( + 'field_definition' => $instance, + 'view_mode' => $this->mode, + 'configuration' => $configuration + )); } - drupal_set_message(t('Your settings have been saved.')); + return $plugin; } /** - * Form submission handler for multistep buttons. + * {@inheritdoc} */ - public function multistepSubmit($form, &$form_state) { - $trigger = $form_state['triggering_element']; - $op = $trigger['#op']; - - switch ($op) { - case 'edit': - // Store the field whose settings are currently being edited. - $field_name = $trigger['#field_name']; - $form_state['formatter_settings_edit'] = $field_name; - break; - - case 'update': - // Store the saved settings, and set the field back to 'non edit' mode. - $field_name = $trigger['#field_name']; - $values = $form_state['values']['fields'][$field_name]['settings_edit_form']['settings']; - $form_state['formatter_settings'][$field_name] = $values; - unset($form_state['formatter_settings_edit']); - break; - - case 'cancel': - // Set the field back to 'non edit' mode. - unset($form_state['formatter_settings_edit']); - break; + protected function getPluginOptions($field_type) { + return parent::getPluginOptions($field_type) + array('hidden' => '- ' . t('Hidden') . ' -'); + } - case 'refresh_table': - // If the currently edited field is one of the rows to be refreshed, set - // it back to 'non edit' mode. - $updated_rows = explode(' ', $form_state['values']['refresh_rows']); - if (isset($form_state['formatter_settings_edit']) && in_array($form_state['formatter_settings_edit'], $updated_rows)) { - unset($form_state['formatter_settings_edit']); - } - break; - } + /** + * {@inheritdoc} + */ + protected function getDefaultPlugin($field_type) { + return $this->fieldTypes[$field_type]['default_formatter']; + } - $form_state['rebuild'] = TRUE; + /** + * {@inheritdoc} + */ + protected function getDisplayModes() { + return entity_get_view_modes($this->entity_type); } /** - * Ajax handler for multistep buttons. + * {@inheritdoc} */ - public function multistepAjax($form, &$form_state) { - $trigger = $form_state['triggering_element']; - $op = $trigger['#op']; + protected function getDisplayModeSettings() { + return field_view_mode_settings($this->entity_type, $this->bundle); + } - // Pick the elements that need to receive the ajax-new-content effect. - switch ($op) { - case 'edit': - $updated_rows = array($trigger['#field_name']); - $updated_columns = array('format'); - break; + /** + * {@inheritdoc} + */ + protected function saveDisplayModeSettings($display_mode_settings) { + $bundle_settings = field_bundle_settings($this->entity_type, $this->bundle); + $bundle_settings['view_modes'] = NestedArray::mergeDeep($bundle_settings['view_modes'], $display_mode_settings); + field_bundle_settings($this->entity_type, $this->bundle, $bundle_settings); + } - case 'update': - case 'cancel': - $updated_rows = array($trigger['#field_name']); - $updated_columns = array('format', 'settings_summary', 'settings_edit'); - break; + /** + * {@inheritdoc + */ + protected function getTableHeader() { + return array( + t('Field'), + t('Weight'), + t('Parent'), + t('Label'), + array('data' => t('Format'), 'colspan' => 3), + ); + } - case 'refresh_table': - $updated_rows = array_values(explode(' ', $form_state['values']['refresh_rows'])); - $updated_columns = array('settings_summary', 'settings_edit'); - break; - } + /** + * {@inheritdoc} + */ + protected function getOverviewPath($mode) { + return $this->entityManager->getAdminPath($this->entity_type, $this->bundle) . "/display/$mode"; + } - foreach ($updated_rows as $name) { - foreach ($updated_columns as $key) { - $element = &$form['fields'][$name][$key]; - $element['#prefix'] = '
' . (isset($element['#prefix']) ? $element['#prefix'] : ''); - $element['#suffix'] = (isset($element['#suffix']) ? $element['#suffix'] : '') . '
'; - } - } + /** + * Returns an array of visibility options for field labels. + * + * @return array + * An array of visibility options. + */ + protected function getFieldLabelOptions() { + return array( + 'above' => t('Above'), + 'inline' => t('Inline'), + 'hidden' => '- ' . t('Hidden') . ' -', + ); + } - // Return the whole table. - return $form['fields']; + /** + * {@inheritdoc} + */ + protected function alterSettingsForm(array &$settings_form, $plugin, FieldInstanceInterface $instance, array $form, array &$form_state) { + $context = array( + 'formatter' => $plugin, + 'field' => $instance->getField(), + 'instance' => $instance, + 'view_mode' => $this->mode, + 'form' => $form, + ); + drupal_alter('field_formatter_settings_form', $settings_form, $form_state, $context); } /** - * Returns the region to which a row in the display overview belongs. - * - * @param array $row - * The row element. - * - * @return string|null - * The region name this row belongs to. + * {@inheritdoc} */ - public function getRowRegion($row) { - switch ($row['#row_type']) { - case 'field': - case 'extra_field': - return ($row['format']['type']['#value'] == 'hidden' ? 'hidden' : 'content'); - } + protected function alterSettingsSummary(array &$summary, $plugin, FieldInstanceInterface $instance) { + $context = array( + 'formatter' => $plugin, + 'field' => $instance->getField(), + 'instance' => $instance, + 'view_mode' => $this->mode, + ); + drupal_alter('field_formatter_settings_summary', $summary, $context); } } diff --git a/core/modules/field_ui/lib/Drupal/field_ui/DisplayOverviewBase.php b/core/modules/field_ui/lib/Drupal/field_ui/DisplayOverviewBase.php new file mode 100644 index 0000000..609bd48 --- /dev/null +++ b/core/modules/field_ui/lib/Drupal/field_ui/DisplayOverviewBase.php @@ -0,0 +1,760 @@ +pluginManager = $plugin_manager; + $this->fieldTypes = field_info_field_types(); + } + + /** + * {@inheritdoc} + */ + public function getRegions() { + return array( + 'content' => array( + 'title' => t('Content'), + 'invisible' => TRUE, + 'message' => t('No field is displayed.') + ), + 'hidden' => array( + 'title' => t('Disabled'), + 'message' => t('No field is hidden.') + ), + ); + } + + /** + * {@inheritdoc} + */ + public function buildForm(array $form, array &$form_state, $entity_type = NULL, $bundle = NULL, $mode = NULL) { + parent::buildForm($form, $form_state, $entity_type, $bundle); + + $this->mode = (isset($mode) ? $mode : 'default'); + + // Gather type information. + $instances = field_info_instances($this->entity_type, $this->bundle); + $extra_fields = $this->getExtraFields(); + $entity_display = $this->getEntityDisplay($this->mode); + + $form_state += array( + 'plugin_settings_edit' => NULL, + ); + + $form += array( + '#entity_type' => $this->entity_type, + '#bundle' => $this->bundle, + '#mode' => $this->mode, + '#fields' => array_keys($instances), + '#extra' => array_keys($extra_fields), + ); + + if (empty($instances) && empty($extra_fields)) { + drupal_set_message(t('There are no fields yet added. You can add new fields on the Manage fields page.', array('@link' => url($this->adminPath . '/fields'))), 'warning'); + return $form; + } + + $table = array( + '#type' => 'field_ui_table', + '#pre_render' => array(array($this, 'tablePreRender')), + '#tree' => TRUE, + '#header' => $this->getTableHeader(), + '#regions' => $this->getRegions(), + '#attributes' => array( + 'class' => array('field-ui-overview'), + 'id' => 'field-display-overview', + ), + // Add Ajax wrapper. + '#prefix' => '
', + '#suffix' => '
', + ); + + // Field rows. + foreach ($instances as $field_id => $instance) { + $table[$field_id] = $this->buildFieldRow($field_id, $instance, $entity_display, $form, $form_state); + } + + // Non-field elements. + foreach ($extra_fields as $field_id => $extra_field) { + $table[$field_id] = $this->buildExtraFieldRow($field_id, $extra_field, $entity_display); + } + + $form['fields'] = $table; + + // Custom display settings. + if ($this->mode == 'default') { + // Only show the settings if there is at least one custom display mode. + if ($display_modes = $this->getDisplayModes()) { + $form['modes'] = array( + '#type' => 'details', + '#title' => t('Custom display settings'), + '#collapsed' => TRUE, + ); + // Collect options and default values for the 'Custom display settings' + // checkboxes. + $options = array(); + $default = array(); + $display_mode_settings = $this->getDisplayModeSettings(); + foreach ($display_modes as $mode_name => $mode_info) { + $options[$mode_name] = $mode_info['label']; + if (!empty($display_mode_settings[$mode_name]['status'])) { + $default[] = $mode_name; + } + } + $form['modes']['display_modes_custom'] = array( + '#type' => 'checkboxes', + '#title' => t('Use custom display settings for the following modes'), + '#options' => $options, + '#default_value' => $default, + ); + } + } + + // In overviews involving nested rows from contributed modules (i.e + // field_group), the 'plugin type' selects can trigger a series of changes + // in child rows. The #ajax behavior is therefore not attached directly to + // the selects, but triggered by the client-side script through a hidden + // #ajax 'Refresh' button. A hidden 'refresh_rows' input tracks the name of + // affected rows. + $form['refresh_rows'] = array('#type' => 'hidden'); + $form['refresh'] = array( + '#type' => 'submit', + '#value' => t('Refresh'), + '#op' => 'refresh_table', + '#submit' => array(array($this, 'multistepSubmit')), + '#ajax' => array( + 'callback' => array($this, 'multistepAjax'), + 'wrapper' => 'field-display-overview-wrapper', + 'effect' => 'fade', + // The button stays hidden, so we hide the Ajax spinner too. Ad-hoc + // spinners will be added manually by the client-side script. + 'progress' => 'none', + ), + '#attributes' => array('class' => array('element-invisible')) + ); + + $form['actions'] = array('#type' => 'actions'); + $form['actions']['submit'] = array('#type' => 'submit', '#value' => t('Save')); + + $form['#attached']['library'][] = array('field_ui', 'drupal.field_ui'); + + // Add tabledrag behavior. + $form['#attached']['drupal_add_tabledrag'][] = array('field-display-overview', 'order', 'sibling', 'field-weight'); + $form['#attached']['drupal_add_tabledrag'][] = array('field-display-overview', 'match', 'parent', 'field-parent', 'field-parent', 'field-name'); + + return $form; + } + + /** + * Builds the table row structure for a single field. + * + * @param string $field_id + * The field ID. + * @param \Drupal\field\FieldInstanceInterface $instance + * The field instance. + * @param \Drupal\entity\EntityDisplayBaseInterface $entity_display + * The entity display. + * @param array $form + * An associative array containing the structure of the form. + * @param array $form_state + * A reference to a keyed array containing the current state of the form. + * + * @return array + * A table row array. + */ + protected function buildFieldRow($field_id, FieldInstanceInterface $instance, EntityDisplayBaseInterface $entity_display, array $form, array &$form_state) { + $field = $instance->getField(); + $display_options = $entity_display->getComponent($field_id); + + $field_row = array( + '#attributes' => array('class' => array('draggable', 'tabledrag-leaf')), + '#row_type' => 'field', + '#region_callback' => array($this, 'getRowRegion'), + '#js_settings' => array( + 'rowHandler' => 'field', + 'defaultPlugin' => $this->getDefaultPlugin($field['type']), + ), + 'human_name' => array( + '#markup' => check_plain($instance['label']), + ), + 'weight' => array( + '#type' => 'textfield', + '#title' => t('Weight for @title', array('@title' => $instance['label'])), + '#title_display' => 'invisible', + '#default_value' => $display_options ? $display_options['weight'] : '0', + '#size' => 3, + '#attributes' => array('class' => array('field-weight')), + ), + 'parent_wrapper' => array( + 'parent' => array( + '#type' => 'select', + '#title' => t('Label display for @title', array('@title' => $instance['label'])), + '#title_display' => 'invisible', + '#options' => drupal_map_assoc(array_keys($this->getRegions())), + '#empty_value' => '', + '#attributes' => array('class' => array('field-parent')), + '#parents' => array('fields', $field_id, 'parent'), + ), + 'hidden_name' => array( + '#type' => 'hidden', + '#default_value' => $field_id, + '#attributes' => array('class' => array('field-name')), + ), + ), + + ); + + $field_row['plugin'] = array( + 'type' => array( + '#type' => 'select', + '#title' => t('Plugin for @title', array('@title' => $instance['label'])), + '#title_display' => 'invisible', + '#options' => $this->getPluginOptions($field['type']), + '#default_value' => $display_options ? $display_options['type'] : 'hidden', + '#parents' => array('fields', $field_id, 'type'), + '#attributes' => array('class' => array('field-plugin-type')), + ), + 'settings_edit_form' => array(), + ); + + // Check the currently selected plugin, and merge persisted values for its + // settings. + if (isset($form_state['values']['fields'][$field_id]['type'])) { + $display_options['type'] = $form_state['values']['fields'][$field_id]['type']; + } + if (isset($form_state['plugin_settings'][$field_id])) { + $display_options['settings'] = $form_state['plugin_settings'][$field_id]; + } + + // Get the corresponding plugin object. + $plugin = $this->getPlugin($instance, $display_options); + + // Base button element for the various plugin settings actions. + $base_button = array( + '#submit' => array(array($this, 'multistepSubmit')), + '#ajax' => array( + 'callback' => array($this, 'multistepAjax'), + 'wrapper' => 'field-display-overview-wrapper', + 'effect' => 'fade', + ), + '#field_name' => $field_id, + ); + + if ($form_state['plugin_settings_edit'] == $field_id) { + // We are currently editing this field's plugin settings. Display the + // settings form and submit buttons. + $field_row['plugin']['settings_edit_form'] = array(); + + if ($plugin) { + // Generate the settings form and allow other modules to alter it. + $settings_form = $plugin->settingsForm($form, $form_state); + $this->alterSettingsForm($settings_form, $plugin, $instance, $form, $form_state); + + if ($settings_form) { + $field_row['plugin']['#cell_attributes'] = array('colspan' => 3); + $field_row['plugin']['settings_edit_form'] = array( + '#type' => 'container', + '#attributes' => array('class' => array('field-plugin-settings-edit-form')), + '#parents' => array('fields', $field_id, 'settings_edit_form'), + 'label' => array( + '#markup' => t('Plugin settings'), + ), + 'settings' => $settings_form, + 'actions' => array( + '#type' => 'actions', + 'save_settings' => $base_button + array( + '#type' => 'submit', + '#name' => $field_id . '_plugin_settings_update', + '#value' => t('Update'), + '#op' => 'update', + ), + 'cancel_settings' => $base_button + array( + '#type' => 'submit', + '#name' => $field_id . '_plugin_settings_cancel', + '#value' => t('Cancel'), + '#op' => 'cancel', + // Do not check errors for the 'Cancel' button, but make sure we + // get the value of the 'plugin type' select. + '#limit_validation_errors' => array(array('fields', $field_id, 'type')), + ), + ), + ); + $field_row['#attributes']['class'][] = 'field-plugin-settings-editing'; + } + } + } + else { + $field_row['settings_summary'] = array(); + $field_row['settings_edit'] = array(); + + if ($plugin) { + // Display a summary of the current plugin settings, and (if the + // summary is not empty) a button to edit them. + $summary = $plugin->settingsSummary(); + + // Allow other modules to alter the summary. + $this->alterSettingsSummary($summary, $plugin, $instance); + + if (!empty($summary)) { + $field_row['settings_summary'] = array( + '#markup' => '
' . implode('
', $summary) . '
', + '#cell_attributes' => array('class' => array('field-plugin-summary-cell')), + ); + $field_row['settings_edit'] = $base_button + array( + '#type' => 'image_button', + '#name' => $field_id . '_settings_edit', + '#src' => 'core/misc/configure-dark.png', + '#attributes' => array('class' => array('field-plugin-settings-edit'), 'alt' => t('Edit')), + '#op' => 'edit', + // Do not check errors for the 'Edit' button, but make sure we get + // the value of the 'plugin type' select. + '#limit_validation_errors' => array(array('fields', $field_id, 'type')), + '#prefix' => '
', + '#suffix' => '
', + ); + } + } + } + + return $field_row; + } + + /** + * Builds the table row structure for a single extra field. + * + * @param string $field_id + * The field ID. + * @param array $extra_field + * The pseudo-field element. + * @param \Drupal\entity\EntityDisplayBaseInterface $entity_display + * The entity display. + * + * @return array + * A table row array. + */ + protected function buildExtraFieldRow($field_id, $extra_field, $entity_display) { + $display_options = $entity_display->getComponent($field_id); + + $extra_field_row = array( + '#attributes' => array('class' => array('draggable', 'tabledrag-leaf')), + '#row_type' => 'extra_field', + '#region_callback' => array($this, 'getRowRegion'), + '#js_settings' => array('rowHandler' => 'field'), + 'human_name' => array( + '#markup' => check_plain($extra_field['label']), + ), + 'weight' => array( + '#type' => 'textfield', + '#title' => t('Weight for @title', array('@title' => $extra_field['label'])), + '#title_display' => 'invisible', + '#default_value' => $display_options ? $display_options['weight'] : 0, + '#size' => 3, + '#attributes' => array('class' => array('field-weight')), + ), + 'parent_wrapper' => array( + 'parent' => array( + '#type' => 'select', + '#title' => t('Parents for @title', array('@title' => $extra_field['label'])), + '#title_display' => 'invisible', + '#options' => drupal_map_assoc(array_keys($this->getRegions())), + '#empty_value' => '', + '#attributes' => array('class' => array('field-parent')), + '#parents' => array('fields', $field_id, 'parent'), + ), + 'hidden_name' => array( + '#type' => 'hidden', + '#default_value' => $field_id, + '#attributes' => array('class' => array('field-name')), + ), + ), + 'plugin' => array( + 'type' => array( + '#type' => 'select', + '#title' => t('Visibility for @title', array('@title' => $extra_field['label'])), + '#title_display' => 'invisible', + '#options' => $this->getExtraFieldVisibilityOptions(), + '#default_value' => $display_options ? 'visible' : 'hidden', + '#parents' => array('fields', $field_id, 'type'), + '#attributes' => array('class' => array('field-plugin-type')), + ), + ), + 'settings_summary' => array(), + 'settings_edit' => array(), + ); + + return $extra_field_row; + } + + /** + * {@inheritdoc} + */ + public function submitForm(array &$form, array &$form_state) { + $form_values = $form_state['values']; + $display = $this->getEntityDisplay($this->mode); + + // Collect data for 'regular' fields. + foreach ($form['#fields'] as $field_name) { + // Retrieve the stored instance settings to merge with the incoming + // values. + $values = $form_values['fields'][$field_name]; + + if ($values['type'] == 'hidden') { + $display->removeComponent($field_name); + } + else { + // Get plugin settings. They lie either directly in submitted form + // values (if the whole form was submitted while some plugin settings + // were being edited), or have been persisted in $form_state. + $settings = array(); + if (isset($values['settings_edit_form']['settings'])) { + $settings = $values['settings_edit_form']['settings']; + } + elseif (isset($form_state['plugin_settings'][$field_name])) { + $settings = $form_state['plugin_settings'][$field_name]; + } + elseif ($current_options = $display->getComponent($field_name)) { + $settings = $current_options['settings']; + } + + // Only save settings actually used by the selected plugin. + $default_settings = $this->pluginManager->getDefaultSettings($values['type']); + $settings = array_intersect_key($settings, $default_settings); + + // Default component values. + $component_values = array( + 'type' => $values['type'], + 'weight' => $values['weight'], + 'settings' => $settings + ); + + // Only formatters have configurable label visibility. + if (isset($values['label'])) { + $component_values['label'] = $values['label']; + } + + $display->setComponent($field_name, $component_values); + } + } + + // Collect data for 'extra' fields. + foreach ($form['#extra'] as $name) { + if ($form_values['fields'][$name]['type'] == 'hidden') { + $display->removeComponent($name); + } + else { + $display->setComponent($name, array( + 'weight' => $form_values['fields'][$name]['weight'], + )); + } + } + + // Save the display. + $display->save(); + + // Handle the 'view modes' checkboxes if present. + if ($this->mode == 'default' && !empty($form_values['display_modes_custom'])) { + $display_modes = $this->getDisplayModes(); + $display_mode_settings = $this->getDisplayModeSettings(); + + $display_mode_bundle_settings = array(); + foreach ($form_values['display_modes_custom'] as $mode => $value) { + if (!empty($value) && empty($display_mode_settings[$mode]['status'])) { + // If no display exists for the newly enabled view mode, initialize + // it with those from the 'default' view mode, which were used so + // far. + if (!entity_load($this->getEntityDisplay('default')->entityType(), $this->entity_type . '.' . $this->bundle . '.' . $mode)) { + $display = $this->getEntityDisplay('default')->createCopy($mode); + $display->save(); + } + + $display_mode_label = $display_modes[$mode]['label']; + $path = $this->getOverviewPath($mode); + drupal_set_message(t('The %display_mode mode now uses custom display settings. You might want to configure them.', array('%display_mode' => $display_mode_label, '@url' => url($path)))); + } + $display_mode_bundle_settings[$mode]['status'] = !empty($value); + } + + // Save updated bundle settings. + $this->saveDisplayModeSettings($display_mode_bundle_settings); + } + + drupal_set_message(t('Your settings have been saved.')); + } + + /** + * Form submission handler for multistep buttons. + */ + public function multistepSubmit($form, &$form_state) { + $trigger = $form_state['triggering_element']; + $op = $trigger['#op']; + + switch ($op) { + case 'edit': + // Store the field whose settings are currently being edited. + $field_name = $trigger['#field_name']; + $form_state['plugin_settings_edit'] = $field_name; + break; + + case 'update': + // Store the saved settings, and set the field back to 'non edit' mode. + $field_name = $trigger['#field_name']; + $values = $form_state['values']['fields'][$field_name]['settings_edit_form']['settings']; + $form_state['plugin_settings'][$field_name] = $values; + unset($form_state['plugin_settings_edit']); + break; + + case 'cancel': + // Set the field back to 'non edit' mode. + unset($form_state['plugin_settings_edit']); + break; + + case 'refresh_table': + // If the currently edited field is one of the rows to be refreshed, set + // it back to 'non edit' mode. + $updated_rows = explode(' ', $form_state['values']['refresh_rows']); + if (isset($form_state['plugin_settings_edit']) && in_array($form_state['plugin_settings_edit'], $updated_rows)) { + unset($form_state['plugin_settings_edit']); + } + break; + } + + $form_state['rebuild'] = TRUE; + } + + /** + * Ajax handler for multistep buttons. + */ + public function multistepAjax($form, &$form_state) { + $trigger = $form_state['triggering_element']; + $op = $trigger['#op']; + + // Pick the elements that need to receive the ajax-new-content effect. + switch ($op) { + case 'edit': + $updated_rows = array($trigger['#field_name']); + $updated_columns = array('plugin'); + break; + + case 'update': + case 'cancel': + $updated_rows = array($trigger['#field_name']); + $updated_columns = array('plugin', 'settings_summary', 'settings_edit'); + break; + + case 'refresh_table': + $updated_rows = array_values(explode(' ', $form_state['values']['refresh_rows'])); + $updated_columns = array('settings_summary', 'settings_edit'); + break; + } + + foreach ($updated_rows as $name) { + foreach ($updated_columns as $key) { + $element = &$form['fields'][$name][$key]; + $element['#prefix'] = '
' . (isset($element['#prefix']) ? $element['#prefix'] : ''); + $element['#suffix'] = (isset($element['#suffix']) ? $element['#suffix'] : '') . '
'; + } + } + + // Return the whole table. + return $form['fields']; + } + + /** + * Returns the entity display object used by this form. + * + * @param string $mode + * A view or form mode. + * + * @return \Drupal\entity\EntityDisplayBaseInterface + * An entity display. + */ + abstract protected function getEntityDisplay($mode); + + /** + * Returns the extra fields of the entity type and bundle used by this form. + * + * @return array + * An array of extra field info, as provided by field_info_extra_fields(). + */ + abstract protected function getExtraFields(); + + /** + * Returns the widget or formatter plugin for a field. + * + * @param \Drupal\field\FieldInstanceInterface $instance + * The field instance. + * @param array $configuration + * The plugin configuration + * + * @return object + * The corresponding plugin. + */ + abstract protected function getPlugin($instance, $configuration); + + /** + * Returns an array of widget or formatter options for a field type. + * + * @param string $field_type + * The name of the field type. + * + * @return array + * An array of widget or formatter options. + */ + protected function getPluginOptions($field_type) { + return $this->pluginManager->getOptions($field_type); + } + + /** + * Returns the ID of the default widget or formatter plugin for a field type. + * + * @param string $field_type + * The field type. + * + * @return string + * The widget or formatter plugin ID. + */ + abstract protected function getDefaultPlugin($field_type); + + /** + * Returns the form or view modes used by this form. + * + * @return array + * An array of form or view mode info. + */ + abstract protected function getDisplayModes(); + + /** + * Returns form or view modes settings for the bundle used by this form. + * + * @return array + * An array of form or view mode settings. + */ + abstract protected function getDisplayModeSettings(); + + /** + * Saves the updated display mode settings. + * + * @param array $display_mode_settings + * An array holding updated form or view mode settings. + */ + abstract protected function saveDisplayModeSettings($display_mode_settings); + + /** + * Returns the region to which a row in the display overview belongs. + * + * @param array $row + * The row element. + * + * @return string|null + * The region name this row belongs to. + */ + public function getRowRegion($row) { + switch ($row['#row_type']) { + case 'field': + case 'extra_field': + return ($row['plugin']['type']['#value'] == 'hidden' ? 'hidden' : 'content'); + } + } + + /** + * Returns an array of visibility options for extra fields. + * + * @return array + * An array of visibility options. + */ + protected function getExtraFieldVisibilityOptions() { + return array( + 'visible' => t('Visible'), + 'hidden' => '- ' . t('Hidden') . ' -', + ); + } + + /** + * Returns an array containing the table headers. + * + * @return array + * The table header. + */ + abstract protected function getTableHeader(); + + /** + * Returns the path of a specific form or view mode form. + * + * @param string $mode + * The form or view mode. + * + * @return string + * An internal path. + */ + abstract protected function getOverviewPath($mode); + + /** + * Alters the widget or formatter settings form. + * + * @param array $settings_form + * The widget or formatter settings form. + * @param object $plugin + * The widget or formatter. + * @param FieldInstanceInterface $instance + * The field instance. + * @param array $form + * The The (entire) configuration form array. + * @param array $form_state + * The form state. + */ + abstract protected function alterSettingsForm(array &$settings_form, $plugin, FieldInstanceInterface $instance, array $form, array &$form_state); + + /** + * Alters the widget or formatter settings summary. + * + * @param array $summary + * The widget or formatter settings summary. + * @param object $plugin + * The widget or formatter. + * @param FieldInstanceInterface $instance + * The field instance. + */ + abstract protected function alterSettingsSummary(array &$summary, $plugin, FieldInstanceInterface $instance); + +} 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 cc5ab8b..943ffaa 100644 --- a/core/modules/field_ui/lib/Drupal/field_ui/FieldOverview.php +++ b/core/modules/field_ui/lib/Drupal/field_ui/FieldOverview.php @@ -8,9 +8,6 @@ namespace Drupal\field_ui; use Drupal\field_ui\OverviewBase; -use Drupal\Core\Entity\EntityManager; -use Drupal\field\Plugin\Type\Widget\WidgetPluginManager; -use Symfony\Component\DependencyInjection\ContainerInterface; /** * Field UI field overview form. @@ -18,101 +15,51 @@ class FieldOverview extends OverviewBase { /** - * The widget plugin manager. - * - * @var \Drupal\field\Plugin\Type\Widget\WidgetPluginManager - */ - protected $widgetManager; - - /** - * Constructs a new DisplayOverview. - * - * @param \Drupal\Core\Entity\EntityManager $entity_manager - * The entity manager. - * @param \Drupal\field\Plugin\Type\Widget\WidgetPluginManager $widget_manager - * The widget plugin manager. - */ - public function __construct(EntityManager $entity_manager, WidgetPluginManager $widget_manager) { - parent::__construct($entity_manager); - - $this->widgetManager = $widget_manager; - } - - /** * {@inheritdoc} */ - public static function create(ContainerInterface $container) { - return new static( - $container->get('plugin.manager.entity'), - $container->get('plugin.manager.field.widget') - ); - } - - /** - * Implements Drupal\field_ui\OverviewBase::getRegions(). - */ public function getRegions() { return array( 'content' => array( 'title' => t('Content'), 'invisible' => TRUE, - 'message' => t('No fields are present yet.'), - ), - 'hidden' => array( - 'title' => t('Hidden'), - 'invisible' => TRUE, - 'message' => t('No fields.'), + // @todo Bring back this message in https://drupal.org/node/1963340. + //'message' => t('No fields are present yet.'), ), ); } /** - * Implements \Drupal\Core\Form\FormInterface::getFormID(). + * {@inheritdoc} */ public function getFormID() { return 'field_ui_field_overview_form'; } /** - * Implements \Drupal\Core\Form\FormInterface::buildForm(). + * {@inheritdoc} */ - public function buildForm(array $form, array &$form_state, $entity_type = NULL, $bundle = NULL, $form_mode = NULL) { + public function buildForm(array $form, array &$form_state, $entity_type = NULL, $bundle = 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(); - } - // Gather bundle information. $instances = field_info_instances($this->entity_type, $this->bundle); $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, '#bundle' => $this->bundle, '#fields' => array_keys($instances), - '#extra' => array_keys($extra_fields), ); $table = array( '#type' => 'field_ui_table', - '#pre_render' => array(array($this, 'tablePreRender')), '#tree' => TRUE, '#header' => array( t('Label'), - t('Weight'), - t('Parent'), t('Machine name'), t('Field type'), - t('Widget'), t('Operations'), ), - '#parent_options' => array(), '#regions' => $this->getRegions(), '#attributes' => array( 'class' => array('field-ui-overview'), @@ -123,39 +70,14 @@ public function buildForm(array $form, array &$form_state, $entity_type = NULL, // Fields. foreach ($instances as $name => $instance) { $field = field_info_field($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', - '#region_callback' => array($this, 'getRowRegion'), + '#attributes' => array( + 'id' => drupal_html_class($name), + ), 'label' => array( '#markup' => check_plain($instance['label']), ), - 'weight' => array( - '#type' => 'textfield', - '#title' => t('Weight for @title', array('@title' => $instance['label'])), - '#title_display' => 'invisible', - '#default_value' => $widget_configuration ? $widget_configuration['weight'] : '0', - '#size' => 3, - '#attributes' => array('class' => array('field-weight')), - ), - 'parent_wrapper' => array( - 'parent' => array( - '#type' => 'select', - '#title' => t('Parent for @title', array('@title' => $instance['label'])), - '#title_display' => 'invisible', - '#options' => $table['#parent_options'], - '#empty_value' => '', - '#attributes' => array('class' => array('field-parent')), - '#parents' => array('fields', $name, 'parent'), - ), - 'hidden_name' => array( - '#type' => 'hidden', - '#default_value' => $name, - '#attributes' => array('class' => array('field-name')), - ), - ), 'field_name' => array( '#markup' => $instance['field_name'], ), @@ -165,12 +87,6 @@ public function buildForm(array $form, array &$form_state, $entity_type = NULL, '#href' => $admin_field_path . '/field', '#options' => array('attributes' => array('title' => t('Edit field settings.'))), ), - 'widget_type' => array( - '#type' => 'link', - '#title' => $widget_configuration ? $widget_types[$widget_configuration['type']]['label'] : $widget_types['hidden']['label'], - '#href' => $admin_field_path . '/widget-type', - '#options' => array('attributes' => array('title' => t('Change widget type.'))), - ), ); $links = array(); @@ -179,6 +95,11 @@ public function buildForm(array $form, array &$form_state, $entity_type = NULL, 'href' => $admin_field_path, 'attributes' => array('title' => t('Edit instance settings.')), ); + $links['field-settings'] = array( + 'title' => t('Field settings'), + 'href' => $admin_field_path . '/field', + 'attributes' => array('title' => t('Edit field settings.')), + ); $links['delete'] = array( 'title' => t('Delete'), 'href' => "$admin_field_path/delete", @@ -195,79 +116,21 @@ public function buildForm(array $form, array &$form_state, $entity_type = NULL, } } - // Non-field elements. - foreach ($extra_fields as $name => $extra_field) { - $table[$name] = array( - '#attributes' => array('class' => array('draggable', 'tabledrag-leaf')), - '#row_type' => 'extra_field', - '#region_callback' => array($this, 'getRowRegion'), - 'label' => array( - '#markup' => check_plain($extra_field['label']), - ), - 'weight' => array( - '#type' => 'textfield', - '#default_value' => $extra_field['weight'], - '#size' => 3, - '#attributes' => array('class' => array('field-weight')), - '#title_display' => 'invisible', - '#title' => t('Weight for @title', array('@title' => $extra_field['label'])), - ), - 'parent_wrapper' => array( - 'parent' => array( - '#type' => 'select', - '#title' => t('Parent for @title', array('@title' => $extra_field['label'])), - '#title_display' => 'invisible', - '#options' => $table['#parent_options'], - '#empty_value' => '', - '#attributes' => array('class' => array('field-parent')), - '#parents' => array('fields', $name, 'parent'), - ), - 'hidden_name' => array( - '#type' => 'hidden', - '#default_value' => $name, - '#attributes' => array('class' => array('field-name')), - ), - ), - 'field_name' => array( - '#markup' => $name, - ), - 'type' => array( - '#markup' => isset($extra_field['description']) ? $extra_field['description'] : '', - '#cell_attributes' => array('colspan' => 2), - ), - 'operations' => array( - '#markup' => '', - ), - ); - } - - // Additional row: add new field. - $max_weight = $entity_form_display->getHighestWeight(); - - // Prepare the widget types to be display as options. - $widget_options = $this->widgetManager->getOptions(); - $widget_type_options = array(); - foreach ($widget_options as $field_type => $widgets) { - $widget_type_options[$field_types[$field_type]['label']] = $widgets; - } - // Gather valid field types. $field_type_options = array(); foreach ($field_types as $name => $field_type) { - // Skip field types which have no widget types, or should not be added via - // user interface. - if (isset($widget_options[$name]) && empty($field_type['no_ui'])) { + // Skip field types which should not be added via user interface. + if (empty($field_type['no_ui'])) { $field_type_options[$name] = $field_type['label']; } } asort($field_type_options); - if ($field_type_options && $widget_type_options) { + // Additional row: add new field. + if ($field_type_options) { $name = '_add_new_field'; $table[$name] = array( - '#attributes' => array('class' => array('draggable', 'tabledrag-leaf', 'add-new')), - '#row_type' => 'add_new_field', - '#region_callback' => array($this, 'getRowRegion'), + '#attributes' => array('class' => array('add-new')), 'label' => array( '#type' => 'textfield', '#title' => t('New field label'), @@ -277,32 +140,6 @@ public function buildForm(array $form, array &$form_state, $entity_type = NULL, '#prefix' => '
' . t('Add new field') .'
', '#suffix' => '
', ), - 'weight' => array( - '#type' => 'textfield', - '#default_value' => $max_weight + 1, - '#size' => 3, - '#title_display' => 'invisible', - '#title' => t('Weight for new field'), - '#attributes' => array('class' => array('field-weight')), - '#prefix' => '
 
', - ), - 'parent_wrapper' => array( - 'parent' => array( - '#type' => 'select', - '#title' => t('Parent for new field'), - '#title_display' => 'invisible', - '#options' => $table['#parent_options'], - '#empty_value' => '', - '#attributes' => array('class' => array('field-parent')), - '#prefix' => '
 
', - '#parents' => array('fields', $name, 'parent'), - ), - 'hidden_name' => array( - '#type' => 'hidden', - '#default_value' => $name, - '#attributes' => array('class' => array('field-name')), - ), - ), 'field_name' => array( '#type' => 'machine_name', '#title' => t('New field name'), @@ -331,17 +168,7 @@ public function buildForm(array $form, array &$form_state, $entity_type = NULL, '#empty_option' => t('- Select a field type -'), '#description' => t('Type of data to store.'), '#attributes' => array('class' => array('field-type-select')), - '#prefix' => '
 
', - ), - 'widget_type' => array( - '#type' => 'select', - '#title' => t('Widget for new field'), - '#title_display' => 'invisible', - '#options' => $widget_type_options, - '#empty_option' => t('- Select a widget -'), - '#description' => t('Form element to edit the data.'), - '#attributes' => array('class' => array('widget-type-select')), - '#cell_attributes' => array('colspan' => 3), + '#cell_attributes' => array('colspan' => 2), '#prefix' => '
 
', ), // Place the 'translatable' property as an explicit value so that @@ -355,7 +182,7 @@ public function buildForm(array $form, array &$form_state, $entity_type = NULL, // Additional row: re-use existing field. $existing_fields = $this->getExistingFieldOptions(); - if ($existing_fields && $widget_type_options) { + if ($existing_fields) { // Build list of options. $existing_field_options = array(); foreach ($existing_fields as $field_name => $info) { @@ -369,7 +196,7 @@ public function buildForm(array $form, array &$form_state, $entity_type = NULL, asort($existing_field_options); $name = '_add_existing_field'; $table[$name] = array( - '#attributes' => array('class' => array('draggable', 'tabledrag-leaf', 'add-new')), + '#attributes' => array('class' => array('add-new')), '#row_type' => 'add_new_field', '#region_callback' => array($this, 'getRowRegion'), 'label' => array( @@ -382,32 +209,6 @@ public function buildForm(array $form, array &$form_state, $entity_type = NULL, '#prefix' => '
' . t('Re-use existing field') .'
', '#suffix' => '
', ), - 'weight' => array( - '#type' => 'textfield', - '#default_value' => $max_weight + 2, - '#size' => 3, - '#title_display' => 'invisible', - '#title' => t('Weight for added field'), - '#attributes' => array('class' => array('field-weight')), - '#prefix' => '
 
', - ), - 'parent_wrapper' => array( - 'parent' => array( - '#type' => 'select', - '#title' => t('Parent for existing field'), - '#title_display' => 'invisible', - '#options' => $table['#parent_options'], - '#empty_value' => '', - '#attributes' => array('class' => array('field-parent')), - '#prefix' => '
 
', - '#parents' => array('fields', $name, 'parent'), - ), - 'hidden_name' => array( - '#type' => 'hidden', - '#default_value' => $name, - '#attributes' => array('class' => array('field-name')), - ), - ), 'field_name' => array( '#type' => 'select', '#title' => t('Existing field to share'), @@ -416,58 +217,29 @@ public function buildForm(array $form, array &$form_state, $entity_type = NULL, '#empty_option' => t('- Select an existing field -'), '#description' => t('Field to share'), '#attributes' => array('class' => array('field-select')), - '#cell_attributes' => array('colspan' => 2), - '#prefix' => '
 
', - ), - 'widget_type' => array( - '#type' => 'select', - '#title' => t('Widget for existing field'), - '#title_display' => 'invisible', - '#options' => $widget_type_options, - '#empty_option' => t('- Select a widget -'), - '#description' => t('Form element to edit the data.'), - '#attributes' => array('class' => array('widget-type-select')), '#cell_attributes' => array('colspan' => 3), '#prefix' => '
 
', ), ); } - $form['fields'] = $table; - // Add AJAX wrapper. - $form['fields']['#prefix'] = '
'; - $form['fields']['#suffix'] = '
'; + // We can set the 'rows_order' element, needed by theme_field_ui_table(), + // here instead of a #pre_render callback because this form doesn't have the + // tabledrag behavior anymore. + foreach (element_children($table) as $name) { + $table['#regions']['content']['rows_order'][] = $name; + } - // This key is used to store the current updated field. - $form_state += array( - 'formatter_settings_edit' => NULL, - ); + $form['fields'] = $table; $form['actions'] = array('#type' => 'actions'); $form['actions']['submit'] = array('#type' => 'submit', '#value' => t('Save')); - $form['#attached']['library'][] = array('field_ui', 'drupal.field_ui'); - - // Add settings for the update selects behavior. - $js_fields = array(); - foreach ($existing_fields as $field_name => $info) { - $js_fields[$field_name] = array('label' => $info['label'], 'type' => $info['type'], 'widget' => $info['widget_type']); - } - - $form['#attached']['js'][] = array( - 'type' => 'setting', - 'data' => array('fields' => $js_fields, 'fieldWidgetTypes' => $widget_options), - ); - - // Add tabledrag behavior. - $form['#attached']['drupal_add_tabledrag'][] = array('field-overview', 'order', 'sibling', 'field-weight'); - $form['#attached']['drupal_add_tabledrag'][] = array('field-overview', 'match', 'parent', 'field-parent', 'field-parent', 'field-name'); - return $form; } /** - * Implements \Drupal\Core\Form\FormInterface::validateForm(). + * {@inheritdoc} */ public function validateForm(array &$form, array &$form_state) { $this->validateAddNew($form, $form_state); @@ -488,7 +260,7 @@ protected function validateAddNew(array $form, array &$form_state) { $field = $form_state['values']['fields']['_add_new_field']; // Validate if any information was provided in the 'add new field' row. - if (array_filter(array($field['label'], $field['field_name'], $field['type'], $field['widget_type']))) { + if (array_filter(array($field['label'], $field['field_name'], $field['type']))) { // Missing label. if (!$field['label']) { form_set_error('fields][_add_new_field][label', t('Add new field: you need to provide a label.')); @@ -511,18 +283,6 @@ protected function validateAddNew(array $form, array &$form_state) { if (!$field['type']) { form_set_error('fields][_add_new_field][type', t('Add new field: you need to select a field type.')); } - - // Missing widget type. - if (!$field['widget_type']) { - form_set_error('fields][_add_new_field][widget_type', t('Add new field: you need to select a widget.')); - } - // Wrong widget type. - elseif ($field['type']) { - $widget_types = $this->widgetManager->getOptions($field['type']); - if (!isset($widget_types[$field['widget_type']])) { - form_set_error('fields][_add_new_field][widget_type', t('Add new field: invalid widget.')); - } - } } } @@ -544,7 +304,7 @@ protected function validateAddExisting(array $form, array &$form_state) { // Validate if any information was provided in the // 're-use existing field' row. - if (array_filter(array($field['label'], $field['field_name'], $field['widget_type']))) { + if (array_filter(array($field['label'], $field['field_name']))) { // Missing label. if (!$field['label']) { form_set_error('fields][_add_existing_field][label', t('Re-use existing field: you need to provide a label.')); @@ -554,18 +314,6 @@ protected function validateAddExisting(array $form, array &$form_state) { if (!$field['field_name']) { form_set_error('fields][_add_existing_field][field_name', t('Re-use existing field: you need to select a field.')); } - - // Missing widget type. - if (!$field['widget_type']) { - form_set_error('fields][_add_existing_field][widget_type', t('Re-use existing field: you need to select a widget.')); - } - // Wrong widget type. - elseif ($field['field_name'] && ($existing_field = field_info_field($field['field_name']))) { - $widget_types = $this->widgetManager->getOptions($existing_field['type']); - if (!isset($widget_types[$field['widget_type']])) { - form_set_error('fields][_add_existing_field][widget_type', t('Re-use existing field: invalid widget.')); - } - } } } } @@ -575,26 +323,6 @@ 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); - - // 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']; - - $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'], - )); - } - - // Save the form display. - $entity_form_display->save(); - $destinations = array(); // Create new field. @@ -620,12 +348,10 @@ public function submitForm(array &$form, array &$form_state) { $new_instance->save(); // Make sure the field is displayed in the 'default' form mode (using - // the configured widget and default settings). + // default widget and settings). It stays hidden for other form modes + // until it is explicitly configured. entity_get_form_display($this->entity_type, $this->bundle, 'default') - ->setComponent($field['field_name'], array( - 'type' => $values['widget_type'], - 'weight' => $values['weight'], - )) + ->setComponent($field['field_name']) ->save(); // Make sure the field is displayed in the 'default' view mode (using @@ -668,12 +394,10 @@ public function submitForm(array &$form, array &$form_state) { $new_instance->save(); // Make sure the field is displayed in the 'default' form mode (using - // the configured widget and default settings). + // default widget and settings). It stays hidden for other form modes + // until it is explicitly configured. entity_get_form_display($this->entity_type, $this->bundle, 'default') - ->setComponent($field['field_name'], array( - 'type' => $values['widget_type'], - 'weight' => $values['weight'], - )) + ->setComponent($field['field_name']) ->save(); // Make sure the field is displayed in the 'default' view mode (using @@ -708,27 +432,6 @@ public function submitForm(array &$form, array &$form_state) { } /** - * Returns the region to which a row in the display overview belongs. - * - * @param array $row - * The row element. - * - * @return string|null - * The region name this row belongs to. - */ - public function getRowRegion($row) { - switch ($row['#row_type']) { - case 'field': - case 'extra_field': - return 'content'; - case 'add_new_field': - // If no input in 'label', assume the row has not been dragged out of the - // 'add new' section. - return (!empty($row['label']['#value']) ? 'content' : 'hidden'); - } - } - - /** * Returns an array of existing fields to be added to a bundle. * * @return array @@ -754,13 +457,11 @@ protected function getExistingFieldOptions() { && !field_info_instance($this->entity_type, $field['field_name'], $this->bundle) && (empty($field['entity_types']) || in_array($this->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' => $widget['type'], ); } } 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 index 393997a..56871fe 100644 --- a/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldInstanceEditForm.php +++ b/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldInstanceEditForm.php @@ -104,11 +104,6 @@ public function buildForm(array $form, array &$form_state, FieldInstanceInterfac $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); @@ -143,7 +138,7 @@ public function validateForm(array &$form, array &$form_state) { // Extract the 'default value'. $items = array(); - $entity_form_display->getWidget($this->instance->getField()->id)->extractFormValues($entity, Language::LANGCODE_NOT_SPECIFIED, $items, $element, $form_state); + $entity_form_display->getRenderer($this->instance->getField()->id)->extractFormValues($entity, Language::LANGCODE_NOT_SPECIFIED, $items, $element, $form_state); // Get the field state. $field_state = field_form_get_state($element['#parents'], $field_name, Language::LANGCODE_NOT_SPECIFIED, $form_state); @@ -162,7 +157,7 @@ public function validateForm(array &$form, array &$form_state) { field_form_set_state($element['#parents'], $field_name, Language::LANGCODE_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::LANGCODE_NOT_SPECIFIED, $items, $element, $form_state); + $entity_form_display->getRenderer($this->instance->getField()->id)->flagErrors($entity, Language::LANGCODE_NOT_SPECIFIED, $items, $element, $form_state); } } } @@ -180,17 +175,11 @@ public function submitForm(array &$form, array &$form_state) { // Extract field values. $items = array(); - $entity_form_display->getWidget($this->instance->getField()->id)->extractFormValues($entity, Language::LANGCODE_NOT_SPECIFIED, $items, $element, $form_state); + $entity_form_display->getRenderer($this->instance->getField()->id)->extractFormValues($entity, Language::LANGCODE_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; @@ -199,10 +188,6 @@ public function submitForm(array &$form, array &$form_state) { 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'] = $this->getNextDestination(); } @@ -243,7 +228,8 @@ protected function getDefaultValueWidget($field, array &$form, &$form_state) { // 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') { + // @todo Clean this up since we don't have $this->instance['widget'] anymore. + if ($this->instance['widget']['type'] == 'hidden') { $field_type = field_info_field_types($field['type']); $default_widget = $this->widgetManager->getDefinition($field_type['default_widget']); @@ -260,7 +246,7 @@ protected function getDefaultValueWidget($field, array &$form, &$form_state) { if (!empty($this->instance['default_value'])) { $items = (array) $this->instance['default_value']; } - $element += $entity_form_display->getWidget($this->instance->getField()->id)->form($entity, Language::LANGCODE_NOT_SPECIFIED, $items, $element, $form_state); + $element += $entity_form_display->getRenderer($this->instance->getField()->id)->form($entity, Language::LANGCODE_NOT_SPECIFIED, $items, $element, $form_state); return $element; } 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 deleted file mode 100644 index 4f44947..0000000 --- a/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldWidgetTypeForm.php +++ /dev/null @@ -1,99 +0,0 @@ -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 = $this->instance->getField(); - $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' => $this->widgetManager->getOptions($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'] = $this->getNextDestination(); - } - -} diff --git a/core/modules/field_ui/lib/Drupal/field_ui/FormDisplayOverview.php b/core/modules/field_ui/lib/Drupal/field_ui/FormDisplayOverview.php new file mode 100644 index 0000000..d2ab86a --- /dev/null +++ b/core/modules/field_ui/lib/Drupal/field_ui/FormDisplayOverview.php @@ -0,0 +1,161 @@ +get('plugin.manager.entity'), + $container->get('plugin.manager.field.widget') + ); + } + + /** + * {@inheritdoc} + */ + public function getFormID() { + return 'field_ui_form_display_overview_form'; + } + + /** + * {@inheritdoc} + */ + protected function buildFieldRow($field_id, FieldInstanceInterface $instance, EntityDisplayBaseInterface $entity_display, array $form, array &$form_state) { + $field_row = parent::buildFieldRow($field_id, $instance, $entity_display, $form, $form_state); + + // Update the (invisible) title of the 'plugin' column. + $field_row['plugin']['#title'] = t('Formatter for @title', array('@title' => $instance['label'])); + if (!empty($field_row['plugin']['settings_edit_form']) && ($plugin = $entity_display->getRenderer($field_id))) { + $plugin_type_info = $plugin->getPluginDefinition(); + $field_row['plugin']['settings_edit_form']['label']['#markup'] = t('Widget settings:') . ' ' . $plugin_type_info['label'] . ''; + } + + return $field_row; + } + + /** + * {@inheritdoc} + */ + protected function getEntityDisplay($mode) { + return entity_get_form_display($this->entity_type, $this->bundle, $mode); + } + + /** + * {@inheritdoc} + */ + protected function getExtraFields() { + return field_info_extra_fields($this->entity_type, $this->bundle, 'form'); + } + + /** + * {@inheritdoc} + */ + protected function getPlugin($instance, $configuration) { + $plugin = NULL; + + if ($configuration && $configuration['type'] != 'hidden') { + $plugin = $this->pluginManager->getInstance(array( + 'field_definition' => $instance, + 'form_mode' => $this->mode, + 'configuration' => $configuration + )); + } + + return $plugin; + } + + /** + * {@inheritdoc} + */ + protected function getDefaultPlugin($field_type) { + return $this->fieldTypes[$field_type]['default_widget']; + } + + /** + * {@inheritdoc} + */ + protected function getDisplayModes() { + return entity_get_form_modes($this->entity_type); + } + + /** + * {@inheritdoc} + */ + protected function getDisplayModeSettings() { + return field_form_mode_settings($this->entity_type, $this->bundle); + } + + /** + * {@inheritdoc} + */ + protected function saveDisplayModeSettings($display_mode_settings) { + $bundle_settings = field_bundle_settings($this->entity_type, $this->bundle); + $bundle_settings['form_modes'] = NestedArray::mergeDeep($bundle_settings['form_modes'], $display_mode_settings); + field_bundle_settings($this->entity_type, $this->bundle, $bundle_settings); + } + + /** + * {@inheritdoc + */ + protected function getTableHeader() { + return array( + t('Field'), + t('Weight'), + t('Parent'), + array('data' => t('Widget'), 'colspan' => 3), + ); + } + + /** + * {@inheritdoc} + */ + protected function getOverviewPath($mode) { + return $this->entityManager->getAdminPath($this->entity_type, $this->bundle) . "/form-display/$mode"; + } + + /** + * {@inheritdoc} + */ + protected function alterSettingsForm(array &$settings_form, $plugin, FieldInstanceInterface $instance, array $form, array &$form_state) { + $context = array( + 'widget' => $plugin, + 'field' => $instance->getField(), + 'instance' => $instance, + 'form_mode' => $this->mode, + 'form' => $form, + ); + drupal_alter('field_widget_settings_form', $settings_form, $form_state, $context); + } + + /** + * {@inheritdoc} + */ + protected function alterSettingsSummary(array &$summary, $plugin, FieldInstanceInterface $instance) { + $context = array( + 'widget' => $plugin, + 'field' => $instance->getField(), + 'instance' => $instance, + 'form_mode' => $this->mode, + ); + drupal_alter('field_widget_settings_summary', $summary, $context); + } + +} 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 ecf8de4..67b742b 100644 --- a/core/modules/field_ui/lib/Drupal/field_ui/OverviewBase.php +++ b/core/modules/field_ui/lib/Drupal/field_ui/OverviewBase.php @@ -83,6 +83,11 @@ public function buildForm(array $form, array &$form_state, $entity_type = NULL, $this->entity_type = $entity_type; $this->bundle = $bundle; $this->adminPath = $this->entityManager->getAdminPath($this->entity_type, $this->bundle); + + // When displaying the form, make sure the list of fields is up-to-date. + if (empty($form_state['post'])) { + field_info_cache_clear(); + } } /** 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 index 934a56e..2d0c9c8 100644 --- a/core/modules/field_ui/lib/Drupal/field_ui/Routing/RouteSubscriber.php +++ b/core/modules/field_ui/lib/Drupal/field_ui/Routing/RouteSubscriber.php @@ -68,13 +68,6 @@ public function routes(RouteBuildEvent $event) { $collection->add("field_ui.field_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}/delete", array('_form' => '\Drupal\field_ui\Form\FieldDeleteForm'), array('_permission' => 'administer ' . $entity_type . ' fields') @@ -94,6 +87,24 @@ public function routes(RouteBuildEvent $event) { $collection->add("field_ui.overview.$entity_type", $route); $route = new Route( + "$path/form-display", + array('_form' => '\Drupal\field_ui\FormDisplayOverview') + $defaults, + array('_permission' => 'administer ' . $entity_type . ' form display') + ); + $collection->add("field_ui.form_display_overview.$entity_type", $route); + + foreach (entity_get_form_modes($entity_type) as $form_mode => $form_mode_info) { + $route = new Route( + "$path/form-display/$form_mode", + array( + '_form' => '\Drupal\field_ui\FormDisplayOverview', + 'mode' => $form_mode, + ) + $defaults, + array('_field_ui_form_mode_access' => 'administer ' . $entity_type . ' form display')); + $collection->add("field_ui.form_display_overview.$entity_type.$form_mode", $route); + } + + $route = new Route( "$path/display", array('_form' => '\Drupal\field_ui\DisplayOverview') + $defaults, array('_permission' => 'administer ' . $entity_type . ' display') @@ -105,7 +116,7 @@ public function routes(RouteBuildEvent $event) { "$path/display/$view_mode", array( '_form' => '\Drupal\field_ui\DisplayOverview', - 'view_mode' => $view_mode, + '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/FieldUIRouteTest.php b/core/modules/field_ui/lib/Drupal/field_ui/Tests/FieldUIRouteTest.php index 32d2a71..669b58e 100644 --- a/core/modules/field_ui/lib/Drupal/field_ui/Tests/FieldUIRouteTest.php +++ b/core/modules/field_ui/lib/Drupal/field_ui/Tests/FieldUIRouteTest.php @@ -46,7 +46,9 @@ public function setUp() { */ public function testFieldUIRoutes() { $this->drupalGet('field-ui-test-no-bundle/manage/fields'); - $this->assertText('No fields are present yet.'); + // @todo Bring back this assertion in https://drupal.org/node/1963340. + // @see \Drupal\field_ui\FieldOverview::getRegions() + //$this->assertText('No fields are present yet.'); $this->drupalGet('admin/structure/types/manage/article/fields'); $this->assertTitle('Article | Drupal'); diff --git a/core/modules/field_ui/lib/Drupal/field_ui/Tests/FieldUiTestBase.php b/core/modules/field_ui/lib/Drupal/field_ui/Tests/FieldUiTestBase.php index bc44cbd..4ba0242 100644 --- a/core/modules/field_ui/lib/Drupal/field_ui/Tests/FieldUiTestBase.php +++ b/core/modules/field_ui/lib/Drupal/field_ui/Tests/FieldUiTestBase.php @@ -67,10 +67,8 @@ function fieldUIAddNewField($bundle_path, $initial_edit, $field_edit = array(), // Use 'test_field' field type by default. $initial_edit += array( 'fields[_add_new_field][type]' => 'test_field', - 'fields[_add_new_field][widget_type]' => 'test_field_widget', ); $label = $initial_edit['fields[_add_new_field][label]']; - $field_name = $initial_edit['fields[_add_new_field][field_name]']; // First step : 'Add new field' on the 'Manage fields' page. $this->drupalPost("$bundle_path/fields", $initial_edit, t('Save')); @@ -101,12 +99,7 @@ function fieldUIAddNewField($bundle_path, $initial_edit, $field_edit = array(), * form). */ function fieldUIAddExistingField($bundle_path, $initial_edit, $instance_edit = array()) { - // Use 'test_field_widget' by default. - $initial_edit += array( - 'fields[_add_existing_field][widget_type]' => 'test_field_widget', - ); $label = $initial_edit['fields[_add_existing_field][label]']; - $field_name = $initial_edit['fields[_add_existing_field][field_name]']; // First step : 'Re-use existing field' on the 'Manage fields' page. $this->drupalPost("$bundle_path/fields", $initial_edit, t('Save')); diff --git a/core/modules/field_ui/lib/Drupal/field_ui/Tests/ManageDisplayTest.php b/core/modules/field_ui/lib/Drupal/field_ui/Tests/ManageDisplayTest.php index 55028d1..4f918c4 100644 --- a/core/modules/field_ui/lib/Drupal/field_ui/Tests/ManageDisplayTest.php +++ b/core/modules/field_ui/lib/Drupal/field_ui/Tests/ManageDisplayTest.php @@ -81,17 +81,17 @@ function testFormatterUI() { // Click on the formatter settings button to open the formatter settings // form. - $this->drupalPostAJAX(NULL, array(), "field_test_formatter_settings_edit"); + $this->drupalPostAJAX(NULL, array(), "field_test_settings_edit"); // Assert that the field added in // field_test_field_formatter_settings_form_alter() is present. $fieldname = 'fields[field_test][settings_edit_form][settings][field_test_formatter_settings_form_alter]'; $this->assertField($fieldname, 'The field added in hook_field_formatter_settings_form_alter() is present on the settings form.'); $edit = array($fieldname => 'foo'); - $this->drupalPostAJAX(NULL, $edit, "field_test_formatter_settings_update"); + $this->drupalPostAJAX(NULL, $edit, "field_test_plugin_settings_update"); // Confirm that the settings are updated on the settings form. - $this->drupalPostAJAX(NULL, array(), "field_test_formatter_settings_edit"); + $this->drupalPostAJAX(NULL, array(), "field_test_settings_edit"); $this->assertFieldByName($fieldname, 'foo'); } @@ -137,7 +137,7 @@ function testViewModeCustom() { // Specialize the 'rss' mode, check that the field is displayed the same. $edit = array( - "view_modes_custom[rss]" => TRUE, + "display_modes_custom[rss]" => TRUE, ); $this->drupalPost('admin/structure/types/manage/' . $this->type . '/display', $edit, t('Save')); $this->assertNodeViewText($node, 'rss', $output['field_test_with_prepare_view'], "The field is displayed as expected in newly specialized 'rss' mode."); @@ -153,14 +153,14 @@ function testViewModeCustom() { // Set the view mode back to 'default', check that the field is displayed // accordingly. $edit = array( - "view_modes_custom[rss]" => FALSE, + "display_modes_custom[rss]" => FALSE, ); $this->drupalPost('admin/structure/types/manage/' . $this->type . '/display', $edit, t('Save')); $this->assertNodeViewText($node, 'rss', $output['field_test_with_prepare_view'], "The field is displayed as expected when 'rss' mode is set back to 'default' settings."); // Specialize the view mode again. $edit = array( - "view_modes_custom[rss]" => TRUE, + "display_modes_custom[rss]" => TRUE, ); $this->drupalPost('admin/structure/types/manage/' . $this->type . '/display', $edit, t('Save')); // Check that the previous settings for the view mode have been kept. 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 c0f5471..c4bb806 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 @@ -88,7 +88,6 @@ function manageFieldsPage($type = '') { t('Label'), t('Machine name'), t('Field type'), - t('Widget'), t('Operations'), ); foreach ($table_headers as $table_header) { @@ -144,7 +143,6 @@ function updateField() { $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, ); $this->drupalPost(NULL, $edit, t('Save settings')); @@ -235,13 +233,9 @@ function assertFieldSettings($bundle, $field_name, $string = 'dummy test string' $field = field_info_field($field_name); $this->assertTrue($field['settings']['test_field_setting'] == $string, 'Field settings were found.'); - // Assert instance and widget settings. + // Assert instance settings. $instance = field_info_instance($entity_type, $field_name, $bundle); $this->assertTrue($instance['settings']['test_instance_setting'] == $string, 'Field instance 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.'); } /** @@ -381,11 +375,11 @@ function testLockedField() { // Check that the links for edit and delete are not present. $this->drupalGet('admin/structure/types/manage/' . $this->type . '/fields'); - $locked = $this->xpath('//tr[@id=:field_name]/td[7]', array(':field_name' => $field->id())); + $locked = $this->xpath('//tr[@id=:field_name]/td[4]', array(':field_name' => $field->id())); $this->assertTrue(in_array('Locked', $locked), 'Field is marked as Locked in the UI'); - $edit_link = $this->xpath('//tr[@id=:field_name]/td[7]', array(':field_name' => $field->id())); + $edit_link = $this->xpath('//tr[@id=:field_name]/td[4]', array(':field_name' => $field->id())); $this->assertFalse(in_array('edit', $edit_link), 'Edit option for locked field is not present the UI'); - $delete_link = $this->xpath('//tr[@id=:field_name]/td[8]', array(':field_name' => $field->id())); + $delete_link = $this->xpath('//tr[@id=:field_name]/td[4]', array(':field_name' => $field->id())); $this->assertFalse(in_array('delete', $delete_link), 'Delete option for locked field is not present the UI'); } @@ -424,15 +418,6 @@ function testHiddenFields() { $bundle_path = 'admin/structure/types/manage/article/fields/'; $this->drupalGet($bundle_path); $this->assertFalse($this->xpath('//select[@id="edit-add-existing-field-field-name"]//option[@value=:field_name]', array(':field_name' => $field_name)), "The 're-use existing field' select respects field types 'no_ui' property."); - - // Remove the form display component to check the fallback label. - entity_get_form_display('node', $this->type, 'default') - ->removeComponent($field_name) - ->save(); - - $this->drupalGet('admin/structure/types/manage/' . $this->type . '/fields/'); - $this->assertLinkByHref(url('admin/structure/types/manage/' . $this->type . '/fields/node.' . $this->type . '.' . $field_name . '/widget-type')); - $this->assertLink('- Hidden -'); } /** @@ -458,7 +443,6 @@ function testDuplicateFieldName() { 'fields[_add_new_field][field_name]' => 'tags', 'fields[_add_new_field][label]' => $this->randomName(), 'fields[_add_new_field][type]' => 'taxonomy_term_reference', - 'fields[_add_new_field][widget_type]' => 'options_select', ); $url = 'admin/structure/types/manage/' . $this->type . '/fields'; $this->drupalPost($url, $edit, t('Save')); @@ -468,49 +452,6 @@ function testDuplicateFieldName() { } /** - * Tests changing the widget used by a field. - */ - function testWidgetChange() { - $url_fields = 'admin/structure/types/manage/article/fields'; - $url_tags_widget = $url_fields . '/node.article.field_tags/widget-type'; - - // Check that the field_tags field currently uses the 'options_select' - // widget. - $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); - $link = current($this->xpath('//a[contains(@href, :href)]', array(':href' => $url_tags_widget))); - $this->assertEqual((string) $link, 'Select list'); - - // Go to the 'Widget type' form and check that the correct widget is - // selected. - $this->drupalGet($url_tags_widget); - $this->assertFieldByXPath("//select[@name='widget_type']", 'options_select'); - - // Change the widget type. - $edit = array( - 'widget_type' => 'options_buttons', - ); - $this->drupalPost(NULL, $edit, t('Continue')); - - // Check that the "Manage fields" page shows the correct widget type. - $link = current($this->xpath('//a[contains(@href, :href)]', array(':href' => $url_tags_widget))); - $this->assertEqual((string) $link, 'Check boxes/radio buttons'); - - // Check that the field uses the newly set widget. - field_cache_clear(); - $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. - $this->drupalGet($url_tags_widget); - $this->assertFieldByXPath("//select[@name='widget_type']", 'options_buttons'); - } - - /** * Tests that deletion removes fields and instances as expected for a term. */ function testDeleteTaxonomyField() { diff --git a/core/modules/file/lib/Drupal/file/Plugin/field/widget/FileWidget.php b/core/modules/file/lib/Drupal/file/Plugin/field/widget/FileWidget.php index 4603288..fb012f7 100644 --- a/core/modules/file/lib/Drupal/file/Plugin/field/widget/FileWidget.php +++ b/core/modules/file/lib/Drupal/file/Plugin/field/widget/FileWidget.php @@ -51,6 +51,15 @@ public function settingsForm(array $form, array &$form_state) { /** * {@inheritdoc} + */ + public function settingsSummary() { + $summary = array(); + $summary[] = t('Progress indicator: @progress_indicator', array('@progress_indicator' => $this->getSetting('progress_indicator'))); + return $summary; + } + + /** + * Overrides \Drupal\field\Plugin\Type\Widget\WidgetBase::formMultipleElements(). * * Special handling for draggable multiple widgets and 'add more' button. */ diff --git a/core/modules/file/lib/Drupal/file/Tests/FileFieldRSSContentTest.php b/core/modules/file/lib/Drupal/file/Tests/FileFieldRSSContentTest.php index a3b86ea..086db41 100644 --- a/core/modules/file/lib/Drupal/file/Tests/FileFieldRSSContentTest.php +++ b/core/modules/file/lib/Drupal/file/Tests/FileFieldRSSContentTest.php @@ -48,7 +48,7 @@ function testFileFieldRSSContent() { // RSS display must be added manually. $this->drupalGet("admin/structure/types/manage/$type_name/display"); $edit = array( - "view_modes_custom[rss]" => '1', + "display_modes_custom[rss]" => '1', ); $this->drupalPost(NULL, $edit, t('Save')); diff --git a/core/modules/file/lib/Drupal/file/Tests/FileFieldWidgetTest.php b/core/modules/file/lib/Drupal/file/Tests/FileFieldWidgetTest.php index 702c8a2..1720e28 100644 --- a/core/modules/file/lib/Drupal/file/Tests/FileFieldWidgetTest.php +++ b/core/modules/file/lib/Drupal/file/Tests/FileFieldWidgetTest.php @@ -253,7 +253,6 @@ function testPrivateFileComment() { 'fields[_add_new_field][label]' => $label = $this->randomName(), 'fields[_add_new_field][field_name]' => $name = strtolower($this->randomName()), 'fields[_add_new_field][type]' => 'file', - 'fields[_add_new_field][widget_type]' => 'file_generic', ); $this->drupalPost('admin/structure/types/manage/article/comment/fields', $edit, t('Save')); $edit = array('field[settings][uri_scheme]' => 'private'); diff --git a/core/modules/image/lib/Drupal/image/Plugin/field/widget/ImageWidget.php b/core/modules/image/lib/Drupal/image/Plugin/field/widget/ImageWidget.php index 3ad6e0f..d0ae8fa 100644 --- a/core/modules/image/lib/Drupal/image/Plugin/field/widget/ImageWidget.php +++ b/core/modules/image/lib/Drupal/image/Plugin/field/widget/ImageWidget.php @@ -33,7 +33,7 @@ class ImageWidget extends FileWidget { /** - * Overrides \Drupal\file\Plugin\field\widget\FileWidget::settingsForm(). + * {@inheritdoc} */ public function settingsForm(array $form, array &$form_state) { $element = parent::settingsForm($form, $form_state); @@ -53,6 +53,30 @@ public function settingsForm(array $form, array &$form_state) { /** * {@inheritdoc} + */ + public function settingsSummary() { + $summary = parent::settingsSummary(); + + $image_styles = image_style_options(FALSE); + // Unset possible 'No defined styles' option. + unset($image_styles['']); + // Styles could be lost because of enabled/disabled modules that defines + // their styles in code. + $image_style_setting = $this->getSetting('preview_image_style'); + if (isset($image_styles[$image_style_setting])) { + $preview_image_style = t('Preview image style: @style', array('@style' => $image_styles[$image_style_setting])); + } + else { + $preview_image_style = t('Original image'); + } + + array_unshift($summary, $preview_image_style); + + return $summary; + } + + /** + * Overrides \Drupal\file\Plugin\field\widget\FileWidget::formMultipleElements(). * * Special handling for draggable multiple widgets and 'add more' button. */ diff --git a/core/modules/link/lib/Drupal/link/Plugin/field/widget/LinkWidget.php b/core/modules/link/lib/Drupal/link/Plugin/field/widget/LinkWidget.php index f960613..d5bc6fd 100644 --- a/core/modules/link/lib/Drupal/link/Plugin/field/widget/LinkWidget.php +++ b/core/modules/link/lib/Drupal/link/Plugin/field/widget/LinkWidget.php @@ -105,6 +105,30 @@ public function settingsForm(array $form, array &$form_state) { } /** + * {@inheritdoc} + */ + public function settingsSummary() { + $summary = array(); + + $placeholder_title = $this->getSetting('placeholder_title'); + $placeholder_url = $this->getSetting('placeholder_url'); + if (empty($placeholder_title) && empty($placeholder_url)) { + $summary[] = t('No placeholders'); + } + else { + if (!empty($placeholder_title)) { + $summary[] = t('Title placeholder: @placeholder_title', array('@placeholder_title' => $placeholder_title)); + } + if (!empty($placeholder_url)) { + $summary[] = t('URL placeholder: @placeholder_url', array('@placeholder_url' => $placeholder_url)); + } + } + + return $summary; + } + + + /** * Form element validation handler for link_field_widget_form(). * * Conditionally requires the link title if a URL value was filled in. diff --git a/core/modules/link/lib/Drupal/link/Tests/LinkFieldUITest.php b/core/modules/link/lib/Drupal/link/Tests/LinkFieldUITest.php index f8ff160..910ff14 100644 --- a/core/modules/link/lib/Drupal/link/Tests/LinkFieldUITest.php +++ b/core/modules/link/lib/Drupal/link/Tests/LinkFieldUITest.php @@ -51,7 +51,6 @@ function testFieldUI() { 'fields[_add_new_field][label]' => $label, 'fields[_add_new_field][field_name]' => $field_name, 'fields[_add_new_field][type]' => 'link', - 'fields[_add_new_field][widget_type]' => 'link_default', ); $this->drupalPost("$type_path/fields", $edit, t('Save')); // Proceed to the Edit (field instance settings) page. diff --git a/core/modules/node/content_types.inc b/core/modules/node/content_types.inc index 156576b..32c7f4b 100644 --- a/core/modules/node/content_types.inc +++ b/core/modules/node/content_types.inc @@ -30,6 +30,13 @@ function node_overview_types() { 'weight' => 0, ); } + if ($field_ui && user_access('administer node form display')) { + $links['fields'] = array( + 'title' => t('Manage form display'), + 'href' => 'admin/structure/types/manage/' . $type->type . '/form-display', + 'weight' => 0, + ); + } if ($field_ui && user_access('administer node display')) { $links['display'] = array( 'title' => t('Manage display'), diff --git a/core/modules/node/lib/Drupal/node/Tests/NodeTypeInitialLanguageTest.php b/core/modules/node/lib/Drupal/node/Tests/NodeTypeInitialLanguageTest.php index 27e31c6..1a0b7ed 100644 --- a/core/modules/node/lib/Drupal/node/Tests/NodeTypeInitialLanguageTest.php +++ b/core/modules/node/lib/Drupal/node/Tests/NodeTypeInitialLanguageTest.php @@ -32,7 +32,7 @@ public static function getInfo() { function setUp() { parent::setUp(); - $web_user = $this->drupalCreateUser(array('bypass node access', 'administer content types', 'administer node fields', 'administer node display', 'administer languages', 'administer site configuration')); + $web_user = $this->drupalCreateUser(array('bypass node access', 'administer content types', 'administer node fields', 'administer node form display', 'administer node display', 'administer languages', 'administer site configuration')); $this->drupalLogin($web_user); } @@ -75,10 +75,11 @@ function testNodeTypeInitialLanguageDefaults() { $this->assertField('langcode', 'Language is selectable on node add/edit page when language not hidden.'); $this->assertOptionSelected('edit-langcode', 'hu', 'The initial language is the site default on the node add page after the site default language is changed.'); - // Tests if the language field can be rearranged on the manage fields tab. - $this->drupalGet('admin/structure/types/manage/article/fields'); + // Tests if the language field can be rearranged on the manage form display + // tab. + $this->drupalGet('admin/structure/types/manage/article/form-display'); $language_field = $this->xpath('//*[@id="language"]'); - $this->assert(!empty($language_field), 'Language field is visible on manage fields tab.'); + $this->assert(!empty($language_field), 'Language field is visible on manage form display tab.'); // Tests if the language field can be rearranged on the manage display tab. $this->drupalGet('admin/structure/types/manage/article/display'); diff --git a/core/modules/number/lib/Drupal/number/Plugin/field/widget/NumberWidget.php b/core/modules/number/lib/Drupal/number/Plugin/field/widget/NumberWidget.php index 7cca027..e2ad8fd 100644 --- a/core/modules/number/lib/Drupal/number/Plugin/field/widget/NumberWidget.php +++ b/core/modules/number/lib/Drupal/number/Plugin/field/widget/NumberWidget.php @@ -46,6 +46,23 @@ public function settingsForm(array $form, array &$form_state) { /** * {@inheritdoc} */ + public function settingsSummary() { + $summary = array(); + + $placeholder = $this->getSetting('placeholder'); + if (!empty($placeholder)) { + $summary[] = t('Placeholder: @placeholder', array('@placeholder' => $placeholder)); + } + else { + $summary[] = t('No placeholder'); + } + + return $summary; + } + + /** + * {@inheritdoc} + */ public function formElement(array $items, $delta, array $element, $langcode, array &$form, array &$form_state) { $value = isset($items[$delta]['value']) ? $items[$delta]['value'] : NULL; $field_settings = $this->getFieldSettings(); diff --git a/core/modules/number/lib/Drupal/number/Tests/NumberFieldTest.php b/core/modules/number/lib/Drupal/number/Tests/NumberFieldTest.php index f9a817f..da399f8 100644 --- a/core/modules/number/lib/Drupal/number/Tests/NumberFieldTest.php +++ b/core/modules/number/lib/Drupal/number/Tests/NumberFieldTest.php @@ -151,7 +151,6 @@ function testNumberIntegerField() { 'fields[_add_new_field][label]'=> $label, 'fields[_add_new_field][field_name]' => $field_name, 'fields[_add_new_field][type]' => 'number_integer', - 'fields[_add_new_field][widget_type]' => 'number', ); $this->drupalPost(NULL, $edit, t('Save')); diff --git a/core/modules/options/lib/Drupal/options/Plugin/field/widget/OnOffWidget.php b/core/modules/options/lib/Drupal/options/Plugin/field/widget/OnOffWidget.php index fd0d230..25f9865 100644 --- a/core/modules/options/lib/Drupal/options/Plugin/field/widget/OnOffWidget.php +++ b/core/modules/options/lib/Drupal/options/Plugin/field/widget/OnOffWidget.php @@ -44,6 +44,18 @@ public function settingsForm(array $form, array &$form_state) { /** * {@inheritdoc} */ + public function settingsSummary() { + $summary = array(); + + $display_label = $this->getSetting('display_label'); + $summary[] = t('Use field label: @display_label', array('@display_label' => ($display_label ? t('Yes') : 'No'))); + + return $summary; + } + + /** + * {@inheritdoc} + */ public function formElement(array $items, $delta, array $element, $langcode, array &$form, array &$form_state) { $element = parent::formElement($items, $delta, $element, $langcode, $form, $form_state); diff --git a/core/modules/options/lib/Drupal/options/Tests/OptionsWidgetsTest.php b/core/modules/options/lib/Drupal/options/Tests/OptionsWidgetsTest.php index f206d0e..781e535 100644 --- a/core/modules/options/lib/Drupal/options/Tests/OptionsWidgetsTest.php +++ b/core/modules/options/lib/Drupal/options/Tests/OptionsWidgetsTest.php @@ -502,7 +502,7 @@ function testOnOffCheckbox() { $this->drupalCreateContentType(array('type' => 'page', 'name' => 'Basic page')); // Create admin user. - $admin_user = $this->drupalCreateUser(array('access content', 'administer content types', 'administer node fields', 'administer taxonomy')); + $admin_user = $this->drupalCreateUser(array('access content', 'administer content types', 'administer node fields', 'administer node form display', 'administer taxonomy')); $this->drupalLogin($admin_user); // Create a test field instance. @@ -522,39 +522,37 @@ function testOnOffCheckbox() { )) ->save(); - // Go to the edit page and check if the default settings works as expected - $fieldEditUrl = 'admin/structure/types/manage/page/fields/node.page.bool'; + // Go to the form display page and check if the default settings works as + // expected. + $fieldEditUrl = 'admin/structure/types/manage/page/form-display'; $this->drupalGet($fieldEditUrl); + $field_name = $this->bool['field_name']; + // Click on the widget settings button to open the widget settings form. + $this->drupalPostAJAX(NULL, array(), $field_name . "_settings_edit"); + $this->assertText( 'Use field label instead of the "On value" as label', t('Display setting checkbox available.') ); - $this->assertFieldByXPath( - '*//label[@for="edit-' . $this->bool['field_name'] . '-und" and text()="MyOnValue"]', - TRUE, - t('Default case shows "On value"') - ); + // Enable setting. + $edit = array('fields[' . $field_name . '][settings_edit_form][settings][display_label]' => 1); + $this->drupalPostAJAX(NULL, $edit, $field_name . "_plugin_settings_update"); + $this->drupalPost(NULL, NULL, 'Save'); - // Enable setting - $edit = array('instance[widget][settings][display_label]' => 1); - // Save the new Settings - $this->drupalPost($fieldEditUrl, $edit, t('Save settings')); - - // Go again to the edit page and check if the setting - // is stored and has the expected effect + // Go again to the form display page and check if the setting + // is stored and has the expected effect. $this->drupalGet($fieldEditUrl); + $this->assertText('Use field label: Yes', 'Checking the display settings checkbox updated the value.'); + + $this->drupalPostAJAX(NULL, array(), $field_name . "_settings_edit"); $this->assertText( 'Use field label instead of the "On value" as label', t('Display setting checkbox is available') ); - $this->assertFieldChecked( - 'edit-instance-widget-settings-display-label', - t('Display settings checkbox checked') - ); $this->assertFieldByXPath( - '*//label[@for="edit-' . $this->bool['field_name'] . '-und" and text()="' . $this->bool['field_name'] . '"]', + '*//input[@id="edit-fields-' . $field_name . '-settings-edit-form-settings-display-label" and @value="1"]', TRUE, t('Display label changes label of the checkbox') ); diff --git a/core/modules/overlay/overlay.module b/core/modules/overlay/overlay.module index b158083..ca8ce28 100644 --- a/core/modules/overlay/overlay.module +++ b/core/modules/overlay/overlay.module @@ -99,7 +99,7 @@ function overlay_field_extra_fields() { /** * Implements hook_form_FORM_ID_alter(). */ -function overlay_form_user_profile_form_alter(&$form, &$form_state) { +function overlay_form_user_form_alter(&$form, &$form_state) { $account = $form_state['controller']->getEntity(); if (user_access('access overlay', $account)) { $account_data = Drupal::service('user.data')->get('overlay', $account->id(), 'enabled'); 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 f049ac8..80f6eea 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Form/ArbitraryRebuildTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Form/ArbitraryRebuildTest.php @@ -46,12 +46,9 @@ function setUp() { 'field_name' => 'test_multiple', 'bundle' => 'user', 'label' => 'Test a multiple valued field', - 'settings' => array( - 'user_register_form' => TRUE, - ), ); field_create_instance($instance); - entity_get_form_display('user', 'user', 'default') + entity_get_form_display('user', 'user', 'register') ->setComponent('test_multiple', array( 'type' => 'text_textfield', 'weight' => 0, 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 c2d6593..4f2c99a 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Menu/BreadcrumbTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Menu/BreadcrumbTest.php @@ -149,10 +149,6 @@ function testBreadCrumbs() { "admin/structure/types/manage/$type/fields" => t('Manage fields'), ); $this->assertBreadcrumb("admin/structure/types/manage/$type/fields/node.$type.body", $trail); - $trail += array( - "admin/structure/types/manage/$type/fields/node.$type.body" => t('Body'), - ); - $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 ab3e56d..0d65411 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Upgrade/FieldUpgradePathTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Upgrade/FieldUpgradePathTest.php @@ -170,7 +170,9 @@ function testFieldUpgradeToConfig() { 'settings' => array( 'display_summary' => TRUE, 'text_processing' => 1, - 'user_register_form' => FALSE, + // This setting has been removed in field_update_8005(). We keep it + // here, commented out, to prove that the upgrade path is working. + //'user_register_form' => FALSE, ), 'status' => 1, 'langcode' => 'und', diff --git a/core/modules/system/system.module b/core/modules/system/system.module index 6a1f766..495870d 100644 --- a/core/modules/system/system.module +++ b/core/modules/system/system.module @@ -2543,7 +2543,7 @@ function system_custom_theme() { /** * Implements hook_form_FORM_ID_alter(). */ -function system_form_user_profile_form_alter(&$form, &$form_state) { +function system_form_user_form_alter(&$form, &$form_state) { if (config('system.timezone')->get('user.configurable')) { system_user_timezone($form, $form_state); } @@ -2595,7 +2595,7 @@ function system_user_timezone(&$form, &$form_state) { $form['timezone']['timezone'] = array( '#type' => 'select', '#title' => t('Time zone'), - '#default_value' => isset($account->timezone) ? $account->timezone : ($account->uid == $user->uid ? config('system.date')->get('timezone.default') : ''), + '#default_value' => isset($account->timezone) ? $account->timezone : ($account->uid == $user->uid ? config('system.timezone')->get('default') : ''), '#options' => system_time_zones($account->uid != $user->uid), '#description' => t('Select the desired local time and time zone. Dates and times throughout this site will be displayed using this time zone.'), ); diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/field/widget/TaxonomyAutocompleteWidget.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/field/widget/TaxonomyAutocompleteWidget.php index c0ef1f6..596f745 100644 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/field/widget/TaxonomyAutocompleteWidget.php +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/field/widget/TaxonomyAutocompleteWidget.php @@ -47,6 +47,24 @@ public function settingsForm(array $form, array &$form_state) { /** * {@inheritdoc} */ + public function settingsSummary() { + $summary = array(); + + $summary[] = t('Textfield size: !size', array('!size' => $this->getSetting('size'))); + $placeholder = $this->getSetting('placeholder'); + if (!empty($placeholder)) { + $summary[] = t('Placeholder: @placeholder', array('@placeholder' => $placeholder)); + } + else { + $summary[] = t('No placeholder'); + } + + return $summary; + } + + /** + * {@inheritdoc} + */ public function formElement(array $items, $delta, array $element, $langcode, array &$form, array &$form_state) { $tags = array(); foreach ($items as $item) { diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/RssTest.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/RssTest.php index 118e813..5e88d62 100644 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/RssTest.php +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/RssTest.php @@ -81,7 +81,7 @@ function testTaxonomyRss() { // RSS display must be added manually. $this->drupalGet("admin/structure/types/manage/article/display"); $edit = array( - "view_modes_custom[rss]" => '1', + "display_modes_custom[rss]" => '1', ); $this->drupalPost(NULL, $edit, t('Save')); diff --git a/core/modules/telephone/lib/Drupal/telephone/Plugin/field/widget/TelephoneDefaultWidget.php b/core/modules/telephone/lib/Drupal/telephone/Plugin/field/widget/TelephoneDefaultWidget.php index 66884fe..444dc3a 100644 --- a/core/modules/telephone/lib/Drupal/telephone/Plugin/field/widget/TelephoneDefaultWidget.php +++ b/core/modules/telephone/lib/Drupal/telephone/Plugin/field/widget/TelephoneDefaultWidget.php @@ -28,6 +28,7 @@ */ class TelephoneDefaultWidget extends WidgetBase { + /** * Implements Drupal\field\Plugin\Type\Widget\WidgetInterface::settingsForm(). */ @@ -42,6 +43,23 @@ public function settingsForm(array $form, array &$form_state) { } /** + * {@inheritdoc} + */ + public function settingsSummary() { + $summary = array(); + + $placeholder = $this->getSetting('placeholder'); + if (!empty($placeholder)) { + $summary[] = t('Placeholder: @placeholder', array('@placeholder' => $placeholder)); + } + else { + $summary[] = t('No placeholder'); + } + + return $summary; + } + + /** * Implements \Drupal\field\Plugin\Type\Widget\WidgetInterface::formElement(). */ public function formElement(array $items, $delta, array $element, $langcode, array &$form, array &$form_state) { diff --git a/core/modules/text/lib/Drupal/text/Plugin/field/widget/TextareaWidget.php b/core/modules/text/lib/Drupal/text/Plugin/field/widget/TextareaWidget.php index 2fe37a0..72eff19 100644 --- a/core/modules/text/lib/Drupal/text/Plugin/field/widget/TextareaWidget.php +++ b/core/modules/text/lib/Drupal/text/Plugin/field/widget/TextareaWidget.php @@ -52,6 +52,21 @@ public function settingsForm(array $form, array &$form_state) { /** * {@inheritdoc} */ + public function settingsSummary() { + $summary = array(); + + $summary[] = t('Number of rows: !rows', array('!rows' => $this->getSetting('rows'))); + $placeholder = $this->getSetting('placeholder'); + if (!empty($placeholder)) { + $summary[] = t('Placeholder: @placeholder', array('@placeholder' => $placeholder)); + } + + return $summary; + } + + /** + * {@inheritdoc} + */ public function formElement(array $items, $delta, array $element, $langcode, array &$form, array &$form_state) { $main_widget = $element + array( '#type' => 'textarea', diff --git a/core/modules/text/lib/Drupal/text/Plugin/field/widget/TextareaWithSummaryWidget.php b/core/modules/text/lib/Drupal/text/Plugin/field/widget/TextareaWithSummaryWidget.php index b98ce32..84f2f87 100644 --- a/core/modules/text/lib/Drupal/text/Plugin/field/widget/TextareaWithSummaryWidget.php +++ b/core/modules/text/lib/Drupal/text/Plugin/field/widget/TextareaWithSummaryWidget.php @@ -32,6 +32,32 @@ class TextareaWithSummaryWidget extends TextareaWidget { /** * {@inheritdoc} */ + public function settingsForm(array $form, array &$form_state) { + $element = parent::settingsForm($form, $form_state); + $element['summary_rows'] = array( + '#type' => 'number', + '#title' => t('Summary rows'), + '#default_value' => $this->getSetting('summary_rows'), + '#required' => TRUE, + '#min' => 1, + ); + return $element; + } + + /** + * {@inheritdoc} + */ + public function settingsSummary() { + $summary = parent::settingsSummary(); + + $summary[] = t('Number of summary rows: !rows', array('!rows' => $this->getSetting('summary_rows'))); + + return $summary; + } + + /** + * {@inheritdoc} + */ function formElement(array $items, $delta, array $element, $langcode, array &$form, array &$form_state) { $element = parent::formElement($items, $delta, $element, $langcode, $form, $form_state); diff --git a/core/modules/text/lib/Drupal/text/Plugin/field/widget/TextfieldWidget.php b/core/modules/text/lib/Drupal/text/Plugin/field/widget/TextfieldWidget.php index 7012c75..5319aab 100644 --- a/core/modules/text/lib/Drupal/text/Plugin/field/widget/TextfieldWidget.php +++ b/core/modules/text/lib/Drupal/text/Plugin/field/widget/TextfieldWidget.php @@ -52,6 +52,21 @@ public function settingsForm(array $form, array &$form_state) { /** * {@inheritdoc} */ + public function settingsSummary() { + $summary = array(); + + $summary[] = t('Textfield size: !size', array('!size' => $this->getSetting('size'))); + $placeholder = $this->getSetting('placeholder'); + if (!empty($placeholder)) { + $summary[] = t('Placeholder: @placeholder', array('@placeholder' => $placeholder)); + } + + return $summary; + } + + /** + * {@inheritdoc} + */ public function formElement(array $items, $delta, array $element, $langcode, array &$form, array &$form_state) { $main_widget = $element + array( '#type' => 'textfield', diff --git a/core/modules/user/config/entity.form_mode.user.register.yml b/core/modules/user/config/entity.form_mode.user.register.yml new file mode 100644 index 0000000..222bac7 --- /dev/null +++ b/core/modules/user/config/entity.form_mode.user.register.yml @@ -0,0 +1,4 @@ +id: user.register +label: Register +status: '1' +targetEntityType: user 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 0f2e28a..4870892 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 @@ -28,12 +28,11 @@ * "access" = "Drupal\user\UserAccessController", * "render" = "Drupal\Core\Entity\EntityRenderController", * "form" = { - * "profile" = "Drupal\user\ProfileFormController", + * "default" = "Drupal\user\ProfileFormController", * "register" = "Drupal\user\RegisterFormController" * }, * "translation" = "Drupal\user\ProfileTranslationController" * }, - * default_operation = "profile", * base_table = "users", * uri_callback = "user_uri", * route_base_path = "admin/config/people/accounts", diff --git a/core/modules/user/lib/Drupal/user/RegisterFormController.php b/core/modules/user/lib/Drupal/user/RegisterFormController.php index ceecd65..59b73c2 100644 --- a/core/modules/user/lib/Drupal/user/RegisterFormController.php +++ b/core/modules/user/lib/Drupal/user/RegisterFormController.php @@ -40,14 +40,8 @@ public function form(array $form, array &$form_state) { // Start with the default user account fields. $form = parent::form($form, $form_state, $account); - // Attach field widgets, and hide the ones where the 'user_register_form' - // setting is not on. + // Attach field widgets. field_attach_form($account, $form, $form_state); - foreach (field_info_instances('user', 'user') as $field_name => $instance) { - if (empty($instance['settings']['user_register_form'])) { - $form[$field_name]['#access'] = FALSE; - } - } if ($admin) { // Redirect back to page which initiated the create request; usually diff --git a/core/modules/user/lib/Drupal/user/Tests/UserRegistrationTest.php b/core/modules/user/lib/Drupal/user/Tests/UserRegistrationTest.php index 8da2c2b..e832451 100644 --- a/core/modules/user/lib/Drupal/user/Tests/UserRegistrationTest.php +++ b/core/modules/user/lib/Drupal/user/Tests/UserRegistrationTest.php @@ -207,7 +207,6 @@ function testRegistrationWithUserFields() { 'label' => 'Some user field', 'bundle' => 'user', 'required' => TRUE, - 'settings' => array('user_register_form' => FALSE), ); field_create_instance($instance); entity_get_form_display('user', 'user', 'default') @@ -219,8 +218,9 @@ function testRegistrationWithUserFields() { $this->assertNoText($instance['label'], 'The field does not appear on user registration form'); // Have the field appear on the registration form. - $instance['settings']['user_register_form'] = TRUE; - field_update_instance($instance); + entity_get_form_display('user', 'user', 'register') + ->setComponent('test_user_field', array('type' => 'test_field_widget')) + ->save(); $this->drupalGet('user/register'); $this->assertText($instance['label'], 'The field appears on user registration form'); diff --git a/core/modules/user/user.install b/core/modules/user/user.install index 94c9d5d..5d4c3a2 100644 --- a/core/modules/user/user.install +++ b/core/modules/user/user.install @@ -1050,5 +1050,20 @@ function user_update_8017() { } /** + * Create the 'register' form mode. + */ +function user_update_8018() { + $uuid = new Uuid(); + + config("entity.form_mode.user.register") + ->set('id', "user.register") + ->set('uuid', $uuid->generate()) + ->set('label', 'Register') + ->set('targetEntityType', 'user') + ->set('status', '1') + ->save(); +} + +/** * @} End of "addtogroup updates-7.x-to-8.x". */ diff --git a/core/modules/user/user.module b/core/modules/user/user.module index e0ef6e6..301f0a1 100644 --- a/core/modules/user/user.module +++ b/core/modules/user/user.module @@ -201,19 +201,6 @@ function user_picture_enabled() { } /** - * Implements hook_field_info_alter(). - */ -function user_field_info_alter(&$info) { - // Add the 'user_register_form' instance setting to all field types. - foreach ($info as $field_type => &$field_type_info) { - $field_type_info += array('instance_settings' => array()); - $field_type_info['instance_settings'] += array( - 'user_register_form' => FALSE, - ); - } -} - -/** * Implements hook_field_extra_fields(). */ function user_field_extra_fields() { @@ -1017,7 +1004,7 @@ function user_menu() { $items['user/%user/edit'] = array( 'title' => 'Edit', 'page callback' => 'entity_get_form', - 'page arguments' => array(1, 'profile'), + 'page arguments' => array(1), 'access callback' => 'entity_page_access', 'access arguments' => array(1, 'update'), 'type' => MENU_LOCAL_TASK, @@ -2358,55 +2345,6 @@ function user_node_load($nodes, $types) { } /** - * Implements hook_form_FORM_ID_alter() for 'field_ui_field_instance_edit_form'. - * - * Add a checkbox for the 'user_register_form' instance settings on the 'Edit - * field instance' form. - */ -function user_form_field_ui_field_instance_edit_form_alter(&$form, &$form_state, $form_id) { - $instance = $form_state['instance']; - - if ($instance['entity_type'] == 'user') { - $form['instance']['settings']['user_register_form'] = array( - '#type' => 'checkbox', - '#title' => t('Display on user registration form.'), - '#description' => t("This is compulsory for 'required' fields."), - // Field instances created in D7 beta releases before the setting was - // introduced might be set as 'required' and 'not shown on user_register - // form'. We make sure the checkbox comes as 'checked' for those. - '#default_value' => $instance['settings']['user_register_form'] || $instance['required'], - // Display just below the 'required' checkbox. - '#weight' => $form['instance']['required']['#weight'] + .1, - // Disabled when the 'required' checkbox is checked. - '#states' => array( - 'enabled' => array('input[name="instance[required]"]' => array('checked' => FALSE)), - ), - // Checked when the 'required' checkbox is checked. This is done through - // a custom behavior, since the #states system would also synchronize on - // uncheck. - '#attached' => array( - 'library' => array(array('user', 'drupal.user')), - ), - ); - - array_unshift($form['#submit'], 'user_form_field_ui_field_instance_edit_form_submit'); - } -} - -/** - * Additional submit handler for the 'Edit field instance' form. - * - * Make sure the 'user_register_form' setting is set for required fields. - */ -function user_form_field_ui_field_instance_edit_form_submit($form, &$form_state) { - $instance = $form_state['values']['instance']; - - if (!empty($instance['required'])) { - form_set_value($form['instance']['settings']['user_register_form'], 1, $form_state); - } -} - -/** * Implements hook_modules_installed(). */ function user_modules_installed($modules) { diff --git a/core/themes/seven/style.css b/core/themes/seven/style.css index 052d0f1..e2ffe33 100644 --- a/core/themes/seven/style.css +++ b/core/themes/seven/style.css @@ -1043,23 +1043,23 @@ h1#overlay-title { /* Field UI */ -#field-display-overview input.field-formatter-settings-edit { +#field-display-overview input.field-plugin-settings-edit { margin: 0; padding: 1px 8px; } -#field-display-overview tr.field-formatter-settings-changed { +#field-display-overview tr.field-plugin-settings-changed { background: #ffffbb; } #field-display-overview tr.drag { background: #ffee77; } -#field-display-overview tr.field-formatter-settings-editing { +#field-display-overview tr.field-plugin-settings-editing { background: #d5e9f2; } -#field-display-overview .field-formatter-settings-edit-form .form-item { +#field-display-overview .field-plugin-settings-edit-form .form-item { margin: 10px 0; } -#field-display-overview .field-formatter-settings-edit-form .form-submit { +#field-display-overview .field-plugin-settings-edit-form .form-submit { margin-bottom: 0; }