diff --git a/core/lib/Drupal/Core/Field/FieldDefinition.php b/core/lib/Drupal/Core/Field/FieldDefinition.php index 0829820..c133039 100644 --- a/core/lib/Drupal/Core/Field/FieldDefinition.php +++ b/core/lib/Drupal/Core/Field/FieldDefinition.php @@ -188,6 +188,38 @@ public function setPropertyConstraints($name, array $constraints) { } /** + * @todo + * + * @param $context + * @param array $options + */ + public function setDisplayOptions($context, array $options, $configurable = FALSE) { + $this->definition['display'][$context] = array( + 'options' => $options, + 'configurable' => $configurable, + ); + return $this; + } + + /** + * @todo + * + * @param $context + * + * @return array + */ + public function getDisplayOptions($context) { + return isset($this->definition['display'][$context]) ? $this->definition['display'][$context]['options'] : array(); + } + + /** + * {@inheritdoc} + */ + public function isDisplayConfigurable($context) { + return isset($this->definition['display'][$context]) ? $this->definition['display'][$context]['configurable'] : FALSE; + } + + /** * {@inheritdoc} */ public function isConfigurable() { diff --git a/core/lib/Drupal/Core/Field/FieldDefinitionInterface.php b/core/lib/Drupal/Core/Field/FieldDefinitionInterface.php index 76f0ef9..93a6bb7 100644 --- a/core/lib/Drupal/Core/Field/FieldDefinitionInterface.php +++ b/core/lib/Drupal/Core/Field/FieldDefinitionInterface.php @@ -135,6 +135,17 @@ public function isTranslatable(); public function isConfigurable(); /** + * Determines whether the disolay for the field is configurable. + * + * @param string $context + * The display context. Either 'view' or 'form'. + * + * @return bool + * TRUE if the display for this field is configurable. + */ + public function isDisplayConfigurable($context); + + /** * Determines whether the field is queryable via QueryInterface. * * @return bool diff --git a/core/modules/entity/lib/Drupal/entity/Entity/EntityDisplay.php b/core/modules/entity/lib/Drupal/entity/Entity/EntityDisplay.php index 3fe0743..4a988be 100644 --- a/core/modules/entity/lib/Drupal/entity/Entity/EntityDisplay.php +++ b/core/modules/entity/lib/Drupal/entity/Entity/EntityDisplay.php @@ -33,11 +33,15 @@ class EntityDisplay extends EntityDisplayBase implements EntityDisplayInterface { /** + * @{inheritdoc} + */ + var $displayContext = 'view'; + + /** * {@inheritdoc} */ public function __construct(array $values, $entity_type) { $this->pluginManager = \Drupal::service('plugin.manager.field.formatter'); - $this->displayContext = 'display'; parent::__construct($values, $entity_type); } diff --git a/core/modules/entity/lib/Drupal/entity/Entity/EntityFormDisplay.php b/core/modules/entity/lib/Drupal/entity/Entity/EntityFormDisplay.php index c4637f7..b60270d 100644 --- a/core/modules/entity/lib/Drupal/entity/Entity/EntityFormDisplay.php +++ b/core/modules/entity/lib/Drupal/entity/Entity/EntityFormDisplay.php @@ -33,11 +33,15 @@ class EntityFormDisplay extends EntityDisplayBase implements EntityFormDisplayInterface, \Serializable { /** + * @{inheritdoc} + */ + var $displayContext = 'form'; + + /** * {@inheritdoc} */ public function __construct(array $values, $entity_type) { $this->pluginManager = \Drupal::service('plugin.manager.field.widget'); - $this->displayContext = 'form'; parent::__construct($values, $entity_type); } diff --git a/core/modules/entity/lib/Drupal/entity/EntityDisplayBase.php b/core/modules/entity/lib/Drupal/entity/EntityDisplayBase.php index e96959f..2e69ad8 100644 --- a/core/modules/entity/lib/Drupal/entity/EntityDisplayBase.php +++ b/core/modules/entity/lib/Drupal/entity/EntityDisplayBase.php @@ -9,6 +9,9 @@ use Drupal\Core\Config\Entity\ConfigEntityBase; use Drupal\Core\Entity\ContentEntityInterface; +use Drupal\Core\Entity\EntityStorageControllerInterface; +use Drupal\Core\Field\FieldDefinitionInterface; +use Drupal\Core\Field\FieldDefinition; /** * Base class for config entity types that store configuration for entity forms @@ -45,15 +48,11 @@ public $bundle; /** - * A partial entity, created via _field_create_entity_from_ids() from - * $targetEntityType and $bundle. + * A list of field definitions eligible for configuration in this display. * - * @var \Drupal\Core\Entity\EntityInterface - * - * @todo Remove when getFieldDefinition() is fixed to not need it. - * https://drupal.org/node/2114707 + * @var \Drupal\Core\Field\FieldDefinitionInterface][ */ - private $targetEntity; + protected $fieldDefinitions; /** * View or form mode to be displayed. @@ -78,6 +77,13 @@ protected $content = array(); /** + * List of components that are set to be hidden. + * + * @var array + */ + protected $hidden = array(); + + /** * The original view or form mode that was requested (case of view/form modes * being configured to fall back to the 'default' display). * @@ -129,6 +135,8 @@ public function __construct(array $values, $entity_type) { parent::__construct($values, $entity_type); $this->originalMode = $this->mode; + + $this->init(); } /** @@ -141,15 +149,19 @@ public function id() { /** * {@inheritdoc} */ - public function save() { - $return = parent::save(); + public function preSave(EntityStorageControllerInterface $storage_controller, $update = TRUE) { + // Sort elements by weight before saving. + uasort($this->content, 'Drupal\Component\Utility\SortArray::sortByWeightElement'); + } + /** + * {@inheritdoc} + */ + public function postSave(EntityStorageControllerInterface $storage_controller, $update = TRUE) { // Reset the render cache for the target entity type. if (\Drupal::entityManager()->hasController($this->targetEntityType, 'view_builder')) { \Drupal::entityManager()->getViewBuilder($this->targetEntityType)->resetCache(); } - - return $return; } /** @@ -163,16 +175,55 @@ public function getExportProperties() { 'bundle', 'mode', 'content', + 'hidden', 'status', ); $properties = array(); foreach ($names as $name) { $properties[$name] = $this->get($name); } + return $properties; } /** + * @todo + */ + protected function init() { + // Fill in defaults for extra fields. + $extra_fields = field_info_extra_fields($this->targetEntityType, $this->bundle, ($this->displayContext == 'view' ? 'display' : $this->displayContext)); + foreach ($extra_fields as $name => $definition) { + if (!isset($this->content[$name]) && !isset($this->hidden[$name])) { + if (!isset($definition['visible']) || $definition['visible'] == TRUE) { + $this->content[$name] = array( + 'weight' => $definition['weight'] + ); + } + else { + $this->hidden[$name] = TRUE; + } + } + } + // Fill in defaults for fields. + $fields = $this->getFieldDefinitions(); + foreach ($fields as $name => $definition) { + if (!isset($this->content[$name]) && !isset($this->hidden[$name])) { + if ($definition instanceof FieldDefinition && $options = $definition->getDisplayOptions($this->displayContext)) { + if (empty($options['type']) || $options['type'] != 'hidden') { + $this->content[$name] = $this->pluginManager->prepareConfiguration($definition->getType(), $options); + } + else { + $this->hidden[$name] = TRUE; + } + } + else { + $this->hidden[$name] = TRUE; + } + } + } + } + + /** * {@inheritdoc} */ public function createCopy($mode) { @@ -185,64 +236,14 @@ public function createCopy($mode) { * {@inheritdoc} */ public function getComponents() { - $result = array(); - foreach ($this->content as $name => $options) { - if (!isset($options['visible']) || $options['visible'] == TRUE) { - unset($options['visible']); - $result[$name] = $options; - } - } - return $result; + return $this->content; } /** * {@inheritdoc} */ public function getComponent($name) { - // Until https://drupal.org/node/2144919 allows base fields to be configured - // in the UI, many base fields are also still registered as "extra fields" - // to keep appearing in the "Manage (form) display" screens. - // - Field UI still treats them as "base fields", saving only the weight - // and visibility flag in the EntityDisplay. - // - For some of them (e.g. node title), the custom rendering code has been - // removed in favor of regular widgets/formatters. Their display options - // are "upgraded" to those of a field (widget/formatter + settings) at - // runtime using hook_entity_display_alter(). - // The getComponent() / setComponent() methods handle this by treating - // components as "extra fields" if they are registered as such, *and* if - // their display options contain no 'type' entry specifying a widget or - // formatter. - // @todo Cleanup after https://drupal.org/node/2144919 is fixed. - $extra_fields = field_info_extra_fields($this->targetEntityType, $this->bundle, $this->displayContext); - if (isset($extra_fields[$name]) && !isset($this->content[$name]['type'])) { - // If we have explicit settings, return an array or NULL depending on - // visibility. - if (isset($this->content[$name])) { - if ($this->content[$name]['visible']) { - return array( - 'weight' => $this->content[$name]['weight'], - ); - } - else { - return NULL; - } - } - - // If no explicit settings for the extra field, look at the default - // visibility in its definition. - $definition = $extra_fields[$name]; - if (!isset($definition['visible']) || $definition['visible'] == TRUE) { - return array( - 'weight' => $definition['weight'] - ); - } - else { - return NULL; - } - } - elseif (isset($this->content[$name])) { - return $this->content[$name]; - } + return isset($this->content[$name]) ? $this->content[$name] : NULL; } /** @@ -254,20 +255,15 @@ public function setComponent($name, array $options = array()) { $max = $this->getHighestWeight(); $options['weight'] = isset($max) ? $max + 1 : 0; } - // See remark in getComponent(). - // @todo Cleanup after https://drupal.org/node/2144919 is fixed. - $extra_fields = field_info_extra_fields($this->targetEntityType, $this->bundle, $this->displayContext); - if (isset($extra_fields[$name]) && !isset($options['type'])) { - $options['visible'] = TRUE; - } - elseif ($field_definition = $this->getFieldDefinition($name)) { + + // For a field, fill in default options. + if ($field_definition = $this->getFieldDefinition($name)) { $options = $this->pluginManager->prepareConfiguration($field_definition->getType(), $options); } - // Clear the persisted plugin, if any. - unset($this->plugins[$name]); - $this->content[$name] = $options; + unset($this->hidden[$name]); + unset($this->plugins[$name]); return $this; } @@ -276,22 +272,8 @@ public function setComponent($name, array $options = array()) { * {@inheritdoc} */ public function removeComponent($name) { - // See remark in getComponent(). - // @todo Cleanup after https://drupal.org/node/2144919 is fixed. - $extra_fields = field_info_extra_fields($this->targetEntityType, $this->bundle, $this->displayContext); - if (isset($extra_fields[$name]) && !isset($this->content[$name]['type'])) { - // 'Extra fields' are exposed in hooks and can appear at any given time. - // Therefore we store extra fields that are explicitly being hidden, so - // that we can differenciate with those that are simply not configured - // yet. - $this->content[$name] = array( - 'visible' => FALSE, - ); - } - else { - unset($this->content[$name]); - } - + $this->hidden[$name] = TRUE; + unset($this->content[$name]); unset($this->plugins[$name]); return $this; @@ -320,14 +302,37 @@ public function getHighestWeight() { * Returns the field definition of a field. */ protected function getFieldDefinition($field_name) { - // @todo Replace this entire implementation with - // \Drupal::entityManager()->getFieldDefinition() when it can hand the - // $instance objects - https://drupal.org/node/2114707 - if (!isset($this->targetEntity)) { - $this->targetEntity = _field_create_entity_from_ids((object) array('entity_type' => $this->targetEntityType, 'bundle' => $this->bundle, 'entity_id' => NULL)); - } - if (($this->targetEntity instanceof ContentEntityInterface) && $this->targetEntity->hasField($field_name)) { - return $this->targetEntity->get($field_name)->getFieldDefinition(); + $definitions = $this->getFieldDefinitions(); + return isset($definitions[$field_name]) ? $definitions[$field_name] : NULL; + } + + /** + * Returns the definitions of the fields that are candidate for display. + */ + protected function getFieldDefinitions() { + if (!isset($this->fieldDefinitions)) { + // @todo Replace this with \Drupal::entityManager()->getFieldDefinition() + // when it can hand the $instance objects. + // https://drupal.org/node/2114707 + $entity_manager = \Drupal::entityManager(); + $entity_info = $entity_manager->getDefinition($this->targetEntityType); + $field_definitions = array(); + if (is_subclass_of($entity_info['class'], '\Drupal\Core\Entity\ContentEntityInterface')) { + $entity = _field_create_entity_from_ids((object) array('entity_type' => $this->targetEntityType, 'bundle' => $this->bundle, 'entity_id' => NULL)); + foreach ($entity as $field_name => $items) { + $field_definitions[$field_name] = $items->getFieldDefinition(); + } + } + + $context = $this->displayContext; + $this->fieldDefinitions = array_filter($field_definitions, function(FieldDefinitionInterface $field_definition) use ($context) { + // @todo getDisplayOptions() is not part of FieldDefinitionInterface, we + // should check for instanceof FieldDefinition + return $field_definition->isConfigurable() || $field_definition->getDisplayOptions($context); + }); } + + return $this->fieldDefinitions; } + } diff --git a/core/modules/entity/lib/Drupal/entity/Tests/EntityDisplayTest.php b/core/modules/entity/lib/Drupal/entity/Tests/EntityDisplayTest.php index 5fe5f89..33ad943 100644 --- a/core/modules/entity/lib/Drupal/entity/Tests/EntityDisplayTest.php +++ b/core/modules/entity/lib/Drupal/entity/Tests/EntityDisplayTest.php @@ -109,9 +109,10 @@ public function testEntityGetDisplay() { * Tests the behavior of a field component within an EntityDisplay object. */ public function testExtraFieldComponent() { + entity_test_create_bundle('bundle_with_extra_fields'); $display = entity_create('entity_display', array( 'targetEntityType' => 'entity_test', - 'bundle' => 'entity_test', + 'bundle' => 'bundle_with_extra_fields', 'mode' => 'default', )); @@ -133,12 +134,6 @@ public function testExtraFieldComponent() { public function testFieldComponent() { $this->enableModules(array('field_test')); - $display = entity_create('entity_display', array( - 'targetEntityType' => 'entity_test', - 'bundle' => 'entity_test', - 'mode' => 'default', - )); - $field_name = 'test_field'; // Create a field and an instance. $field = entity_create('field_entity', array( @@ -154,6 +149,12 @@ public function testFieldComponent() { )); $instance->save(); + $display = entity_create('entity_display', array( + 'targetEntityType' => 'entity_test', + 'bundle' => 'entity_test', + 'mode' => 'default', + )); + // Check that providing no options results in default values being used. $display->setComponent($field_name); $field_type_info = \Drupal::service('plugin.manager.field.field_type')->getDefinition($field->type); diff --git a/core/modules/entity/lib/Drupal/entity/Tests/EntityFormDisplayTest.php b/core/modules/entity/lib/Drupal/entity/Tests/EntityFormDisplayTest.php index a364b3f..66b267a 100644 --- a/core/modules/entity/lib/Drupal/entity/Tests/EntityFormDisplayTest.php +++ b/core/modules/entity/lib/Drupal/entity/Tests/EntityFormDisplayTest.php @@ -55,12 +55,6 @@ public function testEntityGetFromDisplay() { public function testFieldComponent() { $this->enableModules(array('field_test')); - $form_display = entity_create('entity_form_display', array( - 'targetEntityType' => 'entity_test', - 'bundle' => 'entity_test', - 'mode' => 'default', - )); - // Create a field and an instance. $field_name = 'test_field'; $field = entity_create('field_entity', array( @@ -76,6 +70,12 @@ public function testFieldComponent() { )); $instance->save(); + $form_display = entity_create('entity_form_display', array( + 'targetEntityType' => 'entity_test', + 'bundle' => 'entity_test', + 'mode' => 'default', + )); + // Check that providing no options results in default values being used. $form_display->setComponent($field_name); $field_type_info = \Drupal::service('plugin.manager.field.field_type')->getDefinition($field->type); diff --git a/core/modules/field/lib/Drupal/field/Entity/Field.php b/core/modules/field/lib/Drupal/field/Entity/Field.php index e1f89e2..c9d9640 100644 --- a/core/modules/field/lib/Drupal/field/Entity/Field.php +++ b/core/modules/field/lib/Drupal/field/Entity/Field.php @@ -628,6 +628,13 @@ public function isConfigurable() { /** * {@inheritdoc} */ + public function isDisplayConfigurable($context) { + return TRUE; + } + + /** + * {@inheritdoc} + */ public function isQueryable() { return TRUE; } diff --git a/core/modules/field/lib/Drupal/field/Entity/FieldInstance.php b/core/modules/field/lib/Drupal/field/Entity/FieldInstance.php index 23c7d18..9696916 100644 --- a/core/modules/field/lib/Drupal/field/Entity/FieldInstance.php +++ b/core/modules/field/lib/Drupal/field/Entity/FieldInstance.php @@ -577,6 +577,13 @@ public function isConfigurable() { /** * {@inheritdoc} */ + public function isDisplayConfigurable($context) { + return TRUE; + } + + /** + * {@inheritdoc} + */ public function isQueryable() { return TRUE; } @@ -665,4 +672,5 @@ public function getItemDefinition() { } return $this->itemDefinition; } + } diff --git a/core/modules/field_ui/field_ui.api.php b/core/modules/field_ui/field_ui.api.php index 176993d..255ce85 100644 --- a/core/modules/field_ui/field_ui.api.php +++ b/core/modules/field_ui/field_ui.api.php @@ -20,8 +20,7 @@ * @param $context * An associative array with the following elements: * - formatter: The formatter object. - * - field: The field structure being configured. - * - instance: The instance structure being configured. + * - field_definition: The field definition. * - view_mode: The view mode being configured. * - form: The (entire) configuration form array. * @@ -49,8 +48,7 @@ function hook_field_formatter_settings_form_alter(&$element, &$form_state, $cont * @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. + * - field_definition: The field definition. * - form_mode: The form mode being configured. * - form: The (entire) configuration form array. * @@ -75,8 +73,7 @@ function hook_field_widget_settings_form_alter(&$element, &$form_state, $context * @param $context * An associative array with the following elements: * - formatter: The formatter object. - * - field: The field structure being configured. - * - instance: The instance structure being configured. + * - field_definition: The field definition. * - view_mode: The view mode being configured. * * @see \Drupal\field_ui\DisplayOverView. @@ -99,8 +96,7 @@ function hook_field_formatter_settings_summary_alter(&$summary, $context) { * @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. + * - field_definition: The field definition. * - form_mode: The form mode being configured. * * @see \Drupal\field_ui\FormDisplayOverView. 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 49b1612..15a70dd 100644 --- a/core/modules/field_ui/lib/Drupal/field_ui/DisplayOverview.php +++ b/core/modules/field_ui/lib/Drupal/field_ui/DisplayOverview.php @@ -7,9 +7,8 @@ namespace Drupal\field_ui; -use Drupal\Component\Utility\NestedArray; +use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\entity\EntityDisplayBaseInterface; -use Drupal\field\FieldInstanceInterface; use Symfony\Component\DependencyInjection\ContainerInterface; /** @@ -18,6 +17,11 @@ class DisplayOverview extends DisplayOverviewBase { /** + * @{inheritdoc} + */ + var $displayContext = 'view'; + + /** * {@inheritdoc} */ public static function create(ContainerInterface $container) { @@ -49,15 +53,17 @@ public function buildForm(array $form, array &$form_state, $entity_type = NULL, /** * {@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); - $display_options = $entity_display->getComponent($field_id); + protected function buildFieldRow(FieldDefinitionInterface $field_definition, EntityDisplayBaseInterface $entity_display, array $form, array &$form_state) { + $field_row = parent::buildFieldRow($field_definition, $entity_display, $form, $form_state); + + $field_name = $field_definition->getName(); + $display_options = $entity_display->getComponent($field_name); // Insert the label column. $label = array( 'label' => array( '#type' => 'select', - '#title' => $this->t('Label display for @title', array('@title' => $instance->getLabel())), + '#title' => $this->t('Label display for @title', array('@title' => $field_definition->getLabel())), '#title_display' => 'invisible', '#options' => $this->getFieldLabelOptions(), '#default_value' => $display_options ? $display_options['label'] : 'above', @@ -68,9 +74,9 @@ protected function buildFieldRow($field_id, FieldInstanceInterface $instance, En $field_row = array_slice($field_row, 0, $label_position, TRUE) + $label + array_slice($field_row, $label_position, count($field_row) - 1, TRUE); // Update the (invisible) title of the 'plugin' column. - $field_row['plugin']['#title'] = $this->t('Formatter for @title', array('@title' => $instance->getLabel())); - if (!empty($field_row['plugin']['settings_edit_form'])) { - $plugin_type_info = $entity_display->getRenderer($field_id)->getPluginDefinition(); + $field_row['plugin']['#title'] = $this->t('Formatter for @title', array('@title' => $field_definition->getLabel())); + if (!empty($field_row['plugin']['settings_edit_form']) && ($plugin = $entity_display->getRenderer($field_name))) { + $plugin_type_info = $plugin->getPluginDefinition(); $field_row['plugin']['settings_edit_form']['label']['#markup'] = $this->t('Format settings:') . ' ' . $plugin_type_info['label'] . ''; } @@ -105,19 +111,12 @@ protected function getEntityDisplay($mode) { /** * {@inheritdoc} */ - protected function getExtraFields() { - return field_info_extra_fields($this->entity_type, $this->bundle, 'display'); - } - - /** - * {@inheritdoc} - */ - protected function getPlugin($instance, $configuration) { + protected function getPlugin(FieldDefinitionInterface $field_definition, $configuration) { $plugin = NULL; if ($configuration && $configuration['type'] != 'hidden') { $plugin = $this->pluginManager->getInstance(array( - 'field_definition' => $instance, + 'field_definition' => $field_definition, 'view_mode' => $this->mode, 'configuration' => $configuration )); @@ -191,11 +190,10 @@ protected function getFieldLabelOptions() { /** * {@inheritdoc} */ - protected function alterSettingsForm(array &$settings_form, $plugin, FieldInstanceInterface $instance, array $form, array &$form_state) { + protected function alterSettingsForm(array &$settings_form, $plugin, FieldDefinitionInterface $field_definition, array $form, array &$form_state) { $context = array( 'formatter' => $plugin, - 'field' => $instance->getField(), - 'instance' => $instance, + 'field_definition' => $field_definition, 'view_mode' => $this->mode, 'form' => $form, ); @@ -205,11 +203,10 @@ protected function alterSettingsForm(array &$settings_form, $plugin, FieldInstan /** * {@inheritdoc} */ - protected function alterSettingsSummary(array &$summary, $plugin, FieldInstanceInterface $instance) { + protected function alterSettingsSummary(array &$summary, $plugin, FieldDefinitionInterface $field_definition) { $context = array( 'formatter' => $plugin, - 'field' => $instance->getField(), - 'instance' => $instance, + 'field_definition' => $field_definition, '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 index c24daf2..0614c28 100644 --- a/core/modules/field_ui/lib/Drupal/field_ui/DisplayOverviewBase.php +++ b/core/modules/field_ui/lib/Drupal/field_ui/DisplayOverviewBase.php @@ -9,10 +9,9 @@ use Drupal\Component\Plugin\PluginManagerBase; use Drupal\Core\Entity\EntityManagerInterface; +use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\Field\FieldTypePluginManager; use Drupal\entity\EntityDisplayBaseInterface; -use Drupal\field\FieldInstanceInterface; -use Drupal\field_ui\OverviewBase; use Symfony\Component\DependencyInjection\ContainerInterface; /** @@ -21,6 +20,13 @@ abstract class DisplayOverviewBase extends OverviewBase { /** + * @todo + * + * @var string + */ + var $displayContext; + + /** * The widget or formatter plugin manager. * * @var \Drupal\Component\Plugin\PluginManagerBase @@ -80,6 +86,28 @@ public function getRegions() { } /** + * Collects the definitions of fields whose display is configurable. + * + * @return \Drupal\Core\Field\FieldDefinitionInterface[] + * The array of field definitions + */ + protected function getFieldDefinitions() { + // @todo Replace this entire implementation with + // \Drupal::entityManager()->getFieldDefinition() when it can hand the + // $instance objects - https://drupal.org/node/2114707 + $entity = _field_create_entity_from_ids((object) array('entity_type' => $this->entity_type, 'bundle' => $this->bundle, 'entity_id' => NULL)); + $field_definitions = array(); + foreach ($entity as $field_name => $items) { + $field_definitions[$field_name] = $items->getFieldDefinition(); + } + + $context = $this->displayContext; + return array_filter($field_definitions, function(FieldDefinitionInterface $field_definition) use ($context) { + return $field_definition->isDisplayConfigurable($context); + }); + } + + /** * {@inheritdoc} */ public function buildForm(array $form, array &$form_state, $entity_type = NULL, $bundle = NULL) { @@ -89,8 +117,7 @@ public function buildForm(array $form, array &$form_state, $entity_type = NULL, $this->mode = 'default'; } - // Gather type information. - $instances = field_info_instances($this->entity_type, $this->bundle); + $field_definitions = $this->getFieldDefinitions(); $extra_fields = $this->getExtraFields(); $entity_display = $this->getEntityDisplay($this->mode); @@ -102,11 +129,11 @@ public function buildForm(array $form, array &$form_state, $entity_type = NULL, '#entity_type' => $this->entity_type, '#bundle' => $this->bundle, '#mode' => $this->mode, - '#fields' => array_keys($instances), + '#fields' => array_keys($field_definitions), '#extra' => array_keys($extra_fields), ); - if (empty($instances) && empty($extra_fields)) { + if (empty($field_definitions) && empty($extra_fields)) { drupal_set_message($this->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; } @@ -127,8 +154,8 @@ public function buildForm(array $form, array &$form_state, $entity_type = NULL, ); // Field rows. - foreach ($instances as $field_id => $instance) { - $table[$field_id] = $this->buildFieldRow($field_id, $instance, $entity_display, $form, $form_state); + foreach ($field_definitions as $field_name => $field_definition) { + $table[$field_name] = $this->buildFieldRow($field_definition, $entity_display, $form, $form_state); } // Non-field elements. @@ -205,10 +232,8 @@ public function buildForm(array $form, array &$form_state, $entity_type = NULL, /** * 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\Core\Field\FieldDefinitionInterface $field_definition + * The field definition. * @param \Drupal\entity\EntityDisplayBaseInterface $entity_display * The entity display. * @param array $form @@ -219,9 +244,10 @@ public function buildForm(array $form, array &$form_state, $entity_type = NULL, * @return array * A table row array. */ - protected function buildFieldRow($field_id, FieldInstanceInterface $instance, EntityDisplayBaseInterface $entity_display, array $form, array &$form_state) { - $display_options = $entity_display->getComponent($field_id); - $label = $instance->getLabel(); + protected function buildFieldRow(FieldDefinitionInterface $field_definition, EntityDisplayBaseInterface $entity_display, array $form, array &$form_state) { + $field_name = $field_definition->getName(); + $display_options = $entity_display->getComponent($field_name); + $label = $field_definition->getLabel(); $field_row = array( '#attributes' => array('class' => array('draggable', 'tabledrag-leaf')), @@ -229,7 +255,7 @@ protected function buildFieldRow($field_id, FieldInstanceInterface $instance, En '#region_callback' => array($this, 'getRowRegion'), '#js_settings' => array( 'rowHandler' => 'field', - 'defaultPlugin' => $this->getDefaultPlugin($instance->getType()), + 'defaultPlugin' => $this->getDefaultPlugin($field_definition->getType()), ), 'human_name' => array( '#markup' => check_plain($label), @@ -250,11 +276,11 @@ protected function buildFieldRow($field_id, FieldInstanceInterface $instance, En '#options' => drupal_map_assoc(array_keys($this->getRegions())), '#empty_value' => '', '#attributes' => array('class' => array('field-parent')), - '#parents' => array('fields', $field_id, 'parent'), + '#parents' => array('fields', $field_name, 'parent'), ), 'hidden_name' => array( '#type' => 'hidden', - '#default_value' => $field_id, + '#default_value' => $field_name, '#attributes' => array('class' => array('field-name')), ), ), @@ -266,9 +292,9 @@ protected function buildFieldRow($field_id, FieldInstanceInterface $instance, En '#type' => 'select', '#title' => $this->t('Plugin for @title', array('@title' => $label)), '#title_display' => 'invisible', - '#options' => $this->getPluginOptions($instance->getType()), + '#options' => $this->getPluginOptions($field_definition->getType()), '#default_value' => $display_options ? $display_options['type'] : 'hidden', - '#parents' => array('fields', $field_id, 'type'), + '#parents' => array('fields', $field_name, 'type'), '#attributes' => array('class' => array('field-plugin-type')), ), 'settings_edit_form' => array(), @@ -276,15 +302,15 @@ protected function buildFieldRow($field_id, FieldInstanceInterface $instance, En // 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['values']['fields'][$field_name]['type'])) { + $display_options['type'] = $form_state['values']['fields'][$field_name]['type']; } - if (isset($form_state['plugin_settings'][$field_id])) { - $display_options['settings'] = $form_state['plugin_settings'][$field_id]; + if (isset($form_state['plugin_settings'][$field_name])) { + $display_options['settings'] = $form_state['plugin_settings'][$field_name]; } // Get the corresponding plugin object. - $plugin = $this->getPlugin($instance, $display_options); + $plugin = $this->getPlugin($field_definition, $display_options); // Base button element for the various plugin settings actions. $base_button = array( @@ -294,10 +320,10 @@ protected function buildFieldRow($field_id, FieldInstanceInterface $instance, En 'wrapper' => 'field-display-overview-wrapper', 'effect' => 'fade', ), - '#field_name' => $field_id, + '#field_name' => $field_name, ); - if ($form_state['plugin_settings_edit'] == $field_id) { + if ($form_state['plugin_settings_edit'] == $field_name) { // We are currently editing this field's plugin settings. Display the // settings form and submit buttons. $field_row['plugin']['settings_edit_form'] = array(); @@ -305,14 +331,14 @@ protected function buildFieldRow($field_id, FieldInstanceInterface $instance, En 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); + $this->alterSettingsForm($settings_form, $plugin, $field_definition, $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'), + '#parents' => array('fields', $field_name, 'settings_edit_form'), 'label' => array( '#markup' => $this->t('Plugin settings'), ), @@ -321,18 +347,18 @@ protected function buildFieldRow($field_id, FieldInstanceInterface $instance, En '#type' => 'actions', 'save_settings' => $base_button + array( '#type' => 'submit', - '#name' => $field_id . '_plugin_settings_update', + '#name' => $field_name . '_plugin_settings_update', '#value' => $this->t('Update'), '#op' => 'update', ), 'cancel_settings' => $base_button + array( '#type' => 'submit', - '#name' => $field_id . '_plugin_settings_cancel', + '#name' => $field_name . '_plugin_settings_cancel', '#value' => $this->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')), + '#limit_validation_errors' => array(array('fields', $field_name, 'type')), ), ), ); @@ -350,7 +376,7 @@ protected function buildFieldRow($field_id, FieldInstanceInterface $instance, En $summary = $plugin->settingsSummary(); // Allow other modules to alter the summary. - $this->alterSettingsSummary($summary, $plugin, $instance); + $this->alterSettingsSummary($summary, $plugin, $field_definition); if (!empty($summary)) { $field_row['settings_summary'] = array( @@ -364,13 +390,13 @@ protected function buildFieldRow($field_id, FieldInstanceInterface $instance, En if ($plugin_definition['settings']) { $field_row['settings_edit'] = $base_button + array( '#type' => 'image_button', - '#name' => $field_id . '_settings_edit', + '#name' => $field_name . '_settings_edit', '#src' => 'core/misc/configure-dark.png', '#attributes' => array('class' => array('field-plugin-settings-edit'), 'alt' => $this->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')), + '#limit_validation_errors' => array(array('fields', $field_name, 'type')), '#prefix' => '
', '#suffix' => '
', ); @@ -637,12 +663,14 @@ public function multistepAjax($form, &$form_state) { * @return array * An array of extra field info, as provided by field_info_extra_fields(). */ - abstract protected function getExtraFields(); + protected function getExtraFields() { + return field_info_extra_fields($this->entity_type, $this->bundle, ($this->displayContext == 'view' ? 'display' : $this->displayContext)); + } /** * Returns the widget or formatter plugin for a field. * - * @param \Drupal\field\FieldInstanceInterface $instance + * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition * The field instance. * @param array $configuration * The plugin configuration @@ -650,7 +678,7 @@ public function multistepAjax($form, &$form_state) { * @return object * The corresponding plugin. */ - abstract protected function getPlugin($instance, $configuration); + abstract protected function getPlugin(FieldDefinitionInterface $field_definition, $configuration); /** * Returns an array of widget or formatter options for a field type. @@ -799,14 +827,14 @@ protected function saveDisplayStatuses($display_statuses) { * The widget or formatter settings form. * @param object $plugin * The widget or formatter. - * @param FieldInstanceInterface $instance - * The field instance. + * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition + * The field definition. * @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); + abstract protected function alterSettingsForm(array &$settings_form, $plugin, FieldDefinitionInterface $field_definition, array $form, array &$form_state); /** * Alters the widget or formatter settings summary. @@ -815,9 +843,9 @@ protected function saveDisplayStatuses($display_statuses) { * The widget or formatter settings summary. * @param object $plugin * The widget or formatter. - * @param FieldInstanceInterface $instance - * The field instance. + * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition + * The field definition. */ - abstract protected function alterSettingsSummary(array &$summary, $plugin, FieldInstanceInterface $instance); + abstract protected function alterSettingsSummary(array &$summary, $plugin, FieldDefinitionInterface $field_definition); } diff --git a/core/modules/field_ui/lib/Drupal/field_ui/FormDisplayOverview.php b/core/modules/field_ui/lib/Drupal/field_ui/FormDisplayOverview.php index e35b33a..d3a8cea 100644 --- a/core/modules/field_ui/lib/Drupal/field_ui/FormDisplayOverview.php +++ b/core/modules/field_ui/lib/Drupal/field_ui/FormDisplayOverview.php @@ -7,9 +7,8 @@ namespace Drupal\field_ui; -use Drupal\Component\Utility\NestedArray; +use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\entity\EntityDisplayBaseInterface; -use Drupal\field\FieldInstanceInterface; use Symfony\Component\DependencyInjection\ContainerInterface; /** @@ -18,6 +17,11 @@ class FormDisplayOverview extends DisplayOverviewBase { /** + * @{inheritdoc} + */ + var $displayContext = 'form'; + + /** * {@inheritdoc} */ public static function create(ContainerInterface $container) { @@ -49,12 +53,14 @@ public function buildForm(array $form, array &$form_state, $entity_type = NULL, /** * {@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); + protected function buildFieldRow(FieldDefinitionInterface $field_definition, EntityDisplayBaseInterface $entity_display, array $form, array &$form_state) { + $field_row = parent::buildFieldRow($field_definition, $entity_display, $form, $form_state); + + $field_name = $field_definition->getName(); // Update the (invisible) title of the 'plugin' column. - $field_row['plugin']['#title'] = $this->t('Formatter for @title', array('@title' => $instance->getLabel())); - if (!empty($field_row['plugin']['settings_edit_form']) && ($plugin = $entity_display->getRenderer($field_id))) { + $field_row['plugin']['#title'] = $this->t('Formatter for @title', array('@title' => $field_definition->getLabel())); + if (!empty($field_row['plugin']['settings_edit_form']) && ($plugin = $entity_display->getRenderer($field_name))) { $plugin_type_info = $plugin->getPluginDefinition(); $field_row['plugin']['settings_edit_form']['label']['#markup'] = $this->t('Widget settings:') . ' ' . $plugin_type_info['label'] . ''; } @@ -72,19 +78,12 @@ protected function getEntityDisplay($mode) { /** * {@inheritdoc} */ - protected function getExtraFields() { - return field_info_extra_fields($this->entity_type, $this->bundle, 'form'); - } - - /** - * {@inheritdoc} - */ - protected function getPlugin($instance, $configuration) { + protected function getPlugin(FieldDefinitionInterface $field_definition, $configuration) { $plugin = NULL; if ($configuration && $configuration['type'] != 'hidden') { $plugin = $this->pluginManager->getInstance(array( - 'field_definition' => $instance, + 'field_definition' => $field_definition, 'form_mode' => $this->mode, 'configuration' => $configuration )); @@ -143,11 +142,10 @@ protected function getOverviewPath($mode) { /** * {@inheritdoc} */ - protected function alterSettingsForm(array &$settings_form, $plugin, FieldInstanceInterface $instance, array $form, array &$form_state) { + protected function alterSettingsForm(array &$settings_form, $plugin, FieldDefinitionInterface $field_definition, array $form, array &$form_state) { $context = array( 'widget' => $plugin, - 'field' => $instance->getField(), - 'instance' => $instance, + 'field_definition' => $field_definition, 'form_mode' => $this->mode, 'form' => $form, ); @@ -157,11 +155,10 @@ protected function alterSettingsForm(array &$settings_form, $plugin, FieldInstan /** * {@inheritdoc} */ - protected function alterSettingsSummary(array &$summary, $plugin, FieldInstanceInterface $instance) { + protected function alterSettingsSummary(array &$summary, $plugin, FieldDefinitionInterface $field_definition) { $context = array( 'widget' => $plugin, - 'field' => $instance->getField(), - 'instance' => $instance, + 'field_definition' => $field_definition, 'form_mode' => $this->mode, ); drupal_alter('field_widget_settings_summary', $summary, $context); diff --git a/core/modules/forum/config/entity.display.taxonomy_term.forums.default.yml b/core/modules/forum/config/entity.display.taxonomy_term.forums.default.yml index c4d4f8b..06aa5c6 100644 --- a/core/modules/forum/config/entity.display.taxonomy_term.forums.default.yml +++ b/core/modules/forum/config/entity.display.taxonomy_term.forums.default.yml @@ -7,4 +7,3 @@ status: 1 content: description: weight: '0' - visible: '1' diff --git a/core/modules/forum/config/entity.form_display.taxonomy_term.forums.default.yml b/core/modules/forum/config/entity.form_display.taxonomy_term.forums.default.yml index f091e30..1caf718 100644 --- a/core/modules/forum/config/entity.form_display.taxonomy_term.forums.default.yml +++ b/core/modules/forum/config/entity.form_display.taxonomy_term.forums.default.yml @@ -7,7 +7,5 @@ status: 1 content: name: weight: '-5' - visible: '1' description: weight: '0' - visible: '1' diff --git a/core/modules/node/lib/Drupal/node/Entity/Node.php b/core/modules/node/lib/Drupal/node/Entity/Node.php index 968184a..893d936 100644 --- a/core/modules/node/lib/Drupal/node/Entity/Node.php +++ b/core/modules/node/lib/Drupal/node/Entity/Node.php @@ -363,7 +363,16 @@ public static function baseFieldDefinitions($entity_type) { 'default_value' => '', 'max_length' => 255, 'text_processing' => 0, - )); + )) + ->setDisplayOptions('view', array( + 'label' => 'hidden', + 'type' => 'text_default', + 'weight' => -5, + )) + ->setDisplayOptions('form', array( + 'type' => 'text_textfield', + 'weight' => -5, + ), TRUE); $fields['uid'] = FieldDefinition::create('entity_reference') ->setLabel(t('User ID')) diff --git a/core/modules/node/node.module b/core/modules/node/node.module index 1702ee9..37b4cbb 100644 --- a/core/modules/node/node.module +++ b/core/modules/node/node.module @@ -205,12 +205,6 @@ function node_entity_display_alter(EntityDisplay $display, $context) { } } } - // @todo Manage base field displays in the YAML: - // https://drupal.org/node/2144919. - $display->setComponent('title', array( - 'label' => 'hidden', - 'type' => 'text_default', - )); } } @@ -219,16 +213,8 @@ function node_entity_display_alter(EntityDisplay $display, $context) { */ function node_entity_form_display_alter(EntityFormDisplay $form_display, $context) { if ($context['entity_type'] == 'node') { - // @todo Manage base field displays in the YAML: - // https://drupal.org/node/2144919. $node_type = node_type_load($context['bundle']); - if ($node_type->has_title) { - // Title is also registered in node_field_extra_fields(). - $options = $form_display->getComponent('title') ?: array('weight' => -5); - $options['type'] = 'text_textfield'; - $form_display->setComponent('title', $options); - } - else { + if (!$node_type->has_title) { $form_display->removeComponent('title'); } } @@ -479,14 +465,6 @@ function node_field_extra_fields() { $description = t('Node module element'); foreach (node_type_get_types() as $bundle) { - if ($bundle->has_title) { - $extra['node'][$bundle->type]['form']['title'] = array( - 'label' => $bundle->title_label, - 'description' => $description, - 'weight' => -5, - ); - } - // Add also the 'language' select if Language module is enabled and the // bundle has multilingual support. // Visibility of the ordering of the language selector is the same as on the diff --git a/core/modules/system/tests/modules/entity_test/entity_test.module b/core/modules/system/tests/modules/entity_test/entity_test.module index ede9907..fa8ad41 100644 --- a/core/modules/system/tests/modules/entity_test/entity_test.module +++ b/core/modules/system/tests/modules/entity_test/entity_test.module @@ -195,7 +195,7 @@ function entity_test_entity_form_mode_info_alter(&$form_modes) { * Implements hook_field_extra_fields(). */ function entity_test_field_extra_fields() { - $extra['entity_test']['entity_test'] = array( + $extra['entity_test']['bundle_with_extra_fields'] = array( 'display' => array( // Note: those extra fields do not currently display anything, they are // just used in \Drupal\entity\Tests\EntityDisplayTest to test the diff --git a/core/modules/user/user.install b/core/modules/user/user.install index 62d9e17..9a2f4e0 100644 --- a/core/modules/user/user.install +++ b/core/modules/user/user.install @@ -688,9 +688,7 @@ function user_update_8011() { 'weight' => 0, )) ->set('status', 1) - ->set('content.member_for', array( - 'visible' => FALSE, - )); + ->set('hidden.member_for', TRUE); $display->save(); // Add file usage for the default field. diff --git a/core/profiles/standard/config/entity.display.user.user.compact.yml b/core/profiles/standard/config/entity.display.user.user.compact.yml index d83a3dd..85b7992 100644 --- a/core/profiles/standard/config/entity.display.user.user.compact.yml +++ b/core/profiles/standard/config/entity.display.user.user.compact.yml @@ -11,6 +11,6 @@ content: image_style: thumbnail image_link: content weight: 0 - member_for: - visible: false +hidden: + member_for: true status: true