Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"phpunit/phpunit": "^10.5",
"dg/bypass-finals": "^1.8",
"dms/phpunit-arraysubset-asserts": "^0.5",
"dompdf/dompdf": "^3.0",
"fpdf/fpdf": "^1.85",
"friendsofphp/php-cs-fixer": "^3.15",
"khanamiryan/qrcode-detector-decoder": "^2.0.2",
Expand All @@ -42,7 +43,8 @@
"tecnickcom/tcpdf": "Needed to create pdfs with TcPdfOutput",
"fpdf/fpdf": "Needed to create pdfs with FpdfOutput",
"setasign/fpdi": "Needed to create pdfs with Fpdi",
"setasign/fpdf": "Needed to create pdfs with Fpdi"
"setasign/fpdf": "Needed to create pdfs with Fpdi",
"dompdf/dompdf": "Needed to create pdfs with Dompdf"
},
"autoload": {
"psr-4": {
Expand Down
51 changes: 51 additions & 0 deletions example/DompdfOutput/dompdf-example.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php declare(strict_types=1);

use Sprain\SwissQrBill\PaymentPart\Output\DisplayOptions;
use Sprain\SwissQrBill\PaymentPart\Output\DompdfOutput\DompdfOutput;
use Dompdf\Dompdf;

require __DIR__ . '/../../vendor/autoload.php';

// 1. Let's load the base example to define the qr bill contents
require __DIR__ . '/../example.php';

// 2. Create a full payment part in HTML
$output = new DompdfOutput($qrBill, 'en');

// 3. Optional, set layout options
$displayOptions = new DisplayOptions();
$displayOptions
->setPrintable(false) // true to remove lines for printing on a perforated stationery
->setDisplayTextDownArrows(false) // true to show arrows next to separation text, if shown
->setDisplayScissors(false) // true to show scissors instead of separation text
->setPositionScissorsAtBottom(false) // true to place scissors at the bottom, if shown
;

// 4. Create a full payment part in HTML
$html = $output
->setDisplayOptions($displayOptions)
->getPaymentPart();

$dompdf = new Dompdf();
$dompdf->setPaper('A4', 'portrait');

// important: needs UTF-8
$html = <<<EOT
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>$html</body>
</html>
EOT;

$dompdf->loadHtml($html, 'UTF-8');
$dompdf->render();

// 5. For demo purposes, let's save the generated example in a file
$examplePath = __DIR__ . '/dompdf-example.pdf';
file_put_contents($examplePath, $dompdf->output());

print 'Dompdf example created here: ' . $examplePath;
92 changes: 92 additions & 0 deletions src/PaymentPart/Output/DompdfOutput/DompdfOutput.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
<?php declare(strict_types=1);

namespace Sprain\SwissQrBill\PaymentPart\Output\DompdfOutput;

use Sprain\SwissQrBill\PaymentPart\Output\AbstractOutput;
use Sprain\SwissQrBill\PaymentPart\Output\HtmlOutput\HtmlOutput;
use Sprain\SwissQrBill\QrCode\QrCode;
use Sprain\SwissQrBill\QrBill;

final class DompdfOutput extends AbstractOutput
{
private HtmlOutput $htmlOutput;
private const FONT_UNICODE = 'zapfdingbats';
private const FONT_UNICODE_CHAR_SCISSORS = '"';
private const FONT_UNICODE_CHAR_DOWN_ARROW = 't';

public function __construct(QrBill $qrBill, string $language)
{
parent::__construct($qrBill, $language);
$this->htmlOutput = (new HtmlOutput($qrBill, $language));
}

public function getPaymentPart(): ?string
{
$options = $this->getDisplayOptions();

$html = $this->htmlOutput
->setDisplayOptions($options)
// SVG is not compatible with Dompdf for now
->setQrCodeImageFormat(QrCode::FILE_FORMAT_PNG)
->getPaymentPart();

// add custom styles
$html .= $this->getTemplate();

// replace base HTML special chars with the Dompdf-compatible ones
$mapping = [
'\\2702' => self::FONT_UNICODE_CHAR_SCISSORS,
'\\25BC' => self::FONT_UNICODE_CHAR_DOWN_ARROW,
'&#9986;' => self::FONT_UNICODE_CHAR_SCISSORS
];
$html = str_replace(array_keys($mapping), array_values($mapping), $html);

return $html;
}

private function getTemplate(): string
{
$options = $this->getDisplayOptions();

$font = self::FONT_UNICODE;
$scissorsLeft = $options->isPositionScissorsAtBottom() ? '2.6mm' : '-0.9mm';

return <<<EOT
<style type="text/css">
html {
margin: 0;
}
#qr-bill-separate-info:before,
#qr-bill-separate-info-text:before,
#qr-bill-separate-info-text:after,
#qr-bill #qr-bill-scissors {
font-family: $font !important;
}
#qr-bill-separate-info-text:before {
margin-right: -6mm;
}
#qr-bill-separate-info-text:before,
#qr-bill-separate-info-text:after {
letter-spacing: 0.7mm;
}
#qr-bill-separate-info:before {
top: 3.0mm;
}
#qr-bill-scissors {
left: $scissorsLeft;
}
#qr-bill {
position: absolute;
bottom: 104mm;
}
#qr-bill-currency {
float: none !important;
display: inline-block;
}
#qr-bill-amount {
display: inline-block;
}
</style>
EOT;
}
}
97 changes: 97 additions & 0 deletions tests/PaymentPart/Output/DompdfOutput/DompdfOutputTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
<?php declare(strict_types=1);

