diff --git a/lib/Alchemy/Phrasea/Controller/Admin/DataboxController.php b/lib/Alchemy/Phrasea/Controller/Admin/DataboxController.php index 987585789a..81829f659b 100644 --- a/lib/Alchemy/Phrasea/Controller/Admin/DataboxController.php +++ b/lib/Alchemy/Phrasea/Controller/Admin/DataboxController.php @@ -15,10 +15,11 @@ use Alchemy\Phrasea\Authentication\Authenticator; use Alchemy\Phrasea\Controller\Controller; use Alchemy\Phrasea\Core\Configuration\DisplaySettingService; -use Alchemy\Phrasea\Model\Manipulator\TaskManipulator; use Alchemy\Phrasea\SearchEngine\Elastic\ElasticsearchOptions; use Alchemy\Phrasea\WorkerManager\Event\PopulateIndexEvent; use Alchemy\Phrasea\WorkerManager\Event\WorkerEvents; +use collection; +use Exception; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\RedirectResponse; @@ -103,7 +104,8 @@ public function deleteBase(Request $request, $databox_id) $success = true; $msg = $this->app->trans('Successful removal'); } - } catch (\Exception $e) { + } + catch (Exception $e) { } if (!$databox) { @@ -150,7 +152,8 @@ public function setLabels(Request $request, $databox_id) $value = $labels[$code] ?: null; $databox->set_label($code, $value); } - } catch (\Exception $e) { + } + catch (Exception $e) { $success = false; } @@ -190,7 +193,9 @@ public function reindex(Request $request, $databox_id) try { $this->getDispatcher()->dispatch(WorkerEvents::POPULATE_INDEX, new PopulateIndexEvent($populateInfo)); $success = true; - } catch (\Exception $e) { + } + catch (Exception $e) { + // no-op } if ('json' === $request->getRequestFormat()) { @@ -222,8 +227,8 @@ public function setIndexable(Request $request, $databox_id) $indexable = !!$request->request->get('indexable', false); $this->getApplicationBox()->set_databox_indexable($databox, $indexable); $success = true; - } catch (\Exception $e) { - + } catch (Exception $e) { + // no-op } if ('json' === $request->getRequestFormat()) { @@ -255,7 +260,8 @@ public function updateDatabaseCGU(Request $request, $databox_id) foreach ($request->request->get('TOU', []) as $loc => $terms) { $databox->update_cgus($loc, $terms, !!$request->request->get('valid', false)); } - } catch (\Exception $e) { + } + catch (Exception $e) { return $this->app->redirectPath('admin_database_display_cgus', [ 'databox_id' => $databox_id, 'success' => 0, @@ -283,7 +289,7 @@ public function mountCollection(Request $request, $databox_id, $collection_id) try { /** @var Authenticator $authenticator */ $authenticator = $this->app->getAuthenticator(); - $baseId = \collection::mount_collection( + $baseId = collection::mount_collection( $this->app, $this->findDataboxById($databox_id), $collection_id, @@ -315,7 +321,8 @@ public function mountCollection(Request $request, $databox_id, $collection_id) 'databox_id' => $databox_id, 'mount' => 'ok', ]); - } catch (\Exception $e) { + } + catch (Exception $e) { $connection->rollBack(); return $this->app->redirectPath('admin_database', [ @@ -366,7 +373,8 @@ public function sendLogoPdf(Request $request, $databox_id) 'error' => 'file-invalid', ]); } - } catch (\Exception $e) { + } + catch (Exception $e) { return $this->app->redirectPath('admin_database', [ 'databox_id' => $databox_id, 'success' => '0', @@ -395,8 +403,9 @@ public function deleteLogoPdf(Request $request, $databox_id) \databox::PIC_PDF ); $success = true; - } catch (\Exception $e) { - + } + catch (Exception $e) { + // no-op } if ('json' === $request->getRequestFormat()) { @@ -428,8 +437,9 @@ public function clearLogs(Request $request, $databox_id) try { $this->findDataboxById($databox_id)->clear_logs(); $success = true; - } catch (\Exception $e) { - + } + catch (Exception $e) { + // no-op } if ('json' === $request->getRequestFormat()) { @@ -465,8 +475,9 @@ public function changeViewName(Request $request, $databox_id) try { $this->findDataboxById($databox_id)->set_viewname($viewName); $success = true; - } catch (\Exception $e) { - + } + catch (Exception $e) { + // no-op } if ('json' === $request->getRequestFormat()) { @@ -500,8 +511,9 @@ public function unmountDatabase(Request $request, $databox_id) $databox->unmount_databox(); $success = true; - } catch (\Exception $e) { - + } + catch (Exception $e) { + // no-op } if ('json' === $request->getRequestFormat()) { @@ -553,8 +565,9 @@ public function emptyDatabase(Request $request, $databox_id) // if ($taskCreated) { // $msg = $this->app->trans('A task has been created, please run it to complete empty collection'); // } - } catch (\Exception $e) { - + } + catch (Exception $e) { + // no-op } if ('json' === $request->getRequestFormat()) { @@ -612,8 +625,9 @@ public function progressBarInfos(Request $request, $databox_id) $ret['success'] = true; $ret['msg'] = $this->app->trans('Successful update'); - } catch (\Exception $e) { - + } + catch (Exception $e) { + // no-op } return $this->app->json($ret); @@ -645,11 +659,12 @@ public function setReorder(Request $request, $databox_id) { try { foreach ($request->request->get('order', []) as $data) { - $collection = \collection::getByBaseId($this->app, $data['id']); + $collection = collection::getByBaseId($this->app, $data['id']); $collection->set_ord($data['offset']); } $success = true; - } catch (\Exception $e) { + } + catch (Exception $e) { $success = false; } @@ -680,11 +695,11 @@ public function getNewCollection() /** * Create a new collection * - * @param Request $request The current HTTP request - * @param integer $databox_id The requested databox + * @param Request $request The current HTTP request + * @param integer $databox_id The requested databox * @return Response */ - public function createCollection(Request $request, $databox_id) + public function createCollection(Request $request, int $databox_id) { if (($name = trim($request->request->get('name', ''))) === '') { return $this->app->redirectPath('admin_database_display_new_collection_form', [ @@ -695,7 +710,7 @@ public function createCollection(Request $request, $databox_id) try { $databox = $this->findDataboxById($databox_id); - $collection = \collection::create( + $collection = collection::create( $this->app, $databox, $this->getApplicationBox(), $name, @@ -721,7 +736,8 @@ public function createCollection(Request $request, $databox_id) 'success' => 1, 'reload-tree' => 1, ]); - } catch (\Exception $e) { + } + catch (Exception $e) { return $this->app->redirectPath('admin_database_submit_collection', [ 'databox_id' => $databox_id, 'error' => $e->getMessage(), diff --git a/lib/Alchemy/Phrasea/Controller/Prod/ExportController.php b/lib/Alchemy/Phrasea/Controller/Prod/ExportController.php index 6ccea28428..a1f82104e4 100644 --- a/lib/Alchemy/Phrasea/Controller/Prod/ExportController.php +++ b/lib/Alchemy/Phrasea/Controller/Prod/ExportController.php @@ -22,6 +22,7 @@ use Alchemy\Phrasea\WorkerManager\Event\WorkerEvents; use DOMDocument; use DOMXPath; +use Exception; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -61,8 +62,10 @@ public function displayMultiExport(Request $request) $removeable_stamp = false; // true if at least one coll is "unstampable" $removeable_stamp_by_base = []; // unset: no stamp ; false: stamp not "unstampable" ; true: stamp "unstampable" - $colls_manageable = array_keys($this->getAclForConnectedUser()->get_granted_base([ACL::COLL_MANAGE]) ?? []); - $dbox_manageable = array_keys($this->getAclForConnectedUser()->get_granted_sbas([ACL::BAS_MANAGE]) ?? []); + $colls_manageable = array_keys($this->getAclForConnectedUser()->get_granted_base([ACL::COLL_MANAGE]) ?? []); + $colls_editable = array_keys($this->getAclForConnectedUser()->get_granted_base([ACL::CANMODIFRECORD]) ?? []); + $colls_imgtoolsable = array_keys($this->getAclForConnectedUser()->get_granted_base([ACL::IMGTOOLS]) ?? []); + $dbox_manageable = array_keys($this->getAclForConnectedUser()->get_granted_sbas([ACL::BAS_MANAGE]) ?? []); foreach($download->get_elements() as $recordAdapter) { // check collection only once @@ -92,6 +95,16 @@ public function displayMultiExport(Request $request) $removeable_stamp_by_base[$bid] = $removeable_stamp = true; } break; + case 'record_edit': + if (in_array($bid, $colls_editable)) { + $removeable_stamp_by_base[$bid] = $removeable_stamp = true; + } + break; + case 'image_tools': + if (in_array($bid, $colls_imgtoolsable)) { + $removeable_stamp_by_base[$bid] = $removeable_stamp = true; + } + break; case 'manage_databox': if (in_array($recordAdapter->getDatabox()->get_sbas_id(), $dbox_manageable)) { $removeable_stamp_by_base[$bid] = $removeable_stamp = true; @@ -138,7 +151,9 @@ public function testFtpConnexion(Request $request) $ftpClient->close(); $msg = $this->app->trans('Connection to FTP succeed'); $success = true; - } catch (\Exception $e) { + } + catch (Exception $e) { + // no-op } return $this->app->json([ @@ -184,7 +199,7 @@ public function exportFtp(Request $request) \set_export::STAMP_ASYNC, $request->request->get('stamp_choice') === "REMOVE_STAMP", false - ); + ); $exportFtpId = $download->export_ftp( $request->request->get('user_dest'), @@ -206,7 +221,8 @@ public function exportFtp(Request $request) 'success' => true, 'message' => $this->app->trans('Export saved in the waiting queue') ]); - } catch (\Exception $e) { + } + catch (Exception $e) { return $this->app->json([ 'success' => false, 'message' => $e->getMessage()//$this->app->trans('Something went wrong') @@ -217,8 +233,9 @@ public function exportFtp(Request $request) /** * Export document by mail * - * @param Request $request + * @param Request $request * @return JsonResponse + * @throws Exception */ public function exportMail(Request $request) { diff --git a/lib/Alchemy/Phrasea/ControllerProvider/Admin/Databox.php b/lib/Alchemy/Phrasea/ControllerProvider/Admin/Databox.php index 7f809c1e32..f17ccc1b8f 100644 --- a/lib/Alchemy/Phrasea/ControllerProvider/Admin/Databox.php +++ b/lib/Alchemy/Phrasea/ControllerProvider/Admin/Databox.php @@ -72,6 +72,7 @@ public function connect(Application $app) ->before([$this, 'requireManageRightOnSbas']) ->bind('admin_database_submit_collections_order'); + /** @uses DataboxController::createCollection */ $controllers->post('/{databox_id}/collection/', 'controller.admin.databox:createCollection') ->before([$this, 'requireManageRightOnSbas']) ->bind('admin_database_submit_collection'); @@ -97,6 +98,7 @@ public function connect(Application $app) ->before([$this, 'requireManageRightOnSbas']) ->bind('admin_database_display_document_details'); + /** @uses DataboxController::mountCollection */ $controllers->post('/{databox_id}/collection/{collection_id}/mount/', 'controller.admin.databox:mountCollection') ->assert('collection_id', '\d+') ->before([$this, 'requireManageRightOnSbas']) diff --git a/lib/Alchemy/Phrasea/Model/Entities/FtpExportElement.php b/lib/Alchemy/Phrasea/Model/Entities/FtpExportElement.php index 7fc3b4f920..c61b6912d7 100644 --- a/lib/Alchemy/Phrasea/Model/Entities/FtpExportElement.php +++ b/lib/Alchemy/Phrasea/Model/Entities/FtpExportElement.php @@ -95,6 +95,11 @@ class FtpExportElement */ private $updated; + /** + * @ORM\Column(type="boolean", options={"default" = 0}) + */ + private $toStamp = false; + /** * Get id * @@ -368,4 +373,20 @@ public function getExport() { return $this->export; } + + /** + * @return bool + */ + public function isToStamp(): bool + { + return $this->toStamp; + } + + /** + * @param bool $toStamp + */ + public function setToStamp(bool $toStamp) + { + $this->toStamp = $toStamp; + } } diff --git a/lib/Alchemy/Phrasea/WorkerManager/Worker/ExportMailWorker.php b/lib/Alchemy/Phrasea/WorkerManager/Worker/ExportMailWorker.php index f60849dbfd..0e33106341 100644 --- a/lib/Alchemy/Phrasea/WorkerManager/Worker/ExportMailWorker.php +++ b/lib/Alchemy/Phrasea/WorkerManager/Worker/ExportMailWorker.php @@ -88,7 +88,7 @@ public function process(array $payload) foreach($list['files'] as $k_file => $v_file) { foreach($v_file['subdefs'] as $k_subdef => $v_subdef) { - if($k_subdef === "document" && $v_subdef['to_stamp']) { + if($v_subdef['to_stamp']) { // we must stamp this document try { $record = $this->app->getApplicationBox()->get_databox($v_file['databox_id'])->get_record($v_file['record_id']); diff --git a/lib/Alchemy/Phrasea/WorkerManager/Worker/FtpWorker.php b/lib/Alchemy/Phrasea/WorkerManager/Worker/FtpWorker.php index e849eadd1d..4c0431afe9 100644 --- a/lib/Alchemy/Phrasea/WorkerManager/Worker/FtpWorker.php +++ b/lib/Alchemy/Phrasea/WorkerManager/Worker/FtpWorker.php @@ -15,6 +15,8 @@ use Alchemy\Phrasea\Notification\Mail\MailSuccessFTPSender; use Alchemy\Phrasea\Notification\Receiver; use Alchemy\Phrasea\WorkerManager\Queue\MessagePublisher; +use Exception; +use ftpClient; use Psr\Log\LoggerInterface; use Symfony\Component\Translation\TranslatorInterface; @@ -83,7 +85,8 @@ private function doExport(FtpExport $export, array $payload) $em->flush(); $em->commit(); - } catch (\Exception $e) { + } + catch (Exception $e) { $em->rollback(); } } else { @@ -101,7 +104,8 @@ private function doExport(FtpExport $export, array $payload) $em->flush(); $em->commit(); - } catch (\Exception $e) { + } + catch (Exception $e) { $em->rollback(); } } @@ -146,7 +150,7 @@ private function doExport(FtpExport $export, array $payload) try { $ssl = $export->isSsl(); - /** @var \ftpClient $ftp_client */ + /** @var ftpClient $ftp_client */ $ftp_client = $this->app['phraseanet.ftp.client']( $ftp_server, 21, 300, $ssl, $proxy, $proxyport, $proxyuser, $proxypwd @@ -156,7 +160,8 @@ private function doExport(FtpExport $export, array $payload) if ($export->isPassif()) { try { $ftp_client->passive(true); - } catch (\Exception $e) { + } + catch (Exception $e) { $this->logger->debug($e->getMessage()); } } @@ -165,7 +170,8 @@ private function doExport(FtpExport $export, array $payload) try { $ftp_client->chdir($export->getDestFolder()); $export->setDestfolder('/' . $export->getDestfolder()); - } catch (\Exception $e) { + } + catch (Exception $e) { $this->logger->debug($e->getMessage()); } } else { @@ -175,14 +181,16 @@ private function doExport(FtpExport $export, array $payload) if (trim($export->getFoldertocreate()) != '') { try { $ftp_client->mkdir($export->getFoldertocreate()); - } catch (\Exception $e) { + } + catch (Exception $e) { $this->logger->debug($e->getMessage()); } try { $new_dir = $ftp_client->add_end_slash($export->getDestfolder()) . $export->getFoldertocreate(); $ftp_client->chdir($new_dir); - } catch (\Exception $e) { + } + catch (Exception $e) { $this->logger->debug($e->getMessage()); } } @@ -223,25 +231,35 @@ private function doExport(FtpExport $export, array $payload) $localfile = sys_get_temp_dir().'/' . md5($desc . time() . mt_rand()); if (file_put_contents($localfile, $desc) === false) { - throw new \Exception('Impossible de creer un fichier temporaire'); + throw new Exception('Impossible de creer un fichier temporaire'); } - } elseif ($subdef == 'caption-yaml') { + } + elseif ($subdef == 'caption-yaml') { $desc = $this->app['serializer.caption']->serialize($record->get_caption(), CaptionSerializer::SERIALIZE_YAML, $exportElement->isBusinessfields()); $localfile = sys_get_temp_dir().'/' . md5($desc . time() . mt_rand()); if (file_put_contents($localfile, $desc) === false) { - throw new \Exception('Impossible de creer un fichier temporaire'); + throw new Exception('Impossible de creer un fichier temporaire'); } - } else { + } + else { try { $sd = $record->get_subdef($subdef); - } catch (\Exception_Media_SubdefNotFound $notFount) { + $localfile = $sd->getRealPath(); + + if($exportElement->isToStamp()) { + if (!is_null($path = \recordutils_image::stamp($this->app, $sd))) { + // stamped ! + $localfile = $path; + } + } + } + catch (\Exception_Media_SubdefNotFound $notFound) { continue; } - $localfile = $sd->getRealPath(); - if (!file_exists($localfile)) { - throw new \Exception('Le fichier local n\'existe pas'); + if (!$localfile || !file_exists($localfile)) { + throw new Exception('Le fichier local n\'existe pas'); } } @@ -250,7 +268,8 @@ private function doExport(FtpExport $export, array $payload) if ($ftp_client->pwd() != $current_folder) { try { $ftp_client->chdir($current_folder); - } catch (\Exception $e) { + } + catch (Exception $e) { $this->logger->debug($e->getMessage()); } } @@ -272,7 +291,8 @@ private function doExport(FtpExport $export, array $payload) $this->app['orm.em']->persist($exportElement); $this->app['orm.em']->flush(); $this->logexport($this->app, $record, $obj, $ftpLog); - } catch (\Exception $e) { + } + catch (Exception $e) { $state .= $line = $this->translator->trans('task::ftp:File "%file%" (record %record_id%) de la base "%basename%" (Export du Document) : Transfert cancelled (le document n\'existe plus)', ['%file%' => basename($localfile), '%record_id%' => $record_id, '%basename%' => \phrasea::sbas_labels(\phrasea::sbasFromBas($this->app, $base_id), $this->app)]) . "\n
"; $this->logger->debug($line); @@ -317,7 +337,8 @@ private function doExport(FtpExport $export, array $payload) } $ftp_client->close(); - } catch (\Exception $e) { + } + catch (Exception $e) { $state .= $line = $e . "\n"; $this->logger->debug($line); @@ -342,7 +363,8 @@ private function doExport(FtpExport $export, array $payload) $em->persist($workerRunningJob); $em->flush(); $em->commit(); - } catch (\Exception $e) { + } + catch (Exception $e) { $em->rollback(); } } else { @@ -360,7 +382,8 @@ private function doExport(FtpExport $export, array $payload) $em->persist($workerRunningJob); $em->flush(); $em->commit(); - } catch (\Exception $e) { + } + catch (Exception $e) { $em->rollback(); } @@ -472,7 +495,9 @@ private function send_mails(Application $app, FtpExport $export) $mail = MailSuccessFTPSender::create($app, $receiver, null, $sender_message); $mail->setServer($ftp_server); $this->deliver($mail); - } catch (\Exception $e) { + } + catch (Exception $e) { + // no-op } try { @@ -480,7 +505,8 @@ private function send_mails(Application $app, FtpExport $export) $mail = MailSuccessFTPReceiver::create($app, $receiver, null, $receiver_message); $mail->setServer($ftp_server); $this->deliver($mail); - } catch (\Exception $e) { + } + catch (Exception $e) { $this->logger->debug(sprintf('Unable to deliver success message : %s', $e->getMessage())); } } diff --git a/lib/classes/collection.php b/lib/classes/collection.php index db34c04cb4..d95ada37ee 100644 --- a/lib/classes/collection.php +++ b/lib/classes/collection.php @@ -66,6 +66,19 @@ public static function create(Application $app, databox $databox, appbox $appbox $repository = self::getRepository($app, $databoxId); $collection = new CollectionVO($databoxId, 0, $name); + $dom = new \DOMDocument(); + try { + if(!@$dom->load($app['root.path'] . '/lib/conf.d/collection_settings.xml')) { + $dom = null; + } + } + catch (Exception $e) { + $dom = null; + } + if($dom) { + $collection->setPreferences($dom->saveXML()); + } + $repository->save($collection); $repository = $app['repo.collection-references']; diff --git a/lib/classes/record/adapter.php b/lib/classes/record/adapter.php index 311d26c677..32659e42df 100644 --- a/lib/classes/record/adapter.php +++ b/lib/classes/record/adapter.php @@ -1339,9 +1339,9 @@ private function do_collection($base_id) /** * @param $metadatas - * @throws Exception + * @throws Exception|Exception_InvalidArgument * - * nb : use of "silent" @ operator on stdClass member access (equals null in not defined) is more simple than "iseet()" or "empty()" + * nb : use of "silent" @ operator on stdClass member access (equals null if not defined) is more simple than "isset()" or "empty()" */ private function do_metadatas(array $metadatas) { diff --git a/lib/classes/set/export.php b/lib/classes/set/export.php index 757db0695a..7ae50f0079 100644 --- a/lib/classes/set/export.php +++ b/lib/classes/set/export.php @@ -458,8 +458,10 @@ public function prepare_export(User $user, Filesystem $filesystem, Array $wanted // remove stamp on this collection $stamp_by_base = []; // unset: no stamp ; false: stamp not "unstampable" ; true: stamp "unstampable" - $colls_manageable = array_keys($this->getAclForUser($user)->get_granted_base([ACL::COLL_MANAGE]) ?? []); - $dbox_manageable = array_keys($this->getAclForUser($user)->get_granted_sbas([ACL::BAS_MANAGE]) ?? []); + $colls_manageable = array_keys($this->getAclForUser($user)->get_granted_base([ACL::COLL_MANAGE]) ?? []); + $colls_editable = array_keys($this->getAclForUser($user)->get_granted_base([ACL::CANMODIFRECORD]) ?? []); + $colls_imgtoolsable = array_keys($this->getAclForUser($user)->get_granted_base([ACL::IMGTOOLS]) ?? []); + $dbox_manageable = array_keys($this->getAclForUser($user)->get_granted_sbas([ACL::BAS_MANAGE]) ?? []); /** @var record_exportElement $download_element */ foreach ($this->elements as $download_element) { @@ -511,6 +513,16 @@ public function prepare_export(User $user, Filesystem $filesystem, Array $wanted $stamp_by_base[$bid] = self::NO_STAMP; } break; + case 'record_edit': + if (in_array($bid, $colls_editable)) { + $stamp_by_base[$bid] = self::NO_STAMP; + } + break; + case 'image_tools': + if (in_array($bid, $colls_imgtoolsable)) { + $stamp_by_base[$bid] = self::NO_STAMP; + } + break; case 'manage_databox': if (in_array($download_element->getDatabox()->get_sbas_id(), $dbox_manageable)) { $stamp_by_base[$bid] = self::NO_STAMP; diff --git a/lib/classes/set/exportftp.php b/lib/classes/set/exportftp.php index c6c3ec13b7..0d36e8d7d5 100644 --- a/lib/classes/set/exportftp.php +++ b/lib/classes/set/exportftp.php @@ -83,7 +83,8 @@ public function export_ftp($usr_to, $host, $login, $password, $ssl, $retry, $pas ->setFilename($filename) ->setFolder($properties['folder']) ->setRecordId($file['record_id']) - ->setSubdef($subdef); + ->setSubdef($subdef) + ->setToStamp($file['to_stamp'] !== set_export::NO_STAMP); $export->addElement($element); $this->app['orm.em']->persist($element); diff --git a/lib/conf.d/collection_settings.xml b/lib/conf.d/collection_settings.xml new file mode 100644 index 0000000000..37825d25f2 --- /dev/null +++ b/lib/conf.d/collection_settings.xml @@ -0,0 +1,20 @@ + + + + + + + diff --git a/templates/web/common/dialog_export.html.twig b/templates/web/common/dialog_export.html.twig index 21643d13e1..16a885a6df 100644 --- a/templates/web/common/dialog_export.html.twig +++ b/templates/web/common/dialog_export.html.twig @@ -171,9 +171,9 @@ {% endif %} {% if removeable_stamp and download.has_stamp_option() == true %} -
-
+ {% if removeable_stamp and download.has_stamp_option() == true %} +
+ +
+ {% endif %} {% if download.has_business_fields_access() %} {% endif %} {% endfor %} + {% if removeable_stamp and download.has_stamp_option() == true %} +
+ +
+ {% endif %} {% if download.has_business_fields_access() %}