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
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 . '"', |
|
]); |
|
} |
|
|
|
}
|
|
|