From a368bf53f65ee4f335c7c20ac8eadbb3213675c0 Mon Sep 17 00:00:00 2001
From: "florian.azizian" <florian.azizian@maarch.org>
Date: Tue, 28 Jan 2020 23:57:29 +0100
Subject: [PATCH] FEAT #12346 TIME 4:45 migrate outgoing mail attachment

---
 migration/20.03/2003.sql                      |   3 +
 migration/20.03/migrate.sh                    |   2 +
 .../20.03/migrateOutgoingAttachments.php      | 353 ++++++++++++++++++
 3 files changed, 358 insertions(+)
 create mode 100644 migration/20.03/migrateOutgoingAttachments.php

diff --git a/migration/20.03/2003.sql b/migration/20.03/2003.sql
index a3f4332b2fc..cb534a78fff 100644
--- a/migration/20.03/2003.sql
+++ b/migration/20.03/2003.sql
@@ -32,6 +32,9 @@ UPDATE res_letterbox SET fulltext_result = 'ERROR' WHERE fulltext_result = '-1'
 UPDATE res_attachments SET fulltext_result = 'SUCCESS' WHERE fulltext_result = '1' OR fulltext_result = '2';
 UPDATE res_attachments SET fulltext_result = 'ERROR' WHERE fulltext_result = '-1' OR fulltext_result = '-2';
 
+UPDATE res_attachments SET attachment_type = 'response_project' WHERE attachment_type = 'outgoing_mail';
+UPDATE res_attachments SET attachment_type = 'signed_response' WHERE attachment_type = 'outgoing_mail_signed';
+UPDATE res_attachments SET attachment_type = 'simple_attachment' WHERE attachment_type = 'document_with_notes';
 
 /* GROUPS INDEXING */
 ALTER TABLE usergroups ALTER COLUMN group_desc DROP DEFAULT;
diff --git a/migration/20.03/migrate.sh b/migration/20.03/migrate.sh
index 4ad4fe78e64..7129106407d 100644
--- a/migration/20.03/migrate.sh
+++ b/migration/20.03/migrate.sh
@@ -20,7 +20,9 @@ php ./migrateExtensions.php
 php ./migrateM2MConfiguration.php
 php ./removeNatureFromPrint.php
 php ./migrateCustomValues.php
+# migrateVersionAttachments always before migrateOutgoingAttachments
 php ./migrateVersionAttachments.php
+php ./migrateOutgoingAttachments.php
 php ./migrateContacts.php
 # migrateOutgoingTemplate always before migrateTemplates
 php ./migrateOutgoingTemplate.php
