Files
Phraseanet/lib/Alchemy/Phrasea/Controller/Prod/DownloadController.php
jygaulier 7d703b690f PHRAS-3928_download_async WIP ok to test (#4386)
* WIP/POC DO NOT MERGE
use "pusher" to wait for export-by-email worker to tell client that export is done.
nb: export worker is artificially delayed by 30s !

* WIP OK TO TEST ; DO NOT MERGE

* WIP/POC DO NOT MERGE
use "pusher" to wait for export-by-email worker to tell client that export is done.
nb: export worker is artificially delayed by 30s !

* WIP OK TO TEST ; DO NOT MERGE

* cleanup

* cleanup

* better conf & cleanup

* fix typo

* fix stamp transparency (bump imagine)
fix missing cgu for one file download
better cli feedback
add (re)download link on cli

* fix test

* fix missing js feedback (when worker publish before client subscribes)

* cleanup

* fix "remove stamp" choice

* add default conf

* WIP/POC DO NOT MERGE
use "pusher" to wait for export-by-email worker to tell client that export is done.
nb: export worker is artificially delayed by 30s !

* WIP OK TO TEST ; DO NOT MERGE

* WIP/POC DO NOT MERGE
use "pusher" to wait for export-by-email worker to tell client that export is done.
nb: export worker is artificially delayed by 30s !

* WIP OK TO TEST ; DO NOT MERGE

* cleanup

* cleanup

* better conf & cleanup

* fix typo

* fix stamp transparency (bump imagine)
fix missing cgu for one file download
better cli feedback
add (re)download link on cli

* fix test

* fix missing js feedback (when worker publish before client subscribes)

* cleanup

* fix "remove stamp" choice

* add default conf

* WIP OK TO TEST generates an excel report for async download.
define some env-vars for Pusher (todo: fix entrypoint to add during install)

* fix xl formating for tabs >1
add env_vars to config build

* fix test
2023-10-30 15:08:55 +01:00

216 lines
7.1 KiB
PHP

<?php
/*
* This file is part of Phraseanet
*
* (c) 2005-2016 Alchemy
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Phrasea\Controller\Prod;
use Alchemy\Phrasea\Application\Helper\DispatcherAware;
use Alchemy\Phrasea\Controller\Controller;
use Alchemy\Phrasea\Core\Configuration\PropertyAccess;
use Alchemy\Phrasea\Core\Event\DownloadAsyncEvent;
use Alchemy\Phrasea\Core\Event\ExportEvent;
use Alchemy\Phrasea\Core\PhraseaEvents;
use Alchemy\Phrasea\Model\Manipulator\TokenManipulator;
use set_export;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
class DownloadController extends Controller
{
use DispatcherAware;
/**
* Download a set of documents
*
* @param Request $request
* @return RedirectResponse
*/
public function checkDownload(Request $request)
{
if (!$this->isCrsfValid($request, 'prodExportDownload')) {
$this->app->abort(403);
}
$lst = $request->request->get('lst');
$ssttid = $request->request->get('ssttid', '');
$subdefs = $request->request->get('obj', []);
$download = new \set_export($this->app, $lst, $ssttid);
if (0 === $download->get_total_download()) {
$this->app->abort(403);
}
$list = $download->prepare_export(
$this->getAuthenticatedUser(),
$this->app['filesystem'],
$subdefs,
$request->request->get('type') === 'title' ? true : false,
$request->request->get('businessfields'),
$request->request->get('stamp_choice') === "NO_STAMP" ? \set_export::NO_STAMP : \set_export::STAMP_SYNC
);
$list['export_name'] = sprintf('%s.zip', $download->getExportName());
$token = $this->getTokenManipulator()->createDownloadToken($this->getAuthenticatedUser(), serialize($list));
$this->getDispatcher()->dispatch(PhraseaEvents::EXPORT_CREATE, new ExportEvent(
$this->getAuthenticatedUser(),
$ssttid,
$lst,
$subdefs,
$download->getExportName()
)
);
/** @see DoDownloadController::prepareDownload */
return $this->app->redirectPath('prepare_download', ['token' => $token->getValue()]);
}
/**
* display the downloasAsync page
*
* @param Request $request
* @return Response
*/
public function listDownloadAsync(Request $request)
{
if (!$this->isCrsfValid($request, 'prodExportDownload')) {
$this->app->abort(403);
}
$lst = $request->request->get('lst');
$ssttid = $request->request->get('ssttid', '');
$subdefs = $request->request->get('obj', []);
$download = new \set_export($this->app, $lst, $ssttid);
if (0 === $download->get_total_download()) {
$this->app->abort(403);
}
// "stamp_choice" is a ckbox with value "NO_STAMP" to "remove stamp" on download
$stamp_method = set_export::STAMP_ASYNC; // will not stamp, but flag files to be stamped
if($request->request->get('stamp_choice') === set_export::NO_STAMP) {
$stamp_method = set_export::NO_STAMP;
}
$list = $download->prepare_export(
$this->getAuthenticatedUser(),
$this->app['filesystem'],
$subdefs,
$request->request->get('type') === 'title' ? true : false,
$request->request->get('businessfields'),
// do not stamp now, worker will do
$stamp_method,
true
);
$list['export_name'] = sprintf('%s.zip', $download->getExportName());
$list['include_report'] = $request->request->get('include_report') === 'INCLUDE_REPORT';
$list['include_businessfields'] = (bool)$request->request->get('businessfields');
$records = [];
foreach ($list['files'] as $file) {
if (!is_array($file) || !isset($file['base_id']) || !isset($file['record_id'])) {
continue;
}
$sbasId = \phrasea::sbasFromBas($this->app, $file['base_id']);
try {
$record = new \record_adapter($this->app, $sbasId, $file['record_id']);
} catch (\Exception $e) {
continue;
}
$records[sprintf('%s_%s', $sbasId, $file['record_id'])] = $record;
}
$token = $this->getTokenManipulator()->createDownloadToken($this->getAuthenticatedUser(), serialize($list));
$pusher_auth_key =$this->getConf()->get(['download_async', 'enabled'], false) ? $this->getConf()->get(['pusher', 'auth_key'], '') : null;
return new Response($this->render(
/** @uses templates/web/prod/actions/Download/prepare_async.html.twig */
'/prod/actions/Download/prepare_async.html.twig', [
'module_name' => $this->app->trans('Export'),
'module' => $this->app->trans('Export'),
'list' => $list,
'records' => $records,
'token' => $token,
'anonymous' => $request->query->get('anonymous', false),
'type' => $request->query->get('type', \Session_Logger::EVENT_EXPORTDOWNLOAD),
'pusher_auth_key' => $pusher_auth_key,
'csrfToken' => $this->getSession()->get('prodExportDownload_token'),
]));
}
/**
* @param Request $request
* @return JsonResponse|void
* @throws \Doctrine\ORM\NonUniqueResultException
*/
public function startDownloadAsync(Request $request)
{
if (!$this->isCrsfValid($request, 'prodExportDownload')) {
$this->app->abort(403);
}
try {
$token = $this->getTokenManipulator()->findValidToken($request->request->get('token', ""));
if ($token) {
// ask the worker to build the zip
$this->dispatch(PhraseaEvents::DOWNLOAD_ASYNC_CREATE, new DownloadAsyncEvent(
$token->getUser()->getId(),
$token->getValue(),
[
]
));
return new JsonResponse([
'success' => true,
'token' => $token->getValue()
]);
}
else {
throw new \Exception("invalid or expired token");
}
}
catch(\Exception $e) {
// no-op
$this->app->abort(403, $e->getMessage());
}
}
/**
* @return TokenManipulator
*/
private function getTokenManipulator()
{
return $this->app['manipulator.token'];
}
/**
* @return PropertyAccess
*/
protected function getConf()
{
return $this->app['conf'];
}
/**
* @return PropertyAccess
*/
protected function getSession()
{
return $this->app['session'];
}
}