TcPdfOutput::printLine()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 4
dl 0
loc 3
rs 10
1
<?php declare(strict_types=1);
2
3
namespace Sprain\SwissQrBill\PaymentPart\Output\TcPdfOutput;
4
5
use Sprain\SwissQrBill\PaymentPart\Output\AbstractOutput;
6
use Sprain\SwissQrBill\PaymentPart\Output\Element\OutputElementInterface;
7
use Sprain\SwissQrBill\PaymentPart\Output\Element\Placeholder;
8
use Sprain\SwissQrBill\PaymentPart\Output\Element\Text;
9
use Sprain\SwissQrBill\PaymentPart\Output\Element\Title;
10
use Sprain\SwissQrBill\PaymentPart\Output\OutputInterface;
11
use Sprain\SwissQrBill\QrCode\QrCode;
12
use Sprain\SwissQrBill\PaymentPart\Translation\Translation;
13
use Sprain\SwissQrBill\QrBill;
14
use TCPDF;
15
16
final class TcPdfOutput extends AbstractOutput implements OutputInterface
17
{
18
    // TCPDF
19
    private const BORDER = 0;
20
    private const ALIGN_BELOW = 2;
21
    private const ALIGN_LEFT = 'L';
22
    private const ALIGN_RIGHT = 'R';
23
    private const ALIGN_CENTER = 'C';
24
    private const FONT = 'Helvetica';
25
26
    // Ratio
27
    private const LEFT_CELL_HEIGHT_RATIO_COMMON = 1.2;
28
    private const RIGHT_CELL_HEIGHT_RATIO_COMMON = 1.1;
29
    private const LEFT_CELL_HEIGHT_RATIO_CURRENCY_AMOUNT = 1.5;
30
    private const RIGHT_CELL_HEIGHT_RATIO_CURRENCY_AMOUNT = 1.5;
31
32
    // Location
33
    private const CURRENCY_AMOUNT_Y = 259;
34
    private const LEFT_PART_X = 4;
35
    private const RIGHT_PART_X = 66;
36
    private const RIGHT_PART_X_INFO = 117;
37
    private const TITLE_Y = 195;
38
39
    // Font
40
    private const FONT_SIZE_MAIN_TITLE = 11;
41
    private const FONT_SIZE_TITLE_RECEIPT = 6;
42
    private const FONT_SIZE_RECEIPT = 8;
43
    private const FONT_SIZE_TITLE_PAYMENT_PART = 8;
44
    private const FONT_SIZE_PAYMENT_PART = 10;
45
    private const FONT_SIZE_FURTHER_INFORMATION = 7;
46
47
    // Line spacing
48
    private const LINE_SPACING_RECEIPT = 3.5;
49
    private const LINE_SPACING_PAYMENT_PART = 4.8;
50
51
    private TCPDF $tcPdf;
52
    private float $offsetX;
53
    private float $offsetY;
54
55
    public function __construct(
56
        QrBill $qrBill,
57
        string $language,
58
        TCPDF $tcPdf,
59
        float $offsetX = 0,
60
        float $offsetY = 0
61
    ) {
62
        parent::__construct($qrBill, $language);
63
        $this->tcPdf = $tcPdf;
64
        $this->offsetX = $offsetX;
65
        $this->offsetY = $offsetY;
66
        $this->setQrCodeImageFormat(QrCode::FILE_FORMAT_SVG);
67
    }
68
69
    public function getPaymentPart(): void
70
    {
71
        $retainCellHeightRatio = $this->tcPdf->getCellHeightRatio();
72
        $retainAutoPageBreak = $this->tcPdf->getAutoPageBreak();
73
74
        $this->tcPdf->SetAutoPageBreak(false);
75
76
        $this->addSeparatorContentIfNotPrintable();
77
78
        $this->addInformationContentReceipt();
79
        $this->addCurrencyContentReceipt();
80
        $this->addAmountContentReceipt();
81
82
        $this->addSwissQrCodeImage();
83
        $this->addInformationContent();
84
        $this->addCurrencyContent();
85
        $this->addAmountContent();
86
        $this->addFurtherInformationContent();
87
88
        $this->tcPdf->setCellHeightRatio($retainCellHeightRatio);
89
        $this->tcPdf->SetAutoPageBreak($retainAutoPageBreak);
90
    }
91
92
    private function addSwissQrCodeImage(): void
93
    {
94
        $qrCode = $this->getQrCode();
95
96
        switch ($this->getQrCodeImageFormat()) {
97
            case QrCode::FILE_FORMAT_SVG:
98
                $method = "ImageSVG";
99
                break;
100
            case QrCode::FILE_FORMAT_PNG:
101
            default:
102
                $method = "Image";
103
        }
104
105
        $yPosQrCode = 209.5 + $this->offsetY;
106
        $xPosQrCode = self::RIGHT_PART_X + 1 + $this->offsetX;
107
108
        $img = $qrCode->getAsString($this->getQrCodeImageFormat());
109
        $this->tcPdf->$method("@".$img, $xPosQrCode, $yPosQrCode, 46, 46);
110
    }
111
112
    private function addInformationContentReceipt(): void
113
    {
114
        $x = self::LEFT_PART_X;
115
        $this->tcPdf->setCellHeightRatio(self::LEFT_CELL_HEIGHT_RATIO_COMMON);
116
117
        // Title
118
        $this->tcPdf->SetFont(self::FONT, 'B', self::FONT_SIZE_MAIN_TITLE);
119
        $this->setY(self::TITLE_Y);
120
        $this->setX($x);
121
        $this->printCell(Translation::get('receipt', $this->language), 0, 7);
122
123
        // Elements
124
        $this->setY(204);
125
        foreach ($this->getInformationElementsOfReceipt() as $informationElement) {
126
            $this->setX($x);
127
            $this->setContentElement($informationElement, true);
128
        }
129
130
        // Acceptance section
131
        $this->tcPdf->SetFont(self::FONT, 'B', 6);
132
        $this->setY(273);
133
        $this->setX($x);
134
        $this->printCell(Translation::get('acceptancePoint', $this->language), 54, 0, self::ALIGN_BELOW, self::ALIGN_RIGHT);
135
    }
136
137
    private function addInformationContent(): void
138
    {
139
        $x = self::RIGHT_PART_X_INFO;
140
        $this->tcPdf->setCellHeightRatio(self::RIGHT_CELL_HEIGHT_RATIO_COMMON);
141
142
        // Title
143
        $this->tcPdf->SetFont(self::FONT, 'B', self::FONT_SIZE_MAIN_TITLE);
144
        $this->setY(self::TITLE_Y);
145
        $this->setX(self::RIGHT_PART_X);
146
        $this->printCell(Translation::get('paymentPart', $this->language), 48, 7);
147
148
        // Elements
149
        $this->setY(197);
150
        foreach ($this->getInformationElements() as $informationElement) {
151
            $this->setX($x);
152
            $this->setContentElement($informationElement, false);
153
        }
154
    }
155
156
    private function addCurrencyContentReceipt(): void
157
    {
158
        $x = self::LEFT_PART_X;
159
        $this->tcPdf->setCellHeightRatio(self::LEFT_CELL_HEIGHT_RATIO_CURRENCY_AMOUNT);
160
        $this->setY(self::CURRENCY_AMOUNT_Y);
161
162
        foreach ($this->getCurrencyElements() as $currencyElement) {
163
            $this->setX($x);
164
            $this->setContentElement($currencyElement, true);
165
        }
166
    }
167
168
    private function addAmountContentReceipt(): void
169
    {
170
        $x = 16;
171
        $this->tcPdf->setCellHeightRatio(self::LEFT_CELL_HEIGHT_RATIO_CURRENCY_AMOUNT);
172
        $this->setY(self::CURRENCY_AMOUNT_Y);
173
174
        foreach ($this->getAmountElementsReceipt() as $amountElement) {
175
            $this->setX($x);
176
            $this->setContentElement($amountElement, true);
177
        }
178
    }
179
180
    private function addCurrencyContent(): void
181
    {
182
        $x = self::RIGHT_PART_X;
183
        $this->tcPdf->setCellHeightRatio(self::RIGHT_CELL_HEIGHT_RATIO_CURRENCY_AMOUNT);
184
        $this->setY(self::CURRENCY_AMOUNT_Y);
185
186
        foreach ($this->getCurrencyElements() as $currencyElement) {
187
            $this->setX($x);
188
            $this->setContentElement($currencyElement, false);
189
        }
190
    }
191
192
    private function addAmountContent(): void
193
    {
194
        $x = 80;
195
        $this->tcPdf->setCellHeightRatio(self::RIGHT_CELL_HEIGHT_RATIO_CURRENCY_AMOUNT);
196
        $this->setY(self::CURRENCY_AMOUNT_Y);
197
198
        foreach ($this->getAmountElements() as $amountElement) {
199
            $this->setX($x);
200
            $this->setContentElement($amountElement, false);
201
        }
202
    }
203
204
    private function addFurtherInformationContent(): void
205
    {
206
        $x = self::RIGHT_PART_X;
207
        $this->tcPdf->setCellHeightRatio(self::RIGHT_CELL_HEIGHT_RATIO_COMMON);
208
        $this->setY(286);
209
        $this->tcPdf->SetFont(self::FONT, '', self::FONT_SIZE_FURTHER_INFORMATION);
210
211
        foreach ($this->getFurtherInformationElements() as $furtherInformationElement) {
212
            $this->setX($x);
213
            $this->setContentElement($furtherInformationElement, true);
214
        }
215
    }
216
217
    private function addSeparatorContentIfNotPrintable(): void
218
    {
219
        if (!$this->isPrintable()) {
220
            $this->tcPdf->SetLineStyle(['width' => 0.1, 'color' => [0, 0, 0]]);
221
            $this->printLine(2, 193, 208, 193);
222
            $this->printLine(62, 193, 62, 296);
223
            $this->tcPdf->SetFont(self::FONT, '', self::FONT_SIZE_FURTHER_INFORMATION);
224
            $this->setY(188);
225
            $this->setX(5);
226
            $this->printCell(Translation::get('separate', $this->language), 200, 0, 0, self::ALIGN_CENTER);
227
        }
228
    }
229
230
    private function setContentElement(OutputElementInterface $element, bool $isReceiptPart): void
231
    {
232
        if ($element instanceof Title) {
233
            $this->setTitleElement($element, $isReceiptPart);
234
        }
235
236
        if ($element instanceof Text) {
237
            $this->setTextElement($element, $isReceiptPart);
238
        }
239
240
        if ($element instanceof Placeholder) {
241
            $this->setPlaceholderElement($element);
242
        }
243
    }
244
245
    private function setTitleElement(Title $element, bool $isReceiptPart): void
246
    {
247
        $this->tcPdf->SetFont(
248
            self::FONT,
249
            'B',
250
            $isReceiptPart ? self::FONT_SIZE_TITLE_RECEIPT : self::FONT_SIZE_TITLE_PAYMENT_PART
251
        );
252
        $this->printCell(
253
            Translation::get(str_replace("text.", "", $element->getTitle()), $this->language),
254
            0,
255
            0,
256
            self::ALIGN_BELOW
257
        );
258
    }
259
260
    private function setTextElement(Text $element, bool $isReceiptPart): void
261
    {
262
        $this->tcPdf->SetFont(
263
            self::FONT,
264
            '',
265
            $isReceiptPart ? self::FONT_SIZE_RECEIPT : self::FONT_SIZE_PAYMENT_PART
266
        );
267
268
        $this->printMultiCell(
269
            str_replace("text.", "", $element->getText()),
270
            $isReceiptPart ? 54 : 0,
271
            0,
272
            self::ALIGN_BELOW,
273
            self::ALIGN_LEFT
274
        );
275
        $this->tcPdf->Ln($isReceiptPart ? self::LINE_SPACING_RECEIPT : self::LINE_SPACING_PAYMENT_PART);
276
    }
277
278
    private function setPlaceholderElement(Placeholder $element): void
279
    {
280
        $type = $element->getType();
281
282
        switch ($type) {
283
            case Placeholder::PLACEHOLDER_TYPE_AMOUNT['type']:
284
                $y = $this->tcPdf->GetY() + 1;
285
                $x = $this->tcPdf->GetX() - 2;
286
                break;
287
            case Placeholder::PLACEHOLDER_TYPE_AMOUNT_RECEIPT['type']:
288
                $y = $this->tcPdf->GetY() - 2;
289
                $x = $this->tcPdf->GetX() + 11;
290
                break;
291
            case Placeholder::PLACEHOLDER_TYPE_PAYABLE_BY['type']:
292
            case Placeholder::PLACEHOLDER_TYPE_PAYABLE_BY_RECEIPT['type']:
293
            default:
294
                $y = $this->tcPdf->GetY() + 1;
295
                $x = $this->tcPdf->GetX() + 1;
296
        }
297
298
        $this->tcPdf->ImageSVG(
299
            $element->getFile(),
300
            $x,
301
            $y,
302
            $element->getWidth(),
303
            $element->getHeight()
304
        );
305
    }
306
307
    private function setX(int $x): void
308
    {
309
        $this->tcPdf->SetX($x+$this->offsetX);
310
    }
311
312
    private function setY(int $y): void
313
    {
314
        $this->tcPdf->SetY($y+$this->offsetY);
315
    }
316
317
    private function printCell(
318
        string $text,
319
        int $w = 0,
320
        int $h = 0,
321
        int $nextLineAlign = 0,
322
        string $textAlign = self::ALIGN_LEFT
323
    ): void {
324
        $this->tcPdf->Cell($w, $h, $text, self::BORDER, $nextLineAlign, $textAlign);
325
    }
326
327
    private function printMultiCell(
328
        string $text,
329
        int $w = 0,
330
        int $h = 0,
331
        int $nextLineAlign = 0,
332
        string $textAlign = self::ALIGN_LEFT
333
    ): void {
334
        $this->tcPdf->MultiCell($w, $h, $text, self::BORDER, $textAlign, false, $nextLineAlign);
335
    }
336
337
    private function printLine(int $x1, int $y1, int $x2, int $y2): void
338
    {
339
        $this->tcPdf->Line($x1+$this->offsetX, $y1+$this->offsetY, $x2+$this->offsetX, $y2+$this->offsetY);
340
    }
341
}
342