Passed
Pull Request — master (#136)
by
unknown
03:38
created

FpdfOutput::setX()   A

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
26
    // Location
27
    private const CURRENCY_AMOUNT_Y = 259.3;
28
    private const AMOUNT_LINE_SPACING = 1.2;
29
    private const AMOUNT_LINE_SPACING_RCPT = 0.6;
30
    private const LEFT_PART_X = 4;
31
    private const RIGHT_PART_X = 66;
32
    private const RIGHT_PART_X_INFO = 117;
33
    private const TITLE_Y = 195.2;
34
35
    // Font size
36
    private const FONT_SIZE_MAIN_TITLE = 11;
37
    private const FONT_SIZE_TITLE_RECEIPT = 6;
38
    private const FONT_SIZE_RECEIPT = 8;
39
    private const FONT_SIZE_TITLE_PAYMENT_PART = 8;
40
    private const FONT_SIZE_PAYMENT_PART = 10;
41
    private const FONT_SIZE_FURTHER_INFORMATION = 7;
42
43
    // Line spacing
44
    private const LINE_SPACING_RECEIPT = 3.4;
45
    private const LINE_SPACING_PAYMENT_PART = 4.8;
46
    private float $amountLS = 0;
47
48
    private Fpdf $fpdf;
49
    private float $offsetX;
50
    private float $offsetY;
51
    private string $font;
52
53
    public function __construct(
54
        QrBill $qrBill,
55
        string $language,
56
        Fpdf $fpdf,
57
        float $offsetX = 0,
58
        float $offsetY = 0,
59
        string $font = 'Helvetica'
60
    )
61
    {
62
        parent::__construct($qrBill, $language);
63
        $this->fpdf = $fpdf;
64
        $this->offsetX = $offsetX;
65
        $this->offsetY = $offsetY;
66
        $this->font = $font;
67
        $this->setQrCodeImageFormat(QrCode::FILE_FORMAT_PNG);
68
    }
69
70
    public function getPaymentPart()
71
    {
72
        $this->fpdf->SetAutoPageBreak(false);
73
74
        $this->addSeparatorContentIfNotPrintable();
75
76
        $this->addInformationContentReceipt();
77
        $this->addCurrencyContentReceipt();
78
        $this->addAmountContentReceipt();
79
80
        $this->addSwissQrCodeImage();
81
        $this->addInformationContent();
82
        $this->addCurrencyContent();
83
        $this->addAmountContent();
84
        $this->addFurtherInformationContent();
85
    }
86
87
    public function setQrCodeImageFormat(string $fileExtension): AbstractOutput
88
    {
89
        if ($fileExtension === 'svg') {
90
            throw new InvalidFpdfImageFormat('SVG images are not allowed by FPDF.');
91
        }
92
93
        $this->qrCodeImageFormat = $fileExtension;
94
95
        return $this;
96
    }
97
98
    private function addSwissQrCodeImage(): void
99
    {
100
        $qrCode = $this->getQrCode();
101
        $qrCode->setWriterByExtension(
102
            $this->getQrCodeImageFormat()
103
        );
104
105
        $yPosQrCode = 209.5 + $this->offsetY;
106
        $xPosQrCode = 67 + $this->offsetX;
107
108
        $this->fpdf->Image($qrCode->writeDataUri(), $xPosQrCode, $yPosQrCode, 46, 46, 'png');
109
    }
110
111
    private function addInformationContentReceipt(): void
112
    {
113
        // Title
114
        $this->fpdf->SetFont($this->font, 'B', self::FONT_SIZE_MAIN_TITLE);
115
        $this->SetXY(self::LEFT_PART_X, self::TITLE_Y);
116
        $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

116
        $this->fpdf->MultiCell(0, 7, utf8_decode(/** @scrutinizer ignore-type */ Translation::get('receipt', $this->language)));
Loading history...
117
118
        // Elements
119
        $this->SetY(204);
120
        foreach ($this->getInformationElementsOfReceipt() as $receiptInformationElement) {
121
            $this->SetX(self::LEFT_PART_X);
122
            $this->setContentElement($receiptInformationElement, true);
123
        }
124
125
        // Acceptance section
126
        $this->fpdf->SetFont($this->font, 'B', self::FONT_SIZE_TITLE_RECEIPT);
127
        $this->SetXY(self::LEFT_PART_X, 274.3);
128
        $this->fpdf->Cell(54, 0, utf8_decode(Translation::get('acceptancePoint', $this->language)), self::BORDER, '', self::ALIGN_RIGHT);
129
    }
130
131
    private function addInformationContent(): void
132
    {
133
        // Title
134
        $this->fpdf->SetFont($this->font, 'B', self::FONT_SIZE_MAIN_TITLE);
135
        $this->SetXY(self::RIGHT_PART_X, 195.2);
136
        $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

136
        $this->fpdf->MultiCell(48, 7, utf8_decode(/** @scrutinizer ignore-type */ Translation::get('paymentPart', $this->language)));
Loading history...
137
138
        // Elements
139
        $this->SetY(197.3);
140
        foreach ($this->getInformationElements() as $informationElement) {
141
            $this->SetX(self::RIGHT_PART_X_INFO);
142
            $this->setContentElement($informationElement, false);
143
        }
144
    }
145
146
    private function addCurrencyContentReceipt(): void
147
    {
148
        $this->SetY(self::CURRENCY_AMOUNT_Y);
149
        foreach ($this->getCurrencyElements() as $receiptCurrencyElement) {
150
            $this->amountLS = self::AMOUNT_LINE_SPACING_RCPT;
151
            $this->SetX(self::LEFT_PART_X);
152
            $this->setContentElement($receiptCurrencyElement, true);
153
            $this->amountLS = 0;
154
        }
155
    }
156
157
    private function addAmountContentReceipt(): void
158
    {
159
        $this->SetY(self::CURRENCY_AMOUNT_Y);
160
        foreach ($this->getAmountElementsReceipt() as $receiptAmountElement) {
161
            $this->amountLS = self::AMOUNT_LINE_SPACING_RCPT;
162
            $this->SetX(16);
163
            $this->setContentElement($receiptAmountElement, true);
164
            $this->amountLS = 0;
165
        }
166
    }
167
168
    private function addCurrencyContent(): void
169
    {
170
        $this->SetY(self::CURRENCY_AMOUNT_Y);
171
        foreach ($this->getCurrencyElements() as $currencyElement) {
172
            $this->amountLS = self::AMOUNT_LINE_SPACING;
173
            $this->SetX(self::RIGHT_PART_X);
174
            $this->setContentElement($currencyElement, false);
175
            $this->amountLS = 0;
176
        }
177
    }
178
179
    private function addAmountContent(): void
180
    {
181
        $this->SetY(self::CURRENCY_AMOUNT_Y);
182
        foreach ($this->getAmountElements() as $amountElement) {
183
            $this->amountLS = self::AMOUNT_LINE_SPACING;
184
            $this->SetX(80);
185
            $this->setContentElement($amountElement, false);
186
            $this->amountLS = 0;
187
        }
188
    }
189
190
    private function addFurtherInformationContent(): void
191
    {
192
        $this->SetXY(self::RIGHT_PART_X, 286);
193
        $this->fpdf->SetFont($this->font, '', self::FONT_SIZE_FURTHER_INFORMATION);
194
195
        foreach ($this->getFurtherInformationElements() as $furtherInformationElement) {
196
            $this->SetX(self::RIGHT_PART_X);
197
            $this->setContentElement($furtherInformationElement, true);
198
        }
199
    }
200
201
    private function addSeparatorContentIfNotPrintable(): void
202
    {
203
        if (!$this->isPrintable()) {
204
            $this->fpdf->SetLineWidth(0.1);
205
            $this->fpdf->Line(2 + $this->offsetX, 193 + $this->offsetY, 208 + $this->offsetX, 193 + $this->offsetY);
206
            $this->fpdf->Line(62 + $this->offsetX, 193 + $this->offsetY, 62 + $this->offsetX, 296 + $this->offsetY);
207
            $this->fpdf->SetFont($this->font, '', self::FONT_SIZE_FURTHER_INFORMATION);
208
            $this->SetY(189.6);
209
            $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

209
            $this->fpdf->MultiCell(0, 0, utf8_decode(/** @scrutinizer ignore-type */ Translation::get('separate', $this->language)), self::BORDER, self::ALIGN_CENTER);
Loading history...
210
        }
211
    }
212
213
    private function setContentElement(OutputElementInterface $element, bool $isReceiptPart): void
214
    {
215
        if ($element instanceof Title) {
216
            $this->setTitleElement($element, $isReceiptPart);
217
        }
218
219
        if ($element instanceof Text) {
220
            $this->setTextElement($element, $isReceiptPart);
221
        }
222
223
        if ($element instanceof Placeholder) {
224
            $this->setPlaceholderElement($element);
225
        }
226
    }
227
228
    private function setTitleElement(Title $element, bool $isReceiptPart): void
229
    {
230
        $this->fpdf->SetFont($this->font, 'B', $isReceiptPart ? self::FONT_SIZE_TITLE_RECEIPT : self::FONT_SIZE_TITLE_PAYMENT_PART);
231
        $this->fpdf->MultiCell(0, 2.8, utf8_decode(
232
            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

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