diff --git a/config/schema/simple_sitemap.schema.yml b/config/schema/simple_sitemap.schema.yml index aea1d49..876dced 100644 --- a/config/schema/simple_sitemap.schema.yml +++ b/config/schema/simple_sitemap.schema.yml @@ -61,6 +61,11 @@ simple_sitemap.bundle_settings.*.*.*: include_images: label: 'Include images' type: boolean + file_mimetypes: + label: 'File MIME types' + type: sequence + sequence: + type: string simple_sitemap.custom_links.*: label: 'Custom links' diff --git a/simple_sitemap.install b/simple_sitemap.install index 0037c82..1548f1f 100644 --- a/simple_sitemap.install +++ b/simple_sitemap.install @@ -718,3 +718,39 @@ function simple_sitemap_update_8302() { $settings->save(); } } + +/** + * Adding file MIME type inclusion setting to all existing bundle and entity instance settings. + */ +function simple_sitemap_update_8306() { + + // Update existing bundle settings. + $config_factory = \Drupal::service('config.factory'); + $all_bundle_settings = $config_factory->listAll('simple_sitemap.bundle_settings.'); + + foreach ($all_bundle_settings as $bundle_settings) { + $config = $config_factory->get($bundle_settings)->get(); + if (!isset($config['file_mimetypes'])) { + $config_factory->getEditable($bundle_settings) + ->setData($config + ['file_mimetypes' => []]) + ->save(); + } + } + + // Update existing entity override data. + $results = \Drupal::database()->select('simple_sitemap_entity_overrides', 'o') + ->fields('o', ['id', 'inclusion_settings']) + ->execute()->fetchAll(\PDO::FETCH_OBJ); + + foreach ($results as $row) { + $settings = unserialize($row->inclusion_settings); + if (!isset($settings['file_mimetypes'])) { + \Drupal::database()->update('simple_sitemap_entity_overrides') + ->fields(['inclusion_settings' => serialize($settings + ['file_mimetypes' => []])]) + ->condition('id', $row->id) + ->execute(); + } + } + + return t('You may now want to configure your XML sitemap entities to specific file MIME types.'); +} diff --git a/simple_sitemap.module b/simple_sitemap.module index dacec83..4ea7fe8 100644 --- a/simple_sitemap.module +++ b/simple_sitemap.module @@ -107,11 +107,17 @@ function simple_sitemap_entity_form_submit($form, FormStateInterface &$form_stat foreach ($generator->getSitemapManager()->getSitemapVariants(NULL, FALSE) as $variant => $definition) { if (isset($values['index_' . $variant . '_' . $f->getEntityTypeId() . '_settings'])) { // Variants may have changed since form load. + $file_mimetypes = []; + if (isset($values['file_mimetypes_' . $variant . '_' . $f->getEntityTypeId() . '_settings'])) { + $file_mimetypes = $values['file_mimetypes_' . $variant . '_' . $f->getEntityTypeId() . '_settings']; + } + $settings = [ 'index' => (bool) $values['index_' . $variant . '_' . $f->getEntityTypeId() . '_settings'], 'priority' => $values['priority_' . $variant . '_' . $f->getEntityTypeId() . '_settings'], 'changefreq' => $values['changefreq_' . $variant . '_' . $f->getEntityTypeId() . '_settings'], 'include_images' => (bool) $values['include_images_' . $variant . '_' . $f->getEntityTypeId() . '_settings'], + 'file_mimetypes' => $generator->getFileMimetypes($file_mimetypes), ]; $generator->setVariants($variant); diff --git a/simple_sitemap.services.yml b/simple_sitemap.services.yml index 1b6ce08..6abb451 100644 --- a/simple_sitemap.services.yml +++ b/simple_sitemap.services.yml @@ -62,12 +62,19 @@ services: - '@entity_type.manager' - '@entity_type.bundle.info' + simple_sitemap.mimetypes_helper: + class: Drupal\simple_sitemap\MimetypesHelper + public: true + arguments: + - '@module_handler' + simple_sitemap.form_helper: class: Drupal\simple_sitemap\Form\FormHelper public: true arguments: - '@simple_sitemap.generator' - '@simple_sitemap.entity_helper' + - '@simple_sitemap.mimetypes_helper' - '@current_user' simple_sitemap.logger: diff --git a/src/EntityHelper.php b/src/EntityHelper.php index 906c7f7..36f786b 100644 --- a/src/EntityHelper.php +++ b/src/EntityHelper.php @@ -8,6 +8,7 @@ use Drupal\Core\Entity\EntityTypeBundleInfoInterface; use Drupal\Core\Entity\EntityTypeInterface; use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Url; +use Drupal\file\FileInterface; /** * Helper class for working with entities. @@ -103,18 +104,22 @@ class EntityHelper { * Determines if an entity type is supported or not. * * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type + * The Entity Type object. + * * @return bool * TRUE if entity type supported by Simple Sitemap, FALSE if not. */ public function supports(EntityTypeInterface $entity_type) { - if (!$entity_type instanceof ContentEntityTypeInterface + if ( + !$entity_type instanceof ContentEntityTypeInterface || !method_exists($entity_type, 'getBundleEntityType') - || !$entity_type->hasLinkTemplate('canonical')) { + || (!$entity_type->hasLinkTemplate('canonical') && $entity_type instanceof FileInterface) + ) { return FALSE; } return TRUE; - } + } /** * Checks whether an entity type does not provide bundles. diff --git a/src/Form/FormHelper.php b/src/Form/FormHelper.php index b19c78e..c63e323 100644 --- a/src/Form/FormHelper.php +++ b/src/Form/FormHelper.php @@ -5,8 +5,10 @@ namespace Drupal\simple_sitemap\Form; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\StringTranslation\StringTranslationTrait; use Drupal\simple_sitemap\EntityHelper; +use Drupal\simple_sitemap\MimetypesHelper; use Drupal\simple_sitemap\Simplesitemap; use Drupal\Core\Session\AccountProxyInterface; +use Drupal\media\Entity\MediaType; /** * Class FormHelper @@ -28,6 +30,11 @@ class FormHelper { */ protected $entityHelper; + /** + * @var \Drupal\simple_sitemap\MimetypesHelper + */ + protected $mimetypesHelper; + /** * @var \Drupal\Core\Session\AccountProxyInterface */ @@ -104,15 +111,18 @@ class FormHelper { * FormHelper constructor. * @param \Drupal\simple_sitemap\Simplesitemap $generator * @param \Drupal\simple_sitemap\EntityHelper $entityHelper + * @param \Drupal\simple_sitemap\MimetypesHelper $mimetypesHelper * @param \Drupal\Core\Session\AccountProxyInterface $current_user */ public function __construct( Simplesitemap $generator, EntityHelper $entityHelper, + MimetypesHelper $mimetypesHelper, AccountProxyInterface $current_user ) { $this->generator = $generator; $this->entityHelper = $entityHelper; + $this->mimetypesHelper = $mimetypesHelper; $this->currentUser = $current_user; } @@ -275,6 +285,9 @@ class FormHelper { /** * @param $form_fragment * @return $this + * + * @todo Gives user ability to enable file/media indexing in an entity instance if + * its MIME type is allowed by the bundle. */ public function displayEntitySettings(&$form_fragment) { $bundle_name = !empty($this->getBundleName()) @@ -368,6 +381,29 @@ class FormHelper { if ($this->getEntityCategory() === 'instance' && isset($this->settings[$variant]['bundle_settings']['include_images'])) { $form_fragment['settings'][$variant]['include_images_' . $variant . '_' . $this->getEntityTypeId() . '_settings']['#options'][(int) $this->settings[$variant]['bundle_settings']['include_images']] .= ' (' . $this->t('default') . ')'; } + + // File MIME types. + // Only add configurable field to bundle category. + if (in_array($this->getEntityTypeId(), ['media', 'file'])) { + $file_mimetypes_field_config = $this->getFileMimeTypesFieldConfig( + isset($this->settings[$variant]['file_mimetypes']) ? $this->settings[$variant]['file_mimetypes'] : [] + ); + + $form_fragment['settings'][$variant]['file_mimetypes_' . $variant . '_' . $this->getEntityTypeId() . '_settings'] = [ + '#type' => 'select', + '#title' => $this->t('File MIME types'), + '#description' => $this->getEntityCategory() === 'instance' + ? $this->t('Determines which file MIME type referenced by this @bundle entity should be included in the sitemap.', ['@bundle' => $bundle_name]) + : $this->t('Determines which file MIME type referenced by entities of this type should be included in the sitemap.'), + '#default_value' => $file_mimetypes_field_config['default_value'], + '#options' => $file_mimetypes_field_config['options'], + '#multiple' => TRUE, + '#disabled' => ($this->getEntityCategory() !== 'bundle'), + '#states' => [ + 'visible' => [':input[name="index_' . $variant . '_' . $this->getEntityTypeId() . '_settings"]' => ['value' => 1]], + ], + ]; + } } return $this; @@ -431,6 +467,10 @@ class FormHelper { * 'delete'. */ protected function getFormEntity() { + if (empty($this->formState)) { + return FALSE; + } + $form_object = $this->formState->getFormObject(); if (NULL !== $form_object && method_exists($form_object, 'getOperation') @@ -602,4 +642,200 @@ class FormHelper { public static function getDonationText() { return '
' . t('If you would like to say thanks and support the development of this module, a donation will be much appreciated.', ['@url' => 'https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=5AFYRSBLGSC3W']) . '
'; } + + /** + * Gets the file MIME type field configuration. + * + * @param array $default_value + * The default value configured. + * + * @return array + * File MIME type field config. e.g ['default_value' => [], 'options' => []] + */ + public function getFileMimeTypesFieldConfig(array $default_value) { + $field_config['default_value'] = $default_value; + + if ($this->getEntityCategory() == 'bundle') { + $field_config['options'] = $this->getFileMimeTypesSelectOptions(); + + // Define default_value the same as options when it's empty + // and there is not - All types - option. + if (empty($field_config['default_value'])) { + if (!isset($field_config['options'][''])) { + $field_config['default_value'] = $field_config['options']; + } + else { + $field_config['default_value'] = ['']; + } + } + } + else { + $field_config['options'] = $default_value; + $field_config['default_value'] = $field_config['options']; + } + + return $field_config; + } + + /** + * Gets the values needed to display the file MIME types dropdown setting. + * + * @return array + * File MIME types select value. + */ + private function getFileMimeTypesSelectOptions() { + if ($this->getEntityTypeId() == 'media') { + return $this->getFileMimeTypesMediaOptions(); + } + + return $this->getFileMimeTypesFileOptions(); + } + + /** + * Gets the media MIME types options. + * + * @return array + * Media MIME types options. + */ + private function getFileMimeTypesMediaOptions() { + /** @var \Drupal\media\Entity\MediaType $entity */ + $entity = $this->getFormEntity(); + + if (!$entity instanceof MediaType) { + return $this->filterFileMimeTypesOptions(); + } + + if (empty($entity->get('source'))) { + return $this->filterFileMimeTypesOptions(); + } + + /** @var \Drupal\media\MediaSourceInterface $source */ + $source = $entity->getSource(); + $field_definition = $source->getSourceFieldDefinition($entity); + + // Get all the options when is creating a Media Type. + if (empty($field_definition)) { + return $this->filterFileMimeTypesOptions(); + } + + $file_extensions_allowed = $field_definition->getSetting('file_extensions'); + $file_extensions_allowed = explode(' ', $file_extensions_allowed); + + return $this->filterFileMimeTypesOptions($file_extensions_allowed); + } + + /** + * Gets the file MIME types options. + * + * @return array + * File file MIME types options. + */ + private function getFileMimeTypesFileOptions() { + /** @var \Drupal\file_entity\Entity\FileType|null $entity */ + $entity = $this->getFormEntity(); + + if (!interface_exists('\Drupal\file_entity\Entity\FileType') + || !$entity instanceof \Drupal\file_entity\Entity\FileType) { + return $this->filterFileMimeTypesOptions(); + } + + return $entity->getMimetypes(); + } + + /** + * Gets all file MIME types options. + * + * @return array + * All the file MIME types options supported. + * + * @todo Drupal 9.x will replace how mimetypes are mapped. + * See https://www.drupal.org/project/drupal/issues/2311679 + */ + private function getAllFileMimeTypesOptions() { + return $this->mimetypesHelper->get(); + } + + /** + * Filter the file MIME types based on allowed types. + * + * @param array $types_allowed + * The file types allowed. + * @param bool $by_extension + * Filter options by extension. + * + * @return array + * The options allowed. + */ + private function filterFileMimeTypesOptions(array $types_allowed = [], $by_extension = TRUE) { + $all_file_types = $this->getAllFileMimeTypesOptions(); + + if (empty($types_allowed)) { + $options = ['' => $this->t('- All types -')]; + $options += array_combine($all_file_types['mimetypes'], $all_file_types['mimetypes']); + return $options; + } + + if ($by_extension) { + return $this->filterFileMimeTypesOptionsByExtension($all_file_types, $types_allowed); + } + + return $this->filterFileMimeTypesOptionsByMimeType($all_file_types, $types_allowed); + } + + /** + * Filter the file MIME types based on allowed extensions. + * + * @param array $all_file_types + * All the file types available. + * @param array $types_allowed + * The file types allowed. + * + * @return array + * Options filtered by allowed extension. + */ + private function filterFileMimeTypesOptionsByExtension(array $all_file_types, array $types_allowed) { + $options = []; + + foreach ($all_file_types['extensions'] as $extension => $mimetype_id) { + if (!in_array($extension, $types_allowed)) { + continue; + } + + $mimetype_name = $all_file_types['mimetypes'][$mimetype_id]; + + if (in_array($extension, $options)) { + continue; + } + + $options[$mimetype_name] = $mimetype_name; + } + + return $options; + } + + /** + * Filter the file MIME types based on allowed mimetypes. + * + * @param array $all_file_types + * All the file types available. + * @param array $types_allowed + * The file types allowed. + * + * @return array + * Options filtered by allowed mimetypes. + */ + private function filterFileMimeTypesOptionsByMimeType(array $all_file_types, array $types_allowed) { + $options = []; + + foreach ($all_file_types['mimetypes'] as $mimetype) { + if (!in_array($mimetype, $types_allowed)) { + continue; + } + + $options[$mimetype] = $mimetype; + } + + return $options; + } + } diff --git a/src/Form/SimplesitemapEntitiesForm.php b/src/Form/SimplesitemapEntitiesForm.php index 5bd498e..c7b51a6 100644 --- a/src/Form/SimplesitemapEntitiesForm.php +++ b/src/Form/SimplesitemapEntitiesForm.php @@ -175,6 +175,7 @@ class SimplesitemapEntitiesForm extends SimplesitemapFormBase { if ($this->entityHelper->entityTypeIsAtomic($entity_type_id)) { foreach ($this->generator->getSitemapManager()->getSitemapVariants(NULL, FALSE) as $variant => $definition) { if (isset($values['index_' . $variant . '_' . $entity_type_id . '_settings'])) { + $mimeType = isset($values['file_mimetypes_' . $variant . '_' . $entity_type_id . '_settings']) ? $values['file_mimetypes_' . $variant . '_' . $entity_type_id . '_settings']: []; $this->generator ->setVariants($variant) ->setBundleSettings($entity_type_id, $entity_type_id, [ @@ -182,7 +183,8 @@ class SimplesitemapEntitiesForm extends SimplesitemapFormBase { 'priority' => $values['priority_' . $variant . '_' . $entity_type_id . '_settings'], 'changefreq' => $values['changefreq_' . $variant . '_' . $entity_type_id . '_settings'], 'include_images' => (bool) $values['include_images_' . $variant . '_' . $entity_type_id . '_settings'], - ]); + 'file_mimetypes' => $this->generator->getFileMimetypes($mimeType), + ]); } } } diff --git a/src/MimetypesHelper.php b/src/MimetypesHelper.php new file mode 100644 index 0000000..001fa7a --- /dev/null +++ b/src/MimetypesHelper.php @@ -0,0 +1,32 @@ +mapping === NULL) { + $mapping = $this->defaultMapping; + // Allow modules to alter the default mapping. + $this->moduleHandler->alter('file_mimetype_mapping', $mapping); + $this->mapping = $mapping; + } + + return $this->mapping; + } + +} diff --git a/src/Plugin/simple_sitemap/SitemapType/DefaultHreflangSitemapType.php b/src/Plugin/simple_sitemap/SitemapType/DefaultHreflangSitemapType.php index 357e3c1..8bdd912 100644 --- a/src/Plugin/simple_sitemap/SitemapType/DefaultHreflangSitemapType.php +++ b/src/Plugin/simple_sitemap/SitemapType/DefaultHreflangSitemapType.php @@ -3,7 +3,8 @@ namespace Drupal\simple_sitemap\Plugin\simple_sitemap\SitemapType; /** - * Class DefaultHreflangSitemapType + * Class DefaultHreflangSitemapType. + * * @package Drupal\simple_sitemap\Plugin\simple_sitemap\SitemapType * * @SitemapType( @@ -15,6 +16,7 @@ namespace Drupal\simple_sitemap\Plugin\simple_sitemap\SitemapType; * "custom", * "entity", * "entity_menu_link_content", + * "entity_file", * "arbitrary", * }, * ) diff --git a/src/Plugin/simple_sitemap/UrlGenerator/EntityFileUrlGenerator.php b/src/Plugin/simple_sitemap/UrlGenerator/EntityFileUrlGenerator.php new file mode 100644 index 0000000..44be175 --- /dev/null +++ b/src/Plugin/simple_sitemap/UrlGenerator/EntityFileUrlGenerator.php @@ -0,0 +1,243 @@ +entityHelper = $entity_helper; + $this->entityTypeManager = $entity_type_manager; + $this->anonUser = new AnonymousUserSession(); + } + + /** + * {@inheritDoc} + */ + public static function create( + ContainerInterface $container, + array $configuration, + $plugin_id, + $plugin_definition + ) { + return new static( + $configuration, + $plugin_id, + $plugin_definition, + $container->get('simple_sitemap.generator'), + $container->get('simple_sitemap.logger'), + $container->get('simple_sitemap.entity_helper'), + $container->get('entity_type.manager') + ); + } + + /** + * {@inheritDoc} + */ + public function getDataSets() { + $sitemap_entity_types = $this->entityHelper->getSupportedEntityTypes(); + + if (!isset($sitemap_entity_types['file'])) { + return []; + } + + $file_entity_keys = $sitemap_entity_types['file']->getKeys(); + + $bundles = $this->generator->setVariants($this->sitemapVariant)->getBundleSettings(); + + $data_sets = []; + + foreach (self::OVERRIDES_ENTITY_TYPE as $entity_type_name) { + if (!isset($sitemap_entity_types[$entity_type_name])) { + continue; + } + + if (!isset($bundles[$entity_type_name])) { + continue; + } + + foreach ($bundles[$entity_type_name] as $bundle_name => $bundle_settings) { + // Skip bundle if it will be generated in a different sitemap variant. + if ( + NULL !== $this->sitemapVariant && isset($bundle_settings['variant']) + && $bundle_settings['variant'] !== $this->sitemapVariant + ) { + $bundle_settings['index'] = FALSE; + } + unset($bundle_settings['variant']); + + if (empty($bundle_settings['index'])) { + continue; + } + + /** @var \Drupal\Core\Entity\EntityStorageInterface $file_entity_storage */ + $file_entity_storage = $this->entityTypeManager->getStorage('file'); + + $query = $file_entity_storage->getQuery(); + + // Only load files configured. + if (!empty($file_entity_keys['id'])) { + $query->sort($file_entity_keys['id'], 'ASC'); + } + if (!empty($file_entity_keys['bundle'])) { + $query->condition($file_entity_keys['bundle'], $bundle_name); + } + if (!empty($file_entity_keys['status'])) { + $query->condition($file_entity_keys['status'], 1); + } + if (isset($bundle_settings['file_mimetypes']) && !empty($bundle_settings['file_mimetypes'])) { + $query->condition('filemime', $bundle_settings['file_mimetypes'], 'IN'); + } + + foreach ($query->execute() as $file_id) { + if (in_array($file_id, array_column($data_sets, 'id'))) { + continue; + } + + $data_sets[] = [ + 'entity_type' => 'file', + 'id' => $file_id, + ]; + } + } + } + + return $data_sets; + } + + /** + * {@inheritDoc} + */ + protected function processDataSet($data_set) { + /** @var \Drupal\file\Entity\File $entity */ + if (empty($entity = $this->entityTypeManager->getStorage($data_set['entity_type'])->load($data_set['id']))) { + return FALSE; + } + + if (!($entity instanceof FileInterface)) { + return FALSE; + } + + $entity_id = $entity->id(); + $entity_type_name = $entity->getEntityTypeId(); + + $entity_settings = $this->generator + ->setVariants($this->sitemapVariant) + ->getEntityInstanceSettings($entity_type_name, $entity_id); + + if (empty($entity_settings['index'])) { + return FALSE; + } + + if (!$entity->access('view', $this->anonUser)) { + return FALSE; + } + + return [ + 'url' => $this->replaceBaseUrlWithCustom($entity->createFileUrl(FALSE)), + 'lastmod' => method_exists($entity, 'getChangedTime') ? date('c', $entity->getChangedTime()) : NULL, + 'priority' => isset($entity_settings['priority']) ? $entity_settings['priority'] : NULL, + 'changefreq' => !empty($entity_settings['changefreq']) ? $entity_settings['changefreq'] : NULL, + + // Additional info useful in hooks. + 'meta' => [ + 'path' => $entity->getFileUri(), + 'entity_info' => [ + 'entity_type' => $entity_type_name, + 'id' => $entity_id, + ], + ], + ]; + } + +} diff --git a/src/Plugin/simple_sitemap/UrlGenerator/EntityUrlGenerator.php b/src/Plugin/simple_sitemap/UrlGenerator/EntityUrlGenerator.php index efa2abf..fd7f0f5 100755 --- a/src/Plugin/simple_sitemap/UrlGenerator/EntityUrlGenerator.php +++ b/src/Plugin/simple_sitemap/UrlGenerator/EntityUrlGenerator.php @@ -10,7 +10,8 @@ use Drupal\Core\Entity\EntityTypeManagerInterface; use Symfony\Component\DependencyInjection\ContainerInterface; /** - * Class EntityUrlGenerator + * Class EntityUrlGenerator. + * * @package Drupal\simple_sitemap\Plugin\simple_sitemap\UrlGenerator * * @UrlGenerator( @@ -90,10 +91,18 @@ class EntityUrlGenerator extends EntityUrlGeneratorBase { foreach ($this->generator->setVariants($this->sitemapVariant)->getBundleSettings() as $entity_type_name => $bundles) { if (isset($sitemap_entity_types[$entity_type_name])) { - // Skip this entity type if another plugin is written to override its generation. + // Skip this entity type if it's overridden by other plugin generation. foreach ($this->urlGeneratorManager->getDefinitions() as $plugin) { - if (isset($plugin['settings']['overrides_entity_type']) - && $plugin['settings']['overrides_entity_type'] === $entity_type_name) { + // Skip this plugin definition if it doesn't override an entity type. + if (!isset($plugin['settings']['overrides_entity_type'])) { + continue; + } + + $plugin_entity_type_overridden = $plugin['settings']['overrides_entity_type']; + if ( + (is_array($plugin_entity_type_overridden) && in_array($entity_type_name, $plugin_entity_type_overridden)) + || ($plugin_entity_type_overridden === $entity_type_name) + ) { continue 2; } } diff --git a/src/Simplesitemap.php b/src/Simplesitemap.php index a3782ed..a6970b6 100644 --- a/src/Simplesitemap.php +++ b/src/Simplesitemap.php @@ -76,7 +76,13 @@ class Simplesitemap { * @var array */ protected static $allowedLinkSettings = [ - 'entity' => ['index', 'priority', 'changefreq', 'include_images'], + 'entity' => [ + 'index', + 'priority', + 'changefreq', + 'include_images', + 'file_mimetypes', + ], 'custom' => ['priority', 'changefreq'], ]; @@ -88,6 +94,7 @@ class Simplesitemap { 'priority' => '0.5', 'changefreq' => '', 'include_images' => FALSE, + 'file_mimetypes' => [], ]; /** @@ -966,4 +973,29 @@ class Simplesitemap { return $this; } + + /** + * Gets file MIME types values formatted. + * + * @param array $mimetypes + * The mimetypes configured. + * + * @return array + * The mimetypes formatted values. + */ + public function getFileMimetypes(array $mimetypes) { + $mimetypes = array_values($mimetypes); + + $values = []; + foreach ($mimetypes as $mimetype) { + if (empty($mimetype)) { + continue; + } + + $values[] = $mimetype; + } + + return $values; + } + }