diff --git a/migration/20.03/migrateOutgoingAttachments.php b/migration/20.03/migrateOutgoingAttachments.php
new file mode 100644
index 00000000000..74a9574c55c
--- /dev/null
+++ b/migration/20.03/migrateOutgoingAttachments.php
@@ -0,0 +1,353 @@
+<?php
+
+use Convert\controllers\ConvertPdfController;
+use Convert\controllers\ConvertThumbnailController;
+use Convert\models\AdrModel;
+use Docserver\controllers\DocserverController;
+use Resource\models\ResModel;
+use SrcCore\models\CoreConfigModel;
+
+require '../../vendor/autoload.php';
+
+chdir('../..');
+
+$customs =  scandir('custom');
+
+foreach ($customs as $custom) {
+    if ($custom == 'custom.xml' || $custom == '.' || $custom == '..') {
+        continue;
+    }
+
+    \SrcCore\models\DatabasePDO::reset();
+    new \SrcCore\models\DatabasePDO(['customId' => $custom]);
+
+    $migrated = 0;
+    $attachmentsInfo = \SrcCore\models\DatabaseModel::select([
+        'select' => ['l.category_id', 'a.res_id', 'a.relation', 'a.docserver_id', 'a.path', 'a.filename', 'a.format', 'a.res_id_master', 'a.in_signature_book',
+                        'a.in_send_attach', 'a.external_id', 'a.attachment_type', 'a.origin_id', 'a.external_id', 'l.external_id as letterbox_external_id'],
+        'table'  => ['res_attachments a, res_letterbox l'],
+        'where'  => ['attachment_type = ?', 'a.status not in (?)', 'a.res_id_master = l.res_id', 'category_id = ?'],
+        'data'   => ['outgoing_mail', ['DEL', 'TMP', 'OBS'], 'outgoing'],
+        'orderBy' => ['a.res_id desc']
+    ]);
+
+    $superadmin = \User\models\UserModel::getByLogin(['select' => ['id'], 'login' => 'superadmin']);
+    if (empty($superadmin)) {
+        $firstMan = \User\models\UserModel::get(['select' => ['id'], 'orderBy' => ['id'], 'limit' => 1]);
+        $masterOwnerId = $firstMan[0]['id'];
+    } else {
+        $masterOwnerId = $superadmin['id'];
+    }
+
+    $tmpPath = CoreConfigModel::getTmpPath();
+
+    $previousResId = 0;
+    foreach ($attachmentsInfo as $attachmentInfo) {
+        if ($previousResId == $attachmentInfo['res_id_master']) {
+            continue;
+        }
+        $previousResId = $attachmentInfo['res_id_master'];
+
+        $inSignatureBook = empty($attachmentInfo['in_signature_book']) ?  'false' : 'true';
+        $inSendAttach    = empty($attachmentInfo['in_send_attach']) ?  'false' : 'true';
+        $format          = empty($attachmentInfo['format']) ?  pathinfo($attachmentInfo['filename'], PATHINFO_EXTENSION) : $attachmentInfo['format'];
+        
+        $docserver = \SrcCore\models\DatabaseModel::select([
+            'select' => ['path_template', 'docserver_type_id'],
+            'table'  => ['docservers'],
+            'where'  => ['docserver_id = ?'],
+            'data'   => [$attachmentInfo['docserver_id']]
+        ]);
+
+        $pathToDocument = $docserver[0]['path_template'] . str_replace('#', DIRECTORY_SEPARATOR, $attachmentInfo['path']) . $attachmentInfo['filename'];
+
+        if (!file_exists($pathToDocument)) {
+            echo "Le document avec res_attachments.res_id = " . $attachmentInfo['res_id']
+                . " n'a pas été trouvé sur le docserver (path = '" . $pathToDocument . "')"
+                . ", il n'est donc pas migré\n";
+            continue;
+        } else {
+            $resource = file_get_contents($pathToDocument);
+            $storeResult = DocserverController::storeResourceOnDocServer([
+                'collId'            => 'letterbox_coll',
+                'docserverTypeId'   => 'DOC',
+                'encodedResource'   => base64_encode($resource),
+                'format'            => $format
+            ]);
+            if (!empty($storeResult['errors'])) {
+                echo "[ConvertPdf] {$storeResult['errors']}";
+            }
+
+            if (!empty($resource)) {
+                \SrcCore\models\DatabaseModel::delete([
+                    'table' => 'adr_letterbox',
+                    'where' => ['res_id = ?'],
+                    'data'  => [$attachmentInfo['res_id_master']]
+                ]);
+
+                $integration = [];
+                $integration['in_signature_book'] = empty($attachmentInfo['in_signature_book']) ?  'false' : 'true';
+                $integration['in_send_attach']    = empty($attachmentInfo['in_send_attach']) ?  'false' : 'true';
+                $attachmentExternalId = json_decode($attachmentInfo['external_id'], true);
+                $externalId           = json_decode($attachmentInfo['letterbox_external_id'], true);
+                $externalId           = array_merge($externalId, $attachmentExternalId);
+                ResModel::update([
+                    'set' => [
+                        'docserver_id' => $storeResult['docserver_id'],
+                        'path'         => $storeResult['destination_dir'],
+                        'filename'     => $storeResult['file_destination_name'],
+                        'fingerprint'  => $storeResult['fingerPrint'],
+                        'filesize'     => $storeResult['fileSize'],
+                        'version'      => $attachmentInfo['relation'],
+                        'integrations' => json_encode($integration),
+                        'external_id'  => json_encode($externalId)
+                    ],
+                    'where' => ['res_id = ?'],
+                    'data'  => [$attachmentInfo['res_id_master']]
+                ]);
+
+                ConvertPdfController::convert([
+                    'resId'   => $attachmentInfo['res_id_master'],
+                    'collId'  => 'letterbox_coll',
+                    'version' => $attachmentInfo['relation']
+                ]);
+                ConvertThumbnailController::convert(['type' => 'resource', 'resId' => $attachmentInfo['res_id_master']]);
+    
+                $customId = empty($custom) ? 'null' : $custom;
+                exec("php src/app/convert/scripts/FullTextScript.php --customId {$customId} --resId {$attachmentInfo['res_id_master']} --collId letterbox_coll --userId {$masterOwnerId} > /dev/null &");
+    
+                if ($attachmentInfo['relation'] > 1) {
+                    $attachmentsVersion = \SrcCore\models\DatabaseModel::select([
+                        'select'  => ['res_id', 'relation', 'docserver_id', 'path', 'filename', 'format', 'res_id_master', 'attachment_type'],
+                        'table'   => ['res_attachments'],
+                        'where'   => ['(origin_id = ? or res_id = ?)', 'relation < ?'],
+                        'data'    => [$attachmentInfo['origin_id'], $attachmentInfo['origin_id'], $attachmentInfo['relation']],
+                        'orderBy' => ['relation asc']
+                    ]);
+
+                    $attachmentToDelete = [];
+                    foreach ($attachmentsVersion as $attachmentVersion) {
+                        $attachmentVersion[0]['adrType'] = 'PDF';
+                        $attachmentVersion[0]['relation'] = $attachmentVersion['relation'];
+                        addOutgoingMailSignedInAdr($attachmentVersion[0]);
+                    
+                        $docserver = \SrcCore\models\DatabaseModel::select([
+                            'select' => ['path_template', 'docserver_type_id'],
+                            'table'  => ['docservers'],
+                            'where'  => ['docserver_id = ?'],
+                            'data'   => [$attachmentVersion['docserver_id']]
+                        ]);
+                    
+                        $pathToDocument = $docserver[0]['path_template'] . str_replace('#', DIRECTORY_SEPARATOR, $attachmentVersion['path']) . $attachmentVersion['filename'];
+                        $resource = file_get_contents($pathToDocument);
+                        $storeResult = DocserverController::storeResourceOnDocServer([
+                            'collId'            => 'letterbox_coll',
+                            'docserverTypeId'   => 'TNL',
+                            'encodedResource'   => base64_encode($resource),
+                            'format'            => $attachmentVersion['format']
+                        ]);
+    
+                        AdrModel::createDocumentAdr([
+                            'resId'         => $attachmentInfo['res_id_master'],
+                            'type'          => 'TNL',
+                            'docserverId'   => $storeResult['docserver_id'],
+                            'path'          => $storeResult['destination_dir'],
+                            'filename'      => $storeResult['file_destination_name'],
+                            'version'       => $attachmentVersion['relation'],
+                            'fingerprint'   => $storeResult['fingerPrint']
+                        ]);
+
+                        unlink($pathToDocument);
+                        unlink($tmpPath.$fileNameOnTmp.'.png');
+                        $attachmentToDelete[] = $attachmentVersion['res_id'];
+                    }
+                }
+                $outgoingMailSigned = \SrcCore\models\DatabaseModel::select([
+                    'select'  => ['res_id', 'relation', 'docserver_id', 'path', 'filename', 'format', 'res_id_master', 'attachment_type'],
+                    'table'   => ['res_attachments'],
+                    'where'   => ['attachment_type = ?', 'res_id_master = ?', 'status not in (?)'],
+                    'data'    => ['outgoing_mail_signed', $attachmentInfo['res_id_master'], ['DEL']],
+                    'orderBy' => ['res_id desc'],
+                    'limit'   => 1
+                ]);
+                if (!empty($outgoingMailSigned)) {
+                    // Version signée outgoing_mail_signed
+                    $outgoingMailSigned[0]['adrType'] = 'SIGN';
+                    $outgoingMailSigned[0]['relation'] = $attachmentInfo['relation'];
+                    addOutgoingMailSignedInAdr($outgoingMailSigned[0]);
+                    $attachmentToDelete[] = $outgoingMailSigned[0]['res_id'];
+                } else {
+                    $signedResponse = \SrcCore\models\DatabaseModel::select([
+                        'select'  => ['res_id', 'relation', 'docserver_id', 'path', 'filename', 'format', 'res_id_master', 'attachment_type'],
+                        'table'   => ['res_attachments'],
+                        'where'   => ['attachment_type = ?', 'origin = ?', 'status not in (?)'],
+                        'data'    => ['signed_response', $attachmentInfo['res_id_master'].',res_attachments', ['DEL']],
+                        'orderBy' => ['res_id desc'],
+                        'limit'   => 1
+                    ]);
+                    if (!empty($signedResponse)) {
+                        // Réponse signée signed_response
+                        $signedResponse[0]['adrType'] = 'SIGN';
+                        $signedResponse[0]['relation'] = $attachmentInfo['relation'];
+                        addOutgoingMailSignedInAdr($signedResponse[0]);
+                        $attachmentToDelete[] = $signedResponse[0]['res_id'];
+                    }
+                }
+                $attachmentToDelete[] = $attachmentInfo['res_id'];
+            }
+
+            $outgoigAnnotated = \SrcCore\models\DatabaseModel::select([
+                'select'  => ['res_id', 'relation', 'docserver_id', 'path', 'filename', 'format', 'res_id_master', 'attachment_type'],
+                'table'   => ['res_attachments'],
+                'where'   => ['attachment_type = ?', 'res_id_master = ?', 'status not in (?)'],
+                'data'    => ['document_with_notes', $attachmentInfo['res_id_master'], ['DEL']],
+                'orderBy' => ['res_id desc'],
+                'limit'   => 1
+            ]);
+            if (!empty($outgoigAnnotated)) {
+                // Version annotée
+                $outgoigAnnotated[0]['adrType'] = 'NOTE';
+                $outgoigAnnotated[0]['relation'] = empty($resource) ? 1 : $attachmentInfo['relation'];
+                addOutgoingMailSignedInAdr($outgoigAnnotated[0]);
+                $attachmentToDelete[] = $outgoigAnnotated[0]['res_id'];
+            }
+            
+            // migrateHistoryVersion(['oldResId' => $attachmentInfo['res_id'], 'newResId' => $attachmentInfo['res_id_master']]);
+            // migrateEmailsVersion(['oldResId' => $attachmentInfo['res_id'], 'newResId' => $attachmentInfo['res_id_master']]);
+            // migrateMessageExchangeVersion(['oldResId' => $attachmentInfo['res_id'], 'newResId' => $attachmentInfo['res_id_master']]);
+            // migrateShippingVersion(['oldResId' => $attachmentInfo['res_id'], 'newResId' => $attachmentInfo['res_id_master']]);
+            $migrated++;
+        }
+    }
+
+    // \SrcCore\models\DatabaseModel::delete([
+    //     'table' => 'res_attachments',
+    //     'where' => ['res_id in (?)'],
+    //     'data'  => [$attachmentToDelete]
+    // ]);
+
+    // \SrcCore\models\DatabaseModel::delete([
+    //     'table' => 'adr_attachments',
+    //     'where' => ['res_id in (?)'],
+    //     'data'  => [$attachmentToDelete]
+    // ]);
+
+    printf("Migration outgoing_mail, outgoing_mail_signed (CUSTOM {$custom}) : " . $migrated . " courier(s) départ(s) trouvé(s) et migré(s).\n");
+}
+
+function addOutgoingMailSignedInAdr($args = [])
+{
+    $tmpPath = CoreConfigModel::getTmpPath();
+
+    $formatVersion = empty($args['format']) ?  pathinfo($args['filename'], PATHINFO_EXTENSION) : $args['format'];
+    $fileNameOnTmp = 'migrationOutgoingAttachmentVersion_' . rand() . '_' . rand();
+
+    $docserver = \SrcCore\models\DatabaseModel::select([
+        'select' => ['path_template', 'docserver_type_id'],
+        'table'  => ['docservers'],
+        'where'  => ['docserver_id = ?'],
+        'data'   => [$args['docserver_id']]
+    ]);
+
+    $pathToDocument = $docserver[0]['path_template'] . str_replace('#', DIRECTORY_SEPARATOR, $args['path']) . $args['filename'];
+    if (file_exists($pathToDocument)) {
+        copy($pathToDocument, $tmpPath.$fileNameOnTmp.'.'.$formatVersion);
+    
+        if (strtolower($formatVersion) != 'pdf') {
+            $command = "timeout 30 unoconv -f pdf " . escapeshellarg($tmpPath.$fileNameOnTmp.'.'.$formatVersion);
+            exec('export HOME=' . $tmpPath . ' && '.$command, $output, $return);
+    
+            if (!file_exists($tmpPath.$fileNameOnTmp.'.pdf')) {
+                echo '[ConvertPdf]  Conversion failed ! '. implode(" ", $output);
+                return '';
+            }
+        }
+    
+        $resource = file_get_contents("{$tmpPath}{$fileNameOnTmp}.pdf");
+        $storeResult = DocserverController::storeResourceOnDocServer([
+            'collId'            => 'letterbox_coll',
+            'docserverTypeId'   => 'CONVERT',
+            'encodedResource'   => base64_encode($resource),
+            'format'            => 'pdf'
+        ]);
+    
+        AdrModel::createDocumentAdr([
+            'resId'         => $args['res_id_master'],
+            'type'          => $args['adrType'],
+            'docserverId'   => $storeResult['docserver_id'],
+            'path'          => $storeResult['destination_dir'],
+            'filename'      => $storeResult['file_destination_name'],
+            'version'       => $args['relation'],
+            'fingerprint'   => $storeResult['fingerPrint']
+        ]);
+    
+        if (in_array($args['adrType'], ['SIGN', 'NOTE'])) {
+            \SrcCore\models\DatabaseModel::delete([
+                'table' => 'adr_letterbox',
+                'where' => ['res_id = ?', 'type = ?', 'version = ?'],
+                'data'  => [$args['res_id_master'], 'TNL', $args['relation']]
+            ]);
+        }
+    
+        unlink($tmpPath.$fileNameOnTmp.'.'.$formatVersion);
+        unlink($tmpPath.$fileNameOnTmp.'.pdf');
+    }
+}
+
+function migrateHistoryVersion($args = [])
+{
+    \SrcCore\models\DatabaseModel::update([
+        'postSet' => ['info' => "REPLACE(info, '{$args['oldResId']} (res_attachments)', '{$args['newResId']} (res_letterbox)')"],
+        'table'   => 'history',
+        'where'   => ['table_name = ?', 'record_id = ?'],
+        'data'    => ['res_attachments', $args['oldResId']]
+    ]);
+}
+
+function migrateEmailsVersion($args = [])
+{
+    $emails = \SrcCore\models\DatabaseModel::select([
+        'select' => ['id', 'document'],
+        'table' => ['emails'],
+        'where' => ['document->\'attachments\' @> ?'],
+        'data' => ['[{"id":'.$args['oldResId'].'}]']
+    ]);
+
+    foreach ($emails as $email) {
+        $document = json_decode($email['document'], true);
+        foreach ($document['attachments'] as $key => $attachment) {
+            if ($attachment['id'] == $args['oldResId']) {
+                $document['isLinked'] = true;
+                $document['original'] = $attachment['original'];
+                unset($document['attachments'][$key]);
+                break;
+            }
+        }
+        \SrcCore\models\DatabaseModel::update([
+            'set'   => ['document' => json_encode($document)],
+            'table' => 'emails',
+            'where' => ['id = ?'],
+            'data'  => [$email['id']]
+        ]);
+    }
+}
+
+function migrateMessageExchangeVersion($args = [])
+{
+    \SrcCore\models\DatabaseModel::update([
+        'set'   => ['res_id' => $args['newResId'], 'tablename' => 'res_letterbox'],
+        'table' => 'unit_identifier',
+        'where' => ['res_id = ?', 'tablename = ?'],
+        'data'  => [$args['oldResId'], 'res_attachments']
+    ]);
+}
+
+function migrateShippingVersion($args = [])
+{
+    \SrcCore\models\DatabaseModel::update([
+        'set'   => ['resource_id' => $args['newResId'], 'resource_type' => 'res_letterbox'],
+        'table' => 'shippings',
+        'where' => ['resource_id = ?', 'resource_type = ?'],
+        'data'  => [$args['oldResId'], 'res_attachment']
+    ]);
+}
-- 
GitLab