namespace Sprain\Tests\SwissQrBill\PaymentPart\Output\DompdfOutput;

use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
use Sprain\SwissQrBill\PaymentPart\Output\DompdfOutput\DompdfOutput;
use Sprain\SwissQrBill\PaymentPart\Output\DisplayOptions;
use Sprain\SwissQrBill\QrBill;
use Sprain\SwissQrBill\QrCode\QrCode;
use Sprain\Tests\SwissQrBill\TestCompactSvgQrCodeTrait;
use Sprain\Tests\SwissQrBill\TraitValidQrBillsProvider;
use Dompdf\Dompdf;

final class DompdfOutputTest extends TestCase
{
use TraitValidQrBillsProvider;
use TestCompactSvgQrCodeTrait;

#[DataProvider('validQrBillsProvider')]
public function testValidQrBills(string $name, QrBill $qrBill)
{
$variations = [
[
'layout' => (new DisplayOptions())->setPrintable(false),
'format' => QrCode::FILE_FORMAT_PNG,
'file' => __DIR__ . '/../../../TestData/DompdfOutput/' . $name . $this->getCompact() . '.pdf'
],
[
'layout' => (new DisplayOptions())->setPrintable(true),
'format' => QrCode::FILE_FORMAT_PNG,
'file' => __DIR__ . '/../../../TestData/DompdfOutput/' . $name . $this->getCompact() . '.print.pdf'
],
[
'layout' => (new DisplayOptions())->setPrintable(false)->setDisplayScissors(true),
'format' => QrCode::FILE_FORMAT_PNG,
'file' => __DIR__ . '/../../../TestData/DompdfOutput/' . $name . $this->getCompact() . '.scissors.pdf'
],
[
'layout' => (new DisplayOptions())->setPrintable(false)->setDisplayScissors(true)->setPositionScissorsAtBottom(true),
'format' => QrCode::FILE_FORMAT_PNG,
'file' => __DIR__ . '/../../../TestData/DompdfOutput/' . $name . $this->getCompact() . '.scissorsdown.pdf'
],
[
'layout' => (new DisplayOptions())->setPrintable(false)->setDisplayTextDownArrows(true),
'format' => QrCode::FILE_FORMAT_PNG,
'file' => __DIR__ . '/../../../TestData/DompdfOutput/' . $name . $this->getCompact() . '.textarrows.pdf'
]
];

foreach ($variations as $variation) {
$file = $variation['file'];

$dompdf = new Dompdf();
$dompdf->setPaper('A4', 'portrait');

$dompdfOutput = (new DompdfOutput($qrBill, 'en'));
$html = $dompdfOutput
->setDisplayOptions($variation['layout'])
->getPaymentPart();

$html = <<<EOT
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>$html</body>
</html>
EOT;

$dompdf->loadHtml($html, 'UTF-8');
$dompdf->render();

$output = $dompdf->output();

if ($this->regenerateReferenceFiles) {
file_put_contents($file, $output);
}

$contents = $this->getActualPdfContents($output);

$this->assertNotNull($contents);
$this->assertSame($this->getActualPdfContents(file_get_contents($file)), $contents);
}
}

private function getActualPdfContents(string $fileContents): ?string
{
// Extract actual pdf content and ignore all meta data which may differ in different versions of Fpdf
$pattern = '/stream(.*?)endstream/s';
preg_match($pattern, $fileContents, $matches);

return $matches[1] ?? null;
}
}
2 changes: 1 addition & 1 deletion tests/QrBillTestDataRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -309,4 +309,4 @@ public function invalidAddress(): CombinedAddress
''
);
}
}
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added tests/TestData/DompdfOutput/qr-full-set.pdf
Binary file not shown.
Binary file added tests/TestData/DompdfOutput/qr-full-set.print.pdf
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added tests/TestData/DompdfOutput/qr-minimal-setup.pdf
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -264,4 +264,5 @@ <h2>Account / Payable to</h2><p>CH44 3199 9123 0008 8901 2<br />
</div>
</td>
</tr>
</table>
</table>

Original file line number Diff line number Diff line change
Expand Up @@ -271,4 +271,5 @@ <h2>Account / Payable to</h2><p>CH44 3199 9123 0008 8901 2<br />
</div>
</td>
</tr>
</table>
</table>

Loading