1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* webtrees: online genealogy |
4
|
|
|
* Copyright (C) 2017 webtrees development team |
5
|
|
|
* This program is free software: you can redistribute it and/or modify |
6
|
|
|
* it under the terms of the GNU General Public License as published by |
7
|
|
|
* the Free Software Foundation, either version 3 of the License, or |
8
|
|
|
* (at your option) any later version. |
9
|
|
|
* This program is distributed in the hope that it will be useful, |
10
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
11
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12
|
|
|
* GNU General Public License for more details. |
13
|
|
|
* You should have received a copy of the GNU General Public License |
14
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
15
|
|
|
*/ |
16
|
|
|
namespace Fisharebest\Webtrees\Report; |
17
|
|
|
|
18
|
|
|
use TCPDF; |
19
|
|
|
|
20
|
|
|
/** |
21
|
|
|
* WT Report PDF Class |
22
|
|
|
* |
23
|
|
|
* This class inherits from the TCPDF class and is used to generate the PDF document |
24
|
|
|
*/ |
25
|
|
|
class ReportTcpdf extends TCPDF { |
26
|
|
|
/** @var ReportBaseElement[] Array of elements in the header */ |
27
|
|
|
public $headerElements = []; |
28
|
|
|
|
29
|
|
|
/** @var ReportBaseElement[] Array of elements in the page header */ |
30
|
|
|
public $pageHeaderElements = []; |
31
|
|
|
|
32
|
|
|
/** @var ReportBaseElement[] Array of elements in the footer */ |
33
|
|
|
public $footerElements = []; |
34
|
|
|
|
35
|
|
|
/** @var ReportBaseElement[] Array of elements in the body */ |
36
|
|
|
public $bodyElements = []; |
37
|
|
|
|
38
|
|
|
/** @var ReportBaseFootnote[] Array of elements in the footer notes */ |
39
|
|
|
public $printedfootnotes = []; |
40
|
|
|
|
41
|
|
|
/** @var string Currently used style name */ |
42
|
|
|
public $currentStyle; |
43
|
|
|
|
44
|
|
|
/** @var int The last cell height */ |
45
|
|
|
public $lastCellHeight = 0; |
46
|
|
|
|
47
|
|
|
/** @var int The largest font size within a TextBox to calculate the height */ |
48
|
|
|
public $largestFontHeight = 0; |
49
|
|
|
|
50
|
|
|
/** @var int The last pictures page number */ |
51
|
|
|
public $lastpicpage = 0; |
52
|
|
|
|
53
|
|
|
/** @var ReportBase The current report. */ |
54
|
|
|
public $wt_report; |
55
|
|
|
|
56
|
|
|
/** |
57
|
|
|
* PDF Header -PDF |
58
|
|
|
*/ |
59
|
|
|
public function header() { |
60
|
|
|
foreach ($this->headerElements as $element) { |
61
|
|
|
if (is_object($element)) { |
62
|
|
|
$element->render($this); |
63
|
|
|
} elseif (is_string($element) && $element == 'footnotetexts') { |
64
|
|
|
$this->footnotes(); |
65
|
|
|
} elseif (is_string($element) && $element == 'addpage') { |
66
|
|
|
$this->newPage(); |
67
|
|
|
} |
68
|
|
|
} |
69
|
|
|
foreach ($this->pageHeaderElements as $element) { |
70
|
|
|
if (is_object($element)) { |
71
|
|
|
$element->render($this); |
72
|
|
|
} elseif (is_string($element) && $element == 'footnotetexts') { |
73
|
|
|
$this->footnotes(); |
74
|
|
|
} elseif (is_string($element) && $element == 'addpage') { |
75
|
|
|
$this->newPage(); |
76
|
|
|
} |
77
|
|
|
} |
78
|
|
|
} |
79
|
|
|
|
80
|
|
|
/** |
81
|
|
|
* PDF Body -PDF |
82
|
|
|
*/ |
83
|
|
|
public function body() { |
84
|
|
|
$this->AddPage(); |
85
|
|
|
foreach ($this->bodyElements as $key => $element) { |
86
|
|
|
if (is_object($element)) { |
87
|
|
|
$element->render($this); |
88
|
|
|
} elseif (is_string($element) && $element == 'footnotetexts') { |
89
|
|
|
$this->footnotes(); |
90
|
|
|
} elseif (is_string($element) && $element == 'addpage') { |
91
|
|
|
$this->newPage(); |
92
|
|
|
} |
93
|
|
|
// Delete used elements in hope to reduce 'some' memory usage |
94
|
|
|
unset($this->bodyElements[$key]); |
95
|
|
|
} |
96
|
|
|
} |
97
|
|
|
|
98
|
|
|
/** |
99
|
|
|
* PDF Footnotes -PDF |
100
|
|
|
*/ |
101
|
|
|
public function footnotes() { |
102
|
|
|
foreach ($this->printedfootnotes as $element) { |
103
|
|
|
if (($this->GetY() + $element->getFootnoteHeight($this)) > $this->getPageHeight()) { |
104
|
|
|
$this->AddPage(); |
105
|
|
|
} |
106
|
|
|
$element->renderFootnote($this); |
107
|
|
|
if ($this->GetY() > $this->getPageHeight()) { |
108
|
|
|
$this->AddPage(); |
109
|
|
|
} |
110
|
|
|
} |
111
|
|
|
} |
112
|
|
|
|
113
|
|
|
/** |
114
|
|
|
* PDF Footer -PDF |
115
|
|
|
*/ |
116
|
|
View Code Duplication |
public function footer() { |
|
|
|
|
117
|
|
|
foreach ($this->footerElements as $element) { |
118
|
|
|
if (is_object($element)) { |
119
|
|
|
$element->render($this); |
120
|
|
|
} elseif (is_string($element) && $element == 'footnotetexts') { |
121
|
|
|
$this->footnotes(); |
122
|
|
|
} elseif (is_string($element) && $element == 'addpage') { |
123
|
|
|
$this->newPage(); |
124
|
|
|
} |
125
|
|
|
} |
126
|
|
|
} |
127
|
|
|
|
128
|
|
|
/** |
129
|
|
|
* Add an element to the Header -PDF |
130
|
|
|
* |
131
|
|
|
* @param object|string $element |
132
|
|
|
* |
133
|
|
|
* @return int The number of the Header elements |
134
|
|
|
*/ |
135
|
|
|
public function addHeader($element) { |
136
|
|
|
$this->headerElements[] = $element; |
137
|
|
|
|
138
|
|
|
return count($this->headerElements) - 1; |
139
|
|
|
} |
140
|
|
|
|
141
|
|
|
/** |
142
|
|
|
* Add an element to the Page Header -PDF |
143
|
|
|
* |
144
|
|
|
* @param object|string $element |
145
|
|
|
* |
146
|
|
|
* @return int The number of the Page Header elements |
147
|
|
|
*/ |
148
|
|
|
public function addPageHeader($element) { |
149
|
|
|
$this->pageHeaderElements[] = $element; |
150
|
|
|
|
151
|
|
|
return count($this->pageHeaderElements) - 1; |
152
|
|
|
} |
153
|
|
|
|
154
|
|
|
/** |
155
|
|
|
* Add an element to the Body -PDF |
156
|
|
|
* |
157
|
|
|
* @param object|string $element |
158
|
|
|
* |
159
|
|
|
* @return int The number of the Body elements |
160
|
|
|
*/ |
161
|
|
|
public function addBody($element) { |
162
|
|
|
$this->bodyElements[] = $element; |
163
|
|
|
|
164
|
|
|
return count($this->bodyElements) - 1; |
165
|
|
|
} |
166
|
|
|
|
167
|
|
|
/** |
168
|
|
|
* Add an element to the Footer -PDF |
169
|
|
|
* |
170
|
|
|
* @param object|string $element |
171
|
|
|
* |
172
|
|
|
* @return int The number of the Footer elements |
173
|
|
|
*/ |
174
|
|
|
public function addFooter($element) { |
175
|
|
|
$this->footerElements[] = $element; |
176
|
|
|
|
177
|
|
|
return count($this->footerElements) - 1; |
178
|
|
|
} |
179
|
|
|
|
180
|
|
|
/** |
181
|
|
|
* Remove the header. |
182
|
|
|
* |
183
|
|
|
* @param $index |
184
|
|
|
*/ |
185
|
|
|
public function removeHeader($index) { |
186
|
|
|
unset($this->headerElements[$index]); |
187
|
|
|
} |
188
|
|
|
|
189
|
|
|
/** |
190
|
|
|
* Remove the page header. |
191
|
|
|
* |
192
|
|
|
* @param $index |
193
|
|
|
*/ |
194
|
|
|
public function removePageHeader($index) { |
195
|
|
|
unset($this->pageHeaderElements[$index]); |
196
|
|
|
} |
197
|
|
|
|
198
|
|
|
/** |
199
|
|
|
* Remove the body. |
200
|
|
|
* |
201
|
|
|
* @param $index |
202
|
|
|
*/ |
203
|
|
|
public function removeBody($index) { |
204
|
|
|
unset($this->bodyElements[$index]); |
205
|
|
|
} |
206
|
|
|
|
207
|
|
|
/** |
208
|
|
|
* Remove the footer. |
209
|
|
|
* |
210
|
|
|
* @param $index |
211
|
|
|
*/ |
212
|
|
|
public function removeFooter($index) { |
213
|
|
|
unset($this->footerElements[$index]); |
214
|
|
|
} |
215
|
|
|
|
216
|
|
|
/** |
217
|
|
|
* Clear the Header -PDF |
218
|
|
|
*/ |
219
|
|
|
public function clearHeader() { |
220
|
|
|
unset($this->headerElements); |
221
|
|
|
$this->headerElements = []; |
222
|
|
|
} |
223
|
|
|
|
224
|
|
|
/** |
225
|
|
|
* Clear the Page Header -PDF |
226
|
|
|
*/ |
227
|
|
|
public function clearPageHeader() { |
228
|
|
|
unset($this->pageHeaderElements); |
229
|
|
|
$this->pageHeaderElements = []; |
230
|
|
|
} |
231
|
|
|
|
232
|
|
|
/** |
233
|
|
|
* Set the report. |
234
|
|
|
* |
235
|
|
|
* @param $r |
236
|
|
|
*/ |
237
|
|
|
public function setReport($r) { |
238
|
|
|
$this->wt_report = $r; |
239
|
|
|
} |
240
|
|
|
|
241
|
|
|
/** |
242
|
|
|
* Get the currently used style name -PDF |
243
|
|
|
* |
244
|
|
|
* @return string |
245
|
|
|
*/ |
246
|
|
|
public function getCurrentStyle() { |
247
|
|
|
return $this->currentStyle; |
248
|
|
|
} |
249
|
|
|
|
250
|
|
|
/** |
251
|
|
|
* Setup a style for usage -PDF |
252
|
|
|
* |
253
|
|
|
* @param string $s Style name |
254
|
|
|
*/ |
255
|
|
|
public function setCurrentStyle($s) { |
256
|
|
|
$this->currentStyle = $s; |
257
|
|
|
$style = $this->wt_report->getStyle($s); |
258
|
|
|
$this->SetFont($style['font'], $style['style'], $style['size']); |
259
|
|
|
} |
260
|
|
|
|
261
|
|
|
/** |
262
|
|
|
* Get the style -PDF |
263
|
|
|
* |
264
|
|
|
* @param string $s Style name |
265
|
|
|
* |
266
|
|
|
* @return array |
267
|
|
|
*/ |
268
|
|
|
public function getStyle($s) { |
269
|
|
|
if (!isset($this->wt_report->Styles[$s])) { |
270
|
|
|
$s = $this->getCurrentStyle(); |
271
|
|
|
$this->wt_report->Styles[$s] = $s; |
272
|
|
|
} |
273
|
|
|
|
274
|
|
|
return $this->wt_report->Styles[$s]; |
275
|
|
|
} |
276
|
|
|
|
277
|
|
|
/** |
278
|
|
|
* Add margin when static horizontal position is used -PDF |
279
|
|
|
* RTL supported |
280
|
|
|
* |
281
|
|
|
* @param float $x Static position |
282
|
|
|
* |
283
|
|
|
* @return float |
284
|
|
|
*/ |
285
|
|
|
public function addMarginX($x) { |
286
|
|
|
$m = $this->getMargins(); |
287
|
|
|
if ($this->getRTL()) { |
288
|
|
|
$x += $m['right']; |
289
|
|
|
} else { |
290
|
|
|
$x += $m['left']; |
291
|
|
|
} |
292
|
|
|
$this->SetX($x); |
293
|
|
|
|
294
|
|
|
return $x; |
295
|
|
|
} |
296
|
|
|
|
297
|
|
|
/** |
298
|
|
|
* Get the maximum line width to draw from the curren position -PDF |
299
|
|
|
* RTL supported |
300
|
|
|
* |
301
|
|
|
* @return float |
302
|
|
|
*/ |
303
|
|
|
public function getMaxLineWidth() { |
304
|
|
|
$m = $this->getMargins(); |
305
|
|
|
if ($this->getRTL()) { |
306
|
|
|
return ($this->getRemainingWidth() + $m['right']); |
307
|
|
|
} else { |
308
|
|
|
return ($this->getRemainingWidth() + $m['left']); |
309
|
|
|
} |
310
|
|
|
} |
311
|
|
|
|
312
|
|
|
/** |
313
|
|
|
* Get the height of the footnote. |
314
|
|
|
* |
315
|
|
|
* @return int |
316
|
|
|
*/ |
317
|
|
|
public function getFootnotesHeight() { |
318
|
|
|
$h = 0; |
319
|
|
|
foreach ($this->printedfootnotes as $element) { |
320
|
|
|
$h += $element->getHeight($this); |
321
|
|
|
} |
322
|
|
|
|
323
|
|
|
return $h; |
324
|
|
|
} |
325
|
|
|
|
326
|
|
|
/** |
327
|
|
|
* Returns the the current font size height -PDF |
328
|
|
|
* |
329
|
|
|
* @return int |
330
|
|
|
*/ |
331
|
|
View Code Duplication |
public function getCurrentStyleHeight() { |
|
|
|
|
332
|
|
|
if (empty($this->currentStyle)) { |
333
|
|
|
return $this->wt_report->defaultFontSize; |
334
|
|
|
} |
335
|
|
|
$style = $this->wt_report->getStyle($this->currentStyle); |
336
|
|
|
|
337
|
|
|
return $style['size']; |
338
|
|
|
} |
339
|
|
|
|
340
|
|
|
/** |
341
|
|
|
* Checks the Footnote and numbers them |
342
|
|
|
* |
343
|
|
|
* @param object $footnote |
344
|
|
|
* |
345
|
|
|
* @return bool false if not numbered befor | object if already numbered |
346
|
|
|
*/ |
347
|
|
View Code Duplication |
public function checkFootnote($footnote) { |
|
|
|
|
348
|
|
|
$ct = count($this->printedfootnotes); |
349
|
|
|
$val = $footnote->getValue(); |
350
|
|
|
$i = 0; |
351
|
|
|
while ($i < $ct) { |
352
|
|
|
if ($this->printedfootnotes[$i]->getValue() == $val) { |
353
|
|
|
// If this footnote already exist then set up the numbers for this object |
354
|
|
|
$footnote->setNum($i + 1); |
355
|
|
|
$footnote->setAddlink($i + 1); |
356
|
|
|
|
357
|
|
|
return $this->printedfootnotes[$i]; |
358
|
|
|
} |
359
|
|
|
$i++; |
360
|
|
|
} |
361
|
|
|
// If this Footnote has not been set up yet |
362
|
|
|
$footnote->setNum($ct + 1); |
363
|
|
|
$footnote->setAddlink($this->AddLink()); |
364
|
|
|
$this->printedfootnotes[] = $footnote; |
365
|
|
|
|
366
|
|
|
return false; |
367
|
|
|
} |
368
|
|
|
|
369
|
|
|
/** |
370
|
|
|
* Used this function instead of AddPage() |
371
|
|
|
* This function will make sure that images will not be overwritten |
372
|
|
|
*/ |
373
|
|
|
public function newPage() { |
374
|
|
|
if ($this->lastpicpage > $this->getPage()) { |
375
|
|
|
$this->setPage($this->lastpicpage); |
376
|
|
|
} |
377
|
|
|
$this->AddPage(); |
378
|
|
|
} |
379
|
|
|
|
380
|
|
|
/** |
381
|
|
|
* Add a page if needed -PDF |
382
|
|
|
* |
383
|
|
|
* @param int $height Cell height |
384
|
|
|
* |
385
|
|
|
* @return bool true in case of page break, false otherwise |
386
|
|
|
*/ |
387
|
|
|
public function checkPageBreakPDF($height) { |
388
|
|
|
return $this->checkPageBreak($height); |
389
|
|
|
} |
390
|
|
|
|
391
|
|
|
/** |
392
|
|
|
* Returns the remaining width between the current position and margins -PDF |
393
|
|
|
* |
394
|
|
|
* @return float Remaining width |
395
|
|
|
*/ |
396
|
|
|
public function getRemainingWidthPDF() { |
397
|
|
|
return $this->getRemainingWidth(); |
398
|
|
|
} |
399
|
|
|
} |
400
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.