From a7c8a849a73c49bc93a8b66c028c8d63daee6625 Mon Sep 17 00:00:00 2001
From: Bertrand GAUTHIER <bertrand.gauthier@unicaen.fr>
Date: Fri, 5 May 2023 16:22:59 +0200
Subject: [PATCH] =?UTF-8?q?Ajout=20des=20commandes=20shell=20de=20concat?=
 =?UTF-8?q?=C3=A9nation=20de=20fichiers=20PDF=20avec=20Ghostscript=20ou=20?=
 =?UTF-8?q?QPDF.?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 CHANGELOG.md                                  |  4 ++
 composer.json                                 |  3 +-
 config/module.config.php                      | 41 +++++++++++++-----
 .../PdfMergeShellCommandAwareTrait.php        | 13 ++++++
 .../Command/PdfMergeShellCommandGs.php        | 42 +++++++++++++++++++
 .../Command/PdfMergeShellCommandInterface.php | 12 ++++++
 .../Command/PdfMergeShellCommandQpdf.php      | 37 ++++++++++++++++
 src/UnicaenPdf/Options/ModuleOptions.php      | 13 ++++++
 .../Options/ModuleOptionsAwareTrait.php       | 13 ++++++
 .../Options/ModuleOptionsFactory.php          | 16 +++++++
 10 files changed, 183 insertions(+), 11 deletions(-)
 create mode 100644 src/UnicaenPdf/Command/PdfMergeShellCommandAwareTrait.php
 create mode 100644 src/UnicaenPdf/Command/PdfMergeShellCommandGs.php
 create mode 100644 src/UnicaenPdf/Command/PdfMergeShellCommandInterface.php
 create mode 100644 src/UnicaenPdf/Command/PdfMergeShellCommandQpdf.php
 create mode 100644 src/UnicaenPdf/Options/ModuleOptions.php
 create mode 100644 src/UnicaenPdf/Options/ModuleOptionsAwareTrait.php
 create mode 100644 src/UnicaenPdf/Options/ModuleOptionsFactory.php

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 58e989a..fc1222b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,10 @@
 CHANGELOG
 =========
 
+6.1.0
+-----
+- Ajout des commandes shell de concaténation de fichiers PDF avec Ghostscript ou QPDF.
+
 6.0.1
 -----
 - Ajout d'une fonction statique afin de simplifier le code de création de PDF dans les applications. 
diff --git a/composer.json b/composer.json
index 913da85..3242b3d 100644
--- a/composer.json
+++ b/composer.json
@@ -5,7 +5,8 @@
     "php": "^8.0",
     "mpdf/mpdf": "^8.0",
     "laminas/laminas-view": "^2.22",
