SwissQR: drop more files from sprain/php-swiss-qr-bill

This commit is contained in:
Didier 'OdyX' Raboud
2023-04-16 16:13:44 +02:00
parent b6a23fc54c
commit feea77bf59
8 changed files with 0 additions and 797 deletions

View File

@@ -1,317 +0,0 @@
<?php declare(strict_types=1);
namespace Sprain\SwissQrBill\PaymentPart\Output\FpdfOutput;
use Fpdf\Fpdf;
use setasign\Fpdi\Fpdi;
use Sprain\SwissQrBill\Exception\InvalidFpdfImageFormat;
use Sprain\SwissQrBill\PaymentPart\Output\AbstractOutput;
use Sprain\SwissQrBill\PaymentPart\Output\Element\OutputElementInterface;
use Sprain\SwissQrBill\PaymentPart\Output\Element\Placeholder;
use Sprain\SwissQrBill\PaymentPart\Output\Element\Text;
use Sprain\SwissQrBill\PaymentPart\Output\Element\Title;
use Sprain\SwissQrBill\PaymentPart\Output\OutputInterface;
use Sprain\SwissQrBill\PaymentPart\Translation\Translation;
use Sprain\SwissQrBill\QrBill;
use Sprain\SwissQrBill\QrCode\QrCode;
final class FpdfOutput extends AbstractOutput implements OutputInterface
{
// FPDF
private const BORDER = 0;
private const ALIGN_LEFT = 'L';
private const ALIGN_RIGHT = 'R';
private const ALIGN_CENTER = 'C';
private const FONT = 'Helvetica';
// Positioning
private const CURRENCY_AMOUNT_Y = 259.3;
private const AMOUNT_LINE_SPACING = 1.2;
private const AMOUNT_LINE_SPACING_RCPT = 0.6;
private const LEFT_PART_X = 4;
private const RIGHT_PART_X = 66;
private const RIGHT_PART_X_INFO = 117;
private const TITLE_Y = 195.2;
// Font size
private const FONT_SIZE_MAIN_TITLE = 11;
private const FONT_SIZE_TITLE_RECEIPT = 6;
private const FONT_SIZE_RECEIPT = 8;
private const FONT_SIZE_TITLE_PAYMENT_PART = 8;
private const FONT_SIZE_PAYMENT_PART = 10;
private const FONT_SIZE_FURTHER_INFORMATION = 7;
// Line spacing
private const LINE_SPACING_RECEIPT = 3.4;
private const LINE_SPACING_PAYMENT_PART = 4.8;
private float $amountLS = 0;
private Fpdf|Fpdi $fpdf;
private float $offsetX;
private float $offsetY;
public function __construct(
QrBill $qrBill,
string $language,
Fpdf|Fpdi $fpdf,
float $offsetX = 0,
float $offsetY = 0
) {
parent::__construct($qrBill, $language);
$this->fpdf = $fpdf;
$this->offsetX = $offsetX;
$this->offsetY = $offsetY;
$this->setQrCodeImageFormat(QrCode::FILE_FORMAT_PNG);
}
public function getPaymentPart(): void
{
$this->fpdf->SetAutoPageBreak(false);
$this->addSeparatorContentIfNotPrintable();
$this->addInformationContentReceipt();
$this->addCurrencyContentReceipt();
$this->addAmountContentReceipt();
$this->addSwissQrCodeImage();
$this->addInformationContent();
$this->addCurrencyContent();
$this->addAmountContent();
$this->addFurtherInformationContent();
}
public function setQrCodeImageFormat(string $fileExtension): AbstractOutput
{
if (QrCode::FILE_FORMAT_SVG === $fileExtension) {
throw new InvalidFpdfImageFormat('SVG images are not allowed by FPDF.');
}
$this->qrCodeImageFormat = $fileExtension;
return $this;
}
private function addSwissQrCodeImage(): void
{
$qrCode = $this->getQrCode();
$yPosQrCode = 209.5 + $this->offsetY;
$xPosQrCode = 67 + $this->offsetX;
if ((bool)ini_get('allow_url_fopen')) {
$this->fpdf->Image(
$qrCode->getDataUri($this->getQrCodeImageFormat()),
$xPosQrCode,
$yPosQrCode,
46,
46,
'png'
);
return;
}
if (method_exists($this->fpdf, 'MemImage')) {
$this->fpdf->MemImage(
$qrCode->getAsString($this->getQrCodeImageFormat()),
$xPosQrCode,
$yPosQrCode,
46,
46
);
return;
}
throw new UnsupportedEnvironmentException(
'"allow_url_fopen" is disabled on your server. Use FPDF with MemImageTrait. See fpdf-example.php within this library.'
);
}
private function addInformationContentReceipt(): void
{
// Title
$this->fpdf->SetFont(self::FONT, 'B', self::FONT_SIZE_MAIN_TITLE);
$this->SetXY(self::LEFT_PART_X, self::TITLE_Y);
$this->fpdf->MultiCell(0, 7, iconv('UTF-8', 'windows-1252', Translation::get('receipt', $this->language)));
// Elements
$this->setY(204);
foreach ($this->getInformationElementsOfReceipt() as $receiptInformationElement) {
$this->setX(self::LEFT_PART_X);
$this->setContentElement($receiptInformationElement, true);
}
// Acceptance section
$this->fpdf->SetFont(self::FONT, 'B', self::FONT_SIZE_TITLE_RECEIPT);
$this->SetXY(self::LEFT_PART_X, 274.3);
$this->fpdf->Cell(54, 0, iconv('UTF-8', 'windows-1252', Translation::get('acceptancePoint', $this->language)), self::BORDER, '', self::ALIGN_RIGHT);
}
private function addInformationContent(): void
{
// Title
$this->fpdf->SetFont(self::FONT, 'B', self::FONT_SIZE_MAIN_TITLE);
$this->SetXY(self::RIGHT_PART_X, 195.2);
$this->fpdf->MultiCell(48, 7, iconv('UTF-8', 'windows-1252', Translation::get('paymentPart', $this->language)));
// Elements
$this->setY(197.3);
foreach ($this->getInformationElements() as $informationElement) {
$this->setX(self::RIGHT_PART_X_INFO);
$this->setContentElement($informationElement, false);
}
}
private function addCurrencyContentReceipt(): void
{
$this->setY(self::CURRENCY_AMOUNT_Y);
foreach ($this->getCurrencyElements() as $receiptCurrencyElement) {
$this->amountLS = self::AMOUNT_LINE_SPACING_RCPT;
$this->setX(self::LEFT_PART_X);
$this->setContentElement($receiptCurrencyElement, true);
$this->amountLS = 0;
}
}
private function addAmountContentReceipt(): void
{
$this->setY(self::CURRENCY_AMOUNT_Y);
foreach ($this->getAmountElementsReceipt() as $receiptAmountElement) {
$this->amountLS = self::AMOUNT_LINE_SPACING_RCPT;
$this->setX(16);
$this->setContentElement($receiptAmountElement, true);
$this->amountLS = 0;
}
}
private function addCurrencyContent(): void
{
$this->setY(self::CURRENCY_AMOUNT_Y);
foreach ($this->getCurrencyElements() as $currencyElement) {
$this->amountLS = self::AMOUNT_LINE_SPACING;
$this->setX(self::RIGHT_PART_X);
$this->setContentElement($currencyElement, false);
$this->amountLS = 0;
}
}
private function addAmountContent(): void
{
$this->setY(self::CURRENCY_AMOUNT_Y);
foreach ($this->getAmountElements() as $amountElement) {
$this->amountLS = self::AMOUNT_LINE_SPACING;
$this->setX(80);
$this->setContentElement($amountElement, false);
$this->amountLS = 0;
}
}
private function addFurtherInformationContent(): void
{
$this->SetXY(self::RIGHT_PART_X, 286);
$this->fpdf->SetFont(self::FONT, '', self::FONT_SIZE_FURTHER_INFORMATION);
foreach ($this->getFurtherInformationElements() as $furtherInformationElement) {
$this->setX(self::RIGHT_PART_X);
$this->setContentElement($furtherInformationElement, true);
}
}
private function addSeparatorContentIfNotPrintable(): void
{
if (!$this->isPrintable()) {
$this->fpdf->SetLineWidth(0.1);
$this->fpdf->Line(2 + $this->offsetX, 193 + $this->offsetY, 208 + $this->offsetX, 193 + $this->offsetY);
$this->fpdf->Line(62 + $this->offsetX, 193 + $this->offsetY, 62 + $this->offsetX, 296 + $this->offsetY);
$this->fpdf->SetFont(self::FONT, '', self::FONT_SIZE_FURTHER_INFORMATION);
$this->setY(189.6);
$this->fpdf->MultiCell(0, 0, iconv('UTF-8', 'windows-1252', Translation::get('separate', $this->language)), self::BORDER, self::ALIGN_CENTER);
}
}
private function setContentElement(OutputElementInterface $element, bool $isReceiptPart): void
{
if ($element instanceof Title) {
$this->setTitleElement($element, $isReceiptPart);
}
if ($element instanceof Text) {
$this->setTextElement($element, $isReceiptPart);
}
if ($element instanceof Placeholder) {
$this->setPlaceholderElement($element);
}
}
private function setTitleElement(Title $element, bool $isReceiptPart): void
{
$this->fpdf->SetFont(self::FONT, 'B', $isReceiptPart ? self::FONT_SIZE_TITLE_RECEIPT : self::FONT_SIZE_TITLE_PAYMENT_PART);
$this->fpdf->MultiCell(0, 2.8, iconv(
'UTF-8',
'windows-1252',
Translation::get(str_replace("text.", "", $element->getTitle()), $this->language)
));
$this->fpdf->Ln($this->amountLS);
}
private function setTextElement(Text $element, bool $isReceiptPart): void
{
$this->fpdf->SetFont(self::FONT, '', $isReceiptPart ? self::FONT_SIZE_RECEIPT : self::FONT_SIZE_PAYMENT_PART);
$this->fpdf->MultiCell(
$isReceiptPart ? 54 : 0,
$isReceiptPart ? 3.3 : 4,
str_replace("text.", "", iconv('UTF-8', 'windows-1252', $element->getText())),
self::BORDER,
self::ALIGN_LEFT
);
$this->fpdf->Ln($isReceiptPart ? self::LINE_SPACING_RECEIPT : self::LINE_SPACING_PAYMENT_PART);
}
private function setPlaceholderElement(Placeholder $element): void
{
$type = $element->getType();
switch ($type) {
case Placeholder::PLACEHOLDER_TYPE_AMOUNT['type']:
$y = $this->fpdf->GetY() + 1;
$x = $this->fpdf->GetX() - 2;
break;
case Placeholder::PLACEHOLDER_TYPE_AMOUNT_RECEIPT['type']:
$y = $this->fpdf->GetY() - 2;
$x = $this->fpdf->GetX() + 11;
break;
case Placeholder::PLACEHOLDER_TYPE_PAYABLE_BY['type']:
case Placeholder::PLACEHOLDER_TYPE_PAYABLE_BY_RECEIPT['type']:
default:
$y = $this->fpdf->GetY() + 1;
$x = $this->fpdf->GetX() + 1;
}
$this->fpdf->Image(
$element->getFile(Placeholder::FILE_TYPE_PNG),
$x,
$y,
$element->getWidth(),
$element->getHeight()
);
}
private function setX(float $x): void
{
$this->fpdf->SetX($x + $this->offsetX);
}
private function setY(float $y): void
{
$this->fpdf->SetY($y + $this->offsetY);
}
private function SetXY(float $x, float $y): void
{
$this->fpdf->SetXY($x + $this->offsetX, $y + $this->offsetY);
}
}

