diff --git a/core/modules/media_entity/config/schema/media_entity.schema.yml b/core/modules/media_entity/config/schema/media_entity.schema.yml index bff9c1e2a7a79815edf8fc0e3fe14ef3e6d0f4a1..3322fe3daef96efda1edfe930715e7fe787aec7f 100644 --- a/core/modules/media_entity/config/schema/media_entity.schema.yml +++ b/core/modules/media_entity/config/schema/media_entity.schema.yml @@ -36,6 +36,14 @@ media_entity.bundle.*: sequence: type: string +media_entity.bundle.type.document: + type: mapping + label: 'Document type configuration' + mapping: + source_field: + type: string + label: 'Field with source information' + action.configuration.media_delete_action: type: action_configuration_default label: 'Delete media configuration' diff --git a/core/modules/media_entity/src/Plugin/MediaEntity/Type/Document.php b/core/modules/media_entity/src/Plugin/MediaEntity/Type/Document.php new file mode 100644 index 0000000000000000000000000000000000000000..6227af637aacdd05ff8e2b960c591a3865299a5f --- /dev/null +++ b/core/modules/media_entity/src/Plugin/MediaEntity/Type/Document.php @@ -0,0 +1,123 @@ + $this->t('File MIME'), + 'size' => $this->t('Size'), + ]; + } + + /** + * {@inheritdoc} + */ + public function getField(MediaInterface $media, $name) { + $source_field = $this->configuration['source_field']; + + // Get the file document. + /** @var \Drupal\file\FileInterface $file */ + $file = $media->{$source_field}->entity; + + // Return the field. + switch ($name) { + case 'mime': + return !$file->filemime->isEmpty() ? $file->getMimeType() : FALSE; + + case 'size': + $size = $file->getSize(); + return $size ? $size : FALSE; + } + + return FALSE; + } + + /** + * {@inheritdoc} + */ + public function buildConfigurationForm(array $form, FormStateInterface $form_state) { + /** @var \Drupal\media_entity\MediaBundleInterface $bundle */ + $bundle = $form_state->getFormObject()->getEntity(); + $options = []; + $allowed_field_types = ['file']; + + /** @var \Drupal\Core\Field\FieldDefinitionInterface $field */ + foreach ($this->entityFieldManager->getFieldDefinitions('media', $bundle->id()) as $field_name => $field) { + if (in_array($field->getType(), $allowed_field_types) && !$field->getFieldStorageDefinition()->isBaseField()) { + $options[$field_name] = $field->getLabel(); + } + } + + $form['source_field'] = [ + '#type' => 'select', + '#title' => $this->t('Field with source information'), + '#description' => $this->t('Field on media entity that stores Document file. You can create a bundle without selecting a value for this dropdown initially. This dropdown can be populated after adding fields to the bundle.'), + '#default_value' => empty($this->configuration['source_field']) ? NULL : $this->configuration['source_field'], + '#options' => $options, + ]; + + return $form; + } + + /** + * {@inheritdoc} + */ + public function thumbnail(MediaInterface $media) { + $source_field = $this->configuration['source_field']; + /** @var \Drupal\file\FileInterface $file */ + $file = $media->{$source_field}->entity; + + if ($file) { + $mimetype = $file->getMimeType(); + $mimetype = explode('/', $mimetype); + $thumbnail = $this->configFactory->get('media_entity.settings')->get('icon_base') . "/{$mimetype[0]}-{$mimetype[1]}.png"; + + if (!is_file($thumbnail)) { + $thumbnail = $this->configFactory->get('media_entity.settings')->get('icon_base') . "/{$mimetype[1]}.png"; + + if (!is_file($thumbnail)) { + $thumbnail = $this->configFactory->get('media_entity.settings')->get('icon_base') . '/generic.png'; + } + } + } + else { + $thumbnail = $this->configFactory->get('media_entity.settings')->get('icon_base') . '/generic.png'; + } + + return $thumbnail; + } + + /** + * {@inheritdoc} + */ + public function getDefaultName(MediaInterface $media) { + // The default name will be the filename of the source_field, if present. + $source_field = $this->configuration['source_field']; + + /** @var \Drupal\file\FileInterface $file */ + if (!empty($source_field) && ($file = $media->{$source_field}->entity)) { + return $file->getFilename(); + } + + return parent::getDefaultName($media); + } + +} diff --git a/core/modules/media_entity/tests/src/FunctionalJavascript/DocumentTest.php b/core/modules/media_entity/tests/src/FunctionalJavascript/DocumentTest.php new file mode 100644 index 0000000000000000000000000000000000000000..639ff22ed1d26060ecc099cded86b37b312c7881 --- /dev/null +++ b/core/modules/media_entity/tests/src/FunctionalJavascript/DocumentTest.php @@ -0,0 +1,57 @@ +getSession(); + $page = $session->getPage(); + $assert_session = $this->assertSession(); + + $bundle_name = 'sfbhg6gfe54rdfjbhbf7'; + $provided_fields = ['mime', 'size']; + $this->createMediaBundleTest($bundle_name, 'document', $provided_fields); + // Create a supported and a non-supported field. + $fields = [ + 'field_string1' => 'string', + 'field_file1' => 'file', + ]; + $this->createMediaFields($fields, $bundle_name); + // Adjust the allowed extensions on the file field. + $file_field = FieldConfig::load("media.$bundle_name.field_file1"); + $file_field->setSetting('file_extensions', 'png')->save(); + $this->drupalGet("admin/structure/media/manage/$bundle_name"); + $this->assertSelectOptions("type_configuration[document][source_field]", ['field_file1'], ['field_string1']); + $page->selectFieldOption("type_configuration[document][source_field]", 'field_file1'); + $page->pressButton('Save media bundle'); + $this->drupalGet('admin/structure/media'); + // Hide the media name to test default name generation. + $this->hideMediaField('name', $bundle_name); + // Create a media item. + $this->drupalGet("media/add/$bundle_name"); + $page->attachFileToField("files[field_file1_0]", \Drupal::root() . '/core/misc/druplicon.png'); + $assert_session->assertWaitOnAjaxRequest(); + $page->pressButton('Save and publish'); + $assert_session->addressEquals('media/1'); + // Make sure the thumbnail shows up. + $assert_session->elementAttributeContains('css', '.image-style-thumbnail', 'src', 'generic.png'); + // Load the media and check its default name. + $media = Media::load(1); + $this->assertEquals($media->label(), 'druplicon.png'); + + } + +} diff --git a/core/modules/media_entity/tests/src/FunctionalJavascript/MediaTypeBaseTest.php b/core/modules/media_entity/tests/src/FunctionalJavascript/MediaTypeBaseTest.php new file mode 100644 index 0000000000000000000000000000000000000000..59d98cedfb1c564ccf8cbe92a0583cb2b71851a6 --- /dev/null +++ b/core/modules/media_entity/tests/src/FunctionalJavascript/MediaTypeBaseTest.php @@ -0,0 +1,143 @@ + $field_name, + 'entity_type' => 'media', + 'type' => $field_type, + ]); + $storage->save(); + $instance = FieldConfig::create([ + 'field_storage' => $storage, + 'bundle' => $bundle_name, + ]); + $instance->save(); + // Make the field visible in the form display. + /** @var \Drupal\Core\Entity\Display\EntityFormDisplayInterface $form_display */ + $component = \Drupal::service('plugin.manager.field.widget') + ->prepareConfiguration($field_type, []); + entity_get_form_display('media', $bundle_name, 'default') + ->setComponent($field_name, $component) + ->save(); + } + + /** + * Helper to create a set of fields in a bundle. + * + * @param array $fields + * An associative array where keys are field names and values field types. + * @param string $bundle_name + * The bundle machine name. + */ + protected function createMediaFields(array $fields, $bundle_name) { + foreach ($fields as $field_name => $field_type) { + $this->createMediaField($field_name, $field_type, $bundle_name); + } + } + + /** + * Hide a component from the default form display config. + * + * @param string $field_name + * The field name. + * @param string $bundle_name + * The media bundle machine name. + */ + protected function hideMediaField($field_name, $bundle_name) { + $form_display = entity_get_form_display('media', $bundle_name, 'default'); + $form_display->removeComponent($field_name)->save(); + } + + /** + * Helper to test a generic bundle creation. + * + * @param string $bundle_name + * The bundle machine name. + * @param string $bundle_type + * The bundle type id. + * @param array $provided_fields + * (optional) An array of field machine names this type provides. + * @param bool $check_source_field_element + * (optional) Whether this type provides a "source_field". Defaults to TRUE. + */ + public function createMediaBundleTest($bundle_name, $bundle_type, array $provided_fields = [], $check_source_field_element = TRUE) { + $session = $this->getSession(); + $page = $session->getPage(); + $assert_session = $this->assertSession(); + + $this->drupalGet('admin/structure/media/add'); + $page->fillField('label', $bundle_name); + // assertWaitOnAjaxRequest() doesn't work on the machine name element. + $session->wait(5000, "jQuery('.machine-name-value').text() === '$bundle_name'"); + + // Make sure the bundle type is available as plugin type. + $assert_session->optionExists('type', $bundle_type); + $page->selectFieldOption('type', $bundle_type); + $assert_session->assertWaitOnAjaxRequest(); + + // Select our plugin type, and make sure the form gets updated. + if ($check_source_field_element) { + $assert_session->selectExists("type_configuration[$bundle_type][source_field]"); + } + + // Make sure the provided fields are visible on the form. + if (!empty($provided_fields)) { + foreach ($provided_fields as $provided_field) { + $assert_session->selectExists("field_mapping[$provided_field]"); + } + } + + // Save the page to create the bundle. + $page->pressButton('Save media bundle'); + $assert_session->pageTextContains('The media bundle ' . $bundle_name . ' has been added.'); + $this->drupalGet('admin/structure/media'); + $assert_session->pageTextContains($bundle_name); + + } + + /** + * Helper to assert presence/absence of select options. + * + * @param string $select + * One of id|name|label|value for the select field. + * @param array $expected_options + * An indexed array of expected option names. + * @param array $non_expected_options + * An indexed array of non-expected option names. + * + * @see \Drupal\Tests\WebAssert::optionExists() + * @see \Drupal\Tests\WebAssert::optionNotExists() + */ + protected function assertSelectOptions($select, $expected_options = [], $non_expected_options = []) { + $assert_session = $this->assertSession(); + foreach ($expected_options as $expected_option) { + $assert_session->optionExists($select, $expected_option); + } + foreach ($non_expected_options as $non_expected_option) { + $assert_session->optionNotExists($select, $non_expected_option); + } + } + +}