| Total Complexity | 42 |
| Total Lines | 235 |
| Duplicated Lines | 0 % |
| Changes | 3 | ||
| Bugs | 0 | Features | 0 |
Complex classes like PhpWordOutput often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use PhpWordOutput, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 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 |
||
| 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 |
||
| 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 |
||
| 238 | } |
||
| 239 | } |
||
| 240 | |||
| 241 | private function addFurtherInformationContent() : void |
||
| 247 | } |
||
| 248 | } |
||
| 249 | |||
| 250 | private function addElementTextRun(string $text, TextRun $textRun, array|string $fStyle = []) : void |
||
| 257 | } |
||
| 258 | } |
||
| 259 | } |
||
| 261 |
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.
If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.