View File

@@ -1,8 +0,0 @@
<?php
namespace Sprain\SwissQrBill\PaymentPart\Output\FpdfOutput;
class UnsupportedEnvironmentException extends \RuntimeException
{
}

View File

@@ -1,190 +0,0 @@
<?php declare(strict_types=1);
namespace Sprain\SwissQrBill\PaymentPart\Output\HtmlOutput;
use Sprain\SwissQrBill\PaymentPart\Output\AbstractOutput;
use Sprain\SwissQrBill\PaymentPart\Output\Element\Placeholder;
use Sprain\SwissQrBill\PaymentPart\Output\Element\Text;
use Sprain\SwissQrBill\PaymentPart\Output\Element\Title;
use Sprain\SwissQrBill\PaymentPart\Output\HtmlOutput\Template\PlaceholderElementTemplate;
use Sprain\SwissQrBill\PaymentPart\Output\HtmlOutput\Template\PrintableStylesTemplate;
use Sprain\SwissQrBill\PaymentPart\Output\HtmlOutput\Template\TextElementTemplate;
use Sprain\SwissQrBill\PaymentPart\Output\HtmlOutput\Template\PaymentPartTemplate;
use Sprain\SwissQrBill\PaymentPart\Output\HtmlOutput\Template\TitleElementTemplate;
use Sprain\SwissQrBill\PaymentPart\Output\OutputInterface;
use Sprain\SwissQrBill\PaymentPart\Translation\Translation;
final class HtmlOutput extends AbstractOutput implements OutputInterface
{
public function getPaymentPart(): string
{
$paymentPart = PaymentPartTemplate::TEMPLATE;
$paymentPart = $this->addSwissQrCodeImage($paymentPart);
$paymentPart = $this->addInformationContent($paymentPart);
$paymentPart = $this->addInformationContentReceipt($paymentPart);
$paymentPart = $this->addCurrencyContent($paymentPart);
$paymentPart = $this->addAmountContent($paymentPart);
$paymentPart = $this->addAmountContentReceipt($paymentPart);
$paymentPart = $this->addFurtherInformationContent($paymentPart);
$paymentPart = $this->hideSeparatorContentIfPrintable($paymentPart);
$paymentPart = $this->translateContents($paymentPart, $this->getLanguage());
return $paymentPart;
}
private function addSwissQrCodeImage(string $paymentPart): string
{
$qrCode = $this->getQrCode();
$paymentPart = str_replace('{{ swiss-qr-image }}', $qrCode->getDataUri($this->getQrCodeImageFormat()), $paymentPart);
return $paymentPart;
}
private function addInformationContent(string $paymentPart): string
{
$informationContent = '';
foreach ($this->getInformationElements() as $informationElement) {
$informationContentPart = $this->getContentElement($informationElement);
$informationContent .= $informationContentPart;
}
$paymentPart = str_replace('{{ information-content }}', $informationContent, $paymentPart);
return $paymentPart;
}
private function addInformationContentReceipt(string $paymentPart): string
{
$informationContent = '';
foreach ($this->getInformationElementsOfReceipt() as $informationElement) {
$informationContent .= $this->getContentElement($informationElement);
}
$paymentPart = str_replace('{{ information-content-receipt }}', $informationContent, $paymentPart);
return $paymentPart;
}
private function addCurrencyContent(string $paymentPart): string
{
$currencyContent = '';
foreach ($this->getCurrencyElements() as $currencyElement) {
$currencyContent .= $this->getContentElement($currencyElement);
}
$paymentPart = str_replace('{{ currency-content }}', $currencyContent, $paymentPart);
return $paymentPart;
}
private function addAmountContent(string $paymentPart): string
{
$amountContent = '';
foreach ($this->getAmountElements() as $amountElement) {
$amountContent .= $this->getContentElement($amountElement);
}
$paymentPart = str_replace('{{ amount-content }}', $amountContent, $paymentPart);
return $paymentPart;
}
private function addAmountContentReceipt(string $paymentPart): string
{
$amountContent = '';
foreach ($this->getAmountElementsReceipt() as $amountElement) {
$amountContent .= $this->getContentElement($amountElement);
}
$paymentPart = str_replace('{{ amount-content-receipt }}', $amountContent, $paymentPart);
return $paymentPart;
}
private function addFurtherInformationContent(string $paymentPart): string
{
$furtherInformationContent = '';
foreach ($this->getFurtherInformationElements() as $furtherInformationElement) {
$furtherInformationContent .= $this->getContentElement($furtherInformationElement);
}
$paymentPart = str_replace('{{ further-information-content }}', $furtherInformationContent, $paymentPart);
return $paymentPart;
}
private function hideSeparatorContentIfPrintable(string $paymentPart): string
{
$printableStyles = '';
if ($this->isPrintable()) {
$printableStyles = PrintableStylesTemplate::TEMPLATE;
}
$paymentPart = str_replace('{{ printable-content }}', $printableStyles, $paymentPart);
return $paymentPart;
}
private function getContentElement(Title|Text|Placeholder $element): string
{
# https://github.com/phpstan/phpstan/issues/4451
# @phpstan-ignore-next-line
return match (get_class($element)) {
Title::class => $this->getTitleElement($element),
Text::class => $this->getTextElement($element),
Placeholder::class => $this->getPlaceholderElement($element)
};
}
private function getTitleElement(Title $element): string
{
$elementTemplate = TitleElementTemplate::TEMPLATE;
$elementString = str_replace('{{ title }}', $element->getTitle(), $elementTemplate);
return $elementString;
}
private function getTextElement(Text $element): string
{
$elementTemplate = TextElementTemplate::TEMPLATE;
$elementString = str_replace('{{ text }}', nl2br($element->getText()), $elementTemplate);
return $elementString;
}
private function getPlaceholderElement(Placeholder $element): string
{
$elementTemplate = PlaceholderElementTemplate::TEMPLATE;
$elementString = $elementTemplate;
$svgDoc = new \DOMDocument();
$svgDoc->loadXML(file_get_contents($element->getFile()));
$svg = $svgDoc->getElementsByTagName('svg');
$dataUri = 'data:image/svg+xml;base64,' . base64_encode($svg->item(0)->C14N());
$elementString = str_replace('{{ file }}', $dataUri, $elementString);
$elementString = str_replace('{{ width }}', (string) $element->getWidth(), $elementString);
$elementString = str_replace('{{ height }}', (string) $element->getHeight(), $elementString);
$elementString = str_replace('{{ id }}', $element->getType(), $elementString);
return $elementString;
}
private function translateContents(string $paymentPart, string $language): string
{
$translations = Translation::getAllByLanguage($language);
foreach ($translations as $key => $text) {
$paymentPart = str_replace('{{ text.' . $key . ' }}', $text, $paymentPart);
}
return $paymentPart;
}
}

