Passed
Pull Request — main (#4945)
by
unknown
06:13
created

ReportHtmlTextbox::render()   F

Complexity

Conditions 56
Paths > 20000

Size

Total Lines 277
Code Lines 167

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 56
eloc 167
c 1
b 0
f 0
nc 784465920
nop 1
dl 0
loc 277
rs 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * webtrees: online genealogy
5
 * Copyright (C) 2023 webtrees development team
6
 * This program is free software: you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation, either version 3 of the License, or
9
 * (at your option) any later version.
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
 * GNU General Public License for more details.
14
 * You should have received a copy of the GNU General Public License
15
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
16
 */
17
18
declare(strict_types=1);
19
20
namespace Fisharebest\Webtrees\Report;
21
22
use function abs;
23
use function count;
24
use function is_object;
25
use function ksort;
26
use function str_replace;
27
use function trim;
28
29
/**
30
 * Class ReportHtmlTextbox
31
 */
32
class ReportHtmlTextbox extends ReportBaseTextbox
33
{
34
    /**
35
     * Render the elements.
36
     *
37
     * @param HtmlRenderer $renderer
38
     *
39
     * @return void
40
     */
41
    public function render($renderer): void
42
    {
43
        static $lastBoxYfinal;
44
        // checkFootnote
45
        $newelements      = [];
46
        $lastelement      = null;
47
        $footnote_element = [];
48
        // Element counter
49
        $cE = count($this->elements);
50
        //-- collapse duplicate elements
51
        for ($i = 0; $i < $cE; $i++) {
52
            $element = $this->elements[$i];
53
            if ($element instanceof ReportBaseElement) {
54
                if ($element instanceof ReportBaseText) {
55
                    if (!empty($footnote_element)) {
56
                        ksort($footnote_element);
57
                        foreach ($footnote_element as $links) {
58
                            $newelements[] = $links;
59
                        }
60
                        $footnote_element = [];
61
                    }
62
                    if (!isset($lastelement)) {
63
                        $lastelement = $element;
64
                    } elseif (($element instanceof ReportBaseText && $lastelement instanceof ReportBaseText) &&
65
                           ($element->getStyleName() === $lastelement->getStyleName())) {
66
                            // Checking if the Text has the same style
67
                            $lastelement->addText(str_replace("\n", '<br>', $element->getValue()));
68
                        
69
                    } else {
70
                        $newelements[] = $lastelement;
71
                        $lastelement   = $element;
72
                    }
73
                } elseif ($element instanceof ReportHtmlImage) {
74
                    $lastelement   = $element;
75
                } elseif ($element instanceof ReportHtmlFootnote) {
76
                    // Check if the Footnote has been set with it’s link number
77
                    $renderer->checkFootnote($element);
78
                    // Save first the last element if any
79
                    if (isset($lastelement)) {
80
                        $newelements[] = $lastelement;
81
                        $lastelement   = null;
82
                    }
83
                    // Save the Footnote with it’s link number as key for sorting later
84
                    $footnote_element[$element->num] = $element;
85
                } elseif (trim($element->getValue()) !== '') {
86
                    // Do not keep empty footnotes
87
                    if (!empty($footnote_element)) {
88
                        ksort($footnote_element);
89
                        foreach ($footnote_element as $links) {
90
                            $newelements[] = $links;
91
                        }
92
                        $footnote_element = [];
93
                    }
94
                    if (isset($lastelement)) {
95
                        $newelements[] = $lastelement;
96
                        $lastelement   = null;
97
                    }
98
                    $newelements[] = $element;
99
                }
100
            } else {
101
                if (isset($lastelement)) {
102
                    $newelements[] = $lastelement;
103
                    $lastelement   = null;
104
                }
105
                if (!empty($footnote_element)) {
106
                    ksort($footnote_element);
107
                    foreach ($footnote_element as $links) {
108
                        $newelements[] = $links;
109
                    }
110
                    $footnote_element = [];
111
                }
112
                $newelements[] = $element;
113
            }
114
        }
115
        if (isset($lastelement)) {
116
            $newelements[] = $lastelement;
117
        }
118
        if (!empty($footnote_element)) {
119
            ksort($footnote_element);
120
            foreach ($footnote_element as $links) {
121
                $newelements[] = $links;
122
            }
123
        }
124
        $this->elements = $newelements;
125
        unset($footnote_element, $lastelement, $newelements);
126
127
        $cP = 0; // Class Padding
128
129
        // Used with line breaks and cell height calculation within this box only
130
        $renderer->largestFontHeight = 0;
131
132
        // If current position (left)
133
        if ($this->left === ReportBaseElement::CURRENT_POSITION) {
134
            $cX = $renderer->getX();
135
        } else {
136
            $cX = $this->left;
137
            $renderer->setX($cX);
138
        }
139
        // If current position (top)
140
        $align_Y = false;
141
        $topstr = "";
0 ignored issues
show
Unused Code introduced by
The assignment to $topstr is dead and can be removed.
Loading history...
142
        if ($this->top < -110000) { // pos='abs'
143
            $this->top += 222000;
144
        }
145
        if ($this->top < -10000) { // <= -100000: both pdf and html; -100000 -- -90000: only html
146
            $this->top += 90000;  //= ReportBaseElement::CURRENT_POSITION;
147
            if ($this->top < -9000) {
148
                $this->top += 10000;
149
            }
150
            $topstr = "top:" . $this->top . "pt;";
151
            $align_Y = true;
152
        }
153
        if ($this->top === ReportBaseElement::CURRENT_POSITION) {
154
            $this->top = $renderer->getY();
155
        } else {
156
            $renderer->setY($this->top);
157
        }
158
159
        // Check the width if set to page wide OR set by xml to larger then page width (margin)
160
        if ($this->width === 0.0 || $this->width > $renderer->getRemainingWidth()) {
161
            $this->width = $renderer->getRemainingWidth();
162
        }
163
        // Setup the CellPadding
164
        if ($this->padding) {
165
            $cP = $renderer->cPadding;
166
        }
167
168
        // For padding, we have to use less wrap width
169
        $cW = $this->width - $cP * 2.0;
170
171
        //-- calculate the text box height
172
        // Number of lines, will be converted to height
173
        $cHT = 0;
174
        // Element height (except text)
175
        $eH = 0.0;
176
        // Footnote height (in points)
177
        $fH = 0;
178
        $w  = 0;
179
        //-- $lw is an array
180
        // 0 => last line width
181
        // 1 => 1 if text was wrapped, 0 if text did not wrap
182
        // 2 => number of LF
183
        $lw = [];
184
        // Element counter
185
        $cE = count($this->elements);
186
        for ($i = 0; $i < $cE; $i++) {
187
            if (is_object($this->elements[$i])) {
188
                $ew = $this->elements[$i]->setWrapWidth($cW - $w - 2, $cW);
189
                if ($ew === $cW) {
190
                    $w = 0;
191
                }
192
                $lw = $this->elements[$i]->getWidth($renderer);
193
                // Text is already gets the # LF
194
                $cHT += $lw[2];
195
                if ($lw[1] === 1) {
196
                    $w = $lw[0];
197
                } elseif ($lw[1] === 2) {
198
                    $w = 0;
199
                } else {
200
                    $w += $lw[0];
201
                }
202
                if ($w > $cW) {
203
                    $w = $lw[0];
204
                }
205
                // For anything else but text (images), get the height
206
                $eH += $this->elements[$i]->getHeight($renderer);
207
            } else {
208
                $fH += abs($renderer->getFootnotesHeight($cW));
209
            }
210
        }
211
212
        // Add up what’s the final height
213
        //$cH = $this->height;
214
        $cH = 0;
215
        // If any element exist
216
        if ($cE > 0) {
217
            // Check if this is text or some other element, like images
218
            if ($eH === 0.0) {
0 ignored issues
show
introduced by
The condition $eH === 0.0 is always true.
Loading history...
219
                // Number of LF but at least one line
220
                $cHT = ($cHT + 1) * $renderer->cellHeightRatio;
221
                // Calculate the cell height with the largest font size used
222
                $cHT *= $renderer->largestFontHeight;
223
                if ($cH < $cHT) {
224
                    $cH = $cHT;
225
                }
226
            } else {
227
                // This is any other element
228
                if ($cH < $eH) {
229
                    $cH = $eH;
230
                }
231
                // Add Footnote height to the rest of the height
232
                $cH += $fH;
233
            }
234
        }
235
236
        unset($lw, $cHT, $fH, $w);
237
238
        // Finally, check the last cells height
239
        if ($cH < $renderer->lastCellHeight) {
240
            $cH = $renderer->lastCellHeight;
241
        }
242
        // Update max Y in case of a pagebreak
243
        // We don't want to over write any images or other stuff
244
        $renderer->addMaxY($this->top + $cH);
245
246
        // Start to print HTML
247
        if (!$align_Y) {
248
            echo '<div style="position:absolute;top:', $this->top, 'pt;';
249
        } else {
250
            echo '<div style="position:relative;top:', $this->top, 'pt;';
251
        }
252
        //echo '<div style="position:relative;';
253
        // LTR (left) or RTL (right)
254
        echo $renderer->alignRTL, ':', $cX, 'pt;';
255
        // Background color
256
        if ($this->fill && $this->bgcolor !== '') {
257
            echo ' background-color:', $this->bgcolor, ';';
258
        }
259
        // Print padding only when it’s set
260
        if ($this->padding) {
261
            // Use Cell around padding to support RTL also
262
            echo 'padding:', $cP, 'pt;';
263
        }
264
        // Border setup
265
        if ($this->border) {
266
            echo ' border:solid black 1pt;';
267
            if (!$align_Y) {
268
                echo 'width:', $this->width - 1 - $cP * 2, 'pt;height:', $cH - 1, 'pt;';
269
            } else {
270
                echo 'width:', $this->width - 1 - $cP * 2, 'pt;height:auto;';
271
            } // height:',$this->height,'pt;'; //,$topstr;
272
        } else {
273
            if (!$align_Y) {
274
                echo 'width:', $this->width - $cP * 2, 'pt;height:', $cH, 'pt;';
275
            } else {
276
                echo 'width:', $this->width - $cP * 2, 'pt;height:auto;';
277
            } //height:',$this->height,'pt;'; //,$topstr;
278
        }
279
        echo '">';
280
281
        // Do a little "margin" trick before print
282
        // to get the correct current position => "."
283
        $cXT = $renderer->getX();
284
        $cYT = $renderer->getY();
285
        $renderer->setXy(0, 0);
286
287
        // Print the text elements
288
        foreach ($this->elements as $element) {
289
            if ($element instanceof ReportHtmlText) {
290
                $element->render($renderer, false);
291
            } elseif ($element instanceof ReportBaseElement) {
292
                $element->render($renderer);
293
            } elseif ($element === 'footnotetexts') {
294
                $renderer->footnotes();
295
            } elseif ($element === 'addpage') {
296
                $renderer->addPage();
297
            }
298
        }
299
        echo "</div>\n";
300
301
        // Reset "margins"
302
        $renderer->setXy($cXT, $cYT);
303
        // This will be mostly used to trick the multiple images last height
304
        if ($this->reseth) {
305
            $cH = 0;
306
        }
307
        // New line and some clean up
308
        if (!$this->newline) {
309
            $renderer->setXy($cX + $this->width, $this->top);
310
            $renderer->lastCellHeight = $cH;
311
        } else {
312
            $renderer->setXy(0, $this->top + $cH + $cP * 2);
313
            $renderer->lastCellHeight = 0;
314
        }
315
        // This will make images in textboxes to ignore images in previous textboxes
316
        // Without this trick the $lastpicbottom in the previos textbox will be used in ReportHtmlImage
317
        $renderer->pageN++;
318
    }
319
}
320