FpdfOutput::setX()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php declare(strict_types=1);
2
3
4
namespace Sprain\SwissQrBill\PaymentPart\Output\FpdfOutput;
5
6
use Fpdf\Fpdf;
7
use Sprain\SwissQrBill\Exception\InvalidFpdfImageFormat;
8
use Sprain\SwissQrBill\PaymentPart\Output\AbstractOutput;
9
use Sprain\SwissQrBill\PaymentPart\Output\Element\OutputElementInterface;
10
use Sprain\SwissQrBill\PaymentPart\Output\Element\Placeholder;
11
use Sprain\SwissQrBill\PaymentPart\Output\Element\Text;
12
use Sprain\SwissQrBill\PaymentPart\Output\Element\Title;
13
use Sprain\SwissQrBill\PaymentPart\Output\OutputInterface;
14
use Sprain\SwissQrBill\PaymentPart\Translation\Translation;
15
use Sprain\SwissQrBill\QrBill;
16
use Sprain\SwissQrBill\QrCode\QrCode;
17
18
final class FpdfOutput extends AbstractOutput implements OutputInterface
19
{
20
    // FPDF
21
    private const BORDER = 0;
22
    private const ALIGN_LEFT = 'L';
23
    private const ALIGN_RIGHT = 'R';
24
    private const ALIGN_CENTER = 'C';
25
    private const FONT = 'Helvetica';
26
27
    // Location
28
    private const CURRENCY_AMOUNT_Y = 259.3;
29
    private const AMOUNT_LINE_SPACING = 1.2;
30
    private const AMOUNT_LINE_SPACING_RCPT = 0.6;
31
    private const LEFT_PART_X = 4;
32
    private const RIGHT_PART_X = 66;
33
    private const RIGHT_PART_X_INFO = 117;
34
    private const TITLE_Y = 195.2;
35
36
    // Font size
37
    private const FONT_SIZE_MAIN_TITLE = 11;
38
    private const FONT_SIZE_TITLE_RECEIPT = 6;
39
    private const FONT_SIZE_RECEIPT = 8;
40
    private const FONT_SIZE_TITLE_PAYMENT_PART = 8;
41
    private const FONT_SIZE_PAYMENT_PART = 10;
42
    private const FONT_SIZE_FURTHER_INFORMATION = 7;
43
44
    // Line spacing
45
    private const LINE_SPACING_RECEIPT = 3.4;
46
    private const LINE_SPACING_PAYMENT_PART = 4.8;
47
    private float $amountLS = 0;
48
49
    private Fpdf $fpdf;
50
    private float $offsetX;
51
    private float $offsetY;
52
53
    public function __construct(
54
        QrBill $qrBill,
55
        string $language,
56
        Fpdf $fpdf,
57
        float $offsetX = 0,
58
        float $offsetY = 0
59
    ) {
60
        parent::__construct($qrBill, $language);
61
        $this->fpdf = $fpdf;
62
        $this->offsetX = $offsetX;
63
        $this->offsetY = $offsetY;
64
        $this->setQrCodeImageFormat(QrCode::FILE_FORMAT_PNG);
65
    }
66
67
    public function getPaymentPart(): void
68
    {
69
        $this->fpdf->SetAutoPageBreak(false);
70
71
        $this->addSeparatorContentIfNotPrintable();
72
73
        $this->addInformationContentReceipt();
74
        $this->addCurrencyContentReceipt();
75
        $this->addAmountContentReceipt();
76
77
        $this->addSwissQrCodeImage();
78
        $this->addInformationContent();
79
        $this->addCurrencyContent();
80
        $this->addAmountContent();
81
        $this->addFurtherInformationContent();
82
    }
83
84
    public function setQrCodeImageFormat(string $fileExtension): AbstractOutput
85
    {
86
        if ($fileExtension === 'svg') {
87
            throw new InvalidFpdfImageFormat('SVG images are not allowed by FPDF.');
88
        }
89
90
        $this->qrCodeImageFormat = $fileExtension;
91
92
        return $this;
93
    }
94
95
    private function addSwissQrCodeImage(): void
96
    {
97
        $qrCode = $this->getQrCode();
98
99
        $yPosQrCode = 209.5 + $this->offsetY;
100
        $xPosQrCode = 67 + $this->offsetX;
101
102
        $this->fpdf->Image($qrCode->getDataUri($this->getQrCodeImageFormat()), $xPosQrCode, $yPosQrCode, 46, 46, 'png');
103
    }
104
105
    private function addInformationContentReceipt(): void
106
    {
107
        // Title
108
        $this->fpdf->SetFont(self::FONT, 'B', self::FONT_SIZE_MAIN_TITLE);
109
        $this->SetXY(self::LEFT_PART_X, self::TITLE_Y);
110
        $this->fpdf->MultiCell(0, 7, utf8_decode(Translation::get('receipt', $this->language)));
0 ignored issues
show
Bug introduced by
It seems like Sprain\SwissQrBill\Payme...eipt', $this->language) can also be of type null; however, parameter $string of utf8_decode() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

110
        $this->fpdf->MultiCell(0, 7, utf8_decode(/** @scrutinizer ignore-type */ Translation::get('receipt', $this->language)));
Loading history...
111
112
        // Elements
113
        $this->setY(204);
114
        foreach ($this->getInformationElementsOfReceipt() as $receiptInformationElement) {
115
            $this->setX(self::LEFT_PART_X);
116
            $this->setContentElement($receiptInformationElement, true);
117
        }
118
119
        // Acceptance section
120
        $this->fpdf->SetFont(self::FONT, 'B', self::FONT_SIZE_TITLE_RECEIPT);
121
        $this->SetXY(self::LEFT_PART_X, 274.3);
122
        $this->fpdf->Cell(54, 0, utf8_decode(Translation::get('acceptancePoint', $this->language)), self::BORDER, '', self::ALIGN_RIGHT);
123
    }
124
125
    private function addInformationContent(): void
126
    {
127
        // Title
128
        $this->fpdf->SetFont(self::FONT, 'B', self::FONT_SIZE_MAIN_TITLE);
129
        $this->SetXY(self::RIGHT_PART_X, 195.2);
130
        $this->fpdf->MultiCell(48, 7, utf8_decode(Translation::get('paymentPart', $this->language)));
0 ignored issues
show
Bug introduced by
It seems like Sprain\SwissQrBill\Payme...Part', $this->language) can also be of type null; however, parameter $string of utf8_decode() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

130
        $this->fpdf->MultiCell(48, 7, utf8_decode(/** @scrutinizer ignore-type */ Translation::get('paymentPart', $this->language)));
Loading history...
131
132
        // Elements
133
        $this->setY(197.3);
134
        foreach ($this->getInformationElements() as $informationElement) {
135
            $this->setX(self::RIGHT_PART_X_INFO);
136
            $this->setContentElement($informationElement, false);
137
        }
138
    }
139
140
    private function addCurrencyContentReceipt(): void
141
    {
142
        $this->setY(self::CURRENCY_AMOUNT_Y);
143
        foreach ($this->getCurrencyElements() as $receiptCurrencyElement) {
144
            $this->amountLS = self::AMOUNT_LINE_SPACING_RCPT;
145
            $this->setX(self::LEFT_PART_X);
146
            $this->setContentElement($receiptCurrencyElement, true);
147
            $this->amountLS = 0;
148
        }
149
    }
150
151
    private function addAmountContentReceipt(): void
152
    {
153
        $this->setY(self::CURRENCY_AMOUNT_Y);
154
        foreach ($this->getAmountElementsReceipt() as $receiptAmountElement) {
155
            $this->amountLS = self::AMOUNT_LINE_SPACING_RCPT;
156
            $this->setX(16);
157
            $this->setContentElement($receiptAmountElement, true);
158
            $this->amountLS = 0;
159
        }
160
    }
161
162
    private function addCurrencyContent(): void
163
    {
164
        $this->setY(self::CURRENCY_AMOUNT_Y);
165
        foreach ($this->getCurrencyElements() as $currencyElement) {
166
            $this->amountLS = self::AMOUNT_LINE_SPACING;
167
            $this->setX(self::RIGHT_PART_X);
168
            $this->setContentElement($currencyElement, false);
169
            $this->amountLS = 0;
170
        }
171
    }
172
173
    private function addAmountContent(): void
174
    {
175
        $this->setY(self::CURRENCY_AMOUNT_Y);
176
        foreach ($this->getAmountElements() as $amountElement) {
177
            $this->amountLS = self::AMOUNT_LINE_SPACING;
178
            $this->setX(80);
179
            $this->setContentElement($amountElement, false);
180
            $this->amountLS = 0;
181
        }
182
    }
183
184
    private function addFurtherInformationContent(): void
185
    {
186
        $this->SetXY(self::RIGHT_PART_X, 286);
187
        $this->fpdf->SetFont(self::FONT, '', self::FONT_SIZE_FURTHER_INFORMATION);
188
189
        foreach ($this->getFurtherInformationElements() as $furtherInformationElement) {
190
            $this->setX(self::RIGHT_PART_X);
191
            $this->setContentElement($furtherInformationElement, true);
192
        }
193
    }
194
195
    private function addSeparatorContentIfNotPrintable(): void
196
    {
197
        if (!$this->isPrintable()) {
198
            $this->fpdf->SetLineWidth(0.1);
199
            $this->fpdf->Line(2 + $this->offsetX, 193 + $this->offsetY, 208 + $this->offsetX, 193 + $this->offsetY);
200
            $this->fpdf->Line(62 + $this->offsetX, 193 + $this->offsetY, 62 + $this->offsetX, 296 + $this->offsetY);
201
            $this->fpdf->SetFont(self::FONT, '', self::FONT_SIZE_FURTHER_INFORMATION);
202
            $this->setY(189.6);
203
            $this->fpdf->MultiCell(0, 0, utf8_decode(Translation::get('separate', $this->language)), self::BORDER, self::ALIGN_CENTER);
0 ignored issues
show
Bug introduced by
It seems like Sprain\SwissQrBill\Payme...rate', $this->language) can also be of type null; however, parameter $string of utf8_decode() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

203
            $this->fpdf->MultiCell(0, 0, utf8_decode(/** @scrutinizer ignore-type */ Translation::get('separate', $this->language)), self::BORDER, self::ALIGN_CENTER);
Loading history...
204
        }
205
    }
206
207
    private function setContentElement(OutputElementInterface $element, bool $isReceiptPart): void
208
    {
209
        if ($element instanceof Title) {
210
            $this->setTitleElement($element, $isReceiptPart);
211
        }
212
213
        if ($element instanceof Text) {
214
            $this->setTextElement($element, $isReceiptPart);
215
        }
216
217
        if ($element instanceof Placeholder) {
218
            $this->setPlaceholderElement($element);
219
        }
220
    }
221
222
    private function setTitleElement(Title $element, bool $isReceiptPart): void
223
    {
224
        $this->fpdf->SetFont(self::FONT, 'B', $isReceiptPart ? self::FONT_SIZE_TITLE_RECEIPT : self::FONT_SIZE_TITLE_PAYMENT_PART);
225
        $this->fpdf->MultiCell(0, 2.8, utf8_decode(
226
            Translation::get(str_replace("text.", "", $element->getTitle()), $this->language)
0 ignored issues
show
Bug introduced by
It seems like Sprain\SwissQrBill\Payme...le()), $this->language) can also be of type null; however, parameter $string of utf8_decode() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

226
            /** @scrutinizer ignore-type */ Translation::get(str_replace("text.", "", $element->getTitle()), $this->language)
Loading history...
227
        ));
