From 2adc618c9d8758e9d1cdfebc35941da199371806 Mon Sep 17 00:00:00 2001 From: Guillaume Heurtier <guillaume.heurtier@maarch.org> Date: Wed, 2 Dec 2020 13:28:47 +0100 Subject: [PATCH] FEAT #12026 TIME 5:30 added route to convert document page to image --- rest/index.php | 2 + .../controllers/ActionMethodController.php | 9 +- .../controllers/AttachmentController.php | 67 +++++++++++ .../ConvertThumbnailController.php | 104 ++++++++++++++++++ .../resource/controllers/ResController.php | 66 ++++++++++- 5 files changed, 242 insertions(+), 6 deletions(-) diff --git a/rest/index.php b/rest/index.php index 7ea9bb7a45f..790dfe8e4fe 100755 --- a/rest/index.php +++ b/rest/index.php @@ -87,6 +87,7 @@ $app->delete('/attachments/{id}', \Attachment\controllers\AttachmentController:: $app->get('/attachments/{id}/content', \Attachment\controllers\AttachmentController::class . ':getFileContent'); $app->get('/attachments/{id}/originalContent', \Attachment\controllers\AttachmentController::class . ':getOriginalFileContent'); $app->get('/attachments/{id}/thumbnail', \Attachment\controllers\AttachmentController::class . ':getThumbnailContent'); +$app->get('/attachments/{id}/thumbnail/{page}', \Attachment\controllers\AttachmentController::class . ':getThumbnailContentByPage'); $app->put('/attachments/{id}/inSendAttachment', \Attachment\controllers\AttachmentController::class . ':setInSendAttachment'); $app->put('/attachments/{id}/inSignatureBook', \Attachment\controllers\AttachmentController::class . ':setInSignatureBook'); $app->put('/attachments/{id}/sign', \SignatureBook\controllers\SignatureBookController::class . ':signAttachment'); @@ -400,6 +401,7 @@ $app->get('/resources/{resId}/versionsInformations', \Resource\controllers\ResCo $app->get('/resources/{resId}/content/{version}', \Resource\controllers\ResController::class . ':getVersionFileContent'); $app->get('/resources/{resId}/originalContent', \Resource\controllers\ResController::class . ':getOriginalFileContent'); $app->get('/resources/{resId}/thumbnail', \Resource\controllers\ResController::class . ':getThumbnailContent'); +$app->get('/resources/{resId}/thumbnail/{page}', \Resource\controllers\ResController::class . ':getThumbnailContentByPage'); $app->get('/resources/{resId}/isAllowed', \Resource\controllers\ResController::class . ':isAllowedForCurrentUser'); $app->get('/resources/{resId}/items', \Resource\controllers\ResController::class . ':getItems'); $app->get('/resources/{resId}/attachments', \Attachment\controllers\AttachmentController::class . ':getByResId'); diff --git a/src/app/action/controllers/ActionMethodController.php b/src/app/action/controllers/ActionMethodController.php index 0a5fadb1f03..acc6df8ec39 100644 --- a/src/app/action/controllers/ActionMethodController.php +++ b/src/app/action/controllers/ActionMethodController.php @@ -327,17 +327,16 @@ class ActionMethodController return true; } - public function sendSignatureBook(array $args) + public static function sendSignatureBook(array $args) { ValidatorModel::notEmpty($args, ['resId']); ValidatorModel::intVal($args, ['resId']); $circuit = ListInstanceModel::get([ - 'select' => ['requested_signature'], + 'select' => ['requested_signature', 'item_mode'], 'where' => ['res_id = ?', 'difflist_type = ?', 'process_date is null'], 'data' => [$args['resId'], 'VISA_CIRCUIT'], - 'orderBy' => ['listinstance_id'], - 'limit' => 1 + 'orderBy' => ['listinstance_id'] ]); if (empty($circuit)) { return ['errors' => ['No available circuit']]; @@ -400,7 +399,7 @@ class ActionMethodController return true; } - public function continueVisaCircuit(array $args) + public static function continueVisaCircuit(array $args) { ValidatorModel::notEmpty($args, ['resId']); ValidatorModel::intVal($args, ['resId']); diff --git a/src/app/attachment/controllers/AttachmentController.php b/src/app/attachment/controllers/AttachmentController.php index 4a1cc4a3686..7a9c799408f 100755 --- a/src/app/attachment/controllers/AttachmentController.php +++ b/src/app/attachment/controllers/AttachmentController.php @@ -31,6 +31,7 @@ use Resource\controllers\WatermarkController; use Resource\models\ResModel; use Resource\models\ResourceContactModel; use Respect\Validation\Validator; +use setasign\Fpdi\Tcpdf\Fpdi; use SignatureBook\controllers\SignatureBookController; use Slim\Http\Request; use Slim\Http\Response; @@ -481,6 +482,72 @@ class AttachmentController return $response->withHeader('Content-Type', $mimeType); } + + public function getThumbnailContentByPage(Request $request, Response $response, array $args) + { + if (!Validator::intVal()->validate($args['id'])) { + return $response->withStatus(403)->withJson(['errors' => 'id param is not an integer']); + } + + $document = AttachmentModel::getById(['select' => [1], 'id' => $args['id']]); + if (empty($document)) { + return $response->withStatus(400)->withJson(['errors' => 'Document does not exist']); + } + + $docserver = DocserverModel::getByDocserverId(['docserverId' => 'TNL_ATTACH', 'select' => ['path_template']]); + if (empty($docserver['path_template']) || !file_exists($docserver['path_template'])) { + return $response->withStatus(400)->withJson(['errors' => 'Docserver does not exist']); + } + + $adr = AdrModel::getAttachments([ + 'select' => ['path', 'filename'], + 'where' => ['res_id = ?', 'type = ?'], + 'data' => [$args['id'], 'TNL' . $args['page']] + ]); + + $pathToThumbnail = $docserver['path_template'] . $adr[0]['path'] . $adr[0]['filename']; + if (!is_file($pathToThumbnail) || !is_readable($pathToThumbnail)) { + $control = ConvertThumbnailController::convertOnePage(['type' => 'attachment', 'resId' => $args['id'], 'page' => $args['page']]); + if (!empty($control['errors'])) { + return $response->withStatus(400)->withJson(['errors' => $control['errors']]); + } + $adr = AdrModel::getAttachments([ + 'select' => ['path', 'filename'], + 'where' => ['res_id = ?', 'type = ?'], + 'data' => [$args['id'], 'TNL' . $args['page']] + ]); + $pathToThumbnail = $docserver['path_template'] . $adr[0]['path'] . $adr[0]['filename']; + if (!is_file($pathToThumbnail) || !is_readable($pathToThumbnail)) { + return $response->withStatus(400)->withJson(['errors' => 'Thumbnail not found on docserver or not readable', 'lang' => 'thumbnailNotFound']); + } + } + $pathToThumbnail = str_replace('#', '/', $pathToThumbnail); + + $fileContent = file_get_contents($pathToThumbnail); + if ($fileContent === false) { + return $response->withStatus(404)->withJson(['errors' => 'Page not found on docserver']); + } + + $base64Content = base64_encode($fileContent); + + $adrPdf = AdrModel::getAttachments([ + 'select' => ['path', 'filename', 'docserver_id'], + 'where' => ['res_id = ?', 'type = ?'], + 'data' => [$args['id'], 'PDF'] + ]); + + $docserver = DocserverModel::getByDocserverId(['docserverId' => $adrPdf[0]['docserver_id'], 'select' => ['path_template']]); + if (empty($docserver['path_template']) || !file_exists($docserver['path_template'])) { + return $response->withStatus(400)->withJson(['errors' => 'Docserver does not exist']); + } + $pathToPdf = $docserver['path_template'] . $adrPdf[0]['path'] . $adrPdf[0]['filename']; + $pathToPdf = str_replace('#', '/', $pathToPdf); + + $pdf = new Fpdi('P', 'pt'); + $pageCount = $pdf->setSourceFile($pathToPdf); + + return $response->withJson(['fileContent' => $base64Content, 'pageCount' => $pageCount]); + } public function getFileContent(Request $request, Response $response, array $args) { diff --git a/src/app/convert/controllers/ConvertThumbnailController.php b/src/app/convert/controllers/ConvertThumbnailController.php index 86360b16ad1..20e3e224406 100755 --- a/src/app/convert/controllers/ConvertThumbnailController.php +++ b/src/app/convert/controllers/ConvertThumbnailController.php @@ -154,4 +154,108 @@ class ConvertThumbnailController return true; } + + public static function convertOnePage(array $args) + { + ValidatorModel::notEmpty($args, ['resId', 'page', 'type']); + ValidatorModel::intVal($args, ['resId', 'page']); + ValidatorModel::stringType($args, ['type']); + + if ($args['type'] == 'resource') { + $resource = ResModel::getById(['resId' => $args['resId'], 'select' => ['filename', 'version']]); + } elseif ($args['type'] == 'attachment') { + $resource = AttachmentModel::getById(['id' => $args['resId'], 'select' => ['filename']]); + } + + if (empty($resource)) { + return ['errors' => '[ConvertThumbnail] Resource does not exist']; + } + if (empty($resource['filename'])) { + return true; + } + + if ($args['type'] == 'resource') { + $convertedDocument = AdrModel::getDocuments([ + 'select' => ['id', 'docserver_id', 'path', 'filename', 'fingerprint'], + 'where' => ['res_id = ?', 'type in (?)', 'version = ?'], + 'data' => [$args['resId'], ['PDF', 'SIGN'], $resource['version']], + 'orderBy' => ["type='SIGN' DESC"], + 'limit' => 1 + ]); + $convertedDocument = $convertedDocument[0] ?? null; + } elseif ($args['type'] == 'attachment') { + $convertedDocument = AdrModel::getConvertedDocumentById([ + 'select' => ['id', 'docserver_id','path', 'filename', 'fingerprint'], + 'resId' => $args['resId'], + 'collId' => 'attachment', + 'type' => 'PDF' + ]); + } + + $docserver = DocserverModel::getByDocserverId(['docserverId' => $convertedDocument['docserver_id'], 'select' => ['path_template', 'docserver_type_id']]); + if (empty($docserver['path_template']) || !is_dir($docserver['path_template'])) { + return ['errors' => 'Docserver does not exist']; + } + + $pathToDocument = $docserver['path_template'] . $convertedDocument['path'] . $convertedDocument['filename']; + if (!is_file($pathToDocument) || !is_readable($pathToDocument)) { + return ['errors' => 'Document not found on docserver or not readable']; + } + + $filename = pathinfo($pathToDocument, PATHINFO_FILENAME); + $tmpPath = CoreConfigModel::getTmpPath(); + + $img = new \Imagick(); + $img->pingImage($pathToDocument); + $pageCount = $img->getNumberImages(); + if ($pageCount < $args['page']) { + return ['errors' => 'Page does not exist']; + } + + $fileNameOnTmp = rand() . $filename; + + $convertPage = $args['page'] - 1; + $command = "convert -density 500x500 -quality 100 -background white -alpha remove " + . escapeshellarg($pathToDocument) . "[{$convertPage}] " . escapeshellarg("{$tmpPath}{$fileNameOnTmp}.png"); + exec($command.' 2>&1', $output, $return); + + if ($return !== 0) { + return ['errors' => "[ConvertThumbnail] Convert command failed for page {$args['page']} : ".implode(" ", $output)]; + } + + $content = file_get_contents("{$tmpPath}{$fileNameOnTmp}.png"); + + $storeResult = DocserverController::storeResourceOnDocServer([ + 'collId' => $args['type'] == 'resource' ? 'letterbox_coll' : 'attachments_coll', + 'docserverTypeId' => 'TNL', + 'encodedResource' => base64_encode($content), + 'format' => 'png' + ]); + if (!empty($storeInfos['errors'])) { + return ['errors' => $storeInfos['errors']]; + } + + unlink("{$tmpPath}{$fileNameOnTmp}.png"); + + if ($args['type'] == 'resource') { + AdrModel::createDocumentAdr([ + 'resId' => $args['resId'], + 'type' => 'TNL' . $args['page'], + 'docserverId' => $storeResult['docserver_id'], + 'path' => $storeResult['destination_dir'], + 'filename' => $storeResult['file_destination_name'], + 'version' => $resource['version'] + ]); + } else { + AdrModel::createAttachAdr([ + 'resId' => $args['resId'], + 'type' => 'TNL' . $args['page'], + 'docserverId' => $storeResult['docserver_id'], + 'path' => $storeResult['destination_dir'], + 'filename' => $storeResult['file_destination_name'] + ]); + } + + return true; + } } diff --git a/src/app/resource/controllers/ResController.php b/src/app/resource/controllers/ResController.php index b6131b12898..b744a1add45 100755 --- a/src/app/resource/controllers/ResController.php +++ b/src/app/resource/controllers/ResController.php @@ -19,7 +19,6 @@ use Action\models\ActionModel; use Attachment\models\AttachmentModel; use Basket\models\BasketModel; use Basket\models\GroupBasketModel; -use Basket\models\RedirectBasketModel; use Convert\controllers\ConvertPdfController; use Convert\controllers\ConvertThumbnailController; use Convert\models\AdrModel; @@ -45,6 +44,7 @@ use Resource\models\ResourceContactModel; use Resource\models\UserFollowedResourceModel; use Respect\Validation\Validator; use Search\controllers\SearchController; +use setasign\Fpdi\Tcpdf\Fpdi; use Shipping\models\ShippingModel; use Slim\Http\Request; use Slim\Http\Response; @@ -746,6 +746,70 @@ class ResController extends ResourceControlController return $response->withHeader('Content-Type', $mimeType); } + public function getThumbnailContentByPage(Request $request, Response $response, array $args) + { + if (!Validator::intVal()->validate($args['resId'])) { + return $response->withStatus(403)->withJson(['errors' => 'resId param is not an integer']); + } + + $document = ResModel::getById(['select' => ['filename', 'version'], 'resId' => $args['resId']]); + if (empty($document)) { + return $response->withStatus(400)->withJson(['errors' => 'Document does not exist']); + } + + $docserver = DocserverModel::getByDocserverId(['docserverId' => 'TNL_MLB', 'select' => ['path_template']]); + if (empty($docserver['path_template']) || !file_exists($docserver['path_template'])) { + return $response->withStatus(400)->withJson(['errors' => 'Docserver does not exist']); + } + + $adr = AdrModel::getDocuments([ + 'select' => ['path', 'filename'], + 'where' => ['res_id = ?', 'type = ?'], + 'data' => [$args['resId'], 'TNL' . $args['page']] + ]); + + $pathToThumbnail = $docserver['path_template'] . $adr[0]['path'] . $adr[0]['filename']; + if (!is_file($pathToThumbnail) || !is_readable($pathToThumbnail)) { + $control = ConvertThumbnailController::convertOnePage(['type' => 'resource', 'resId' => $args['resId'], 'page' => $args['page']]); + if (!empty($control['errors'])) { + return $response->withStatus(400)->withJson(['errors' => $control['errors']]); + } + $adr = AdrModel::getDocuments([ + 'select' => ['path', 'filename'], + 'where' => ['res_id = ?', 'type = ?'], + 'data' => [$args['resId'], 'TNL' . $args['page']] + ]); + $pathToThumbnail = $docserver['path_template'] . $adr[0]['path'] . $adr[0]['filename']; + if (!is_file($pathToThumbnail) || !is_readable($pathToThumbnail)) { + return $response->withStatus(400)->withJson(['errors' => 'Thumbnail not found on docserver or not readable', 'lang' => 'thumbnailNotFound']); + } + } + + $fileContent = file_get_contents($pathToThumbnail); + if ($fileContent === false) { + return $response->withStatus(404)->withJson(['errors' => 'Page not found on docserver']); + } + + $base64Content = base64_encode($fileContent); + + $adrPdf = AdrModel::getDocuments([ + 'select' => ['path', 'filename', 'docserver_id'], + 'where' => ['res_id = ?', 'type = ?'], + 'data' => [$args['resId'], 'PDF'] + ]); + $docserver = DocserverModel::getByDocserverId(['docserverId' => $adrPdf[0]['docserver_id'], 'select' => ['path_template']]); + if (empty($docserver['path_template']) || !file_exists($docserver['path_template'])) { + return $response->withStatus(400)->withJson(['errors' => 'Docserver does not exist']); + } + $pathToPdf = $docserver['path_template'] . $adrPdf[0]['path'] . $adrPdf[0]['filename']; + $pathToPdf = str_replace('#', '/', $pathToPdf); + + $pdf = new Fpdi('P', 'pt'); + $pageCount = $pdf->setSourceFile($pathToPdf); + + return $response->withJson(['fileContent' => $base64Content, 'pageCount' => $pageCount]); + } + public function getItems(Request $request, Response $response, array $args) { if (!Validator::intVal()->validate($args['resId']) || !ResController::hasRightByResId(['resId' => [$args['resId']], 'userId' => $GLOBALS['id']])) { -- GitLab