Passed
Push — master ( a07d8a...66d505 )
by Manuel
04:50
created

TcPdfOutput::addAmountContent()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

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