Issue #2928699 by marcoscano, phenaproxima, amateescu, seanB, yoroy: Add an alter hook for the pre-configured field UI options and implement it in the Media module

8.5.x
Lee Rowlands 2018-01-04 07:29:24 +10:00
parent 72c76b73c5
commit cf805af249
No known key found for this signature in database
GPG Key ID: 2B829A3DF9204DC4
10 changed files with 144 additions and 9 deletions

View File

@ -135,7 +135,7 @@ class FieldTypePluginManager extends DefaultPluginManager implements FieldTypePl
// Add preconfigured definitions. // Add preconfigured definitions.
foreach ($definitions as $id => $definition) { foreach ($definitions as $id => $definition) {
if (is_subclass_of($definition['class'], '\Drupal\Core\Field\PreconfiguredFieldUiOptionsInterface')) { if (is_subclass_of($definition['class'], '\Drupal\Core\Field\PreconfiguredFieldUiOptionsInterface')) {
foreach ($definition['class']::getPreconfiguredOptions() as $key => $option) { foreach ($this->getPreconfiguredOptions($definition['id']) as $key => $option) {
$definitions['field_ui:' . $id . ':' . $key] = [ $definitions['field_ui:' . $id . ':' . $key] = [
'label' => $option['label'], 'label' => $option['label'],
] + $definition; ] + $definition;
@ -150,6 +150,19 @@ class FieldTypePluginManager extends DefaultPluginManager implements FieldTypePl
return $definitions; return $definitions;
} }
/**
* {@inheritdoc}
*/
public function getPreconfiguredOptions($field_type) {
$options = [];
$class = $this->getPluginClass($field_type);
if (is_subclass_of($class, '\Drupal\Core\Field\PreconfiguredFieldUiOptionsInterface')) {
$options = $class::getPreconfiguredOptions();
$this->moduleHandler->alter('field_ui_preconfigured_options', $options, $field_type);
}
return $options;
}
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */

View File

@ -84,6 +84,26 @@ interface FieldTypePluginManagerInterface extends PluginManagerInterface, Catego
*/ */
public function getUiDefinitions(); public function getUiDefinitions();
/**
* Returns preconfigured field options for a field type.
*
* This is a wrapper around
* \Drupal\Core\Field\PreconfiguredFieldUiOptionsInterface::getPreconfiguredOptions()
* allowing modules to alter the result of this method by implementing
* hook_field_ui_preconfigured_options_alter().
*
* @param string $field_type
* The field type plugin ID.
*
* @return array
* A multi-dimensional array as returned from
* \Drupal\Core\Field\PreconfiguredFieldUiOptionsInterface::getPreconfiguredOptions().
*
* @see \Drupal\Core\Field\PreconfiguredFieldUiOptionsInterface::getPreconfiguredOptions()
* @see hook_field_ui_preconfigured_options_alter()
*/
public function getPreconfiguredOptions($field_type);
/** /**
* Returns the PHP class that implements the field type plugin. * Returns the PHP class that implements the field type plugin.
* *

View File

@ -16,6 +16,11 @@ interface PreconfiguredFieldUiOptionsInterface {
/** /**
* Returns preconfigured field options for a field type. * Returns preconfigured field options for a field type.
* *
* Note that if you want to give modules an opportunity to alter the result
* of this method, you should call
* \Drupal\Core\Field\FieldTypePluginManagerInterface::getPreconfiguredOptions()
* instead.
*
* @return mixed[][] * @return mixed[][]
* A multi-dimensional array with string keys and the following structure: * A multi-dimensional array with string keys and the following structure:
* - label: The label to show in the field type selection list. * - label: The label to show in the field type selection list.
@ -35,6 +40,7 @@ interface PreconfiguredFieldUiOptionsInterface {
* @see \Drupal\field\Entity\FieldStorageConfig * @see \Drupal\field\Entity\FieldStorageConfig
* @see \Drupal\field\Entity\FieldConfig * @see \Drupal\field\Entity\FieldConfig
* @see \Drupal\Core\Entity\Display\EntityDisplayInterface::setComponent() * @see \Drupal\Core\Entity\Display\EntityDisplayInterface::setComponent()
* @see \Drupal\Core\Field\FieldTypePluginManagerInterface::getPreconfiguredOptions()
*/ */
public static function getPreconfiguredOptions(); public static function getPreconfiguredOptions();

View File

@ -58,6 +58,33 @@ function hook_field_info_alter(&$info) {
} }
} }
/**
* Perform alterations on preconfigured field options.
*
* @param array $options
* Array of options as returned from
* \Drupal\Core\Field\PreconfiguredFieldUiOptionsInterface::getPreconfiguredOptions().
* @param string $field_type
* The field type plugin ID.
*
* @see \Drupal\Core\Field\PreconfiguredFieldUiOptionsInterface::getPreconfiguredOptions()
*/
function hook_field_ui_preconfigured_options_alter(array &$options, $field_type) {
// If the field is not an "entity_reference"-based field, bail out.
/** @var \Drupal\Core\Field\FieldTypePluginManager $field_type_manager */
$field_type_manager = \Drupal::service('plugin.manager.field.field_type');
$class = $field_type_manager->getPluginClass($field_type);
if (!is_a($class, 'Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem', TRUE)) {
return;
}
// Set the default formatter for media in entity reference fields to be the
// "Rendered entity" formatter.
if (!empty($options['media'])) {
$options['media']['entity_view_display']['type'] = 'entity_reference_entity_view';
}
}
/** /**
* Forbid a field storage update from occurring. * Forbid a field storage update from occurring.
* *

View File

@ -171,3 +171,14 @@ function field_test_entity_bundle_field_info_alter(&$fields, EntityTypeInterface
]); ]);
} }
} }
/**
* Implements hook_field_ui_preconfigured_options_alter().
*/
function field_test_field_ui_preconfigured_options_alter(array &$options, $field_type) {
if ($field_type === 'test_field_with_preconfigured_options') {
$options['custom_options']['entity_view_display']['settings'] = [
'test_formatter_setting_multiple' => 'altered dummy test string',
];
}
}

View File

@ -312,14 +312,16 @@ class FieldStorageAddForm extends FormBase {
'translatable' => FALSE, 'translatable' => FALSE,
]; ];
$widget_id = $formatter_id = NULL; $widget_id = $formatter_id = NULL;
$widget_settings = $formatter_settings = [];
// Check if we're dealing with a preconfigured field. // Check if we're dealing with a preconfigured field.
if (strpos($field_storage_values['type'], 'field_ui:') !== FALSE) { if (strpos($field_storage_values['type'], 'field_ui:') !== FALSE) {
list(, $field_type, $option_key) = explode(':', $field_storage_values['type'], 3); list(, $field_type, $option_key) = explode(':', $field_storage_values['type'], 3);
$field_storage_values['type'] = $field_type; $field_storage_values['type'] = $field_type;
$field_type_class = $this->fieldTypePluginManager->getDefinition($field_type)['class']; $field_definition = $this->fieldTypePluginManager->getDefinition($field_type);
$field_options = $field_type_class::getPreconfiguredOptions()[$option_key]; $options = $this->fieldTypePluginManager->getPreconfiguredOptions($field_definition['id']);
$field_options = $options[$option_key];
// Merge in preconfigured field storage options. // Merge in preconfigured field storage options.
if (isset($field_options['field_storage_config'])) { if (isset($field_options['field_storage_config'])) {
@ -340,7 +342,9 @@ class FieldStorageAddForm extends FormBase {
} }
$widget_id = isset($field_options['entity_form_display']['type']) ? $field_options['entity_form_display']['type'] : NULL; $widget_id = isset($field_options['entity_form_display']['type']) ? $field_options['entity_form_display']['type'] : NULL;
$widget_settings = isset($field_options['entity_form_display']['settings']) ? $field_options['entity_form_display']['settings'] : [];
$formatter_id = isset($field_options['entity_view_display']['type']) ? $field_options['entity_view_display']['type'] : NULL; $formatter_id = isset($field_options['entity_view_display']['type']) ? $field_options['entity_view_display']['type'] : NULL;
$formatter_settings = isset($field_options['entity_view_display']['settings']) ? $field_options['entity_view_display']['settings'] : [];
} }
// Create the field storage and field. // Create the field storage and field.
@ -349,8 +353,8 @@ class FieldStorageAddForm extends FormBase {
$field = $this->entityManager->getStorage('field_config')->create($field_values); $field = $this->entityManager->getStorage('field_config')->create($field_values);
$field->save(); $field->save();
$this->configureEntityFormDisplay($values['field_name'], $widget_id); $this->configureEntityFormDisplay($values['field_name'], $widget_id, $widget_settings);
$this->configureEntityViewDisplay($values['field_name'], $formatter_id); $this->configureEntityViewDisplay($values['field_name'], $formatter_id, $formatter_settings);
// Always show the field settings step, as the cardinality needs to be // Always show the field settings step, as the cardinality needs to be
// configured for new fields. // configured for new fields.
@ -418,12 +422,20 @@ class FieldStorageAddForm extends FormBase {
* The field name. * The field name.
* @param string|null $widget_id * @param string|null $widget_id
* (optional) The plugin ID of the widget. Defaults to NULL. * (optional) The plugin ID of the widget. Defaults to NULL.
* @param array $widget_settings
* (optional) An array of widget settings. Defaults to an empty array.
*/ */
protected function configureEntityFormDisplay($field_name, $widget_id = NULL) { protected function configureEntityFormDisplay($field_name, $widget_id = NULL, array $widget_settings = []) {
$options = [];
if ($widget_id) {
$options['type'] = $widget_id;
if (!empty($widget_settings)) {
$options['settings'] = $widget_settings;
}
}
// Make sure the field is displayed in the 'default' form mode (using // Make sure the field is displayed in the 'default' form mode (using
// default widget and settings). It stays hidden for other form modes // default widget and settings). It stays hidden for other form modes
// until it is explicitly configured. // until it is explicitly configured.
$options = $widget_id ? ['type' => $widget_id] : [];
entity_get_form_display($this->entityTypeId, $this->bundle, 'default') entity_get_form_display($this->entityTypeId, $this->bundle, 'default')
->setComponent($field_name, $options) ->setComponent($field_name, $options)
->save(); ->save();
@ -436,12 +448,20 @@ class FieldStorageAddForm extends FormBase {
* The field name. * The field name.
* @param string|null $formatter_id * @param string|null $formatter_id
* (optional) The plugin ID of the formatter. Defaults to NULL. * (optional) The plugin ID of the formatter. Defaults to NULL.
* @param array $formatter_settings
* (optional) An array of formatter settings. Defaults to an empty array.
*/ */
protected function configureEntityViewDisplay($field_name, $formatter_id = NULL) { protected function configureEntityViewDisplay($field_name, $formatter_id = NULL, array $formatter_settings = []) {
$options = [];
if ($formatter_id) {
$options['type'] = $formatter_id;
if (!empty($formatter_settings)) {
$options['settings'] = $formatter_settings;
}
}
// Make sure the field is displayed in the 'default' view mode (using // Make sure the field is displayed in the 'default' view mode (using
// default formatter and settings). It stays hidden for other view // default formatter and settings). It stays hidden for other view
// modes until it is explicitly configured. // modes until it is explicitly configured.
$options = $formatter_id ? ['type' => $formatter_id] : [];
entity_get_display($this->entityTypeId, $this->bundle, 'default') entity_get_display($this->entityTypeId, $this->bundle, 'default')
->setComponent($field_name, $options) ->setComponent($field_name, $options)
->save(); ->save();

View File

@ -750,6 +750,7 @@ class ManageFieldsTest extends WebTestBase {
$this->assertEqual($form_display->getComponent('field_test_custom_options')['type'], 'test_field_widget_multiple'); $this->assertEqual($form_display->getComponent('field_test_custom_options')['type'], 'test_field_widget_multiple');
$view_display = entity_get_display('node', 'article', 'default'); $view_display = entity_get_display('node', 'article', 'default');
$this->assertEqual($view_display->getComponent('field_test_custom_options')['type'], 'field_test_multiple'); $this->assertEqual($view_display->getComponent('field_test_custom_options')['type'], 'field_test_multiple');
$this->assertEqual($view_display->getComponent('field_test_custom_options')['settings']['test_formatter_setting_multiple'], 'altered dummy test string');
} }
/** /**

View File

@ -96,3 +96,22 @@ function template_preprocess_media(array &$variables) {
$variables['content'][$key] = $variables['elements'][$key]; $variables['content'][$key] = $variables['elements'][$key];
} }
} }
/**
* Implements hook_field_ui_preconfigured_options_alter().
*/
function media_field_ui_preconfigured_options_alter(array &$options, $field_type) {
// If the field is not an "entity_reference"-based field, bail out.
/** @var \Drupal\Core\Field\FieldTypePluginManager $field_type_manager */
$field_type_manager = \Drupal::service('plugin.manager.field.field_type');
$class = $field_type_manager->getPluginClass($field_type);
if (!is_a($class, 'Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem', TRUE)) {
return;
}
// Set the default formatter for media in entity reference fields to be the
// "Rendered entity" formatter.
if (!empty($options['media'])) {
$options['media']['entity_view_display']['type'] = 'entity_reference_entity_view';
}
}

View File

@ -32,6 +32,7 @@ trait MediaFunctionalTestTrait {
'administer content types', 'administer content types',
'administer node fields', 'administer node fields',
'administer node form display', 'administer node form display',
'administer node display',
'bypass node access', 'bypass node access',
]; ];

View File

@ -175,4 +175,21 @@ class MediaUiFunctionalTest extends MediaFunctionalTestBase {
$assert_session->pageTextContains($second_media_item->getName()); $assert_session->pageTextContains($second_media_item->getName());
} }
/**
* Test that media in ER fields use the Rendered Entity formatter by default.
*/
public function testRenderedEntityReferencedMedia() {
$page = $this->getSession()->getPage();
$assert_session = $this->assertSession();
$this->drupalCreateContentType(['type' => 'page', 'name' => 'Page']);
$this->drupalGet('/admin/structure/types/manage/page/fields/add-field');
$page->selectFieldOption('new_storage_type', 'field_ui:entity_reference:media');
$page->fillField('label', 'Foo field');
$page->fillField('field_name', 'foo_field');
$page->pressButton('Save and continue');
$this->drupalGet('/admin/structure/types/manage/page/display');
$assert_session->fieldValueEquals('fields[field_foo_field][type]', 'entity_reference_entity_view');
}
} }