228
        $this->fpdf->Ln($this->amountLS);
229
    }
230
231
    private function setTextElement(Text $element, bool $isReceiptPart): void
232
    {
233
        $this->fpdf->SetFont(self::FONT, '', $isReceiptPart ? self::FONT_SIZE_RECEIPT : self::FONT_SIZE_PAYMENT_PART);
234
        $this->fpdf->MultiCell(
235
            $isReceiptPart ? 54 : 0,
236
            $isReceiptPart ? 3.3 : 4,
237
            str_replace("text.", "", utf8_decode($element->getText())),
238
            self::BORDER,
239
            self::ALIGN_LEFT
240
        );
241
        $this->fpdf->Ln($isReceiptPart ? self::LINE_SPACING_RECEIPT : self::LINE_SPACING_PAYMENT_PART);
242
    }
243
244
    private function setPlaceholderElement(Placeholder $element): void
245
    {
246
        $type = $element->getType();
247
248
        switch ($type) {
249
            case Placeholder::PLACEHOLDER_TYPE_AMOUNT['type']:
250
                $y = $this->fpdf->GetY() + 1;
251
                $x = $this->fpdf->GetX() - 2;
252
                break;
253
            case Placeholder::PLACEHOLDER_TYPE_AMOUNT_RECEIPT['type']:
254
                $y = $this->fpdf->GetY() - 2;
255
                $x = $this->fpdf->GetX() + 11;
256
                break;
257
            case Placeholder::PLACEHOLDER_TYPE_PAYABLE_BY['type']:
258
            case Placeholder::PLACEHOLDER_TYPE_PAYABLE_BY_RECEIPT['type']:
259
            default:
260
                $y = $this->fpdf->GetY() + 1;
261
                $x = $this->fpdf->GetX() + 1;
262
        }
263
264
        $this->fpdf->Image(
265
            $element->getFile(Placeholder::FILE_TYPE_PNG),
266
            $x,
267
            $y,
268
            $element->getWidth(),
269
            $element->getHeight()
270
        );
271
    }
272
273
    private function setX(float $x): void
274
    {
275
        $this->fpdf->SetX($x + $this->offsetX);
276
    }
277
278
    private function setY(float $y): void
279
    {
280
        $this->fpdf->SetY($y + $this->offsetY);
281
    }
282
283
    private function SetXY(float $x, float $y): void
284
    {
285
        $this->fpdf->SetXY($x + $this->offsetX, $y + $this->offsetY);
286
    }
287
}
288