From fbd6658f944005c5a72115d7a59c486ad0fbc4f3 Mon Sep 17 00:00:00 2001 From: jygaulier Date: Mon, 9 Aug 2021 20:12:11 +0200 Subject: [PATCH] PHRAS-3499_stamper-in-download-worker - for download by email, stamp is done by the worker (not by the prod controller) - add "no-stamp" checkbox on download dlg (port from PHRAS-424) - todo : add "no-stamp" to download-by-email dlg. - todo ? apply stamp for download-by-ftp --- config/configuration.sample.yml | 2 + .../Phrasea/Controller/AbstractDelivery.php | 4 +- .../Controller/Prod/DownloadController.php | 3 +- .../Controller/Prod/ExportController.php | 13 +- .../Configuration/RegistryFormManipulator.php | 1 + .../Order/Controller/ApiOrderController.php | 2 +- .../WorkerManager/Worker/ExportMailWorker.php | 24 ++++ lib/classes/recordutils/image.php | 36 +++--- lib/classes/set/export.php | 114 +++++++++++++----- templates/web/common/dialog_export.html.twig | 16 +++ 10 files changed, 156 insertions(+), 59 deletions(-) diff --git a/config/configuration.sample.yml b/config/configuration.sample.yml index 21fef21576..853284738b 100644 --- a/config/configuration.sample.yml +++ b/config/configuration.sample.yml @@ -235,6 +235,8 @@ registry: api-clients: api-require-ssl: false api-auth-token-header-only: false + actions: + export-stamp-choice: false crossdomain: site-control: 'master-only' allow-access-from: diff --git a/lib/Alchemy/Phrasea/Controller/AbstractDelivery.php b/lib/Alchemy/Phrasea/Controller/AbstractDelivery.php index 95f57fd220..b244345fda 100644 --- a/lib/Alchemy/Phrasea/Controller/AbstractDelivery.php +++ b/lib/Alchemy/Phrasea/Controller/AbstractDelivery.php @@ -91,7 +91,9 @@ abstract class AbstractDelivery if ($watermark === true && $mediaSubdefinition->get_type() === \media_subdef::TYPE_IMAGE) { $pathOut = \recordutils_image::watermark($this->app, $mediaSubdefinition); } elseif ($stamp === true && $mediaSubdefinition->get_type() === \media_subdef::TYPE_IMAGE) { - $pathOut = \recordutils_image::stamp($this->app, $mediaSubdefinition); + if( !is_null($newPath = \recordutils_image::stamp($this->app, $mediaSubdefinition)) ) { + $pathOut = $newPath; + } } return $pathOut; diff --git a/lib/Alchemy/Phrasea/Controller/Prod/DownloadController.php b/lib/Alchemy/Phrasea/Controller/Prod/DownloadController.php index c8ca51de57..9d19d7297c 100644 --- a/lib/Alchemy/Phrasea/Controller/Prod/DownloadController.php +++ b/lib/Alchemy/Phrasea/Controller/Prod/DownloadController.php @@ -44,7 +44,8 @@ class DownloadController extends Controller $this->app['filesystem'], $subdefs, $request->request->get('type') === 'title' ? true : false, - $request->request->get('businessfields') + $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()); diff --git a/lib/Alchemy/Phrasea/Controller/Prod/ExportController.php b/lib/Alchemy/Phrasea/Controller/Prod/ExportController.php index d01cd06f7c..50db492c2c 100644 --- a/lib/Alchemy/Phrasea/Controller/Prod/ExportController.php +++ b/lib/Alchemy/Phrasea/Controller/Prod/ExportController.php @@ -9,7 +9,6 @@ */ namespace Alchemy\Phrasea\Controller\Prod; -use Alchemy\Phrasea\Application; use Alchemy\Phrasea\Application\Helper\DispatcherAware; use Alchemy\Phrasea\Application\Helper\FilesystemAware; use Alchemy\Phrasea\Application\Helper\NotifierAware; @@ -17,11 +16,7 @@ use Alchemy\Phrasea\Controller\Controller; use Alchemy\Phrasea\Core\Event\ExportFailureEvent; use Alchemy\Phrasea\Core\Event\ExportMailEvent; use Alchemy\Phrasea\Core\PhraseaEvents; -use Alchemy\Phrasea\Exception\InvalidArgumentException; use Alchemy\Phrasea\Model\Manipulator\TokenManipulator; -use Alchemy\Phrasea\Notification\Emitter; -use Alchemy\Phrasea\Notification\Mail\MailRecordsExport; -use Alchemy\Phrasea\Notification\Receiver; use Alchemy\Phrasea\WorkerManager\Event\ExportFtpEvent; use Alchemy\Phrasea\WorkerManager\Event\WorkerEvents; use Symfony\Component\HttpFoundation\JsonResponse; @@ -118,8 +113,9 @@ class ExportController extends Controller $this->getFilesystem(), $request->request->get('obj'), false, - $request->request->get('businessfields') - ); + $request->request->get('businessfields'), + $request->request->get('stamp_choice') === "NO_STAMP" ? \set_export::NO_STAMP : \set_export::STAMP_ASYNC + ); $exportFtpId = $download->export_ftp( $request->request->get('user_dest'), @@ -171,7 +167,8 @@ class ExportController extends Controller $this->getFilesystem(), (array) $request->request->get('obj'), $request->request->get("type") == "title" ? : false, - $request->request->get('businessfields') + $request->request->get('businessfields'), + $request->request->get('stamp_choice') === "NO_STAMP" ? \set_export::NO_STAMP : \set_export::STAMP_ASYNC ); $list['export_name'] = sprintf("%s.zip", $download->getExportName()); diff --git a/lib/Alchemy/Phrasea/Core/Configuration/RegistryFormManipulator.php b/lib/Alchemy/Phrasea/Core/Configuration/RegistryFormManipulator.php index 73bcc48538..66d8808feb 100644 --- a/lib/Alchemy/Phrasea/Core/Configuration/RegistryFormManipulator.php +++ b/lib/Alchemy/Phrasea/Core/Configuration/RegistryFormManipulator.php @@ -128,6 +128,7 @@ class RegistryFormManipulator 'force-push-authentication' => false, 'enable-feed-notification' => true, 'download-link-validity' => 24, + 'export-stamp-choice' => false, ], 'ftp' => [ 'ftp-enabled' => false, diff --git a/lib/Alchemy/Phrasea/Order/Controller/ApiOrderController.php b/lib/Alchemy/Phrasea/Order/Controller/ApiOrderController.php index a69c731ca7..c61e27d1c6 100644 --- a/lib/Alchemy/Phrasea/Order/Controller/ApiOrderController.php +++ b/lib/Alchemy/Phrasea/Order/Controller/ApiOrderController.php @@ -189,7 +189,7 @@ class ApiOrderController extends BaseOrderController $subdefs = $this->findDataboxSubdefNames(); try { - $exportData = $export->prepare_export($user, $this->getFilesystem(), $subdefs, true, true); + $exportData = $export->prepare_export($user, $this->getFilesystem(), $subdefs, true, true, false); } catch (\Exception $e) { throw new NotFoundHttpException(sprintf('No archive could be downloaded for Order "%d"', $order->getId())); diff --git a/lib/Alchemy/Phrasea/WorkerManager/Worker/ExportMailWorker.php b/lib/Alchemy/Phrasea/WorkerManager/Worker/ExportMailWorker.php index e5a0576468..60cd332880 100644 --- a/lib/Alchemy/Phrasea/WorkerManager/Worker/ExportMailWorker.php +++ b/lib/Alchemy/Phrasea/WorkerManager/Worker/ExportMailWorker.php @@ -81,6 +81,30 @@ class ExportMailWorker implements WorkerInterface $list = unserialize($token->getData()); + 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']) { + // we must stamp this document + try { + $record = $this->app->getApplicationBox()->get_databox($v_file['databox_id'])->get_record($v_file['record_id']); + assert(!is_object($record)); + $sd = $record->get_subdef($k_subdef); + assert(!is_object($sd)); + if(!is_null($path = \recordutils_image::stamp($this->app, $sd))) { + // stamped ! + $pi = pathinfo($path); + $list['files'][$k_file]['subdefs'][$k_subdef]['path'] = $pi['dirname']; + $list['files'][$k_file]['subdefs'][$k_subdef]['file'] = $pi['basename']; + $list['files'][$k_file]['subdefs'][$k_subdef]['size'] = filesize($path); + } + } + catch (\Exception $e) { + // failed to stamp ? ignore and send the original file + } + } + } + } + $this->repoWorkerJob->reconnect(); //zip documents \set_export::build_zip( diff --git a/lib/classes/recordutils/image.php b/lib/classes/recordutils/image.php index a7fee96aeb..e71ae80661 100644 --- a/lib/classes/recordutils/image.php +++ b/lib/classes/recordutils/image.php @@ -11,13 +11,13 @@ use Alchemy\Phrasea\Application; use Alchemy\Phrasea\Model\Serializer\CaptionSerializer; +use Imagine\Exception\Exception as ImagineException; +use Imagine\Image\Box; use Imagine\Image\ImagineInterface; use Imagine\Image\Palette\RGB; -use Imagine\Image\Box; use Imagine\Image\Point; -use Imagine\Exception\Exception as ImagineException; -use MediaVorus\Media\MediaInterface; use MediaVorus\Media\Image; +use MediaVorus\Media\MediaInterface; class recordutils_image { @@ -25,12 +25,23 @@ class recordutils_image * @param Application $app * @param \media_subdef $subdef * - * @return string The path to the stamped file + * @return string|null The path to the stamped file, or null if stamp is not required */ public static function stamp(Application $app, \media_subdef $subdef) { static $palette; + $domprefs = new DOMDocument(); + + if (false === $domprefs->loadXML($subdef->get_record()->getCollection()->get_prefs())) { + return null; + } + $xpprefs = new DOMXPath($domprefs); + $stampNodes = $xpprefs->query('/baseprefs/stamp'); + if ($stampNodes->length == 0) { + return null; + } + if (null === $palette) { $palette = new RGB(); } @@ -52,11 +63,11 @@ class recordutils_image $base_id = $subdef->get_record()->getBaseId(); if ($subdef->get_type() !== \media_subdef::TYPE_IMAGE) { - return $subdef->getRealPath(); + return null; } if (!$subdef->is_physically_present()) { - return $subdef->getRealPath(); + return null; } $rotation = null; @@ -69,20 +80,9 @@ class recordutils_image // getting orientation failed but we don't care the reason } - $domprefs = new DOMDocument(); - - if (false === $domprefs->loadXML($subdef->get_record()->getCollection()->get_prefs())) { - return $subdef->getRealPath(); - } if (false === $sxxml = simplexml_load_string($app['serializer.caption']->serialize($subdef->get_record()->get_caption(), CaptionSerializer::SERIALIZE_XML))) { - return $subdef->getRealPath(); - } - - $xpprefs = new DOMXPath($domprefs); - $stampNodes = $xpprefs->query('/baseprefs/stamp'); - if ($stampNodes->length == 0) { - return $subdef->getRealPath(); + return null; } $pathIn = $subdef->getRealPath(); diff --git a/lib/classes/set/export.php b/lib/classes/set/export.php index 55abec8b03..40ba2a2e5a 100644 --- a/lib/classes/set/export.php +++ b/lib/classes/set/export.php @@ -389,22 +389,29 @@ class set_export extends set_abstract return $this->total_ftp; } + const NO_STAMP = 'NO_STAMP'; + const STAMP_SYNC = 'STAMP_SYNC'; + const STAMP_ASYNC = 'STAMP_ASYNC'; /** * @param User $user * @param Filesystem $filesystem * @param array $wantedSubdefs * @param bool $rename_title * @param bool $includeBusinessFields - * @param $stampChoice + * @param $no_stamp * @return array * @throws Exception */ - public function prepare_export(User $user, Filesystem $filesystem, Array $wantedSubdefs, $rename_title, $includeBusinessFields, $stampChoice = null) + public function prepare_export(User $user, Filesystem $filesystem, Array $wantedSubdefs, $rename_title, $includeBusinessFields, $stampMethod) { if (!is_array($wantedSubdefs)) { throw new Exception('No subdefs given'); } + if(!$stampMethod) { + $stampMethod = self::STAMP_SYNC; + } + $includeBusinessFields = (bool) $includeBusinessFields; $files = []; $n_files = 0; @@ -509,7 +516,9 @@ class set_export extends set_abstract $subdef_ok = true; $tmp_pathfile = [ 'path' => $sd[$subdefName]->get_path(), - 'file' => $sd[$subdefName]->get_file() + 'file' => $sd[$subdefName]->get_file(), + 'to_stamp' => false, + 'to_watermark' => false ]; break; @@ -517,16 +526,28 @@ class set_export extends set_abstract $subdef_ok = true; $tmp_pathfile = [ 'path' => $sd[$subdefName]->get_path(), - 'file' => $sd[$subdefName]->get_file() + 'file' => $sd[$subdefName]->get_file(), + 'to_stamp' => false, + 'to_watermark' => false ]; - if($this->app['conf']->get(['registry', 'actions', 'export-stamp-choice']) !== true || is_null($stampChoice) ){ - $path = \recordutils_image::stamp($this->app , $sd[$subdefName]); - if (file_exists($path)) { - $tmp_pathfile = [ - 'path' => dirname($path), - 'file' => basename($path) - ]; + if($this->app['conf']->get(['registry', 'actions', 'export-stamp-choice']) !== true || $stampMethod !== self::NO_STAMP ){ + // stamp is mandatory, or user did not check "no stamp" : we must apply stamp + if($stampMethod === self::STAMP_SYNC) { + // we prepare a direct download, we must stamp now + $path = \recordutils_image::stamp($this->app, $sd[$subdefName]); + if ($path && file_exists($path)) { + $tmp_pathfile = [ + 'path' => dirname($path), + 'file' => basename($path), + 'to_stamp' => false, + 'to_watermark' => false + ]; + } + } + else { + // we prepare an email or ftp download : the worker will apply stamp + $tmp_pathfile ['to_stamp'] = true; } } @@ -534,7 +555,9 @@ class set_export extends set_abstract case 'preview': $tmp_pathfile = [ 'path' => $sd[$subdefName]->get_path(), - 'file' => $sd[$subdefName]->get_file() + 'file' => $sd[$subdefName]->get_file(), + 'to_stamp' => false, + 'to_watermark' => false ]; if (!$this->app->getAclForUser($user)->has_right_on_base($download_element->getBaseId(), \ACL::NOWATERMARK) @@ -545,7 +568,9 @@ class set_export extends set_abstract if (file_exists($path)) { $tmp_pathfile = [ 'path' => dirname($path), - 'file' => basename($path) + 'file' => basename($path), + 'to_stamp' => false, + 'to_watermark' => false ]; $subdef_ok = true; } @@ -569,14 +594,17 @@ class set_export extends set_abstract $mime = 'text/xml'; } - $files[$id]["subdefs"][$subdefName]["ajout"] = $ajout; - $files[$id]["subdefs"][$subdefName]["exportExt"] = $ext; - $files[$id]["subdefs"][$subdefName]["label"] = $properties['label']; - $files[$id]["subdefs"][$subdefName]["path"] = null; - $files[$id]["subdefs"][$subdefName]["file"] = null; - $files[$id]["subdefs"][$subdefName]["size"] = 0; - $files[$id]["subdefs"][$subdefName]["mime"] = $mime; - $files[$id]["subdefs"][$subdefName]["folder"] = $download_element->get_directory(); + $files[$id]["subdefs"][$subdefName] = [ + "ajout" => $ajout, + "exportExt" => $ext, + "label" => $properties['label'], + "path" => null, + "file" => null, + "to_stamp" => false, + "size" => 0, + "mime" => $mime, + "folder" => $download_element->get_directory() + ]; break; case 'document': @@ -586,19 +614,22 @@ class set_export extends set_abstract $infos = pathinfo(p4string::addEndSlash($tmp_pathfile["path"]) . $tmp_pathfile["file"]); $ext = isset($infos['extension']) ? $infos['extension'] : ''; - $files[$id]["subdefs"][$subdefName]["ajout"] = $ajout; - $files[$id]["subdefs"][$subdefName]["exportExt"] = $ext; - $files[$id]["subdefs"][$subdefName]["label"] = $properties['label']; - $files[$id]["subdefs"][$subdefName]["path"] = $tmp_pathfile["path"]; - $files[$id]["subdefs"][$subdefName]["file"] = $tmp_pathfile["file"]; - $files[$id]["subdefs"][$subdefName]["size"] = $sd[$subdefName]->get_size(); - $files[$id]["subdefs"][$subdefName]["mime"] = $sd[$subdefName]->get_mime(); - $files[$id]["subdefs"][$subdefName]["folder"] = $download_element->get_directory(); + $files[$id]["subdefs"][$subdefName] = [ + "ajout" => $ajout, + "exportExt" => $ext, + "label" => $properties['label'], + "path" => $tmp_pathfile["path"], + "file" => $tmp_pathfile["file"], + "to_stamp" => $tmp_pathfile["to_stamp"], + "size" => $sd[$subdefName]->get_size(), + "mime" => $sd[$subdefName]->get_mime(), + "folder" => $download_element->get_directory() + ]; $size += $sd[$subdefName]->get_size(); break; - default: // should no happen + default: // should not happen $ajout = $ext = ''; break; @@ -824,4 +855,27 @@ class set_export extends set_abstract $stmt->closeCursor(); } } + + public function has_stamp_option() + { + if ($this->total_download == 0) { + return false; + } + + $domprefs = new DOMDocument(); + foreach ($this->elements as $download_element) { + if ( ($domprefs->loadXML($download_element->getCollection()->get_prefs())) === false) { + continue; + } + $xpprefs = new DOMXPath($domprefs); + $stampNodes = $xpprefs->query('/baseprefs/stamp'); + if ($stampNodes->length != 0) { + + return true; + } + + } + + return false; + } } diff --git a/templates/web/common/dialog_export.html.twig b/templates/web/common/dialog_export.html.twig index 3fd75a85b1..3138cc3cc8 100644 --- a/templates/web/common/dialog_export.html.twig +++ b/templates/web/common/dialog_export.html.twig @@ -156,6 +156,14 @@ {% endif %} + {% if app['conf'].get(['registry', 'actions', 'export-stamp-choice']) == true and download.has_stamp_option() == true %} +
+ +
+ {% endif %}
@@ -519,6 +527,14 @@ $(document).find(".tagsinput").tagsinput('add', $(this).val()); $(this).val(''); }); + + $('#download_document').click(function(){ + if($(this).is(':checked')){ + $('#download_stamp_choice').show(); + } else{ + $('#download_stamp_choice').hide(); + } + }); {% endif %}