Unverified Commit cf805af2 authored by larowlan's avatar larowlan

Issue #2928699 by marcoscano, phenaproxima, amateescu, seanB, yoroy: Add an...

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
parent 72c76b73
......@@ -135,7 +135,7 @@ public function getUiDefinitions() {
// Add preconfigured definitions.
foreach ($definitions as $id => $definition) {
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] = [
'label' => $option['label'],
] + $definition;
......@@ -150,6 +150,19 @@ public function getUiDefinitions() {
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}
*/
......
......@@ -84,6 +84,26 @@ public function getDefaultStorageSettings($type);
*/
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.
*
......
......@@ -16,6 +16,11 @@ interface PreconfiguredFieldUiOptionsInterface {
/**
* 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[][]
* A multi-dimensional array with string keys and the following structure:
* - 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\FieldConfig
* @see \Drupal\Core\Entity\Display\EntityDisplayInterface::setComponent()
* @see \Drupal\Core\Field\FieldTypePluginManagerInterface::getPreconfiguredOptions()
*/
public static function getPreconfiguredOptions();
......
......@@ -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.
*
......
......@@ -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',
];
}
}
......@@ -312,14 +312,16 @@ public function submitForm(array &$form, FormStateInterface $form_state) {
'translatable' => FALSE,
];
$widget_id = $formatter_id = NULL;
$widget_settings = $formatter_settings = [];
// Check if we're dealing with a preconfigured field.
if (strpos($field_storage_values['type'], 'field_ui:') !== FALSE) {
list(, $field_type, $option_key) = explode(':', $field_storage_values['type'], 3);
$field_storage_values['type'] = $field_type;
$field_type_class = $this->fieldTypePluginManager->getDefinition($field_type)['class'];
$field_options = $field_type_class::getPreconfiguredOptions()[$option_key];
$field_definition = $this->fieldTypePluginManager->getDefinition($field_type);
$options = $this->fieldTypePluginManager->getPreconfiguredOptions($field_definition['id']);
$field_options = $options[$option_key];
// Merge in preconfigured field storage options.
if (isset($field_options['field_storage_config'])) {
......@@ -340,7 +342,9 @@ public function submitForm(array &$form, FormStateInterface $form_state) {
}
$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_settings = isset($field_options['entity_view_display']['settings']) ? $field_options['entity_view_display']['settings'] : [];
}
// Create the field storage and field.
......@@ -349,8 +353,8 @@ public function submitForm(array &$form, FormStateInterface $form_state) {
$field = $this->entityManager->getStorage('field_config')->create($field_values);
$field->save();
$this->configureEntityFormDisplay($values['field_name'], $widget_id);
$this->configureEntityViewDisplay($values['field_name'], $formatter_id);
$this->configureEntityFormDisplay($values['field_name'], $widget_id, $widget_settings);
$this->configureEntityViewDisplay($values['field_name'], $formatter_id, $formatter_settings);
// Always show the field settings step, as the cardinality needs to be
// configured for new fields.
......@@ -418,12 +422,20 @@ public function submitForm(array &$form, FormStateInterface $form_state) {
* The field name.
* @param string|null $widget_id
* (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
// default widget and settings). It stays hidden for other form modes
// until it is explicitly configured.
$options = $widget_id ? ['type' => $widget_id] : [];
entity_get_form_display($this->entityTypeId, $this->bundle, 'default')
->setComponent($field_name, $options)
->save();
......@@ -436,12 +448,20 @@ protected function configureEntityFormDisplay($field_name, $widget_id = NULL) {
* The field name.
* @param string|null $formatter_id
* (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
// default formatter and settings). It stays hidden for other view
// modes until it is explicitly configured.
$options = $formatter_id ? ['type' => $formatter_id] : [];
entity_get_display($this->entityTypeId, $this->bundle, 'default')
->setComponent($field_name, $options)
->save();
......
......@@ -750,6 +750,7 @@ public function testPreconfiguredFields() {
$this->assertEqual($form_display->getComponent('field_test_custom_options')['type'], 'test_field_widget_multiple');
$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')['settings']['test_formatter_setting_multiple'], 'altered dummy test string');
}
/**
......
......@@ -96,3 +96,22 @@ function template_preprocess_media(array &$variables) {
$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';
}
}
......@@ -32,6 +32,7 @@ trait MediaFunctionalTestTrait {
'administer content types',
'administer node fields',
'administer node form display',
'administer node display',
'bypass node access',
];
......
......@@ -175,4 +175,21 @@ public function testMediaWithMultipleMediaTypes() {
$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');
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment