diff --git a/lib/Handler/FooterHandler.php b/lib/Handler/FooterHandler.php index 962c3188c..b76f0cde1 100644 --- a/lib/Handler/FooterHandler.php +++ b/lib/Handler/FooterHandler.php @@ -26,6 +26,7 @@ use OCP\IL10N; use OCP\ITempManager; use OCP\IURLGenerator; +use OCP\L10N\IFactory; class FooterHandler { private QrCode $qrCode; @@ -40,6 +41,7 @@ public function __construct( private PdfParserService $pdfParserService, private IURLGenerator $urlGenerator, private IL10N $l10n, + private IFactory $l10nFactory, private ITempManager $tempManager, ) { } @@ -70,6 +72,7 @@ public function getFooter(File $file, FileEntity $fileEntity): string { $dimension['h'] * self::POINT_TO_MILIMETER, ], ]); + $pdf->SetDirectionality($this->templateVars['direction']); } $pdf->AddPage( orientation: 'P', @@ -110,6 +113,8 @@ public function setTemplateVar(string $name, mixed $value): self { private function getTemplateVars(): array { $this->templateVars['signedBy'] = $this->appConfig->getValueString(Application::APP_ID, 'footer_signed_by', $this->l10n->t('Digital signed by LibreSign.')); + $this->templateVars['direction'] = $this->l10nFactory->getLanguageDirection($this->l10n->getLanguageCode()); + $this->templateVars['linkToSite'] = $this->appConfig->getValueString(Application::APP_ID, 'footer_link_to_site', 'https://libresign.coop'); $this->templateVars['validationSite'] = $this->appConfig->getValueString(Application::APP_ID, 'validation_site'); diff --git a/tests/Unit/Handler/FooterHandlerTest.php b/tests/Unit/Handler/FooterHandlerTest.php index d910552ea..06b8ceaac 100644 --- a/tests/Unit/Handler/FooterHandlerTest.php +++ b/tests/Unit/Handler/FooterHandlerTest.php @@ -13,6 +13,7 @@ use OCP\IL10N; use OCP\ITempManager; use OCP\IURLGenerator; +use OCP\L10N\IFactory; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\MockObject\MockObject; @@ -20,7 +21,8 @@ final class FooterHandlerTest extends \OCA\Libresign\Tests\Unit\TestCase { private IAppConfig $appConfig; private PdfParserService&MockObject $pdfParserService; private IURLGenerator&MockObject $urlGenerator; - private IL10N&MockObject $l10n; + private IL10N $l10n; + private IFactory $l10nFactory; private ITempManager $tempManager; private FooterHandler $footerHandler; public function setUp(): void { @@ -29,10 +31,7 @@ public function setUp(): void { $this->urlGenerator = $this->createMock(IURLGenerator::class); $this->tempManager = \OCP\Server::get(ITempManager::class); - $this->l10n = $this->createMock(IL10N::class); - $this->l10n - ->method('t') - ->will($this->returnArgument(0)); + $this->l10nFactory = \OCP\Server::get(IFactory::class); } private function getClass(): FooterHandler { @@ -41,6 +40,7 @@ private function getClass(): FooterHandler { $this->pdfParserService, $this->urlGenerator, $this->l10n, + $this->l10nFactory, $this->tempManager, ); return $this->footerHandler; @@ -50,12 +50,13 @@ public function testGetFooterWithoutValidationSite(): void { $this->appConfig->setValueBool(Application::APP_ID, 'add_footer', false); $file = $this->createMock(\OCP\Files\File::class); $libresignFile = $this->createMock(\OCA\Libresign\Db\File::class); + $this->l10n = $this->l10nFactory->get(Application::APP_ID); $actual = $this->getClass()->getFooter($file, $libresignFile); $this->assertEmpty($actual); } #[DataProvider('dataGetFooterWithSuccess')] - public function testGetFooterWithSuccess(array $settings, array $expected): void { + public function testGetFooterWithSuccess(string $language, array $settings, array $expected): void { foreach ($settings as $key => $value) { switch (gettype($value)) { case 'boolean': @@ -85,10 +86,17 @@ public function testGetFooterWithSuccess(array $settings, array $expected): void default => '', }; }); + + $this->l10n = $this->l10nFactory->get(Application::APP_ID, $language); + $pdf = $this->getClass() ->getFooter($file, $libresignFile); if ($settings['add_footer']) { - $actual = $this->extractPdfContent($pdf, array_keys($expected)); + $actual = $this->extractPdfContent( + $pdf, + array_keys($expected), + $this->l10nFactory->getLanguageDirection($language) + ); if ($settings['write_qrcode_on_footer']) { $this->assertNotEmpty($actual['qrcode'], 'Invalid qrcode content'); unset($actual['qrcode'], $expected['qrcode']); @@ -100,11 +108,13 @@ public function testGetFooterWithSuccess(array $settings, array $expected): void } public static function dataGetFooterWithSuccess(): array { - return [ - [ + $data = [ + 'without_footer' => [ + 'en', ['add_footer' => false,], [] ], - [ + 'en_with_more_fields' => [ + 'en', [ 'add_footer' => true, 'validation_site' => 'http://test.coop', @@ -113,7 +123,7 @@ public static function dataGetFooterWithSuccess(): array { 'footer_signed_by' => 'Digital signed by LibreSign.', 'footer_validate_in' => 'Validate in %s.', 'footer_template' => <<<'HTML' -
+
qrcodeSize:
signedBy:
validateIn:
@@ -128,7 +138,8 @@ public static function dataGetFooterWithSuccess(): array { 'validateIn' => 'Validate in %s.', ] ], - [ + 'en' => [ + 'en', [ 'add_footer' => true, 'validation_site' => 'http://test.coop', @@ -137,7 +148,7 @@ public static function dataGetFooterWithSuccess(): array { 'footer_signed_by' => 'Digital signed by LibreSign.', 'footer_validate_in' => 'Validate in %s.', 'footer_template' => <<<'HTML' -
+
signedBy:
validateIn:
@@ -148,7 +159,8 @@ public static function dataGetFooterWithSuccess(): array { 'validateIn' => 'Validate in %s.', ] ], - [ + 'fr' => [ + 'fr', [ 'add_footer' => true, 'validation_site' => 'http://test.coop', @@ -157,7 +169,7 @@ public static function dataGetFooterWithSuccess(): array { 'footer_signed_by' => 'Signé numériquement avec LibreSign.', 'footer_validate_in' => 'Validate in %s', 'footer_template' => <<<'HTML' -
+
signedBy:
validateIn:
@@ -168,7 +180,8 @@ public static function dataGetFooterWithSuccess(): array { 'validateIn' => 'Validate in %s', ] ], - [ + 'el' => [ + 'el', [ 'add_footer' => true, 'validation_site' => 'http://test.coop', @@ -177,7 +190,7 @@ public static function dataGetFooterWithSuccess(): array { 'footer_signed_by' => 'Το αρχείο υπάρχει', 'footer_validate_in' => 'Validate in %s.', 'footer_template' => <<<'HTML' -
+
signedBy:
validateIn:
@@ -188,10 +201,34 @@ public static function dataGetFooterWithSuccess(): array { 'validateIn' => 'Validate in %s.', ] ], + 'he' => [ + 'he', + [ + 'add_footer' => true, + 'validation_site' => 'http://test.coop', + 'write_qrcode_on_footer' => false, + 'footer_link_to_site' => 'https://libresign.coop', + 'footer_signed_by' => 'אין המלצות. נא להתחיל להקליד.', + 'footer_validate_in' => 'אמת ב- %s.', + 'footer_template' => <<<'HTML' +
+ signedBy:
+ validateIn:
+
+ HTML, + ], + [ + 'signedBy' => 'אין המלצות. נא להתחיל להקליד.', + 'validateIn' => 'אמת ב- %s.', + ] + ], ]; + + // LTR langages was ignored at CI because the returned text is flipped by MPDF + return array_filter($data, fn ($key) => !in_array($key, ['he']), ARRAY_FILTER_USE_KEY); } - private function extractPdfContent(string $content, array $keys): array { + private function extractPdfContent(string $content, array $keys, string $direction): array { $this->assertNotEmpty($content, 'Empty PDF file'); $this->assertNotEmpty($keys, 'Is necessary to send a not empty array of fields to search at PDF file'); $parser = new \Smalot\PdfParser\Parser(); @@ -201,8 +238,13 @@ private function extractPdfContent(string $content, array $keys): array { $content = explode("\n", $text); $this->assertNotEmpty($content, 'PDF without any row'); $content = array_map(fn ($row) => str_getcsv($row, ':'), $content); - $content = array_filter($content, fn ($row) => in_array($row[0], $keys)); + + // Necessary flip key/value when the language is LTR + $columnKey = $direction === 'rtl' ? 1 : 0; + $columnValue = $direction === 'rtl' ? 0 : 1; + + $content = array_filter($content, fn ($row) => in_array($row[$columnKey], $keys)); $this->assertNotEmpty($content, 'Fields not found at PDF file'); - return array_column($content, 1, 0); + return array_column($content, $columnValue, $columnKey); } }