<?php
namespace App\Controller;
use App\Twig\LayoutExtension;
use App\Twig\PressExtension;
use Pimcore\Model\Asset;
use Pimcore\Model\DataObject\MediaAlbum;
use Pimcore\Model\DataObject\MediaAsset;
use Pimcore\Model\DataObject\PressArticle;
use Pimcore\Model\DataObject\PressDossier;
use Symfony\Component\HttpFoundation\File\Exception\AccessDeniedException;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\StreamedResponse;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Routing\Annotation\Route;
class DownloadController extends AbstractController
{
private LayoutExtension $layoutExtension;
private $assetBasePath = "/home/steiermark/www/public/var/assets";
public function __construct(LayoutExtension $layoutExtension, protected PressExtension $pressExtension) {
$this->layoutExtension = $layoutExtension;
}
/**
* @Route("/download/asset", name="app_asset_download")
* @param Request $request
* @return StreamedResponse
*/
public function downloadAction(Request $request)
{
$asset = Asset::getById($request->get('id'));
if (!$asset instanceof Asset) {
throw new NotFoundHttpException('asset not found');
}
$stream = $asset->getStream();
return new StreamedResponse(function () use ($stream) {
fpassthru($stream);
}, 200, [
'Content-Type' => $asset->getMimetype(),
'Content-Disposition' => sprintf('attachment; filename="%s"', $asset->getFilename()),
'Content-Length' => $asset->getFileSize(),
'X-Robots-Tag' => 'noindex'
]);
}
/**
* @Route("/{_locale}/download/press/watchlist/all", name="download-watchlist-press-all")
* @param Request $request
* @return \Symfony\Component\HttpFoundation\BinaryFileResponse|AccessDeniedHttpException
*/
public function downloadPressAllWatchlist(Request $request) {
if(!empty($request->getSession()->get('pressImageWishlistIds', [])) && !$this->layoutExtension->getMediaUser($request) && !\Pimcore::inDebugMode()) {
//if there are press images and the user is not logged in => download is not allowed
return new AccessDeniedHttpException('Log in to download press images');
}
$assets = [];
$language = $request->getLocale();
$this->addDossiersToAssetsArray($assets, $request, $language);
$this->addArticlesToAssetsArray($assets, $request, $language);
$this->addMediaAlbumToAssetsArray($assets, $request, $language);
$this->addMediaAlbumItemsToAssetsArray($assets, $request, $language);
$this->addImagesToAssetsArray($assets, $request, $language, true);
$this->addMediaAssetsToAssetsArray($assets, $request, $language);
$md5 = md5(serialize($assets));
$zipfile = PIMCORE_PRIVATE_VAR . '/press-all-watchlist-'.$md5.'.zip';
$this->createZipFile($zipfile, $assets);
$filename = 'watchlist.zip';
$fsPath = $zipfile;
$response = $this->file($fsPath, $filename);
$response->headers->add([
'Expires' => '0',
'Cache-Control' => 'must-revalidate',
'Pragma' => 'public',
'X-Robots-Tag' => 'noindex'
]);
$response->deleteFileAfterSend(true);
return $response;
}
/**
* @param Request $request
* @Route("/{_locale}/download/press/image/{assetId}", name="download-press-image")
*/
public function downloadMediaImage(Request $request) {
if(!$this->layoutExtension->getMediaUser($request) && !\Pimcore::inDebugMode()) {
//if there are press images and the user is not logged in => download is not allowed
throw new AccessDeniedHttpException('Log in to download press images');
}
$asset = Asset::getById($request->get('assetId'));
if(!$asset || !$asset->getMetadata('General.mediaArchive') || $asset->getMetadata('General.mediaArchive') != 1) {
throw new NotFoundHttpException('Media Image not found');
}
if($request->get('gdpr') and $request->get('gdpr') == 'checked') {
$stream = $asset->getStream();
return new StreamedResponse(function () use ($stream) {
fpassthru($stream);
}, 200, [
'Content-Type' => $asset->getMimetype(),
'Content-Disposition' => sprintf('attachment; filename="%s"', $asset->getFilename()),
'Content-Length' => $asset->getFileSize(),
'X-Robots-Tag' => 'noindex'
]);
}
throw new AccessDeniedException('gdpr not accepted');
}
/**
* @param Request $request
* @Route("/{_locale}/download/press/video/{assetId}", name="download-press-video")
*/
public function downloadMediaVideo(Request $request) {
$asset = Asset::getById($request->get('assetId'));
if(!$asset || !$asset->getMetadata('General.mediaArchive') || $asset->getMetadata('General.mediaArchive') != 1) {
throw new NotFoundHttpException('Media video not found');
}
if($request->get('gdpr') and $request->get('gdpr') == 'checked') {
$stream = $asset->getStream();
return new StreamedResponse(function () use ($stream) {
fpassthru($stream);
}, 200, [
'Content-Type' => $asset->getMimetype(),
'Content-Disposition' => sprintf('attachment; filename="%s"', $asset->getFilename()),
'Content-Length' => $asset->getFileSize(),
'X-Robots-Tag' => 'noindex'
]);
}
throw new AccessDeniedException('gdpr not accepted');
}
/**
* @Route("/{_locale}/download/press/watchlist/media-album", name="download-watchlist-media-album")
* @param Request $request
* @return \Symfony\Component\HttpFoundation\BinaryFileResponse
*/
public function downloadPressMediaAlbumWatchlist (Request $request) {
$assets = [];
$language = $request->getLocale();
$this->addMediaAlbumToAssetsArray($assets, $request, $language);
$md5 = md5(serialize($assets));
$zipfile = PIMCORE_PRIVATE_VAR . '/media-album-watchlist-'.$md5.'.zip';
$this->createZipFile($zipfile, $assets);
$filename = 'mediaAlbum.zip';
$fsPath = $zipfile;
$response = $this->file($fsPath, $filename);
$response->headers->add([
'Expires' => '0',
'Cache-Control' => 'must-revalidate',
'Pragma' => 'public',
'X-Robots-Tag' => 'noindex'
]);
$response->deleteFileAfterSend(true);
return $response;
}
/**
* @Route("/{_locale}/download/press/watchlist/media-album/items", name="download-watchlist-media-album-items")
* @param Request $request
* @return \Symfony\Component\HttpFoundation\BinaryFileResponse
*/
public function downloadPressMediaAlbumItemsWatchlist (Request $request) {
$assets = [];
$language = $request->getLocale();
$this->addMediaAlbumItemsToAssetsArray($assets, $request, $language);
$md5 = md5(serialize($assets));
$zipfile = PIMCORE_PRIVATE_VAR . '/media-album-watchlist-'.$md5.'.zip';
$this->createZipFile($zipfile, $assets);
$filename = 'mediaAlbum.zip';
$fsPath = $zipfile;
$response = $this->file($fsPath, $filename);
$response->headers->add([
'Expires' => '0',
'Cache-Control' => 'must-revalidate',
'Pragma' => 'public',
'X-Robots-Tag' => 'noindex'
]);
$response->deleteFileAfterSend(true);
return $response;
}
/**
* @Route("/{_locale}/download/press/watchlist/dossiers", name="download-watchlist-pressdossiers")
* @param Request $request
* @return \Symfony\Component\HttpFoundation\BinaryFileResponse
*/
public function downloadPressDossiersWatchlist(Request $request) {
$assets = [];
$language = $request->getLocale();
$this->addDossiersToAssetsArray($assets, $request, $language);
$md5 = md5(serialize($assets));
$zipfile = PIMCORE_PRIVATE_VAR . '/press-dossiers-watchlist-'.$md5.'.zip';
$this->createZipFile($zipfile, $assets);
$filename = 'dossiers.zip';
$fsPath = $zipfile;
$response = $this->file($fsPath, $filename);
$response->headers->add([
'Expires' => '0',
'Cache-Control' => 'must-revalidate',
'Pragma' => 'public',
'X-Robots-Tag' => 'noindex'
]);
$response->deleteFileAfterSend(true);
return $response;
}
/**
* @Route("/{_locale}/download/press/dossiers", name="download-pressdossiers")
* @param Request $request
* @return \Symfony\Component\HttpFoundation\BinaryFileResponse
*/
public function downloadPressDossiersById(Request $request) {
$assets = [];
$language = $request->getLocale();
$dossier = PressDossier::getById($request->get('id'));
if ($dossier) {
foreach ($dossier->getArticles() as $article) {
$this->addArticle($assets, $article, $language);
}
}
$md5 = md5(serialize($assets));
$zipfile = PIMCORE_PRIVATE_VAR . '/press-dossier-'.$md5.'.zip';
$this->createZipFile($zipfile, $assets);
$filename = 'dossier.zip';
$fsPath = $zipfile;
$response = $this->file($fsPath, $filename);
$response->headers->add([
'Expires' => '0',
'Cache-Control' => 'must-revalidate',
'Pragma' => 'public',
'X-Robots-Tag' => 'noindex'
]);
$response->deleteFileAfterSend(true);
return $response;
}
/**
* @Route("/{_locale}/download/press/watchlist/articles", name="download-watchlist-pressarticles")
* @param Request $request
* @return \Symfony\Component\HttpFoundation\BinaryFileResponse
*/
public function downloadPressArticlesWatchlist(Request $request)
{
$assets = [];
$language = $request->getLocale();
$this->addArticlesToAssetsArray($assets, $request, $language);
$md5 = md5(serialize($assets));
$zipfile = PIMCORE_PRIVATE_VAR . '/press-articles-watchlist-'.$md5.'.zip';
$this->createZipFile($zipfile, $assets);
$filename = 'articles.zip';
$fsPath = $zipfile;
$response = $this->file($fsPath, $filename);
$response->headers->add([
'Expires' => '0',
'Cache-Control' => 'must-revalidate',
'Pragma' => 'public',
'X-Robots-Tag' => 'noindex'
]);
$response->deleteFileAfterSend(true);
return $response;
}
/**
* @Route("/{_locale}/download/press/watchlist/images", name="download-watchlist-pressimages")
* @param Request $request
* @return \Symfony\Component\HttpFoundation\BinaryFileResponse
*/
public function downloadPressImagesWatchlist(Request $request)
{
if(!empty($request->getSession()->get('pressImageWishlistIds', [])) && !$this->layoutExtension->getMediaUser($request) && !\Pimcore::inDebugMode()) {
//if there are press images and the user is not logged in => download is not allowed
return new AccessDeniedHttpException('Log in to download press images');
}
$assets = [];
$language = $request->getLocale();
$this->addImagesToAssetsArray($assets, $request, $language);
$md5 = md5(serialize($assets));
$zipfile = PIMCORE_PRIVATE_VAR . '/press-images-watchlist-'.$md5.'.zip';
$this->createZipFile($zipfile, $assets);
$filename = 'images.zip';
$fsPath = $zipfile;
$response = $this->file($fsPath, $filename);
$response->headers->add([
'Expires' => '0',
'Cache-Control' => 'must-revalidate',
'Pragma' => 'public',
'X-Robots-Tag' => 'noindex'
]);
$response->deleteFileAfterSend(true);
return $response;
}
/**
* @Route("/{_locale}/download/press/media-album", name="download-media-album")
* @param Request $request
* @return \Symfony\Component\HttpFoundation\BinaryFileResponse
*/
public function downloadMediaAlbum(Request $request)
{
$mediaAlbum = MediaAlbum::getById($request->get('id'));
if(!$mediaAlbum) {
throw new NotFoundHttpException('Media Album not found');
}
$assets = [];
$language = $request->getLocale();
$this->addMediaAlbumToArray($mediaAlbum->getAlbumItems(), $assets, $mediaAlbum->getTitle($language));
$md5 = md5(serialize($assets));
$zipfile = PIMCORE_PRIVATE_VAR . '/press-media-album-'.$md5.'.zip';
$this->createZipFile($zipfile, $assets);
$filename = ($mediaAlbum->getTitle($language) ?? 'media-album' . $mediaAlbum->getId()) . '.zip';
$fsPath = $zipfile;
$response = $this->file($fsPath, $filename);
$response->headers->add([
'Expires' => '0',
'Cache-Control' => 'must-revalidate',
'Pragma' => 'public',
'X-Robots-Tag' => 'noindex'
]);
$response->deleteFileAfterSend(true);
return $response;
}
/**
* @Route("/{_locale}/download/press/watchlist/media-assets", name="download-watchlist-media-assets")
* @param Request $request
* @return \Symfony\Component\HttpFoundation\BinaryFileResponse
*/
public function downloadPressMediaAssetsWatchlist(Request $request)
{
if(!empty($request->getSession()->get('pressMediaAssetsWishlistIds', [])) && !$this->layoutExtension->getMediaUser($request) && !\Pimcore::inDebugMode()) {
//if there are press images and the user is not logged in => download is not allowed
return new AccessDeniedHttpException('Log in to download press images');
}
$assets = [];
$language = $request->getLocale();
$this->addMediaAssetsToAssetsArray($assets, $request, $language);
$md5 = md5(serialize($assets));
$zipfile = PIMCORE_PRIVATE_VAR . '/press-media-assets-watchlist-'.$md5.'.zip';
$this->createZipFile($zipfile, $assets);
$filename = 'media-assets.zip';
$fsPath = $zipfile;
$response = $this->file($fsPath, $filename);
$response->headers->add([
'Expires' => '0',
'Cache-Control' => 'must-revalidate',
'Pragma' => 'public',
'X-Robots-Tag' => 'noindex'
]);
$response->deleteFileAfterSend(true);
return $response;
}
private function createZipFile($zipfile, $assets) {
#zip it
$zip = new \ZipArchive();
if(file_exists($zipfile)) { unlink($zipfile); }
$zip->open($zipfile, \ZipArchive::CREATE);
$createdStructure = [];
#only two subdirs supported atm
foreach ($assets as $dir1 => $file1) {
if (is_array($file1)) {
if (!in_array($dir1, $createdStructure)) {
$zip->addEmptyDir($dir1);
$createdStructure[] = $dir1;
}
foreach ($file1 as $dir2 => $file2) {
if (is_array($file2)) {
if (!in_array($dir1 . '/' . $dir2, $createdStructure)) {
$zip->addEmptyDir($dir1 . '/' . $dir2);
$createdStructure[] = $dir1 . '/' . $dir2;
}
foreach ($file2 as $dir3 => $file3) {
if (!is_array($file3) && file_exists($file3)) {
$zip->addFile(urldecode($file3), $dir1 . '/' . $dir2 . '/' . basename($dir3));
}
}
} else {
if(file_exists($file2)) {
$zip->addFile(urldecode($file2), $dir1 . '/' . basename($dir2));
}
}
}
} else {
if(file_exists($file1)) {
$zip->addFile(urldecode($file1), basename($dir1));
}
}
}
$zip->close();
return $zip;
}
private function getPressArticlesFromCache(Request $request) : array {
$pressArticles = [];
$pressArticleIds = $request->getSession()->get('pressArticleWishlistIds', []);
if(!empty($pressArticleIds)) {
foreach ($pressArticleIds as $id) {
if($pressArticle = PressArticle::getById($id)) {
$pressArticles[] = $pressArticle;
}
}
}
return $pressArticles;
}
private function getPressDossiersFromCache(Request $request) {
$pressDossiers = [];
$pressDossiersIds = $request->getSession()->get('pressDossierWishlistIds', []);
if(!empty($pressDossiersIds)) {
foreach ($pressDossiersIds as $id) {
if($pressDossier = PressDossier::getById($id)) {
$pressDossiers[] = $pressDossier;
}
}
}
return $pressDossiers;
}
private function getPressMediaAlbumsFromCache(Request $request) {
$pressMediaAlbums = [];
$mediaAlbumIds = $request->getSession()->get('pressAlbumWishlistIds', []);
if(!empty($mediaAlbumIds)) {
foreach ($mediaAlbumIds as $id) {
if($mediaAlbum = MediaAlbum::getById($id)) {
$pressMediaAlbums[] = $mediaAlbum;
}
}
}
return $pressMediaAlbums;
}
private function getPressMediaAlbumItemsFromCache(Request $request) {
$pressMediaAlbumItems = [];
$mediaAlbumItemsIds = $request->getSession()->get('pressAlbumItemsWishlistIds', []);
if(!empty($mediaAlbumItemsIds)) {
foreach ($mediaAlbumItemsIds as $id) {
if($mediaAlbum = Asset::getById($id)) {
$pressMediaAlbumItems[] = $mediaAlbum;
}
}
}
return $pressMediaAlbumItems;
}
private function getPressMediaAssetsFromCache(Request $request) {
$pressMediaAssets = [];
$mediaAssetsIds = $request->getSession()->get('pressMediaAssetsWishlistIds', []);
if(!empty($mediaAssetsIds)) {
foreach ($mediaAssetsIds as $id) {
if(($mediaAsset = MediaAsset::getById($id)) && $mediaAsset->getAsset()) {
$pressMediaAssets[] = $mediaAsset->getAsset();
}
}
}
return $pressMediaAssets;
}
private function addArticle( array &$assets, PressArticle $pressArticle, string $language) {
//prepares data (images, articles,...) from the PressArticle for the ZIP-download including the correct folder structure
$articleAssets = [];
if($pressArticle->getArticleDocument($language)) {
$articleAssets[$pressArticle->getId() . '-'. basename($pressArticle->getArticleDocument($language)->getFullPath())] = $pressArticle->getArticleDocument($language)->getLocalFile();
}
foreach($pressArticle->getDocuments() as $document) {
if($document instanceof \Pimcore\Model\Asset\Video) {
$articleAssets['videos'][$document->getId() . '-' . basename($document->getFullPath())] = $document->getLocalFile();
} elseif($document instanceof \Pimcore\Model\Asset) {
$articleAssets['documents'][$document->getId() . '-' .basename($document->getFullPath())] = $document->getLocalFile();
}
}
$assets[$pressArticle->getId() . '-' . $pressArticle->getKey()] = $articleAssets;
}
private function addDossiersToAssetsArray(array &$assets, Request $request, string $language) {
$pressDossiers = $this->getPressDossiersFromCache($request);
if(!empty($pressDossiers)) {
foreach ($pressDossiers as $dossier) {
if ($dossier instanceof PressDossier) {
if($this->pressExtension->isDownloadableDossier($dossier, $this->layoutExtension->getMediaUser($request))) {
foreach ($dossier->getArticles() as $article) {
$this->addArticle($assets, $article, $language);
}
}
}
}
}
}
private function addMediaAlbumToAssetsArray(array &$assets, Request $request, string $language) {
$mediaAlbums = $this->getPressMediaAlbumsFromCache($request);
if(!empty($mediaAlbums)) {
foreach ($mediaAlbums as $mediaAlbum) {
if ($mediaAlbum instanceof MediaAlbum) {
$this->addMediaAlbumToArray($mediaAlbum->getAlbumItems(), $assets, $mediaAlbum->getTitle($language));
}
}
}
}
private function addMediaAlbumItemsToAssetsArray(array &$assets, Request $request, string $language) {
$mediaAlbumItems = $this->getPressMediaAlbumItemsFromCache($request);
if(!empty($mediaAlbumItems)) {
$this->addMediaAlbumToArray($mediaAlbumItems, $assets, 'single media album assets');
}
}
private function addMediaAssetsToAssetsArray(array &$assets, Request $request, string $language) {
$mediaAssets = $this->getPressMediaAssetsFromCache($request);
if(!empty($mediaAssets)) {
$this->addMediaAlbumToArray($mediaAssets, $assets, 'media assets');
}
}
private function addArticlesToAssetsArray(array &$assets, Request $request, string $language) {
$pressArticles = $this->getPressArticlesFromCache($request);
if(!empty($pressArticles)) {
foreach ($pressArticles as $pressArticle) {
if($pressArticle instanceof PressArticle && $this->pressExtension->isDownloadableArticle($pressArticle, $this->layoutExtension->getMediaUser($request))) {
$this->addArticle($assets, $pressArticle, $language);
}
}
}
}
private function addImagesToAssetsArray(array &$assets, Request $request, string $language, bool $imagesInFolder = false) {
$images = $request->getSession()->get('pressImageWishlistIds', []);
if(!empty($images)) {
foreach ($images as $imageId) {
if(($asset = Asset::getById($imageId)) && $asset->getMetadata('General.mediaArchive') && $asset->getMetadata('General.mediaArchive') == 1 &&
$this->pressExtension->isDownloadableAsset($asset, $this->layoutExtension->getMediaUser($request))) {
if($imagesInFolder) {
$assets['images'][$asset->getId() . '-' . $asset->getKey()] = $asset->getLocalFile();
} else {
$assets[$asset->getId() . '-' . $asset->getKey()] = $asset->getLocalFile();
}
}
}
}
}
private function addMediaAlbumToArray(array $albumItems, array &$downloadAssets, string $albumName) {
foreach ($albumItems as $item) {
if($item instanceof Asset\Image) {
$downloadAssets[$albumName][$item->getId() . '-' . $item->getKey()] = $item->getLocalFile();
} elseif($item instanceof Asset\Video) {
$downloadAssets[$albumName][$item->getId() . '-' . $item->getKey()] = $item->getLocalFile();
} elseif($item instanceof Asset\Folder) {
$this->addMediaAlbumToArray($item->getChildren(), $downloadAssets, $albumName);
} elseif($item instanceof Asset) {
$downloadAssets[$albumName][$item->getId() . '-' . $item->getKey()] = $item->getLocalFile();
}
}
}
}