Skip to content

Commit

Permalink
Use Drupal’s mime type guesser service to determine local mime type (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
jastraat committed Feb 16, 2024
1 parent 8d092bb commit 0be1c1c
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 26 deletions.
1 change: 1 addition & 0 deletions modules/metastore/metastore.services.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ services:
- '@dkan.metastore.storage'
- '@dkan.metastore.url_generator'
- '@http_client'
- '@file.mime_type.guesser.extension'
calls:
- [setLoggerFactory, ['@logger.factory']]

Expand Down
49 changes: 28 additions & 21 deletions modules/metastore/src/Reference/Referencer.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;
use Symfony\Component\Mime\MimeTypeGuesserInterface;

/**
* Metastore referencer service.
Expand Down Expand Up @@ -50,20 +51,40 @@ class Referencer {
*/
private Client $httpClient;

/**
* The MIME type guesser.
*
* @var \Symfony\Component\Mime\MimeTypeGuesserInterface
*/
protected $mimeTypeGuesser;

/**
* Constructor.
*
* @param \Drupal\Core\Config\ConfigFactoryInterface $configService
* Drupal config factory service.
* @param \Contracts\FactoryInterface $storageFactory
* DKAN contracts factory.
* @param \Drupal\metastore\Reference\MetastoreUrlGenerator $metastoreUrlGenerator
* DKAN metastore url generator.
* @param \GuzzleHttp\Client $httpClient
* Guzzle http client.
* @param \Symfony\Component\Mime\MimeTypeGuesserInterface $mimeTypeGuesser
* The MIME type guesser.
*/
public function __construct(
ConfigFactoryInterface $configService,
FactoryInterface $storageFactory,
MetastoreUrlGenerator $metastoreUrlGenerator,
Client $httpClient
Client $httpClient,
MimeTypeGuesserInterface $mimeTypeGuesser
) {
$this->setConfigService($configService);
$this->storageFactory = $storageFactory;
$this->setLoggerFactory(\Drupal::service('logger.factory'));
$this->metastoreUrlGenerator = $metastoreUrlGenerator;
$this->httpClient = $httpClient;
$this->mimeTypeGuesser = $mimeTypeGuesser;
}

/**
Expand Down Expand Up @@ -312,27 +333,13 @@ private function getFileMapper(): ResourceMapper {
* The detected mime type or NULL on failure.
*/
private function getLocalMimeType(string $downloadUrl): ?string {
$mime_type = NULL;
// Use Drupal's mime type guesser service to get the mime type.
$mime_type = $this->mimeTypeGuesser->guessMimeType($downloadUrl);

// Retrieve and decode the file name from the supplied download URL's path.
$filename = \Drupal::service('file_system')->basename($downloadUrl);
$filename = urldecode($filename);

// Attempt to load the file by file name.
/** @var \Drupal\file\FileInterface[] $files */
$files = \Drupal::entityTypeManager()
->getStorage('file')
->loadByProperties(['filename' => $filename]);
$file = reset($files);

// If a valid file was found for the given file name, extract the file's
// mime type...
if ($file !== FALSE) {
$mime_type = $file->getMimeType();
}
// Otherwise, log an error notifying the user that a file was not found.
else {
$this->log('value_referencer', 'Unable to determine mime type of file with name "@name", because no file was found with that name.', [
// If we couldn't find a mime type, log an error notifying the user.
if (is_null($mime_type)) {
$filename = basename($downloadUrl);
$this->log('value_referencer', 'Unable to determine mime type of file with name "@name".', [
'@name' => $filename,
]);
}
Expand Down
23 changes: 20 additions & 3 deletions modules/metastore/tests/src/Unit/Reference/ReferencerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use Drupal\Core\Entity\EntityTypeManager;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\File\FileSystem;
use Drupal\Core\File\MimeType\ExtensionMimeTypeGuesser;
use Drupal\Core\Logger\LoggerChannelFactory;
use Drupal\Core\StreamWrapper\PublicStream;
use Drupal\Core\StreamWrapper\StreamWrapperManager;
Expand Down Expand Up @@ -35,6 +36,7 @@
use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Mime\MimeTypeGuesserInterface;

/**
* @covers \Drupal\metastore\Reference\Referencer
Expand Down Expand Up @@ -119,11 +121,16 @@ private function mockReferencer($existing = TRUE) {
->add(MetastoreUrlGenerator::class, 'uriFromUrl', 'dkan://metastore/schemas/data-dictionary/items/111')
->getMock();

$mimeTypeGuesser = (new Chain($this))
->add(MimeTypeGuesserInterface::class, 'guessMimeType', self::MIME_TYPE)
->getMock();

return new Referencer(
$configService,
$storageFactory,
$urlGenerator,
new Client()
new Client(),
$mimeTypeGuesser
);
}

Expand Down Expand Up @@ -394,11 +401,16 @@ public function getMimeType() { return ReferencerTest::MIME_TYPE; }
->add(MetastoreUrlGenerator::class, 'uriFromUrl', '')
->getMock();

$mimeTypeGuesser = (new Chain($this))
->add(MimeTypeGuesserInterface::class, 'guessMimeType', self::MIME_TYPE)
->getMock();

$referencer = new Referencer(
$configService,
$storageFactory,
$urlGenerator,
new Client()
new Client(),
$mimeTypeGuesser
);

// Test Mime Type detection using the resource `mediaType` property.
Expand Down Expand Up @@ -454,11 +466,16 @@ public function testDistributionHandlingDataDict($distribution, $describedBy) {
->disableOriginalConstructor()
->getMock();

$mimeTypeGuesser = (new Chain($this))
->add(MimeTypeGuesserInterface::class, 'guessMimeType', self::MIME_TYPE)
->getMock();

$referencer = new Referencer(
$configService,
$storageFactory,
$urlGenerator,
$http_client
$http_client,
$mimeTypeGuesser
);

if ($describedBy instanceof \Exception) {
Expand Down
3 changes: 1 addition & 2 deletions tests/src/Functional/DatasetBTBTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -514,8 +514,7 @@ private function getData(string $identifier, string $title, array $downloadUrls)
$distribution = new \stdClass();
$distribution->title = 'Distribution #' . $key . ' for ' . $identifier;
$distribution->downloadURL = $this->getDownloadUrl($downloadUrl);
$distribution->format = 'csv';
$distribution->mediaType = 'text/csv';
// Don't provide mime type or format fields since they're not required.

$data->distribution[] = $distribution;
}
Expand Down

0 comments on commit 0be1c1c

Please sign in to comment.