View File

@@ -1,232 +0,0 @@
<?php declare(strict_types=1);
namespace Sprain\SwissQrBill\PaymentPart\Output\HtmlOutput\Template;
class PaymentPartTemplate
{
public const TEMPLATE = <<<EOT
<style>
#qr-bill {
box-sizing: border-box;
border-collapse: collapse;
color: #000 !important;
}
#qr-bill * {
font-family: Arial, Frutiger, Helvetica, "Liberation Sans" !important;
}
#qr-bill img.qr-bill-placeholder {
margin-top: 1pt;
}
#qr-bill-separate-info {
text-align: center;
font-size: 8pt !important;
line-height: 9pt;
border-bottom: 0.75pt solid black;
height: 5mm;
vertical-align: middle;
}
/* h1 / h2 */
#qr-bill h1 {
font-size: 11pt !important;
font-weight: bold !important;
margin: 0;
padding: 0;
height: 7mm;
color: #000 !important;
}
#qr-bill h2 {
font-weight: bold !important;
margin: 0;
padding: 0;
color: #000 !important;
}
#qr-bill-payment-part h2 {
font-size: 8pt !important;
line-height: 11pt !important;
margin-top: 11pt;
color: #000 !important;
}
#qr-bill-receipt h2 {
font-size: 6pt !important;
line-height: 8pt !important;
margin-top: 8pt;
color: #000 !important;
}
#qr-bill-payment-part h2:first-child,
#qr-bill-receipt h2:first-child {
margin-top: 0;
color: #000 !important;
}
/* p */
#qr-bill p {
font-weight: normal !important;
margin: 0;
padding: 0;
color: #000 !important;
}
#qr-bill-receipt p {
font-size: 8pt !important;
line-height: 9pt !important;
color: #000 !important;
}
#qr-bill-payment-part p {
font-size: 10pt !important;
line-height: 11pt !important;
color: #000 !important;
}
#qr-bill-amount-area-receipt p{
line-height: 11pt !important;
color: #000 !important;
}
#qr-bill-amount-area p{
line-height: 13pt !important;
color: #000 !important;
}
#qr-bill-payment-further-information p {
font-size: 7pt !important;
line-height: 9pt !important;
color: #000 !important;
}
/* Receipt */
#qr-bill-receipt {
box-sizing: border-box;
width: 62mm;
border-right: 0.2mm solid black;
padding-left: 5mm;
padding-top: 5mm;
vertical-align: top;
}
#qr-bill-information-receipt {
height: 56mm;
}
#qr-bill-amount-area-receipt {
height: 14mm;
}
#qr-bill-currency-receipt {
float: left;
margin-right: 2mm;
}
#qr-bill-acceptance-point {
height: 18mm;
text-align: right;
margin-right: 5mm;
}
#qr-bill img#placeholder_amount_receipt {
float: right;
margin-top: -9pt;
margin-right: 5mm;
}
/* Main part */
#qr-bill-payment-part {
box-sizing: border-box;
width: 148mm;
padding-left: 5mm;
padding-top: 5mm;
padding-right: 5mm;
vertical-align: top;
}
#qr-bill-payment-part-left {
float: left;
box-sizing: border-box;
width: 51mm;
}
#qr-bill-swiss-qr-image {
width: 46mm;
height: 46mm;
margin: 5mm;
margin-left: 0;
}
#qr-bill-amount-area {
height: 22mm;
}
#qr-bill-currency {
float: left;
margin-right: 2mm;
}
#qr-bill-payment-further-information {
clear: both;
}
#qr-bill img#placeholder_amount {
margin-left: 11mm;
margin-top: -11pt;
}
{{ printable-content }}
</style>
<table id="qr-bill">
<tr id="qr-bill-separate-info">
<td colspan="99"><span id="qr-bill-separate-info-text">{{ text.separate }}</span></td>
</tr>
<tr>
<td id="qr-bill-receipt">
<h1>{{ text.receipt }}</h1>
<div id="qr-bill-information-receipt">
{{ information-content-receipt }}
</div>
<div id="qr-bill-amount-area-receipt">
<div id="qr-bill-currency-receipt">
{{ currency-content }}
</div>
<div id="qr-bill-amount-receipt">
{{ amount-content-receipt }}
</div>
</div>
<div id="qr-bill-acceptance-point">
<h2>{{ text.acceptancePoint }}</h2>
</div>
</td>
<td id="qr-bill-payment-part">
<div id="qr-bill-payment-part-left">
<h1>{{ text.paymentPart }}</h1>
<img src="{{ swiss-qr-image }}" id="qr-bill-swiss-qr-image">
<div id="qr-bill-amount-area">
<div id="qr-bill-currency">
{{ currency-content }}
</div>
<div id="qr-bill-amount">
{{ amount-content }}
</div>
</div>
</div>
<div id="qr-bill-payment-part-right">
<div id="qr-bill-information">
{{ information-content }}
</div>
</div>
<div id="qr-bill-payment-further-information">
{{ further-information-content }}
</div>
</td>
</tr>
</table>
EOT;
}

