Passed
Pull Request — master (#53)
by Manuel
02:54
created

TcPdfOutput::addInformationContentReceipt()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 23
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 14
c 1
b 0
f 0
nc 2
nop 0
dl 0
loc 23
rs 9.7998
1
<?php
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\Exception\UnsupportedFileExtensionException;
12
use Sprain\SwissQrBill\QrCode\QrCode;
13
use Sprain\SwissQrBill\PaymentPart\Translation\Translation;
14
use Sprain\SwissQrBill\QrBill;
15
use TCPDF;
16
17
final class TcPdfOutput extends AbstractOutput implements OutputInterface
18
{
19
    // TCPDF constants
20
    private const TCPDF_BORDER = 0;
21
    private const TCPDF_ALIGN_BELOW = 2;
22
    private const TCPDF_ALIGN_LEFT = 'L';
23
    private const TCPDF_ALIGN_RIGHT = 'R';
24
    private const TCPDF_FONT = 'Helvetica';
25
26
    // Ratio constants
27
    private const TCPDF_LEFT_CELL_HEIGHT_RATIO_COMMON = 1.2;
28
    private const TCPDF_RIGHT_CELL_HEIGHT_RATIO_COMMON = 1.1;
29
    private const TCPDF_LEFT_CELL_HEIGHT_RATIO_CURRENCY_AMOUNT = 1.5;
30
    private const TCPDF_RIGHT_CELL_HEIGHT_RATIO_CURRENCY_AMOUNT = 1.5;
31
32
    // Location constants
33
    private const TCPDF_CURRENCY_AMOUNT_Y = 259;
34
    private const TCPDF_LEFT_PART_X = 4;
35
    private const TCPDF_RIGHT_PART_X = 66;
36
    private const TCPDF_RIGHT_PAR_X_INFO = 117;
37
    private const TCPDF_TITLE_Y = 195;
38
39
    // Line spacing constants
40
    private const TCPDF_9PT = 3.5;
41
    private const TCPDF_11PT = 4.8;
42
43
    /** @var  string */
44
    protected $language;
45
46
    /** @var QrBill */
47
    protected $qrBill;
48
49
    /* @var TCPDF $tcPdf */
50
    private $tcPdf;
51
52
    /* @var int $offsetX */
53
    private $offsetX;
54
55
    /* @var int $offsetY */
56
    private $offsetY;
57
58
    public function __construct(
59
        QrBill $qrBill,
60
        string $language,
61
        TCPDF $tcPdf,
62
        int $offsetX = 0,
63
        int $offsetY = 0
64
    ) {
65
        parent::__construct($qrBill, $language);
66
        $this->tcPdf = $tcPdf;
67
        $this->offsetX = $offsetX;
68
        $this->offsetY = $offsetY;
69
        $this->setQrCodeImageFormat(QrCode::FILE_FORMAT_SVG);
70
    }
71
72
    public function getPaymentPart(): void
73
    {
74
        $this->tcPdf->SetAutoPageBreak(false);
75
76
        $this->addPrintableContent();
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
89
    private function addSwissQrCodeImage(): void
90
    {
91
        $qrCode = $this->getQrCode();
92
93
        switch ($this->getQrCodeImageFormat()) {
94
            case QrCode::FILE_FORMAT_SVG:
95
                $format = QrCode::FILE_FORMAT_SVG;
96
                $method = "ImageSVG";
97
                break;
98
            case QrCode::FILE_FORMAT_PNG:
99
            default:
100
                $format = QrCode::FILE_FORMAT_PNG;
101
                $method = "Image";
102
        }
103
104
        $yPosQrCode = 209.5 + $this->offsetY;
105
        $xPosQrCode = self::TCPDF_RIGHT_PART_X + 1 + $this->offsetX;
106
107
        $qrCode->setWriterByExtension($format);
108
        $img = base64_decode(preg_replace('#^data:image/[^;]+;base64,#', '', $qrCode->writeDataUri()));
109
        $this->tcPdf->$method("@".$img, $xPosQrCode, $yPosQrCode, 46, 46);
110
    }
111
112
    private function addInformationContentReceipt(): void
113
    {
114
        $x = self::TCPDF_LEFT_PART_X;
115
        $this->tcPdf->setCellHeightRatio(self::TCPDF_LEFT_CELL_HEIGHT_RATIO_COMMON);
116
117
        // Title
118
        $this->tcPdf->SetFont(self::TCPDF_FONT, 'B', 11);
119
        $this->SetY(self::TCPDF_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::TCPDF_FONT, 'B', 6);
132
        $this->SetY(273);
133
        $this->SetX($x);
134
        $this->printCell(Translation::get('acceptancePoint', $this->language), 54, 0, self::TCPDF_ALIGN_BELOW, self::TCPDF_ALIGN_RIGHT);
135
    }
136
137
    private function addInformationContent(): void
138
    {
139
        $x = self::TCPDF_RIGHT_PAR_X_INFO;
140
        $this->tcPdf->setCellHeightRatio(self::TCPDF_RIGHT_CELL_HEIGHT_RATIO_COMMON);
141
142
        // Title
143
        $this->tcPdf->SetFont(self::TCPDF_FONT, 'B', 11);
144
        $this->SetY(self::TCPDF_TITLE_Y);
145
        $this->SetX(self::TCPDF_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::TCPDF_LEFT_PART_X;
159
        $this->tcPdf->setCellHeightRatio(self::TCPDF_LEFT_CELL_HEIGHT_RATIO_CURRENCY_AMOUNT);
160
        $this->SetY(self::TCPDF_CURRENCY_AMOUNT_Y);
161
        foreach ($this->getCurrencyElements() as $currencyElement) {
162
            $this->SetX($x);
163
            $this->setContentElement($currencyElement, true);
164
        }
165
    }
166
167
    private function addAmountContentReceipt(): void
168
    {
169
        $x = 16;
170
        $this->tcPdf->setCellHeightRatio(self::TCPDF_LEFT_CELL_HEIGHT_RATIO_CURRENCY_AMOUNT);
171
        $this->SetY(self::TCPDF_CURRENCY_AMOUNT_Y);
172
        foreach ($this->getAmountElementsReceipt() as $amountElement) {
173
            $this->SetX($x);
174
            $this->setContentElement($amountElement, true);
175
        }
176
    }
177
178
    private function addCurrencyContent(): void
179
    {
180
        $x = self::TCPDF_RIGHT_PART_X;
181
        $this->tcPdf->setCellHeightRatio(self::TCPDF_RIGHT_CELL_HEIGHT_RATIO_CURRENCY_AMOUNT);
182
        $this->SetY(self::TCPDF_CURRENCY_AMOUNT_Y);
183
        foreach ($this->getCurrencyElements() as $currencyElement) {
184
            $this->SetX($x);
185
            $this->setContentElement($currencyElement, false);
186
        }
187
    }
188
189
    private function addAmountContent(): void
190
    {
191
        $x = 80;
192
        $this->tcPdf->setCellHeightRatio(self::TCPDF_RIGHT_CELL_HEIGHT_RATIO_CURRENCY_AMOUNT);
193
        $this->SetY(self::TCPDF_CURRENCY_AMOUNT_Y);
194
        foreach ($this->getAmountElements() as $amountElement) {
195
            $this->SetX($x);
196
            $this->setContentElement($amountElement, false);
197
        }
198
    }
199
200
    private function addFurtherInformationContent(): void
201
    {
202
        $x = self::TCPDF_RIGHT_PART_X;
203
        $this->tcPdf->setCellHeightRatio(self::TCPDF_RIGHT_CELL_HEIGHT_RATIO_COMMON);
204
        $this->SetY(286);
205
        $this->tcPdf->SetFont(self::TCPDF_FONT, '', 7);
206
        foreach ($this->getFurtherInformationElements() as $furtherInformationElement) {
207
            $this->SetX($x);
208
            $this->setContentElement($furtherInformationElement, true);
209
        }
210
    }
211
212
    private function addPrintableContent(): void
213
    {
214
        if ($this->isPrintable()) {
215
            $this->tcPdf->SetLineStyle(array('width' => 0.1, 'dash' => 4, 'color' => array(0, 0, 0)));
216
            $this->printLine(2, 193, 208, 193);
217
            $this->printLine(62, 193, 62, 296);
218
            $this->tcPdf->SetFont(self::TCPDF_FONT, '', 7);
219
            $this->SetY(188);
220
            $this->SetX(self::TCPDF_RIGHT_PART_X);
221
            $this->printCell(Translation::get('separate', $this->language), 0, 0);
222
        }
223
    }
224
225
    private function setContentElement(OutputElementInterface $element, bool $isReceiptPart): void
226
    {
227
        if ($element instanceof Title) {
228
            $this->tcPdf->SetFont(self::TCPDF_FONT, 'B', $isReceiptPart ? 6 : 8);
229
            $this->printCell(Translation::get(str_replace("text.", "", $element->getTitle()), $this->language), 0, 0, self::TCPDF_ALIGN_BELOW);
230
        }
231
232
        if ($element instanceof Text) {
233
            $this->tcPdf->SetFont(self::TCPDF_FONT, '', $isReceiptPart ? 8 : 10);
234
            $this->printMultiCell(
235
                str_replace("text.", "", $element->getText()),
236
                0,
237
                0,
238
                self::TCPDF_ALIGN_BELOW,
239
                self::TCPDF_ALIGN_LEFT
240
            );
241
            $this->tcPdf->Ln($isReceiptPart ? self::TCPDF_9PT : self::TCPDF_11PT);
242
        }
243
244
        if ($element instanceof Placeholder) {
245
            $this->tcPdf->SetLineStyle(array('width' => 0.3, 'dash' => 0, 'color' => array(0, 0, 0)));
246
247
            $lineLength = 3;
248
249
            // Not implemented
250
            if ($isReceiptPart) {
251
                $boxLeftPos = 27;
252
                $boxHeightPos = self::TCPDF_CURRENCY_AMOUNT_Y+2;
253
                $boxHeight = 10;
254
                $boxWidth = 30;
255
                $boxRightPos = $boxLeftPos+$boxWidth;
256
            } else {
257
                $boxLeftPos = 77;
258
                $boxHeightPos = 265;
259
                $boxHeight = 15;
260
                $boxWidth = 40;
261
                $boxRightPos = $boxLeftPos+$boxWidth;
262
            }
263
264
            // Top left
265
            $tlx = $boxLeftPos;
266
            $tly = $boxHeightPos;
267
            $this->printLine($tlx, $tly, $tlx+$lineLength, $tly);
268
            $this->printLine($tlx, $tly, $tlx, $tly+$lineLength);
269
270
            // Top right
271
            $trx = $boxRightPos;
272
            $try = $boxHeightPos;
273
            $this->printLine($trx, $try, $trx-$lineLength, $try);
274
            $this->printLine($trx, $try, $trx, $try+$lineLength);
275
276
            // Bottom left
277
            $blx = $boxLeftPos;
278
            $bly = $boxHeightPos+$boxHeight;
279
            $this->printLine($blx, $bly, $blx+$lineLength, $bly);
280
            $this->printLine($blx, $bly, $blx, $bly-$lineLength);
281
282
            // Bottom right
283
            $brx = $boxRightPos;
284
            $bry = $boxHeightPos+$boxHeight;
285
            $this->printLine($brx, $bry, $brx-$lineLength, $bry);
286
            $this->printLine($brx, $bry, $brx, $bry-$lineLength);
287
        }
288
    }
289
290
    private function setX(int $x) : void
291
    {
292
        $this->tcPdf->SetX($x+$this->offsetX);
293
    }
294
295
    private function setY(int $y) : void
296
    {
297
        $this->tcPdf->SetY($y+$this->offsetY);
298
    }
299
300
    private function printCell(
301
        string $text,
302
        int $w = 0,
303
        int $h = 0,
304
        int $nextLineAlign = 0,
305
        string $textAlign = self::TCPDF_ALIGN_LEFT
306
    ) : void {
307
        $this->tcPdf->Cell($w, $h, $text, self::TCPDF_BORDER, $nextLineAlign, $textAlign);
308
    }
309
310
    private function printMultiCell(
311
        string $text,
312
        int $w = 0,
313
        int $h = 0,
314
        int $nextLineAlign = 0,
315
        string $textAlign = self::TCPDF_ALIGN_LEFT
316
    ) : void {
317
        $this->tcPdf->MultiCell($w, $h, $text, self::TCPDF_BORDER, $textAlign, false, $nextLineAlign);
318
    }
319
320
    private function printLine(int $x1, int $y1, int $x2, int $y2) : void
321
    {
322
        $this->tcPdf->Line($x1+$this->offsetX, $y1+$this->offsetY, $x2+$this->offsetX, $y2+$this->offsetY);
323
    }
324
}
325