Gets media files from all collection members
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

117 lines
3.8 KiB

<?php
declare(strict_types=1);
namespace Drupal\islandora_collection_harvest\Controller;
use Drupal\Core\StreamWrapper\StreamWrapperManagerInterface;
use Drupal\flysystem\FlysystemFactory;
use Drupal\Core\File\FileSystemInterface;
use Drupal\Core\TempStore\PrivateTempStoreFactory;
use Symfony\Component\HttpFoundation\StreamedResponse;
use Drupal\Core\Controller\ControllerBase;
use Symfony\Component\DependencyInjection\ContainerInterface;
final class HarvestDownloadController extends ControllerBase {
protected FileSystemInterface $fileSystem;
protected PrivateTempStoreFactory $tempStoreFactory;
protected FlysystemFactory $flysystemFactory;
protected StreamWrapperManagerInterface $streamWrapperManager;
public function __construct(
FileSystemInterface $file_system,
PrivateTempStoreFactory $tempStoreFactory,
FlysystemFactory $flysystemFactory,
StreamWrapperManagerInterface $streamWrapperManager
) {
$this->fileSystem = $file_system;
$this->tempStoreFactory = $tempStoreFactory;
$this->flysystemFactory = $flysystemFactory;
$this->streamWrapperManager = $streamWrapperManager;
}
public static function create(ContainerInterface $container): self {
return new self(
$container->get('file_system'),
$container->get('tempstore.private'),
$container->get('flysystem_factory'),
$container->get('stream_wrapper_manager')
);
}
/**
* Builds and downloads archive.
*
* @param string $filename
*
* @return \Symfony\Component\HttpFoundation\StreamedResponse
*/
public function download(string $filename): StreamedResponse {
$temp_store = $this->tempStoreFactory->get('islandora_collection_harvest');
$media_entities = $temp_store->get($filename);
if (empty($media_entities)) {
throw new \Symfony\Component\HttpKernel\Exception\NotFoundHttpException('No media found.');
}
return new StreamedResponse(function() use ($media_entities) {
$zip = new \ZipArchive();
$tmpfile = tempnam(sys_get_temp_dir(), 'collection_zip_');
$zip->open($tmpfile, \ZipArchive::CREATE | \ZipArchive::OVERWRITE);
foreach ($media_entities as $media) {
$source_field = $media->getSource()
->getConfiguration()['source_field'] ?? NULL;
if (!$source_field || !$media->hasField($source_field)) {
continue;
}
$file = $media->get($source_field)->entity;
if (!$file) {
continue;
}
$uri = $file->getFileUri();
$filename_in_zip = basename($uri);
$real_path = $this->fileSystem->realpath($uri);
if ($real_path && file_exists($real_path)) {
$zip->addFile($real_path, $filename_in_zip);
}
else {
// Flysystem v1 fallback
try {
$scheme = $this->streamWrapperManager->getScheme($uri);
$path = substr($uri, strlen($scheme) + 3);
$filesystem = $this->flysystemFactory->getFilesystem($scheme);
if ($filesystem && $filesystem->has($path)) {
$contents = $filesystem->read($path);
if ($contents !== FALSE) {
$tmp_fly = tempnam(sys_get_temp_dir(), 'zip_');
file_put_contents($tmp_fly, $contents);
$zip->addFile($tmp_fly, $filename_in_zip);
}
}
}
catch (\Exception $e) {
$this->logger('islandora_collection_harvest')->error(
'Error reading @uri from Flysystem: @msg',
['@uri' => $uri, '@msg' => $e->getMessage()]
);
}
}
}
$zip->close();
readfile($tmpfile);
unlink($tmpfile);
}, 200, [
'Content-Type' => 'application/zip',
'Content-Disposition' => 'attachment; filename="' . $filename . '"',
]);
}
}