diff -u b/src/Entity/MediaBundle.php b/src/Entity/MediaBundle.php --- b/src/Entity/MediaBundle.php +++ b/src/Entity/MediaBundle.php @@ -250,12 +250,17 @@ public function preSave(EntityStorageInterface $storage) { parent::preSave($storage); + // If the type plugin uses a source field, we'll need to store its name in + // our type configuration before saving. We'd need to double-save if we did + // this in postSave(). $type_plugin = $this->getType(); if ($type_plugin instanceof SourceFieldInterface) { $storage = $type_plugin->getSourceField($this)->getFieldStorageDefinition(); + // If the field storage is a new (unsaved) config entity, save it. if ($storage instanceof FieldStorageConfigInterface && $storage->isNew()) { $storage->save(); } + // Store the field name. $configuration = $type_plugin->getConfiguration(); $configuration['source_field'] = $storage->getName(); $this->setTypeConfiguration($configuration); @@ -268,15 +273,24 @@ public function postSave(EntityStorageInterface $storage, $update = TRUE) { parent::postSave($storage, $update); + // If the type plugin is using a source field, we may need to save it if + // it's new. The field storage is guaranteed to exist already because + // preSave() took care of that. $type_plugin = $this->getType(); if ($type_plugin instanceof SourceFieldInterface) { $field = $type_plugin->getSourceField($this); + // If the field is new, save it and add it to this bundle's view and form + // displays. if ($field->isNew()) { + // Ensure the field is saved correctly before adding it to the displays. + $field->save(); + $entity_type = $field->getTargetEntityTypeId(); $bundle = $field->getTargetBundle(); if ($field->isDisplayConfigurable('form')) { + // Use the default widget and settings. $component = \Drupal::service('plugin.manager.field.widget') ->prepareConfiguration($field->getType(), []); @@ -285,6 +299,7 @@ ->save(); } if ($field->isDisplayConfigurable('view')) { + // Use the default formatter and settings. $component = \Drupal::service('plugin.manager.field.formatter') ->prepareConfiguration($field->getType(), []); @@ -292,7 +307,6 @@ ->setComponent($field->getName(), $component) ->save(); } - $field->save(); } } } diff -u b/src/MediaTypeBase.php b/src/MediaTypeBase.php --- b/src/MediaTypeBase.php +++ b/src/MediaTypeBase.php @@ -15,7 +15,7 @@ /** * Base implementation of media type plugin. */ -abstract class MediaTypeBase extends PluginBase implements MediaTypeInterface, SourceFieldInterface, ContainerFactoryPluginInterface { +abstract class MediaTypeBase extends PluginBase implements SourceFieldInterface, ContainerFactoryPluginInterface { use StringTranslationTrait; /** @@ -143,7 +143,7 @@ $options = []; foreach ($this->entityFieldManager->getFieldStorageDefinitions('media') as $field_name => $field) { - $allowed_type = in_array($field->getType(), $this->pluginDefinition['allowed_field_types']); + $allowed_type = in_array($field->getType(), $this->pluginDefinition['allowed_field_types'], TRUE); if ($allowed_type && !$field->isBaseField()) { $options[$field_name] = $field->getLabel(); } @@ -187,32 +187,24 @@ if (empty($this->configuration['source_field'])) { return $this->createSourceField($bundle); } - $id = 'media.' . $bundle->id() . '.' . $this->configuration['source_field']; - - return $this->entityTypeManager - ->getStorage('field_config') - ->load($id) - ?: - $this->createSourceField($bundle); + $field = $this->configuration['source_field']; + $fields = $this->entityFieldManager->getFieldDefinitions('media', $bundle->id()); + return isset($fields[$field]) ? $fields[$field] : $this->createSourceField($bundle); } /** * Returns the source field storage definition. * - * @return \Drupal\field\FieldStorageConfigInterface + * @return \Drupal\Core\Field\FieldStorageDefinitionInterface * The field storage definition. Will be unsaved if new. */ protected function getSourceFieldStorage() { - if ($this->configuration['source_field']) { - $id = 'media.' . $this->configuration['source_field']; - - return $this->entityTypeManager - ->getStorage('field_storage_config') - ->load($id); - } - else { + if (empty($this->configuration['source_field'])) { return $this->createSourceFieldStorage(); } + $field = $this->configuration['source_field']; + $fields = $this->entityFieldManager->getFieldStorageDefinitions('media'); + return isset($fields[$field]) ? $fields[$field] : $this->createSourceFieldStorage(); } /** diff -u b/src/SourceFieldInterface.php b/src/SourceFieldInterface.php --- b/src/SourceFieldInterface.php +++ b/src/SourceFieldInterface.php @@ -5,7 +5,7 @@ /** * Interface for media type plugins that depend on a field. */ -interface SourceFieldInterface { +interface SourceFieldInterface extends MediaTypeInterface { /** * Returns the source field for a bundle using this plugin. diff -u b/tests/modules/media_entity_test_type/src/Plugin/MediaEntity/Type/TestType.php b/tests/modules/media_entity_test_type/src/Plugin/MediaEntity/Type/TestType.php --- b/tests/modules/media_entity_test_type/src/Plugin/MediaEntity/Type/TestType.php +++ b/tests/modules/media_entity_test_type/src/Plugin/MediaEntity/Type/TestType.php @@ -12,7 +12,7 @@ * id = "test_type", * label = @Translation("Test type"), * description = @Translation("Test media type."), - * allowed_field_types = {"string"} + * allowed_field_types = {"string"}, * ) */ class TestType extends Generic { diff -u b/tests/src/FunctionalJavascript/BundleCreationTest.php b/tests/src/FunctionalJavascript/BundleCreationTest.php --- b/tests/src/FunctionalJavascript/BundleCreationTest.php +++ b/tests/src/FunctionalJavascript/BundleCreationTest.php @@ -1,7 +1,6 @@ 'pastafazoul', - 'label' => 'Pastafazoul', - 'type' => 'generic', - ])->save(); + $this->drupalGet('/admin/structure/media/add'); + $page = $this->getSession()->getPage(); + $page->fillField('label', 'Pastafazoul'); + $this->getSession() + ->wait(5000, "jQuery('.machine-name-value').text() === 'pastafazoul'"); + $page->selectFieldOption('Type provider', 'generic'); + $this->assertSession()->assertWaitOnAjaxRequest(); + $page->pressButton('Save media bundle'); $label = 'Bundle reusing Default Field'; $bundleMachineName = str_replace(' ', '_', strtolower($label));