-    "laminas/laminas-dependency-plugin": "^2.1"
+    "laminas/laminas-dependency-plugin": "^2.1",
+    "unicaen/shell": "^1.0"
   },
   "require-dev": {
     "laminas/laminas-test": "^4.0",
diff --git a/config/module.config.php b/config/module.config.php
index a27f367..bfc2340 100644
--- a/config/module.config.php
+++ b/config/module.config.php
@@ -2,32 +2,53 @@
 
 namespace UnicaenPdf;
 
+use UnicaenPdf\Command\PdfMergeShellCommandGs;
+use UnicaenPdf\Command\PdfMergeShellCommandQpdf;
+use UnicaenPdf\Options\ModuleOptions;
+use UnicaenPdf\Options\ModuleOptionsFactory;
+
 return [
-    'router'          => [
+    'unicaen-pdf' => [
+
+    ],
+
+    'unicaen-shell' => [
+        'commands' => [
+            PdfMergeShellCommandGs::class => [
+                'executable' => '/usr/bin/gs',
+            ],
+            PdfMergeShellCommandQpdf::class => [
+                'executable' => '/usr/bin/qpdf',
+            ],
+        ],
+    ],
+
+    'router' => [
         'routes' => [
         ],
     ],
-    'console'         => [
-        'router'       => [
+    'console' => [
+        'router' => [
             'routes' => [
             ],
         ],
     ],
     'service_manager' => [
-        'factories'          => [
+        'factories' => [
+            ModuleOptions::class => ModuleOptionsFactory::class,
         ],
     ],
-    'view_helpers'    => [
-        'aliases'      => [
+    'view_helpers' => [
+        'aliases' => [
         ],
-        'factories'    => [
+        'factories' => [
         ],
     ],
-    'controllers'     => [
-        'factories'    => [
+    'controllers' => [
+        'factories' => [
         ],
     ],
-    'navigation'   => [
+    'navigation' => [
         'default' => [
         ],
     ],
diff --git a/src/UnicaenPdf/Command/PdfMergeShellCommandAwareTrait.php b/src/UnicaenPdf/Command/PdfMergeShellCommandAwareTrait.php
new file mode 100644
index 0000000..7908d8f
--- /dev/null
+++ b/src/UnicaenPdf/Command/PdfMergeShellCommandAwareTrait.php
@@ -0,0 +1,13 @@
+<?php
+
+namespace UnicaenPdf\Command;
+
+trait PdfMergeShellCommandAwareTrait
+{
+    protected PdfMergeShellCommandInterface $pdfMergeShellCommand;
+
+    public function setPdfMergeShellCommand(PdfMergeShellCommandInterface $pdfMergeShellCommand): void
+    {
+        $this->pdfMergeShellCommand = $pdfMergeShellCommand;
+    }
+}
\ No newline at end of file
diff --git a/src/UnicaenPdf/Command/PdfMergeShellCommandGs.php b/src/UnicaenPdf/Command/PdfMergeShellCommandGs.php
new file mode 100644
index 0000000..f031d0f
--- /dev/null
+++ b/src/UnicaenPdf/Command/PdfMergeShellCommandGs.php
@@ -0,0 +1,42 @@
+<?php
+
+namespace UnicaenPdf\Command;
+
+use UnicaenPdf\Command\PdfMergeShellCommandInterface;
+use UnicaenShell\Command\ShellCommand;
+
+/**
+ * Commande de concaténation de N fichiers PDF.
+ *
+ * Version utilisant 'ghostscript'.
+ */
+final class PdfMergeShellCommandGs extends ShellCommand implements PdfMergeShellCommandInterface
+{
+    protected string $noCompressionOption = '-dColorConversionStrategy=/LeaveColorUnchanged -dDownsampleMonoImages=false -dDownsampleGrayImages=false -dDownsampleColorImages=false -dAutoFilterColorImages=false -dAutoFilterGrayImages=false -dColorImageFilter=/FlateEncode -dGrayImageFilter=/FlateEncode';
+
+    /**
+     * @return string
+     */
+    public function getName(): string
+    {
+        return 'PdfMergeShellCommandGs';
+    }
+
+    public function checkRequirements(): void
+    {
+        $this->assertExecutableExists();
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public function generateCommandLine()
+    {
+        $command = $this->executable . ' ' . $this->noCompressionOption;
+        $command .=
+            ' -dNOPAUSE -sDEVICE=pdfwrite -sOUTPUTFILE=' . $this->outputFilePath .
+            ' -dBATCH ' . implode(' ', $this->inputFilesPaths);
+
+        $this->commandLine = $command;
+    }
+}
\ No newline at end of file
diff --git a/src/UnicaenPdf/Command/PdfMergeShellCommandInterface.php b/src/UnicaenPdf/Command/PdfMergeShellCommandInterface.php
new file mode 100644
index 0000000..5049cb7
--- /dev/null
+++ b/src/UnicaenPdf/Command/PdfMergeShellCommandInterface.php
@@ -0,0 +1,12 @@
+<?php
+
+namespace UnicaenPdf\Command;
+
+use UnicaenShell\Command\ShellCommandInterface;
+
+/**
+ * Commande de concaténation de fichiers PDF.
+ */
+interface PdfMergeShellCommandInterface extends ShellCommandInterface
+{
+}
\ No newline at end of file
diff --git a/src/UnicaenPdf/Command/PdfMergeShellCommandQpdf.php b/src/UnicaenPdf/Command/PdfMergeShellCommandQpdf.php
new file mode 100644
index 0000000..4142bab
--- /dev/null
+++ b/src/UnicaenPdf/Command/PdfMergeShellCommandQpdf.php
@@ -0,0 +1,37 @@
+<?php
+
+namespace UnicaenPdf\Command;
+
+use UnicaenPdf\Command\PdfMergeShellCommandInterface;
+use UnicaenShell\Command\ShellCommand;
+
+/**
+ * Commande de concaténation de N fichiers PDF.
+ *
+ * Version utilisant 'qpdf'.
+ */
+final class PdfMergeShellCommandQpdf extends ShellCommand implements PdfMergeShellCommandInterface
+{
+    public function getName(): string
+    {
+        return 'MergeShellCommandQpdf';
+    }
+
+    public function checkRequirements(): void
+    {
+        $this->assertExecutableExists();
+    }
+
+    public function generateCommandLine()
+    {
+        // Commande de fusion (cf. https://qpdf.readthedocs.io/en/10.5/cli.html#page-selection-options)
+        $command = $this->executable .
+            sprintf(' --warning-exit-0 %s --pages . %s -- %s',
+                array_shift($this->inputFilesPaths),
+                implode(' ', $this->inputFilesPaths),
+                $this->outputFilePath
+            );
+
+        $this->commandLine = $command;
+    }
+}
\ No newline at end of file
diff --git a/src/UnicaenPdf/Options/ModuleOptions.php b/src/UnicaenPdf/Options/ModuleOptions.php
new file mode 100644
index 0000000..5d08f30
--- /dev/null
+++ b/src/UnicaenPdf/Options/ModuleOptions.php
@@ -0,0 +1,13 @@
+<?php
+
+namespace UnicaenPdf\Options;
+
+/**
+ * Classe encapsulant les options de fonctionnement du module.
+ *
+ * @author Bertrand GAUTHIER <bertrand.gauthier@unicaen.fr>
+ */
+class ModuleOptions
+{
+
+}
\ No newline at end of file
diff --git a/src/UnicaenPdf/Options/ModuleOptionsAwareTrait.php b/src/UnicaenPdf/Options/ModuleOptionsAwareTrait.php
new file mode 100644
index 0000000..75a0ac8
--- /dev/null
+++ b/src/UnicaenPdf/Options/ModuleOptionsAwareTrait.php
@@ -0,0 +1,13 @@
+<?php
+
+namespace UnicaenPdf\Options;
+
+trait ModuleOptionsAwareTrait
+{
+    protected ModuleOptions $moduleOptions;
+
+    public function setModuleOptions(ModuleOptions $moduleOptions): void
+    {
+        $this->moduleOptions = $moduleOptions;
+    }
+}
\ No newline at end of file
diff --git a/src/UnicaenPdf/Options/ModuleOptionsFactory.php b/src/UnicaenPdf/Options/ModuleOptionsFactory.php
new file mode 100644
index 0000000..f664785
--- /dev/null
+++ b/src/UnicaenPdf/Options/ModuleOptionsFactory.php
@@ -0,0 +1,16 @@
+<?php
+
+namespace UnicaenPdf\Options;
+
+use Interop\Container\ContainerInterface;
+
+/**
+ * @author Unicaen
+ */
+class ModuleOptionsFactory
+{
+    public function __invoke(ContainerInterface $container): ModuleOptions
+    {
+        return new ModuleOptions();
+    }
+}
\ No newline at end of file
-- 
GitLab