View File

@@ -1,10 +0,0 @@
<?php declare(strict_types=1);
namespace Sprain\SwissQrBill\PaymentPart\Output\HtmlOutput\Template;
class PlaceholderElementTemplate
{
public const TEMPLATE = <<<EOT
<img src="{{ file }}" style="width:{{ width }}mm; height:{{ height }}mm;" class="qr-bill-placeholder" id="{{ id }}">
EOT;
}

View File

@@ -1,20 +0,0 @@
<?php declare(strict_types=1);
namespace Sprain\SwissQrBill\PaymentPart\Output\HtmlOutput\Template;
class PrintableStylesTemplate
{
public const TEMPLATE = <<<EOT
#qr-bill-separate-info {
border-bottom: 0;
}
#qr-bill-separate-info-text {
display: none;
}
#qr-bill-receipt {
border-right: 0;
}
EOT;
}

View File

@@ -1,10 +0,0 @@
<?php declare(strict_types=1);
namespace Sprain\SwissQrBill\PaymentPart\Output\HtmlOutput\Template;
class TextElementTemplate
{
public const TEMPLATE = <<<EOT
<p>{{ text }}</p>
EOT;
}

View File

@@ -1,10 +0,0 @@
<?php declare(strict_types=1);
namespace Sprain\SwissQrBill\PaymentPart\Output\HtmlOutput\Template;
class TitleElementTemplate
{
public const TEMPLATE = <<<EOT
<h2>{{ {{ title }} }}</h2>
EOT;
}