Passed
Pull Request — master (#172)
by
unknown
04:01
created

PhpWordOutput::getPaymentPart()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 17
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 12
c 2
b 0
f 0
dl 0
loc 17
rs 9.8666
cc 1
nc 1
nop 0
1
<?php
2
3
namespace Sprain\SwissQrBill\PaymentPart\Output\PhpWordOutput;
4
5
use PhpOffice\PhpWord\Element\Cell;
6
use PhpOffice\PhpWord\Element\TextRun;
7
use PhpOffice\PhpWord\PhpWord;
8
use PhpOffice\PhpWord\Style\Image;
9
use Sprain\SwissQrBill\Exception\InvalidPhpWordImageFormat;
10
use Sprain\SwissQrBill\PaymentPart\Output\AbstractOutput;
11
use Sprain\SwissQrBill\PaymentPart\Output\Element\OutputElementInterface;
12
use Sprain\SwissQrBill\PaymentPart\Output\Element\Placeholder;
13
use Sprain\SwissQrBill\PaymentPart\Output\Element\Text;
14
use Sprain\SwissQrBill\PaymentPart\Output\Element\Title;
15
use Sprain\SwissQrBill\PaymentPart\Output\OutputInterface;
16
use Sprain\SwissQrBill\PaymentPart\Output\PhpWordOutput\Table\Bill;
17
use Sprain\SwissQrBill\PaymentPart\Output\PhpWordOutput\Table\Style;
18
use Sprain\SwissQrBill\PaymentPart\Translation\Translation;
19
use Sprain\SwissQrBill\QrBill;
20
use Sprain\SwissQrBill\QrCode\QrCode;
21
22
final class PhpWordOutput extends AbstractOutput implements OutputInterface
23
{
24
    private PhpWord $phpWord;
25
    private Bill $billTable;
26
27
    public function __construct(
28
        QrBill $qrBill,
29
        string $language,
30
        PhpWord $phpWord,
31
    ) {
32
        parent::__construct($qrBill, $language);
33
        $this->phpWord = $phpWord;
34
        FontStyle::defineFontStyles($this->phpWord);
35
    }
36
37
    public function getPaymentPart()
38
    {
39
        $sections = $this->phpWord->getSections();
40
        $lastAddedSection = end($sections);
41
        $this->billTable = new Bill($lastAddedSection, $this->isPrintable());
42
43
        $this->addSeparatorContentIfNotPrintable();
44
45
        $this->addInformationContentReceipt();
46
        $this->addCurrencyContentReceipt();
47
        $this->addAmountContentReceipt();
48
49
        $this->addSwissQrCodeImage();
50
        $this->addInformationContent();
51
        $this->addCurrencyContent();
52
        $this->addAmountContent();
53
        $this->addFurtherInformationContent();
54
    }
55
56
    public function setQrCodeImageFormat(string $fileExtension) : AbstractOutput
57
    {
58
        if ($fileExtension === QrCode::FILE_FORMAT_SVG) {
59
            throw new InvalidPhpWordImageFormat('SVG images are not allowed by PHPWord.');
60
        }
61
62
        $this->qrCodeImageFormat = $fileExtension;
63
64
        return $this;
65
    }
66
67
    private function addTitleElement(Cell $cell, Title $element, bool $isReceiptPart) : void
68
    {
69
        $text = Translation::get(str_replace("text.", "", $element->getTitle()), $this->language);
70
        $fStyle = $isReceiptPart ? FontStyle::FONT_STYLE_HEADING_RECEIPT : FontStyle::FONT_STYLE_HEADING_PAYMENT_PART;
71
        $cell->addText($text, $fStyle, $fStyle);
72
    }
73
74
    private function addTextElement(Cell $cell, Text $element) : void
75
    {
76
        $fStyle = FontStyle::getCurrentText();
77
        $this->addElementTextRun($element->getText(), $cell->addTextRun($fStyle), $fStyle);
78
    }
79
80
    private function addPlaceholderElement(Cell $cell, Placeholder $element) : void
81
    {
82
        $type = $element->getType();
83
84
        switch ($type) {
85
            case Placeholder::PLACEHOLDER_TYPE_AMOUNT['type']:
86
                $cell->addImage($element->getFile(Placeholder::FILE_TYPE_PNG), [
87
                        'width' => PhpWordHelper::mmToPoint($element->getWidth()),
88
                        'height' => PhpWordHelper::mmToPoint($element->getHeight()),
89
                        'positioning' => Image::POSITION_ABSOLUTE,
90
                        'posHorizontal' => Image::POSITION_ABSOLUTE,
91
                        'posVertical' => Image::POSITION_ABSOLUTE,
92
                        'marginLeft' => PhpWordHelper::mmToPoint(-4.5),
93
                        'marginTop' => PhpWordHelper::mmToPoint(0.8),
94
                ]);
95
                break;
96
            case Placeholder::PLACEHOLDER_TYPE_AMOUNT_RECEIPT['type']:
97
                $cell->addImage($element->getFile(Placeholder::FILE_TYPE_PNG), [
98
                        'width' => PhpWordHelper::mmToPoint($element->getWidth()),
99
                        'height' => PhpWordHelper::mmToPoint($element->getHeight()),
100
                        'positioning' => Image::POSITION_ABSOLUTE,
101
                        'posHorizontal' => Image::POSITION_ABSOLUTE,
102
                        'posVertical' => Image::POSITION_ABSOLUTE,
103
                        'marginLeft' => PhpWordHelper::mmToPoint(9.1),
104
                        'marginTop' => PhpWordHelper::mmToPoint(-2.5),
105
                ]);
106
                break;
107
            case Placeholder::PLACEHOLDER_TYPE_PAYABLE_BY['type']:
108
            case Placeholder::PLACEHOLDER_TYPE_PAYABLE_BY_RECEIPT['type']:
109
            default:
110
                $cell->addImage($element->getFile(Placeholder::FILE_TYPE_PNG), [
111
                        'width' => PhpWordHelper::mmToPoint($element->getWidth()),
112
                        'height' => PhpWordHelper::mmToPoint($element->getHeight()),
113
                        'wrappingStyle' => Image::WRAP_INFRONT,
114
                        'positioning' => Image::POS_RELATIVE,
115
                        'posHorizontalRel' => Image::POS_RELTO_MARGIN,
116
                        'posVerticalRel' => Image::POS_RELTO_LINE,
117
                ]);
118
        }
119
    }
120
121
    private function addSeparatorContentIfNotPrintable() : void
122
    {
123
        if (!$this->isPrintable()) {
124
            $text = Translation::get('separate', $this->language);
125
            $fStyle = FontStyle::FONT_STYLE_SEPARATOR;
126
            $this->billTable->getSeparate()->addText($text, $fStyle, $fStyle);
127
        }
128
    }
129
130
    private function addInformationContentReceipt() : void
131
    {
132
        $this->addReceiptTitle();
133
134
        $cell = $this->billTable->getReceipt()->getInformationSection();
135
        $informationElements = $this->getInformationElementsOfReceipt();
136
        $lastKey = array_key_last($informationElements);
137
        FontStyle::setCurrentText(FontStyle::FONT_STYLE_VALUE_RECEIPT);
138
        foreach ($informationElements as $key => $informationElement) {
139
            $this->addContentElement($cell, $informationElement, true);
140
            if ($informationElement instanceof Text && $key !== $lastKey) {
141
                $cell->addText('', FontStyle::FONT_STYLE_VALUE_RECEIPT, FontStyle::FONT_STYLE_VALUE_RECEIPT);
142
            }
143
        }
144
145
        $this->addReceiptAcceptancePoint();
146
    }
147
148
    private function addContentElement(Cell $cell, OutputElementInterface $element, bool $isReceiptPart = false) : void
149
    {
150
        if ($element instanceof Title) {
151
            $this->addTitleElement($cell, $element, $isReceiptPart);
152
        }
153
154
        if ($element instanceof Text) {
155
            $this->addTextElement($cell, $element);
156
        }
157
158
        if ($element instanceof Placeholder) {
159
            $this->addPlaceholderElement($cell, $element);
160
        }
161
    }
162
163
    private function addCurrencyContentReceipt() : void
164
    {
165
        $cell = $this->billTable->getReceipt()->getAmountSection()->getCurrencyCell();
166
        FontStyle::setCurrentText(FontStyle::FONT_STYLE_AMOUNT_RECEIPT);
167
        foreach ($this->getCurrencyElements() as $informationElement) {
168
            $this->addContentElement($cell, $informationElement, true);
169
        }
170
    }
171
172
    private function addAmountContentReceipt() : void
173
    {
174
        $cell = $this->billTable->getReceipt()->getAmountSection()->getAmountCell();
175
        FontStyle::setCurrentText(FontStyle::FONT_STYLE_AMOUNT_RECEIPT);
176
        foreach ($this->getAmountElementsReceipt() as $informationElement) {
177
            $this->addContentElement($cell, $informationElement, true);
178
        }
179
    }
180
181
    private function addReceiptTitle() : void
182
    {
183
        $text = Translation::get('receipt', $this->language);
184
        $this->billTable->getReceipt()->getTitleSection()->addText($text, FontStyle::FONT_STYLE_TITLE);
185
    }
186
187
    private function addReceiptAcceptancePoint() : void
188
    {
189
        $text = Translation::get('acceptancePoint', $this->language);
190
        $this->billTable->getReceipt()->getAcceptancePointSection()->addText(
191
            $text,
192
            FontStyle::FONT_STYLE_ACCEPTANCE_POINT,
193
            FontStyle::FONT_STYLE_ACCEPTANCE_POINT
194
        );
195
    }
196
197
    private function addSwissQrCodeImage() : void
198
    {
199
        $qrCode = $this->getQrCode()->writeDataUri();
200
        $img = base64_decode(preg_replace('#^data:image/[^;]+;base64,#', '', $qrCode));
201
        $this->billTable->getPayment()->getQrCodeSection()->addImage($img, [
202
                'width' => PhpWordHelper::mmToPoint(Style::QR_CODE_SIZE),
203
                'height' => PhpWordHelper::mmToPoint(Style::QR_CODE_SIZE),
204
        ]);
205
    }
206
207
    private function addInformationContent() : void
208
    {
209
        $text = Translation::get('paymentPart', $this->language);
210
        $this->billTable->getPayment()->getTitleSection()->addText($text, FontStyle::FONT_STYLE_TITLE);
211
        $cell = $this->billTable->getPayment()->getInformationSection();
212
        $informationElements = $this->getInformationElements();
213
        $lastKey = array_key_last($informationElements);
214
        FontStyle::setCurrentText(FontStyle::FONT_STYLE_VALUE_PAYMENT_PART);
215
        foreach ($this->getInformationElements() as $key => $informationElement) {
216
            $this->addContentElement($cell, $informationElement);
217
            if ($informationElement instanceof Text && $key !== $lastKey) {
218
                $cell->addText('', FontStyle::FONT_STYLE_VALUE_PAYMENT_PART, FontStyle::FONT_STYLE_VALUE_PAYMENT_PART);
219
            }
220
        }
221
    }
222
223
    private function addCurrencyContent() : void
224
    {
225
        $cell = $this->billTable->getPayment()->getAmountSection()->getCurrencyCell();
226
        FontStyle::setCurrentText(FontStyle::FONT_STYLE_AMOUNT_PAYMENT_PART);
227
        foreach ($this->getCurrencyElements() as $informationElement) {
228
            $this->addContentElement($cell, $informationElement);
229
        }
230
    }
231
232
    private function addAmountContent() : void
233
    {
234
        $cell = $this->billTable->getPayment()->getAmountSection()->getAmountCell();
235
        FontStyle::setCurrentText(FontStyle::FONT_STYLE_AMOUNT_PAYMENT_PART);
236
        foreach ($this->getAmountElements() as $informationElement) {
237
            $this->addContentElement($cell, $informationElement);
238
        }
239
    }
240
241
    private function addFurtherInformationContent() : void
242
    {
243
        $cell = $this->billTable->getPayment()->getFurtherInformationSection();
244
        FontStyle::setCurrentText(FontStyle::FONT_STYLE_FURTHER_INFORMATION_PAYMENT_PART);
245
        foreach ($this->getFurtherInformationElements() as $informationElement) {
246
            $this->addContentElement($cell, $informationElement);
247
        }
248
    }
249
250
    private function addElementTextRun(string $text, TextRun $textRun, array|string $fStyle = []) : void
251
    {
252
        $lines = explode("\n", $text);
253
        foreach ($lines as $key => $line) {
254
            $textRun->addText($line, $fStyle, $fStyle);
255
            if (array_key_last($lines) !== $key) {
256
                $textRun->addTextBreak();
257
            }
258
        }
259
    }
260
}
261