diff options
| author | Greg Roach <fisharebest@webtrees.net> | 2018-07-16 08:20:33 +0100 |
|---|---|---|
| committer | Greg Roach <fisharebest@webtrees.net> | 2018-07-16 08:20:33 +0100 |
| commit | c1010eda29c0909ed4d5d463f32d32bfefdd4dfe (patch) | |
| tree | fbb656ebc014aa1295ac8e6176f41e89f94b91e7 /app/Report | |
| parent | 782f08d9bd2bfa06635da947ee34f8e1afd65088 (diff) | |
| download | webtrees-c1010eda29c0909ed4d5d463f32d32bfefdd4dfe.tar.gz webtrees-c1010eda29c0909ed4d5d463f32d32bfefdd4dfe.tar.bz2 webtrees-c1010eda29c0909ed4d5d463f32d32bfefdd4dfe.zip | |
Use PSR2 code style
Diffstat (limited to 'app/Report')
32 files changed, 7464 insertions, 6772 deletions
diff --git a/app/Report/ReportBase.php b/app/Report/ReportBase.php index 92227852dd..96bfd8a9cc 100644 --- a/app/Report/ReportBase.php +++ b/app/Report/ReportBase.php @@ -20,456 +20,700 @@ use Fisharebest\Webtrees\I18N; /** * Class ReportBase */ -class ReportBase { - /** User measure unit. */ - const UNITS = 'pt'; +class ReportBase +{ + /** User measure unit. */ + const UNITS = 'pt'; - /** webtrees URL */ - const WT_URL = WT_WEBTREES_URL; + /** webtrees URL */ + const WT_URL = WT_WEBTREES_URL; - /** @var float Left Margin (expressed in points) Default: 17.99 mm, 0.7083 inch */ - public $leftmargin = 51.0; + /** @var float Left Margin (expressed in points) Default: 17.99 mm, 0.7083 inch */ + public $leftmargin = 51.0; - /** @var float Right Margin (expressed in points) Default: 9.87 mm, 0.389 inch */ - public $rightmargin = 28.0; + /** @var float Right Margin (expressed in points) Default: 9.87 mm, 0.389 inch */ + public $rightmargin = 28.0; - /** @var float Top Margin (expressed in points) Default: 26.81 mm */ - public $topmargin = 76.0; + /** @var float Top Margin (expressed in points) Default: 26.81 mm */ + public $topmargin = 76.0; - /** @var float Bottom Margin (expressed in points) Default: 21.6 mm */ - public $bottommargin = 60.0; + /** @var float Bottom Margin (expressed in points) Default: 21.6 mm */ + public $bottommargin = 60.0; - /** @var float Header Margin (expressed in points) Default: 4.93 mm */ - public $headermargin = 14.0; + /** @var float Header Margin (expressed in points) Default: 4.93 mm */ + public $headermargin = 14.0; - /** @var float Footer Margin (expressed in points) Default: 9.88 mm, 0.389 inch */ - public $footermargin = 28.0; + /** @var float Footer Margin (expressed in points) Default: 9.88 mm, 0.389 inch */ + public $footermargin = 28.0; - /** @var string Page orientation (portrait, landscape) */ - public $orientation = 'portrait'; + /** @var string Page orientation (portrait, landscape) */ + public $orientation = 'portrait'; - /** @var string Page format name */ - public $pageFormat = 'A4'; + /** @var string Page format name */ + public $pageFormat = 'A4'; - /** @var float Height of page format in points */ - public $pageh = 0.0; + /** @var float Height of page format in points */ + public $pageh = 0.0; - /** @var float Width of page format in points */ - public $pagew = 0.0; + /** @var float Width of page format in points */ + public $pagew = 0.0; - /** @var string[][] An array of the Styles elements found in the document */ - public $Styles = []; + /** @var string[][] An array of the Styles elements found in the document */ + public $Styles = []; - /** @var string The default Report font name */ - public $defaultFont = 'dejavusans'; + /** @var string The default Report font name */ + public $defaultFont = 'dejavusans'; - /** @var int The default Report font size */ - public $defaultFontSize = 12; + /** @var int The default Report font size */ + public $defaultFontSize = 12; - /** @var string Header (H), Page header (PH), Body (B) or Footer (F) */ - public $processing = 'H'; + /** @var string Header (H), Page header (PH), Body (B) or Footer (F) */ + public $processing = 'H'; - /** @var bool RTL Language (false=LTR, true=RTL) */ - public $rtl = false; + /** @var bool RTL Language (false=LTR, true=RTL) */ + public $rtl = false; - /** @var bool Show the Generated by... (true=show the text) */ - public $showGenText = true; + /** @var bool Show the Generated by... (true=show the text) */ + public $showGenText = true; - /** @var string Generated By... text */ - public $generatedby = ''; + /** @var string Generated By... text */ + public $generatedby = ''; - /** @var string The report title */ - public $title = ''; + /** @var string The report title */ + public $title = ''; - /** @var string Author of the report, the users full name */ - public $rauthor = WT_WEBTREES . ' ' . WT_VERSION; + /** @var string Author of the report, the users full name */ + public $rauthor = WT_WEBTREES . ' ' . WT_VERSION; - /** @var string Keywords */ - public $rkeywords = ''; + /** @var string Keywords */ + public $rkeywords = ''; - /** @var string Report Description / Subject */ - public $rsubject = ''; + /** @var string Report Description / Subject */ + public $rsubject = ''; - /** - * Initial Setup - ReportBase - * - * Setting up document wide defaults that will be inherited of the report modules - * As DEFAULT A4 and Portrait will be used if not set - */ - public function setup() { - // Set RTL direction - if (I18N::direction() === 'rtl') { - $this->rtl = true; - } - // Set the Keywords - $this->rkeywords = ''; - // Generated By...text - // I18N: This is a report footer. %s is the name of the application. - $this->generatedby = I18N::translate('Generated by %s', WT_WEBTREES . ' ' . WT_VERSION); + /** + * Initial Setup - ReportBase + * + * Setting up document wide defaults that will be inherited of the report modules + * As DEFAULT A4 and Portrait will be used if not set + */ + public function setup() + { + // Set RTL direction + if (I18N::direction() === 'rtl') { + $this->rtl = true; + } + // Set the Keywords + $this->rkeywords = ''; + // Generated By...text + // I18N: This is a report footer. %s is the name of the application. + $this->generatedby = I18N::translate('Generated by %s', WT_WEBTREES . ' ' . WT_VERSION); - // For known size pages - if ($this->pagew == 0 && $this->pageh == 0) { - /** - * The current ISO 216 standard was introduced in 1975 and is a direct follow up to the german DIN 476 standard from 1922. ISO 216 is also called EN 20216 in Europe. - * The ISO paper sizes are based on the metric system so everything else is aproxiamte - * - * The Series A is used for Standard Printing and Stationary. - * The Series B is used for Posters, Wall-Charts etc. - * The C series is used for folders, post cards and envelopes. C series envelope is suitable to insert A series sizes. - * ISO also define format series RA and SRA for untrimmed raw paper, where SRA stands for 'supplementary raw format A'. - * Japan has adopted the ISO series A sizes, but its series B sizes are slightly different. These sizes are sometimes called JIS B or JB sizes. - * sun was a unit of length used in Japan and is equal to about 3.03 cm or 1.193 inches - * The United States, Canada, and in part Mexico, are today the only industrialized nations in which the ISO standard paper sizes are not yet widely used. - * - * A0 & A1 Technical drawings, posters - * A1 & A2 Flip charts - * A2 & A3 Drawings, diagrams, large tables - * A4 Letters, magazines, forms, catalogs, laser printer and copying machine output - * A5 Note pads - * A6 Postcards - * B5, A5, B6 A6 Books - * C4, C5, C6 Envelopes for A4 letters: unfolded (C4), folded once (C5), folded twice (C6) - * B4 & A3 Newspapers, supported by most copying machines in addition to A4 - * B8 & A8 Playing cards - * - * 1 inch = 72 points - * 1 mm = 2.8346457 points - * 1 inch = 25.4 mm - * 1 point = 0,35278 mm - */ - switch ($this->pageFormat) { - // ISO A series - case '4A0': // ISO 216, 1682 mm x 2378 mm - $sizes = [4767.86, 6740.79]; - break; - case '2A0': // ISO 216, 1189 mm x 1682 mm - $sizes = [3370.39, 4767.86]; - break; - case 'A0': // ISO 216, 841 mm x 1189mm - $sizes = [2383.94, 3370.39]; - break; - case 'A1': // ISO 216, 594 mm x 841 mm - $sizes = [1683.78, 2383.94]; - break; - case 'A2': // ISO 216, 420 mm x 594 mm - $sizes = [1190.55, 1683.78]; - break; - case 'A3': // ISO 216, 297 mm x 420 mm - $sizes = [841.89, 1190.55]; - break; - case 'A4': // ISO 216, 210 mm 297 mm - $sizes = [595.28, 841.89]; - break; - case 'A5': // ISO 216, 148 mm x 210 mm - $sizes = [419.53, 595.28]; - break; - case 'A6': // ISO 216, 105 mm x 148 mm - $sizes = [297.64, 419.53]; - break; - case 'A7': // ISO 216, 74 mm x 105 mm - $sizes = [209.76, 297.64]; - break; - case 'A8': // ISO 216, 52 mm x 74 mm - $sizes = [147.40, 209.76]; - break; - case 'A9': // ISO 216, 37 mm x 52 mm - $sizes = [104.88, 147.40]; - break; - case 'A10': // ISO 216, 26 mm x 37 mm - $sizes = [73.70, 104.88]; - break; + // For known size pages + if ($this->pagew == 0 && $this->pageh == 0) { + /** + * The current ISO 216 standard was introduced in 1975 and is a direct follow up to the german DIN 476 standard from 1922. ISO 216 is also called EN 20216 in Europe. + * The ISO paper sizes are based on the metric system so everything else is aproxiamte + * + * The Series A is used for Standard Printing and Stationary. + * The Series B is used for Posters, Wall-Charts etc. + * The C series is used for folders, post cards and envelopes. C series envelope is suitable to insert A series sizes. + * ISO also define format series RA and SRA for untrimmed raw paper, where SRA stands for 'supplementary raw format A'. + * Japan has adopted the ISO series A sizes, but its series B sizes are slightly different. These sizes are sometimes called JIS B or JB sizes. + * sun was a unit of length used in Japan and is equal to about 3.03 cm or 1.193 inches + * The United States, Canada, and in part Mexico, are today the only industrialized nations in which the ISO standard paper sizes are not yet widely used. + * + * A0 & A1 Technical drawings, posters + * A1 & A2 Flip charts + * A2 & A3 Drawings, diagrams, large tables + * A4 Letters, magazines, forms, catalogs, laser printer and copying machine output + * A5 Note pads + * A6 Postcards + * B5, A5, B6 A6 Books + * C4, C5, C6 Envelopes for A4 letters: unfolded (C4), folded once (C5), folded twice (C6) + * B4 & A3 Newspapers, supported by most copying machines in addition to A4 + * B8 & A8 Playing cards + * + * 1 inch = 72 points + * 1 mm = 2.8346457 points + * 1 inch = 25.4 mm + * 1 point = 0,35278 mm + */ + switch ($this->pageFormat) { + // ISO A series + case '4A0': // ISO 216, 1682 mm x 2378 mm + $sizes = [ + 4767.86, + 6740.79, + ]; + break; + case '2A0': // ISO 216, 1189 mm x 1682 mm + $sizes = [ + 3370.39, + 4767.86, + ]; + break; + case 'A0': // ISO 216, 841 mm x 1189mm + $sizes = [ + 2383.94, + 3370.39, + ]; + break; + case 'A1': // ISO 216, 594 mm x 841 mm + $sizes = [ + 1683.78, + 2383.94, + ]; + break; + case 'A2': // ISO 216, 420 mm x 594 mm + $sizes = [ + 1190.55, + 1683.78, + ]; + break; + case 'A3': // ISO 216, 297 mm x 420 mm + $sizes = [ + 841.89, + 1190.55, + ]; + break; + case 'A4': // ISO 216, 210 mm 297 mm + $sizes = [ + 595.28, + 841.89, + ]; + break; + case 'A5': // ISO 216, 148 mm x 210 mm + $sizes = [ + 419.53, + 595.28, + ]; + break; + case 'A6': // ISO 216, 105 mm x 148 mm + $sizes = [ + 297.64, + 419.53, + ]; + break; + case 'A7': // ISO 216, 74 mm x 105 mm + $sizes = [ + 209.76, + 297.64, + ]; + break; + case 'A8': // ISO 216, 52 mm x 74 mm + $sizes = [ + 147.40, + 209.76, + ]; + break; + case 'A9': // ISO 216, 37 mm x 52 mm + $sizes = [ + 104.88, + 147.40, + ]; + break; + case 'A10': // ISO 216, 26 mm x 37 mm + $sizes = [ + 73.70, + 104.88, + ]; + break; - // ISO B series - case 'B0': // ISO 216, 1000 mm x 1414 mm - $sizes = [2834.65, 4008.19]; - break; - case 'B1': // ISO 216, 707 mm x 1000 mm - $sizes = [2004.09, 2834.65]; - break; - case 'B2': // ISO 216, 500 mm x 707 mm - $sizes = [1417.32, 2004.09]; - break; - case 'B3': // ISO 216, 353 mm x 500 mm - $sizes = [1000.63, 1417.32]; - break; - case 'B4': // ISO 216, 250 mm x 353 mm - $sizes = [708.66, 1000.63]; - break; - case 'B5': // ISO 216, 176 mm x 250 mm - $sizes = [498.90, 708.66]; - break; - case 'B6': // ISO 216, 125 mm x 176 mm - $sizes = [354.33, 498.90]; - break; - case 'B7': // ISO 216, 88 mm x 125 mm - $sizes = [249.45, 354.33]; - break; - case 'B8': // ISO 216, 62 mm x 88 mm - $sizes = [175.75, 249.45]; - break; - case 'B9': // ISO 216, 44 mm x 62 mm - $sizes = [124.72, 175.75]; - break; - case 'B10': // ISO 216, 31 mm x 44 mm - $sizes = [87.87, 124.72]; - break; + // ISO B series + case 'B0': // ISO 216, 1000 mm x 1414 mm + $sizes = [ + 2834.65, + 4008.19, + ]; + break; + case 'B1': // ISO 216, 707 mm x 1000 mm + $sizes = [ + 2004.09, + 2834.65, + ]; + break; + case 'B2': // ISO 216, 500 mm x 707 mm + $sizes = [ + 1417.32, + 2004.09, + ]; + break; + case 'B3': // ISO 216, 353 mm x 500 mm + $sizes = [ + 1000.63, + 1417.32, + ]; + break; + case 'B4': // ISO 216, 250 mm x 353 mm + $sizes = [ + 708.66, + 1000.63, + ]; + break; + case 'B5': // ISO 216, 176 mm x 250 mm + $sizes = [ + 498.90, + 708.66, + ]; + break; + case 'B6': // ISO 216, 125 mm x 176 mm + $sizes = [ + 354.33, + 498.90, + ]; + break; + case 'B7': // ISO 216, 88 mm x 125 mm + $sizes = [ + 249.45, + 354.33, + ]; + break; + case 'B8': // ISO 216, 62 mm x 88 mm + $sizes = [ + 175.75, + 249.45, + ]; + break; + case 'B9': // ISO 216, 44 mm x 62 mm + $sizes = [ + 124.72, + 175.75, + ]; + break; + case 'B10': // ISO 216, 31 mm x 44 mm + $sizes = [ + 87.87, + 124.72, + ]; + break; - // ISO C series, Envelope - case 'C0': // ISO 269, 917 mm x 1297 mm, For flat A0 sheet - $sizes = [2599.37, 3676.54]; - break; - case 'C1': // ISO 269, 648 mm x 917 mm, For flat A1 sheet - $sizes = [1836.85, 2599.37]; - break; - case 'C2': // ISO 269, 458 mm x 648 mm, For flat A2 sheet, A1 folded in half - $sizes = [1298.27, 1836.85]; - break; - case 'C3': // ISO 269, 324 mm x 458 mm, For flat A3 sheet, A2 folded in half - $sizes = [918.43, 1298.27]; - break; - case 'C4': // ISO 269, 229 mm x 324 mm, For flat A4 sheet, A3 folded in half - $sizes = [649.13, 918.43]; - break; - case 'C5': // ISO 269, 162 mm x 229 mm, For flat A5 sheet, A4 folded in half - $sizes = [459.21, 649.13]; - break; - case 'C6/5': // ISO 269, 114 mm x 229 mm. A5 folded twice = 1/3 A4. Alternative for the DL envelope - $sizes = [323.15, 649.13]; - break; - case 'C6': // ISO 269, 114 mm x 162 mm, For A5 folded in half - $sizes = [323.15, 459.21]; - break; - case 'C7/6': // ISO 269, 81 mm x 162 mm, For A5 sheet folded in thirds - $sizes = [229.61, 459.21]; - break; - case 'C7': // ISO 269, 81 mm x 114 mm, For A5 folded in quarters - $sizes = [229.61, 323.15]; - break; - case 'C8': // ISO 269, 57 mm x 81 mm - $sizes = [161.57, 229.61]; - break; - case 'C9': // ISO 269, 40 mm x 57 mm - $sizes = [113.39, 161.57]; - break; - case 'C10': // ISO 269, 28 mm x 40 mm - $sizes = [79.37, 113.39]; - break; - case 'DL': // Original DIN 678 but ISO 269 now has this C6/5 , 110 mm x 220 mm, For A4 sheet folded in thirds, A5 in half - $sizes = [311.81, 623.62]; - break; + // ISO C series, Envelope + case 'C0': // ISO 269, 917 mm x 1297 mm, For flat A0 sheet + $sizes = [ + 2599.37, + 3676.54, + ]; + break; + case 'C1': // ISO 269, 648 mm x 917 mm, For flat A1 sheet + $sizes = [ + 1836.85, + 2599.37, + ]; + break; + case 'C2': // ISO 269, 458 mm x 648 mm, For flat A2 sheet, A1 folded in half + $sizes = [ + 1298.27, + 1836.85, + ]; + break; + case 'C3': // ISO 269, 324 mm x 458 mm, For flat A3 sheet, A2 folded in half + $sizes = [ + 918.43, + 1298.27, + ]; + break; + case 'C4': // ISO 269, 229 mm x 324 mm, For flat A4 sheet, A3 folded in half + $sizes = [ + 649.13, + 918.43, + ]; + break; + case 'C5': // ISO 269, 162 mm x 229 mm, For flat A5 sheet, A4 folded in half + $sizes = [ + 459.21, + 649.13, + ]; + break; + case 'C6/5': // ISO 269, 114 mm x 229 mm. A5 folded twice = 1/3 A4. Alternative for the DL envelope + $sizes = [ + 323.15, + 649.13, + ]; + break; + case 'C6': // ISO 269, 114 mm x 162 mm, For A5 folded in half + $sizes = [ + 323.15, + 459.21, + ]; + break; + case 'C7/6': // ISO 269, 81 mm x 162 mm, For A5 sheet folded in thirds + $sizes = [ + 229.61, + 459.21, + ]; + break; + case 'C7': // ISO 269, 81 mm x 114 mm, For A5 folded in quarters + $sizes = [ + 229.61, + 323.15, + ]; + break; + case 'C8': // ISO 269, 57 mm x 81 mm + $sizes = [ + 161.57, + 229.61, + ]; + break; + case 'C9': // ISO 269, 40 mm x 57 mm + $sizes = [ + 113.39, + 161.57, + ]; + break; + case 'C10': // ISO 269, 28 mm x 40 mm + $sizes = [ + 79.37, + 113.39, + ]; + break; + case 'DL': // Original DIN 678 but ISO 269 now has this C6/5 , 110 mm x 220 mm, For A4 sheet folded in thirds, A5 in half + $sizes = [ + 311.81, + 623.62, + ]; + break; - // Untrimmed stock sizes for the ISO-A Series - ISO primary range - case 'RA0': // ISO 478, 860 mm x 1220 mm - $sizes = [2437.80, 3458.27]; - break; - case 'RA1': // ISO 478, 610 mm x 860 mm - $sizes = [1729.13, 2437.80]; - break; - case 'RA2': // ISO 478, 430 mm x 610 mm - $sizes = [1218.90, 1729.13]; - break; - case 'RA3': // ISO 478, 305 mm x 430 mm - $sizes = [864.57, 1218.90]; - break; - case 'RA4': // ISO 478, 215 mm x 305 mm - $sizes = [609.45, 864.57]; - break; + // Untrimmed stock sizes for the ISO-A Series - ISO primary range + case 'RA0': // ISO 478, 860 mm x 1220 mm + $sizes = [ + 2437.80, + 3458.27, + ]; + break; + case 'RA1': // ISO 478, 610 mm x 860 mm + $sizes = [ + 1729.13, + 2437.80, + ]; + break; + case 'RA2': // ISO 478, 430 mm x 610 mm + $sizes = [ + 1218.90, + 1729.13, + ]; + break; + case 'RA3': // ISO 478, 305 mm x 430 mm + $sizes = [ + 864.57, + 1218.90, + ]; + break; + case 'RA4': // ISO 478, 215 mm x 305 mm + $sizes = [ + 609.45, + 864.57, + ]; + break; - // Untrimmed stock sizes for the ISO-A Series - ISO supplementary range - case 'SRA0': // ISO 593, 900 mm x 1280 mm - $sizes = [2551.18, 3628.35]; - break; - case 'SRA1': // ISO 593, 640 mm x 900 mm - $sizes = [1814.17, 2551.18]; - break; - case 'SRA2': // ISO 593, 450 mm x 640 mm - $sizes = [1275.59, 1814.17]; - break; - case 'SRA3': // ISO 593, 320 mm x 450 mm - $sizes = [907.09, 1275.59]; - break; - case 'SRA4': // ISO 593, 225 mm x 320 mm - $sizes = [637.80, 907.09]; - break; + // Untrimmed stock sizes for the ISO-A Series - ISO supplementary range + case 'SRA0': // ISO 593, 900 mm x 1280 mm + $sizes = [ + 2551.18, + 3628.35, + ]; + break; + case 'SRA1': // ISO 593, 640 mm x 900 mm + $sizes = [ + 1814.17, + 2551.18, + ]; + break; + case 'SRA2': // ISO 593, 450 mm x 640 mm + $sizes = [ + 1275.59, + 1814.17, + ]; + break; + case 'SRA3': // ISO 593, 320 mm x 450 mm + $sizes = [ + 907.09, + 1275.59, + ]; + break; + case 'SRA4': // ISO 593, 225 mm x 320 mm + $sizes = [ + 637.80, + 907.09, + ]; + break; - // ISO size variations - case 'A2EXTRA': // ISO 216, 445 mm x 619 mm - $sizes = [1261.42, 1754.65]; - break; - case 'A2SUPER': // ISO 216, 305 mm x 508 mm - $sizes = [864.57, 1440.00]; - break; - case 'A3EXTRA': // ISO 216, 322 mm x 445 mm - $sizes = [912.76, 1261.42]; - break; - case 'SUPERA3': // ISO 216, 305 mm x 487 mm - $sizes = [864.57, 1380.47]; - break; - case 'A4EXTRA': // ISO 216, 235 mm x 322 mm - $sizes = [666.14, 912.76]; - break; - case 'A4LONG': // ISO 216, 210 mm x 348 mm - $sizes = [595.28, 986.46]; - break; - case 'A4SUPER': // ISO 216, 229 mm x 322 mm - $sizes = [649.13, 912.76]; - break; - case 'SUPERA4': // ISO 216, 227 mm x 356 mm - $sizes = [643.46, 1009.13]; - break; - case 'A5EXTRA': // ISO 216, 173 mm x 235 mm - $sizes = [490.39, 666.14]; - break; - case 'SOB5EXTRA': // ISO 216, 202 mm x 276 mm - $sizes = [572.60, 782.36]; - break; + // ISO size variations + case 'A2EXTRA': // ISO 216, 445 mm x 619 mm + $sizes = [ + 1261.42, + 1754.65, + ]; + break; + case 'A2SUPER': // ISO 216, 305 mm x 508 mm + $sizes = [ + 864.57, + 1440.00, + ]; + break; + case 'A3EXTRA': // ISO 216, 322 mm x 445 mm + $sizes = [ + 912.76, + 1261.42, + ]; + break; + case 'SUPERA3': // ISO 216, 305 mm x 487 mm + $sizes = [ + 864.57, + 1380.47, + ]; + break; + case 'A4EXTRA': // ISO 216, 235 mm x 322 mm + $sizes = [ + 666.14, + 912.76, + ]; + break; + case 'A4LONG': // ISO 216, 210 mm x 348 mm + $sizes = [ + 595.28, + 986.46, + ]; + break; + case 'A4SUPER': // ISO 216, 229 mm x 322 mm + $sizes = [ + 649.13, + 912.76, + ]; + break; + case 'SUPERA4': // ISO 216, 227 mm x 356 mm + $sizes = [ + 643.46, + 1009.13, + ]; + break; + case 'A5EXTRA': // ISO 216, 173 mm x 235 mm + $sizes = [ + 490.39, + 666.14, + ]; + break; + case 'SOB5EXTRA': // ISO 216, 202 mm x 276 mm + $sizes = [ + 572.60, + 782.36, + ]; + break; - // Japanese version of the ISO 216 B series - case 'JB0': // JIS P 0138-61, 1030 mm x 1456 mm - $sizes = [2919.69, 4127.24]; - break; - case 'JB1': // JIS P 0138-61, 728 mm x 1030 mm - $sizes = [2063.62, 2919.69]; - break; - case 'JB2': // JIS P 0138-61, 515 mm x 728 mm - $sizes = [1459.84, 2063.62]; - break; - case 'JB3': // JIS P 0138-61, 364 mm x 515 mm - $sizes = [1031.81, 1459.84]; - break; - case 'JB4': // JIS P 0138-61, 257 mm x 364 mm - $sizes = [728.50, 1031.81]; - break; - case 'JB5': // JIS P 0138-61, 182 mm x 257 mm - $sizes = [515.91, 728.50]; - break; - case 'JB6': // JIS P 0138-61, 128 mm x 182 mm - $sizes = [362.83, 515.91]; - break; - case 'JB7': // JIS P 0138-61, 91 mm x 128 mm - $sizes = [257.95, 362.83]; - break; - case 'JB8': // JIS P 0138-61, 64 mm x 91 mm - $sizes = [181.42, 257.95]; - break; - case 'JB9': // JIS P 0138-61, 45 mm x 64 mm - $sizes = [127.56, 181.42]; - break; - case 'JB10': // JIS P 0138-61, 32 mm x 45 mm - $sizes = [90.71, 127.56]; - break; + // Japanese version of the ISO 216 B series + case 'JB0': // JIS P 0138-61, 1030 mm x 1456 mm + $sizes = [ + 2919.69, + 4127.24, + ]; + break; + case 'JB1': // JIS P 0138-61, 728 mm x 1030 mm + $sizes = [ + 2063.62, + 2919.69, + ]; + break; + case 'JB2': // JIS P 0138-61, 515 mm x 728 mm + $sizes = [ + 1459.84, + 2063.62, + ]; + break; + case 'JB3': // JIS P 0138-61, 364 mm x 515 mm + $sizes = [ + 1031.81, + 1459.84, + ]; + break; + case 'JB4': // JIS P 0138-61, 257 mm x 364 mm + $sizes = [ + 728.50, + 1031.81, + ]; + break; + case 'JB5': // JIS P 0138-61, 182 mm x 257 mm + $sizes = [ + 515.91, + 728.50, + ]; + break; + case 'JB6': // JIS P 0138-61, 128 mm x 182 mm + $sizes = [ + 362.83, + 515.91, + ]; + break; + case 'JB7': // JIS P 0138-61, 91 mm x 128 mm + $sizes = [ + 257.95, + 362.83, + ]; + break; + case 'JB8': // JIS P 0138-61, 64 mm x 91 mm + $sizes = [ + 181.42, + 257.95, + ]; + break; + case 'JB9': // JIS P 0138-61, 45 mm x 64 mm + $sizes = [ + 127.56, + 181.42, + ]; + break; + case 'JB10': // JIS P 0138-61, 32 mm x 45 mm + $sizes = [ + 90.71, + 127.56, + ]; + break; - // US pages - case 'EXECUTIVE': // 7.25 in x 10.5 in - $sizes = [522.00, 756.00]; - break; - case 'FOLIO': // 8.5 in x 13 in - $sizes = [612.00, 936.00]; - break; - case 'FOOLSCAP': // 13.5 in x 17 in - $sizes = [972.00, 1224.00]; - break; - case 'LEDGER': // 11 in x 17 in - $sizes = [792.00, 1224.00]; - break; - case 'LEGAL': // 8.5 in x 14 in - $sizes = [612.00, 1008.00]; - break; - case 'LETTER': // 8.5 in x 11 in - $sizes = [612.00, 792.00]; - break; - case 'QUARTO': // 8.46 in x 10.8 in - $sizes = [609.12, 777.50]; - break; - case 'STATEMENT': // 5.5 in x 8.5 in - $sizes = [396.00, 612.00]; - break; - case 'USGOVT': // 8 in x 11 in - $sizes = [576.00, 792.00]; - break; - default: - $this->pageFormat = 'A4'; - $sizes = [595.28, 841.89]; - break; - } - $this->pagew = $sizes[0]; - $this->pageh = $sizes[1]; - } else { - if ($this->pagew < 10) { - throw new \DomainException('REPORT ERROR ReportBase::setup(): For custom size pages you must set "customwidth" larger then this in the XML file'); - } - if ($this->pageh < 10) { - throw new \DomainException('REPORT ERROR ReportBase::setup(): For custom size pages you must set "customheight" larger then this in the XML file'); - } - } + // US pages + case 'EXECUTIVE': // 7.25 in x 10.5 in + $sizes = [ + 522.00, + 756.00, + ]; + break; + case 'FOLIO': // 8.5 in x 13 in + $sizes = [ + 612.00, + 936.00, + ]; + break; + case 'FOOLSCAP': // 13.5 in x 17 in + $sizes = [ + 972.00, + 1224.00, + ]; + break; + case 'LEDGER': // 11 in x 17 in + $sizes = [ + 792.00, + 1224.00, + ]; + break; + case 'LEGAL': // 8.5 in x 14 in + $sizes = [ + 612.00, + 1008.00, + ]; + break; + case 'LETTER': // 8.5 in x 11 in + $sizes = [ + 612.00, + 792.00, + ]; + break; + case 'QUARTO': // 8.46 in x 10.8 in + $sizes = [ + 609.12, + 777.50, + ]; + break; + case 'STATEMENT': // 5.5 in x 8.5 in + $sizes = [ + 396.00, + 612.00, + ]; + break; + case 'USGOVT': // 8 in x 11 in + $sizes = [ + 576.00, + 792.00, + ]; + break; + default: + $this->pageFormat = 'A4'; + $sizes = [ + 595.28, + 841.89, + ]; + break; + } + $this->pagew = $sizes[0]; + $this->pageh = $sizes[1]; + } else { + if ($this->pagew < 10) { + throw new \DomainException('REPORT ERROR ReportBase::setup(): For custom size pages you must set "customwidth" larger then this in the XML file'); + } + if ($this->pageh < 10) { + throw new \DomainException('REPORT ERROR ReportBase::setup(): For custom size pages you must set "customheight" larger then this in the XML file'); + } + } - return 0; - } + return 0; + } - /** - * Process the Header , Page header, Body or Footer - ReportBase - * - * @param string $p Header (H), Page header (PH), Body (B) or Footer (F) - * - * @return int - */ - public function setProcessing($p) { - $this->processing = $p; + /** + * Process the Header , Page header, Body or Footer - ReportBase + * + * @param string $p Header (H), Page header (PH), Body (B) or Footer (F) + * + * @return int + */ + public function setProcessing($p) + { + $this->processing = $p; - return 0; - } + return 0; + } - /** - * Add the Title when raw character data is used in Title - ReportBase - * - * @param string $data - * - * @return int - */ - public function addTitle($data) { - $this->title .= $data; + /** + * Add the Title when raw character data is used in Title - ReportBase + * + * @param string $data + * + * @return int + */ + public function addTitle($data) + { + $this->title .= $data; - return 0; - } + return 0; + } - /** - * Add the Description when raw character data is used in Description - ReportBase - * - * @param string $data - * - * @return int - */ - public function addDescription($data) { - $this->rsubject .= $data; + /** + * Add the Description when raw character data is used in Description - ReportBase + * + * @param string $data + * + * @return int + */ + public function addDescription($data) + { + $this->rsubject .= $data; - return 0; - } + return 0; + } - /** - * Add Style to Styles array - ReportBase - * - * @param array $style - * - * @return int - */ - public function addStyle($style) { - $this->Styles[$style['name']] = $style; + /** + * Add Style to Styles array - ReportBase + * + * @param array $style + * + * @return int + */ + public function addStyle($style) + { + $this->Styles[$style['name']] = $style; - return 0; - } + return 0; + } - /** - * Get a style from the Styles array - ReportBase - * - * @param string $s Style name - * - * @return array - */ - public function getStyle($s) { - if (!isset($this->Styles[$s])) { - return current($this->Styles); - } + /** + * Get a style from the Styles array - ReportBase + * + * @param string $s Style name + * + * @return array + */ + public function getStyle($s) + { + if (!isset($this->Styles[$s])) { + return current($this->Styles); + } - return $this->Styles[$s]; - } + return $this->Styles[$s]; + } } diff --git a/app/Report/ReportBaseCell.php b/app/Report/ReportBaseCell.php index 88a7d817cb..631478fcbd 100644 --- a/app/Report/ReportBaseCell.php +++ b/app/Report/ReportBaseCell.php @@ -18,172 +18,177 @@ namespace Fisharebest\Webtrees\Report; /** * Class ReportBaseCell */ -class ReportBaseCell extends ReportBaseElement { - /** - * Allows to center or align the text. Possible values are:<ul><li>left or empty string: left align</li><li>center: center align</li><li>right: right align</li><li>justify: justification (default value when $ishtml=false)</li></ul> - * - * @var string - */ - public $align = ''; - /** - * Whether or not a border should be printed around this box. 0 = no border, 1 = border. Default is 0. - * Or a string containing some or all of the following characters (in any order):<ul><li>L: left</li><li>T: top</li><li>R: right</li><li>B: bottom</li></ul> - * - * @var mixed - */ - public $border; - /** - * Border color in HTML code - * - * @var string - */ - public $bocolor; - /** - * The HTML color code to fill the background of this cell. - * - * @var string - */ - public $bgcolor; - /** - * Indicates if the cell background must be painted (1) or transparent (0). Default value: 1. - * If no background color is set then it will not be painted - * - * @var int - */ - public $fill; - /** - * Cell height DEFAULT 0 (expressed in points) - * The starting height of this cell. If the text wraps the height will automatically be adjusted. - * - * @var int - */ - public $height; - /** - * Left position in user units (X-position). Default is the current position - * - * @var mixed - */ - public $left; - /** - * Indicates where the current position should go after the call. Possible values are:<ul><li>0: to the right [DEFAULT]</li><li>1: to the beginning of the next line</li><li>2: below</li></ul> - * - * @var int - */ - public $newline; - /** - * The name of the Style that should be used to render the text. - * - * @var string - */ - public $styleName; - /** - * Stretch carachter mode: <ul><li>0 = disabled (default)</li><li>1 = horizontal scaling only if necessary</li><li>2 = forced horizontal scaling</li><li>3 = character spacing only if necessary</li><li>4 = forced character spacing</li></ul> - * - * @var int - */ - public $stretch; - /** - * Text color in HTML code - * - * @var string - */ - public $tcolor; - /** - * Top position in user units (Y-position). Default is the current position - * - * @var mixed - */ - public $top; - /** - * URL address - * - * @var string - */ - public $url; - /** - * Cell width DEFAULT 0 (expressed in points) - * Setting the width to 0 will make it the width from the current location to the right margin. - * - * @var int - */ - public $width; +class ReportBaseCell extends ReportBaseElement +{ + /** + * Allows to center or align the text. Possible values are:<ul><li>left or empty string: left align</li><li>center: center align</li><li>right: right align</li><li>justify: justification (default value when $ishtml=false)</li></ul> + * + * @var string + */ + public $align = ''; + /** + * Whether or not a border should be printed around this box. 0 = no border, 1 = border. Default is 0. + * Or a string containing some or all of the following characters (in any order):<ul><li>L: left</li><li>T: top</li><li>R: right</li><li>B: bottom</li></ul> + * + * @var mixed + */ + public $border; + /** + * Border color in HTML code + * + * @var string + */ + public $bocolor; + /** + * The HTML color code to fill the background of this cell. + * + * @var string + */ + public $bgcolor; + /** + * Indicates if the cell background must be painted (1) or transparent (0). Default value: 1. + * If no background color is set then it will not be painted + * + * @var int + */ + public $fill; + /** + * Cell height DEFAULT 0 (expressed in points) + * The starting height of this cell. If the text wraps the height will automatically be adjusted. + * + * @var int + */ + public $height; + /** + * Left position in user units (X-position). Default is the current position + * + * @var mixed + */ + public $left; + /** + * Indicates where the current position should go after the call. Possible values are:<ul><li>0: to the right [DEFAULT]</li><li>1: to the beginning of the next line</li><li>2: below</li></ul> + * + * @var int + */ + public $newline; + /** + * The name of the Style that should be used to render the text. + * + * @var string + */ + public $styleName; + /** + * Stretch carachter mode: <ul><li>0 = disabled (default)</li><li>1 = horizontal scaling only if necessary</li><li>2 = forced horizontal scaling</li><li>3 = character spacing only if necessary</li><li>4 = forced character spacing</li></ul> + * + * @var int + */ + public $stretch; + /** + * Text color in HTML code + * + * @var string + */ + public $tcolor; + /** + * Top position in user units (Y-position). Default is the current position + * + * @var mixed + */ + public $top; + /** + * URL address + * + * @var string + */ + public $url; + /** + * Cell width DEFAULT 0 (expressed in points) + * Setting the width to 0 will make it the width from the current location to the right margin. + * + * @var int + */ + public $width; - /** @var int Unknown */ - public $reseth; + /** @var int Unknown */ + public $reseth; - /** - * CELL - Element - * - * @param int $width cell width (expressed in points) - * @param int $height cell height (expressed in points) - * @param mixed $border Border style - * @param string $align Text alignement - * @param string $bgcolor Background color code - * @param string $style The name of the text style - * @param int $ln Indicates where the current position should go after the call - * @param mixed $top Y-position - * @param mixed $left X-position - * @param int $fill Indicates if the cell background must be painted (1) or transparent (0). Default value: 0. - * @param int $stretch Stretch carachter mode - * @param string $bocolor Border color - * @param string $tcolor Text color - * @param $reseth - */ - public function __construct( - $width, $height, $border, $align, $bgcolor, $style, $ln, $top, $left, $fill, $stretch, $bocolor, $tcolor, $reseth - ) { - $this->align = $align; - $this->border = $border; - $this->bgcolor = $bgcolor; - $this->bocolor = $bocolor; - $this->fill = $fill; - $this->height = $height; - $this->left = $left; - $this->newline = $ln; - $this->styleName = $style; - $this->text = ''; - $this->tcolor = $tcolor; - $this->top = $top; - $this->url = ''; - $this->stretch = $stretch; - $this->width = $width; - $this->reseth = $reseth; + /** + * CELL - Element + * + * @param int $width cell width (expressed in points) + * @param int $height cell height (expressed in points) + * @param mixed $border Border style + * @param string $align Text alignement + * @param string $bgcolor Background color code + * @param string $style The name of the text style + * @param int $ln Indicates where the current position should go after the call + * @param mixed $top Y-position + * @param mixed $left X-position + * @param int $fill Indicates if the cell background must be painted (1) or transparent (0). Default value: 0. + * @param int $stretch Stretch carachter mode + * @param string $bocolor Border color + * @param string $tcolor Text color + * @param $reseth + */ + public function __construct( + $width, $height, $border, $align, $bgcolor, $style, $ln, $top, $left, $fill, $stretch, $bocolor, $tcolor, $reseth + ) + { + $this->align = $align; + $this->border = $border; + $this->bgcolor = $bgcolor; + $this->bocolor = $bocolor; + $this->fill = $fill; + $this->height = $height; + $this->left = $left; + $this->newline = $ln; + $this->styleName = $style; + $this->text = ''; + $this->tcolor = $tcolor; + $this->top = $top; + $this->url = ''; + $this->stretch = $stretch; + $this->width = $width; + $this->reseth = $reseth; - return 0; - } + return 0; + } - /** - * Get the cell height - * - * @param $renderer - * - * @return float - */ - public function getHeight($renderer) { - return $this->height; - } + /** + * Get the cell height + * + * @param $renderer + * + * @return float + */ + public function getHeight($renderer) + { + return $this->height; + } - /** - * Sets the current cells URL - * - * @param string $url The URL address to save - * - * @return int - */ - public function setUrl($url) { - $this->url = $url; + /** + * Sets the current cells URL + * + * @param string $url The URL address to save + * + * @return int + */ + public function setUrl($url) + { + $this->url = $url; - return 0; - } + return 0; + } - /** - * Get the cell width - * - * @param $renderer - * - * @return float - */ - public function getWidth($renderer) { - return $this->width; - } + /** + * Get the cell width + * + * @param $renderer + * + * @return float + */ + public function getWidth($renderer) + { + return $this->width; + } } diff --git a/app/Report/ReportBaseElement.php b/app/Report/ReportBaseElement.php index ffede002a3..cb5e5f2f07 100644 --- a/app/Report/ReportBaseElement.php +++ b/app/Report/ReportBaseElement.php @@ -18,104 +18,120 @@ namespace Fisharebest\Webtrees\Report; /** * Class ReportBaseElement */ -class ReportBaseElement { - /** @var string Text*/ - public $text = ''; +class ReportBaseElement +{ + /** @var string Text */ + public $text = ''; - /** - * Element renderer - * - * @param ReportHtml|ReportTcpdf $renderer - */ - public function render($renderer) { - //-- to be implemented in inherited classes - } + /** + * Element renderer + * + * @param ReportHtml|ReportTcpdf $renderer + */ + public function render($renderer) + { + //-- to be implemented in inherited classes + } - /** - * Get the height. - * - * @param ReportHtml|ReportTcpdf $renderer - * - * @return float - */ - public function getHeight($renderer) { - return 0.0; - } + /** + * Get the height. + * + * @param ReportHtml|ReportTcpdf $renderer + * + * @return float + */ + public function getHeight($renderer) + { + return 0.0; + } - /** - * Get the width. - * - * @param ReportHtml|ReportTcpdf $renderer - * - * @return float - */ - public function getWidth($renderer) { - return 0.0; - } + /** + * Get the width. + * + * @param ReportHtml|ReportTcpdf $renderer + * + * @return float + */ + public function getWidth($renderer) + { + return 0.0; + } - /** - * Add text. - * - * @param string $t - * - * @return int - */ - public function addText($t) { - $t = trim($t, "\r\n\t"); - $t = str_replace(['<br>', ' '], ["\n", ' '], $t); - $t = strip_tags($t); - $t = htmlspecialchars_decode($t); - $this->text .= $t; + /** + * Add text. + * + * @param string $t + * + * @return int + */ + public function addText($t) + { + $t = trim($t, "\r\n\t"); + $t = str_replace([ + '<br>', + ' ', + ], [ + "\n", + ' ', + ], $t); + $t = strip_tags($t); + $t = htmlspecialchars_decode($t); + $this->text .= $t; - return 0; - } + return 0; + } - /** - * Add an end-of-line. - * - * @return int - */ - public function addNewline() { - $this->text .= "\n"; + /** + * Add an end-of-line. + * + * @return int + */ + public function addNewline() + { + $this->text .= "\n"; - return 0; - } + return 0; + } - /** - * Get the current text. - * - * @return string - */ - public function getValue() { - return $this->text; - } + /** + * Get the current text. + * + * @return string + */ + public function getValue() + { + return $this->text; + } - /** - * Set the width to wrap text. - * - * @param $wrapwidth - * @param $cellwidth - * - * @return int - */ - public function setWrapWidth($wrapwidth, $cellwidth) { - return 0; - } + /** + * Set the width to wrap text. + * + * @param $wrapwidth + * @param $cellwidth + * + * @return int + */ + public function setWrapWidth($wrapwidth, $cellwidth) + { + return 0; + } - /** - * Render the footnotes. - * - * @param $renderer - */ - public function renderFootnote($renderer) { - } + /** + * Render the footnotes. + * + * @param $renderer + */ + public function renderFootnote($renderer) + { + } - /** - * Set the text. - * - * @param $text - */ - public function setText($text) { - $this->text = $text; - } + /** + * Set the text. + * + * @param $text + */ + public function setText($text) + { + $this->text = $text; + } } diff --git a/app/Report/ReportBaseFootnote.php b/app/Report/ReportBaseFootnote.php index ae38626358..50989aec93 100644 --- a/app/Report/ReportBaseFootnote.php +++ b/app/Report/ReportBaseFootnote.php @@ -18,119 +18,131 @@ namespace Fisharebest\Webtrees\Report; /** * Class ReportBaseFootnote */ -class ReportBaseFootnote extends ReportBaseElement { - /** - * The name of the style for this element - * - * @var string - */ - public $styleName = ''; +class ReportBaseFootnote extends ReportBaseElement +{ + /** + * The name of the style for this element + * + * @var string + */ + public $styleName = ''; - /** - * Numbers for the links - * - * @var int - */ - public $num; + /** + * Numbers for the links + * + * @var int + */ + public $num; - /** - * The text that will be printed with the number - * - * @var string - */ - public $numText = ''; + /** + * The text that will be printed with the number + * + * @var string + */ + public $numText = ''; - /** - * Remaining width of a cell - * - * @var float User unit (points) - */ - public $wrapWidthRemaining; + /** + * Remaining width of a cell + * + * @var float User unit (points) + */ + public $wrapWidthRemaining; - /** - * Original width of a cell - * - * @var float User unit (points) - */ - public $wrapWidthCell; + /** + * Original width of a cell + * + * @var float User unit (points) + */ + public $wrapWidthCell; - /** @var string A link */ - public $addlink; + /** @var string A link */ + public $addlink; - /** - * Createa an element. - * - * @param string $style - */ - public function __construct($style = '') { - $this->text = ''; - if (!empty($style)) { - $this->styleName = $style; - } else { - $this->styleName = 'footnote'; - } - } + /** + * Createa an element. + * + * @param string $style + */ + public function __construct($style = '') + { + $this->text = ''; + if (!empty($style)) { + $this->styleName = $style; + } else { + $this->styleName = 'footnote'; + } + } - /** - * Add text. - * - * @param $t - * - * @return int - */ - public function addText($t) { - $t = trim($t, "\r\n\t"); - $t = str_replace(['<br>', ' '], ["\n", ' '], $t); - $t = strip_tags($t); - $t = htmlspecialchars_decode($t); - $this->text .= $t; + /** + * Add text. + * + * @param $t + * + * @return int + */ + public function addText($t) + { + $t = trim($t, "\r\n\t"); + $t = str_replace([ + '<br>', + ' ', + ], [ + "\n", + ' ', + ], $t); + $t = strip_tags($t); + $t = htmlspecialchars_decode($t); + $this->text .= $t; - return 0; - } + return 0; + } - /** - * Set the width to wrap text. - * - * @param $wrapwidth - * @param $cellwidth - * - * @return mixed - */ - public function setWrapWidth($wrapwidth, $cellwidth) { - $this->wrapWidthCell = $cellwidth; - if (strpos($this->numText, "\n") !== false) { - $this->wrapWidthRemaining = $cellwidth; - } else { - $this->wrapWidthRemaining = $wrapwidth; - } + /** + * Set the width to wrap text. + * + * @param $wrapwidth + * @param $cellwidth + * + * @return mixed + */ + public function setWrapWidth($wrapwidth, $cellwidth) + { + $this->wrapWidthCell = $cellwidth; + if (strpos($this->numText, "\n") !== false) { + $this->wrapWidthRemaining = $cellwidth; + } else { + $this->wrapWidthRemaining = $wrapwidth; + } - return $this->wrapWidthRemaining; - } + return $this->wrapWidthRemaining; + } - /** - * Set the number. - * - * @param $n - * - * @return int - */ - public function setNum($n) { - $this->num = $n; - $this->numText = "$n "; + /** + * Set the number. + * + * @param $n + * + * @return int + */ + public function setNum($n) + { + $this->num = $n; + $this->numText = "$n "; - return 0; - } + return 0; + } - /** - * Add a link. - * - * @param $a - * - * @return int - */ - public function setAddlink($a) { - $this->addlink = $a; + /** + * Add a link. + * + * @param $a + * + * @return int + */ + public function setAddlink($a) + { + $this->addlink = $a; - return 0; - } + return 0; + } } diff --git a/app/Report/ReportBaseHtml.php b/app/Report/ReportBaseHtml.php index a5252e4d95..8011baa327 100644 --- a/app/Report/ReportBaseHtml.php +++ b/app/Report/ReportBaseHtml.php @@ -18,59 +18,64 @@ namespace Fisharebest\Webtrees\Report; /** * Class ReportBaseHtml */ -class ReportBaseHtml extends ReportBaseElement { - /** @var string The XML tag. */ - public $tag; +class ReportBaseHtml extends ReportBaseElement +{ + /** @var string The XML tag. */ + public $tag; - /** @var string[] Attributes of the XML tag. */ - public $attrs; + /** @var string[] Attributes of the XML tag. */ + public $attrs; - /** @var ReportBaseElement[] A list of elements. */ - public $elements = []; + /** @var ReportBaseElement[] A list of elements. */ + public $elements = []; - /** - * Create an element. - * - * @param $tag - * @param $attrs - */ - public function __construct($tag, $attrs) { - $this->tag = $tag; - $this->attrs = $attrs; + /** + * Create an element. + * + * @param $tag + * @param $attrs + */ + public function __construct($tag, $attrs) + { + $this->tag = $tag; + $this->attrs = $attrs; - return 0; - } + return 0; + } - /** - * Get the start tag. - * - * @return string - */ - public function getStart() { - $str = '<' . $this->tag . ' '; - foreach ($this->attrs as $key => $value) { - $str .= $key . '="' . $value . '" '; - } - $str .= '>'; + /** + * Get the start tag. + * + * @return string + */ + public function getStart() + { + $str = '<' . $this->tag . ' '; + foreach ($this->attrs as $key => $value) { + $str .= $key . '="' . $value . '" '; + } + $str .= '>'; - return $str; - } + return $str; + } - /** - * Get the end tag. - * - * @return string - */ - public function getEnd() { - return '</' . $this->tag . '>'; - } + /** + * Get the end tag. + * + * @return string + */ + public function getEnd() + { + return '</' . $this->tag . '>'; + } - /** - * Add an element. - * - * @param ReportBaseElement $element - */ - public function addElement($element) { - $this->elements[] = $element; - } + /** + * Add an element. + * + * @param ReportBaseElement $element + */ + public function addElement($element) + { + $this->elements[] = $element; + } } diff --git a/app/Report/ReportBaseImage.php b/app/Report/ReportBaseImage.php index df28c9afb6..82e28c8a4c 100644 --- a/app/Report/ReportBaseImage.php +++ b/app/Report/ReportBaseImage.php @@ -18,92 +18,96 @@ namespace Fisharebest\Webtrees\Report; /** * Class ReportBaseImage */ -class ReportBaseImage extends ReportBaseElement { - /** - * Filename of the image - * - * @var string - */ - public $file; - /** - * Height of the image - * - * @var float - */ - public $height; - /** - * Width of the image - * - * @var float - */ - public $width; - /** - * X-position (left) of the image - * - * @var float - */ - public $x; - /** - * Y-position (top) of the image - * - * @var float - */ - public $y; - /** - * Placement fo the image. L: left, C:center, R:right - * - * @var string - */ - public $align = ''; - /** - * T:same line, N:next line - * - * @var string - */ - public $line = ''; +class ReportBaseImage extends ReportBaseElement +{ + /** + * Filename of the image + * + * @var string + */ + public $file; + /** + * Height of the image + * + * @var float + */ + public $height; + /** + * Width of the image + * + * @var float + */ + public $width; + /** + * X-position (left) of the image + * + * @var float + */ + public $x; + /** + * Y-position (top) of the image + * + * @var float + */ + public $y; + /** + * Placement fo the image. L: left, C:center, R:right + * + * @var string + */ + public $align = ''; + /** + * T:same line, N:next line + * + * @var string + */ + public $line = ''; - /** - * Image class function - Base - * - * @param string $file Filename of the image - * @param float $x X-position (left) of the image - * @param float $y Y-position (top) of the image - * @param float $w Width of the image - * @param float $h Height of the image - * @param string $align Placement of the image. L: left, C:center, R:right - * @param string $ln T:same line, N:next line - */ - public function __construct($file, $x, $y, $w, $h, $align, $ln) { - $this->file = $file; - $this->width = $w; - $this->height = $h; - $this->x = $x; - $this->y = $y; - $this->align = $align; - $this->line = $ln; + /** + * Image class function - Base + * + * @param string $file Filename of the image + * @param float $x X-position (left) of the image + * @param float $y Y-position (top) of the image + * @param float $w Width of the image + * @param float $h Height of the image + * @param string $align Placement of the image. L: left, C:center, R:right + * @param string $ln T:same line, N:next line + */ + public function __construct($file, $x, $y, $w, $h, $align, $ln) + { + $this->file = $file; + $this->width = $w; + $this->height = $h; + $this->x = $x; + $this->y = $y; + $this->align = $align; + $this->line = $ln; - return 0; - } + return 0; + } - /** - * Get the height. - * - * @param $renderer - * - * @return float - */ - public function getHeight($renderer) { - return $this->height; - } + /** + * Get the height. + * + * @param $renderer + * + * @return float + */ + public function getHeight($renderer) + { + return $this->height; + } - /** - * Get the width. - * - * @param $renderer - * - * @return float - */ - public function getWidth($renderer) { - return $this->width; - } + /** + * Get the width. + * + * @param $renderer + * + * @return float + */ + public function getWidth($renderer) + { + return $this->width; + } } diff --git a/app/Report/ReportBaseLine.php b/app/Report/ReportBaseLine.php index d785c437df..d1611f2b72 100644 --- a/app/Report/ReportBaseLine.php +++ b/app/Report/ReportBaseLine.php @@ -18,68 +18,72 @@ namespace Fisharebest\Webtrees\Report; /** * Class ReportBaseLine */ -class ReportBaseLine extends ReportBaseElement { - /** - * Start horizontal position, current position (default) - * - * @var mixed - */ - public $x1 = '.'; - /** - * Start vertical position, current position (default) - * - * @var mixed - */ - public $y1 = '.'; - /** - * End horizontal position, maximum width (default) - * - * @var mixed - */ - public $x2 = '.'; - /** - * End vertical position - * - * @var mixed - */ - public $y2 = '.'; +class ReportBaseLine extends ReportBaseElement +{ + /** + * Start horizontal position, current position (default) + * + * @var mixed + */ + public $x1 = '.'; + /** + * Start vertical position, current position (default) + * + * @var mixed + */ + public $y1 = '.'; + /** + * End horizontal position, maximum width (default) + * + * @var mixed + */ + public $x2 = '.'; + /** + * End vertical position + * + * @var mixed + */ + public $y2 = '.'; - /** - * Create a line class - Base - * - * @param mixed $x1 - * @param mixed $y1 - * @param mixed $x2 - * @param mixed $y2 - */ - public function __construct($x1, $y1, $x2, $y2) { - $this->x1 = $x1; - $this->y1 = $y1; - $this->x2 = $x2; - $this->y2 = $y2; + /** + * Create a line class - Base + * + * @param mixed $x1 + * @param mixed $y1 + * @param mixed $x2 + * @param mixed $y2 + */ + public function __construct($x1, $y1, $x2, $y2) + { + $this->x1 = $x1; + $this->y1 = $y1; + $this->x2 = $x2; + $this->y2 = $y2; - return 0; - } + return 0; + } - /** - * Get the height of the line. - * - * @param $renderer - * - * @return number - */ - public function getHeight($renderer) { - return abs($this->y2 - $this->y1); - } + /** + * Get the height of the line. + * + * @param $renderer + * + * @return number + */ + public function getHeight($renderer) + { + return abs($this->y2 - $this->y1); + } - /** - * Get the width of the line. - * - * @param $renderer - * - * @return number - */ - public function getWidth($renderer) { - return abs($this->x2 - $this->x1); - } + /** + * Get the width of the line. + * + * @param $renderer + * + * @return number + */ + public function getWidth($renderer) + { + return abs($this->x2 - $this->x1); + } } diff --git a/app/Report/ReportBasePageheader.php b/app/Report/ReportBasePageheader.php index e01968b097..9d3b3f0d0f 100644 --- a/app/Report/ReportBasePageheader.php +++ b/app/Report/ReportBasePageheader.php @@ -18,36 +18,40 @@ namespace Fisharebest\Webtrees\Report; /** * Class ReportBasePageheader */ -class ReportBasePageheader extends ReportBaseElement { - /** @var ReportBaseElement[] Elements */ - public $elements = []; +class ReportBasePageheader extends ReportBaseElement +{ + /** @var ReportBaseElement[] Elements */ + public $elements = []; - /** - * Create a page header - */ - public function __construct() { - $this->elements = []; + /** + * Create a page header + */ + public function __construct() + { + $this->elements = []; - return 0; - } + return 0; + } - /** - * Unknown? - * - * @return int - */ - public function textBox() { - $this->elements = []; + /** + * Unknown? + * + * @return int + */ + public function textBox() + { + $this->elements = []; - return 0; - } + return 0; + } - /** - * Add element - PageHeader - * - * @param ReportBaseElement $element - */ - public function addElement($element) { - $this->elements[] = $element; - } + /** + * Add element - PageHeader + * + * @param ReportBaseElement $element + */ + public function addElement($element) + { + $this->elements[] = $element; + } } diff --git a/app/Report/ReportBaseText.php b/app/Report/ReportBaseText.php index a9f268fc70..3254440879 100644 --- a/app/Report/ReportBaseText.php +++ b/app/Report/ReportBaseText.php @@ -18,72 +18,76 @@ namespace Fisharebest\Webtrees\Report; /** * Class ReportBaseText */ -class ReportBaseText extends ReportBaseElement { - /** - * Text color in HTML code - * - * @var string - */ - public $color; - /** - * Style name - * - * @var string - */ - public $styleName; - /** - * Remaining width of a cel - * - * @var int User unit (points) - */ - public $wrapWidthRemaining; - /** - * Original width of a cell - * - * @var int User unit (points) - */ - public $wrapWidthCell; +class ReportBaseText extends ReportBaseElement +{ + /** + * Text color in HTML code + * + * @var string + */ + public $color; + /** + * Style name + * + * @var string + */ + public $styleName; + /** + * Remaining width of a cel + * + * @var int User unit (points) + */ + public $wrapWidthRemaining; + /** + * Original width of a cell + * + * @var int User unit (points) + */ + public $wrapWidthCell; - /** - * Create a Text class - Base - * - * @param string $style The name of the text style - * @param string $color HTML color code - */ - public function __construct($style, $color) { - $this->text = ''; - $this->color = $color; - $this->wrapWidthRemaining = 0; - $this->styleName = $style; + /** + * Create a Text class - Base + * + * @param string $style The name of the text style + * @param string $color HTML color code + */ + public function __construct($style, $color) + { + $this->text = ''; + $this->color = $color; + $this->wrapWidthRemaining = 0; + $this->styleName = $style; - return 0; - } + return 0; + } - /** - * Set the width for word-wrapping. - * - * @param $wrapwidth - * @param $cellwidth - * - * @return mixed - */ - public function setWrapWidth($wrapwidth, $cellwidth) { - $this->wrapWidthCell = $cellwidth; - if (strpos($this->text, "\n") !== false) { - $this->wrapWidthRemaining = $cellwidth; - } else { - $this->wrapWidthRemaining = $wrapwidth; - } + /** + * Set the width for word-wrapping. + * + * @param $wrapwidth + * @param $cellwidth + * + * @return mixed + */ + public function setWrapWidth($wrapwidth, $cellwidth) + { + $this->wrapWidthCell = $cellwidth; + if (strpos($this->text, "\n") !== false) { + $this->wrapWidthRemaining = $cellwidth; + } else { + $this->wrapWidthRemaining = $wrapwidth; + } - return $this->wrapWidthRemaining; - } + return $this->wrapWidthRemaining; + } - /** - * Get the style name. - * - * @return string - */ - public function getStyleName() { - return $this->styleName; - } + /** + * Get the style name. + * + * @return string + */ + public function getStyleName() + { + return $this->styleName; + } } diff --git a/app/Report/ReportBaseTextbox.php b/app/Report/ReportBaseTextbox.php index fb116113ec..a6b8de0adc 100644 --- a/app/Report/ReportBaseTextbox.php +++ b/app/Report/ReportBaseTextbox.php @@ -18,141 +18,144 @@ namespace Fisharebest\Webtrees\Report; /** * Class ReportBaseTextbox */ -class ReportBaseTextbox extends ReportBaseElement { - /** - * Array of elements in the TextBox - * - * @var array - */ - public $elements = []; +class ReportBaseTextbox extends ReportBaseElement +{ + /** + * Array of elements in the TextBox + * + * @var array + */ + public $elements = []; - /** - * Background color in HTML code - * - * @var string - */ - public $bgcolor; - /** - * Whether or not paint the background - * - * @var bool - */ - public $fill; + /** + * Background color in HTML code + * + * @var string + */ + public $bgcolor; + /** + * Whether or not paint the background + * + * @var bool + */ + public $fill; - /** - * Position the left corner of this box on the page(expressed in points). The default is the current position. - * - * @var mixed - */ - public $left; - /** - * Position the top corner of this box on the page(expressed in points). the default is the current position - * - * @var mixed - */ - public $top; - /** - * After this box is finished rendering, should the next section of text start immediately after the this box or should it start on a new line under this box. 0 = no new line, 1 = force new line. Default is 0 - * - * @var bool - */ - public $newline; + /** + * Position the left corner of this box on the page(expressed in points). The default is the current position. + * + * @var mixed + */ + public $left; + /** + * Position the top corner of this box on the page(expressed in points). the default is the current position + * + * @var mixed + */ + public $top; + /** + * After this box is finished rendering, should the next section of text start immediately after the this box or should it start on a new line under this box. 0 = no new line, 1 = force new line. Default is 0 + * + * @var bool + */ + public $newline; - /** @var bool Unused? */ - public $pagecheck; + /** @var bool Unused? */ + public $pagecheck; - /** @var bool Whether to print a border */ - public $border; + /** @var bool Whether to print a border */ + public $border; - /** - * Style of rendering - * - * <ul> - * <li>D or empty string: Draw (default).</li> - * <li>F: Fill.</li> - * <li>DF or FD: Draw and fill.</li> - * <li>CNZ: Clipping mode (using the even-odd rule to determine which regions lie inside the clipping path).</li> - *<li>CEO: Clipping mode (using the nonzero winding number rule to determine which regions lie inside the clipping path).</li> - * </ul> - * - * @var string - */ - public $style; + /** + * Style of rendering + * + * <ul> + * <li>D or empty string: Draw (default).</li> + * <li>F: Fill.</li> + * <li>DF or FD: Draw and fill.</li> + * <li>CNZ: Clipping mode (using the even-odd rule to determine which regions lie inside the clipping path).</li> + *<li>CEO: Clipping mode (using the nonzero winding number rule to determine which regions lie inside the clipping path).</li> + * </ul> + * + * @var string + */ + public $style; - /** - * @var array Border style of rectangle. Array with keys among the following: - * <ul> - * <li>all: Line style of all borders. Array like for {@link SetLineStyle SetLineStyle}.</li> - * <li>L, T, R, B or combinations: Line style of left, top, right or bottom border. Array like for {@link SetLineStyle SetLineStyle}.</li> - * </ul> - * Not yet in use - * var $borderstyle; - */ + /** + * @var array Border style of rectangle. Array with keys among the following: + * <ul> + * <li>all: Line style of all borders. Array like for {@link SetLineStyle SetLineStyle}.</li> + * <li>L, T, R, B or combinations: Line style of left, top, right or bottom border. Array like for {@link SetLineStyle SetLineStyle}.</li> + * </ul> + * Not yet in use + * var $borderstyle; + */ - /** - * The starting height of this cell. If the text wraps the height will automatically be adjusted - * - * @var float - */ - public $height; - /** - * Setting the width to 0 will make it the width from the current location to the right margin - * - * @var float - */ - public $width; - /** - * Use cell padding or not - * - * @var bool - */ - public $padding; - /** - * Resets this box last height after it’s done - */ - public $reseth; + /** + * The starting height of this cell. If the text wraps the height will automatically be adjusted + * + * @var float + */ + public $height; + /** + * Setting the width to 0 will make it the width from the current location to the right margin + * + * @var float + */ + public $width; + /** + * Use cell padding or not + * + * @var bool + */ + public $padding; + /** + * Resets this box last height after it’s done + */ + public $reseth; - /** - * TextBox - Element - Base - * - * @param float $width Text box width - * @param float $height Text box height - * @param bool $border - * @param string $bgcolor Background color code in HTML - * @param bool $newline - * @param mixed $left - * @param mixed $top - * @param bool $pagecheck - * @param string $style - * @param bool $fill - * @param bool $padding - * @param bool $reseth - */ - public function __construct( - $width, $height, $border, $bgcolor, $newline, $left, $top, $pagecheck, $style, $fill, $padding, $reseth - ) { - $this->border = $border; - $this->bgcolor = $bgcolor; - $this->fill = $fill; - $this->height = $height; - $this->left = $left; - $this->newline = $newline; - $this->pagecheck = $pagecheck; - $this->style = $style; - $this->top = $top; - $this->width = $width; - $this->padding = $padding; - $this->reseth = $reseth; + /** + * TextBox - Element - Base + * + * @param float $width Text box width + * @param float $height Text box height + * @param bool $border + * @param string $bgcolor Background color code in HTML + * @param bool $newline + * @param mixed $left + * @param mixed $top + * @param bool $pagecheck + * @param string $style + * @param bool $fill + * @param bool $padding + * @param bool $reseth + */ + public function __construct( + $width, $height, $border, $bgcolor, $newline, $left, $top, $pagecheck, $style, $fill, $padding, $reseth + ) + { + $this->border = $border; + $this->bgcolor = $bgcolor; + $this->fill = $fill; + $this->height = $height; + $this->left = $left; + $this->newline = $newline; + $this->pagecheck = $pagecheck; + $this->style = $style; + $this->top = $top; + $this->width = $width; + $this->padding = $padding; + $this->reseth = $reseth; - return 0; - } + return 0; + } - /** - * Add an element to the TextBox - * - * @param object|string $element - */ - public function addElement($element) { - $this->elements[] = $element; - } + /** + * Add an element to the TextBox + * + * @param object|string $element + */ + public function addElement($element) + { + $this->elements[] = $element; + } } diff --git a/app/Report/ReportHtml.php b/app/Report/ReportHtml.php index 06aa160e5a..bdf31f9606 100644 --- a/app/Report/ReportHtml.php +++ b/app/Report/ReportHtml.php @@ -22,712 +22,759 @@ use Fisharebest\Webtrees\MediaFile; /** * Class ReportHtml */ -class ReportHtml extends ReportBase { - /** - * Cell padding - * - * @var int - */ - public $cPadding = 2; +class ReportHtml extends ReportBase +{ + /** + * Cell padding + * + * @var int + */ + public $cPadding = 2; - /** - * Cell height ratio - * - * @var float - */ - public $cellHeightRatio = 1.8; + /** + * Cell height ratio + * + * @var float + */ + public $cellHeightRatio = 1.8; - /** - * Current horizontal position - * - * @var float - */ - public $X = 0.0; + /** + * Current horizontal position + * + * @var float + */ + public $X = 0.0; - /** - * Current vertical position - * - * @var float - */ - public $Y = 0.0; + /** + * Current vertical position + * + * @var float + */ + public $Y = 0.0; - /** - * Currently used style name - * - * @var string - */ - public $currentStyle = ''; + /** + * Currently used style name + * + * @var string + */ + public $currentStyle = ''; - /** - * Page number counter - * - * @var int - */ - public $pageN = 1; + /** + * Page number counter + * + * @var int + */ + public $pageN = 1; - /** - * Store the page width without left and right margins - * - * In HTML, we don't need this - * - * @var float - */ - public $noMarginWidth = 0.0; + /** + * Store the page width without left and right margins + * + * In HTML, we don't need this + * + * @var float + */ + public $noMarginWidth = 0.0; - /** - * Last cell height - * - * @var float - */ - public $lastCellHeight = 0.0; + /** + * Last cell height + * + * @var float + */ + public $lastCellHeight = 0.0; - /** - * LTR or RTL alignement; "left" on LTR, "right" on RTL - * Used in <div> - * - * @var string - */ - public $alignRTL = 'left'; + /** + * LTR or RTL alignement; "left" on LTR, "right" on RTL + * Used in <div> + * + * @var string + */ + public $alignRTL = 'left'; - /** - * LTR or RTL entity - * - * @var string - */ - public $entityRTL = '‎'; + /** + * LTR or RTL entity + * + * @var string + */ + public $entityRTL = '‎'; - /** - * Largest Font Height is used by TextBox etc. - * - * Use this to calculate a the text height. - * This makes sure that the text fits into the cell/box when different font sizes are used - * - * @var int - */ - public $largestFontHeight = 0; + /** + * Largest Font Height is used by TextBox etc. + * + * Use this to calculate a the text height. + * This makes sure that the text fits into the cell/box when different font sizes are used + * + * @var int + */ + public $largestFontHeight = 0; - /** - * Keep track of the highest Y position - * - * Used with Header div / Body div / Footer div / "addpage" / The bottom of the last image etc. - * - * @var float - */ - public $maxY = 0; + /** + * Keep track of the highest Y position + * + * Used with Header div / Body div / Footer div / "addpage" / The bottom of the last image etc. + * + * @var float + */ + public $maxY = 0; - /** @var ReportBaseElement[] Array of elements in the header */ - public $headerElements = []; + /** @var ReportBaseElement[] Array of elements in the header */ + public $headerElements = []; - /** @var ReportBaseElement[] Array of elements in the page header */ - public $pageHeaderElements = []; + /** @var ReportBaseElement[] Array of elements in the page header */ + public $pageHeaderElements = []; - /** @var ReportBaseElement[] Array of elements in the footer */ - public $footerElements = []; + /** @var ReportBaseElement[] Array of elements in the footer */ + public $footerElements = []; - /** @var ReportBaseElement[] Array of elements in the body */ - public $bodyElements = []; + /** @var ReportBaseElement[] Array of elements in the body */ + public $bodyElements = []; - /** @var ReportBaseFootnote[] Array of elements in the footer notes */ - public $printedfootnotes = []; + /** @var ReportBaseFootnote[] Array of elements in the footer notes */ + public $printedfootnotes = []; - /** - * HTML Setup - ReportHtml - */ - public function setup() { - parent::setup(); + /** + * HTML Setup - ReportHtml + */ + public function setup() + { + parent::setup(); - // Setting up the correct dimensions if Portrait (default) or Landscape - if ($this->orientation == 'landscape') { - $tmpw = $this->pagew; - $this->pagew = $this->pageh; - $this->pageh = $tmpw; - } - // Store the pagewidth without margins - $this->noMarginWidth = (int) ($this->pagew - $this->leftmargin - $this->rightmargin); - // If RTL - if ($this->rtl) { - $this->alignRTL = 'right'; - $this->entityRTL = '‏'; - } - // Change the default HTML font name - $this->defaultFont = 'Arial'; + // Setting up the correct dimensions if Portrait (default) or Landscape + if ($this->orientation == 'landscape') { + $tmpw = $this->pagew; + $this->pagew = $this->pageh; + $this->pageh = $tmpw; + } + // Store the pagewidth without margins + $this->noMarginWidth = (int)($this->pagew - $this->leftmargin - $this->rightmargin); + // If RTL + if ($this->rtl) { + $this->alignRTL = 'right'; + $this->entityRTL = '‏'; + } + // Change the default HTML font name + $this->defaultFont = 'Arial'; - if ($this->showGenText) { - // The default style name for Generated by.... is 'genby' - $element = new ReportHtmlCell(0, 10, 0, 'C', '', 'genby', 1, '.', '.', 0, 0, '', '', true); - $element->addText($this->generatedby); - $element->setUrl(parent::WT_URL); - $this->footerElements[] = $element; - } - } + if ($this->showGenText) { + // The default style name for Generated by.... is 'genby' + $element = new ReportHtmlCell(0, 10, 0, 'C', '', 'genby', 1, '.', '.', 0, 0, '', '', true); + $element->addText($this->generatedby); + $element->setUrl(parent::WT_URL); + $this->footerElements[] = $element; + } + } - /** - * Add an element. - * - * @param $element - */ - public function addElement($element) { - if ($this->processing == 'B') { - $this->bodyElements[] = $element; - } elseif ($this->processing == 'H') { - $this->headerElements[] = $element; - } elseif ($this->processing == 'F') { - $this->footerElements[] = $element; - } - } + /** + * Add an element. + * + * @param $element + */ + public function addElement($element) + { + if ($this->processing == 'B') { + $this->bodyElements[] = $element; + } elseif ($this->processing == 'H') { + $this->headerElements[] = $element; + } elseif ($this->processing == 'F') { + $this->footerElements[] = $element; + } + } - /** - * Generate the page header - */ - public function runPageHeader() { - foreach ($this->pageHeaderElements as $element) { - if (is_object($element)) { - $element->render($this); - } elseif (is_string($element) && $element == 'footnotetexts') { - $this->footnotes(); - } elseif (is_string($element) && $element == 'addpage') { - $this->addPage(); - } - } - } + /** + * Generate the page header + */ + public function runPageHeader() + { + foreach ($this->pageHeaderElements as $element) { + if (is_object($element)) { + $element->render($this); + } elseif (is_string($element) && $element == 'footnotetexts') { + $this->footnotes(); + } elseif (is_string($element) && $element == 'addpage') { + $this->addPage(); + } + } + } - /** - * Generate footnotes - */ - public function footnotes() { - $this->currentStyle = ''; - if (!empty($this->printedfootnotes)) { - foreach ($this->printedfootnotes as $element) { - $element->renderFootnote($this); - } - } - } + /** + * Generate footnotes + */ + public function footnotes() + { + $this->currentStyle = ''; + if (!empty($this->printedfootnotes)) { + foreach ($this->printedfootnotes as $element) { + $element->renderFootnote($this); + } + } + } - /** - * Run the report. - */ - public function run() { - // Setting up the styles - echo '<style type="text/css">'; - echo '#bodydiv { font: 10px sans-serif;}'; - foreach ($this->Styles as $class => $style) { - echo '.', $class, ' { '; - if ($style['font'] == 'dejavusans') { - $style['font'] = $this->defaultFont; - } - echo 'font-family: ', $style['font'], '; '; - echo 'font-size: ', $style['size'], 'pt; '; - // Case-insensitive - if (stripos($style['style'], 'B') !== false) { - echo 'font-weight: bold; '; - } - if (stripos($style['style'], 'I') !== false) { - echo 'font-style: italic; '; - } - if (stripos($style['style'], 'U') !== false) { - echo 'text-decoration: underline; '; - } - if (stripos($style['style'], 'D') !== false) { - echo 'text-decoration: line-through; '; - } - echo '}', PHP_EOL; - } - unset($class, $style); - //-- header divider - echo '</style>', PHP_EOL; - echo '<div id="headermargin" style="position: relative; top: auto; height: ', $this->headermargin, 'pt; width: ', $this->noMarginWidth, 'pt;"></div>'; - echo '<div id="headerdiv" style="position: relative; top: auto; width: ', $this->noMarginWidth, 'pt;">'; - foreach ($this->headerElements as $element) { - if (is_object($element)) { - $element->render($this); - } elseif (is_string($element) && $element == 'footnotetexts') { - $this->footnotes(); - } elseif (is_string($element) && $element == 'addpage') { - $this->addPage(); - } - } - //-- body - echo '</div>'; - echo '<script>document.getElementById("headerdiv").style.height="', $this->topmargin - $this->headermargin - 6, 'pt";</script>'; - echo '<div id="bodydiv" style="position: relative; top: auto; width: ', $this->noMarginWidth, 'pt; height: 100%;">'; - $this->Y = 0; - $this->maxY = 0; - $this->runPageHeader(); - foreach ($this->bodyElements as $element) { - if (is_object($element)) { - $element->render($this); - } elseif (is_string($element) && $element == 'footnotetexts') { - $this->footnotes(); - } elseif (is_string($element) && $element == 'addpage') { - $this->addPage(); - } - } - //-- footer - echo '</div>'; - echo '<script>document.getElementById("bodydiv").style.height="', $this->maxY, 'pt";</script>'; - echo '<div id="bottommargin" style="position: relative; top: auto; height: ', $this->bottommargin - $this->footermargin, 'pt;width:', $this->noMarginWidth, 'pt;"></div>'; - echo '<div id="footerdiv" style="position: relative; top: auto; width: ', $this->noMarginWidth, 'pt;height:auto;">'; - $this->Y = 0; - $this->X = 0; - $this->maxY = 0; - foreach ($this->footerElements as $element) { - if (is_object($element)) { - $element->render($this); - } elseif (is_string($element) && $element == 'footnotetexts') { - $this->footnotes(); - } elseif (is_string($element) && $element == 'addpage') { - $this->addPage(); - } - } - echo '</div>'; - echo '<script>document.getElementById("footerdiv").style.height="', $this->maxY, 'pt";</script>'; - echo '<div id="footermargin" style="position: relative; top: auto; height: ', $this->footermargin, 'pt;width:', $this->noMarginWidth, 'pt;"></div>'; - } + /** + * Run the report. + */ + public function run() + { + // Setting up the styles + echo '<style type="text/css">'; + echo '#bodydiv { font: 10px sans-serif;}'; + foreach ($this->Styles as $class => $style) { + echo '.', $class, ' { '; + if ($style['font'] == 'dejavusans') { + $style['font'] = $this->defaultFont; + } + echo 'font-family: ', $style['font'], '; '; + echo 'font-size: ', $style['size'], 'pt; '; + // Case-insensitive + if (stripos($style['style'], 'B') !== false) { + echo 'font-weight: bold; '; + } + if (stripos($style['style'], 'I') !== false) { + echo 'font-style: italic; '; + } + if (stripos($style['style'], 'U') !== false) { + echo 'text-decoration: underline; '; + } + if (stripos($style['style'], 'D') !== false) { + echo 'text-decoration: line-through; '; + } + echo '}', PHP_EOL; + } + unset($class, $style); + //-- header divider + echo '</style>', PHP_EOL; + echo '<div id="headermargin" style="position: relative; top: auto; height: ', $this->headermargin, 'pt; width: ', $this->noMarginWidth, 'pt;"></div>'; + echo '<div id="headerdiv" style="position: relative; top: auto; width: ', $this->noMarginWidth, 'pt;">'; + foreach ($this->headerElements as $element) { + if (is_object($element)) { + $element->render($this); + } elseif (is_string($element) && $element == 'footnotetexts') { + $this->footnotes(); + } elseif (is_string($element) && $element == 'addpage') { + $this->addPage(); + } + } + //-- body + echo '</div>'; + echo '<script>document.getElementById("headerdiv").style.height="', $this->topmargin - $this->headermargin - 6, 'pt";</script>'; + echo '<div id="bodydiv" style="position: relative; top: auto; width: ', $this->noMarginWidth, 'pt; height: 100%;">'; + $this->Y = 0; + $this->maxY = 0; + $this->runPageHeader(); + foreach ($this->bodyElements as $element) { + if (is_object($element)) { + $element->render($this); + } elseif (is_string($element) && $element == 'footnotetexts') { + $this->footnotes(); + } elseif (is_string($element) && $element == 'addpage') { + $this->addPage(); + } + } + //-- footer + echo '</div>'; + echo '<script>document.getElementById("bodydiv").style.height="', $this->maxY, 'pt";</script>'; + echo '<div id="bottommargin" style="position: relative; top: auto; height: ', $this->bottommargin - $this->footermargin, 'pt;width:', $this->noMarginWidth, 'pt;"></div>'; + echo '<div id="footerdiv" style="position: relative; top: auto; width: ', $this->noMarginWidth, 'pt;height:auto;">'; + $this->Y = 0; + $this->X = 0; + $this->maxY = 0; + foreach ($this->footerElements as $element) { + if (is_object($element)) { + $element->render($this); + } elseif (is_string($element) && $element == 'footnotetexts') { + $this->footnotes(); + } elseif (is_string($element) && $element == 'addpage') { + $this->addPage(); + } + } + echo '</div>'; + echo '<script>document.getElementById("footerdiv").style.height="', $this->maxY, 'pt";</script>'; + echo '<div id="footermargin" style="position: relative; top: auto; height: ', $this->footermargin, 'pt;width:', $this->noMarginWidth, 'pt;"></div>'; + } - /** - * Create a new Cell object - ReportHtml - * - * @param int $width cell width (expressed in points) - * @param int $height cell height (expressed in points) - * @param mixed $border Border style - * @param string $align Text alignement - * @param string $bgcolor Background color code - * @param string $style The name of the text style - * @param int $ln Indicates where the current position should go after the call - * @param mixed $top Y-position - * @param mixed $left X-position - * @param int $fill Indicates if the cell background must be painted (1) or transparent (0). Default value: 0. - * @param int $stretch Stretch carachter mode - * @param string $bocolor Border color - * @param string $tcolor Text color - * @param bool $reseth - * - * @return object ReportHtmlCell - */ - public function createCell($width, $height, $border, $align, $bgcolor, $style, $ln, $top, $left, $fill, $stretch, $bocolor, $tcolor, $reseth) { - return new ReportHtmlCell($width, $height, $border, $align, $bgcolor, $style, $ln, $top, $left, $fill, $stretch, $bocolor, $tcolor, $reseth); - } + /** + * Create a new Cell object - ReportHtml + * + * @param int $width cell width (expressed in points) + * @param int $height cell height (expressed in points) + * @param mixed $border Border style + * @param string $align Text alignement + * @param string $bgcolor Background color code + * @param string $style The name of the text style + * @param int $ln Indicates where the current position should go after the call + * @param mixed $top Y-position + * @param mixed $left X-position + * @param int $fill Indicates if the cell background must be painted (1) or transparent (0). Default value: 0. + * @param int $stretch Stretch carachter mode + * @param string $bocolor Border color + * @param string $tcolor Text color + * @param bool $reseth + * + * @return object ReportHtmlCell + */ + public function createCell($width, $height, $border, $align, $bgcolor, $style, $ln, $top, $left, $fill, $stretch, $bocolor, $tcolor, $reseth) + { + return new ReportHtmlCell($width, $height, $border, $align, $bgcolor, $style, $ln, $top, $left, $fill, $stretch, $bocolor, $tcolor, $reseth); + } - /** - * Create a text box. - * - * @param $width - * @param $height - * @param $border - * @param $bgcolor - * @param $newline - * @param $left - * @param $top - * @param $pagecheck - * @param $style - * @param $fill - * @param $padding - * @param $reseth - * - * @return ReportHtmlTextbox - */ - public function createTextBox($width, $height, $border, $bgcolor, $newline, $left, $top, $pagecheck, $style, $fill, $padding, $reseth) { - return new ReportHtmlTextbox($width, $height, $border, $bgcolor, $newline, $left, $top, $pagecheck, $style, $fill, $padding, $reseth); - } + /** + * Create a text box. + * + * @param $width + * @param $height + * @param $border + * @param $bgcolor + * @param $newline + * @param $left + * @param $top + * @param $pagecheck + * @param $style + * @param $fill + * @param $padding + * @param $reseth + * + * @return ReportHtmlTextbox + */ + public function createTextBox($width, $height, $border, $bgcolor, $newline, $left, $top, $pagecheck, $style, $fill, $padding, $reseth) + { + return new ReportHtmlTextbox($width, $height, $border, $bgcolor, $newline, $left, $top, $pagecheck, $style, $fill, $padding, $reseth); + } - /** - * Create a text element. - * - * @param $style - * @param $color - * - * @return ReportHtmlText - */ - public function createText($style, $color) { - return new ReportHtmlText($style, $color); - } + /** + * Create a text element. + * + * @param $style + * @param $color + * + * @return ReportHtmlText + */ + public function createText($style, $color) + { + return new ReportHtmlText($style, $color); + } - /** - * Create a footnote. - * - * @param string $style - * - * @return ReportHtmlFootnote - */ - public function createFootnote($style = '') { - return new ReportHtmlFootnote($style); - } + /** + * Create a footnote. + * + * @param string $style + * + * @return ReportHtmlFootnote + */ + public function createFootnote($style = '') + { + return new ReportHtmlFootnote($style); + } - /** - * Create a page header. - * - * @return ReportHtmlPageheader - */ - public function createPageHeader() { - return new ReportHtmlPageheader; - } + /** + * Create a page header. + * + * @return ReportHtmlPageheader + */ + public function createPageHeader() + { + return new ReportHtmlPageheader; + } - /** - * Create an image. - * - * @param $file - * @param $x - * @param $y - * @param $w - * @param $h - * @param $align - * @param $ln - * - * @return ReportHtmlImage - */ - public function createImage($file, $x, $y, $w, $h, $align, $ln) { - return new ReportHtmlImage($file, $x, $y, $w, $h, $align, $ln); - } + /** + * Create an image. + * + * @param $file + * @param $x + * @param $y + * @param $w + * @param $h + * @param $align + * @param $ln + * + * @return ReportHtmlImage + */ + public function createImage($file, $x, $y, $w, $h, $align, $ln) + { + return new ReportHtmlImage($file, $x, $y, $w, $h, $align, $ln); + } - /** - * Create an image. - * - * @param MediaFile $media_file - * @param $x - * @param $y - * @param $w - * @param $h - * @param $align - * @param $ln - * - * @return ReportHtmlImage - */ - public function createImageFromObject(MediaFile $media_file, $x, $y, $w, $h, $align, $ln) { - return new ReportHtmlImage($media_file->imageUrl($w, $h, ''), $x, $y, $w, $h, $align, $ln); - } + /** + * Create an image. + * + * @param MediaFile $media_file + * @param $x + * @param $y + * @param $w + * @param $h + * @param $align + * @param $ln + * + * @return ReportHtmlImage + */ + public function createImageFromObject(MediaFile $media_file, $x, $y, $w, $h, $align, $ln) + { + return new ReportHtmlImage($media_file->imageUrl($w, $h, ''), $x, $y, $w, $h, $align, $ln); + } - /** - * Create a line. - * - * @param $x1 - * @param $y1 - * @param $x2 - * @param $y2 - * - * @return ReportHtmlLine - */ - public function createLine($x1, $y1, $x2, $y2) { - return new ReportHtmlLine($x1, $y1, $x2, $y2); - } + /** + * Create a line. + * + * @param $x1 + * @param $y1 + * @param $x2 + * @param $y2 + * + * @return ReportHtmlLine + */ + public function createLine($x1, $y1, $x2, $y2) + { + return new ReportHtmlLine($x1, $y1, $x2, $y2); + } - /** - * Create an HTML element. - * - * @param $tag - * @param $attrs - * - * @return ReportHtmlHtml - */ - public function createHTML($tag, $attrs) { - return new ReportHtmlHtml($tag, $attrs); - } + /** + * Create an HTML element. + * + * @param $tag + * @param $attrs + * + * @return ReportHtmlHtml + */ + public function createHTML($tag, $attrs) + { + return new ReportHtmlHtml($tag, $attrs); + } - /** - * Clear the Header - ReportHtml - */ - public function clearHeader() { - $this->headerElements = []; - } + /** + * Clear the Header - ReportHtml + */ + public function clearHeader() + { + $this->headerElements = []; + } - /** - * Update the Page Number and set a new Y if max Y is larger - ReportHtml - */ - public function addPage() { - $this->pageN++; - // Add a little margin to max Y "between pages" - $this->maxY += 10; - // If Y is still heigher by any reason... - if ($this->maxY < $this->Y) { - // ... update max Y - $this->maxY = $this->Y; - } // else update Y so that nothing will be overwritten, like images or cells... - else { - $this->Y = $this->maxY; - } - } + /** + * Update the Page Number and set a new Y if max Y is larger - ReportHtml + */ + public function addPage() + { + $this->pageN++; + // Add a little margin to max Y "between pages" + $this->maxY += 10; + // If Y is still heigher by any reason... + if ($this->maxY < $this->Y) { + // ... update max Y + $this->maxY = $this->Y; + } // else update Y so that nothing will be overwritten, like images or cells... + else { + $this->Y = $this->maxY; + } + } - /** - * Uppdate max Y to keep track it incase of a pagebreak - ReportHtml - * - * @param float $y - */ - public function addMaxY($y) { - if ($this->maxY < $y) { - $this->maxY = $y; - } - } + /** + * Uppdate max Y to keep track it incase of a pagebreak - ReportHtml + * + * @param float $y + */ + public function addMaxY($y) + { + if ($this->maxY < $y) { + $this->maxY = $y; + } + } - /** - * Add a page header. - * - * @param $element - * - * @return int - */ - public function addPageHeader($element) { - $this->pageHeaderElements[] = $element; + /** + * Add a page header. + * + * @param $element + * + * @return int + */ + public function addPageHeader($element) + { + $this->pageHeaderElements[] = $element; - return count($this->headerElements) - 1; - } + return count($this->headerElements) - 1; + } - /** - * Checks the Footnote and numbers them - ReportHtml - * - * @param object $footnote - * - * @return bool false if not numbered before | object if already numbered - */ - public function checkFootnote($footnote) { - $ct = count($this->printedfootnotes); - $i = 0; - $val = $footnote->getValue(); - while ($i < $ct) { - if ($this->printedfootnotes[$i]->getValue() == $val) { - // If this footnote already exist then set up the numbers for this object - $footnote->setNum($i + 1); - $footnote->setAddlink($i + 1); + /** + * Checks the Footnote and numbers them - ReportHtml + * + * @param object $footnote + * + * @return bool false if not numbered before | object if already numbered + */ + public function checkFootnote($footnote) + { + $ct = count($this->printedfootnotes); + $i = 0; + $val = $footnote->getValue(); + while ($i < $ct) { + if ($this->printedfootnotes[$i]->getValue() == $val) { + // If this footnote already exist then set up the numbers for this object + $footnote->setNum($i + 1); + $footnote->setAddlink($i + 1); - return $this->printedfootnotes[$i]; - } - $i++; - } - // If this Footnote has not been set up yet - $footnote->setNum($ct + 1); - $footnote->setAddlink($ct + 1); - $this->printedfootnotes[] = $footnote; + return $this->printedfootnotes[$i]; + } + $i++; + } + // If this Footnote has not been set up yet + $footnote->setNum($ct + 1); + $footnote->setAddlink($ct + 1); + $this->printedfootnotes[] = $footnote; - return false; - } + return false; + } - /** - * Clear the Page Header - ReportHtml - */ - public function clearPageHeader() { - $this->pageHeaderElements = []; - } + /** + * Clear the Page Header - ReportHtml + */ + public function clearPageHeader() + { + $this->pageHeaderElements = []; + } - /** - * Count the number of lines - ReportHtml - * - * @param string $str - * - * @return int Number of lines. 0 if empty line - */ - public function countLines($str) { - if ($str == '') { - return 0; - } + /** + * Count the number of lines - ReportHtml + * + * @param string $str + * + * @return int Number of lines. 0 if empty line + */ + public function countLines($str) + { + if ($str == '') { + return 0; + } - return (substr_count($str, "\n") + 1); - } + return (substr_count($str, "\n") + 1); + } - /** - * Get the current style. - * - * @return string - */ - public function getCurrentStyle() { - return $this->currentStyle; - } + /** + * Get the current style. + * + * @return string + */ + public function getCurrentStyle() + { + return $this->currentStyle; + } - /** - * Get the current style height. - * - * @return int - */ - public function getCurrentStyleHeight() { - if (empty($this->currentStyle)) { - return $this->defaultFontSize; - } - $style = $this->getStyle($this->currentStyle); + /** + * Get the current style height. + * + * @return int + */ + public function getCurrentStyleHeight() + { + if (empty($this->currentStyle)) { + return $this->defaultFontSize; + } + $style = $this->getStyle($this->currentStyle); - return $style['size']; - } + return $style['size']; + } - /** - * Get the current footnotes height. - * - * @param $cellWidth - * - * @return int - */ - public function getFootnotesHeight($cellWidth) { - $h = 0; - foreach ($this->printedfootnotes as $element) { - $h += $element->getFootnoteHeight($this, $cellWidth); - } + /** + * Get the current footnotes height. + * + * @param $cellWidth + * + * @return int + */ + public function getFootnotesHeight($cellWidth) + { + $h = 0; + foreach ($this->printedfootnotes as $element) { + $h += $element->getFootnoteHeight($this, $cellWidth); + } - return $h; - } + return $h; + } - /** - * Get the maximum width from current position to the margin - ReportHtml - * - * @return float - */ - public function getRemainingWidth() { - return $this->noMarginWidth - $this->X; - } + /** + * Get the maximum width from current position to the margin - ReportHtml + * + * @return float + */ + public function getRemainingWidth() + { + return $this->noMarginWidth - $this->X; + } - /** - * Get the page height. - * - * @return float - */ - public function getPageHeight() { - return $this->pageh - $this->topmargin; - } + /** + * Get the page height. + * + * @return float + */ + public function getPageHeight() + { + return $this->pageh - $this->topmargin; + } - /** - * Get the width of a string. - * - * @param $text - * - * @return int - */ - public function getStringWidth($text) { - $style = $this->getStyle($this->currentStyle); + /** + * Get the width of a string. + * + * @param $text + * + * @return int + */ + public function getStringWidth($text) + { + $style = $this->getStyle($this->currentStyle); - return mb_strlen($text) * ($style['size'] / 2); - } + return mb_strlen($text) * ($style['size'] / 2); + } - /** - * Get a text height in points - ReportHtml - * - * @param $str - * - * @return int - */ - public function getTextCellHeight($str) { - // Count the number of lines to calculate the height - $nl = $this->countLines($str); - // Calculate the cell height - return ceil(($this->getCurrentStyleHeight() * $this->cellHeightRatio) * $nl); - } + /** + * Get a text height in points - ReportHtml + * + * @param $str + * + * @return int + */ + public function getTextCellHeight($str) + { + // Count the number of lines to calculate the height + $nl = $this->countLines($str); - /** - * Get the current X position - ReportHtml - * - * @return float - */ - public function getX() { - return $this->X; - } + // Calculate the cell height + return ceil(($this->getCurrentStyleHeight() * $this->cellHeightRatio) * $nl); + } - /** - * Get the current Y position - ReportHtml - * - * @return float - */ - public function getY() { - return $this->Y; - } + /** + * Get the current X position - ReportHtml + * + * @return float + */ + public function getX() + { + return $this->X; + } - /** - * Get the current page number - ReportHtml - * - * @return int - */ - public function pageNo() { - return $this->pageN; - } + /** + * Get the current Y position - ReportHtml + * + * @return float + */ + public function getY() + { + return $this->Y; + } - /** - * Set the current style. - * - * @param $s - */ - public function setCurrentStyle($s) { - $this->currentStyle = $s; - } + /** + * Get the current page number - ReportHtml + * + * @return int + */ + public function pageNo() + { + return $this->pageN; + } - /** - * Set the X position - ReportHtml - * - * @param float $x - */ - public function setX($x) { - $this->X = $x; - } + /** + * Set the current style. + * + * @param $s + */ + public function setCurrentStyle($s) + { + $this->currentStyle = $s; + } - /** - * Set the Y position - ReportHtml - * - * Also updates Max Y position - * - * @param float $y - */ - public function setY($y) { - $this->Y = $y; - if ($this->maxY < $y) { - $this->maxY = $y; - } - } + /** + * Set the X position - ReportHtml + * + * @param float $x + */ + public function setX($x) + { + $this->X = $x; + } - /** - * Set the X and Y position - ReportHtml - * - * Also updates Max Y position - * - * @param float $x - * @param float $y - */ - public function setXy($x, $y) { - $this->setX($x); - $this->setY($y); - } + /** + * Set the Y position - ReportHtml + * + * Also updates Max Y position + * + * @param float $y + */ + public function setY($y) + { + $this->Y = $y; + if ($this->maxY < $y) { + $this->maxY = $y; + } + } - /** - * Wrap text - ReportHtml - * - * @param string $str Text to wrap - * @param int $width Width in points the text has to fit into - * - * @return string - */ - public function textWrap($str, $width) { - // Calculate the line width - $lw = (int) ($width / ($this->getCurrentStyleHeight() / 2)); - // Wordwrap each line - $lines = explode("\n", $str); - // Line Feed counter - $lfct = count($lines); - $wraptext = ''; - foreach ($lines as $line) { - $wtext = FunctionsRtl::utf8WordWrap($line, $lw, "\n", true); - $wraptext .= $wtext; - // Add a new line as long as it’s not the last line - if ($lfct > 1) { - $wraptext .= "\n"; - } - $lfct--; - } + /** + * Set the X and Y position - ReportHtml + * + * Also updates Max Y position + * + * @param float $x + * @param float $y + */ + public function setXy($x, $y) + { + $this->setX($x); + $this->setY($y); + } - return $wraptext; - } + /** + * Wrap text - ReportHtml + * + * @param string $str Text to wrap + * @param int $width Width in points the text has to fit into + * + * @return string + */ + public function textWrap($str, $width) + { + // Calculate the line width + $lw = (int)($width / ($this->getCurrentStyleHeight() / 2)); + // Wordwrap each line + $lines = explode("\n", $str); + // Line Feed counter + $lfct = count($lines); + $wraptext = ''; + foreach ($lines as $line) { + $wtext = FunctionsRtl::utf8WordWrap($line, $lw, "\n", true); + $wraptext .= $wtext; + // Add a new line as long as it’s not the last line + if ($lfct > 1) { + $wraptext .= "\n"; + } + $lfct--; + } - /** - * Write text - ReportHtml - * - * @param string $text Text to print - * @param string $color HTML RGB color code (Ex: #001122) - * @param bool $useclass - */ - public function write($text, $color = '', $useclass = true) { - $style = $this->getStyle($this->getCurrentStyle()); - $htmlcode = '<span dir="' . I18N::direction() . '"'; - if ($useclass) { - $htmlcode .= ' class="' . $style['name'] . '"'; - } - if (!empty($color)) { - // Check if Text Color is set and if it’s valid HTML color - if (preg_match('/#?(..)(..)(..)/', $color)) { - $htmlcode .= ' style="color:' . $color . ';"'; - } - } + return $wraptext; + } - $htmlcode .= '>' . $text . '</span>'; - $htmlcode = str_replace(["\n", '> ', ' <'], ['<br>', '> ', ' <'], $htmlcode); - echo $htmlcode; - } + /** + * Write text - ReportHtml + * + * @param string $text Text to print + * @param string $color HTML RGB color code (Ex: #001122) + * @param bool $useclass + */ + public function write($text, $color = '', $useclass = true) + { + $style = $this->getStyle($this->getCurrentStyle()); + $htmlcode = '<span dir="' . I18N::direction() . '"'; + if ($useclass) { + $htmlcode .= ' class="' . $style['name'] . '"'; + } + if (!empty($color)) { + // Check if Text Color is set and if it’s valid HTML color + if (preg_match('/#?(..)(..)(..)/', $color)) { + $htmlcode .= ' style="color:' . $color . ';"'; + } + } + + $htmlcode .= '>' . $text . '</span>'; + $htmlcode = str_replace([ + "\n", + '> ', + ' <', + ], [ + '<br>', + '> ', + ' <', + ], $htmlcode); + echo $htmlcode; + } } diff --git a/app/Report/ReportHtmlCell.php b/app/Report/ReportHtmlCell.php index b066f3867a..4ba66ca0b2 100644 --- a/app/Report/ReportHtmlCell.php +++ b/app/Report/ReportHtmlCell.php @@ -18,177 +18,185 @@ namespace Fisharebest\Webtrees\Report; /** * Class ReportHtmlCell */ -class ReportHtmlCell extends ReportBaseCell { - /** - * HTML Cell renderer - * - * @param ReportHtml $renderer - */ - public function render($renderer) { - if (strpos($this->text, '{{:ptp:}}') !== false) { - return; - } - $temptext = str_replace('#PAGENUM#', $renderer->pageNo(), $this->text); - // underline «title» part of Source item - $temptext = str_replace(['«', '»'], ['<u>', '</u>'], $temptext); +class ReportHtmlCell extends ReportBaseCell +{ + /** + * HTML Cell renderer + * + * @param ReportHtml $renderer + */ + public function render($renderer) + { + if (strpos($this->text, '{{:ptp:}}') !== false) { + return; + } + $temptext = str_replace('#PAGENUM#', $renderer->pageNo(), $this->text); + // underline «title» part of Source item + $temptext = str_replace([ + '«', + '»', + ], [ + '<u>', + '</u>', + ], $temptext); - // Setup the style name - if ($renderer->getCurrentStyle() != $this->styleName) { - $renderer->setCurrentStyle($this->styleName); - } + // Setup the style name + if ($renderer->getCurrentStyle() != $this->styleName) { + $renderer->setCurrentStyle($this->styleName); + } - // If (Future-feature-enable/disable cell padding) - $cP = $renderer->cPadding; + // If (Future-feature-enable/disable cell padding) + $cP = $renderer->cPadding; - // Adjust the positions - if ($this->left == '.') { - $this->left = $renderer->getX(); - } else { - $renderer->setX($this->left); - } + // Adjust the positions + if ($this->left == '.') { + $this->left = $renderer->getX(); + } else { + $renderer->setX($this->left); + } - if ($this->top == '.') { - $this->top = $renderer->getY(); - } else { - $renderer->setY($this->top); - } + if ($this->top == '.') { + $this->top = $renderer->getY(); + } else { + $renderer->setY($this->top); + } - // Start collecting the HTML code - echo '<div class="', $this->styleName, '" style="position:absolute;top:', $this->top, 'pt;'; - // Use Cell around padding to support RTL also - echo 'padding:', $cP, 'pt;'; - // LTR (left) or RTL (right) - echo $renderer->alignRTL, ':', $this->left, 'pt;'; - // Background color - if (!empty($this->bgcolor)) { - echo 'background-color:', $this->bgcolor, ';'; - } - // Border setup - $bpixX = 0; - $bpixY = 0; - if (!empty($this->border)) { - // Border all around - if ($this->border == 1) { - echo ' border:solid '; - if (!empty($this->bocolor)) { - echo $this->bocolor; - } else { - echo 'black'; - } - echo ' 1pt;'; - $bpixX = 1; - $bpixY = 1; - } else { - if (stripos($this->border, 'T') !== false) { - echo ' border-top:solid '; - if (!empty($this->bocolor)) { - echo $this->bocolor; - } else { - echo 'black'; - } - echo ' 1pt;'; - $bpixY = 1; - } - if (stripos($this->border, 'B') !== false) { - echo ' border-bottom:solid '; - if (!empty($this->bocolor)) { - echo $this->bocolor; - } else { - echo 'black'; - } - echo ' 1pt;'; - $bpixY = 1; - } - if (stripos($this->border, 'R') !== false) { - echo ' border-right:solid '; - if (!empty($this->bocolor)) { - echo $this->bocolor; - } else { - echo 'black'; - } - echo ' 1pt;'; - $bpixX = 1; - } - if (stripos($this->border, 'L') !== false) { - echo ' border-left:solid '; - if (!empty($this->bocolor)) { - echo $this->bocolor; - } else { - echo 'black'; - } - echo ' 1pt;'; - $bpixX = 1; - } - } - } - // Check the width if set to page wide OR set by xml to larger then page wide - if ($this->width == 0 || $this->width > $renderer->getRemainingWidth()) { - $this->width = $renderer->getRemainingWidth(); - } - // We have to calculate a different width for the padding, counting on both side - $cW = $this->width - ($cP * 2); + // Start collecting the HTML code + echo '<div class="', $this->styleName, '" style="position:absolute;top:', $this->top, 'pt;'; + // Use Cell around padding to support RTL also + echo 'padding:', $cP, 'pt;'; + // LTR (left) or RTL (right) + echo $renderer->alignRTL, ':', $this->left, 'pt;'; + // Background color + if (!empty($this->bgcolor)) { + echo 'background-color:', $this->bgcolor, ';'; + } + // Border setup + $bpixX = 0; + $bpixY = 0; + if (!empty($this->border)) { + // Border all around + if ($this->border == 1) { + echo ' border:solid '; + if (!empty($this->bocolor)) { + echo $this->bocolor; + } else { + echo 'black'; + } + echo ' 1pt;'; + $bpixX = 1; + $bpixY = 1; + } else { + if (stripos($this->border, 'T') !== false) { + echo ' border-top:solid '; + if (!empty($this->bocolor)) { + echo $this->bocolor; + } else { + echo 'black'; + } + echo ' 1pt;'; + $bpixY = 1; + } + if (stripos($this->border, 'B') !== false) { + echo ' border-bottom:solid '; + if (!empty($this->bocolor)) { + echo $this->bocolor; + } else { + echo 'black'; + } + echo ' 1pt;'; + $bpixY = 1; + } + if (stripos($this->border, 'R') !== false) { + echo ' border-right:solid '; + if (!empty($this->bocolor)) { + echo $this->bocolor; + } else { + echo 'black'; + } + echo ' 1pt;'; + $bpixX = 1; + } + if (stripos($this->border, 'L') !== false) { + echo ' border-left:solid '; + if (!empty($this->bocolor)) { + echo $this->bocolor; + } else { + echo 'black'; + } + echo ' 1pt;'; + $bpixX = 1; + } + } + } + // Check the width if set to page wide OR set by xml to larger then page wide + if ($this->width == 0 || $this->width > $renderer->getRemainingWidth()) { + $this->width = $renderer->getRemainingWidth(); + } + // We have to calculate a different width for the padding, counting on both side + $cW = $this->width - ($cP * 2); - // If there is any text - if (!empty($temptext)) { - // Wrap the text - $temptext = $renderer->textWrap($temptext, $cW); - $tmph = $renderer->getTextCellHeight($temptext); - // Add some cell padding - $this->height += $cP; - if ($tmph > $this->height) { - $this->height = $tmph; - } - } - // Check the last cell height and ajust with the current cell height - if ($renderer->lastCellHeight > $this->height) { - $this->height = $renderer->lastCellHeight; - } - echo ' width:', $cW - $bpixX, 'pt;height:', $this->height - $bpixY, 'pt;'; + // If there is any text + if (!empty($temptext)) { + // Wrap the text + $temptext = $renderer->textWrap($temptext, $cW); + $tmph = $renderer->getTextCellHeight($temptext); + // Add some cell padding + $this->height += $cP; + if ($tmph > $this->height) { + $this->height = $tmph; + } + } + // Check the last cell height and ajust with the current cell height + if ($renderer->lastCellHeight > $this->height) { + $this->height = $renderer->lastCellHeight; + } + echo ' width:', $cW - $bpixX, 'pt;height:', $this->height - $bpixY, 'pt;'; - // Text alignment - switch ($this->align) { - case 'C': - echo ' text-align:center;'; - break; - case 'L': - echo ' text-align:left;'; - break; - case 'R': - echo ' text-align:right;'; - break; - } + // Text alignment + switch ($this->align) { + case 'C': + echo ' text-align:center;'; + break; + case 'L': + echo ' text-align:left;'; + break; + case 'R': + echo ' text-align:right;'; + break; + } - // Print the collected HTML code - echo '">'; + // Print the collected HTML code + echo '">'; - // Print URL - if (!empty($this->url)) { - echo '<a href="', $this->url, '">'; - } - // Print any text if exists - if (!empty($temptext)) { - $renderer->write($temptext, $this->tcolor, false); - } - if (!empty($this->url)) { - echo '</a>'; - } - // Finish the cell printing and start to clean up - echo "</div>\n"; - // Where to place the next position - // -> Next to this cell in the same line - if ($this->newline == 0) { - $renderer->setXy($this->left + $this->width, $this->top); - $renderer->lastCellHeight = $this->height; - } // -> On a new line at the margin - Default - elseif ($this->newline == 1) { - $renderer->setXy(0, $renderer->getY() + $this->height + ($cP * 2)); - // Reset the last cell height for the next line - $renderer->lastCellHeight = 0; - } // -> On a new line at the end of this cell - elseif ($this->newline == 2) { - $renderer->setXy($renderer->getX() + $this->width, $renderer->getY() + $this->height + ($cP * 2)); - // Reset the last cell height for the next line - $renderer->lastCellHeight = 0; - } - } + // Print URL + if (!empty($this->url)) { + echo '<a href="', $this->url, '">'; + } + // Print any text if exists + if (!empty($temptext)) { + $renderer->write($temptext, $this->tcolor, false); + } + if (!empty($this->url)) { + echo '</a>'; + } + // Finish the cell printing and start to clean up + echo "</div>\n"; + // Where to place the next position + // -> Next to this cell in the same line + if ($this->newline == 0) { + $renderer->setXy($this->left + $this->width, $this->top); + $renderer->lastCellHeight = $this->height; + } // -> On a new line at the margin - Default + elseif ($this->newline == 1) { + $renderer->setXy(0, $renderer->getY() + $this->height + ($cP * 2)); + // Reset the last cell height for the next line + $renderer->lastCellHeight = 0; + } // -> On a new line at the end of this cell + elseif ($this->newline == 2) { + $renderer->setXy($renderer->getX() + $this->width, $renderer->getY() + $this->height + ($cP * 2)); + // Reset the last cell height for the next line + $renderer->lastCellHeight = 0; + } + } } diff --git a/app/Report/ReportHtmlFootnote.php b/app/Report/ReportHtmlFootnote.php index 5a000b1f97..596580fca0 100644 --- a/app/Report/ReportHtmlFootnote.php +++ b/app/Report/ReportHtmlFootnote.php @@ -18,150 +18,169 @@ namespace Fisharebest\Webtrees\Report; /** * class ReportHtmlFootnote */ -class ReportHtmlFootnote extends ReportBaseFootnote { - /** - * HTML Footnotes number renderer - * - * @param ReportHtml $renderer - */ - public function render($renderer) { - $renderer->setCurrentStyle('footnotenum'); - echo '<a href="#footnote', $this->num, '"><sup>'; - $renderer->write($renderer->entityRTL . $this->num); - echo "</sup></a>\n"; - } +class ReportHtmlFootnote extends ReportBaseFootnote +{ + /** + * HTML Footnotes number renderer + * + * @param ReportHtml $renderer + */ + public function render($renderer) + { + $renderer->setCurrentStyle('footnotenum'); + echo '<a href="#footnote', $this->num, '"><sup>'; + $renderer->write($renderer->entityRTL . $this->num); + echo "</sup></a>\n"; + } - /** - * Write the Footnote text - * Uses style name "footnote" by default - * - * @param ReportHtml $html - */ - public function renderFootnote($html) { - if ($html->getCurrentStyle() != $this->styleName) { - $html->setCurrentStyle($this->styleName); - } + /** + * Write the Footnote text + * Uses style name "footnote" by default + * + * @param ReportHtml $html + */ + public function renderFootnote($html) + { + if ($html->getCurrentStyle() != $this->styleName) { + $html->setCurrentStyle($this->styleName); + } - $temptext = str_replace('#PAGENUM#', $html->pageNo(), $this->text); - // underline «title» part of Source item - $temptext = str_replace(['«', '»'], ['<u>', '</u>'], $temptext); - echo "\n<div><a name=\"footnote", $this->num, '"></a>'; - $html->write($this->num . '. ' . $temptext); - echo '</div>'; + $temptext = str_replace('#PAGENUM#', $html->pageNo(), $this->text); + // underline «title» part of Source item + $temptext = str_replace([ + '«', + '»', + ], [ + '<u>', + '</u>', + ], $temptext); + echo "\n<div><a name=\"footnote", $this->num, '"></a>'; + $html->write($this->num . '. ' . $temptext); + echo '</div>'; - $html->setXy(0, $html->getY() + $this->getFootnoteHeight($html)); - } + $html->setXy(0, $html->getY() + $this->getFootnoteHeight($html)); + } - /** - * Calculates the Footnotes height - * - * @param ReportHtml $html - * @param int $cellWidth The width of the cell to use it for text wraping - * - * @return int Footnote height in points - */ - public function getFootnoteHeight($html, $cellWidth = 0) { - if ($html->getCurrentStyle() != $this->styleName) { - $html->setCurrentStyle($this->styleName); - } + /** + * Calculates the Footnotes height + * + * @param ReportHtml $html + * @param int $cellWidth The width of the cell to use it for text wraping + * + * @return int Footnote height in points + */ + public function getFootnoteHeight($html, $cellWidth = 0) + { + if ($html->getCurrentStyle() != $this->styleName) { + $html->setCurrentStyle($this->styleName); + } - if ($cellWidth > 0) { - $this->text = $html->textWrap($this->text, $cellWidth); - } - $this->text = $this->text . "\n\n"; - $ct = substr_count($this->text, "\n"); - $fsize = $html->getCurrentStyleHeight(); + if ($cellWidth > 0) { + $this->text = $html->textWrap($this->text, $cellWidth); + } + $this->text = $this->text . "\n\n"; + $ct = substr_count($this->text, "\n"); + $fsize = $html->getCurrentStyleHeight(); - return ($fsize * $ct) * $html->cellHeightRatio; - } + return ($fsize * $ct) * $html->cellHeightRatio; + } - /** - * Get the width of text - * Breaks up a text into lines if needed - * - * @param ReportHtml $html - * - * @return array - */ - public function getWidth($html) { - // Setup the style name - $html->setCurrentStyle('footnotenum'); + /** + * Get the width of text + * Breaks up a text into lines if needed + * + * @param ReportHtml $html + * + * @return array + */ + public function getWidth($html) + { + // Setup the style name + $html->setCurrentStyle('footnotenum'); - // Check for the largest font size in the box - $fsize = $html->getCurrentStyleHeight(); - if ($fsize > $html->largestFontHeight) { - $html->largestFontHeight = $fsize; - } + // Check for the largest font size in the box + $fsize = $html->getCurrentStyleHeight(); + if ($fsize > $html->largestFontHeight) { + $html->largestFontHeight = $fsize; + } - // Returns the Object if already numbered else false - if (empty($this->num)) { - $html->checkFootnote($this); - } + // Returns the Object if already numbered else false + if (empty($this->num)) { + $html->checkFootnote($this); + } - // Get the line width for the text in points + a little margin - $lw = $html->getStringWidth($this->numText); - // Line Feed counter - Number of lines in the text - $lfct = $html->countLines($this->numText); - // If there is still remaining wrap width... - if ($this->wrapWidthRemaining > 0) { - // Check with line counter too! - if ($lw >= $this->wrapWidthRemaining || $lfct > 1) { - $newtext = ''; - $wrapWidthRemaining = $this->wrapWidthRemaining; - $lines = explode("\n", $this->numText); - // Go throught the text line by line - foreach ($lines as $line) { - // Line width in points + a little margin - $lw = $html->getStringWidth($line); - // If the line has to be wraped - if ($lw > $wrapWidthRemaining) { - $words = explode(' ', $line); - $addspace = count($words); - $lw = 0; - foreach ($words as $word) { - $addspace--; - $lw += $html->getStringWidth($word . ' '); - if ($lw <= $wrapWidthRemaining) { - $newtext .= $word; - if ($addspace != 0) { - $newtext .= ' '; - } - } else { - $lw = $html->getStringWidth($word . ' '); - $newtext .= "\n$word"; - if ($addspace != 0) { - $newtext .= ' '; - } - // Reset the wrap width to the cell width - $wrapWidthRemaining = $this->wrapWidthCell; - } - } - } else { - $newtext .= $line; - } - // Check the Line Feed counter - if ($lfct > 1) { - // Add a new line feed as long as it’s not the last line - $newtext .= "\n"; - // Reset the line width - $lw = 0; - // Reset the wrap width to the cell width - $wrapWidthRemaining = $this->wrapWidthCell; - } - $lfct--; - } - $this->numText = $newtext; - $lfct = substr_count($this->numText, "\n"); + // Get the line width for the text in points + a little margin + $lw = $html->getStringWidth($this->numText); + // Line Feed counter - Number of lines in the text + $lfct = $html->countLines($this->numText); + // If there is still remaining wrap width... + if ($this->wrapWidthRemaining > 0) { + // Check with line counter too! + if ($lw >= $this->wrapWidthRemaining || $lfct > 1) { + $newtext = ''; + $wrapWidthRemaining = $this->wrapWidthRemaining; + $lines = explode("\n", $this->numText); + // Go throught the text line by line + foreach ($lines as $line) { + // Line width in points + a little margin + $lw = $html->getStringWidth($line); + // If the line has to be wraped + if ($lw > $wrapWidthRemaining) { + $words = explode(' ', $line); + $addspace = count($words); + $lw = 0; + foreach ($words as $word) { + $addspace--; + $lw += $html->getStringWidth($word . ' '); + if ($lw <= $wrapWidthRemaining) { + $newtext .= $word; + if ($addspace != 0) { + $newtext .= ' '; + } + } else { + $lw = $html->getStringWidth($word . ' '); + $newtext .= "\n$word"; + if ($addspace != 0) { + $newtext .= ' '; + } + // Reset the wrap width to the cell width + $wrapWidthRemaining = $this->wrapWidthCell; + } + } + } else { + $newtext .= $line; + } + // Check the Line Feed counter + if ($lfct > 1) { + // Add a new line feed as long as it’s not the last line + $newtext .= "\n"; + // Reset the line width + $lw = 0; + // Reset the wrap width to the cell width + $wrapWidthRemaining = $this->wrapWidthCell; + } + $lfct--; + } + $this->numText = $newtext; + $lfct = substr_count($this->numText, "\n"); - return [$lw, 1, $lfct]; - } - } - $l = 0; - $lfct = substr_count($this->numText, "\n"); - if ($lfct > 0) { - $l = 2; - } + return [ + $lw, + 1, + $lfct, + ]; + } + } + $l = 0; + $lfct = substr_count($this->numText, "\n"); + if ($lfct > 0) { + $l = 2; + } - return [$lw, $l, $lfct]; - } + return [ + $lw, + $l, + $lfct, + ]; + } } diff --git a/app/Report/ReportHtmlHtml.php b/app/Report/ReportHtmlHtml.php index 4dbdaa2aca..025dfce202 100644 --- a/app/Report/ReportHtmlHtml.php +++ b/app/Report/ReportHtmlHtml.php @@ -18,52 +18,54 @@ namespace Fisharebest\Webtrees\Report; /** * Class ReportHtmlHtml */ -class ReportHtmlHtml extends ReportBaseHtml { - /** - * Render the elements. - * - * @param ReportHtml $renderer - * @param bool $sub - * @param bool $inat - * - * @return string - */ - public function render($renderer, $sub = false, $inat = true) { - if (!empty($this->attrs['wt_style'])) { - $renderer->setCurrentStyle($this->attrs['wt_style']); - } +class ReportHtmlHtml extends ReportBaseHtml +{ + /** + * Render the elements. + * + * @param ReportHtml $renderer + * @param bool $sub + * @param bool $inat + * + * @return string + */ + public function render($renderer, $sub = false, $inat = true) + { + if (!empty($this->attrs['wt_style'])) { + $renderer->setCurrentStyle($this->attrs['wt_style']); + } - $this->text = $this->getStart() . $this->text; - foreach ($this->elements as $element) { - if (is_string($element) && $element == 'footnotetexts') { - $renderer->footnotes(); - } elseif (is_string($element) && $element == 'addpage') { - $renderer->addPage(); - } elseif ($element instanceof ReportBaseHtml) { - $element->render($renderer, true, false); - } else { - $element->render($renderer); - } - } - $this->text .= $this->getEnd(); - if ($sub) { - return $this->text; - } + $this->text = $this->getStart() . $this->text; + foreach ($this->elements as $element) { + if (is_string($element) && $element == 'footnotetexts') { + $renderer->footnotes(); + } elseif (is_string($element) && $element == 'addpage') { + $renderer->addPage(); + } elseif ($element instanceof ReportBaseHtml) { + $element->render($renderer, true, false); + } else { + $element->render($renderer); + } + } + $this->text .= $this->getEnd(); + if ($sub) { + return $this->text; + } - // If not called by an other attribute - if ($inat) { - $startX = $renderer->getX(); - $startY = $renderer->getY(); - $width = $renderer->getRemainingWidth(); - echo '<div style="position: absolute;top: ', $startY, 'pt;', $renderer->alignRTL, ': ', $startX, 'pt;width: ', $width, 'pt;">'; - $startY += $renderer->getCurrentStyleHeight() + 2; - $renderer->setY($startY); - } + // If not called by an other attribute + if ($inat) { + $startX = $renderer->getX(); + $startY = $renderer->getY(); + $width = $renderer->getRemainingWidth(); + echo '<div style="position: absolute;top: ', $startY, 'pt;', $renderer->alignRTL, ': ', $startX, 'pt;width: ', $width, 'pt;">'; + $startY += $renderer->getCurrentStyleHeight() + 2; + $renderer->setY($startY); + } - echo $this->text; + echo $this->text; - if ($inat) { - echo "</div>\n"; - } - } + if ($inat) { + echo "</div>\n"; + } + } } diff --git a/app/Report/ReportHtmlImage.php b/app/Report/ReportHtmlImage.php index 871a5b7f12..03b47392d0 100644 --- a/app/Report/ReportHtmlImage.php +++ b/app/Report/ReportHtmlImage.php @@ -18,69 +18,72 @@ namespace Fisharebest\Webtrees\Report; /** * Class ReportHtmlImage */ -class ReportHtmlImage extends ReportBaseImage { - /** - * Image renderer - * - * @param ReportHtml $renderer - */ - public function render($renderer) { - global $lastpicbottom, $lastpicpage, $lastpicleft, $lastpicright; +class ReportHtmlImage extends ReportBaseImage +{ + /** + * Image renderer + * + * @param ReportHtml $renderer + */ + public function render($renderer) + { + global $lastpicbottom, $lastpicpage, $lastpicleft, $lastpicright; - // Get the current positions - if ($this->x == '.') { - $this->x = $renderer->getX(); - } - if ($this->y == '.') { - //-- first check for a collision with the last picture - if (isset($lastpicbottom)) { - if (($renderer->pageNo() == $lastpicpage) && ($lastpicbottom >= $renderer->getY()) && ($this->x >= $lastpicleft) && ($this->x <= $lastpicright)) { - $renderer->setY($lastpicbottom + ($renderer->cPadding * 2)); - } - } - $this->y = $renderer->getY(); - } + // Get the current positions + if ($this->x == '.') { + $this->x = $renderer->getX(); + } + if ($this->y == '.') { + //-- first check for a collision with the last picture + if (isset($lastpicbottom)) { + if (($renderer->pageNo() == $lastpicpage) && ($lastpicbottom >= $renderer->getY()) && ($this->x >= $lastpicleft) && ($this->x <= $lastpicright)) { + $renderer->setY($lastpicbottom + ($renderer->cPadding * 2)); + } + } + $this->y = $renderer->getY(); + } - // Image alignment - switch ($this->align) { - case 'L': - echo '<div style="position:absolute;top:', $this->y, 'pt;left:0pt;width:', $renderer->getRemainingWidth(), "pt;text-align:left;\">\n"; - echo '<img src="', $this->file, '" style="width:', $this->width, 'pt;height:', $this->height, "pt;\" alt=\"\">\n</div>\n"; - break; - case 'C': - echo '<div style="position:absolute;top:', $this->y, 'pt;left:0pt;width:', $renderer->getRemainingWidth(), "pt;text-align:center;\">\n"; - echo '<img src="', $this->file, '" style="width:', $this->width, 'pt;height:', $this->height, "pt;\" alt=\"\">\n</div>\n"; - break; - case 'R': - echo '<div style="position:absolute;top:', $this->y, 'pt;left:0pt;width:', $renderer->getRemainingWidth(), "pt;text-align:right;\">\n"; - echo '<img src="', $this->file, '" style="width:', $this->width, 'pt;height:', $this->height, "pt;\" alt=\"\">\n</div>\n"; - break; - default: - echo '<img src="', $this->file, '" style="position:absolute;', $renderer->alignRTL, ':', $this->x, 'pt;top:', $this->y, 'pt;width:', $this->width, 'pt;height:', $this->height, "pt;\" alt=\"\">\n"; - } + // Image alignment + switch ($this->align) { + case 'L': + echo '<div style="position:absolute;top:', $this->y, 'pt;left:0pt;width:', $renderer->getRemainingWidth(), "pt;text-align:left;\">\n"; + echo '<img src="', $this->file, '" style="width:', $this->width, 'pt;height:', $this->height, "pt;\" alt=\"\">\n</div>\n"; + break; + case 'C': + echo '<div style="position:absolute;top:', $this->y, 'pt;left:0pt;width:', $renderer->getRemainingWidth(), "pt;text-align:center;\">\n"; + echo '<img src="', $this->file, '" style="width:', $this->width, 'pt;height:', $this->height, "pt;\" alt=\"\">\n</div>\n"; + break; + case 'R': + echo '<div style="position:absolute;top:', $this->y, 'pt;left:0pt;width:', $renderer->getRemainingWidth(), "pt;text-align:right;\">\n"; + echo '<img src="', $this->file, '" style="width:', $this->width, 'pt;height:', $this->height, "pt;\" alt=\"\">\n</div>\n"; + break; + default: + echo '<img src="', $this->file, '" style="position:absolute;', $renderer->alignRTL, ':', $this->x, 'pt;top:', $this->y, 'pt;width:', $this->width, 'pt;height:', $this->height, "pt;\" alt=\"\">\n"; + } - $lastpicpage = $renderer->pageNo(); - $lastpicleft = $this->x; - $lastpicright = $this->x + $this->width; - $lastpicbottom = $this->y + $this->height; - // Setup for the next line - if ($this->line == 'N') { - $renderer->setY($lastpicbottom); - } - // Keep max Y updated - $renderer->addMaxY($lastpicbottom); - } + $lastpicpage = $renderer->pageNo(); + $lastpicleft = $this->x; + $lastpicright = $this->x + $this->width; + $lastpicbottom = $this->y + $this->height; + // Setup for the next line + if ($this->line == 'N') { + $renderer->setY($lastpicbottom); + } + // Keep max Y updated + $renderer->addMaxY($lastpicbottom); + } - /** - * Get the image height - * This would be called from the TextBox only for multiple images - * so we add a bit bottom space between the images - * - * @param ReportHtml $html - * - * @return float - */ - public function getHeight($html) { - return $this->height + ($html->cPadding * 2); - } + /** + * Get the image height + * This would be called from the TextBox only for multiple images + * so we add a bit bottom space between the images + * + * @param ReportHtml $html + * + * @return float + */ + public function getHeight($html) + { + return $this->height + ($html->cPadding * 2); + } } diff --git a/app/Report/ReportHtmlLine.php b/app/Report/ReportHtmlLine.php index f9b21ce43c..727f40f630 100644 --- a/app/Report/ReportHtmlLine.php +++ b/app/Report/ReportHtmlLine.php @@ -18,36 +18,38 @@ namespace Fisharebest\Webtrees\Report; /** * Class ReportHtmlLine */ -class ReportHtmlLine extends ReportBaseLine { - /** - * HTML line renderer - * - * @param ReportHtml $renderer - */ - public function render($renderer) { - if ($this->x1 == '.') { - $this->x1 = $renderer->getX(); - } - if ($this->y1 == '.') { - $this->y1 = $renderer->getY(); - } - if ($this->x2 == '.') { - $this->x2 = $renderer->getRemainingWidth(); - } - if ($this->y2 == '.') { - $this->y2 = $renderer->getY(); - } - // Vertical line - if ($this->x1 == $this->x2) { - echo '<div style="position:absolute;overflow:hidden;border-', $renderer->alignRTL, ':solid black 1pt;', $renderer->alignRTL, ':', $this->x1, 'pt;top:', $this->y1 + 1, 'pt;width:1pt;height:', $this->y2 - $this->y1, "pt;\"> </div>\n"; - } - // Horizontal line - if ($this->y1 == $this->y2) { - echo '<div style="position:absolute;overflow:hidden;border-top:solid black 1pt;', $renderer->alignRTL, ':', $this->x1, 'pt;top:', $this->y1 + 1, 'pt;width:', $this->x2 - $this->x1, "pt;height:1pt;\"> </div>\n"; - } - // Keep max Y updated - // One or the other will be higher... lasy mans way... - $renderer->addMaxY($this->y1); - $renderer->addMaxY($this->y2); - } +class ReportHtmlLine extends ReportBaseLine +{ + /** + * HTML line renderer + * + * @param ReportHtml $renderer + */ + public function render($renderer) + { + if ($this->x1 == '.') { + $this->x1 = $renderer->getX(); + } + if ($this->y1 == '.') { + $this->y1 = $renderer->getY(); + } + if ($this->x2 == '.') { + $this->x2 = $renderer->getRemainingWidth(); + } + if ($this->y2 == '.') { + $this->y2 = $renderer->getY(); + } + // Vertical line + if ($this->x1 == $this->x2) { + echo '<div style="position:absolute;overflow:hidden;border-', $renderer->alignRTL, ':solid black 1pt;', $renderer->alignRTL, ':', $this->x1, 'pt;top:', $this->y1 + 1, 'pt;width:1pt;height:', $this->y2 - $this->y1, "pt;\"> </div>\n"; + } + // Horizontal line + if ($this->y1 == $this->y2) { + echo '<div style="position:absolute;overflow:hidden;border-top:solid black 1pt;', $renderer->alignRTL, ':', $this->x1, 'pt;top:', $this->y1 + 1, 'pt;width:', $this->x2 - $this->x1, "pt;height:1pt;\"> </div>\n"; + } + // Keep max Y updated + // One or the other will be higher... lasy mans way... + $renderer->addMaxY($this->y1); + $renderer->addMaxY($this->y2); + } } diff --git a/app/Report/ReportHtmlPageheader.php b/app/Report/ReportHtmlPageheader.php index 8451c52125..d7501bb102 100644 --- a/app/Report/ReportHtmlPageheader.php +++ b/app/Report/ReportHtmlPageheader.php @@ -18,16 +18,18 @@ namespace Fisharebest\Webtrees\Report; /** * Class ReportHtmlPageheader */ -class ReportHtmlPageheader extends ReportBasePageheader { - /** - * Render elements. - * - * @param ReportHtml $renderer - */ - public function render($renderer) { - $renderer->clearPageHeader(); - foreach ($this->elements as $element) { - $renderer->addPageHeader($element); - } - } +class ReportHtmlPageheader extends ReportBasePageheader +{ + /** + * Render elements. + * + * @param ReportHtml $renderer + */ + public function render($renderer) + { + $renderer->clearPageHeader(); + foreach ($this->elements as $element) { + $renderer->addPageHeader($element); + } + } } diff --git a/app/Report/ReportHtmlText.php b/app/Report/ReportHtmlText.php index f054953a9e..89dc8d5c27 100644 --- a/app/Report/ReportHtmlText.php +++ b/app/Report/ReportHtmlText.php @@ -18,159 +18,177 @@ namespace Fisharebest\Webtrees\Report; /** * Class ReportHtmlText */ -class ReportHtmlText extends ReportBaseText { - /** - * Render the elements. - * - * @param ReportHtml $renderer - * @param int $curx - * @param bool $attrib Is is called from a different element? - */ - public function render($renderer, $curx = 0, $attrib = true) { +class ReportHtmlText extends ReportBaseText +{ + /** + * Render the elements. + * + * @param ReportHtml $renderer + * @param int $curx + * @param bool $attrib Is is called from a different element? + */ + public function render($renderer, $curx = 0, $attrib = true) + { - // Setup the style name - if ($renderer->getCurrentStyle() != $this->styleName) { - $renderer->setCurrentStyle($this->styleName); - } - $temptext = str_replace('#PAGENUM#', $renderer->pageNo(), $this->text); - // underline «title» part of Source item - $temptext = str_replace(['«', '»'], ['<u>', '</u>'], $temptext); + // Setup the style name + if ($renderer->getCurrentStyle() != $this->styleName) { + $renderer->setCurrentStyle($this->styleName); + } + $temptext = str_replace('#PAGENUM#', $renderer->pageNo(), $this->text); + // underline «title» part of Source item + $temptext = str_replace([ + '«', + '»', + ], [ + '<u>', + '</u>', + ], $temptext); - // If any text at all - if (!empty($temptext)) { - // If called by an other element - if (!$attrib) { - $renderer->write($temptext, $this->color); - } else { - // Save the start positions - $startX = $renderer->getX(); - $startY = $renderer->getY(); - $width = $renderer->getRemainingWidth(); - // If text is wider then page width then wrap it - if ($renderer->getStringWidth($temptext) > $width) { - $lines = explode("\n", $temptext); - foreach ($lines as $line) { - echo '<div style="position:absolute;top:', $startY, 'pt;', $renderer->alignRTL, ':', $startX, 'pt;width:', $width, 'pt;">'; - $line = $renderer->textWrap($line, $width); - $startY += $renderer->getTextCellHeight($line); - $renderer->setY($startY); - $renderer->write($line, $this->color); - echo "</div>\n"; - } - } else { - echo '<div style="position:absolute;top:', $startY, 'pt;', $renderer->alignRTL, ':', $startX, 'pt;width:', $width, 'pt;">'; - $renderer->write($temptext, $this->color); - echo "</div>\n"; - $renderer->setX($startX + $renderer->getStringWidth($temptext)); - if ($renderer->countLines($temptext) != 1) { - $renderer->setXy(0, ($startY + $renderer->getTextCellHeight($temptext))); - } - } - } - } - } + // If any text at all + if (!empty($temptext)) { + // If called by an other element + if (!$attrib) { + $renderer->write($temptext, $this->color); + } else { + // Save the start positions + $startX = $renderer->getX(); + $startY = $renderer->getY(); + $width = $renderer->getRemainingWidth(); + // If text is wider then page width then wrap it + if ($renderer->getStringWidth($temptext) > $width) { + $lines = explode("\n", $temptext); + foreach ($lines as $line) { + echo '<div style="position:absolute;top:', $startY, 'pt;', $renderer->alignRTL, ':', $startX, 'pt;width:', $width, 'pt;">'; + $line = $renderer->textWrap($line, $width); + $startY += $renderer->getTextCellHeight($line); + $renderer->setY($startY); + $renderer->write($line, $this->color); + echo "</div>\n"; + } + } else { + echo '<div style="position:absolute;top:', $startY, 'pt;', $renderer->alignRTL, ':', $startX, 'pt;width:', $width, 'pt;">'; + $renderer->write($temptext, $this->color); + echo "</div>\n"; + $renderer->setX($startX + $renderer->getStringWidth($temptext)); + if ($renderer->countLines($temptext) != 1) { + $renderer->setXy(0, ($startY + $renderer->getTextCellHeight($temptext))); + } + } + } + } + } - /** - * Returns the height in points of the text element - * The height is already calculated in getWidth() - * - * @param ReportHtml $html - * - * @return float - */ - public function getHeight($html) { - $ct = substr_count($this->text, "\n"); - if ($ct > 0) { - $ct += 1; - } - $style = $html->getStyle($this->styleName); + /** + * Returns the height in points of the text element + * The height is already calculated in getWidth() + * + * @param ReportHtml $html + * + * @return float + */ + public function getHeight($html) + { + $ct = substr_count($this->text, "\n"); + if ($ct > 0) { + $ct += 1; + } + $style = $html->getStyle($this->styleName); - return ($style['size'] * $ct) * $html->cellHeightRatio; - } + return ($style['size'] * $ct) * $html->cellHeightRatio; + } - /** - * Get the width of text and wrap it too - * - * @param ReportHtml $html - * - * @return array - */ - public function getWidth($html) { - // Setup the style name - if ($html->getCurrentStyle() != $this->styleName) { - $html->setCurrentStyle($this->styleName); - } + /** + * Get the width of text and wrap it too + * + * @param ReportHtml $html + * + * @return array + */ + public function getWidth($html) + { + // Setup the style name + if ($html->getCurrentStyle() != $this->styleName) { + $html->setCurrentStyle($this->styleName); + } - // Check for the largest font size in the box - $fsize = $html->getCurrentStyleHeight(); - if ($fsize > $html->largestFontHeight) { - $html->largestFontHeight = $fsize; - } + // Check for the largest font size in the box + $fsize = $html->getCurrentStyleHeight(); + if ($fsize > $html->largestFontHeight) { + $html->largestFontHeight = $fsize; + } - // Get the line width for the text in points - $lw = $html->getStringWidth($this->text); - // Line Feed counter - Number of lines in the text - $lfct = $html->countLines($this->text); - // If there is still remaining wrap width... - if ($this->wrapWidthRemaining > 0) { - // Check with line counter too! - if ($lw >= $this->wrapWidthRemaining || $lfct > 1) { - $newtext = ''; - $wrapWidthRemaining = $this->wrapWidthRemaining; - $lines = explode("\n", $this->text); - // Go throught the text line by line - foreach ($lines as $line) { - // Line width in points + a little margin - $lw = $html->getStringWidth($line); - // If the line has to be wraped - if ($lw > $wrapWidthRemaining) { - $words = explode(' ', $line); - $addspace = count($words); - $lw = 0; - foreach ($words as $word) { - $addspace--; - $lw += $html->getStringWidth($word . ' '); - if ($lw <= $wrapWidthRemaining) { - $newtext .= $word; - if ($addspace != 0) { - $newtext .= ' '; - } - } else { - $lw = $html->getStringWidth($word . ' '); - $newtext .= "\n$word"; - if ($addspace != 0) { - $newtext .= ' '; - } - // Reset the wrap width to the cell width - $wrapWidthRemaining = $this->wrapWidthCell; - } - } - } else { - $newtext .= $line; - } - // Check the Line Feed counter - if ($lfct > 1) { - // Add a new line feed as long as it’s not the last line - $newtext .= "\n"; - // Reset the line width - $lw = 0; - // Reset the wrap width to the cell width - $wrapWidthRemaining = $this->wrapWidthCell; - } - $lfct--; - } - $this->text = $newtext; - $lfct = substr_count($this->text, "\n"); + // Get the line width for the text in points + $lw = $html->getStringWidth($this->text); + // Line Feed counter - Number of lines in the text + $lfct = $html->countLines($this->text); + // If there is still remaining wrap width... + if ($this->wrapWidthRemaining > 0) { + // Check with line counter too! + if ($lw >= $this->wrapWidthRemaining || $lfct > 1) { + $newtext = ''; + $wrapWidthRemaining = $this->wrapWidthRemaining; + $lines = explode("\n", $this->text); + // Go throught the text line by line + foreach ($lines as $line) { + // Line width in points + a little margin + $lw = $html->getStringWidth($line); + // If the line has to be wraped + if ($lw > $wrapWidthRemaining) { + $words = explode(' ', $line); + $addspace = count($words); + $lw = 0; + foreach ($words as $word) { + $addspace--; + $lw += $html->getStringWidth($word . ' '); + if ($lw <= $wrapWidthRemaining) { + $newtext .= $word; + if ($addspace != 0) { + $newtext .= ' '; + } + } else { + $lw = $html->getStringWidth($word . ' '); + $newtext .= "\n$word"; + if ($addspace != 0) { + $newtext .= ' '; + } + // Reset the wrap width to the cell width + $wrapWidthRemaining = $this->wrapWidthCell; + } + } + } else { + $newtext .= $line; + } + // Check the Line Feed counter + if ($lfct > 1) { + // Add a new line feed as long as it’s not the last line + $newtext .= "\n"; + // Reset the line width + $lw = 0; + // Reset the wrap width to the cell width + $wrapWidthRemaining = $this->wrapWidthCell; + } + $lfct--; + } + $this->text = $newtext; + $lfct = substr_count($this->text, "\n"); - return [$lw, 1, $lfct]; - } - } - $l = 0; - $lfct = substr_count($this->text, "\n"); - if ($lfct > 0) { - $l = 2; - } + return [ + $lw, + 1, + $lfct, + ]; + } + } + $l = 0; + $lfct = substr_count($this->text, "\n"); + if ($lfct > 0) { + $l = 2; + } - return [$lw, $l, $lfct]; - } + return [ + $lw, + $l, + $lfct, + ]; + } } diff --git a/app/Report/ReportHtmlTextbox.php b/app/Report/ReportHtmlTextbox.php index a70c29d384..1cf212e48b 100644 --- a/app/Report/ReportHtmlTextbox.php +++ b/app/Report/ReportHtmlTextbox.php @@ -18,254 +18,256 @@ namespace Fisharebest\Webtrees\Report; /** * Class ReportHtmlTextbox */ -class ReportHtmlTextbox extends ReportBaseTextbox { - /** - * Render the elements. - * - * @param ReportHtml $renderer - */ - public function render($renderer) { - // checkFootnote - $newelements = []; - $lastelement = []; - $footnote_element = []; - // Element counter - $cE = count($this->elements); - //-- collapse duplicate elements - for ($i = 0; $i < $cE; $i++) { - $element = $this->elements[$i]; - if (is_object($element)) { - if ($element instanceof ReportBaseText) { - if (!empty($footnote_element)) { - ksort($footnote_element); - foreach ($footnote_element as $links) { - $newelements[] = $links; - } - $footnote_element = []; - } - if (empty($lastelement)) { - $lastelement = $element; - } else { - // Checking if the Text has the same style - if ($element->getStyleName() == $lastelement->getStyleName()) { - $lastelement->addText(str_replace("\n", '<br>', $element->getValue())); - } elseif (!empty($lastelement)) { - $newelements[] = $lastelement; - $lastelement = $element; - } - } - } // Collect the Footnote links - elseif ($element instanceof ReportBaseFootnote) { - // Check if the Footnote has been set with it’s link number - $renderer->checkFootnote($element); - // Save first the last element if any - if (!empty($lastelement)) { - $newelements[] = $lastelement; - $lastelement = []; - } - // Save the Footnote with it’s link number as key for sorting later - $footnote_element[$element->num] = $element; - } //-- do not keep empty footnotes - elseif (!($element instanceof ReportBaseFootnote) || trim($element->getValue()) != '') { - if (!empty($footnote_element)) { - ksort($footnote_element); - foreach ($footnote_element as $links) { - $newelements[] = $links; - } - $footnote_element = []; - } - if (!empty($lastelement)) { - $newelements[] = $lastelement; - $lastelement = []; - } - $newelements[] = $element; - } - } else { - if (!empty($lastelement)) { - $newelements[] = $lastelement; - $lastelement = []; - } - if (!empty($footnote_element)) { - ksort($footnote_element); - foreach ($footnote_element as $links) { - $newelements[] = $links; - } - $footnote_element = []; - } - $newelements[] = $element; - } - } - if (!empty($lastelement)) { - $newelements[] = $lastelement; - } - if (!empty($footnote_element)) { - ksort($footnote_element); - foreach ($footnote_element as $links) { - $newelements[] = $links; - } - } - $this->elements = $newelements; - unset($footnote_element, $lastelement, $links, $newelements); +class ReportHtmlTextbox extends ReportBaseTextbox +{ + /** + * Render the elements. + * + * @param ReportHtml $renderer + */ + public function render($renderer) + { + // checkFootnote + $newelements = []; + $lastelement = []; + $footnote_element = []; + // Element counter + $cE = count($this->elements); + //-- collapse duplicate elements + for ($i = 0; $i < $cE; $i++) { + $element = $this->elements[$i]; + if (is_object($element)) { + if ($element instanceof ReportBaseText) { + if (!empty($footnote_element)) { + ksort($footnote_element); + foreach ($footnote_element as $links) { + $newelements[] = $links; + } + $footnote_element = []; + } + if (empty($lastelement)) { + $lastelement = $element; + } else { + // Checking if the Text has the same style + if ($element->getStyleName() == $lastelement->getStyleName()) { + $lastelement->addText(str_replace("\n", '<br>', $element->getValue())); + } elseif (!empty($lastelement)) { + $newelements[] = $lastelement; + $lastelement = $element; + } + } + } // Collect the Footnote links + elseif ($element instanceof ReportBaseFootnote) { + // Check if the Footnote has been set with it’s link number + $renderer->checkFootnote($element); + // Save first the last element if any + if (!empty($lastelement)) { + $newelements[] = $lastelement; + $lastelement = []; + } + // Save the Footnote with it’s link number as key for sorting later + $footnote_element[$element->num] = $element; + } //-- do not keep empty footnotes + elseif (!($element instanceof ReportBaseFootnote) || trim($element->getValue()) != '') { + if (!empty($footnote_element)) { + ksort($footnote_element); + foreach ($footnote_element as $links) { + $newelements[] = $links; + } + $footnote_element = []; + } + if (!empty($lastelement)) { + $newelements[] = $lastelement; + $lastelement = []; + } + $newelements[] = $element; + } + } else { + if (!empty($lastelement)) { + $newelements[] = $lastelement; + $lastelement = []; + } + if (!empty($footnote_element)) { + ksort($footnote_element); + foreach ($footnote_element as $links) { + $newelements[] = $links; + } + $footnote_element = []; + } + $newelements[] = $element; + } + } + if (!empty($lastelement)) { + $newelements[] = $lastelement; + } + if (!empty($footnote_element)) { + ksort($footnote_element); + foreach ($footnote_element as $links) { + $newelements[] = $links; + } + } + $this->elements = $newelements; + unset($footnote_element, $lastelement, $links, $newelements); - $cP = 0; // Class Padding + $cP = 0; // Class Padding - // Used with line breaks and cell height calculation within this box only - $renderer->largestFontHeight = 0; + // Used with line breaks and cell height calculation within this box only + $renderer->largestFontHeight = 0; - // Current position - if ($this->left == '.') { - $cX = $renderer->getX(); - } else { - $cX = $this->left; - $renderer->setX($cX); - } - // Current position (top) - if ($this->top == '.') { - $this->top = $renderer->getY(); - } else { - $renderer->setY($this->top); - } + // Current position + if ($this->left == '.') { + $cX = $renderer->getX(); + } else { + $cX = $this->left; + $renderer->setX($cX); + } + // Current position (top) + if ($this->top == '.') { + $this->top = $renderer->getY(); + } else { + $renderer->setY($this->top); + } - // Check the width if set to page wide OR set by xml to larger then page wide - if ($this->width == 0 || $this->width > $renderer->getRemainingWidth()) { - $this->width = $renderer->getRemainingWidth(); - } - // Setup the CellPadding - if ($this->padding) { - $cP = $renderer->cPadding; - } + // Check the width if set to page wide OR set by xml to larger then page wide + if ($this->width == 0 || $this->width > $renderer->getRemainingWidth()) { + $this->width = $renderer->getRemainingWidth(); + } + // Setup the CellPadding + if ($this->padding) { + $cP = $renderer->cPadding; + } - // For padding, we have to use less wrap width - $cW = $this->width - ($cP * 2); + // For padding, we have to use less wrap width + $cW = $this->width - ($cP * 2); - //-- calculate the text box height - // Number of lines, will be converted to height - $cHT = 0; - // Element height (exept text) - $eH = 0; - // Footnote height (in points) - $fH = 0; - $w = 0; - //-- $lw is an array - // 0 => last line width - // 1 => 1 if text was wrapped, 0 if text did not wrap - // 2 => number of LF - $lw = []; - // Element counter - $cE = count($this->elements); - for ($i = 0; $i < $cE; $i++) { - if (is_object($this->elements[$i])) { - $ew = $this->elements[$i]->setWrapWidth($cW - $w - 2, $cW); - if ($ew == $cW) { - $w = 0; - } - $lw = $this->elements[$i]->getWidth($renderer); - // Text is already gets the # LF - $cHT += $lw[2]; - if ($lw[1] == 1) { - $w = $lw[0]; - } elseif ($lw[1] == 2) { - $w = 0; - } else { - $w += $lw[0]; - } - if ($w > $cW) { - $w = $lw[0]; - } - // For anything else but text (images), get the height - $eH += $this->elements[$i]->getHeight($renderer); - } else { - $fH += abs($renderer->getFootnotesHeight($cW)); - } - } - // Add up what’s the final height - $cH = $this->height; - // If any element exist - if ($cE > 0) { - // Check if this is text or some other element, like images - if ($eH == 0) { - // Number of LF but at least one line - $cHT = ($cHT + 1) * $renderer->cellHeightRatio; - // Calculate the cell hight with the largest font size used - $cHT = $cHT * $renderer->largestFontHeight; - if ($cH < $cHT) { - $cH = $cHT; - } - } // This is any other element - else { - if ($cH < $eH) { - $cH = $eH; - } - // Add Footnote height to the rest of the height - $cH += $fH; - } - } + //-- calculate the text box height + // Number of lines, will be converted to height + $cHT = 0; + // Element height (exept text) + $eH = 0; + // Footnote height (in points) + $fH = 0; + $w = 0; + //-- $lw is an array + // 0 => last line width + // 1 => 1 if text was wrapped, 0 if text did not wrap + // 2 => number of LF + $lw = []; + // Element counter + $cE = count($this->elements); + for ($i = 0; $i < $cE; $i++) { + if (is_object($this->elements[$i])) { + $ew = $this->elements[$i]->setWrapWidth($cW - $w - 2, $cW); + if ($ew == $cW) { + $w = 0; + } + $lw = $this->elements[$i]->getWidth($renderer); + // Text is already gets the # LF + $cHT += $lw[2]; + if ($lw[1] == 1) { + $w = $lw[0]; + } elseif ($lw[1] == 2) { + $w = 0; + } else { + $w += $lw[0]; + } + if ($w > $cW) { + $w = $lw[0]; + } + // For anything else but text (images), get the height + $eH += $this->elements[$i]->getHeight($renderer); + } else { + $fH += abs($renderer->getFootnotesHeight($cW)); + } + } + // Add up what’s the final height + $cH = $this->height; + // If any element exist + if ($cE > 0) { + // Check if this is text or some other element, like images + if ($eH == 0) { + // Number of LF but at least one line + $cHT = ($cHT + 1) * $renderer->cellHeightRatio; + // Calculate the cell hight with the largest font size used + $cHT = $cHT * $renderer->largestFontHeight; + if ($cH < $cHT) { + $cH = $cHT; + } + } // This is any other element + else { + if ($cH < $eH) { + $cH = $eH; + } + // Add Footnote height to the rest of the height + $cH += $fH; + } + } - unset($lw, $cHT, $fH, $w); + unset($lw, $cHT, $fH, $w); - // Finaly, check the last cells height - if ($cH < $renderer->lastCellHeight) { - $cH = $renderer->lastCellHeight; - } - // Update max Y incase of a pagebreak - // We don't want to over write any images or other stuff - $renderer->addMaxY($this->top + $cH); + // Finaly, check the last cells height + if ($cH < $renderer->lastCellHeight) { + $cH = $renderer->lastCellHeight; + } + // Update max Y incase of a pagebreak + // We don't want to over write any images or other stuff + $renderer->addMaxY($this->top + $cH); - // Start to print HTML - echo '<div style="position:absolute;top:', $this->top, 'pt;'; - // LTR (left) or RTL (right) - echo $renderer->alignRTL, ':', $cX, 'pt;'; - // Background color - if ($this->fill) { - if (!empty($this->bgcolor)) { - echo ' background-color:', $this->bgcolor, ';'; - } - } - // Print padding only when it’s set - if ($this->padding) { - // Use Cell around padding to support RTL also - echo 'padding:', $cP, 'pt;'; - } - // Border setup - if ($this->border) { - echo ' border:solid black 1pt;'; - echo 'width:', ($this->width - 1 - ($cP * 2)), 'pt;height:', $cH - 1, 'pt;'; - } else { - echo 'width:', ($this->width - ($cP * 2)), 'pt;height:', $cH, 'pt;'; - } - echo '">'; + // Start to print HTML + echo '<div style="position:absolute;top:', $this->top, 'pt;'; + // LTR (left) or RTL (right) + echo $renderer->alignRTL, ':', $cX, 'pt;'; + // Background color + if ($this->fill) { + if (!empty($this->bgcolor)) { + echo ' background-color:', $this->bgcolor, ';'; + } + } + // Print padding only when it’s set + if ($this->padding) { + // Use Cell around padding to support RTL also + echo 'padding:', $cP, 'pt;'; + } + // Border setup + if ($this->border) { + echo ' border:solid black 1pt;'; + echo 'width:', ($this->width - 1 - ($cP * 2)), 'pt;height:', $cH - 1, 'pt;'; + } else { + echo 'width:', ($this->width - ($cP * 2)), 'pt;height:', $cH, 'pt;'; + } + echo '">'; - // Do a little "margin" trick before print - // to get the correct current position => "." - $cXT = $renderer->getX(); - $cYT = $renderer->getY(); - $renderer->setXy(0, 0); + // Do a little "margin" trick before print + // to get the correct current position => "." + $cXT = $renderer->getX(); + $cYT = $renderer->getY(); + $renderer->setXy(0, 0); - // Print the text elements - foreach ($this->elements as $element) { - if (is_object($element)) { - $element->render($renderer, $cX, false); - } elseif (is_string($element) && $element == 'footnotetexts') { - $renderer->footnotes(); - } elseif (is_string($element) && $element == 'addpage') { - $renderer->addPage(); - } - } - echo "</div>\n"; + // Print the text elements + foreach ($this->elements as $element) { + if (is_object($element)) { + $element->render($renderer, $cX, false); + } elseif (is_string($element) && $element == 'footnotetexts') { + $renderer->footnotes(); + } elseif (is_string($element) && $element == 'addpage') { + $renderer->addPage(); + } + } + echo "</div>\n"; - // Reset "margins" - $renderer->setXy($cXT, $cYT); - // This will be mostly used to trick the multiple images last height - if ($this->reseth) { - $cH = 0; - } - // New line and some clean up - if (!$this->newline) { - $renderer->setXy($cX + $this->width, $this->top); - $renderer->lastCellHeight = $cH; - } else { - $renderer->setXy(0, $this->top + $cH + ($cP * 2)); - $renderer->lastCellHeight = 0; - } - } + // Reset "margins" + $renderer->setXy($cXT, $cYT); + // This will be mostly used to trick the multiple images last height + if ($this->reseth) { + $cH = 0; + } + // New line and some clean up + if (!$this->newline) { + $renderer->setXy($cX + $this->width, $this->top); + $renderer->lastCellHeight = $cH; + } else { + $renderer->setXy(0, $this->top + $cH + ($cP * 2)); + $renderer->lastCellHeight = 0; + } + } } diff --git a/app/Report/ReportParserBase.php b/app/Report/ReportParserBase.php index 324dead3df..26cb7dbac1 100644 --- a/app/Report/ReportParserBase.php +++ b/app/Report/ReportParserBase.php @@ -20,75 +20,89 @@ use Fisharebest\Webtrees\Tree; /** * Class ReportParserBase */ -class ReportParserBase { - /** @var resource The XML parser */ - protected $xml_parser; +class ReportParserBase +{ + /** @var resource The XML parser */ + protected $xml_parser; - /** @var string Text contents of tags */ - protected $text = ''; + /** @var string Text contents of tags */ + protected $text = ''; - /** - * Create a parser for a report - * - * @param string $report The XML filename - * @param ReportBase $report_root - * @param string[][] $vars - * @param Tree $tree - */ - public function __construct($report, ReportBase $report_root, $vars, Tree $tree) { - $this->xml_parser = xml_parser_create(); - xml_parser_set_option($this->xml_parser, XML_OPTION_CASE_FOLDING, false); - xml_set_element_handler($this->xml_parser, [$this, 'startElement'], [$this, 'endElement']); - xml_set_character_data_handler($this->xml_parser, [$this, 'characterData']); + /** + * Create a parser for a report + * + * @param string $report The XML filename + * @param ReportBase $report_root + * @param string[][] $vars + * @param Tree $tree + */ + public function __construct($report, ReportBase $report_root, $vars, Tree $tree) + { + $this->xml_parser = xml_parser_create(); + xml_parser_set_option($this->xml_parser, XML_OPTION_CASE_FOLDING, false); + xml_set_element_handler($this->xml_parser, [ + $this, + 'startElement', + ], [ + $this, + 'endElement', + ]); + xml_set_character_data_handler($this->xml_parser, [ + $this, + 'characterData', + ]); - $fp = fopen($report, 'r'); - while (($data = fread($fp, 4096))) { - if (!xml_parse($this->xml_parser, $data, feof($fp))) { - throw new \DomainException(sprintf( - 'XML error: %s at line %d', - xml_error_string(xml_get_error_code($this->xml_parser)), - xml_get_current_line_number($this->xml_parser) - )); - } - } + $fp = fopen($report, 'r'); + while (($data = fread($fp, 4096))) { + if (!xml_parse($this->xml_parser, $data, feof($fp))) { + throw new \DomainException(sprintf( + 'XML error: %s at line %d', + xml_error_string(xml_get_error_code($this->xml_parser)), + xml_get_current_line_number($this->xml_parser) + )); + } + } - xml_parser_free($this->xml_parser); - } + xml_parser_free($this->xml_parser); + } - /** - * XML handler for an opening (or self-closing) tag. - * - * @param resource $parser The resource handler for the xml parser - * @param string $name The name of the xml element parsed - * @param string[] $attrs An array of key value pairs for the attributes - */ - protected function startElement($parser, $name, $attrs) { - $method = $name . 'StartHandler'; - if (method_exists($this, $method)) { - $this->$method($attrs); - } - } + /** + * XML handler for an opening (or self-closing) tag. + * + * @param resource $parser The resource handler for the xml parser + * @param string $name The name of the xml element parsed + * @param string[] $attrs An array of key value pairs for the attributes + */ + protected function startElement($parser, $name, $attrs) + { + $method = $name . 'StartHandler'; + if (method_exists($this, $method)) { + $this->$method($attrs); + } + } - /** - * XML handler for a closing tag. - * - * @param resource $parser the resource handler for the xml parser - * @param string $name the name of the xml element parsed - */ - protected function endElement($parser, $name) { - $method = $name . 'EndHandler'; - if (method_exists($this, $method)) { - $this->$method(); - } - } + /** + * XML handler for a closing tag. + * + * @param resource $parser the resource handler for the xml parser + * @param string $name the name of the xml element parsed + */ + protected function endElement($parser, $name) + { + $method = $name . 'EndHandler'; + if (method_exists($this, $method)) { + $this->$method(); + } + } - /** - * XML handler for character data. - * - * @param resource $parser The resource handler for the xml parser - * @param string $data The name of the xml element parsed - */ - protected function characterData($parser, $data) { - $this->text .= $data; - } + /** + * XML handler for character data. + * + * @param resource $parser The resource handler for the xml parser + * @param string $data The name of the xml element parsed + */ + protected function characterData($parser, $data) + { + $this->text .= $data; + } } diff --git a/app/Report/ReportParserGenerate.php b/app/Report/ReportParserGenerate.php index ba74ed910e..2267f52af8 100644 --- a/app/Report/ReportParserGenerate.php +++ b/app/Report/ReportParserGenerate.php @@ -35,2730 +35,2885 @@ use Fisharebest\Webtrees\Tree; /** * Class ReportParserGenerate - parse a report.xml file and generate the report. */ -class ReportParserGenerate extends ReportParserBase { - /** @var bool Are we collecting data from <Footnote> elements */ - private $process_footnote = true; +class ReportParserGenerate extends ReportParserBase +{ + /** @var bool Are we collecting data from <Footnote> elements */ + private $process_footnote = true; - /** @var bool Are we currently outputing data? */ - private $print_data = false; + /** @var bool Are we currently outputing data? */ + private $print_data = false; - /** @var bool[] Push-down stack of $print_data */ - private $print_data_stack = []; + /** @var bool[] Push-down stack of $print_data */ + private $print_data_stack = []; - /** @var int Are we processing GEDCOM data */ - private $process_gedcoms = 0; + /** @var int Are we processing GEDCOM data */ + private $process_gedcoms = 0; - /** @var int Are we processing conditionals */ - private $process_ifs = 0; + /** @var int Are we processing conditionals */ + private $process_ifs = 0; - /** @var int Are we processing repeats*/ - private $process_repeats = 0; + /** @var int Are we processing repeats */ + private $process_repeats = 0; - /** @var int Quantity of data to repeat during loops */ - private $repeat_bytes = 0; + /** @var int Quantity of data to repeat during loops */ + private $repeat_bytes = 0; - /** @var array[] Repeated data when iterating over loops */ - private $repeats = []; + /** @var array[] Repeated data when iterating over loops */ + private $repeats = []; - /** @var array[] Nested repeating data */ - private $repeats_stack = []; + /** @var array[] Nested repeating data */ + private $repeats_stack = []; - /** @var ReportBase[] Nested repeating data */ - private $wt_report_stack = []; + /** @var ReportBase[] Nested repeating data */ + private $wt_report_stack = []; - /** @var resource Nested repeating data */ - private $parser; + /** @var resource Nested repeating data */ + private $parser; - /** @var resource[] Nested repeating data */ - private $parser_stack = []; + /** @var resource[] Nested repeating data */ + private $parser_stack = []; - /** @var string The current GEDCOM record */ - private $gedrec = ''; + /** @var string The current GEDCOM record */ + private $gedrec = ''; - /** @var string[] Nested GEDCOM records */ - private $gedrec_stack = []; + /** @var string[] Nested GEDCOM records */ + private $gedrec_stack = []; - /** @var ReportBaseElement The currently processed element */ - private $current_element; + /** @var ReportBaseElement The currently processed element */ + private $current_element; - /** @var ReportBaseElement The currently processed element */ - private $footnote_element; + /** @var ReportBaseElement The currently processed element */ + private $footnote_element; - /** @var string The GEDCOM fact currently being processed */ - private $fact = ''; + /** @var string The GEDCOM fact currently being processed */ + private $fact = ''; - /** @var string The GEDCOM value currently being processed */ - private $desc = ''; + /** @var string The GEDCOM value currently being processed */ + private $desc = ''; - /** @var string The GEDCOM type currently being processed */ - private $type = ''; + /** @var string The GEDCOM type currently being processed */ + private $type = ''; - /** @var int The current generational level */ - private $generation = 1; + /** @var int The current generational level */ + private $generation = 1; - /** @var array Source data for processing lists */ - private $list = []; + /** @var array Source data for processing lists */ + private $list = []; - /** @var int Number of items in lists */ - private $list_total = 0; + /** @var int Number of items in lists */ + private $list_total = 0; - /** @var int Number of items filtered from lists */ - private $list_private = 0; + /** @var int Number of items filtered from lists */ + private $list_private = 0; - /** @var string The filename of the XML report */ - protected $report; + /** @var string The filename of the XML report */ + protected $report; - /** @var ReportBase A factory for creating report elements */ - private $report_root; + /** @var ReportBase A factory for creating report elements */ + private $report_root; - /** @var ReportBase Nested report elements */ - private $wt_report; + /** @var ReportBase Nested report elements */ + private $wt_report; - /** @var string[][] Variables defined in the report at run-time */ - private $vars; + /** @var string[][] Variables defined in the report at run-time */ + private $vars; - /** @var Tree The current tree */ - private $tree; + /** @var Tree The current tree */ + private $tree; - /** - * Create a parser for a report - * - * @param string $report The XML filename - * @param ReportBase $report_root - * @param string[][] $vars - * @param Tree $tree - */ - public function __construct($report, ReportBase $report_root, array $vars, Tree $tree) { - $this->report = $report; - $this->report_root = $report_root; - $this->wt_report = $report_root; - $this->current_element = new ReportBaseElement; - $this->vars = $vars; - $this->tree = $tree; + /** + * Create a parser for a report + * + * @param string $report The XML filename + * @param ReportBase $report_root + * @param string[][] $vars + * @param Tree $tree + */ + public function __construct($report, ReportBase $report_root, array $vars, Tree $tree) + { + $this->report = $report; + $this->report_root = $report_root; + $this->wt_report = $report_root; + $this->current_element = new ReportBaseElement; + $this->vars = $vars; + $this->tree = $tree; - parent::__construct($report, $report_root, $vars, $tree); - } + parent::__construct($report, $report_root, $vars, $tree); + } - /** - * XML start element handler - * - * This function is called whenever a starting element is reached - * The element handler will be called if found, otherwise it must be HTML - * - * @param resource $parser the resource handler for the XML parser - * @param string $name the name of the XML element parsed - * @param array $attrs an array of key value pairs for the attributes - */ - protected function startElement($parser, $name, $attrs) { - $newattrs = []; + /** + * XML start element handler + * + * This function is called whenever a starting element is reached + * The element handler will be called if found, otherwise it must be HTML + * + * @param resource $parser the resource handler for the XML parser + * @param string $name the name of the XML element parsed + * @param array $attrs an array of key value pairs for the attributes + */ + protected function startElement($parser, $name, $attrs) + { + $newattrs = []; - foreach ($attrs as $key => $value) { - if (preg_match("/^\\$(\w+)$/", $value, $match)) { - if ((isset($this->vars[$match[1]]['id'])) && (!isset($this->vars[$match[1]]['gedcom']))) { - $value = $this->vars[$match[1]]['id']; - } - } - $newattrs[$key] = $value; - } - $attrs = $newattrs; - if ($this->process_footnote && ($this->process_ifs === 0 || $name === 'if') && ($this->process_gedcoms === 0 || $name === 'Gedcom') && ($this->process_repeats === 0 || $name === 'Facts' || $name === 'RepeatTag')) { - $start_method = $name . 'StartHandler'; - $end_method = $name . 'EndHandler'; - if (method_exists($this, $start_method)) { - $this->$start_method($attrs); - } elseif (!method_exists($this, $end_method)) { - $this->htmlStartHandler($name, $attrs); - } - } - } + foreach ($attrs as $key => $value) { + if (preg_match("/^\\$(\w+)$/", $value, $match)) { + if ((isset($this->vars[$match[1]]['id'])) && (!isset($this->vars[$match[1]]['gedcom']))) { + $value = $this->vars[$match[1]]['id']; + } + } + $newattrs[$key] = $value; + } + $attrs = $newattrs; + if ($this->process_footnote && ($this->process_ifs === 0 || $name === 'if') && ($this->process_gedcoms === 0 || $name === 'Gedcom') && ($this->process_repeats === 0 || $name === 'Facts' || $name === 'RepeatTag')) { + $start_method = $name . 'StartHandler'; + $end_method = $name . 'EndHandler'; + if (method_exists($this, $start_method)) { + $this->$start_method($attrs); + } elseif (!method_exists($this, $end_method)) { + $this->htmlStartHandler($name, $attrs); + } + } + } - /** - * XML end element handler - * - * This function is called whenever an ending element is reached - * The element handler will be called if found, otherwise it must be HTML - * - * @param resource $parser the resource handler for the XML parser - * @param string $name the name of the XML element parsed - */ - protected function endElement($parser, $name) { - if (($this->process_footnote || $name === 'Footnote') && ($this->process_ifs === 0 || $name === 'if') && ($this->process_gedcoms === 0 || $name === 'Gedcom') && ($this->process_repeats === 0 || $name === 'Facts' || $name === 'RepeatTag' || $name === 'List' || $name === 'Relatives')) { - $start_method = $name . 'StartHandler'; - $end_method = $name . 'EndHandler'; - if (method_exists($this, $end_method)) { - $this->$end_method(); - } elseif (!method_exists($this, $start_method)) { - $this->htmlEndHandler($name); - } - } - } + /** + * XML end element handler + * + * This function is called whenever an ending element is reached + * The element handler will be called if found, otherwise it must be HTML + * + * @param resource $parser the resource handler for the XML parser + * @param string $name the name of the XML element parsed + */ + protected function endElement($parser, $name) + { + if (($this->process_footnote || $name === 'Footnote') && ($this->process_ifs === 0 || $name === 'if') && ($this->process_gedcoms === 0 || $name === 'Gedcom') && ($this->process_repeats === 0 || $name === 'Facts' || $name === 'RepeatTag' || $name === 'List' || $name === 'Relatives')) { + $start_method = $name . 'StartHandler'; + $end_method = $name . 'EndHandler'; + if (method_exists($this, $end_method)) { + $this->$end_method(); + } elseif (!method_exists($this, $start_method)) { + $this->htmlEndHandler($name); + } + } + } - /** - * XML character data handler - * - * @param resource $parser the resource handler for the XML parser - * @param string $data the name of the XML element parsed - */ - protected function characterData($parser, $data) { - if ($this->print_data && $this->process_gedcoms === 0 && $this->process_ifs === 0 && $this->process_repeats === 0) { - $this->current_element->addText($data); - } - } + /** + * XML character data handler + * + * @param resource $parser the resource handler for the XML parser + * @param string $data the name of the XML element parsed + */ + protected function characterData($parser, $data) + { + if ($this->print_data && $this->process_gedcoms === 0 && $this->process_ifs === 0 && $this->process_repeats === 0) { + $this->current_element->addText($data); + } + } - /** - * XML <style> - * - * @param array $attrs an array of key value pairs for the attributes - */ - private function styleStartHandler($attrs) { - if (empty($attrs['name'])) { - throw new \DomainException('REPORT ERROR Style: The "name" of the style is missing or not set in the XML file.'); - } + /** + * XML <style> + * + * @param array $attrs an array of key value pairs for the attributes + */ + private function styleStartHandler($attrs) + { + if (empty($attrs['name'])) { + throw new \DomainException('REPORT ERROR Style: The "name" of the style is missing or not set in the XML file.'); + } - // array Style that will be passed on - $s = []; + // array Style that will be passed on + $s = []; - // string Name af the style - $s['name'] = $attrs['name']; + // string Name af the style + $s['name'] = $attrs['name']; - // string Name of the DEFAULT font - $s['font'] = $this->wt_report->defaultFont; - if (!empty($attrs['font'])) { - $s['font'] = $attrs['font']; - } + // string Name of the DEFAULT font + $s['font'] = $this->wt_report->defaultFont; + if (!empty($attrs['font'])) { + $s['font'] = $attrs['font']; + } - // int The size of the font in points - $s['size'] = $this->wt_report->defaultFontSize; - if (!empty($attrs['size'])) { - $s['size'] = (int) $attrs['size']; - } // Get it as int to ignore all decimal points or text (if any text then int(0)) + // int The size of the font in points + $s['size'] = $this->wt_report->defaultFontSize; + if (!empty($attrs['size'])) { + $s['size'] = (int)$attrs['size']; + } // Get it as int to ignore all decimal points or text (if any text then int(0)) - // string B: bold, I: italic, U: underline, D: line trough, The default value is regular. - $s['style'] = ''; - if (!empty($attrs['style'])) { - $s['style'] = $attrs['style']; - } + // string B: bold, I: italic, U: underline, D: line trough, The default value is regular. + $s['style'] = ''; + if (!empty($attrs['style'])) { + $s['style'] = $attrs['style']; + } - $this->wt_report->addStyle($s); - } + $this->wt_report->addStyle($s); + } - /** - * XML <Doc> - * - * Sets up the basics of the document proparties - * - * @param array $attrs an array of key value pairs for the attributes - */ - private function docStartHandler($attrs) { - $this->parser = $this->xml_parser; + /** + * XML <Doc> + * + * Sets up the basics of the document proparties + * + * @param array $attrs an array of key value pairs for the attributes + */ + private function docStartHandler($attrs) + { + $this->parser = $this->xml_parser; - // Custom page width - if (!empty($attrs['customwidth'])) { - $this->wt_report->pagew = (int) $attrs['customwidth']; - } // Get it as int to ignore all decimal points or text (if any text then int(0)) - // Custom Page height - if (!empty($attrs['customheight'])) { - $this->wt_report->pageh = (int) $attrs['customheight']; - } // Get it as int to ignore all decimal points or text (if any text then int(0)) + // Custom page width + if (!empty($attrs['customwidth'])) { + $this->wt_report->pagew = (int)$attrs['customwidth']; + } // Get it as int to ignore all decimal points or text (if any text then int(0)) + // Custom Page height + if (!empty($attrs['customheight'])) { + $this->wt_report->pageh = (int)$attrs['customheight']; + } // Get it as int to ignore all decimal points or text (if any text then int(0)) - // Left Margin - if (isset($attrs['leftmargin'])) { - if ($attrs['leftmargin'] === '0') { - $this->wt_report->leftmargin = 0; - } elseif (!empty($attrs['leftmargin'])) { - $this->wt_report->leftmargin = (int) $attrs['leftmargin']; // Get it as int to ignore all decimal points or text (if any text then int(0)) - } - } - // Right Margin - if (isset($attrs['rightmargin'])) { - if ($attrs['rightmargin'] === '0') { - $this->wt_report->rightmargin = 0; - } elseif (!empty($attrs['rightmargin'])) { - $this->wt_report->rightmargin = (int) $attrs['rightmargin']; // Get it as int to ignore all decimal points or text (if any text then int(0)) - } - } - // Top Margin - if (isset($attrs['topmargin'])) { - if ($attrs['topmargin'] === '0') { - $this->wt_report->topmargin = 0; - } elseif (!empty($attrs['topmargin'])) { - $this->wt_report->topmargin = (int) $attrs['topmargin']; // Get it as int to ignore all decimal points or text (if any text then int(0)) - } - } - // Bottom Margin - if (isset($attrs['bottommargin'])) { - if ($attrs['bottommargin'] === '0') { - $this->wt_report->bottommargin = 0; - } elseif (!empty($attrs['bottommargin'])) { - $this->wt_report->bottommargin = (int) $attrs['bottommargin']; // Get it as int to ignore all decimal points or text (if any text then int(0)) - } - } - // Header Margin - if (isset($attrs['headermargin'])) { - if ($attrs['headermargin'] === '0') { - $this->wt_report->headermargin = 0; - } elseif (!empty($attrs['headermargin'])) { - $this->wt_report->headermargin = (int) $attrs['headermargin']; // Get it as int to ignore all decimal points or text (if any text then int(0)) - } - } - // Footer Margin - if (isset($attrs['footermargin'])) { - if ($attrs['footermargin'] === '0') { - $this->wt_report->footermargin = 0; - } elseif (!empty($attrs['footermargin'])) { - $this->wt_report->footermargin = (int) $attrs['footermargin']; // Get it as int to ignore all decimal points or text (if any text then int(0)) - } - } + // Left Margin + if (isset($attrs['leftmargin'])) { + if ($attrs['leftmargin'] === '0') { + $this->wt_report->leftmargin = 0; + } elseif (!empty($attrs['leftmargin'])) { + $this->wt_report->leftmargin = (int)$attrs['leftmargin']; // Get it as int to ignore all decimal points or text (if any text then int(0)) + } + } + // Right Margin + if (isset($attrs['rightmargin'])) { + if ($attrs['rightmargin'] === '0') { + $this->wt_report->rightmargin = 0; + } elseif (!empty($attrs['rightmargin'])) { + $this->wt_report->rightmargin = (int)$attrs['rightmargin']; // Get it as int to ignore all decimal points or text (if any text then int(0)) + } + } + // Top Margin + if (isset($attrs['topmargin'])) { + if ($attrs['topmargin'] === '0') { + $this->wt_report->topmargin = 0; + } elseif (!empty($attrs['topmargin'])) { + $this->wt_report->topmargin = (int)$attrs['topmargin']; // Get it as int to ignore all decimal points or text (if any text then int(0)) + } + } + // Bottom Margin + if (isset($attrs['bottommargin'])) { + if ($attrs['bottommargin'] === '0') { + $this->wt_report->bottommargin = 0; + } elseif (!empty($attrs['bottommargin'])) { + $this->wt_report->bottommargin = (int)$attrs['bottommargin']; // Get it as int to ignore all decimal points or text (if any text then int(0)) + } + } + // Header Margin + if (isset($attrs['headermargin'])) { + if ($attrs['headermargin'] === '0') { + $this->wt_report->headermargin = 0; + } elseif (!empty($attrs['headermargin'])) { + $this->wt_report->headermargin = (int)$attrs['headermargin']; // Get it as int to ignore all decimal points or text (if any text then int(0)) + } + } + // Footer Margin + if (isset($attrs['footermargin'])) { + if ($attrs['footermargin'] === '0') { + $this->wt_report->footermargin = 0; + } elseif (!empty($attrs['footermargin'])) { + $this->wt_report->footermargin = (int)$attrs['footermargin']; // Get it as int to ignore all decimal points or text (if any text then int(0)) + } + } - // Page Orientation - if (!empty($attrs['orientation'])) { - if ($attrs['orientation'] == 'landscape') { - $this->wt_report->orientation = 'landscape'; - } elseif ($attrs['orientation'] == 'portrait') { - $this->wt_report->orientation = 'portrait'; - } - } - // Page Size - if (!empty($attrs['pageSize'])) { - $this->wt_report->pageFormat = strtoupper($attrs['pageSize']); - } + // Page Orientation + if (!empty($attrs['orientation'])) { + if ($attrs['orientation'] == 'landscape') { + $this->wt_report->orientation = 'landscape'; + } elseif ($attrs['orientation'] == 'portrait') { + $this->wt_report->orientation = 'portrait'; + } + } + // Page Size + if (!empty($attrs['pageSize'])) { + $this->wt_report->pageFormat = strtoupper($attrs['pageSize']); + } - // Show Generated By... - if (isset($attrs['showGeneratedBy'])) { - if ($attrs['showGeneratedBy'] === '0') { - $this->wt_report->showGenText = false; - } elseif ($attrs['showGeneratedBy'] === '1') { - $this->wt_report->showGenText = true; - } - } + // Show Generated By... + if (isset($attrs['showGeneratedBy'])) { + if ($attrs['showGeneratedBy'] === '0') { + $this->wt_report->showGenText = false; + } elseif ($attrs['showGeneratedBy'] === '1') { + $this->wt_report->showGenText = true; + } + } - $this->wt_report->setup(); - } + $this->wt_report->setup(); + } - /** - * XML </Doc> - */ - private function docEndHandler() { - $this->wt_report->run(); - } + /** + * XML </Doc> + */ + private function docEndHandler() + { + $this->wt_report->run(); + } - /** - * XML <Header> - */ - private function headerStartHandler() { - // Clear the Header before any new elements are added - $this->wt_report->clearHeader(); - $this->wt_report->setProcessing('H'); - } + /** + * XML <Header> + */ + private function headerStartHandler() + { + // Clear the Header before any new elements are added + $this->wt_report->clearHeader(); + $this->wt_report->setProcessing('H'); + } - /** - * XML <PageHeader> - */ - private function pageHeaderStartHandler() { - array_push($this->print_data_stack, $this->print_data); - $this->print_data = false; - array_push($this->wt_report_stack, $this->wt_report); - $this->wt_report = $this->report_root->createPageHeader(); - } + /** + * XML <PageHeader> + */ + private function pageHeaderStartHandler() + { + array_push($this->print_data_stack, $this->print_data); + $this->print_data = false; + array_push($this->wt_report_stack, $this->wt_report); + $this->wt_report = $this->report_root->createPageHeader(); + } - /** - * XML <pageHeaderEndHandler> - */ - private function pageHeaderEndHandler() { - $this->print_data = array_pop($this->print_data_stack); - $this->current_element = $this->wt_report; - $this->wt_report = array_pop($this->wt_report_stack); - $this->wt_report->addElement($this->current_element); - } + /** + * XML <pageHeaderEndHandler> + */ + private function pageHeaderEndHandler() + { + $this->print_data = array_pop($this->print_data_stack); + $this->current_element = $this->wt_report; + $this->wt_report = array_pop($this->wt_report_stack); + $this->wt_report->addElement($this->current_element); + } - /** - * XML <bodyStartHandler> - */ - private function bodyStartHandler() { - $this->wt_report->setProcessing('B'); - } + /** + * XML <bodyStartHandler> + */ + private function bodyStartHandler() + { + $this->wt_report->setProcessing('B'); + } - /** - * XML <footerStartHandler> - */ - private function footerStartHandler() { - $this->wt_report->setProcessing('F'); - } + /** + * XML <footerStartHandler> + */ + private function footerStartHandler() + { + $this->wt_report->setProcessing('F'); + } - /** - * XML <Cell> - * - * @param array $attrs an array of key value pairs for the attributes - */ - private function cellStartHandler($attrs) { - // string The text alignment of the text in this box. - $align = ''; - if (!empty($attrs['align'])) { - $align = $attrs['align']; - // RTL supported left/right alignment - if ($align == 'rightrtl') { - if ($this->wt_report->rtl) { - $align = 'left'; - } else { - $align = 'right'; - } - } elseif ($align == 'leftrtl') { - if ($this->wt_report->rtl) { - $align = 'right'; - } else { - $align = 'left'; - } - } - } + /** + * XML <Cell> + * + * @param array $attrs an array of key value pairs for the attributes + */ + private function cellStartHandler($attrs) + { + // string The text alignment of the text in this box. + $align = ''; + if (!empty($attrs['align'])) { + $align = $attrs['align']; + // RTL supported left/right alignment + if ($align == 'rightrtl') { + if ($this->wt_report->rtl) { + $align = 'left'; + } else { + $align = 'right'; + } + } elseif ($align == 'leftrtl') { + if ($this->wt_report->rtl) { + $align = 'right'; + } else { + $align = 'left'; + } + } + } - // string The color to fill the background of this cell - $bgcolor = ''; - if (!empty($attrs['bgcolor'])) { - $bgcolor = $attrs['bgcolor']; - } + // string The color to fill the background of this cell + $bgcolor = ''; + if (!empty($attrs['bgcolor'])) { + $bgcolor = $attrs['bgcolor']; + } - // int Whether or not the background should be painted - $fill = 1; - if (isset($attrs['fill'])) { - if ($attrs['fill'] === '0') { - $fill = 0; - } elseif ($attrs['fill'] === '1') { - $fill = 1; - } - } + // int Whether or not the background should be painted + $fill = 1; + if (isset($attrs['fill'])) { + if ($attrs['fill'] === '0') { + $fill = 0; + } elseif ($attrs['fill'] === '1') { + $fill = 1; + } + } - $reseth = true; - // boolean if true reset the last cell height (default true) - if (isset($attrs['reseth'])) { - if ($attrs['reseth'] === '0') { - $reseth = false; - } elseif ($attrs['reseth'] === '1') { - $reseth = true; - } - } + $reseth = true; + // boolean if true reset the last cell height (default true) + if (isset($attrs['reseth'])) { + if ($attrs['reseth'] === '0') { + $reseth = false; + } elseif ($attrs['reseth'] === '1') { + $reseth = true; + } + } - // mixed Whether or not a border should be printed around this box - $border = 0; - if (!empty($attrs['border'])) { - $border = $attrs['border']; - } - // string Border color in HTML code - $bocolor = ''; - if (!empty($attrs['bocolor'])) { - $bocolor = $attrs['bocolor']; - } + // mixed Whether or not a border should be printed around this box + $border = 0; + if (!empty($attrs['border'])) { + $border = $attrs['border']; + } + // string Border color in HTML code + $bocolor = ''; + if (!empty($attrs['bocolor'])) { + $bocolor = $attrs['bocolor']; + } - // int Cell height (expressed in points) The starting height of this cell. If the text wraps the height will automatically be adjusted. - $height = 0; - if (!empty($attrs['height'])) { - $height = (int) $attrs['height']; - } - // int Cell width (expressed in points) Setting the width to 0 will make it the width from the current location to the right margin. - $width = 0; - if (!empty($attrs['width'])) { - $width = (int) $attrs['width']; - } + // int Cell height (expressed in points) The starting height of this cell. If the text wraps the height will automatically be adjusted. + $height = 0; + if (!empty($attrs['height'])) { + $height = (int)$attrs['height']; + } + // int Cell width (expressed in points) Setting the width to 0 will make it the width from the current location to the right margin. + $width = 0; + if (!empty($attrs['width'])) { + $width = (int)$attrs['width']; + } - // int Stretch carachter mode - $stretch = 0; - if (!empty($attrs['stretch'])) { - $stretch = (int) $attrs['stretch']; - } + // int Stretch carachter mode + $stretch = 0; + if (!empty($attrs['stretch'])) { + $stretch = (int)$attrs['stretch']; + } - // mixed Position the left corner of this box on the page. The default is the current position. - $left = '.'; - if (isset($attrs['left'])) { - if ($attrs['left'] === '.') { - $left = '.'; - } elseif (!empty($attrs['left'])) { - $left = (int) $attrs['left']; - } elseif ($attrs['left'] === '0') { - $left = 0; - } - } - // mixed Position the top corner of this box on the page. the default is the current position - $top = '.'; - if (isset($attrs['top'])) { - if ($attrs['top'] === '.') { - $top = '.'; - } elseif (!empty($attrs['top'])) { - $top = (int) $attrs['top']; - } elseif ($attrs['top'] === '0') { - $top = 0; - } - } + // mixed Position the left corner of this box on the page. The default is the current position. + $left = '.'; + if (isset($attrs['left'])) { + if ($attrs['left'] === '.') { + $left = '.'; + } elseif (!empty($attrs['left'])) { + $left = (int)$attrs['left']; + } elseif ($attrs['left'] === '0') { + $left = 0; + } + } + // mixed Position the top corner of this box on the page. the default is the current position + $top = '.'; + if (isset($attrs['top'])) { + if ($attrs['top'] === '.') { + $top = '.'; + } elseif (!empty($attrs['top'])) { + $top = (int)$attrs['top']; + } elseif ($attrs['top'] === '0') { + $top = 0; + } + } - // string The name of the Style that should be used to render the text. - $style = ''; - if (!empty($attrs['style'])) { - $style = $attrs['style']; - } + // string The name of the Style that should be used to render the text. + $style = ''; + if (!empty($attrs['style'])) { + $style = $attrs['style']; + } - // string Text color in html code - $tcolor = ''; - if (!empty($attrs['tcolor'])) { - $tcolor = $attrs['tcolor']; - } + // string Text color in html code + $tcolor = ''; + if (!empty($attrs['tcolor'])) { + $tcolor = $attrs['tcolor']; + } - // int Indicates where the current position should go after the call. - $ln = 0; - if (isset($attrs['newline'])) { - if (!empty($attrs['newline'])) { - $ln = (int) $attrs['newline']; - } elseif ($attrs['newline'] === '0') { - $ln = 0; - } - } + // int Indicates where the current position should go after the call. + $ln = 0; + if (isset($attrs['newline'])) { + if (!empty($attrs['newline'])) { + $ln = (int)$attrs['newline']; + } elseif ($attrs['newline'] === '0') { + $ln = 0; + } + } - if ($align == 'left') { - $align = 'L'; - } elseif ($align == 'right') { - $align = 'R'; - } elseif ($align == 'center') { - $align = 'C'; - } elseif ($align == 'justify') { - $align = 'J'; - } + if ($align == 'left') { + $align = 'L'; + } elseif ($align == 'right') { + $align = 'R'; + } elseif ($align == 'center') { + $align = 'C'; + } elseif ($align == 'justify') { + $align = 'J'; + } - array_push($this->print_data_stack, $this->print_data); - $this->print_data = true; + array_push($this->print_data_stack, $this->print_data); + $this->print_data = true; - $this->current_element = $this->report_root->createCell( - $width, - $height, - $border, - $align, - $bgcolor, - $style, - $ln, - $top, - $left, - $fill, - $stretch, - $bocolor, - $tcolor, - $reseth - ); - } + $this->current_element = $this->report_root->createCell( + $width, + $height, + $border, + $align, + $bgcolor, + $style, + $ln, + $top, + $left, + $fill, + $stretch, + $bocolor, + $tcolor, + $reseth + ); + } - /** - * XML </Cell> - */ - private function cellEndHandler() { - $this->print_data = array_pop($this->print_data_stack); - $this->wt_report->addElement($this->current_element); - } + /** + * XML </Cell> + */ + private function cellEndHandler() + { + $this->print_data = array_pop($this->print_data_stack); + $this->wt_report->addElement($this->current_element); + } - /** - * XML <Now /> element handler - */ - private function nowStartHandler() { - $g = FunctionsDate::timestampToGedcomDate(WT_TIMESTAMP + WT_TIMESTAMP_OFFSET); - $this->current_element->addText($g->display()); - } + /** + * XML <Now /> element handler + */ + private function nowStartHandler() + { + $g = FunctionsDate::timestampToGedcomDate(WT_TIMESTAMP + WT_TIMESTAMP_OFFSET); + $this->current_element->addText($g->display()); + } - /** - * XML <PageNum /> element handler - */ - private function pageNumStartHandler() { - $this->current_element->addText('#PAGENUM#'); - } + /** + * XML <PageNum /> element handler + */ + private function pageNumStartHandler() + { + $this->current_element->addText('#PAGENUM#'); + } - /** - * XML <TotalPages /> element handler - */ - private function totalPagesStartHandler() { - $this->current_element->addText('{{:ptp:}}'); - } + /** + * XML <TotalPages /> element handler + */ + private function totalPagesStartHandler() + { + $this->current_element->addText('{{:ptp:}}'); + } - /** - * Called at the start of an element. - * - * @param array $attrs an array of key value pairs for the attributes - */ - private function gedcomStartHandler($attrs) { - if ($this->process_gedcoms > 0) { - $this->process_gedcoms++; + /** + * Called at the start of an element. + * + * @param array $attrs an array of key value pairs for the attributes + */ + private function gedcomStartHandler($attrs) + { + if ($this->process_gedcoms > 0) { + $this->process_gedcoms++; - return; - } + return; + } - $tag = $attrs['id']; - $tag = str_replace('@fact', $this->fact, $tag); - $tags = explode(':', $tag); - $newgedrec = ''; - if (count($tags) < 2) { - $tmp = GedcomRecord::getInstance($attrs['id'], $this->tree); - $newgedrec = $tmp ? $tmp->privatizeGedcom(Auth::accessLevel($this->tree)) : ''; - } - if (empty($newgedrec)) { - $tgedrec = $this->gedrec; - $newgedrec = ''; - foreach ($tags as $tag) { - if (preg_match('/\$(.+)/', $tag, $match)) { - if (isset($this->vars[$match[1]]['gedcom'])) { - $newgedrec = $this->vars[$match[1]]['gedcom']; - } else { - $tmp = GedcomRecord::getInstance($match[1], $this->tree); - $newgedrec = $tmp ? $tmp->privatizeGedcom(Auth::accessLevel($this->tree)) : ''; - } - } else { - if (preg_match('/@(.+)/', $tag, $match)) { - $gmatch = []; - if (preg_match("/\d $match[1] @([^@]+)@/", $tgedrec, $gmatch)) { - $tmp = GedcomRecord::getInstance($gmatch[1], $this->tree); - $newgedrec = $tmp ? $tmp->privatizeGedcom(Auth::accessLevel($this->tree)) : ''; - $tgedrec = $newgedrec; - } else { - $newgedrec = ''; - break; - } - } else { - $temp = explode(' ', trim($tgedrec)); - $level = $temp[0] + 1; - $newgedrec = Functions::getSubRecord($level, "$level $tag", $tgedrec); - $tgedrec = $newgedrec; - } - } - } - } - if (!empty($newgedrec)) { - array_push($this->gedrec_stack, [$this->gedrec, $this->fact, $this->desc]); - $this->gedrec = $newgedrec; - if (preg_match("/(\d+) (_?[A-Z0-9]+) (.*)/", $this->gedrec, $match)) { - $this->fact = $match[2]; - $this->desc = trim($match[3]); - } - } else { - $this->process_gedcoms++; - } - } + $tag = $attrs['id']; + $tag = str_replace('@fact', $this->fact, $tag); + $tags = explode(':', $tag); + $newgedrec = ''; + if (count($tags) < 2) { + $tmp = GedcomRecord::getInstance($attrs['id'], $this->tree); + $newgedrec = $tmp ? $tmp->privatizeGedcom(Auth::accessLevel($this->tree)) : ''; + } + if (empty($newgedrec)) { + $tgedrec = $this->gedrec; + $newgedrec = ''; + foreach ($tags as $tag) { + if (preg_match('/\$(.+)/', $tag, $match)) { + if (isset($this->vars[$match[1]]['gedcom'])) { + $newgedrec = $this->vars[$match[1]]['gedcom']; + } else { + $tmp = GedcomRecord::getInstance($match[1], $this->tree); + $newgedrec = $tmp ? $tmp->privatizeGedcom(Auth::accessLevel($this->tree)) : ''; + } + } else { + if (preg_match('/@(.+)/', $tag, $match)) { + $gmatch = []; + if (preg_match("/\d $match[1] @([^@]+)@/", $tgedrec, $gmatch)) { + $tmp = GedcomRecord::getInstance($gmatch[1], $this->tree); + $newgedrec = $tmp ? $tmp->privatizeGedcom(Auth::accessLevel($this->tree)) : ''; + $tgedrec = $newgedrec; + } else { + $newgedrec = ''; + break; + } + } else { + $temp = explode(' ', trim($tgedrec)); + $level = $temp[0] + 1; + $newgedrec = Functions::getSubRecord($level, "$level $tag", $tgedrec); + $tgedrec = $newgedrec; + } + } + } + } + if (!empty($newgedrec)) { + array_push($this->gedrec_stack, [ + $this->gedrec, + $this->fact, + $this->desc, + ]); + $this->gedrec = $newgedrec; + if (preg_match("/(\d+) (_?[A-Z0-9]+) (.*)/", $this->gedrec, $match)) { + $this->fact = $match[2]; + $this->desc = trim($match[3]); + } + } else { + $this->process_gedcoms++; + } + } - /** - * Called at the end of an element. - */ - private function gedcomEndHandler() { - if ($this->process_gedcoms > 0) { - $this->process_gedcoms--; - } else { - list($this->gedrec, $this->fact, $this->desc) = array_pop($this->gedrec_stack); - } - } + /** + * Called at the end of an element. + */ + private function gedcomEndHandler() + { + if ($this->process_gedcoms > 0) { + $this->process_gedcoms--; + } else { + list($this->gedrec, $this->fact, $this->desc) = array_pop($this->gedrec_stack); + } + } - /** - * XML <textBoxStartHandler> - * - * @param array $attrs an array of key value pairs for the attributes - */ - private function textBoxStartHandler($attrs) { - // string Background color code - $bgcolor = ''; - if (!empty($attrs['bgcolor'])) { - $bgcolor = $attrs['bgcolor']; - } + /** + * XML <textBoxStartHandler> + * + * @param array $attrs an array of key value pairs for the attributes + */ + private function textBoxStartHandler($attrs) + { + // string Background color code + $bgcolor = ''; + if (!empty($attrs['bgcolor'])) { + $bgcolor = $attrs['bgcolor']; + } - // boolean Wether or not fill the background color - $fill = true; - if (isset($attrs['fill'])) { - if ($attrs['fill'] === '0') { - $fill = false; - } elseif ($attrs['fill'] === '1') { - $fill = true; - } - } + // boolean Wether or not fill the background color + $fill = true; + if (isset($attrs['fill'])) { + if ($attrs['fill'] === '0') { + $fill = false; + } elseif ($attrs['fill'] === '1') { + $fill = true; + } + } - // var boolean Whether or not a border should be printed around this box. 0 = no border, 1 = border. Default is 0 - $border = false; - if (isset($attrs['border'])) { - if ($attrs['border'] === '1') { - $border = true; - } elseif ($attrs['border'] === '0') { - $border = false; - } - } + // var boolean Whether or not a border should be printed around this box. 0 = no border, 1 = border. Default is 0 + $border = false; + if (isset($attrs['border'])) { + if ($attrs['border'] === '1') { + $border = true; + } elseif ($attrs['border'] === '0') { + $border = false; + } + } - // int The starting height of this cell. If the text wraps the height will automatically be adjusted - $height = 0; - if (!empty($attrs['height'])) { - $height = (int) $attrs['height']; - } - // int Setting the width to 0 will make it the width from the current location to the margin - $width = 0; - if (!empty($attrs['width'])) { - $width = (int) $attrs['width']; - } + // int The starting height of this cell. If the text wraps the height will automatically be adjusted + $height = 0; + if (!empty($attrs['height'])) { + $height = (int)$attrs['height']; + } + // int Setting the width to 0 will make it the width from the current location to the margin + $width = 0; + if (!empty($attrs['width'])) { + $width = (int)$attrs['width']; + } - // mixed Position the left corner of this box on the page. The default is the current position. - $left = '.'; - if (isset($attrs['left'])) { - if ($attrs['left'] === '.') { - $left = '.'; - } elseif (!empty($attrs['left'])) { - $left = (int) $attrs['left']; - } elseif ($attrs['left'] === '0') { - $left = 0; - } - } - // mixed Position the top corner of this box on the page. the default is the current position - $top = '.'; - if (isset($attrs['top'])) { - if ($attrs['top'] === '.') { - $top = '.'; - } elseif (!empty($attrs['top'])) { - $top = (int) $attrs['top']; - } elseif ($attrs['top'] === '0') { - $top = 0; - } - } - // boolean After this box is finished rendering, should the next section of text start immediately after the this box or should it start on a new line under this box. 0 = no new line, 1 = force new line. Default is 0 - $newline = false; - if (isset($attrs['newline'])) { - if ($attrs['newline'] === '1') { - $newline = true; - } elseif ($attrs['newline'] === '0') { - $newline = false; - } - } - // boolean - $pagecheck = true; - if (isset($attrs['pagecheck'])) { - if ($attrs['pagecheck'] === '0') { - $pagecheck = false; - } elseif ($attrs['pagecheck'] === '1') { - $pagecheck = true; - } - } - // boolean Cell padding - $padding = true; - if (isset($attrs['padding'])) { - if ($attrs['padding'] === '0') { - $padding = false; - } elseif ($attrs['padding'] === '1') { - $padding = true; - } - } - // boolean Reset this box Height - $reseth = false; - if (isset($attrs['reseth'])) { - if ($attrs['reseth'] === '1') { - $reseth = true; - } elseif ($attrs['reseth'] === '0') { - $reseth = false; - } - } + // mixed Position the left corner of this box on the page. The default is the current position. + $left = '.'; + if (isset($attrs['left'])) { + if ($attrs['left'] === '.') { + $left = '.'; + } elseif (!empty($attrs['left'])) { + $left = (int)$attrs['left']; + } elseif ($attrs['left'] === '0') { + $left = 0; + } + } + // mixed Position the top corner of this box on the page. the default is the current position + $top = '.'; + if (isset($attrs['top'])) { + if ($attrs['top'] === '.') { + $top = '.'; + } elseif (!empty($attrs['top'])) { + $top = (int)$attrs['top']; + } elseif ($attrs['top'] === '0') { + $top = 0; + } + } + // boolean After this box is finished rendering, should the next section of text start immediately after the this box or should it start on a new line under this box. 0 = no new line, 1 = force new line. Default is 0 + $newline = false; + if (isset($attrs['newline'])) { + if ($attrs['newline'] === '1') { + $newline = true; + } elseif ($attrs['newline'] === '0') { + $newline = false; + } + } + // boolean + $pagecheck = true; + if (isset($attrs['pagecheck'])) { + if ($attrs['pagecheck'] === '0') { + $pagecheck = false; + } elseif ($attrs['pagecheck'] === '1') { + $pagecheck = true; + } + } + // boolean Cell padding + $padding = true; + if (isset($attrs['padding'])) { + if ($attrs['padding'] === '0') { + $padding = false; + } elseif ($attrs['padding'] === '1') { + $padding = true; + } + } + // boolean Reset this box Height + $reseth = false; + if (isset($attrs['reseth'])) { + if ($attrs['reseth'] === '1') { + $reseth = true; + } elseif ($attrs['reseth'] === '0') { + $reseth = false; + } + } - // string Style of rendering - $style = ''; + // string Style of rendering + $style = ''; - array_push($this->print_data_stack, $this->print_data); - $this->print_data = false; + array_push($this->print_data_stack, $this->print_data); + $this->print_data = false; - array_push($this->wt_report_stack, $this->wt_report); - $this->wt_report = $this->report_root->createTextBox( - $width, - $height, - $border, - $bgcolor, - $newline, - $left, - $top, - $pagecheck, - $style, - $fill, - $padding, - $reseth - ); - } + array_push($this->wt_report_stack, $this->wt_report); + $this->wt_report = $this->report_root->createTextBox( + $width, + $height, + $border, + $bgcolor, + $newline, + $left, + $top, + $pagecheck, + $style, + $fill, + $padding, + $reseth + ); + } - /** - * XML <textBoxEndHandler> - */ - private function textBoxEndHandler() { - $this->print_data = array_pop($this->print_data_stack); - $this->current_element = $this->wt_report; - $this->wt_report = array_pop($this->wt_report_stack); - $this->wt_report->addElement($this->current_element); - } + /** + * XML <textBoxEndHandler> + */ + private function textBoxEndHandler() + { + $this->print_data = array_pop($this->print_data_stack); + $this->current_element = $this->wt_report; + $this->wt_report = array_pop($this->wt_report_stack); + $this->wt_report->addElement($this->current_element); + } - /** - * XLM <Text>. - * - * @param array $attrs an array of key value pairs for the attributes - */ - private function textStartHandler($attrs) { - array_push($this->print_data_stack, $this->print_data); - $this->print_data = true; + /** + * XLM <Text>. + * + * @param array $attrs an array of key value pairs for the attributes + */ + private function textStartHandler($attrs) + { + array_push($this->print_data_stack, $this->print_data); + $this->print_data = true; - // string The name of the Style that should be used to render the text. - $style = ''; - if (!empty($attrs['style'])) { - $style = $attrs['style']; - } + // string The name of the Style that should be used to render the text. + $style = ''; + if (!empty($attrs['style'])) { + $style = $attrs['style']; + } - // string The color of the text - Keep the black color as default - $color = ''; - if (!empty($attrs['color'])) { - $color = $attrs['color']; - } + // string The color of the text - Keep the black color as default + $color = ''; + if (!empty($attrs['color'])) { + $color = $attrs['color']; + } - $this->current_element = $this->report_root->createText($style, $color); - } + $this->current_element = $this->report_root->createText($style, $color); + } - /** - * XML </Text> - */ - private function textEndHandler() { - $this->print_data = array_pop($this->print_data_stack); - $this->wt_report->addElement($this->current_element); - } + /** + * XML </Text> + */ + private function textEndHandler() + { + $this->print_data = array_pop($this->print_data_stack); + $this->wt_report->addElement($this->current_element); + } - /** - * XML <GetPersonName/> - * - * Get the name - * 1. id is empty - current GEDCOM record - * 2. id is set with a record id - * - * @param array $attrs an array of key value pairs for the attributes - */ - private function getPersonNameStartHandler($attrs) { - $id = ''; - $match = []; - if (empty($attrs['id'])) { - if (preg_match('/0 @(.+)@/', $this->gedrec, $match)) { - $id = $match[1]; - } - } else { - if (preg_match('/\$(.+)/', $attrs['id'], $match)) { - if (isset($this->vars[$match[1]]['id'])) { - $id = $this->vars[$match[1]]['id']; - } - } else { - if (preg_match('/@(.+)/', $attrs['id'], $match)) { - $gmatch = []; - if (preg_match("/\d $match[1] @([^@]+)@/", $this->gedrec, $gmatch)) { - $id = $gmatch[1]; - } - } else { - $id = $attrs['id']; - } - } - } - if (!empty($id)) { - $record = GedcomRecord::getInstance($id, $this->tree); - if (is_null($record)) { - return; - } - if (!$record->canShowName()) { - $this->current_element->addText(I18N::translate('Private')); - } else { - $name = $record->getFullName(); - $name = preg_replace( - ['/<span class="starredname">/', '/<\/span><\/span>/', '/<\/span>/'], - ['«', '', '»'], - $name - ); - $name = strip_tags($name); - if (!empty($attrs['truncate'])) { - if (mb_strlen($name) > $attrs['truncate']) { - $name = preg_replace("/\(.*\) ?/", '', $name); //removes () and text inbetween - what about ", [ and { etc? - $words = preg_split('/[, -]+/', $name); // names separated with space, comma or hyphen - any others? - $name = $words[count($words) - 1]; - for ($i = count($words) - 2; $i >= 0; $i--) { - $len = mb_strlen($name); - for ($j = count($words) - 3; $j >= 0; $j--) { - $len += mb_strlen($words[$j]); - } - if ($len > $attrs['truncate']) { - $first_letter = mb_substr($words[$i], 0, 1); - // Do not show " of nick-names - if ($first_letter != '"') { - $name = mb_substr($words[$i], 0, 1) . '. ' . $name; - } - } else { - $name = $words[$i] . ' ' . $name; - } - } - } - } else { - $addname = $record->getAddName(); - $addname = preg_replace( - ['/<span class="starredname">/', '/<\/span><\/span>/', '/<\/span>/'], - ['«', '', '»'], - $addname - ); - $addname = strip_tags($addname); - if (!empty($addname)) { - $name .= ' ' . $addname; - } - } - $this->current_element->addText(trim($name)); - } - } - } + /** + * XML <GetPersonName/> + * + * Get the name + * 1. id is empty - current GEDCOM record + * 2. id is set with a record id + * + * @param array $attrs an array of key value pairs for the attributes + */ + private function getPersonNameStartHandler($attrs) + { + $id = ''; + $match = []; + if (empty($attrs['id'])) { + if (preg_match('/0 @(.+)@/', $this->gedrec, $match)) { + $id = $match[1]; + } + } else { + if (preg_match('/\$(.+)/', $attrs['id'], $match)) { + if (isset($this->vars[$match[1]]['id'])) { + $id = $this->vars[$match[1]]['id']; + } + } else { + if (preg_match('/@(.+)/', $attrs['id'], $match)) { + $gmatch = []; + if (preg_match("/\d $match[1] @([^@]+)@/", $this->gedrec, $gmatch)) { + $id = $gmatch[1]; + } + } else { + $id = $attrs['id']; + } + } + } + if (!empty($id)) { + $record = GedcomRecord::getInstance($id, $this->tree); + if (is_null($record)) { + return; + } + if (!$record->canShowName()) { + $this->current_element->addText(I18N::translate('Private')); + } else { + $name = $record->getFullName(); + $name = preg_replace( + [ + '/<span class="starredname">/', + '/<\/span><\/span>/', + '/<\/span>/', + ], + [ + '«', + '', + '»', + ], + $name + ); + $name = strip_tags($name); + if (!empty($attrs['truncate'])) { + if (mb_strlen($name) > $attrs['truncate']) { + $name = preg_replace("/\(.*\) ?/", '', $name); //removes () and text inbetween - what about ", [ and { etc? + $words = preg_split('/[, -]+/', $name); // names separated with space, comma or hyphen - any others? + $name = $words[count($words) - 1]; + for ($i = count($words) - 2; $i >= 0; $i--) { + $len = mb_strlen($name); + for ($j = count($words) - 3; $j >= 0; $j--) { + $len += mb_strlen($words[$j]); + } + if ($len > $attrs['truncate']) { + $first_letter = mb_substr($words[$i], 0, 1); + // Do not show " of nick-names + if ($first_letter != '"') { + $name = mb_substr($words[$i], 0, 1) . '. ' . $name; + } + } else { + $name = $words[$i] . ' ' . $name; + } + } + } + } else { + $addname = $record->getAddName(); + $addname = preg_replace( + [ + '/<span class="starredname">/', + '/<\/span><\/span>/', + '/<\/span>/', + ], + [ + '«', + '', + '»', + ], + $addname + ); + $addname = strip_tags($addname); + if (!empty($addname)) { + $name .= ' ' . $addname; + } + } + $this->current_element->addText(trim($name)); + } + } + } - /** - * XML <GedcomValue/> - * - * @param array $attrs an array of key value pairs for the attributes - */ - private function gedcomValueStartHandler($attrs) { - $id = ''; - $match = []; - if (preg_match('/0 @(.+)@/', $this->gedrec, $match)) { - $id = $match[1]; - } + /** + * XML <GedcomValue/> + * + * @param array $attrs an array of key value pairs for the attributes + */ + private function gedcomValueStartHandler($attrs) + { + $id = ''; + $match = []; + if (preg_match('/0 @(.+)@/', $this->gedrec, $match)) { + $id = $match[1]; + } - if (isset($attrs['newline']) && $attrs['newline'] == '1') { - $useBreak = '1'; - } else { - $useBreak = '0'; - } + if (isset($attrs['newline']) && $attrs['newline'] == '1') { + $useBreak = '1'; + } else { + $useBreak = '0'; + } - $tag = $attrs['tag']; - if (!empty($tag)) { - if ($tag == '@desc') { - $value = $this->desc; - $value = trim($value); - $this->current_element->addText($value); - } - if ($tag == '@id') { - $this->current_element->addText($id); - } else { - $tag = str_replace('@fact', $this->fact, $tag); - if (empty($attrs['level'])) { - $temp = explode(' ', trim($this->gedrec)); - $level = $temp[0]; - if ($level == 0) { - $level++; - } - } else { - $level = $attrs['level']; - } - $tags = preg_split('/[: ]/', $tag); - $value = $this->getGedcomValue($tag, $level, $this->gedrec); - switch (end($tags)) { - case 'DATE': - $tmp = new Date($value); - $value = $tmp->display(); - break; - case 'PLAC': - $tmp = new Place($value, $this->tree); - $value = $tmp->getShortName(); - break; - } - if ($useBreak == '1') { - // Insert <br> when multiple dates exist. - // This works around a TCPDF bug that incorrectly wraps RTL dates on LTR pages - $value = str_replace('(', '<br>(', $value); - $value = str_replace('<span dir="ltr"><br>', '<br><span dir="ltr">', $value); - $value = str_replace('<span dir="rtl"><br>', '<br><span dir="rtl">', $value); - if (substr($value, 0, 6) == '<br>') { - $value = substr($value, 6); - } - } - $tmp = explode(':', $tag); - if (in_array(end($tmp), ['NOTE', 'TEXT'])) { - $value = Filter::formatText($value, $this->tree); // We'll strip HTML in addText() - } - $this->current_element->addText($value); - } - } - } + $tag = $attrs['tag']; + if (!empty($tag)) { + if ($tag == '@desc') { + $value = $this->desc; + $value = trim($value); + $this->current_element->addText($value); + } + if ($tag == '@id') { + $this->current_element->addText($id); + } else { + $tag = str_replace('@fact', $this->fact, $tag); + if (empty($attrs['level'])) { + $temp = explode(' ', trim($this->gedrec)); + $level = $temp[0]; + if ($level == 0) { + $level++; + } + } else { + $level = $attrs['level']; + } + $tags = preg_split('/[: ]/', $tag); + $value = $this->getGedcomValue($tag, $level, $this->gedrec); + switch (end($tags)) { + case 'DATE': + $tmp = new Date($value); + $value = $tmp->display(); + break; + case 'PLAC': + $tmp = new Place($value, $this->tree); + $value = $tmp->getShortName(); + break; + } + if ($useBreak == '1') { + // Insert <br> when multiple dates exist. + // This works around a TCPDF bug that incorrectly wraps RTL dates on LTR pages + $value = str_replace('(', '<br>(', $value); + $value = str_replace('<span dir="ltr"><br>', '<br><span dir="ltr">', $value); + $value = str_replace('<span dir="rtl"><br>', '<br><span dir="rtl">', $value); + if (substr($value, 0, 6) == '<br>') { + $value = substr($value, 6); + } + } + $tmp = explode(':', $tag); + if (in_array(end($tmp), [ + 'NOTE', + 'TEXT', + ])) { + $value = Filter::formatText($value, $this->tree); // We'll strip HTML in addText() + } + $this->current_element->addText($value); + } + } + } - /** - * XML <RepeatTag> - * - * @param array $attrs an array of key value pairs for the attributes - */ - private function repeatTagStartHandler($attrs) { - $this->process_repeats++; - if ($this->process_repeats > 1) { - return; - } + /** + * XML <RepeatTag> + * + * @param array $attrs an array of key value pairs for the attributes + */ + private function repeatTagStartHandler($attrs) + { + $this->process_repeats++; + if ($this->process_repeats > 1) { + return; + } - array_push($this->repeats_stack, [$this->repeats, $this->repeat_bytes]); - $this->repeats = []; - $this->repeat_bytes = xml_get_current_line_number($this->parser); + array_push($this->repeats_stack, [ + $this->repeats, + $this->repeat_bytes, + ]); + $this->repeats = []; + $this->repeat_bytes = xml_get_current_line_number($this->parser); - $tag = ''; - if (isset($attrs['tag'])) { - $tag = $attrs['tag']; - } - if (!empty($tag)) { - if ($tag == '@desc') { - $value = $this->desc; - $value = trim($value); - $this->current_element->addText($value); - } else { - $tag = str_replace('@fact', $this->fact, $tag); - $tags = explode(':', $tag); - $temp = explode(' ', trim($this->gedrec)); - $level = $temp[0]; - if ($level == 0) { - $level++; - } - $subrec = $this->gedrec; - $t = $tag; - $count = count($tags); - $i = 0; - while ($i < $count) { - $t = $tags[$i]; - if (!empty($t)) { - if ($i < ($count - 1)) { - $subrec = Functions::getSubRecord($level, "$level $t", $subrec); - if (empty($subrec)) { - $level--; - $subrec = Functions::getSubRecord($level, "@ $t", $this->gedrec); - if (empty($subrec)) { - return; - } - } - } - $level++; - } - $i++; - } - $level--; - $count = preg_match_all("/$level $t(.*)/", $subrec, $match, PREG_SET_ORDER); - $i = 0; - while ($i < $count) { - $i++; - // Privacy check - is this a link, and are we allowed to view the linked object? - $subrecord = Functions::getSubRecord($level, "$level $t", $subrec, $i); - if (preg_match('/^\d ' . WT_REGEX_TAG . ' @(' . WT_REGEX_XREF . ')@/', $subrecord, $xref_match)) { - $linked_object = GedcomRecord::getInstance($xref_match[1], $this->tree); - if ($linked_object && !$linked_object->canShow()) { - continue; - } - } - $this->repeats[] = $subrecord; - } - } - } - } + $tag = ''; + if (isset($attrs['tag'])) { + $tag = $attrs['tag']; + } + if (!empty($tag)) { + if ($tag == '@desc') { + $value = $this->desc; + $value = trim($value); + $this->current_element->addText($value); + } else { + $tag = str_replace('@fact', $this->fact, $tag); + $tags = explode(':', $tag); + $temp = explode(' ', trim($this->gedrec)); + $level = $temp[0]; + if ($level == 0) { + $level++; + } + $subrec = $this->gedrec; + $t = $tag; + $count = count($tags); + $i = 0; + while ($i < $count) { + $t = $tags[$i]; + if (!empty($t)) { + if ($i < ($count - 1)) { + $subrec = Functions::getSubRecord($level, "$level $t", $subrec); + if (empty($subrec)) { + $level--; + $subrec = Functions::getSubRecord($level, "@ $t", $this->gedrec); + if (empty($subrec)) { + return; + } + } + } + $level++; + } + $i++; + } + $level--; + $count = preg_match_all("/$level $t(.*)/", $subrec, $match, PREG_SET_ORDER); + $i = 0; + while ($i < $count) { + $i++; + // Privacy check - is this a link, and are we allowed to view the linked object? + $subrecord = Functions::getSubRecord($level, "$level $t", $subrec, $i); + if (preg_match('/^\d ' . WT_REGEX_TAG . ' @(' . WT_REGEX_XREF . ')@/', $subrecord, $xref_match)) { + $linked_object = GedcomRecord::getInstance($xref_match[1], $this->tree); + if ($linked_object && !$linked_object->canShow()) { + continue; + } + } + $this->repeats[] = $subrecord; + } + } + } + } - /** - * XML </ RepeatTag> - */ - private function repeatTagEndHandler() { - $this->process_repeats--; - if ($this->process_repeats > 0) { - return; - } + /** + * XML </ RepeatTag> + */ + private function repeatTagEndHandler() + { + $this->process_repeats--; + if ($this->process_repeats > 0) { + return; + } - // Check if there is anything to repeat - if (count($this->repeats) > 0) { - // No need to load them if not used... + // Check if there is anything to repeat + if (count($this->repeats) > 0) { + // No need to load them if not used... - $lineoffset = 0; - foreach ($this->repeats_stack as $rep) { - $lineoffset += $rep[1]; - } - //-- read the xml from the file - $lines = file($this->report); - while (strpos($lines[$lineoffset + $this->repeat_bytes], '<RepeatTag') === false) { - $lineoffset--; - } - $lineoffset++; - $reportxml = "<tempdoc>\n"; - $line_nr = $lineoffset + $this->repeat_bytes; - // RepeatTag Level counter - $count = 1; - while (0 < $count) { - if (strstr($lines[$line_nr], '<RepeatTag') !== false) { - $count++; - } elseif (strstr($lines[$line_nr], '</RepeatTag') !== false) { - $count--; - } - if (0 < $count) { - $reportxml .= $lines[$line_nr]; - } - $line_nr++; - } - // No need to drag this - unset($lines); - $reportxml .= "</tempdoc>\n"; - // Save original values - array_push($this->parser_stack, $this->parser); - $oldgedrec = $this->gedrec; - foreach ($this->repeats as $gedrec) { - $this->gedrec = $gedrec; - $repeat_parser = xml_parser_create(); - $this->parser = $repeat_parser; - xml_parser_set_option($repeat_parser, XML_OPTION_CASE_FOLDING, false); - xml_set_element_handler($repeat_parser, [$this, 'startElement'], [$this, 'endElement']); - xml_set_character_data_handler($repeat_parser, [$this, 'characterData']); - if (!xml_parse($repeat_parser, $reportxml, true)) { - throw new \DomainException(sprintf( - 'RepeatTagEHandler XML error: %s at line %d', - xml_error_string(xml_get_error_code($repeat_parser)), - xml_get_current_line_number($repeat_parser) - )); - } - xml_parser_free($repeat_parser); - } - // Restore original values - $this->gedrec = $oldgedrec; - $this->parser = array_pop($this->parser_stack); - } - list($this->repeats, $this->repeat_bytes) = array_pop($this->repeats_stack); - } + $lineoffset = 0; + foreach ($this->repeats_stack as $rep) { + $lineoffset += $rep[1]; + } + //-- read the xml from the file + $lines = file($this->report); + while (strpos($lines[$lineoffset + $this->repeat_bytes], '<RepeatTag') === false) { + $lineoffset--; + } + $lineoffset++; + $reportxml = "<tempdoc>\n"; + $line_nr = $lineoffset + $this->repeat_bytes; + // RepeatTag Level counter + $count = 1; + while (0 < $count) { + if (strstr($lines[$line_nr], '<RepeatTag') !== false) { + $count++; + } elseif (strstr($lines[$line_nr], '</RepeatTag') !== false) { + $count--; + } + if (0 < $count) { + $reportxml .= $lines[$line_nr]; + } + $line_nr++; + } + // No need to drag this + unset($lines); + $reportxml .= "</tempdoc>\n"; + // Save original values + array_push($this->parser_stack, $this->parser); + $oldgedrec = $this->gedrec; + foreach ($this->repeats as $gedrec) { + $this->gedrec = $gedrec; + $repeat_parser = xml_parser_create(); + $this->parser = $repeat_parser; + xml_parser_set_option($repeat_parser, XML_OPTION_CASE_FOLDING, false); + xml_set_element_handler($repeat_parser, [ + $this, + 'startElement', + ], [ + $this, + 'endElement', + ]); + xml_set_character_data_handler($repeat_parser, [ + $this, + 'characterData', + ]); + if (!xml_parse($repeat_parser, $reportxml, true)) { + throw new \DomainException(sprintf( + 'RepeatTagEHandler XML error: %s at line %d', + xml_error_string(xml_get_error_code($repeat_parser)), + xml_get_current_line_number($repeat_parser) + )); + } + xml_parser_free($repeat_parser); + } + // Restore original values + $this->gedrec = $oldgedrec; + $this->parser = array_pop($this->parser_stack); + } + list($this->repeats, $this->repeat_bytes) = array_pop($this->repeats_stack); + } - /** - * Variable lookup - * - * Retrieve predefined variables : - * - * @ desc GEDCOM fact description, example: - * 1 EVEN This is a description - * @ fact GEDCOM fact tag, such as BIRT, DEAT etc. - * $ I18N::translate('....') - * $ language_settings[] - * - * @param array $attrs an array of key value pairs for the attributes - */ - private function varStartHandler($attrs) { - if (empty($attrs['var'])) { - throw new \DomainException('REPORT ERROR var: The attribute "var=" is missing or not set in the XML file on line: ' . xml_get_current_line_number($this->parser)); - } + /** + * Variable lookup + * + * Retrieve predefined variables : + * + * @ desc GEDCOM fact description, example: + * 1 EVEN This is a description + * @ fact GEDCOM fact tag, such as BIRT, DEAT etc. + * $ I18N::translate('....') + * $ language_settings[] + * + * @param array $attrs an array of key value pairs for the attributes + */ + private function varStartHandler($attrs) + { + if (empty($attrs['var'])) { + throw new \DomainException('REPORT ERROR var: The attribute "var=" is missing or not set in the XML file on line: ' . xml_get_current_line_number($this->parser)); + } - $var = $attrs['var']; - // SetVar element preset variables - if (!empty($this->vars[$var]['id'])) { - $var = $this->vars[$var]['id']; - } else { - $tfact = $this->fact; - if (($this->fact === 'EVEN' || $this->fact === 'FACT') && $this->type !== ' ') { - // Use : - // n TYPE This text if string - $tfact = $this->type; - } - $var = str_replace(['@fact', '@desc'], [GedcomTag::getLabel($tfact), $this->desc], $var); - if (preg_match('/^I18N::number\((.+)\)$/', $var, $match)) { - $var = I18N::number($match[1]); - } elseif (preg_match('/^I18N::translate\(\'(.+)\'\)$/', $var, $match)) { - $var = I18N::translate($match[1]); - } elseif (preg_match('/^I18N::translateContext\(\'(.+)\', *\'(.+)\'\)$/', $var, $match)) { - $var = I18N::translateContext($match[1], $match[2]); - } - } - // Check if variable is set as a date and reformat the date - if (isset($attrs['date'])) { - if ($attrs['date'] === '1') { - $g = new Date($var); - $var = $g->display(); - } - } - $this->current_element->addText($var); - $this->text = $var; // Used for title/descriptio - } + $var = $attrs['var']; + // SetVar element preset variables + if (!empty($this->vars[$var]['id'])) { + $var = $this->vars[$var]['id']; + } else { + $tfact = $this->fact; + if (($this->fact === 'EVEN' || $this->fact === 'FACT') && $this->type !== ' ') { + // Use : + // n TYPE This text if string + $tfact = $this->type; + } + $var = str_replace([ + '@fact', + '@desc', + ], [ + GedcomTag::getLabel($tfact), + $this->desc, + ], $var); + if (preg_match('/^I18N::number\((.+)\)$/', $var, $match)) { + $var = I18N::number($match[1]); + } elseif (preg_match('/^I18N::translate\(\'(.+)\'\)$/', $var, $match)) { + $var = I18N::translate($match[1]); + } elseif (preg_match('/^I18N::translateContext\(\'(.+)\', *\'(.+)\'\)$/', $var, $match)) { + $var = I18N::translateContext($match[1], $match[2]); + } + } + // Check if variable is set as a date and reformat the date + if (isset($attrs['date'])) { + if ($attrs['date'] === '1') { + $g = new Date($var); + $var = $g->display(); + } + } + $this->current_element->addText($var); + $this->text = $var; // Used for title/descriptio + } - /** - * XML <Facts> - * - * @param array $attrs an array of key value pairs for the attributes - */ - private function factsStartHandler($attrs) { - $this->process_repeats++; - if ($this->process_repeats > 1) { - return; - } + /** + * XML <Facts> + * + * @param array $attrs an array of key value pairs for the attributes + */ + private function factsStartHandler($attrs) + { + $this->process_repeats++; + if ($this->process_repeats > 1) { + return; + } - array_push($this->repeats_stack, [$this->repeats, $this->repeat_bytes]); - $this->repeats = []; - $this->repeat_bytes = xml_get_current_line_number($this->parser); + array_push($this->repeats_stack, [ + $this->repeats, + $this->repeat_bytes, + ]); + $this->repeats = []; + $this->repeat_bytes = xml_get_current_line_number($this->parser); - $id = ''; - $match = []; - if (preg_match('/0 @(.+)@/', $this->gedrec, $match)) { - $id = $match[1]; - } - $tag = ''; - if (isset($attrs['ignore'])) { - $tag .= $attrs['ignore']; - } - if (preg_match('/\$(.+)/', $tag, $match)) { - $tag = $this->vars[$match[1]]['id']; - } + $id = ''; + $match = []; + if (preg_match('/0 @(.+)@/', $this->gedrec, $match)) { + $id = $match[1]; + } + $tag = ''; + if (isset($attrs['ignore'])) { + $tag .= $attrs['ignore']; + } + if (preg_match('/\$(.+)/', $tag, $match)) { + $tag = $this->vars[$match[1]]['id']; + } - $record = GedcomRecord::getInstance($id, $this->tree); - if (empty($attrs['diff']) && !empty($id)) { - $facts = $record->getFacts(); - Functions::sortFacts($facts); - $this->repeats = []; - $nonfacts = explode(',', $tag); - foreach ($facts as $event) { - if (!in_array($event->getTag(), $nonfacts)) { - $this->repeats[] = $event->getGedcom(); - } - } - } else { - foreach ($record->getFacts() as $fact) { - if ($fact->isPendingAddition() && $fact->getTag() !== 'CHAN') { - $this->repeats[] = $fact->getGedcom(); - } - } - } - } + $record = GedcomRecord::getInstance($id, $this->tree); + if (empty($attrs['diff']) && !empty($id)) { + $facts = $record->getFacts(); + Functions::sortFacts($facts); + $this->repeats = []; + $nonfacts = explode(',', $tag); + foreach ($facts as $event) { + if (!in_array($event->getTag(), $nonfacts)) { + $this->repeats[] = $event->getGedcom(); + } + } + } else { + foreach ($record->getFacts() as $fact) { + if ($fact->isPendingAddition() && $fact->getTag() !== 'CHAN') { + $this->repeats[] = $fact->getGedcom(); + } + } + } + } - /** - * XML </Facts> - */ - private function factsEndHandler() { - $this->process_repeats--; - if ($this->process_repeats > 0) { - return; - } + /** + * XML </Facts> + */ + private function factsEndHandler() + { + $this->process_repeats--; + if ($this->process_repeats > 0) { + return; + } - // Check if there is anything to repeat - if (count($this->repeats) > 0) { - $line = xml_get_current_line_number($this->parser) - 1; - $lineoffset = 0; - foreach ($this->repeats_stack as $rep) { - $lineoffset += $rep[1]; - } + // Check if there is anything to repeat + if (count($this->repeats) > 0) { + $line = xml_get_current_line_number($this->parser) - 1; + $lineoffset = 0; + foreach ($this->repeats_stack as $rep) { + $lineoffset += $rep[1]; + } - //-- read the xml from the file - $lines = file($this->report); - while ($lineoffset + $this->repeat_bytes > 0 && strpos($lines[$lineoffset + $this->repeat_bytes], '<Facts ') === false) { - $lineoffset--; - } - $lineoffset++; - $reportxml = "<tempdoc>\n"; - $i = $line + $lineoffset; - $line_nr = $this->repeat_bytes + $lineoffset; - while ($line_nr < $i) { - $reportxml .= $lines[$line_nr]; - $line_nr++; - } - // No need to drag this - unset($lines); - $reportxml .= "</tempdoc>\n"; - // Save original values - array_push($this->parser_stack, $this->parser); - $oldgedrec = $this->gedrec; - $count = count($this->repeats); - $i = 0; - while ($i < $count) { - $this->gedrec = $this->repeats[$i]; - $this->fact = ''; - $this->desc = ''; - if (preg_match('/1 (\w+)(.*)/', $this->gedrec, $match)) { - $this->fact = $match[1]; - if ($this->fact === 'EVEN' || $this->fact === 'FACT') { - $tmatch = []; - if (preg_match('/2 TYPE (.+)/', $this->gedrec, $tmatch)) { - $this->type = trim($tmatch[1]); - } else { - $this->type = ' '; - } - } - $this->desc = trim($match[2]); - $this->desc .= Functions::getCont(2, $this->gedrec); - } - $repeat_parser = xml_parser_create(); - $this->parser = $repeat_parser; - xml_parser_set_option($repeat_parser, XML_OPTION_CASE_FOLDING, false); - xml_set_element_handler($repeat_parser, [$this, 'startElement'], [$this, 'endElement']); - xml_set_character_data_handler($repeat_parser, [$this, 'characterData']); - if (!xml_parse($repeat_parser, $reportxml, true)) { - throw new \DomainException(sprintf( - 'FactsEHandler XML error: %s at line %d', - xml_error_string(xml_get_error_code($repeat_parser)), - xml_get_current_line_number($repeat_parser) - )); - } - xml_parser_free($repeat_parser); - $i++; - } - // Restore original values - $this->parser = array_pop($this->parser_stack); - $this->gedrec = $oldgedrec; - } - list($this->repeats, $this->repeat_bytes) = array_pop($this->repeats_stack); - } + //-- read the xml from the file + $lines = file($this->report); + while ($lineoffset + $this->repeat_bytes > 0 && strpos($lines[$lineoffset + $this->repeat_bytes], '<Facts ') === false) { + $lineoffset--; + } + $lineoffset++; + $reportxml = "<tempdoc>\n"; + $i = $line + $lineoffset; + $line_nr = $this->repeat_bytes + $lineoffset; + while ($line_nr < $i) { + $reportxml .= $lines[$line_nr]; + $line_nr++; + } + // No need to drag this + unset($lines); + $reportxml .= "</tempdoc>\n"; + // Save original values + array_push($this->parser_stack, $this->parser); + $oldgedrec = $this->gedrec; + $count = count($this->repeats); + $i = 0; + while ($i < $count) { + $this->gedrec = $this->repeats[$i]; + $this->fact = ''; + $this->desc = ''; + if (preg_match('/1 (\w+)(.*)/', $this->gedrec, $match)) { + $this->fact = $match[1]; + if ($this->fact === 'EVEN' || $this->fact === 'FACT') { + $tmatch = []; + if (preg_match('/2 TYPE (.+)/', $this->gedrec, $tmatch)) { + $this->type = trim($tmatch[1]); + } else { + $this->type = ' '; + } + } + $this->desc = trim($match[2]); + $this->desc .= Functions::getCont(2, $this->gedrec); + } + $repeat_parser = xml_parser_create(); + $this->parser = $repeat_parser; + xml_parser_set_option($repeat_parser, XML_OPTION_CASE_FOLDING, false); + xml_set_element_handler($repeat_parser, [ + $this, + 'startElement', + ], [ + $this, + 'endElement', + ]); + xml_set_character_data_handler($repeat_parser, [ + $this, + 'characterData', + ]); + if (!xml_parse($repeat_parser, $reportxml, true)) { + throw new \DomainException(sprintf( + 'FactsEHandler XML error: %s at line %d', + xml_error_string(xml_get_error_code($repeat_parser)), + xml_get_current_line_number($repeat_parser) + )); + } + xml_parser_free($repeat_parser); + $i++; + } + // Restore original values + $this->parser = array_pop($this->parser_stack); + $this->gedrec = $oldgedrec; + } + list($this->repeats, $this->repeat_bytes) = array_pop($this->repeats_stack); + } - /** - * Setting upp or changing variables in the XML - * The XML variable name and value is stored in $this->vars - * - * @param array $attrs an array of key value pairs for the attributes - */ - private function setVarStartHandler($attrs) { - if (empty($attrs['name'])) { - throw new \DomainException('REPORT ERROR var: The attribute "name" is missing or not set in the XML file'); - } + /** + * Setting upp or changing variables in the XML + * The XML variable name and value is stored in $this->vars + * + * @param array $attrs an array of key value pairs for the attributes + */ + private function setVarStartHandler($attrs) + { + if (empty($attrs['name'])) { + throw new \DomainException('REPORT ERROR var: The attribute "name" is missing or not set in the XML file'); + } - $name = $attrs['name']; - $value = $attrs['value']; - $match = []; - // Current GEDCOM record strings - if ($value == '@ID') { - if (preg_match('/0 @(.+)@/', $this->gedrec, $match)) { - $value = $match[1]; - } - } elseif ($value == '@fact') { - $value = $this->fact; - } elseif ($value == '@desc') { - $value = $this->desc; - } elseif ($value == '@generation') { - $value = $this->generation; - } elseif (preg_match("/@(\w+)/", $value, $match)) { - $gmatch = []; - if (preg_match("/\d $match[1] (.+)/", $this->gedrec, $gmatch)) { - $value = str_replace('@', '', trim($gmatch[1])); - } - } - if (preg_match("/\\$(\w+)/", $name, $match)) { - $name = $this->vars["'" . $match[1] . "'"]['id']; - } - $count = preg_match_all("/\\$(\w+)/", $value, $match, PREG_SET_ORDER); - $i = 0; - while ($i < $count) { - $t = $this->vars[$match[$i][1]]['id']; - $value = preg_replace('/\$' . $match[$i][1] . '/', $t, $value, 1); - $i++; - } - if (preg_match('/^I18N::number\((.+)\)$/', $value, $match)) { - $value = I18N::number($match[1]); - } elseif (preg_match('/^I18N::translate\(\'(.+)\'\)$/', $value, $match)) { - $value = I18N::translate($match[1]); - } elseif (preg_match('/^I18N::translateContext\(\'(.+)\', *\'(.+)\'\)$/', $value, $match)) { - $value = I18N::translateContext($match[1], $match[2]); - } - // Arithmetic functions - if (preg_match("/(\d+)\s*([\-\+\*\/])\s*(\d+)/", $value, $match)) { - switch ($match[2]) { - case '+': - $t = $match[1] + $match[3]; - $value = preg_replace('/' . $match[1] . "\s*([\-\+\*\/])\s*" . $match[3] . '/', $t, $value); - break; - case '-': - $t = $match[1] - $match[3]; - $value = preg_replace('/' . $match[1] . "\s*([\-\+\*\/])\s*" . $match[3] . '/', $t, $value); - break; - case '*': - $t = $match[1] * $match[3]; - $value = preg_replace('/' . $match[1] . "\s*([\-\+\*\/])\s*" . $match[3] . '/', $t, $value); - break; - case '/': - $t = $match[1] / $match[3]; - $value = preg_replace('/' . $match[1] . "\s*([\-\+\*\/])\s*" . $match[3] . '/', $t, $value); - break; - } - } - if (strpos($value, '@') !== false) { - $value = ''; - } - $this->vars[$name]['id'] = $value; - } + $name = $attrs['name']; + $value = $attrs['value']; + $match = []; + // Current GEDCOM record strings + if ($value == '@ID') { + if (preg_match('/0 @(.+)@/', $this->gedrec, $match)) { + $value = $match[1]; + } + } elseif ($value == '@fact') { + $value = $this->fact; + } elseif ($value == '@desc') { + $value = $this->desc; + } elseif ($value == '@generation') { + $value = $this->generation; + } elseif (preg_match("/@(\w+)/", $value, $match)) { + $gmatch = []; + if (preg_match("/\d $match[1] (.+)/", $this->gedrec, $gmatch)) { + $value = str_replace('@', '', trim($gmatch[1])); + } + } + if (preg_match("/\\$(\w+)/", $name, $match)) { + $name = $this->vars["'" . $match[1] . "'"]['id']; + } + $count = preg_match_all("/\\$(\w+)/", $value, $match, PREG_SET_ORDER); + $i = 0; + while ($i < $count) { + $t = $this->vars[$match[$i][1]]['id']; + $value = preg_replace('/\$' . $match[$i][1] . '/', $t, $value, 1); + $i++; + } + if (preg_match('/^I18N::number\((.+)\)$/', $value, $match)) { + $value = I18N::number($match[1]); + } elseif (preg_match('/^I18N::translate\(\'(.+)\'\)$/', $value, $match)) { + $value = I18N::translate($match[1]); + } elseif (preg_match('/^I18N::translateContext\(\'(.+)\', *\'(.+)\'\)$/', $value, $match)) { + $value = I18N::translateContext($match[1], $match[2]); + } + // Arithmetic functions + if (preg_match("/(\d+)\s*([\-\+\*\/])\s*(\d+)/", $value, $match)) { + switch ($match[2]) { + case '+': + $t = $match[1] + $match[3]; + $value = preg_replace('/' . $match[1] . "\s*([\-\+\*\/])\s*" . $match[3] . '/', $t, $value); + break; + case '-': + $t = $match[1] - $match[3]; + $value = preg_replace('/' . $match[1] . "\s*([\-\+\*\/])\s*" . $match[3] . '/', $t, $value); + break; + case '*': + $t = $match[1] * $match[3]; + $value = preg_replace('/' . $match[1] . "\s*([\-\+\*\/])\s*" . $match[3] . '/', $t, $value); + break; + case '/': + $t = $match[1] / $match[3]; + $value = preg_replace('/' . $match[1] . "\s*([\-\+\*\/])\s*" . $match[3] . '/', $t, $value); + break; + } + } + if (strpos($value, '@') !== false) { + $value = ''; + } + $this->vars[$name]['id'] = $value; + } - /** - * XML <if > start element - * - * @param array $attrs an array of key value pairs for the attributes - */ - private function ifStartHandler($attrs) { - if ($this->process_ifs > 0) { - $this->process_ifs++; + /** + * XML <if > start element + * + * @param array $attrs an array of key value pairs for the attributes + */ + private function ifStartHandler($attrs) + { + if ($this->process_ifs > 0) { + $this->process_ifs++; - return; - } + return; + } - $condition = $attrs['condition']; - $condition = $this->substituteVars($condition, true); - $condition = str_replace([' LT ', ' GT '], ['<', '>'], $condition); - // Replace the first accurance only once of @fact:DATE or in any other combinations to the current fact, such as BIRT - $condition = str_replace('@fact:', $this->fact . ':', $condition); - $match = []; - $count = preg_match_all("/@([\w:\.]+)/", $condition, $match, PREG_SET_ORDER); - $i = 0; - while ($i < $count) { - $id = $match[$i][1]; - $value = '""'; - if ($id == 'ID') { - if (preg_match('/0 @(.+)@/', $this->gedrec, $match)) { - $value = "'" . $match[1] . "'"; - } - } elseif ($id === 'fact') { - $value = '"' . $this->fact . '"'; - } elseif ($id === 'desc') { - $value = '"' . addslashes($this->desc) . '"'; - } elseif ($id === 'generation') { - $value = '"' . $this->generation . '"'; - } else { - $temp = explode(' ', trim($this->gedrec)); - $level = $temp[0]; - if ($level == 0) { - $level++; - } - $value = $this->getGedcomValue($id, $level, $this->gedrec); - if (empty($value)) { - $level++; - $value = $this->getGedcomValue($id, $level, $this->gedrec); - } - $value = preg_replace('/^@(' . WT_REGEX_XREF . ')@$/', '$1', $value); - $value = '"' . addslashes($value) . '"'; - } - $condition = str_replace("@$id", $value, $condition); - $i++; - } - $ret = eval("return (bool) ($condition);"); - if (!$ret) { - $this->process_ifs++; - } - } + $condition = $attrs['condition']; + $condition = $this->substituteVars($condition, true); + $condition = str_replace([ + ' LT ', + ' GT ', + ], [ + '<', + '>', + ], $condition); + // Replace the first accurance only once of @fact:DATE or in any other combinations to the current fact, such as BIRT + $condition = str_replace('@fact:', $this->fact . ':', $condition); + $match = []; + $count = preg_match_all("/@([\w:\.]+)/", $condition, $match, PREG_SET_ORDER); + $i = 0; + while ($i < $count) { + $id = $match[$i][1]; + $value = '""'; + if ($id == 'ID') { + if (preg_match('/0 @(.+)@/', $this->gedrec, $match)) { + $value = "'" . $match[1] . "'"; + } + } elseif ($id === 'fact') { + $value = '"' . $this->fact . '"'; + } elseif ($id === 'desc') { + $value = '"' . addslashes($this->desc) . '"'; + } elseif ($id === 'generation') { + $value = '"' . $this->generation . '"'; + } else { + $temp = explode(' ', trim($this->gedrec)); + $level = $temp[0]; + if ($level == 0) { + $level++; + } + $value = $this->getGedcomValue($id, $level, $this->gedrec); + if (empty($value)) { + $level++; + $value = $this->getGedcomValue($id, $level, $this->gedrec); + } + $value = preg_replace('/^@(' . WT_REGEX_XREF . ')@$/', '$1', $value); + $value = '"' . addslashes($value) . '"'; + } + $condition = str_replace("@$id", $value, $condition); + $i++; + } + $ret = eval("return (bool) ($condition);"); + if (!$ret) { + $this->process_ifs++; + } + } - /** - * XML <if /> end element - */ - private function ifEndHandler() { - if ($this->process_ifs > 0) { - $this->process_ifs--; - } - } + /** + * XML <if /> end element + */ + private function ifEndHandler() + { + if ($this->process_ifs > 0) { + $this->process_ifs--; + } + } - /** - * XML <Footnote > start element - * Collect the Footnote links - * GEDCOM Records that are protected by Privacy setting will be ignore - * - * @param array $attrs an array of key value pairs for the attributes - */ - private function footnoteStartHandler($attrs) { - $id = ''; - if (preg_match('/[0-9] (.+) @(.+)@/', $this->gedrec, $match)) { - $id = $match[2]; - } - $record = GedcomRecord::getInstance($id, $this->tree); - if ($record && $record->canShow()) { - array_push($this->print_data_stack, $this->print_data); - $this->print_data = true; - $style = ''; - if (!empty($attrs['style'])) { - $style = $attrs['style']; - } - $this->footnote_element = $this->current_element; - $this->current_element = $this->report_root->createFootnote($style); - } else { - $this->print_data = false; - $this->process_footnote = false; - } - } + /** + * XML <Footnote > start element + * Collect the Footnote links + * GEDCOM Records that are protected by Privacy setting will be ignore + * + * @param array $attrs an array of key value pairs for the attributes + */ + private function footnoteStartHandler($attrs) + { + $id = ''; + if (preg_match('/[0-9] (.+) @(.+)@/', $this->gedrec, $match)) { + $id = $match[2]; + } + $record = GedcomRecord::getInstance($id, $this->tree); + if ($record && $record->canShow()) { + array_push($this->print_data_stack, $this->print_data); + $this->print_data = true; + $style = ''; + if (!empty($attrs['style'])) { + $style = $attrs['style']; + } + $this->footnote_element = $this->current_element; + $this->current_element = $this->report_root->createFootnote($style); + } else { + $this->print_data = false; + $this->process_footnote = false; + } + } - /** - * XML <Footnote /> end element - * Print the collected Footnote data - */ - private function footnoteEndHandler() { - if ($this->process_footnote) { - $this->print_data = array_pop($this->print_data_stack); - $temp = trim($this->current_element->getValue()); - if (strlen($temp) > 3) { - $this->wt_report->addElement($this->current_element); - } - $this->current_element = $this->footnote_element; - } else { - $this->process_footnote = true; - } - } + /** + * XML <Footnote /> end element + * Print the collected Footnote data + */ + private function footnoteEndHandler() + { + if ($this->process_footnote) { + $this->print_data = array_pop($this->print_data_stack); + $temp = trim($this->current_element->getValue()); + if (strlen($temp) > 3) { + $this->wt_report->addElement($this->current_element); + } + $this->current_element = $this->footnote_element; + } else { + $this->process_footnote = true; + } + } - /** - * XML <FootnoteTexts /> element - */ - private function footnoteTextsStartHandler() { - $temp = 'footnotetexts'; - $this->wt_report->addElement($temp); - } + /** + * XML <FootnoteTexts /> element + */ + private function footnoteTextsStartHandler() + { + $temp = 'footnotetexts'; + $this->wt_report->addElement($temp); + } - /** - * XML <AgeAtDeath /> element handler - */ - private function ageAtDeathStartHandler() { - // This duplicates functionality in FunctionsPrint::format_fact_date() - global $factrec; + /** + * XML <AgeAtDeath /> element handler + */ + private function ageAtDeathStartHandler() + { + // This duplicates functionality in FunctionsPrint::format_fact_date() + global $factrec; - $match = []; - if (preg_match('/0 @(.+)@/', $this->gedrec, $match)) { - $person = Individual::getInstance($match[1], $this->tree); - // Recorded age - if (preg_match('/\n2 AGE (.+)/', $factrec, $match)) { - $fact_age = $match[1]; - } else { - $fact_age = ''; - } - if (preg_match('/\n2 HUSB\n3 AGE (.+)/', $factrec, $match)) { - $husb_age = $match[1]; - } else { - $husb_age = ''; - } - if (preg_match('/\n2 WIFE\n3 AGE (.+)/', $factrec, $match)) { - $wife_age = $match[1]; - } else { - $wife_age = ''; - } + $match = []; + if (preg_match('/0 @(.+)@/', $this->gedrec, $match)) { + $person = Individual::getInstance($match[1], $this->tree); + // Recorded age + if (preg_match('/\n2 AGE (.+)/', $factrec, $match)) { + $fact_age = $match[1]; + } else { + $fact_age = ''; + } + if (preg_match('/\n2 HUSB\n3 AGE (.+)/', $factrec, $match)) { + $husb_age = $match[1]; + } else { + $husb_age = ''; + } + if (preg_match('/\n2 WIFE\n3 AGE (.+)/', $factrec, $match)) { + $wife_age = $match[1]; + } else { + $wife_age = ''; + } - // Calculated age - $birth_date = $person->getBirthDate(); - // Can't use getDeathDate(), as this also gives BURI/CREM events, which - // wouldn't give the correct "days after death" result for people with - // no DEAT. - $death_event = $person->getFirstFact('DEAT'); - if ($death_event) { - $death_date = $death_event->getDate(); - } else { - $death_date = new Date(''); - } - $value = ''; - if (Date::compare($birth_date, $death_date) <= 0 || !$person->isDead()) { - $age = Date::getAgeGedcom($birth_date, $death_date); - // Only show calculated age if it differs from recorded age - if ($age != '' && $age != '0d') { - if ($fact_age != '' && $fact_age != $age || $fact_age == '' && $husb_age == '' && $wife_age == '' || $husb_age != '' && $person->getSex() == 'M' && $husb_age != $age || $wife_age != '' && $person->getSex() == 'F' && $wife_age != $age - ) { - $value = FunctionsDate::getAgeAtEvent($age); - $abbrev = substr($value, 0, strpos($value, ' ') + 5); - if ($value !== $abbrev) { - $value = $abbrev . '.'; - } - } - } - } - $this->current_element->addText($value); - } - } + // Calculated age + $birth_date = $person->getBirthDate(); + // Can't use getDeathDate(), as this also gives BURI/CREM events, which + // wouldn't give the correct "days after death" result for people with + // no DEAT. + $death_event = $person->getFirstFact('DEAT'); + if ($death_event) { + $death_date = $death_event->getDate(); + } else { + $death_date = new Date(''); + } + $value = ''; + if (Date::compare($birth_date, $death_date) <= 0 || !$person->isDead()) { + $age = Date::getAgeGedcom($birth_date, $death_date); + // Only show calculated age if it differs from recorded age + if ($age != '' && $age != '0d') { + if ($fact_age != '' && $fact_age != $age || $fact_age == '' && $husb_age == '' && $wife_age == '' || $husb_age != '' && $person->getSex() == 'M' && $husb_age != $age || $wife_age != '' && $person->getSex() == 'F' && $wife_age != $age + ) { + $value = FunctionsDate::getAgeAtEvent($age); + $abbrev = substr($value, 0, strpos($value, ' ') + 5); + if ($value !== $abbrev) { + $value = $abbrev . '.'; + } + } + } + } + $this->current_element->addText($value); + } + } - /** - * XML element Forced line break handler - HTML code - */ - private function brStartHandler() { - if ($this->print_data && $this->process_gedcoms === 0) { - $this->current_element->addText('<br>'); - } - } + /** + * XML element Forced line break handler - HTML code + */ + private function brStartHandler() + { + if ($this->print_data && $this->process_gedcoms === 0) { + $this->current_element->addText('<br>'); + } + } - /** - * XML <sp />element Forced space handler - */ - private function spStartHandler() { - if ($this->print_data && $this->process_gedcoms === 0) { - $this->current_element->addText(' '); - } - } + /** + * XML <sp />element Forced space handler + */ + private function spStartHandler() + { + if ($this->print_data && $this->process_gedcoms === 0) { + $this->current_element->addText(' '); + } + } - /** - * XML <HighlightedImage/> - * - * @param array $attrs an array of key value pairs for the attributes - */ - private function highlightedImageStartHandler($attrs) { - $id = ''; - $match = []; - if (preg_match('/0 @(.+)@/', $this->gedrec, $match)) { - $id = $match[1]; - } + /** + * XML <HighlightedImage/> + * + * @param array $attrs an array of key value pairs for the attributes + */ + private function highlightedImageStartHandler($attrs) + { + $id = ''; + $match = []; + if (preg_match('/0 @(.+)@/', $this->gedrec, $match)) { + $id = $match[1]; + } - // mixed Position the top corner of this box on the page. the default is the current position - $top = '.'; - if (isset($attrs['top'])) { - if ($attrs['top'] === '0') { - $top = 0; - } elseif ($attrs['top'] === '.') { - $top = '.'; - } elseif (!empty($attrs['top'])) { - $top = (int) $attrs['top']; - } - } + // mixed Position the top corner of this box on the page. the default is the current position + $top = '.'; + if (isset($attrs['top'])) { + if ($attrs['top'] === '0') { + $top = 0; + } elseif ($attrs['top'] === '.') { + $top = '.'; + } elseif (!empty($attrs['top'])) { + $top = (int)$attrs['top']; + } + } - // mixed Position the left corner of this box on the page. the default is the current position - $left = '.'; - if (isset($attrs['left'])) { - if ($attrs['left'] === '0') { - $left = 0; - } elseif ($attrs['left'] === '.') { - $left = '.'; - } elseif (!empty($attrs['left'])) { - $left = (int) $attrs['left']; - } - } + // mixed Position the left corner of this box on the page. the default is the current position + $left = '.'; + if (isset($attrs['left'])) { + if ($attrs['left'] === '0') { + $left = 0; + } elseif ($attrs['left'] === '.') { + $left = '.'; + } elseif (!empty($attrs['left'])) { + $left = (int)$attrs['left']; + } + } - // string Align the image in left, center, right - $align = ''; - if (!empty($attrs['align'])) { - $align = $attrs['align']; - } + // string Align the image in left, center, right + $align = ''; + if (!empty($attrs['align'])) { + $align = $attrs['align']; + } - // string Next Line should be T:next to the image, N:next line - $ln = ''; - if (!empty($attrs['ln'])) { - $ln = $attrs['ln']; - } + // string Next Line should be T:next to the image, N:next line + $ln = ''; + if (!empty($attrs['ln'])) { + $ln = $attrs['ln']; + } - $width = 0; - $height = 0; - if (!empty($attrs['width'])) { - $width = (int) $attrs['width']; - } - if (!empty($attrs['height'])) { - $height = (int) $attrs['height']; - } + $width = 0; + $height = 0; + if (!empty($attrs['width'])) { + $width = (int)$attrs['width']; + } + if (!empty($attrs['height'])) { + $height = (int)$attrs['height']; + } - $person = Individual::getInstance($id, $this->tree); - $media_file = $person->findHighlightedMediaFile(); + $person = Individual::getInstance($id, $this->tree); + $media_file = $person->findHighlightedMediaFile(); - if ($media_file !== null && $media_file->fileExists()) { - $attributes = getimagesize($media_file->getServerFilename()) ?: [0, 0]; - if ($width > 0 && $height == 0) { - $perc = $width / $attributes[0]; - $height = round($attributes[1] * $perc); - } elseif ($height > 0 && $width == 0) { - $perc = $height / $attributes[1]; - $width = round($attributes[0] * $perc); - } else { - $width = $attributes[0]; - $height = $attributes[1]; - } - $image = $this->report_root->createImageFromObject($media_file, $left, $top, $width, $height, $align, $ln); - $this->wt_report->addElement($image); - } - } + if ($media_file !== null && $media_file->fileExists()) { + $attributes = getimagesize($media_file->getServerFilename()) ?: [ + 0, + 0, + ]; + if ($width > 0 && $height == 0) { + $perc = $width / $attributes[0]; + $height = round($attributes[1] * $perc); + } elseif ($height > 0 && $width == 0) { + $perc = $height / $attributes[1]; + $width = round($attributes[0] * $perc); + } else { + $width = $attributes[0]; + $height = $attributes[1]; + } + $image = $this->report_root->createImageFromObject($media_file, $left, $top, $width, $height, $align, $ln); + $this->wt_report->addElement($image); + } + } - /** - * XML <Image/> - * - * @param array $attrs an array of key value pairs for the attributes - */ - private function imageStartHandler($attrs) { - // mixed Position the top corner of this box on the page. the default is the current position - $top = '.'; - if (isset($attrs['top'])) { - if ($attrs['top'] === '0') { - $top = 0; - } elseif ($attrs['top'] === '.') { - $top = '.'; - } elseif (!empty($attrs['top'])) { - $top = (int) $attrs['top']; - } - } + /** + * XML <Image/> + * + * @param array $attrs an array of key value pairs for the attributes + */ + private function imageStartHandler($attrs) + { + // mixed Position the top corner of this box on the page. the default is the current position + $top = '.'; + if (isset($attrs['top'])) { + if ($attrs['top'] === '0') { + $top = 0; + } elseif ($attrs['top'] === '.') { + $top = '.'; + } elseif (!empty($attrs['top'])) { + $top = (int)$attrs['top']; + } + } - // mixed Position the left corner of this box on the page. the default is the current position - $left = '.'; - if (isset($attrs['left'])) { - if ($attrs['left'] === '0') { - $left = 0; - } elseif ($attrs['left'] === '.') { - $left = '.'; - } elseif (!empty($attrs['left'])) { - $left = (int) $attrs['left']; - } - } + // mixed Position the left corner of this box on the page. the default is the current position + $left = '.'; + if (isset($attrs['left'])) { + if ($attrs['left'] === '0') { + $left = 0; + } elseif ($attrs['left'] === '.') { + $left = '.'; + } elseif (!empty($attrs['left'])) { + $left = (int)$attrs['left']; + } + } - // string Align the image in left, center, right - $align = ''; - if (!empty($attrs['align'])) { - $align = $attrs['align']; - } + // string Align the image in left, center, right + $align = ''; + if (!empty($attrs['align'])) { + $align = $attrs['align']; + } - // string Next Line should be T:next to the image, N:next line - $ln = 'T'; - if (!empty($attrs['ln'])) { - $ln = $attrs['ln']; - } + // string Next Line should be T:next to the image, N:next line + $ln = 'T'; + if (!empty($attrs['ln'])) { + $ln = $attrs['ln']; + } - $width = 0; - $height = 0; - if (!empty($attrs['width'])) { - $width = (int) $attrs['width']; - } - if (!empty($attrs['height'])) { - $height = (int) $attrs['height']; - } + $width = 0; + $height = 0; + if (!empty($attrs['width'])) { + $width = (int)$attrs['width']; + } + if (!empty($attrs['height'])) { + $height = (int)$attrs['height']; + } - $file = ''; - if (!empty($attrs['file'])) { - $file = $attrs['file']; - } - if ($file == '@FILE') { - $match = []; - if (preg_match("/\d OBJE @(.+)@/", $this->gedrec, $match)) { - $mediaobject = Media::getInstance($match[1], $this->tree); - $media_file = $mediaobject->firstImageFile(); + $file = ''; + if (!empty($attrs['file'])) { + $file = $attrs['file']; + } + if ($file == '@FILE') { + $match = []; + if (preg_match("/\d OBJE @(.+)@/", $this->gedrec, $match)) { + $mediaobject = Media::getInstance($match[1], $this->tree); + $media_file = $mediaobject->firstImageFile(); - if ($media_file !== null && $media_file->fileExists()) { - $attributes = getimagesize($media_file->getServerFilename()) ?: [0, 0]; - if ($width > 0 && $height == 0) { - $perc = $width / $attributes[0]; - $height = round($attributes[1] * $perc); - } elseif ($height > 0 && $width == 0) { - $perc = $height / $attributes[1]; - $width = round($attributes[0] * $perc); - } else { - $width = $attributes[0]; - $height = $attributes[1]; - } - $image = $this->report_root->createImageFromObject($media_file, $left, $top, $width, $height, $align, $ln); - $this->wt_report->addElement($image); - } - } - } else { - if (file_exists($file) && preg_match('/(jpg|jpeg|png|gif)$/i', $file)) { - $size = getimagesize($file); - if ($width > 0 && $height == 0) { - $perc = $width / $size[0]; - $height = round($size[1] * $perc); - } elseif ($height > 0 && $width == 0) { - $perc = $height / $size[1]; - $width = round($size[0] * $perc); - } else { - $width = $size[0]; - $height = $size[1]; - } - $image = $this->report_root->createImage($file, $left, $top, $width, $height, $align, $ln); - $this->wt_report->addElement($image); - } - } - } + if ($media_file !== null && $media_file->fileExists()) { + $attributes = getimagesize($media_file->getServerFilename()) ?: [ + 0, + 0, + ]; + if ($width > 0 && $height == 0) { + $perc = $width / $attributes[0]; + $height = round($attributes[1] * $perc); + } elseif ($height > 0 && $width == 0) { + $perc = $height / $attributes[1]; + $width = round($attributes[0] * $perc); + } else { + $width = $attributes[0]; + $height = $attributes[1]; + } + $image = $this->report_root->createImageFromObject($media_file, $left, $top, $width, $height, $align, $ln); + $this->wt_report->addElement($image); + } + } + } else { + if (file_exists($file) && preg_match('/(jpg|jpeg|png|gif)$/i', $file)) { + $size = getimagesize($file); + if ($width > 0 && $height == 0) { + $perc = $width / $size[0]; + $height = round($size[1] * $perc); + } elseif ($height > 0 && $width == 0) { + $perc = $height / $size[1]; + $width = round($size[0] * $perc); + } else { + $width = $size[0]; + $height = $size[1]; + } + $image = $this->report_root->createImage($file, $left, $top, $width, $height, $align, $ln); + $this->wt_report->addElement($image); + } + } + } - /** - * XML <Line> element handler - * - * @param array $attrs an array of key value pairs for the attributes - */ - private function lineStartHandler($attrs) { - // Start horizontal position, current position (default) - $x1 = '.'; - if (isset($attrs['x1'])) { - if ($attrs['x1'] === '0') { - $x1 = 0; - } elseif ($attrs['x1'] === '.') { - $x1 = '.'; - } elseif (!empty($attrs['x1'])) { - $x1 = (int) $attrs['x1']; - } - } - // Start vertical position, current position (default) - $y1 = '.'; - if (isset($attrs['y1'])) { - if ($attrs['y1'] === '0') { - $y1 = 0; - } elseif ($attrs['y1'] === '.') { - $y1 = '.'; - } elseif (!empty($attrs['y1'])) { - $y1 = (int) $attrs['y1']; - } - } - // End horizontal position, maximum width (default) - $x2 = '.'; - if (isset($attrs['x2'])) { - if ($attrs['x2'] === '0') { - $x2 = 0; - } elseif ($attrs['x2'] === '.') { - $x2 = '.'; - } elseif (!empty($attrs['x2'])) { - $x2 = (int) $attrs['x2']; - } - } - // End vertical position - $y2 = '.'; - if (isset($attrs['y2'])) { - if ($attrs['y2'] === '0') { - $y2 = 0; - } elseif ($attrs['y2'] === '.') { - $y2 = '.'; - } elseif (!empty($attrs['y2'])) { - $y2 = (int) $attrs['y2']; - } - } + /** + * XML <Line> element handler + * + * @param array $attrs an array of key value pairs for the attributes + */ + private function lineStartHandler($attrs) + { + // Start horizontal position, current position (default) + $x1 = '.'; + if (isset($attrs['x1'])) { + if ($attrs['x1'] === '0') { + $x1 = 0; + } elseif ($attrs['x1'] === '.') { + $x1 = '.'; + } elseif (!empty($attrs['x1'])) { + $x1 = (int)$attrs['x1']; + } + } + // Start vertical position, current position (default) + $y1 = '.'; + if (isset($attrs['y1'])) { + if ($attrs['y1'] === '0') { + $y1 = 0; + } elseif ($attrs['y1'] === '.') { + $y1 = '.'; + } elseif (!empty($attrs['y1'])) { + $y1 = (int)$attrs['y1']; + } + } + // End horizontal position, maximum width (default) + $x2 = '.'; + if (isset($attrs['x2'])) { + if ($attrs['x2'] === '0') { + $x2 = 0; + } elseif ($attrs['x2'] === '.') { + $x2 = '.'; + } elseif (!empty($attrs['x2'])) { + $x2 = (int)$attrs['x2']; + } + } + // End vertical position + $y2 = '.'; + if (isset($attrs['y2'])) { + if ($attrs['y2'] === '0') { + $y2 = 0; + } elseif ($attrs['y2'] === '.') { + $y2 = '.'; + } elseif (!empty($attrs['y2'])) { + $y2 = (int)$attrs['y2']; + } + } - $line = $this->report_root->createLine($x1, $y1, $x2, $y2); - $this->wt_report->addElement($line); - } + $line = $this->report_root->createLine($x1, $y1, $x2, $y2); + $this->wt_report->addElement($line); + } - /** - * XML <List> - * - * @param array $attrs an array of key value pairs for the attributes - */ - private function listStartHandler($attrs) { - $this->process_repeats++; - if ($this->process_repeats > 1) { - return; - } + /** + * XML <List> + * + * @param array $attrs an array of key value pairs for the attributes + */ + private function listStartHandler($attrs) + { + $this->process_repeats++; + if ($this->process_repeats > 1) { + return; + } - $match = []; - if (isset($attrs['sortby'])) { - $sortby = $attrs['sortby']; - if (preg_match("/\\$(\w+)/", $sortby, $match)) { - $sortby = $this->vars[$match[1]]['id']; - $sortby = trim($sortby); - } - } else { - $sortby = 'NAME'; - } + $match = []; + if (isset($attrs['sortby'])) { + $sortby = $attrs['sortby']; + if (preg_match("/\\$(\w+)/", $sortby, $match)) { + $sortby = $this->vars[$match[1]]['id']; + $sortby = trim($sortby); + } + } else { + $sortby = 'NAME'; + } - if (isset($attrs['list'])) { - $listname = $attrs['list']; - } else { - $listname = 'individual'; - } - // Some filters/sorts can be applied using SQL, while others require PHP - switch ($listname) { - case 'pending': - $rows = Database::prepare( - "SELECT xref, CASE new_gedcom WHEN '' THEN old_gedcom ELSE new_gedcom END AS gedcom" . - " FROM `##change`" . " WHERE (xref, change_id) IN (" . - " SELECT xref, MAX(change_id)" . - " FROM `##change`" . - " WHERE status = 'pending' AND gedcom_id = :tree_id" . - " GROUP BY xref" . - " )" - )->execute([ - 'tree_id' => $this->tree->getTreeId(), - ])->fetchAll(); - $this->list = []; - foreach ($rows as $row) { - $this->list[] = GedcomRecord::getInstance($row->xref, $this->tree, $row->gedcom); - } - break; - case 'individual': - $sql_select = "SELECT i_id AS xref, i_gedcom AS gedcom FROM `##individuals` "; - $sql_join = ""; - $sql_where = " WHERE i_file = :tree_id"; - $sql_order_by = ""; - $sql_params = ['tree_id' => $this->tree->getTreeId()]; - foreach ($attrs as $attr => $value) { - if (strpos($attr, 'filter') === 0 && $value) { - $value = $this->substituteVars($value, false); - // Convert the various filters into SQL - if (preg_match('/^(\w+):DATE (LTE|GTE) (.+)$/', $value, $match)) { - $sql_join .= " JOIN `##dates` AS {$attr} ON ({$attr}.d_file=i_file AND {$attr}.d_gid=i_id)"; - $sql_where .= " AND {$attr}.d_fact = :{$attr}fact"; - $sql_params[$attr . 'fact'] = $match[1]; - $date = new Date($match[3]); - if ($match[2] == 'LTE') { - $sql_where .= " AND {$attr}.d_julianday2 <= :{$attr}date"; - $sql_params[$attr . 'date'] = $date->maximumJulianDay(); - } else { - $sql_where .= " AND {$attr}.d_julianday1 >= :{$attr}date"; - $sql_params[$attr . 'date'] = $date->minimumJulianDay(); - } - if ($sortby == $match[1]) { - $sortby = ""; - $sql_order_by .= ($sql_order_by ? ", " : " ORDER BY ") . "{$attr}.d_julianday1"; - } - unset($attrs[$attr]); // This filter has been fully processed - } elseif (preg_match('/^NAME CONTAINS (.*)$/', $value, $match)) { - // Do nothing, unless you have to - if ($match[1] != '' || $sortby == 'NAME') { - $sql_join .= " JOIN `##name` AS {$attr} ON (n_file=i_file AND n_id=i_id)"; - // Search the DB only if there is any name supplied - if ($match[1] != '') { - $names = explode(' ', $match[1]); - foreach ($names as $n => $name) { - $sql_where .= " AND {$attr}.n_full LIKE CONCAT('%', :{$attr}name{$n}, '%')"; - $sql_params[$attr . 'name' . $n] = $name; - } - } - // Let the DB do the name sorting even when no name was entered - if ($sortby == 'NAME') { - $sortby = ''; - $sql_order_by .= ($sql_order_by ? ', ' : ' ORDER BY ') . "{$attr}.n_sort"; - } - } - unset($attrs[$attr]); // This filter has been fully processed - } elseif (preg_match('/^REGEXP \/(.+)\//', $value, $match)) { - $sql_where .= " AND i_gedcom REGEXP :{$attr}gedcom"; - // PDO helpfully escapes backslashes for us, preventing us from matching "\n1 FACT" - $sql_params[$attr . 'gedcom'] = str_replace('\n', "\n", $match[1]); - unset($attrs[$attr]); // This filter has been fully processed - } elseif (preg_match('/^(?:\w+):PLAC CONTAINS (.+)$/', $value, $match)) { - $sql_join .= " JOIN `##places` AS {$attr}a ON ({$attr}a.p_file = i_file)"; - $sql_join .= " JOIN `##placelinks` AS {$attr}b ON ({$attr}a.p_file = {$attr}b.pl_file AND {$attr}b.pl_p_id = {$attr}a.p_id AND {$attr}b.pl_gid = i_id)"; - $sql_where .= " AND {$attr}a.p_place LIKE CONCAT('%', :{$attr}place, '%')"; - $sql_params[$attr . 'place'] = $match[1]; - // Don't unset this filter. This is just initial filtering - } elseif (preg_match('/^(\w*):*(\w*) CONTAINS (.+)$/', $value, $match)) { - $sql_where .= " AND i_gedcom LIKE CONCAT('%', :{$attr}contains1, '%', :{$attr}contains2, '%', :{$attr}contains3, '%')"; - $sql_params[$attr . 'contains1'] = $match[1]; - $sql_params[$attr . 'contains2'] = $match[2]; - $sql_params[$attr . 'contains3'] = $match[3]; - // Don't unset this filter. This is just initial filtering - } - } - } + if (isset($attrs['list'])) { + $listname = $attrs['list']; + } else { + $listname = 'individual'; + } + // Some filters/sorts can be applied using SQL, while others require PHP + switch ($listname) { + case 'pending': + $rows = Database::prepare( + "SELECT xref, CASE new_gedcom WHEN '' THEN old_gedcom ELSE new_gedcom END AS gedcom" . + " FROM `##change`" . " WHERE (xref, change_id) IN (" . + " SELECT xref, MAX(change_id)" . + " FROM `##change`" . + " WHERE status = 'pending' AND gedcom_id = :tree_id" . + " GROUP BY xref" . + " )" + )->execute([ + 'tree_id' => $this->tree->getTreeId(), + ])->fetchAll(); + $this->list = []; + foreach ($rows as $row) { + $this->list[] = GedcomRecord::getInstance($row->xref, $this->tree, $row->gedcom); + } + break; + case 'individual': + $sql_select = "SELECT i_id AS xref, i_gedcom AS gedcom FROM `##individuals` "; + $sql_join = ""; + $sql_where = " WHERE i_file = :tree_id"; + $sql_order_by = ""; + $sql_params = ['tree_id' => $this->tree->getTreeId()]; + foreach ($attrs as $attr => $value) { + if (strpos($attr, 'filter') === 0 && $value) { + $value = $this->substituteVars($value, false); + // Convert the various filters into SQL + if (preg_match('/^(\w+):DATE (LTE|GTE) (.+)$/', $value, $match)) { + $sql_join .= " JOIN `##dates` AS {$attr} ON ({$attr}.d_file=i_file AND {$attr}.d_gid=i_id)"; + $sql_where .= " AND {$attr}.d_fact = :{$attr}fact"; + $sql_params[$attr . 'fact'] = $match[1]; + $date = new Date($match[3]); + if ($match[2] == 'LTE') { + $sql_where .= " AND {$attr}.d_julianday2 <= :{$attr}date"; + $sql_params[$attr . 'date'] = $date->maximumJulianDay(); + } else { + $sql_where .= " AND {$attr}.d_julianday1 >= :{$attr}date"; + $sql_params[$attr . 'date'] = $date->minimumJulianDay(); + } + if ($sortby == $match[1]) { + $sortby = ""; + $sql_order_by .= ($sql_order_by ? ", " : " ORDER BY ") . "{$attr}.d_julianday1"; + } + unset($attrs[$attr]); // This filter has been fully processed + } elseif (preg_match('/^NAME CONTAINS (.*)$/', $value, $match)) { + // Do nothing, unless you have to + if ($match[1] != '' || $sortby == 'NAME') { + $sql_join .= " JOIN `##name` AS {$attr} ON (n_file=i_file AND n_id=i_id)"; + // Search the DB only if there is any name supplied + if ($match[1] != '') { + $names = explode(' ', $match[1]); + foreach ($names as $n => $name) { + $sql_where .= " AND {$attr}.n_full LIKE CONCAT('%', :{$attr}name{$n}, '%')"; + $sql_params[$attr . 'name' . $n] = $name; + } + } + // Let the DB do the name sorting even when no name was entered + if ($sortby == 'NAME') { + $sortby = ''; + $sql_order_by .= ($sql_order_by ? ', ' : ' ORDER BY ') . "{$attr}.n_sort"; + } + } + unset($attrs[$attr]); // This filter has been fully processed + } elseif (preg_match('/^REGEXP \/(.+)\//', $value, $match)) { + $sql_where .= " AND i_gedcom REGEXP :{$attr}gedcom"; + // PDO helpfully escapes backslashes for us, preventing us from matching "\n1 FACT" + $sql_params[$attr . 'gedcom'] = str_replace('\n', "\n", $match[1]); + unset($attrs[$attr]); // This filter has been fully processed + } elseif (preg_match('/^(?:\w+):PLAC CONTAINS (.+)$/', $value, $match)) { + $sql_join .= " JOIN `##places` AS {$attr}a ON ({$attr}a.p_file = i_file)"; + $sql_join .= " JOIN `##placelinks` AS {$attr}b ON ({$attr}a.p_file = {$attr}b.pl_file AND {$attr}b.pl_p_id = {$attr}a.p_id AND {$attr}b.pl_gid = i_id)"; + $sql_where .= " AND {$attr}a.p_place LIKE CONCAT('%', :{$attr}place, '%')"; + $sql_params[$attr . 'place'] = $match[1]; + // Don't unset this filter. This is just initial filtering + } elseif (preg_match('/^(\w*):*(\w*) CONTAINS (.+)$/', $value, $match)) { + $sql_where .= " AND i_gedcom LIKE CONCAT('%', :{$attr}contains1, '%', :{$attr}contains2, '%', :{$attr}contains3, '%')"; + $sql_params[$attr . 'contains1'] = $match[1]; + $sql_params[$attr . 'contains2'] = $match[2]; + $sql_params[$attr . 'contains3'] = $match[3]; + // Don't unset this filter. This is just initial filtering + } + } + } - $this->list = []; - $rows = Database::prepare( - $sql_select . $sql_join . $sql_where . $sql_order_by - )->execute($sql_params)->fetchAll(); + $this->list = []; + $rows = Database::prepare( + $sql_select . $sql_join . $sql_where . $sql_order_by + )->execute($sql_params)->fetchAll(); - foreach ($rows as $row) { - $this->list[$row->xref] = Individual::getInstance($row->xref, $this->tree, $row->gedcom); - } - break; + foreach ($rows as $row) { + $this->list[$row->xref] = Individual::getInstance($row->xref, $this->tree, $row->gedcom); + } + break; - case 'family': - $sql_select = "SELECT f_id AS xref, f_gedcom AS gedcom FROM `##families`"; - $sql_join = ""; - $sql_where = " WHERE f_file = :tree_id"; - $sql_order_by = ""; - $sql_params = ['tree_id' => $this->tree->getTreeId()]; - foreach ($attrs as $attr => $value) { - if (strpos($attr, 'filter') === 0 && $value) { - $value = $this->substituteVars($value, false); - // Convert the various filters into SQL - if (preg_match('/^(\w+):DATE (LTE|GTE) (.+)$/', $value, $match)) { - $sql_join .= " JOIN `##dates` AS {$attr} ON ({$attr}.d_file=f_file AND {$attr}.d_gid=f_id)"; - $sql_where .= " AND {$attr}.d_fact = :{$attr}fact"; - $sql_params[$attr . 'fact'] = $match[1]; - $date = new Date($match[3]); - if ($match[2] == 'LTE') { - $sql_where .= " AND {$attr}.d_julianday2 <= :{$attr}date"; - $sql_params[$attr . 'date'] = $date->maximumJulianDay(); - } else { - $sql_where .= " AND {$attr}.d_julianday1 >= :{$attr}date"; - $sql_params[$attr . 'date'] = $date->minimumJulianDay(); - } - if ($sortby == $match[1]) { - $sortby = ''; - $sql_order_by .= ($sql_order_by ? ', ' : ' ORDER BY ') . "{$attr}.d_julianday1"; - } - unset($attrs[$attr]); // This filter has been fully processed - } elseif (preg_match('/^REGEXP \/(.+)\//', $value, $match)) { - $sql_where .= " AND f_gedcom REGEXP :{$attr}gedcom"; - // PDO helpfully escapes backslashes for us, preventing us from matching "\n1 FACT" - $sql_params[$attr . 'gedcom'] = str_replace('\n', "\n", $match[1]); - unset($attrs[$attr]); // This filter has been fully processed - } elseif (preg_match('/^NAME CONTAINS (.+)$/', $value, $match)) { - // Do nothing, unless you have to - if ($match[1] != '' || $sortby == 'NAME') { - $sql_join .= " JOIN `##name` AS {$attr} ON n_file = f_file AND n_id IN (f_husb, f_wife)"; - // Search the DB only if there is any name supplied - if ($match[1] != '') { - $names = explode(' ', $match[1]); - foreach ($names as $n => $name) { - $sql_where .= " AND {$attr}.n_full LIKE CONCAT('%', :{$attr}name{$n}, '%')"; - $sql_params[$attr . 'name' . $n] = $name; - } - } - // Let the DB do the name sorting even when no name was entered - if ($sortby == 'NAME') { - $sortby = ''; - $sql_order_by .= ($sql_order_by ? ', ' : ' ORDER BY ') . "{$attr}.n_sort"; - } - } - unset($attrs[$attr]); // This filter has been fully processed - } elseif (preg_match('/^(?:\w+):PLAC CONTAINS (.+)$/', $value, $match)) { - $sql_join .= " JOIN `##places` AS {$attr}a ON ({$attr}a.p_file=f_file)"; - $sql_join .= " JOIN `##placelinks` AS {$attr}b ON ({$attr}a.p_file={$attr}b.pl_file AND {$attr}b.pl_p_id={$attr}a.p_id AND {$attr}b.pl_gid=f_id)"; - $sql_where .= " AND {$attr}a.p_place LIKE CONCAT('%', :{$attr}place, '%')"; - $sql_params[$attr . 'place'] = $match[1]; - // Don't unset this filter. This is just initial filtering - } elseif (preg_match('/^(\w*):*(\w*) CONTAINS (.+)$/', $value, $match)) { - $sql_where .= " AND f_gedcom LIKE CONCAT('%', :{$attr}contains1, '%', :{$attr}contains2, '%', :{$attr}contains3, '%')"; - $sql_params[$attr . 'contains1'] = $match[1]; - $sql_params[$attr . 'contains2'] = $match[2]; - $sql_params[$attr . 'contains3'] = $match[3]; - // Don't unset this filter. This is just initial filtering - } - } - } + case 'family': + $sql_select = "SELECT f_id AS xref, f_gedcom AS gedcom FROM `##families`"; + $sql_join = ""; + $sql_where = " WHERE f_file = :tree_id"; + $sql_order_by = ""; + $sql_params = ['tree_id' => $this->tree->getTreeId()]; + foreach ($attrs as $attr => $value) { + if (strpos($attr, 'filter') === 0 && $value) { + $value = $this->substituteVars($value, false); + // Convert the various filters into SQL + if (preg_match('/^(\w+):DATE (LTE|GTE) (.+)$/', $value, $match)) { + $sql_join .= " JOIN `##dates` AS {$attr} ON ({$attr}.d_file=f_file AND {$attr}.d_gid=f_id)"; + $sql_where .= " AND {$attr}.d_fact = :{$attr}fact"; + $sql_params[$attr . 'fact'] = $match[1]; + $date = new Date($match[3]); + if ($match[2] == 'LTE') { + $sql_where .= " AND {$attr}.d_julianday2 <= :{$attr}date"; + $sql_params[$attr . 'date'] = $date->maximumJulianDay(); + } else { + $sql_where .= " AND {$attr}.d_julianday1 >= :{$attr}date"; + $sql_params[$attr . 'date'] = $date->minimumJulianDay(); + } + if ($sortby == $match[1]) { + $sortby = ''; + $sql_order_by .= ($sql_order_by ? ', ' : ' ORDER BY ') . "{$attr}.d_julianday1"; + } + unset($attrs[$attr]); // This filter has been fully processed + } elseif (preg_match('/^REGEXP \/(.+)\//', $value, $match)) { + $sql_where .= " AND f_gedcom REGEXP :{$attr}gedcom"; + // PDO helpfully escapes backslashes for us, preventing us from matching "\n1 FACT" + $sql_params[$attr . 'gedcom'] = str_replace('\n', "\n", $match[1]); + unset($attrs[$attr]); // This filter has been fully processed + } elseif (preg_match('/^NAME CONTAINS (.+)$/', $value, $match)) { + // Do nothing, unless you have to + if ($match[1] != '' || $sortby == 'NAME') { + $sql_join .= " JOIN `##name` AS {$attr} ON n_file = f_file AND n_id IN (f_husb, f_wife)"; + // Search the DB only if there is any name supplied + if ($match[1] != '') { + $names = explode(' ', $match[1]); + foreach ($names as $n => $name) { + $sql_where .= " AND {$attr}.n_full LIKE CONCAT('%', :{$attr}name{$n}, '%')"; + $sql_params[$attr . 'name' . $n] = $name; + } + } + // Let the DB do the name sorting even when no name was entered + if ($sortby == 'NAME') { + $sortby = ''; + $sql_order_by .= ($sql_order_by ? ', ' : ' ORDER BY ') . "{$attr}.n_sort"; + } + } + unset($attrs[$attr]); // This filter has been fully processed + } elseif (preg_match('/^(?:\w+):PLAC CONTAINS (.+)$/', $value, $match)) { + $sql_join .= " JOIN `##places` AS {$attr}a ON ({$attr}a.p_file=f_file)"; + $sql_join .= " JOIN `##placelinks` AS {$attr}b ON ({$attr}a.p_file={$attr}b.pl_file AND {$attr}b.pl_p_id={$attr}a.p_id AND {$attr}b.pl_gid=f_id)"; + $sql_where .= " AND {$attr}a.p_place LIKE CONCAT('%', :{$attr}place, '%')"; + $sql_params[$attr . 'place'] = $match[1]; + // Don't unset this filter. This is just initial filtering + } elseif (preg_match('/^(\w*):*(\w*) CONTAINS (.+)$/', $value, $match)) { + $sql_where .= " AND f_gedcom LIKE CONCAT('%', :{$attr}contains1, '%', :{$attr}contains2, '%', :{$attr}contains3, '%')"; + $sql_params[$attr . 'contains1'] = $match[1]; + $sql_params[$attr . 'contains2'] = $match[2]; + $sql_params[$attr . 'contains3'] = $match[3]; + // Don't unset this filter. This is just initial filtering + } + } + } - $this->list = []; - $rows = Database::prepare( - $sql_select . $sql_join . $sql_where . $sql_order_by - )->execute($sql_params)->fetchAll(); + $this->list = []; + $rows = Database::prepare( + $sql_select . $sql_join . $sql_where . $sql_order_by + )->execute($sql_params)->fetchAll(); - foreach ($rows as $row) { - $this->list[$row->xref] = Family::getInstance($row->xref, $this->tree, $row->gedcom); - } - break; + foreach ($rows as $row) { + $this->list[$row->xref] = Family::getInstance($row->xref, $this->tree, $row->gedcom); + } + break; - default: - throw new \DomainException('Invalid list name: ' . $listname); - } + default: + throw new \DomainException('Invalid list name: ' . $listname); + } - $filters = []; - $filters2 = []; - if (isset($attrs['filter1']) && count($this->list) > 0) { - foreach ($attrs as $key => $value) { - if (preg_match("/filter(\d)/", $key)) { - $condition = $value; - if (preg_match("/@(\w+)/", $condition, $match)) { - $id = $match[1]; - $value = "''"; - if ($id == 'ID') { - if (preg_match('/0 @(.+)@/', $this->gedrec, $match)) { - $value = "'" . $match[1] . "'"; - } - } elseif ($id == 'fact') { - $value = "'" . $this->fact . "'"; - } elseif ($id == 'desc') { - $value = "'" . $this->desc . "'"; - } else { - if (preg_match("/\d $id (.+)/", $this->gedrec, $match)) { - $value = "'" . str_replace('@', '', trim($match[1])) . "'"; - } - } - $condition = preg_replace("/@$id/", $value, $condition); - } - //-- handle regular expressions - if (preg_match("/([A-Z:]+)\s*([^\s]+)\s*(.+)/", $condition, $match)) { - $tag = trim($match[1]); - $expr = trim($match[2]); - $val = trim($match[3]); - if (preg_match("/\\$(\w+)/", $val, $match)) { - $val = $this->vars[$match[1]]['id']; - $val = trim($val); - } - if ($val) { - $searchstr = ''; - $tags = explode(':', $tag); - //-- only limit to a level number if we are specifically looking at a level - if (count($tags) > 1) { - $level = 1; - foreach ($tags as $t) { - if (!empty($searchstr)) { - $searchstr .= "[^\n]*(\n[2-9][^\n]*)*\n"; - } - //-- search for both EMAIL and _EMAIL... silly double gedcom standard - if ($t == 'EMAIL' || $t == '_EMAIL') { - $t = '_?EMAIL'; - } - $searchstr .= $level . ' ' . $t; - $level++; - } - } else { - if ($tag == 'EMAIL' || $tag == '_EMAIL') { - $tag = '_?EMAIL'; - } - $t = $tag; - $searchstr = '1 ' . $tag; - } - switch ($expr) { - case 'CONTAINS': - if ($t == 'PLAC') { - $searchstr .= "[^\n]*[, ]*" . $val; - } else { - $searchstr .= "[^\n]*" . $val; - } - $filters[] = $searchstr; - break; - default: - $filters2[] = ['tag' => $tag, 'expr' => $expr, 'val' => $val]; - break; - } - } - } - } - } - } - //-- apply other filters to the list that could not be added to the search string - if ($filters) { - foreach ($this->list as $key => $record) { - foreach ($filters as $filter) { - if (!preg_match('/' . $filter . '/i', $record->privatizeGedcom(Auth::accessLevel($this->tree)))) { - unset($this->list[$key]); - break; - } - } - } - } - if ($filters2) { - $mylist = []; - foreach ($this->list as $indi) { - $key = $indi->getXref(); - $grec = $indi->privatizeGedcom(Auth::accessLevel($this->tree)); - $keep = true; - foreach ($filters2 as $filter) { - if ($keep) { - $tag = $filter['tag']; - $expr = $filter['expr']; - $val = $filter['val']; - if ($val == "''") { - $val = ''; - } - $tags = explode(':', $tag); - $t = end($tags); - $v = $this->getGedcomValue($tag, 1, $grec); - //-- check for EMAIL and _EMAIL (silly double gedcom standard :P) - if ($t == 'EMAIL' && empty($v)) { - $tag = str_replace('EMAIL', '_EMAIL', $tag); - $tags = explode(':', $tag); - $t = end($tags); - $v = Functions::getSubRecord(1, $tag, $grec); - } + $filters = []; + $filters2 = []; + if (isset($attrs['filter1']) && count($this->list) > 0) { + foreach ($attrs as $key => $value) { + if (preg_match("/filter(\d)/", $key)) { + $condition = $value; + if (preg_match("/@(\w+)/", $condition, $match)) { + $id = $match[1]; + $value = "''"; + if ($id == 'ID') { + if (preg_match('/0 @(.+)@/', $this->gedrec, $match)) { + $value = "'" . $match[1] . "'"; + } + } elseif ($id == 'fact') { + $value = "'" . $this->fact . "'"; + } elseif ($id == 'desc') { + $value = "'" . $this->desc . "'"; + } else { + if (preg_match("/\d $id (.+)/", $this->gedrec, $match)) { + $value = "'" . str_replace('@', '', trim($match[1])) . "'"; + } + } + $condition = preg_replace("/@$id/", $value, $condition); + } + //-- handle regular expressions + if (preg_match("/([A-Z:]+)\s*([^\s]+)\s*(.+)/", $condition, $match)) { + $tag = trim($match[1]); + $expr = trim($match[2]); + $val = trim($match[3]); + if (preg_match("/\\$(\w+)/", $val, $match)) { + $val = $this->vars[$match[1]]['id']; + $val = trim($val); + } + if ($val) { + $searchstr = ''; + $tags = explode(':', $tag); + //-- only limit to a level number if we are specifically looking at a level + if (count($tags) > 1) { + $level = 1; + foreach ($tags as $t) { + if (!empty($searchstr)) { + $searchstr .= "[^\n]*(\n[2-9][^\n]*)*\n"; + } + //-- search for both EMAIL and _EMAIL... silly double gedcom standard + if ($t == 'EMAIL' || $t == '_EMAIL') { + $t = '_?EMAIL'; + } + $searchstr .= $level . ' ' . $t; + $level++; + } + } else { + if ($tag == 'EMAIL' || $tag == '_EMAIL') { + $tag = '_?EMAIL'; + } + $t = $tag; + $searchstr = '1 ' . $tag; + } + switch ($expr) { + case 'CONTAINS': + if ($t == 'PLAC') { + $searchstr .= "[^\n]*[, ]*" . $val; + } else { + $searchstr .= "[^\n]*" . $val; + } + $filters[] = $searchstr; + break; + default: + $filters2[] = [ + 'tag' => $tag, + 'expr' => $expr, + 'val' => $val, + ]; + break; + } + } + } + } + } + } + //-- apply other filters to the list that could not be added to the search string + if ($filters) { + foreach ($this->list as $key => $record) { + foreach ($filters as $filter) { + if (!preg_match('/' . $filter . '/i', $record->privatizeGedcom(Auth::accessLevel($this->tree)))) { + unset($this->list[$key]); + break; + } + } + } + } + if ($filters2) { + $mylist = []; + foreach ($this->list as $indi) { + $key = $indi->getXref(); + $grec = $indi->privatizeGedcom(Auth::accessLevel($this->tree)); + $keep = true; + foreach ($filters2 as $filter) { + if ($keep) { + $tag = $filter['tag']; + $expr = $filter['expr']; + $val = $filter['val']; + if ($val == "''") { + $val = ''; + } + $tags = explode(':', $tag); + $t = end($tags); + $v = $this->getGedcomValue($tag, 1, $grec); + //-- check for EMAIL and _EMAIL (silly double gedcom standard :P) + if ($t == 'EMAIL' && empty($v)) { + $tag = str_replace('EMAIL', '_EMAIL', $tag); + $tags = explode(':', $tag); + $t = end($tags); + $v = Functions::getSubRecord(1, $tag, $grec); + } - switch ($expr) { - case 'GTE': - if ($t == 'DATE') { - $date1 = new Date($v); - $date2 = new Date($val); - $keep = (Date::compare($date1, $date2) >= 0); - } elseif ($val >= $v) { - $keep = true; - } - break; - case 'LTE': - if ($t == 'DATE') { - $date1 = new Date($v); - $date2 = new Date($val); - $keep = (Date::compare($date1, $date2) <= 0); - } elseif ($val >= $v) { - $keep = true; - } - break; - default: - if ($v == $val) { - $keep = true; - } else { - $keep = false; - } - break; - } - } - } - if ($keep) { - $mylist[$key] = $indi; - } - } - $this->list = $mylist; - } + switch ($expr) { + case 'GTE': + if ($t == 'DATE') { + $date1 = new Date($v); + $date2 = new Date($val); + $keep = (Date::compare($date1, $date2) >= 0); + } elseif ($val >= $v) { + $keep = true; + } + break; + case 'LTE': + if ($t == 'DATE') { + $date1 = new Date($v); + $date2 = new Date($val); + $keep = (Date::compare($date1, $date2) <= 0); + } elseif ($val >= $v) { + $keep = true; + } + break; + default: + if ($v == $val) { + $keep = true; + } else { + $keep = false; + } + break; + } + } + } + if ($keep) { + $mylist[$key] = $indi; + } + } + $this->list = $mylist; + } - switch ($sortby) { - case 'NAME': - uasort($this->list, '\Fisharebest\Webtrees\GedcomRecord::compare'); - break; - case 'CHAN': - uasort($this->list, function (GedcomRecord $x, GedcomRecord $y) { - return $y->lastChangeTimestamp(true) - $x->lastChangeTimestamp(true); - }); - break; - case 'BIRT:DATE': - uasort($this->list, '\Fisharebest\Webtrees\Individual::compareBirthDate'); - break; - case 'DEAT:DATE': - uasort($this->list, '\Fisharebest\Webtrees\Individual::compareDeathDate'); - break; - case 'MARR:DATE': - uasort($this->list, '\Fisharebest\Webtrees\Family::compareMarrDate'); - break; - default: - // unsorted or already sorted by SQL - break; - } + switch ($sortby) { + case 'NAME': + uasort($this->list, '\Fisharebest\Webtrees\GedcomRecord::compare'); + break; + case 'CHAN': + uasort($this->list, function (GedcomRecord $x, GedcomRecord $y) { + return $y->lastChangeTimestamp(true) - $x->lastChangeTimestamp(true); + }); + break; + case 'BIRT:DATE': + uasort($this->list, '\Fisharebest\Webtrees\Individual::compareBirthDate'); + break; + case 'DEAT:DATE': + uasort($this->list, '\Fisharebest\Webtrees\Individual::compareDeathDate'); + break; + case 'MARR:DATE': + uasort($this->list, '\Fisharebest\Webtrees\Family::compareMarrDate'); + break; + default: + // unsorted or already sorted by SQL + break; + } - array_push($this->repeats_stack, [$this->repeats, $this->repeat_bytes]); - $this->repeat_bytes = xml_get_current_line_number($this->parser) + 1; - } + array_push($this->repeats_stack, [ + $this->repeats, + $this->repeat_bytes, + ]); + $this->repeat_bytes = xml_get_current_line_number($this->parser) + 1; + } - /** - * XML <List> - */ - private function listEndHandler() { - $this->process_repeats--; - if ($this->process_repeats > 0) { - return; - } + /** + * XML <List> + */ + private function listEndHandler() + { + $this->process_repeats--; + if ($this->process_repeats > 0) { + return; + } - // Check if there is any list - if (count($this->list) > 0) { - $lineoffset = 0; - foreach ($this->repeats_stack as $rep) { - $lineoffset += $rep[1]; - } - //-- read the xml from the file - $lines = file($this->report); - while ((strpos($lines[$lineoffset + $this->repeat_bytes], '<List') === false) && (($lineoffset + $this->repeat_bytes) > 0)) { - $lineoffset--; - } - $lineoffset++; - $reportxml = "<tempdoc>\n"; - $line_nr = $lineoffset + $this->repeat_bytes; - // List Level counter - $count = 1; - while (0 < $count) { - if (strpos($lines[$line_nr], '<List') !== false) { - $count++; - } elseif (strpos($lines[$line_nr], '</List') !== false) { - $count--; - } - if (0 < $count) { - $reportxml .= $lines[$line_nr]; - } - $line_nr++; - } - // No need to drag this - unset($lines); - $reportxml .= '</tempdoc>'; - // Save original values - array_push($this->parser_stack, $this->parser); - $oldgedrec = $this->gedrec; + // Check if there is any list + if (count($this->list) > 0) { + $lineoffset = 0; + foreach ($this->repeats_stack as $rep) { + $lineoffset += $rep[1]; + } + //-- read the xml from the file + $lines = file($this->report); + while ((strpos($lines[$lineoffset + $this->repeat_bytes], '<List') === false) && (($lineoffset + $this->repeat_bytes) > 0)) { + $lineoffset--; + } + $lineoffset++; + $reportxml = "<tempdoc>\n"; + $line_nr = $lineoffset + $this->repeat_bytes; + // List Level counter + $count = 1; + while (0 < $count) { + if (strpos($lines[$line_nr], '<List') !== false) { + $count++; + } elseif (strpos($lines[$line_nr], '</List') !== false) { + $count--; + } + if (0 < $count) { + $reportxml .= $lines[$line_nr]; + } + $line_nr++; + } + // No need to drag this + unset($lines); + $reportxml .= '</tempdoc>'; + // Save original values + array_push($this->parser_stack, $this->parser); + $oldgedrec = $this->gedrec; - $this->list_total = count($this->list); - $this->list_private = 0; - foreach ($this->list as $record) { - if ($record->canShow()) { - $this->gedrec = $record->privatizeGedcom(Auth::accessLevel($record->getTree())); - //-- start the sax parser - $repeat_parser = xml_parser_create(); - $this->parser = $repeat_parser; - xml_parser_set_option($repeat_parser, XML_OPTION_CASE_FOLDING, false); - xml_set_element_handler($repeat_parser, [$this, 'startElement'], [$this, 'endElement']); - xml_set_character_data_handler($repeat_parser, [$this, 'characterData']); - if (!xml_parse($repeat_parser, $reportxml, true)) { - throw new \DomainException(sprintf( - 'ListEHandler XML error: %s at line %d', - xml_error_string(xml_get_error_code($repeat_parser)), - xml_get_current_line_number($repeat_parser) - )); - } - xml_parser_free($repeat_parser); - } else { - $this->list_private++; - } - } - $this->list = []; - $this->parser = array_pop($this->parser_stack); - $this->gedrec = $oldgedrec; - } - list($this->repeats, $this->repeat_bytes) = array_pop($this->repeats_stack); - } + $this->list_total = count($this->list); + $this->list_private = 0; + foreach ($this->list as $record) { + if ($record->canShow()) { + $this->gedrec = $record->privatizeGedcom(Auth::accessLevel($record->getTree())); + //-- start the sax parser + $repeat_parser = xml_parser_create(); + $this->parser = $repeat_parser; + xml_parser_set_option($repeat_parser, XML_OPTION_CASE_FOLDING, false); + xml_set_element_handler($repeat_parser, [ + $this, + 'startElement', + ], [ + $this, + 'endElement', + ]); + xml_set_character_data_handler($repeat_parser, [ + $this, + 'characterData', + ]); + if (!xml_parse($repeat_parser, $reportxml, true)) { + throw new \DomainException(sprintf( + 'ListEHandler XML error: %s at line %d', + xml_error_string(xml_get_error_code($repeat_parser)), + xml_get_current_line_number($repeat_parser) + )); + } + xml_parser_free($repeat_parser); + } else { + $this->list_private++; + } + } + $this->list = []; + $this->parser = array_pop($this->parser_stack); + $this->gedrec = $oldgedrec; + } + list($this->repeats, $this->repeat_bytes) = array_pop($this->repeats_stack); + } - /** - * XML <ListTotal> element handler - * - * Prints the total number of records in a list - * The total number is collected from - * List and Relatives - */ - private function listTotalStartHandler() { - if ($this->list_private == 0) { - $this->current_element->addText($this->list_total); - } else { - $this->current_element->addText(($this->list_total - $this->list_private) . ' / ' . $this->list_total); - } - } + /** + * XML <ListTotal> element handler + * + * Prints the total number of records in a list + * The total number is collected from + * List and Relatives + */ + private function listTotalStartHandler() + { + if ($this->list_private == 0) { + $this->current_element->addText($this->list_total); + } else { + $this->current_element->addText(($this->list_total - $this->list_private) . ' / ' . $this->list_total); + } + } - /** - * XML <Relatives> - * - * @param array $attrs an array of key value pairs for the attributes - */ - private function relativesStartHandler($attrs) { - $this->process_repeats++; - if ($this->process_repeats > 1) { - return; - } + /** + * XML <Relatives> + * + * @param array $attrs an array of key value pairs for the attributes + */ + private function relativesStartHandler($attrs) + { + $this->process_repeats++; + if ($this->process_repeats > 1) { + return; + } - $sortby = 'NAME'; - if (isset($attrs['sortby'])) { - $sortby = $attrs['sortby']; - } - $match = []; - if (preg_match("/\\$(\w+)/", $sortby, $match)) { - $sortby = $this->vars[$match[1]]['id']; - $sortby = trim($sortby); - } + $sortby = 'NAME'; + if (isset($attrs['sortby'])) { + $sortby = $attrs['sortby']; + } + $match = []; + if (preg_match("/\\$(\w+)/", $sortby, $match)) { + $sortby = $this->vars[$match[1]]['id']; + $sortby = trim($sortby); + } - $maxgen = -1; - if (isset($attrs['maxgen'])) { - $maxgen = $attrs['maxgen']; - } - if ($maxgen == '*') { - $maxgen = -1; - } + $maxgen = -1; + if (isset($attrs['maxgen'])) { + $maxgen = $attrs['maxgen']; + } + if ($maxgen == '*') { + $maxgen = -1; + } - $group = 'child-family'; - if (isset($attrs['group'])) { - $group = $attrs['group']; - } - if (preg_match("/\\$(\w+)/", $group, $match)) { - $group = $this->vars[$match[1]]['id']; - $group = trim($group); - } + $group = 'child-family'; + if (isset($attrs['group'])) { + $group = $attrs['group']; + } + if (preg_match("/\\$(\w+)/", $group, $match)) { + $group = $this->vars[$match[1]]['id']; + $group = trim($group); + } - $id = ''; - if (isset($attrs['id'])) { - $id = $attrs['id']; - } - if (preg_match("/\\$(\w+)/", $id, $match)) { - $id = $this->vars[$match[1]]['id']; - $id = trim($id); - } + $id = ''; + if (isset($attrs['id'])) { + $id = $attrs['id']; + } + if (preg_match("/\\$(\w+)/", $id, $match)) { + $id = $this->vars[$match[1]]['id']; + $id = trim($id); + } - $this->list = []; - $person = Individual::getInstance($id, $this->tree); - if (!empty($person)) { - $this->list[$id] = $person; - switch ($group) { - case 'child-family': - foreach ($person->getChildFamilies() as $family) { - $husband = $family->getHusband(); - $wife = $family->getWife(); - if (!empty($husband)) { - $this->list[$husband->getXref()] = $husband; - } - if (!empty($wife)) { - $this->list[$wife->getXref()] = $wife; - } - $children = $family->getChildren(); - foreach ($children as $child) { - if (!empty($child)) { - $this->list[$child->getXref()] = $child; - } - } - } - break; - case 'spouse-family': - foreach ($person->getSpouseFamilies() as $family) { - $husband = $family->getHusband(); - $wife = $family->getWife(); - if (!empty($husband)) { - $this->list[$husband->getXref()] = $husband; - } - if (!empty($wife)) { - $this->list[$wife->getXref()] = $wife; - } - $children = $family->getChildren(); - foreach ($children as $child) { - if (!empty($child)) { - $this->list[$child->getXref()] = $child; - } - } - } - break; - case 'direct-ancestors': - $this->addAncestors($this->list, $id, false, $maxgen); - break; - case 'ancestors': - $this->addAncestors($this->list, $id, true, $maxgen); - break; - case 'descendants': - $this->list[$id]->generation = 1; - $this->addDescendancy($this->list, $id, false, $maxgen); - break; - case 'all': - $this->addAncestors($this->list, $id, true, $maxgen); - $this->addDescendancy($this->list, $id, true, $maxgen); - break; - } - } + $this->list = []; + $person = Individual::getInstance($id, $this->tree); + if (!empty($person)) { + $this->list[$id] = $person; + switch ($group) { + case 'child-family': + foreach ($person->getChildFamilies() as $family) { + $husband = $family->getHusband(); + $wife = $family->getWife(); + if (!empty($husband)) { + $this->list[$husband->getXref()] = $husband; + } + if (!empty($wife)) { + $this->list[$wife->getXref()] = $wife; + } + $children = $family->getChildren(); + foreach ($children as $child) { + if (!empty($child)) { + $this->list[$child->getXref()] = $child; + } + } + } + break; + case 'spouse-family': + foreach ($person->getSpouseFamilies() as $family) { + $husband = $family->getHusband(); + $wife = $family->getWife(); + if (!empty($husband)) { + $this->list[$husband->getXref()] = $husband; + } + if (!empty($wife)) { + $this->list[$wife->getXref()] = $wife; + } + $children = $family->getChildren(); + foreach ($children as $child) { + if (!empty($child)) { + $this->list[$child->getXref()] = $child; + } + } + } + break; + case 'direct-ancestors': + $this->addAncestors($this->list, $id, false, $maxgen); + break; + case 'ancestors': + $this->addAncestors($this->list, $id, true, $maxgen); + break; + case 'descendants': + $this->list[$id]->generation = 1; + $this->addDescendancy($this->list, $id, false, $maxgen); + break; + case 'all': + $this->addAncestors($this->list, $id, true, $maxgen); + $this->addDescendancy($this->list, $id, true, $maxgen); + break; + } + } - switch ($sortby) { - case 'NAME': - uasort($this->list, '\Fisharebest\Webtrees\GedcomRecord::compare'); - break; - case 'BIRT:DATE': - uasort($this->list, '\Fisharebest\Webtrees\Individual::compareBirthDate'); - break; - case 'DEAT:DATE': - uasort($this->list, '\Fisharebest\Webtrees\Individual::compareDeathDate'); - break; - case 'generation': - $newarray = []; - reset($this->list); - $genCounter = 1; - while (count($newarray) < count($this->list)) { - foreach ($this->list as $key => $value) { - $this->generation = $value->generation; - if ($this->generation == $genCounter) { - $newarray[$key] = new \stdClass; - $newarray[$key]->generation = $this->generation; - } - } - $genCounter++; - } - $this->list = $newarray; - break; - default: - // unsorted - break; - } - array_push($this->repeats_stack, [$this->repeats, $this->repeat_bytes]); - $this->repeat_bytes = xml_get_current_line_number($this->parser) + 1; - } + switch ($sortby) { + case 'NAME': + uasort($this->list, '\Fisharebest\Webtrees\GedcomRecord::compare'); + break; + case 'BIRT:DATE': + uasort($this->list, '\Fisharebest\Webtrees\Individual::compareBirthDate'); + break; + case 'DEAT:DATE': + uasort($this->list, '\Fisharebest\Webtrees\Individual::compareDeathDate'); + break; + case 'generation': + $newarray = []; + reset($this->list); + $genCounter = 1; + while (count($newarray) < count($this->list)) { + foreach ($this->list as $key => $value) { + $this->generation = $value->generation; + if ($this->generation == $genCounter) { + $newarray[$key] = new \stdClass; + $newarray[$key]->generation = $this->generation; + } + } + $genCounter++; + } + $this->list = $newarray; + break; + default: + // unsorted + break; + } + array_push($this->repeats_stack, [ + $this->repeats, + $this->repeat_bytes, + ]); + $this->repeat_bytes = xml_get_current_line_number($this->parser) + 1; + } - /** - * XML </ Relatives> - */ - private function relativesEndHandler() { - $this->process_repeats--; - if ($this->process_repeats > 0) { - return; - } + /** + * XML </ Relatives> + */ + private function relativesEndHandler() + { + $this->process_repeats--; + if ($this->process_repeats > 0) { + return; + } - // Check if there is any relatives - if (count($this->list) > 0) { - $lineoffset = 0; - foreach ($this->repeats_stack as $rep) { - $lineoffset += $rep[1]; - } - //-- read the xml from the file - $lines = file($this->report); - while ((strpos($lines[$lineoffset + $this->repeat_bytes], '<Relatives') === false) && (($lineoffset + $this->repeat_bytes) > 0)) { - $lineoffset--; - } - $lineoffset++; - $reportxml = "<tempdoc>\n"; - $line_nr = $lineoffset + $this->repeat_bytes; - // Relatives Level counter - $count = 1; - while (0 < $count) { - if (strpos($lines[$line_nr], '<Relatives') !== false) { - $count++; - } elseif (strpos($lines[$line_nr], '</Relatives') !== false) { - $count--; - } - if (0 < $count) { - $reportxml .= $lines[$line_nr]; - } - $line_nr++; - } - // No need to drag this - unset($lines); - $reportxml .= "</tempdoc>\n"; - // Save original values - array_push($this->parser_stack, $this->parser); - $oldgedrec = $this->gedrec; + // Check if there is any relatives + if (count($this->list) > 0) { + $lineoffset = 0; + foreach ($this->repeats_stack as $rep) { + $lineoffset += $rep[1]; + } + //-- read the xml from the file + $lines = file($this->report); + while ((strpos($lines[$lineoffset + $this->repeat_bytes], '<Relatives') === false) && (($lineoffset + $this->repeat_bytes) > 0)) { + $lineoffset--; + } + $lineoffset++; + $reportxml = "<tempdoc>\n"; + $line_nr = $lineoffset + $this->repeat_bytes; + // Relatives Level counter + $count = 1; + while (0 < $count) { + if (strpos($lines[$line_nr], '<Relatives') !== false) { + $count++; + } elseif (strpos($lines[$line_nr], '</Relatives') !== false) { + $count--; + } + if (0 < $count) { + $reportxml .= $lines[$line_nr]; + } + $line_nr++; + } + // No need to drag this + unset($lines); + $reportxml .= "</tempdoc>\n"; + // Save original values + array_push($this->parser_stack, $this->parser); + $oldgedrec = $this->gedrec; - $this->list_total = count($this->list); - $this->list_private = 0; - foreach ($this->list as $key => $value) { - if (isset($value->generation)) { - $this->generation = $value->generation; - } - $tmp = GedcomRecord::getInstance($key, $this->tree); - $this->gedrec = $tmp->privatizeGedcom(Auth::accessLevel($this->tree)); + $this->list_total = count($this->list); + $this->list_private = 0; + foreach ($this->list as $key => $value) { + if (isset($value->generation)) { + $this->generation = $value->generation; + } + $tmp = GedcomRecord::getInstance($key, $this->tree); + $this->gedrec = $tmp->privatizeGedcom(Auth::accessLevel($this->tree)); - $repeat_parser = xml_parser_create(); - $this->parser = $repeat_parser; - xml_parser_set_option($repeat_parser, XML_OPTION_CASE_FOLDING, false); - xml_set_element_handler($repeat_parser, [$this, 'startElement'], [$this, 'endElement']); - xml_set_character_data_handler($repeat_parser, [$this, 'characterData']); + $repeat_parser = xml_parser_create(); + $this->parser = $repeat_parser; + xml_parser_set_option($repeat_parser, XML_OPTION_CASE_FOLDING, false); + xml_set_element_handler($repeat_parser, [ + $this, + 'startElement', + ], [ + $this, + 'endElement', + ]); + xml_set_character_data_handler($repeat_parser, [ + $this, + 'characterData', + ]); - if (!xml_parse($repeat_parser, $reportxml, true)) { - throw new \DomainException(sprintf('RelativesEHandler XML error: %s at line %d', xml_error_string(xml_get_error_code($repeat_parser)), xml_get_current_line_number($repeat_parser))); - } - xml_parser_free($repeat_parser); - } - // Clean up the list array - $this->list = []; - $this->parser = array_pop($this->parser_stack); - $this->gedrec = $oldgedrec; - } - list($this->repeats, $this->repeat_bytes) = array_pop($this->repeats_stack); - } + if (!xml_parse($repeat_parser, $reportxml, true)) { + throw new \DomainException(sprintf('RelativesEHandler XML error: %s at line %d', xml_error_string(xml_get_error_code($repeat_parser)), xml_get_current_line_number($repeat_parser))); + } + xml_parser_free($repeat_parser); + } + // Clean up the list array + $this->list = []; + $this->parser = array_pop($this->parser_stack); + $this->gedrec = $oldgedrec; + } + list($this->repeats, $this->repeat_bytes) = array_pop($this->repeats_stack); + } - /** - * XML <Generation /> element handler - * - * Prints the number of generations - */ - private function generationStartHandler() { - $this->current_element->addText($this->generation); - } + /** + * XML <Generation /> element handler + * + * Prints the number of generations + */ + private function generationStartHandler() + { + $this->current_element->addText($this->generation); + } - /** - * XML <NewPage /> element handler - * - * Has to be placed in an element (header, pageheader, body or footer) - */ - private function newPageStartHandler() { - $temp = 'addpage'; - $this->wt_report->addElement($temp); - } + /** + * XML <NewPage /> element handler + * + * Has to be placed in an element (header, pageheader, body or footer) + */ + private function newPageStartHandler() + { + $temp = 'addpage'; + $this->wt_report->addElement($temp); + } - /** - * XML <html> - * - * @param string $tag HTML tag name - * @param array[] $attrs an array of key value pairs for the attributes - */ - private function htmlStartHandler($tag, $attrs) { - if ($tag === 'tempdoc') { - return; - } - array_push($this->wt_report_stack, $this->wt_report); - $this->wt_report = $this->report_root->createHTML($tag, $attrs); - $this->current_element = $this->wt_report; + /** + * XML <html> + * + * @param string $tag HTML tag name + * @param array[] $attrs an array of key value pairs for the attributes + */ + private function htmlStartHandler($tag, $attrs) + { + if ($tag === 'tempdoc') { + return; + } + array_push($this->wt_report_stack, $this->wt_report); + $this->wt_report = $this->report_root->createHTML($tag, $attrs); + $this->current_element = $this->wt_report; - array_push($this->print_data_stack, $this->print_data); - $this->print_data = true; - } + array_push($this->print_data_stack, $this->print_data); + $this->print_data = true; + } - /** - * XML </html> - * - * @param string $tag - */ - private function htmlEndHandler($tag) { - if ($tag === 'tempdoc') { - return; - } + /** + * XML </html> + * + * @param string $tag + */ + private function htmlEndHandler($tag) + { + if ($tag === 'tempdoc') { + return; + } - $this->print_data = array_pop($this->print_data_stack); - $this->current_element = $this->wt_report; - $this->wt_report = array_pop($this->wt_report_stack); - if (!is_null($this->wt_report)) { - $this->wt_report->addElement($this->current_element); - } else { - $this->wt_report = $this->current_element; - } - } + $this->print_data = array_pop($this->print_data_stack); + $this->current_element = $this->wt_report; + $this->wt_report = array_pop($this->wt_report_stack); + if (!is_null($this->wt_report)) { + $this->wt_report->addElement($this->current_element); + } else { + $this->wt_report = $this->current_element; + } + } - /** - * Handle <Input> - */ - private function inputStartHandler() { - // Dummy function, to prevent the default HtmlStartHandler() being called - } + /** + * Handle <Input> + */ + private function inputStartHandler() + { + // Dummy function, to prevent the default HtmlStartHandler() being called + } - /** - * Handle </Input> - */ - private function inputEndHandler() { - // Dummy function, to prevent the default HtmlEndHandler() being called - } + /** + * Handle </Input> + */ + private function inputEndHandler() + { + // Dummy function, to prevent the default HtmlEndHandler() being called + } - /** - * Handle <Report> - */ - private function reportStartHandler() { - // Dummy function, to prevent the default HtmlStartHandler() being called - } + /** + * Handle <Report> + */ + private function reportStartHandler() + { + // Dummy function, to prevent the default HtmlStartHandler() being called + } - /** - * Handle </Report> - */ - private function reportEndHandler() { - // Dummy function, to prevent the default HtmlEndHandler() being called - } + /** + * Handle </Report> + */ + private function reportEndHandler() + { + // Dummy function, to prevent the default HtmlEndHandler() being called + } - /** - * XML </titleEndHandler> - */ - private function titleEndHandler() { - $this->report_root->addTitle($this->text); - } + /** + * XML </titleEndHandler> + */ + private function titleEndHandler() + { + $this->report_root->addTitle($this->text); + } - /** - * XML </descriptionEndHandler> - */ - private function descriptionEndHandler() { - $this->report_root->addDescription($this->text); - } + /** + * XML </descriptionEndHandler> + */ + private function descriptionEndHandler() + { + $this->report_root->addDescription($this->text); + } - /** - * Create a list of all descendants. - * - * @param string[] $list - * @param string $pid - * @param bool $parents - * @param int $generations - */ - private function addDescendancy(&$list, $pid, $parents = false, $generations = -1) { - $person = Individual::getInstance($pid, $this->tree); - if ($person === null) { - return; - } - if (!isset($list[$pid])) { - $list[$pid] = $person; - } - if (!isset($list[$pid]->generation)) { - $list[$pid]->generation = 0; - } - foreach ($person->getSpouseFamilies() as $family) { - if ($parents) { - $husband = $family->getHusband(); - $wife = $family->getWife(); - if ($husband) { - $list[$husband->getXref()] = $husband; - if (isset($list[$pid]->generation)) { - $list[$husband->getXref()]->generation = $list[$pid]->generation - 1; - } else { - $list[$husband->getXref()]->generation = 1; - } - } - if ($wife) { - $list[$wife->getXref()] = $wife; - if (isset($list[$pid]->generation)) { - $list[$wife->getXref()]->generation = $list[$pid]->generation - 1; - } else { - $list[$wife->getXref()]->generation = 1; - } - } - } - $children = $family->getChildren(); - foreach ($children as $child) { - if ($child) { - $list[$child->getXref()] = $child; - if (isset($list[$pid]->generation)) { - $list[$child->getXref()]->generation = $list[$pid]->generation + 1; - } else { - $list[$child->getXref()]->generation = 2; - } - } - } - if ($generations == -1 || $list[$pid]->generation + 1 < $generations) { - foreach ($children as $child) { - $this->addDescendancy($list, $child->getXref(), $parents, $generations); // recurse on the childs family - } - } - } - } + /** + * Create a list of all descendants. + * + * @param string[] $list + * @param string $pid + * @param bool $parents + * @param int $generations + */ + private function addDescendancy(&$list, $pid, $parents = false, $generations = -1) + { + $person = Individual::getInstance($pid, $this->tree); + if ($person === null) { + return; + } + if (!isset($list[$pid])) { + $list[$pid] = $person; + } + if (!isset($list[$pid]->generation)) { + $list[$pid]->generation = 0; + } + foreach ($person->getSpouseFamilies() as $family) { + if ($parents) { + $husband = $family->getHusband(); + $wife = $family->getWife(); + if ($husband) { + $list[$husband->getXref()] = $husband; + if (isset($list[$pid]->generation)) { + $list[$husband->getXref()]->generation = $list[$pid]->generation - 1; + } else { + $list[$husband->getXref()]->generation = 1; + } + } + if ($wife) { + $list[$wife->getXref()] = $wife; + if (isset($list[$pid]->generation)) { + $list[$wife->getXref()]->generation = $list[$pid]->generation - 1; + } else { + $list[$wife->getXref()]->generation = 1; + } + } + } + $children = $family->getChildren(); + foreach ($children as $child) { + if ($child) { + $list[$child->getXref()] = $child; + if (isset($list[$pid]->generation)) { + $list[$child->getXref()]->generation = $list[$pid]->generation + 1; + } else { + $list[$child->getXref()]->generation = 2; + } + } + } + if ($generations == -1 || $list[$pid]->generation + 1 < $generations) { + foreach ($children as $child) { + $this->addDescendancy($list, $child->getXref(), $parents, $generations); // recurse on the childs family + } + } + } + } - /** - * Create a list of all ancestors. - * - * @param string[] $list - * @param string $pid - * @param bool $children - * @param int $generations - */ - private function addAncestors(&$list, $pid, $children = false, $generations = -1) { - $genlist = [$pid]; - $list[$pid]->generation = 1; - while (count($genlist) > 0) { - $id = array_shift($genlist); - if (strpos($id, 'empty') === 0) { - continue; // id can be something like “empty7” - } - $person = Individual::getInstance($id, $this->tree); - foreach ($person->getChildFamilies() as $family) { - $husband = $family->getHusband(); - $wife = $family->getWife(); - if ($husband) { - $list[$husband->getXref()] = $husband; - $list[$husband->getXref()]->generation = $list[$id]->generation + 1; - } - if ($wife) { - $list[$wife->getXref()] = $wife; - $list[$wife->getXref()]->generation = $list[$id]->generation + 1; - } - if ($generations == -1 || $list[$id]->generation + 1 < $generations) { - if ($husband) { - array_push($genlist, $husband->getXref()); - } - if ($wife) { - array_push($genlist, $wife->getXref()); - } - } - if ($children) { - foreach ($family->getChildren() as $child) { - $list[$child->getXref()] = $child; - if (isset($list[$id]->generation)) { - $list[$child->getXref()]->generation = $list[$id]->generation; - } else { - $list[$child->getXref()]->generation = 1; - } - } - } - } - } - } + /** + * Create a list of all ancestors. + * + * @param string[] $list + * @param string $pid + * @param bool $children + * @param int $generations + */ + private function addAncestors(&$list, $pid, $children = false, $generations = -1) + { + $genlist = [$pid]; + $list[$pid]->generation = 1; + while (count($genlist) > 0) { + $id = array_shift($genlist); + if (strpos($id, 'empty') === 0) { + continue; // id can be something like “empty7” + } + $person = Individual::getInstance($id, $this->tree); + foreach ($person->getChildFamilies() as $family) { + $husband = $family->getHusband(); + $wife = $family->getWife(); + if ($husband) { + $list[$husband->getXref()] = $husband; + $list[$husband->getXref()]->generation = $list[$id]->generation + 1; + } + if ($wife) { + $list[$wife->getXref()] = $wife; + $list[$wife->getXref()]->generation = $list[$id]->generation + 1; + } + if ($generations == -1 || $list[$id]->generation + 1 < $generations) { + if ($husband) { + array_push($genlist, $husband->getXref()); + } + if ($wife) { + array_push($genlist, $wife->getXref()); + } + } + if ($children) { + foreach ($family->getChildren() as $child) { + $list[$child->getXref()] = $child; + if (isset($list[$id]->generation)) { + $list[$child->getXref()]->generation = $list[$id]->generation; + } else { + $list[$child->getXref()]->generation = 1; + } + } + } + } + } + } - /** - * get gedcom tag value - * - * @param string $tag The tag to find, use : to delineate subtags - * @param int $level The gedcom line level of the first tag to find, setting level to 0 will cause it to use 1+ the level of the incoming record - * @param string $gedrec The gedcom record to get the value from - * - * @return string the value of a gedcom tag from the given gedcom record - */ - private function getGedcomValue($tag, $level, $gedrec) { - if (empty($gedrec)) { - return ''; - } - $tags = explode(':', $tag); - $origlevel = $level; - if ($level == 0) { - $level = $gedrec[0] + 1; - } + /** + * get gedcom tag value + * + * @param string $tag The tag to find, use : to delineate subtags + * @param int $level The gedcom line level of the first tag to find, setting level to 0 will cause it to use 1+ the level of the incoming record + * @param string $gedrec The gedcom record to get the value from + * + * @return string the value of a gedcom tag from the given gedcom record + */ + private function getGedcomValue($tag, $level, $gedrec) + { + if (empty($gedrec)) { + return ''; + } + $tags = explode(':', $tag); + $origlevel = $level; + if ($level == 0) { + $level = $gedrec[0] + 1; + } - $subrec = $gedrec; - foreach ($tags as $t) { - $lastsubrec = $subrec; - $subrec = Functions::getSubRecord($level, "$level $t", $subrec); - if (empty($subrec) && $origlevel == 0) { - $level--; - $subrec = Functions::getSubRecord($level, "$level $t", $lastsubrec); - } - if (empty($subrec)) { - if ($t == 'TITL') { - $subrec = Functions::getSubRecord($level, "$level ABBR", $lastsubrec); - if (!empty($subrec)) { - $t = 'ABBR'; - } - } - if (empty($subrec)) { - if ($level > 0) { - $level--; - } - $subrec = Functions::getSubRecord($level, "@ $t", $gedrec); - if (empty($subrec)) { - return ''; - } - } - } - $level++; - } - $level--; - $ct = preg_match("/$level $t(.*)/", $subrec, $match); - if ($ct == 0) { - $ct = preg_match("/$level @.+@ (.+)/", $subrec, $match); - } - if ($ct == 0) { - $ct = preg_match("/@ $t (.+)/", $subrec, $match); - } - if ($ct > 0) { - $value = trim($match[1]); - if ($t == 'NOTE' && preg_match('/^@(.+)@$/', $value, $match)) { - $note = Note::getInstance($match[1], $this->tree); - if ($note) { - $value = $note->getNote(); - } else { - //-- set the value to the id without the @ - $value = $match[1]; - } - } - if ($level != 0 || $t != 'NOTE') { - $value .= Functions::getCont($level + 1, $subrec); - } + $subrec = $gedrec; + foreach ($tags as $t) { + $lastsubrec = $subrec; + $subrec = Functions::getSubRecord($level, "$level $t", $subrec); + if (empty($subrec) && $origlevel == 0) { + $level--; + $subrec = Functions::getSubRecord($level, "$level $t", $lastsubrec); + } + if (empty($subrec)) { + if ($t == 'TITL') { + $subrec = Functions::getSubRecord($level, "$level ABBR", $lastsubrec); + if (!empty($subrec)) { + $t = 'ABBR'; + } + } + if (empty($subrec)) { + if ($level > 0) { + $level--; + } + $subrec = Functions::getSubRecord($level, "@ $t", $gedrec); + if (empty($subrec)) { + return ''; + } + } + } + $level++; + } + $level--; + $ct = preg_match("/$level $t(.*)/", $subrec, $match); + if ($ct == 0) { + $ct = preg_match("/$level @.+@ (.+)/", $subrec, $match); + } + if ($ct == 0) { + $ct = preg_match("/@ $t (.+)/", $subrec, $match); + } + if ($ct > 0) { + $value = trim($match[1]); + if ($t == 'NOTE' && preg_match('/^@(.+)@$/', $value, $match)) { + $note = Note::getInstance($match[1], $this->tree); + if ($note) { + $value = $note->getNote(); + } else { + //-- set the value to the id without the @ + $value = $match[1]; + } + } + if ($level != 0 || $t != 'NOTE') { + $value .= Functions::getCont($level + 1, $subrec); + } - return $value; - } + return $value; + } - return ''; - } + return ''; + } - /** - * Replace variable identifiers with their values. - * - * @param string $expression An expression such as "$foo == 123" - * @param bool $quote Whether to add quotation marks - * - * @return string - */ - private function substituteVars($expression, $quote) { - return preg_replace_callback( - '/\$(\w+)/', - function ($matches) use ($quote) { - if (isset($this->vars[$matches[1]]['id'])) { - if ($quote) { - return "'" . addcslashes($this->vars[$matches[1]]['id'], "'") . "'"; - } else { - return $this->vars[$matches[1]]['id']; - } - } else { - Log::addErrorLog(sprintf('Undefined variable $%s in report', $matches[1])); + /** + * Replace variable identifiers with their values. + * + * @param string $expression An expression such as "$foo == 123" + * @param bool $quote Whether to add quotation marks + * + * @return string + */ + private function substituteVars($expression, $quote) + { + return preg_replace_callback( + '/\$(\w+)/', + function ($matches) use ($quote) { + if (isset($this->vars[$matches[1]]['id'])) { + if ($quote) { + return "'" . addcslashes($this->vars[$matches[1]]['id'], "'") . "'"; + } else { + return $this->vars[$matches[1]]['id']; + } + } else { + Log::addErrorLog(sprintf('Undefined variable $%s in report', $matches[1])); - return '$' . $matches[1]; - } - }, - $expression - ); - } + return '$' . $matches[1]; + } + }, + $expression + ); + } } diff --git a/app/Report/ReportParserSetup.php b/app/Report/ReportParserSetup.php index fd02ff7a70..3cb8b1c817 100644 --- a/app/Report/ReportParserSetup.php +++ b/app/Report/ReportParserSetup.php @@ -21,126 +21,135 @@ use Fisharebest\Webtrees\I18N; /** * Class ReportParserSetup - parse a report.xml file and extract the setup options. */ -class ReportParserSetup extends ReportParserBase { - /** @var array An array of report options/parameters */ - private $data = []; +class ReportParserSetup extends ReportParserBase +{ + /** @var array An array of report options/parameters */ + private $data = []; - /** @var string[] An array of input attributes */ - private $input; + /** @var string[] An array of input attributes */ + private $input; - /** - * Return the parsed data. - * - * @return array - */ - public function reportProperties() { - return $this->data; - } + /** + * Return the parsed data. + * + * @return array + */ + public function reportProperties() + { + return $this->data; + } - /** - * Process <Report> - * - * @param string[] $attrs - */ - protected function reportStartHandler($attrs) { - $access = Auth::PRIV_PRIVATE; - if (isset($attrs['access'])) { - if (isset($$attrs['access'])) { - $access = $$attrs['access']; - } - } - $this->data['access'] = $access; + /** + * Process <Report> + * + * @param string[] $attrs + */ + protected function reportStartHandler($attrs) + { + $access = Auth::PRIV_PRIVATE; + if (isset($attrs['access'])) { + if (isset($$attrs['access'])) { + $access = $$attrs['access']; + } + } + $this->data['access'] = $access; - if (isset($attrs['icon'])) { - $this->data['icon'] = $attrs['icon']; - } else { - $this->data['icon'] = ''; - } - } + if (isset($attrs['icon'])) { + $this->data['icon'] = $attrs['icon']; + } else { + $this->data['icon'] = ''; + } + } - /** - * Process <var var=""> - * - * @param string[] $attrs - */ - protected function varStartHandler($attrs) { - if (preg_match('/^I18N::number\((.+)\)$/', $attrs['var'], $match)) { - $this->text .= I18N::number($match[1]); - } elseif (preg_match('/^I18N::translate\(\'(.+)\'\)$/', $attrs['var'], $match)) { - $this->text .= I18N::translate($match[1]); - } elseif (preg_match('/^I18N::translateContext\(\'(.+)\', *\'(.+)\'\)$/', $attrs['var'], $match)) { - $this->text .= I18N::translateContext($match[1], $match[2]); - } else { - $this->text .= $attrs['var']; - } - } + /** + * Process <var var=""> + * + * @param string[] $attrs + */ + protected function varStartHandler($attrs) + { + if (preg_match('/^I18N::number\((.+)\)$/', $attrs['var'], $match)) { + $this->text .= I18N::number($match[1]); + } elseif (preg_match('/^I18N::translate\(\'(.+)\'\)$/', $attrs['var'], $match)) { + $this->text .= I18N::translate($match[1]); + } elseif (preg_match('/^I18N::translateContext\(\'(.+)\', *\'(.+)\'\)$/', $attrs['var'], $match)) { + $this->text .= I18N::translateContext($match[1], $match[2]); + } else { + $this->text .= $attrs['var']; + } + } - /** - * Process <Title> - */ - protected function titleStartHandler() { - $this->text = ''; - } + /** + * Process <Title> + */ + protected function titleStartHandler() + { + $this->text = ''; + } - /** - * Process </Title> - */ - protected function titleEndHandler() { - $this->data['title'] = $this->text; - $this->text = ''; - } + /** + * Process </Title> + */ + protected function titleEndHandler() + { + $this->data['title'] = $this->text; + $this->text = ''; + } - /** - * Process </Description> - */ - protected function descriptionEndHandler() { - $this->data['description'] = $this->text; - $this->text = ''; - } + /** + * Process </Description> + */ + protected function descriptionEndHandler() + { + $this->data['description'] = $this->text; + $this->text = ''; + } - /** - * Process <Input> - * - * @param string[] $attrs - */ - protected function inputStartHandler($attrs) { - $this->text = ''; - $this->input = [ - 'name' => isset($attrs['name']) ? $attrs['name'] : '', - 'type' => isset($attrs['type']) ? $attrs['type'] : '', - 'lookup' => isset($attrs['lookup']) ? $attrs['lookup'] : '', - 'options' => isset($attrs['options']) ? $attrs['options'] : '', - 'default' => '', - 'value' => '', - ]; + /** + * Process <Input> + * + * @param string[] $attrs + */ + protected function inputStartHandler($attrs) + { + $this->text = ''; + $this->input = [ + 'name' => isset($attrs['name']) ? $attrs['name'] : '', + 'type' => isset($attrs['type']) ? $attrs['type'] : '', + 'lookup' => isset($attrs['lookup']) ? $attrs['lookup'] : '', + 'options' => isset($attrs['options']) ? $attrs['options'] : '', + 'default' => '', + 'value' => '', + ]; - if (isset($attrs['default'])) { - if ($attrs['default'] === 'NOW') { - $this->input['default'] = date('d M Y'); - } else { - $match = []; - if (preg_match('/NOW\s*([+\-])\s*(\d+)/', $attrs['default'], $match) > 0) { - $plus = 1; - if ($match[1] === '-') { - $plus = -1; - } - $this->input['default'] = date('d M Y', WT_TIMESTAMP + $plus * 60 * 60 * 24 * $match[2]); - } else { - $this->input['default'] = $attrs['default']; - } - } - } - } + if (isset($attrs['default'])) { + if ($attrs['default'] === 'NOW') { + $this->input['default'] = date('d M Y'); + } else { + $match = []; + if (preg_match('/NOW\s*([+\-])\s*(\d+)/', $attrs['default'], $match) > 0) { + $plus = 1; + if ($match[1] === '-') { + $plus = -1; + } + $this->input['default'] = date('d M Y', WT_TIMESTAMP + $plus * 60 * 60 * 24 * $match[2]); + } else { + $this->input['default'] = $attrs['default']; + } + } + } + } - /** - * Process </Input> - */ - protected function inputEndHandler() { - $this->input['value'] = $this->text; - if (!isset($this->data['inputs'])) { - $this->data['inputs'] = []; - } - $this->data['inputs'][] = $this->input; - $this->text = ''; - } + /** + * Process </Input> + */ + protected function inputEndHandler() + { + $this->input['value'] = $this->text; + if (!isset($this->data['inputs'])) { + $this->data['inputs'] = []; + } + $this->data['inputs'][] = $this->input; + $this->text = ''; + } } diff --git a/app/Report/ReportPdf.php b/app/Report/ReportPdf.php index 3f2b797d99..24e5672845 100644 --- a/app/Report/ReportPdf.php +++ b/app/Report/ReportPdf.php @@ -21,267 +21,282 @@ use Fisharebest\Webtrees\MediaFile; /** * Class ReportPdf */ -class ReportPdf extends ReportBase { - /** - * PDF compression - Zlib extension is required - * - * @var bool const - */ - const COMPRESSION = true; - /** - * If true reduce the RAM memory usage by caching temporary data on filesystem (slower). - * - * @var bool const - */ - const DISK_CACHE = false; - /** - * true means that the input text is unicode (PDF) - * - * @var bool const - */ - const UNICODE = true; - /** - * false means that the full font is embedded, true means only the used chars - * in TCPDF v5.9 font subsetting is a very slow process, this leads to larger files - * - * @var bool const - */ - const SUBSETTING = false; - /** - * A new object of the PDF class - * - * @var ReportTcpdf - */ - public $pdf; +class ReportPdf extends ReportBase +{ + /** + * PDF compression - Zlib extension is required + * + * @var bool const + */ + const COMPRESSION = true; + /** + * If true reduce the RAM memory usage by caching temporary data on filesystem (slower). + * + * @var bool const + */ + const DISK_CACHE = false; + /** + * true means that the input text is unicode (PDF) + * + * @var bool const + */ + const UNICODE = true; + /** + * false means that the full font is embedded, true means only the used chars + * in TCPDF v5.9 font subsetting is a very slow process, this leads to larger files + * + * @var bool const + */ + const SUBSETTING = false; + /** + * A new object of the PDF class + * + * @var ReportTcpdf + */ + public $pdf; - /** - * PDF Setup - ReportPdf - */ - public function setup() { - parent::setup(); + /** + * PDF Setup - ReportPdf + */ + public function setup() + { + parent::setup(); - // Setup the PDF class with custom size pages because WT supports more page sizes. If WT sends an unknown size name then the default would be A4 - $this->pdf = new ReportTcpdf($this->orientation, parent::UNITS, [ - $this->pagew, - $this->pageh, - ], self::UNICODE, 'UTF-8', self::DISK_CACHE); + // Setup the PDF class with custom size pages because WT supports more page sizes. If WT sends an unknown size name then the default would be A4 + $this->pdf = new ReportTcpdf($this->orientation, parent::UNITS, [ + $this->pagew, + $this->pageh, + ], self::UNICODE, 'UTF-8', self::DISK_CACHE); - // Setup the PDF margins - $this->pdf->SetMargins($this->leftmargin, $this->topmargin, $this->rightmargin); - $this->pdf->setHeaderMargin($this->headermargin); - $this->pdf->setFooterMargin($this->footermargin); - //Set auto page breaks - $this->pdf->SetAutoPageBreak(true, $this->bottommargin); - // Set font subsetting - $this->pdf->setFontSubsetting(self::SUBSETTING); - // Setup PDF compression - $this->pdf->SetCompression(self::COMPRESSION); - // Setup RTL support - $this->pdf->setRTL($this->rtl); - // Set the document information - // Only admin should see the version number - $appversion = WT_WEBTREES; - if (Auth::isAdmin()) { - $appversion .= ' ' . WT_VERSION; - } - $this->pdf->SetCreator($appversion . ' (' . parent::WT_URL . ')'); - // Not implemented yet - ReportBase::setup() - $this->pdf->SetAuthor($this->rauthor); - $this->pdf->SetTitle($this->title); - $this->pdf->SetSubject($this->rsubject); - $this->pdf->SetKeywords($this->rkeywords); + // Setup the PDF margins + $this->pdf->SetMargins($this->leftmargin, $this->topmargin, $this->rightmargin); + $this->pdf->setHeaderMargin($this->headermargin); + $this->pdf->setFooterMargin($this->footermargin); + //Set auto page breaks + $this->pdf->SetAutoPageBreak(true, $this->bottommargin); + // Set font subsetting + $this->pdf->setFontSubsetting(self::SUBSETTING); + // Setup PDF compression + $this->pdf->SetCompression(self::COMPRESSION); + // Setup RTL support + $this->pdf->setRTL($this->rtl); + // Set the document information + // Only admin should see the version number + $appversion = WT_WEBTREES; + if (Auth::isAdmin()) { + $appversion .= ' ' . WT_VERSION; + } + $this->pdf->SetCreator($appversion . ' (' . parent::WT_URL . ')'); + // Not implemented yet - ReportBase::setup() + $this->pdf->SetAuthor($this->rauthor); + $this->pdf->SetTitle($this->title); + $this->pdf->SetSubject($this->rsubject); + $this->pdf->SetKeywords($this->rkeywords); - $this->pdf->setReport($this); + $this->pdf->setReport($this); - if ($this->showGenText) { - // The default style name for Generated by.... is 'genby' - $element = new ReportPdfCell(0, 10, 0, 'C', '', 'genby', 1, '.', '.', 0, 0, '', '', true); - $element->addText($this->generatedby); - $element->setUrl(parent::WT_URL); - $this->pdf->addFooter($element); - } - } + if ($this->showGenText) { + // The default style name for Generated by.... is 'genby' + $element = new ReportPdfCell(0, 10, 0, 'C', '', 'genby', 1, '.', '.', 0, 0, '', '', true); + $element->addText($this->generatedby); + $element->setUrl(parent::WT_URL); + $this->pdf->addFooter($element); + } + } - /** - * Add an element - ReportPdf - * - * @param object|string $element Object or string - * - * @return int - */ - public function addElement($element) { - if ($this->processing == 'B') { - return $this->pdf->addBody($element); - } elseif ($this->processing == 'H') { - return $this->pdf->addHeader($element); - } elseif ($this->processing == 'F') { - return $this->pdf->addFooter($element); - } + /** + * Add an element - ReportPdf + * + * @param object|string $element Object or string + * + * @return int + */ + public function addElement($element) + { + if ($this->processing == 'B') { + return $this->pdf->addBody($element); + } elseif ($this->processing == 'H') { + return $this->pdf->addHeader($element); + } elseif ($this->processing == 'F') { + return $this->pdf->addFooter($element); + } - return 0; - } + return 0; + } - /** - * Run the report. - */ - public function run() { - $this->pdf->body(); - echo $this->pdf->Output('doc.pdf', 'S'); - } + /** + * Run the report. + */ + public function run() + { + $this->pdf->body(); + echo $this->pdf->Output('doc.pdf', 'S'); + } - /** - * Clear the Header - ReportPdf - */ - public function clearHeader() { - $this->pdf->clearHeader(); - } + /** + * Clear the Header - ReportPdf + */ + public function clearHeader() + { + $this->pdf->clearHeader(); + } - /** - * Clear the Page Header - ReportPdf - */ - public function clearPageHeader() { - $this->pdf->clearPageHeader(); - } + /** + * Clear the Page Header - ReportPdf + */ + public function clearPageHeader() + { + $this->pdf->clearPageHeader(); + } - /** - * Create a new Cell object - ReportPdf - * - * @param int $width cell width (expressed in points) - * @param int $height cell height (expressed in points) - * @param mixed $border Border style - * @param string $align Text alignement - * @param string $bgcolor Background color code - * @param string $style The name of the text style - * @param int $ln Indicates where the current position should go after the call - * @param mixed $top Y-position - * @param mixed $left X-position - * @param int $fill Indicates if the cell background must be painted (1) or transparent (0). Default value: 1 - * @param int $stretch Stretch carachter mode - * @param string $bocolor Border color - * @param string $tcolor Text color - * @param bool $reseth - * - * @return ReportPdfCell - */ - public function createCell( - $width, $height, $border, $align, $bgcolor, $style, $ln, $top, $left, $fill, $stretch, $bocolor, $tcolor, $reseth - ) { - return new ReportPdfCell($width, $height, $border, $align, $bgcolor, $style, $ln, $top, $left, $fill, $stretch, $bocolor, $tcolor, $reseth); - } + /** + * Create a new Cell object - ReportPdf + * + * @param int $width cell width (expressed in points) + * @param int $height cell height (expressed in points) + * @param mixed $border Border style + * @param string $align Text alignement + * @param string $bgcolor Background color code + * @param string $style The name of the text style + * @param int $ln Indicates where the current position should go after the call + * @param mixed $top Y-position + * @param mixed $left X-position + * @param int $fill Indicates if the cell background must be painted (1) or transparent (0). Default value: 1 + * @param int $stretch Stretch carachter mode + * @param string $bocolor Border color + * @param string $tcolor Text color + * @param bool $reseth + * + * @return ReportPdfCell + */ + public function createCell( + $width, $height, $border, $align, $bgcolor, $style, $ln, $top, $left, $fill, $stretch, $bocolor, $tcolor, $reseth + ) + { + return new ReportPdfCell($width, $height, $border, $align, $bgcolor, $style, $ln, $top, $left, $fill, $stretch, $bocolor, $tcolor, $reseth); + } - /** - * Create a new TextBox object - ReportPdf - * - * @param float $width Text box width - * @param float $height Text box height - * @param bool $border - * @param string $bgcolor Background color code in HTML - * @param bool $newline - * @param mixed $left - * @param mixed $top - * @param bool $pagecheck - * @param string $style - * @param bool $fill - * @param bool $padding - * @param bool $reseth - * - * @return ReportPdfTextbox - */ - public function createTextBox( - $width, $height, $border, $bgcolor, $newline, $left, $top, $pagecheck, $style, $fill, $padding, $reseth - ) { - return new ReportPdfTextbox($width, $height, $border, $bgcolor, $newline, $left, $top, $pagecheck, $style, $fill, $padding, $reseth); - } + /** + * Create a new TextBox object - ReportPdf + * + * @param float $width Text box width + * @param float $height Text box height + * @param bool $border + * @param string $bgcolor Background color code in HTML + * @param bool $newline + * @param mixed $left + * @param mixed $top + * @param bool $pagecheck + * @param string $style + * @param bool $fill + * @param bool $padding + * @param bool $reseth + * + * @return ReportPdfTextbox + */ + public function createTextBox( + $width, $height, $border, $bgcolor, $newline, $left, $top, $pagecheck, $style, $fill, $padding, $reseth + ) + { + return new ReportPdfTextbox($width, $height, $border, $bgcolor, $newline, $left, $top, $pagecheck, $style, $fill, $padding, $reseth); + } - /** - * Create a new Text object- ReportPdf - * - * @param string $style The name of the text style - * @param string $color HTML color code - * - * @return ReportPdfText - */ - public function createText($style, $color) { - return new ReportPdfText($style, $color); - } + /** + * Create a new Text object- ReportPdf + * + * @param string $style The name of the text style + * @param string $color HTML color code + * + * @return ReportPdfText + */ + public function createText($style, $color) + { + return new ReportPdfText($style, $color); + } - /** - * Create a new Footnote object - ReportPdf - * - * @param string $style Style name - * - * @return ReportPdfFootnote - */ - public function createFootnote($style) { - return new ReportPdfFootnote($style); - } + /** + * Create a new Footnote object - ReportPdf + * + * @param string $style Style name + * + * @return ReportPdfFootnote + */ + public function createFootnote($style) + { + return new ReportPdfFootnote($style); + } - /** - * Create a new Page Header object - ReportPdf - * - * @return ReportPdfPageheader - */ - public function createPageHeader() { - return new ReportPdfPageheader; - } + /** + * Create a new Page Header object - ReportPdf + * + * @return ReportPdfPageheader + */ + public function createPageHeader() + { + return new ReportPdfPageheader; + } - /** - * Create a new image object - ReportPdf - * - * @param string $file Filename - * @param mixed $x - * @param mixed $y - * @param int $w Image width - * @param int $h Image height - * @param string $align L:left, C:center, R:right or empty to use x/y - * @param string $ln T:same line, N:next line - * - * @return ReportPdfImage - */ - public function createImage($file, $x, $y, $w, $h, $align, $ln) { - return new ReportPdfImage($file, $x, $y, $w, $h, $align, $ln); - } + /** + * Create a new image object - ReportPdf + * + * @param string $file Filename + * @param mixed $x + * @param mixed $y + * @param int $w Image width + * @param int $h Image height + * @param string $align L:left, C:center, R:right or empty to use x/y + * @param string $ln T:same line, N:next line + * + * @return ReportPdfImage + */ + public function createImage($file, $x, $y, $w, $h, $align, $ln) + { + return new ReportPdfImage($file, $x, $y, $w, $h, $align, $ln); + } - /** - * Create a new image object from Media Object - ReportPdf - * - * @param MediaFile $media_file - * @param mixed $x - * @param mixed $y - * @param int $w Image width - * @param int $h Image height - * @param string $align L:left, C:center, R:right or empty to use x/y - * @param string $ln T:same line, N:next line - * - * @return ReportPdfImage - */ - public function createImageFromObject(MediaFile $media_file, $x, $y, $w, $h, $align, $ln) { - return new ReportPdfImage($media_file->getServerFilename(), $x, $y, $w, $h, $align, $ln); - } + /** + * Create a new image object from Media Object - ReportPdf + * + * @param MediaFile $media_file + * @param mixed $x + * @param mixed $y + * @param int $w Image width + * @param int $h Image height + * @param string $align L:left, C:center, R:right or empty to use x/y + * @param string $ln T:same line, N:next line + * + * @return ReportPdfImage + */ + public function createImageFromObject(MediaFile $media_file, $x, $y, $w, $h, $align, $ln) + { + return new ReportPdfImage($media_file->getServerFilename(), $x, $y, $w, $h, $align, $ln); + } - /** - * Create a new line object - ReportPdf - * - * @param mixed $x1 - * @param mixed $y1 - * @param mixed $x2 - * @param mixed $y2 - * - * @return ReportPdfLine - */ - public function createLine($x1, $y1, $x2, $y2) { - return new ReportPdfLine($x1, $y1, $x2, $y2); - } + /** + * Create a new line object - ReportPdf + * + * @param mixed $x1 + * @param mixed $y1 + * @param mixed $x2 + * @param mixed $y2 + * + * @return ReportPdfLine + */ + public function createLine($x1, $y1, $x2, $y2) + { + return new ReportPdfLine($x1, $y1, $x2, $y2); + } - /** - * Create an HTML element. - * - * @param $tag - * @param $attrs - * - * @return ReportPdfHtml - */ - public function createHTML($tag, $attrs) { - return new ReportPdfHtml($tag, $attrs); - } + /** + * Create an HTML element. + * + * @param $tag + * @param $attrs + * + * @return ReportPdfHtml + */ + public function createHTML($tag, $attrs) + { + return new ReportPdfHtml($tag, $attrs); + } } diff --git a/app/Report/ReportPdfCell.php b/app/Report/ReportPdfCell.php index 8b7f17d586..d12ae523cb 100644 --- a/app/Report/ReportPdfCell.php +++ b/app/Report/ReportPdfCell.php @@ -20,126 +20,134 @@ use Fisharebest\Webtrees\Functions\FunctionsRtl; /** * Class ReportPdfCell */ -class ReportPdfCell extends ReportBaseCell { - /** - * PDF Cell renderer - * - * @param ReportTcpdf $renderer - */ - public function render($renderer) { +class ReportPdfCell extends ReportBaseCell +{ + /** + * PDF Cell renderer + * + * @param ReportTcpdf $renderer + */ + public function render($renderer) + { - // Set up the text style - if (($renderer->getCurrentStyle()) != ($this->styleName)) { - $renderer->setCurrentStyle($this->styleName); - } - $temptext = str_replace('#PAGENUM#', $renderer->PageNo(), $this->text); - // underline «title» part of Source item - $temptext = str_replace(['«', '»'], ['<u>', '</u>'], $temptext); - $match = []; - // Indicates if the cell background must be painted (1) or transparent (0) - if ($this->fill == 1) { - if (!empty($this->bgcolor)) { - // HTML color to RGB - if (preg_match('/#?(..)(..)(..)/', $this->bgcolor, $match)) { - $r = hexdec($match[1]); - $g = hexdec($match[2]); - $b = hexdec($match[3]); - $renderer->SetFillColor($r, $g, $b); - } - } // If no color set then don't fill - else { - $this->fill = 0; - } - } - // Paint the Border color if set - if (!empty($this->bocolor)) { - // HTML color to RGB - if (preg_match('/#?(..)(..)(..)/', $this->bocolor, $match)) { - $r = hexdec($match[1]); - $g = hexdec($match[2]); - $b = hexdec($match[3]); - $renderer->SetDrawColor($r, $g, $b); - } - } - // Paint the text color or they might use inherited colors by the previous function - if (preg_match('/#?(..)(..)(..)/', $this->tcolor, $match)) { - $r = hexdec($match[1]); - $g = hexdec($match[2]); - $b = hexdec($match[3]); - $renderer->SetTextColor($r, $g, $b); - } else { - $renderer->SetTextColor(0, 0, 0); - } + // Set up the text style + if (($renderer->getCurrentStyle()) != ($this->styleName)) { + $renderer->setCurrentStyle($this->styleName); + } + $temptext = str_replace('#PAGENUM#', $renderer->PageNo(), $this->text); + // underline «title» part of Source item + $temptext = str_replace([ + '«', + '»', + ], [ + '<u>', + '</u>', + ], $temptext); + $match = []; + // Indicates if the cell background must be painted (1) or transparent (0) + if ($this->fill == 1) { + if (!empty($this->bgcolor)) { + // HTML color to RGB + if (preg_match('/#?(..)(..)(..)/', $this->bgcolor, $match)) { + $r = hexdec($match[1]); + $g = hexdec($match[2]); + $b = hexdec($match[3]); + $renderer->SetFillColor($r, $g, $b); + } + } // If no color set then don't fill + else { + $this->fill = 0; + } + } + // Paint the Border color if set + if (!empty($this->bocolor)) { + // HTML color to RGB + if (preg_match('/#?(..)(..)(..)/', $this->bocolor, $match)) { + $r = hexdec($match[1]); + $g = hexdec($match[2]); + $b = hexdec($match[3]); + $renderer->SetDrawColor($r, $g, $b); + } + } + // Paint the text color or they might use inherited colors by the previous function + if (preg_match('/#?(..)(..)(..)/', $this->tcolor, $match)) { + $r = hexdec($match[1]); + $g = hexdec($match[2]); + $b = hexdec($match[3]); + $renderer->SetTextColor($r, $g, $b); + } else { + $renderer->SetTextColor(0, 0, 0); + } - // If current position (left) - if ($this->left == '.') { - $cX = $renderer->GetX(); - } // For static position add margin (also updates X) - else { - $cX = $renderer->addMarginX($this->left); - } + // If current position (left) + if ($this->left == '.') { + $cX = $renderer->GetX(); + } // For static position add margin (also updates X) + else { + $cX = $renderer->addMarginX($this->left); + } - // Check the width if set to page wide OR set by xml to larger then page wide - if ($this->width == 0 || $this->width > $renderer->getRemainingWidthPDF()) { - $this->width = $renderer->getRemainingWidthPDF(); - } - // For current position - if ($this->top == '.') { - $this->top = $renderer->GetY(); - } else { - $renderer->SetY($this->top); - } + // Check the width if set to page wide OR set by xml to larger then page wide + if ($this->width == 0 || $this->width > $renderer->getRemainingWidthPDF()) { + $this->width = $renderer->getRemainingWidthPDF(); + } + // For current position + if ($this->top == '.') { + $this->top = $renderer->GetY(); + } else { + $renderer->SetY($this->top); + } - // Check the last cell height and adjust the current cell height if needed - if ($renderer->lastCellHeight > $this->height) { - $this->height = $renderer->lastCellHeight; - } - // Check for pagebreak - if (!empty($temptext)) { - $cHT = $renderer->getNumLines($temptext, $this->width); - $cHT = $cHT * $renderer->getCellHeightRatio() * $renderer->getCurrentStyleHeight(); - $cM = $renderer->getMargins(); - // Add padding - if (is_array($cM['cell'])) { - $cHT += ($cM['padding_bottom'] + $cM['padding_top']); - } else { - $cHT += ($cM['cell'] * 2); - } - // Add a new page if needed - if ($renderer->checkPageBreakPDF($cHT)) { - $this->top = $renderer->GetY(); - } - $temptext = FunctionsRtl::spanLtrRtl($temptext, 'BOTH'); - } - // HTML ready - last value is true - $renderer->MultiCell( - $this->width, - $this->height, - $temptext, - $this->border, - $this->align, - $this->fill, - $this->newline, - $cX, - $this->top, - $this->reseth, - $this->stretch, - true - ); - // Reset the last cell height for the next line - if ($this->newline >= 1) { - $renderer->lastCellHeight = 0; - } // OR save the last height if heigher then before - elseif ($renderer->lastCellHeight < $renderer->getLastH()) { - $renderer->lastCellHeight = $renderer->getLastH(); - } + // Check the last cell height and adjust the current cell height if needed + if ($renderer->lastCellHeight > $this->height) { + $this->height = $renderer->lastCellHeight; + } + // Check for pagebreak + if (!empty($temptext)) { + $cHT = $renderer->getNumLines($temptext, $this->width); + $cHT = $cHT * $renderer->getCellHeightRatio() * $renderer->getCurrentStyleHeight(); + $cM = $renderer->getMargins(); + // Add padding + if (is_array($cM['cell'])) { + $cHT += ($cM['padding_bottom'] + $cM['padding_top']); + } else { + $cHT += ($cM['cell'] * 2); + } + // Add a new page if needed + if ($renderer->checkPageBreakPDF($cHT)) { + $this->top = $renderer->GetY(); + } + $temptext = FunctionsRtl::spanLtrRtl($temptext, 'BOTH'); + } + // HTML ready - last value is true + $renderer->MultiCell( + $this->width, + $this->height, + $temptext, + $this->border, + $this->align, + $this->fill, + $this->newline, + $cX, + $this->top, + $this->reseth, + $this->stretch, + true + ); + // Reset the last cell height for the next line + if ($this->newline >= 1) { + $renderer->lastCellHeight = 0; + } // OR save the last height if heigher then before + elseif ($renderer->lastCellHeight < $renderer->getLastH()) { + $renderer->lastCellHeight = $renderer->getLastH(); + } - // Set up the url link if exists ontop of the cell - if (!empty($this->url)) { - $renderer->Link($cX, $this->top, $this->width, $this->height, $this->url); - } - // Reset the border and the text color to black or they will be inherited - $renderer->SetDrawColor(0, 0, 0); - $renderer->SetTextColor(0, 0, 0); - } + // Set up the url link if exists ontop of the cell + if (!empty($this->url)) { + $renderer->Link($cX, $this->top, $this->width, $this->height, $this->url); + } + // Reset the border and the text color to black or they will be inherited + $renderer->SetDrawColor(0, 0, 0); + $renderer->SetTextColor(0, 0, 0); + } } diff --git a/app/Report/ReportPdfFootnote.php b/app/Report/ReportPdfFootnote.php index 3a1a657374..304204f40d 100644 --- a/app/Report/ReportPdfFootnote.php +++ b/app/Report/ReportPdfFootnote.php @@ -18,141 +18,160 @@ namespace Fisharebest\Webtrees\Report; /** * Class ReportPdfFootnote */ -class ReportPdfFootnote extends ReportBaseFootnote { - /** - * PDF Footnotes number renderer - * - * @param ReportTcpdf $renderer - */ - public function render($renderer) { - $renderer->setCurrentStyle('footnotenum'); - $renderer->Write($renderer->getCurrentStyleHeight(), $this->numText, $this->addlink); //source link numbers after name - } +class ReportPdfFootnote extends ReportBaseFootnote +{ + /** + * PDF Footnotes number renderer + * + * @param ReportTcpdf $renderer + */ + public function render($renderer) + { + $renderer->setCurrentStyle('footnotenum'); + $renderer->Write($renderer->getCurrentStyleHeight(), $this->numText, $this->addlink); //source link numbers after name + } - /** - * Write the Footnote text - * Uses style name "footnote" by default - * - * @param ReportTcpdf $pdf - */ - public function renderFootnote($pdf) { - if ($pdf->getCurrentStyle() != $this->styleName) { - $pdf->setCurrentStyle($this->styleName); - } - $temptext = str_replace('#PAGENUM#', $pdf->PageNo(), $this->text); - // Set the link to this y/page position - $pdf->SetLink($this->addlink, -1, -1); - // Print first the source number - // working - if ($pdf->getRTL()) { - $pdf->writeHTML('<span> .' . $this->num . '</span>', false, false, false, false, ''); - } else { - $temptext = '<span>' . $this->num . '. </span>' . $temptext; - } - // underline «title» part of Source item - $temptext = str_replace(['«', '»'], ['<u>', '</u>'], $temptext); - $pdf->writeHTML($temptext, true, false, true, false, ''); - } + /** + * Write the Footnote text + * Uses style name "footnote" by default + * + * @param ReportTcpdf $pdf + */ + public function renderFootnote($pdf) + { + if ($pdf->getCurrentStyle() != $this->styleName) { + $pdf->setCurrentStyle($this->styleName); + } + $temptext = str_replace('#PAGENUM#', $pdf->PageNo(), $this->text); + // Set the link to this y/page position + $pdf->SetLink($this->addlink, -1, -1); + // Print first the source number + // working + if ($pdf->getRTL()) { + $pdf->writeHTML('<span> .' . $this->num . '</span>', false, false, false, false, ''); + } else { + $temptext = '<span>' . $this->num . '. </span>' . $temptext; + } + // underline «title» part of Source item + $temptext = str_replace([ + '«', + '»', + ], [ + '<u>', + '</u>', + ], $temptext); + $pdf->writeHTML($temptext, true, false, true, false, ''); + } - /** - * Returns the height in points of the Footnote element - * - * @param ReportTcpdf $renderer - * - * @return float $h - */ - public function getFootnoteHeight($renderer) { - return 0; - } + /** + * Returns the height in points of the Footnote element + * + * @param ReportTcpdf $renderer + * + * @return float $h + */ + public function getFootnoteHeight($renderer) + { + return 0; + } - /** - * Splits the text into lines to fit into a giving cell - * and returns the last lines width - * - * @param ReportTcpdf $pdf - * - * @return array - */ - public function getWidth($pdf) { - // Setup the style name, a font must be selected to calculate the width - $pdf->setCurrentStyle('footnotenum'); + /** + * Splits the text into lines to fit into a giving cell + * and returns the last lines width + * + * @param ReportTcpdf $pdf + * + * @return array + */ + public function getWidth($pdf) + { + // Setup the style name, a font must be selected to calculate the width + $pdf->setCurrentStyle('footnotenum'); - // Check for the largest font size in the box - $fsize = $pdf->getCurrentStyleHeight(); - if ($fsize > $pdf->largestFontHeight) { - $pdf->largestFontHeight = $fsize; - } + // Check for the largest font size in the box + $fsize = $pdf->getCurrentStyleHeight(); + if ($fsize > $pdf->largestFontHeight) { + $pdf->largestFontHeight = $fsize; + } - // Returns the Object if already numbered else false - if (empty($this->num)) { - $pdf->checkFootnote($this); - } + // Returns the Object if already numbered else false + if (empty($this->num)) { + $pdf->checkFootnote($this); + } - // Get the line width - $lw = ceil($pdf->GetStringWidth($this->numText)); - // Line Feed counter - Number of lines in the text - $lfct = substr_count($this->numText, "\n") + 1; - // If there is still remaining wrap width... - if ($this->wrapWidthRemaining > 0) { - // Check with line counter too! - // but floor the $wrapWidthRemaining first to keep it bugfree! - $wrapWidthRemaining = (int) ($this->wrapWidthRemaining); - if ($lw >= $wrapWidthRemaining || $lfct > 1) { - $newtext = ''; - $lines = explode("\n", $this->numText); - // Go throught the text line by line - foreach ($lines as $line) { - // Line width in points - $lw = ceil($pdf->GetStringWidth($line)); - // If the line has to be wraped - if ($lw >= $wrapWidthRemaining) { - $words = explode(' ', $line); - $addspace = count($words); - $lw = 0; - foreach ($words as $word) { - $addspace--; - $lw += ceil($pdf->GetStringWidth($word . ' ')); - if ($lw < $wrapWidthRemaining) { - $newtext .= $word; - if ($addspace != 0) { - $newtext .= ' '; - } - } else { - $lw = $pdf->GetStringWidth($word . ' '); - $newtext .= "\n$word"; - if ($addspace != 0) { - $newtext .= ' '; - } - // Reset the wrap width to the cell width - $wrapWidthRemaining = $this->wrapWidthCell; - } - } - } else { - $newtext .= $line; - } - // Check the Line Feed counter - if ($lfct > 1) { - // Add a new line feed as long as it’s not the last line - $newtext .= "\n"; - // Reset the line width - $lw = 0; - // Reset the wrap width to the cell width - $wrapWidthRemaining = $this->wrapWidthCell; - } - $lfct--; - } - $this->numText = $newtext; - $lfct = substr_count($this->numText, "\n"); + // Get the line width + $lw = ceil($pdf->GetStringWidth($this->numText)); + // Line Feed counter - Number of lines in the text + $lfct = substr_count($this->numText, "\n") + 1; + // If there is still remaining wrap width... + if ($this->wrapWidthRemaining > 0) { + // Check with line counter too! + // but floor the $wrapWidthRemaining first to keep it bugfree! + $wrapWidthRemaining = (int)($this->wrapWidthRemaining); + if ($lw >= $wrapWidthRemaining || $lfct > 1) { + $newtext = ''; + $lines = explode("\n", $this->numText); + // Go throught the text line by line + foreach ($lines as $line) { + // Line width in points + $lw = ceil($pdf->GetStringWidth($line)); + // If the line has to be wraped + if ($lw >= $wrapWidthRemaining) { + $words = explode(' ', $line); + $addspace = count($words); + $lw = 0; + foreach ($words as $word) { + $addspace--; + $lw += ceil($pdf->GetStringWidth($word . ' ')); + if ($lw < $wrapWidthRemaining) { + $newtext .= $word; + if ($addspace != 0) { + $newtext .= ' '; + } + } else { + $lw = $pdf->GetStringWidth($word . ' '); + $newtext .= "\n$word"; + if ($addspace != 0) { + $newtext .= ' '; + } + // Reset the wrap width to the cell width + $wrapWidthRemaining = $this->wrapWidthCell; + } + } + } else { + $newtext .= $line; + } + // Check the Line Feed counter + if ($lfct > 1) { + // Add a new line feed as long as it’s not the last line + $newtext .= "\n"; + // Reset the line width + $lw = 0; + // Reset the wrap width to the cell width + $wrapWidthRemaining = $this->wrapWidthCell; + } + $lfct--; + } + $this->numText = $newtext; + $lfct = substr_count($this->numText, "\n"); - return [$lw, 1, $lfct]; - } - } - $l = 0; - $lfct = substr_count($this->numText, "\n"); - if ($lfct > 0) { - $l = 2; - } + return [ + $lw, + 1, + $lfct, + ]; + } + } + $l = 0; + $lfct = substr_count($this->numText, "\n"); + if ($lfct > 0) { + $l = 2; + } - return [$lw, $l, $lfct]; - } + return [ + $lw, + $l, + $lfct, + ]; + } } diff --git a/app/Report/ReportPdfHtml.php b/app/Report/ReportPdfHtml.php index 4417e75d6f..5519e3a785 100644 --- a/app/Report/ReportPdfHtml.php +++ b/app/Report/ReportPdfHtml.php @@ -18,40 +18,43 @@ namespace Fisharebest\Webtrees\Report; /** * Class ReportPdfHtml */ -class ReportPdfHtml extends ReportBaseHtml { - /** - * Render the output. - * - * @param $renderer - * @param bool $sub - * - * @return int|string - */ - public function render($renderer, $sub = false) { - if (!empty($this->attrs['style'])) { - $renderer->setCurrentStyle($this->attrs['style']); - } - if (!empty($this->attrs['width'])) { - $this->attrs['width'] *= 3.9; - } +class ReportPdfHtml extends ReportBaseHtml +{ + /** + * Render the output. + * + * @param $renderer + * @param bool $sub + * + * @return int|string + */ + public function render($renderer, $sub = false) + { + if (!empty($this->attrs['style'])) { + $renderer->setCurrentStyle($this->attrs['style']); + } + if (!empty($this->attrs['width'])) { + $this->attrs['width'] *= 3.9; + } - $this->text = $this->getStart() . $this->text; - foreach ($this->elements as $element) { - if (is_string($element) && $element == 'footnotetexts') { - $renderer->Footnotes(); - } elseif (is_string($element) && $element == 'addpage') { - $renderer->newPage(); - } elseif ($element instanceof ReportBaseHtml) { - $element->render($renderer, true); - } else { - $element->render($renderer); - } - } - $this->text .= $this->getEnd(); - if ($sub) { - return $this->text; - } - $renderer->writeHTML($this->text); //prints 2 empty cells in the Expanded Relatives report - return 0; - } + $this->text = $this->getStart() . $this->text; + foreach ($this->elements as $element) { + if (is_string($element) && $element == 'footnotetexts') { + $renderer->Footnotes(); + } elseif (is_string($element) && $element == 'addpage') { + $renderer->newPage(); + } elseif ($element instanceof ReportBaseHtml) { + $element->render($renderer, true); + } else { + $element->render($renderer); + } + } + $this->text .= $this->getEnd(); + if ($sub) { + return $this->text; + } + $renderer->writeHTML($this->text); //prints 2 empty cells in the Expanded Relatives report + + return 0; + } } diff --git a/app/Report/ReportPdfImage.php b/app/Report/ReportPdfImage.php index 0eedf218b4..c45db986db 100644 --- a/app/Report/ReportPdfImage.php +++ b/app/Report/ReportPdfImage.php @@ -18,100 +18,104 @@ namespace Fisharebest\Webtrees\Report; /** * Class ReportPdfImage */ -class ReportPdfImage extends ReportBaseImage { - /** - * PDF image renderer - * - * @param ReportTcpdf $renderer - */ - public function render($renderer) { - global $lastpicbottom, $lastpicpage, $lastpicleft, $lastpicright; +class ReportPdfImage extends ReportBaseImage +{ + /** + * PDF image renderer + * + * @param ReportTcpdf $renderer + */ + public function render($renderer) + { + global $lastpicbottom, $lastpicpage, $lastpicleft, $lastpicright; - // Check for a pagebreak first - if ($renderer->checkPageBreakPDF($this->height + 5)) { - $this->y = $renderer->GetY(); - } + // Check for a pagebreak first + if ($renderer->checkPageBreakPDF($this->height + 5)) { + $this->y = $renderer->GetY(); + } - $curx = $renderer->GetX(); - // If current position (left)set "." - if ($this->x == '.') { - $this->x = $renderer->GetX(); - } // For static position add margin - else { - $this->x = $renderer->addMarginX($this->x); - $renderer->SetX($curx); - } - if ($this->y == '.') { - //-- first check for a collision with the last picture - if (isset($lastpicbottom)) { - if (($renderer->PageNo() == $lastpicpage) && ($lastpicbottom >= $renderer->GetY()) && ($this->x >= $lastpicleft) && ($this->x <= $lastpicright) - ) { - $renderer->SetY($lastpicbottom + 5); - } - } - $this->y = $renderer->GetY(); - } else { - $renderer->SetY($this->y); - } - if ($renderer->getRTL()) { - $renderer->Image( - $this->file, - $renderer->getPageWidth() - $this->x, - $this->y, - $this->width, - $this->height, - '', - '', - $this->line, - false, - 72, - $this->align - ); - } else { - $renderer->Image( - $this->file, - $this->x, - $this->y, - $this->width, - $this->height, - '', - '', - $this->line, - false, - 72, - $this->align - ); - } - $lastpicpage = $renderer->PageNo(); - $renderer->lastpicpage = $renderer->getPage(); - $lastpicleft = $this->x; - $lastpicright = $this->x + $this->width; - $lastpicbottom = $this->y + $this->height; - // Setup for the next line - if ($this->line == 'N') { - $renderer->SetY($lastpicbottom); - } - } + $curx = $renderer->GetX(); + // If current position (left)set "." + if ($this->x == '.') { + $this->x = $renderer->GetX(); + } // For static position add margin + else { + $this->x = $renderer->addMarginX($this->x); + $renderer->SetX($curx); + } + if ($this->y == '.') { + //-- first check for a collision with the last picture + if (isset($lastpicbottom)) { + if (($renderer->PageNo() == $lastpicpage) && ($lastpicbottom >= $renderer->GetY()) && ($this->x >= $lastpicleft) && ($this->x <= $lastpicright) + ) { + $renderer->SetY($lastpicbottom + 5); + } + } + $this->y = $renderer->GetY(); + } else { + $renderer->SetY($this->y); + } + if ($renderer->getRTL()) { + $renderer->Image( + $this->file, + $renderer->getPageWidth() - $this->x, + $this->y, + $this->width, + $this->height, + '', + '', + $this->line, + false, + 72, + $this->align + ); + } else { + $renderer->Image( + $this->file, + $this->x, + $this->y, + $this->width, + $this->height, + '', + '', + $this->line, + false, + 72, + $this->align + ); + } + $lastpicpage = $renderer->PageNo(); + $renderer->lastpicpage = $renderer->getPage(); + $lastpicleft = $this->x; + $lastpicright = $this->x + $this->width; + $lastpicbottom = $this->y + $this->height; + // Setup for the next line + if ($this->line == 'N') { + $renderer->SetY($lastpicbottom); + } + } - /** - * Get the image height - * - * @param ReportTcpdf $pdf - * - * @return float - */ - public function getHeight($pdf) { - return $this->height; - } + /** + * Get the image height + * + * @param ReportTcpdf $pdf + * + * @return float + */ + public function getHeight($pdf) + { + return $this->height; + } - /** - * Get the image width. - * - * @param $pdf - * - * @return float - */ - public function getWidth($pdf) { - return $this->width; - } + /** + * Get the image width. + * + * @param $pdf + * + * @return float + */ + public function getWidth($pdf) + { + return $this->width; + } } diff --git a/app/Report/ReportPdfLine.php b/app/Report/ReportPdfLine.php index effe9edb1d..11927ea04c 100644 --- a/app/Report/ReportPdfLine.php +++ b/app/Report/ReportPdfLine.php @@ -18,29 +18,31 @@ namespace Fisharebest\Webtrees\Report; /** * Class ReportPdfLine */ -class ReportPdfLine extends ReportBaseLine { - /** - * PDF line renderer - * - * @param ReportTcpdf $renderer - */ - public function render($renderer) { - if ($this->x1 == '.') { - $this->x1 = $renderer->GetX(); - } - if ($this->y1 == '.') { - $this->y1 = $renderer->GetY(); - } - if ($this->x2 == '.') { - $this->x2 = $renderer->getMaxLineWidth(); - } - if ($this->y2 == '.') { - $this->y2 = $renderer->GetY(); - } - if ($renderer->getRTL()) { - $renderer->Line($renderer->getPageWidth() - $this->x1, $this->y1, $renderer->getPageWidth() - $this->x2, $this->y2); - } else { - $renderer->Line($this->x1, $this->y1, $this->x2, $this->y2); - } - } +class ReportPdfLine extends ReportBaseLine +{ + /** + * PDF line renderer + * + * @param ReportTcpdf $renderer + */ + public function render($renderer) + { + if ($this->x1 == '.') { + $this->x1 = $renderer->GetX(); + } + if ($this->y1 == '.') { + $this->y1 = $renderer->GetY(); + } + if ($this->x2 == '.') { + $this->x2 = $renderer->getMaxLineWidth(); + } + if ($this->y2 == '.') { + $this->y2 = $renderer->GetY(); + } + if ($renderer->getRTL()) { + $renderer->Line($renderer->getPageWidth() - $this->x1, $this->y1, $renderer->getPageWidth() - $this->x2, $this->y2); + } else { + $renderer->Line($this->x1, $this->y1, $this->x2, $this->y2); + } + } } diff --git a/app/Report/ReportPdfPageheader.php b/app/Report/ReportPdfPageheader.php index c0194baa43..61b5520603 100644 --- a/app/Report/ReportPdfPageheader.php +++ b/app/Report/ReportPdfPageheader.php @@ -18,16 +18,18 @@ namespace Fisharebest\Webtrees\Report; /** * class ReportPdfPageheader */ -class ReportPdfPageheader extends ReportBasePageheader { - /** - * PageHeader element renderer - * - * @param ReportTcpdf $renderer - */ - public function render($renderer) { - $renderer->clearPageHeader(); - foreach ($this->elements as $element) { - $renderer->addPageHeader($element); - } - } +class ReportPdfPageheader extends ReportBasePageheader +{ + /** + * PageHeader element renderer + * + * @param ReportTcpdf $renderer + */ + public function render($renderer) + { + $renderer->clearPageHeader(); + foreach ($this->elements as $element) { + $renderer->addPageHeader($element); + } + } } diff --git a/app/Report/ReportPdfText.php b/app/Report/ReportPdfText.php index d320eba1ac..a5b569c4ea 100644 --- a/app/Report/ReportPdfText.php +++ b/app/Report/ReportPdfText.php @@ -20,145 +20,173 @@ use Fisharebest\Webtrees\Functions\FunctionsRtl; /** * Class ReportPdfText */ -class ReportPdfText extends ReportBaseText { - /** - * PDF Text renderer - * - * @param ReportTcpdf $renderer - */ - public function render($renderer) { - // Set up the style - if ($renderer->getCurrentStyle() != $this->styleName) { - $renderer->setCurrentStyle($this->styleName); - } - $temptext = str_replace('#PAGENUM#', $renderer->PageNo(), $this->text); - // underline «title» part of Source item - $temptext = str_replace(['«', '»'], ['<u>', '</u>'], $temptext); +class ReportPdfText extends ReportBaseText +{ + /** + * PDF Text renderer + * + * @param ReportTcpdf $renderer + */ + public function render($renderer) + { + // Set up the style + if ($renderer->getCurrentStyle() != $this->styleName) { + $renderer->setCurrentStyle($this->styleName); + } + $temptext = str_replace('#PAGENUM#', $renderer->PageNo(), $this->text); + // underline «title» part of Source item + $temptext = str_replace([ + '«', + '»', + ], [ + '<u>', + '</u>', + ], $temptext); - // Paint the text color or they might use inherited colors by the previous function - $match = []; - if (preg_match('/#?(..)(..)(..)/', $this->color, $match)) { - $r = hexdec($match[1]); - $g = hexdec($match[2]); - $b = hexdec($match[3]); - $renderer->SetTextColor($r, $g, $b); - } else { - $renderer->SetTextColor(0, 0, 0); - } - $temptext = FunctionsRtl::spanLtrRtl($temptext, 'BOTH'); - $temptext = str_replace( - ['<br><span dir="rtl" >', '<br><span dir="ltr" >', '> ', ' <'], - ['<span dir="rtl" ><br>', '<span dir="ltr" ><br>', '> ', ' <'], - $temptext - ); - $renderer->writeHTML( - $temptext, - false, - false, - true, - false, - '' - ); //change height - line break etc. - the form is mirror on rtl pages - // Reset the text color to black or it will be inherited - $renderer->SetTextColor(0, 0, 0); - } + // Paint the text color or they might use inherited colors by the previous function + $match = []; + if (preg_match('/#?(..)(..)(..)/', $this->color, $match)) { + $r = hexdec($match[1]); + $g = hexdec($match[2]); + $b = hexdec($match[3]); + $renderer->SetTextColor($r, $g, $b); + } else { + $renderer->SetTextColor(0, 0, 0); + } + $temptext = FunctionsRtl::spanLtrRtl($temptext, 'BOTH'); + $temptext = str_replace( + [ + '<br><span dir="rtl" >', + '<br><span dir="ltr" >', + '> ', + ' <', + ], + [ + '<span dir="rtl" ><br>', + '<span dir="ltr" ><br>', + '> ', + ' <', + ], + $temptext + ); + $renderer->writeHTML( + $temptext, + false, + false, + true, + false, + '' + ); //change height - line break etc. - the form is mirror on rtl pages + // Reset the text color to black or it will be inherited + $renderer->SetTextColor(0, 0, 0); + } - /** - * Returns the height in points of the text element - * - * The height is already calculated in getWidth() - * - * @param ReportTcpdf $pdf - * - * @return float 0 - */ - public function getHeight($pdf) { - return 0; - } + /** + * Returns the height in points of the text element + * + * The height is already calculated in getWidth() + * + * @param ReportTcpdf $pdf + * + * @return float 0 + */ + public function getHeight($pdf) + { + return 0; + } - /** - * Splits the text into lines if necessary to fit into a giving cell - * - * @param ReportTcpdf $pdf - * - * @return array - */ - public function getWidth($pdf) { - // Setup the style name, a font must be selected to calculate the width - if ($pdf->getCurrentStyle() != $this->styleName) { - $pdf->setCurrentStyle($this->styleName); - } - // Check for the largest font size in the box - $fsize = $pdf->getCurrentStyleHeight(); - if ($fsize > $pdf->largestFontHeight) { - $pdf->largestFontHeight = $fsize; - } + /** + * Splits the text into lines if necessary to fit into a giving cell + * + * @param ReportTcpdf $pdf + * + * @return array + */ + public function getWidth($pdf) + { + // Setup the style name, a font must be selected to calculate the width + if ($pdf->getCurrentStyle() != $this->styleName) { + $pdf->setCurrentStyle($this->styleName); + } + // Check for the largest font size in the box + $fsize = $pdf->getCurrentStyleHeight(); + if ($fsize > $pdf->largestFontHeight) { + $pdf->largestFontHeight = $fsize; + } - // Get the line width - $lw = $pdf->GetStringWidth($this->text); - // Line Feed counter - Number of lines in the text - $lfct = substr_count($this->text, "\n") + 1; - // If there is still remaining wrap width... - if ($this->wrapWidthRemaining > 0) { - // Check with line counter too! - // but floor the $wrapWidthRemaining first to keep it bugfree! - $wrapWidthRemaining = (int) ($this->wrapWidthRemaining); - if ($lw >= $wrapWidthRemaining || $lfct > 1) { - $newtext = ''; - $lines = explode("\n", $this->text); - // Go throught the text line by line - foreach ($lines as $line) { - // Line width in points + a little margin - $lw = $pdf->GetStringWidth($line); - // If the line has to be wraped - if ($lw >= $wrapWidthRemaining) { - $words = explode(' ', $line); - $addspace = count($words); - $lw = 0; - foreach ($words as $word) { - $addspace--; - $lw += $pdf->GetStringWidth($word . ' '); - if ($lw <= $wrapWidthRemaining) { - $newtext .= $word; - if ($addspace != 0) { - $newtext .= ' '; - } - } else { - $lw = $pdf->GetStringWidth($word . ' '); - $newtext .= "\n$word"; - if ($addspace != 0) { - $newtext .= ' '; - } - // Reset the wrap width to the cell width - $wrapWidthRemaining = $this->wrapWidthCell; - } - } - } else { - $newtext .= $line; - } - // Check the Line Feed counter - if ($lfct > 1) { - // Add a new line as long as it’s not the last line - $newtext .= "\n"; - // Reset the line width - $lw = 0; - // Reset the wrap width to the cell width - $wrapWidthRemaining = $this->wrapWidthCell; - } - $lfct--; - } - $this->text = $newtext; - $lfct = substr_count($this->text, "\n"); + // Get the line width + $lw = $pdf->GetStringWidth($this->text); + // Line Feed counter - Number of lines in the text + $lfct = substr_count($this->text, "\n") + 1; + // If there is still remaining wrap width... + if ($this->wrapWidthRemaining > 0) { + // Check with line counter too! + // but floor the $wrapWidthRemaining first to keep it bugfree! + $wrapWidthRemaining = (int)($this->wrapWidthRemaining); + if ($lw >= $wrapWidthRemaining || $lfct > 1) { + $newtext = ''; + $lines = explode("\n", $this->text); + // Go throught the text line by line + foreach ($lines as $line) { + // Line width in points + a little margin + $lw = $pdf->GetStringWidth($line); + // If the line has to be wraped + if ($lw >= $wrapWidthRemaining) { + $words = explode(' ', $line); + $addspace = count($words); + $lw = 0; + foreach ($words as $word) { + $addspace--; + $lw += $pdf->GetStringWidth($word . ' '); + if ($lw <= $wrapWidthRemaining) { + $newtext .= $word; + if ($addspace != 0) { + $newtext .= ' '; + } + } else { + $lw = $pdf->GetStringWidth($word . ' '); + $newtext .= "\n$word"; + if ($addspace != 0) { + $newtext .= ' '; + } + // Reset the wrap width to the cell width + $wrapWidthRemaining = $this->wrapWidthCell; + } + } + } else { + $newtext .= $line; + } + // Check the Line Feed counter + if ($lfct > 1) { + // Add a new line as long as it’s not the last line + $newtext .= "\n"; + // Reset the line width + $lw = 0; + // Reset the wrap width to the cell width + $wrapWidthRemaining = $this->wrapWidthCell; + } + $lfct--; + } + $this->text = $newtext; + $lfct = substr_count($this->text, "\n"); - return [$lw, 1, $lfct]; - } - } - $l = 0; - $lfct = substr_count($this->text, "\n"); - if ($lfct > 0) { - $l = 2; - } + return [ + $lw, + 1, + $lfct, + ]; + } + } + $l = 0; + $lfct = substr_count($this->text, "\n"); + if ($lfct > 0) { + $l = 2; + } - return [$lw, $l, $lfct]; - } + return [ + $lw, + $l, + $lfct, + ]; + } } diff --git a/app/Report/ReportPdfTextbox.php b/app/Report/ReportPdfTextbox.php index 1d7fd00641..c14184bcfe 100644 --- a/app/Report/ReportPdfTextbox.php +++ b/app/Report/ReportPdfTextbox.php @@ -18,310 +18,312 @@ namespace Fisharebest\Webtrees\Report; /** * Class ReportPdfTextbox */ -class ReportPdfTextbox extends ReportBaseTextbox { - /** - * PDF Text Box renderer - * - * @param ReportTcpdf $renderer - * - * @return bool|int - */ - public function render($renderer) { - $newelements = []; - $lastelement = ''; - $footnote_element = []; - // Element counter - $cE = count($this->elements); - //-- collapse duplicate elements - for ($i = 0; $i < $cE; $i++) { - $element = $this->elements[$i]; - if (is_object($element)) { - if ($element instanceof ReportBaseText) { - if (!empty($footnote_element)) { - ksort($footnote_element); - foreach ($footnote_element as $links) { - $newelements[] = $links; - } - $footnote_element = []; - } - if (empty($lastelement)) { - $lastelement = $element; - } else { - // Checking if the Text has the same style - if ($element->getStyleName() == $lastelement->getStyleName()) { - $lastelement->addText(str_replace("\n", '<br>', $element->getValue())); - } elseif (!empty($lastelement)) { - $newelements[] = $lastelement; - $lastelement = $element; - } - } - } // Collect the Footnote links - elseif ($element instanceof ReportBaseFootnote) { - // Check if the Footnote has been set with it’s link number - $renderer->checkFootnote($element); - // Save first the last element if any - if (!empty($lastelement)) { - $newelements[] = $lastelement; - $lastelement = []; - } - // Save the Footnote with it’s link number as key for sorting later - $footnote_element[$element->num] = $element; - } //-- do not keep empty footnotes - elseif (!($element instanceof ReportBaseFootnote) || trim($element->getValue()) != '') { - if (!empty($footnote_element)) { - ksort($footnote_element); - foreach ($footnote_element as $links) { - $newelements[] = $links; - } - $footnote_element = []; - } - if (!empty($lastelement)) { - $newelements[] = $lastelement; - $lastelement = []; - } - $newelements[] = $element; - } - } else { - if (!empty($lastelement)) { - $newelements[] = $lastelement; - $lastelement = []; - } - if (!empty($footnote_element)) { - ksort($footnote_element); - foreach ($footnote_element as $links) { - $newelements[] = $links; - } - $footnote_element = []; - } - $newelements[] = $element; - } - } - if (!empty($lastelement)) { - $newelements[] = $lastelement; - } - if (!empty($footnote_element)) { - ksort($footnote_element); - foreach ($footnote_element as $links) { - $newelements[] = $links; - } - } - $this->elements = $newelements; - unset($footnote_element, $lastelement, $links, $newelements); +class ReportPdfTextbox extends ReportBaseTextbox +{ + /** + * PDF Text Box renderer + * + * @param ReportTcpdf $renderer + * + * @return bool|int + */ + public function render($renderer) + { + $newelements = []; + $lastelement = ''; + $footnote_element = []; + // Element counter + $cE = count($this->elements); + //-- collapse duplicate elements + for ($i = 0; $i < $cE; $i++) { + $element = $this->elements[$i]; + if (is_object($element)) { + if ($element instanceof ReportBaseText) { + if (!empty($footnote_element)) { + ksort($footnote_element); + foreach ($footnote_element as $links) { + $newelements[] = $links; + } + $footnote_element = []; + } + if (empty($lastelement)) { + $lastelement = $element; + } else { + // Checking if the Text has the same style + if ($element->getStyleName() == $lastelement->getStyleName()) { + $lastelement->addText(str_replace("\n", '<br>', $element->getValue())); + } elseif (!empty($lastelement)) { + $newelements[] = $lastelement; + $lastelement = $element; + } + } + } // Collect the Footnote links + elseif ($element instanceof ReportBaseFootnote) { + // Check if the Footnote has been set with it’s link number + $renderer->checkFootnote($element); + // Save first the last element if any + if (!empty($lastelement)) { + $newelements[] = $lastelement; + $lastelement = []; + } + // Save the Footnote with it’s link number as key for sorting later + $footnote_element[$element->num] = $element; + } //-- do not keep empty footnotes + elseif (!($element instanceof ReportBaseFootnote) || trim($element->getValue()) != '') { + if (!empty($footnote_element)) { + ksort($footnote_element); + foreach ($footnote_element as $links) { + $newelements[] = $links; + } + $footnote_element = []; + } + if (!empty($lastelement)) { + $newelements[] = $lastelement; + $lastelement = []; + } + $newelements[] = $element; + } + } else { + if (!empty($lastelement)) { + $newelements[] = $lastelement; + $lastelement = []; + } + if (!empty($footnote_element)) { + ksort($footnote_element); + foreach ($footnote_element as $links) { + $newelements[] = $links; + } + $footnote_element = []; + } + $newelements[] = $element; + } + } + if (!empty($lastelement)) { + $newelements[] = $lastelement; + } + if (!empty($footnote_element)) { + ksort($footnote_element); + foreach ($footnote_element as $links) { + $newelements[] = $links; + } + } + $this->elements = $newelements; + unset($footnote_element, $lastelement, $links, $newelements); - // Used with line breaks and cell height calculation within this box - $renderer->largestFontHeight = 0; + // Used with line breaks and cell height calculation within this box + $renderer->largestFontHeight = 0; - // If current position (left) - if ($this->left == '.') { - $cX = $renderer->GetX(); - } else { - // For static position add margin (returns and updates X) - $cX = $renderer->addMarginX($this->left); - } + // If current position (left) + if ($this->left == '.') { + $cX = $renderer->GetX(); + } else { + // For static position add margin (returns and updates X) + $cX = $renderer->addMarginX($this->left); + } - // If current position (top) - if ($this->top == '.') { - $cY = $renderer->GetY(); - } else { - $cY = $this->top; - $renderer->SetY($cY); - } + // If current position (top) + if ($this->top == '.') { + $cY = $renderer->GetY(); + } else { + $cY = $this->top; + $renderer->SetY($cY); + } - // Check the width if set to page wide OR set by xml to larger then page width (margin) - if ($this->width == 0 || $this->width > $renderer->getRemainingWidthPDF()) { - $cW = $renderer->getRemainingWidthPDF(); - } else { - $cW = $this->width; - } + // Check the width if set to page wide OR set by xml to larger then page width (margin) + if ($this->width == 0 || $this->width > $renderer->getRemainingWidthPDF()) { + $cW = $renderer->getRemainingWidthPDF(); + } else { + $cW = $this->width; + } - // Save the original margins - $cM = $renderer->getMargins(); - // Use cell padding to wrap the width - // Temp Width with cell padding - if (is_array($cM['cell'])) { - $cWT = $cW - ($cM['padding_left'] + $cM['padding_right']); - } else { - $cWT = $cW - ($cM['cell'] * 2); - } - // Element height (exept text) - $eH = 0; - $w = 0; - // Temp Height - $cHT = 0; - //-- $lw is an array - // 0 => last line width - // 1 => 1 if text was wrapped, 0 if text did not wrap - // 2 => number of LF - $lw = []; - // Element counter - $cE = count($this->elements); - //-- calculate the text box height + width - for ($i = 0; $i < $cE; $i++) { - if (is_object($this->elements[$i])) { - $ew = $this->elements[$i]->setWrapWidth($cWT - $w, $cWT); - if ($ew == $cWT) { - $w = 0; - } - $lw = $this->elements[$i]->getWidth($renderer); - // Text is already gets the # LF - $cHT += $lw[2]; - if ($lw[1] == 1) { - $w = $lw[0]; - } elseif ($lw[1] == 2) { - $w = 0; - } else { - $w += $lw[0]; - } - if ($w > $cWT) { - $w = $lw[0]; - } - // Footnote is at the bottom of the page. No need to calculate it’s height or wrap the text! - // We are changing the margins anyway! - // For anything else but text (images), get the height - $eH += $this->elements[$i]->getHeight($renderer); - } - } + // Save the original margins + $cM = $renderer->getMargins(); + // Use cell padding to wrap the width + // Temp Width with cell padding + if (is_array($cM['cell'])) { + $cWT = $cW - ($cM['padding_left'] + $cM['padding_right']); + } else { + $cWT = $cW - ($cM['cell'] * 2); + } + // Element height (exept text) + $eH = 0; + $w = 0; + // Temp Height + $cHT = 0; + //-- $lw is an array + // 0 => last line width + // 1 => 1 if text was wrapped, 0 if text did not wrap + // 2 => number of LF + $lw = []; + // Element counter + $cE = count($this->elements); + //-- calculate the text box height + width + for ($i = 0; $i < $cE; $i++) { + if (is_object($this->elements[$i])) { + $ew = $this->elements[$i]->setWrapWidth($cWT - $w, $cWT); + if ($ew == $cWT) { + $w = 0; + } + $lw = $this->elements[$i]->getWidth($renderer); + // Text is already gets the # LF + $cHT += $lw[2]; + if ($lw[1] == 1) { + $w = $lw[0]; + } elseif ($lw[1] == 2) { + $w = 0; + } else { + $w += $lw[0]; + } + if ($w > $cWT) { + $w = $lw[0]; + } + // Footnote is at the bottom of the page. No need to calculate it’s height or wrap the text! + // We are changing the margins anyway! + // For anything else but text (images), get the height + $eH += $this->elements[$i]->getHeight($renderer); + } + } - // Add up what’s the final height - $cH = $this->height; - // If any element exist - if ($cE > 0) { - // Check if this is text or some other element, like images - if ($eH == 0) { - // This is text elements. Number of LF but at least one line - $cHT = ($cHT + 1) * $renderer->getCellHeightRatio(); - // Calculate the cell hight with the largest font size used within this Box - $cHT = $cHT * $renderer->largestFontHeight; - // Add cell padding - if ($this->padding) { - if (is_array($cM['cell'])) { - $cHT += ($cM['padding_bottom'] + $cM['padding_top']); - } else { - $cHT += ($cM['cell'] * 2); - } - } - if ($cH < $cHT) { - $cH = $cHT; - } - } // This is any other element - elseif ($cH < $eH) { - $cH = $eH; - } - } - // Finaly, check the last cells height - if ($cH < $renderer->lastCellHeight) { - $cH = $renderer->lastCellHeight; - } - // Add a new page if needed - if ($this->pagecheck) { - // Reset last cell height or Header/Footer will inherit it, in case of pagebreak - $renderer->lastCellHeight = 0; - if ($renderer->checkPageBreakPDF($cH)) { - $cY = $renderer->GetY(); - } - } + // Add up what’s the final height + $cH = $this->height; + // If any element exist + if ($cE > 0) { + // Check if this is text or some other element, like images + if ($eH == 0) { + // This is text elements. Number of LF but at least one line + $cHT = ($cHT + 1) * $renderer->getCellHeightRatio(); + // Calculate the cell hight with the largest font size used within this Box + $cHT = $cHT * $renderer->largestFontHeight; + // Add cell padding + if ($this->padding) { + if (is_array($cM['cell'])) { + $cHT += ($cM['padding_bottom'] + $cM['padding_top']); + } else { + $cHT += ($cM['cell'] * 2); + } + } + if ($cH < $cHT) { + $cH = $cHT; + } + } // This is any other element + elseif ($cH < $eH) { + $cH = $eH; + } + } + // Finaly, check the last cells height + if ($cH < $renderer->lastCellHeight) { + $cH = $renderer->lastCellHeight; + } + // Add a new page if needed + if ($this->pagecheck) { + // Reset last cell height or Header/Footer will inherit it, in case of pagebreak + $renderer->lastCellHeight = 0; + if ($renderer->checkPageBreakPDF($cH)) { + $cY = $renderer->GetY(); + } + } - // Setup the border and background color - $cS = ''; // Class Style - if ($this->border) { - $cS = 'D'; - } // D or empty string: Draw (default) - $match = []; - // Fill the background - if ($this->fill) { - if (!empty($this->bgcolor)) { - if (preg_match('/#?(..)(..)(..)/', $this->bgcolor, $match)) { - $cS .= 'F'; // F: Fill the background - $r = hexdec($match[1]); - $g = hexdec($match[2]); - $b = hexdec($match[3]); - $renderer->SetFillColor($r, $g, $b); - } - } - } - // Clean up a bit - unset($lw, $w, $match, $cE, $eH); - // Draw the border - if (!empty($cS)) { - if (!$renderer->getRTL()) { - $cXM = $cX; - } else { - $cXM = ($renderer->getPageWidth()) - $cX - $cW; - } - $renderer->Rect($cXM, $cY, $cW, $cH, $cS); - } - // Add cell padding if set and if any text (element) exist - if ($this->padding) { - if ($cHT > 0) { - if (is_array($cM['cell'])) { - $renderer->SetY($cY + $cM['padding_top']); - } else { - $renderer->SetY($cY + $cM['cell']); - } - } - } - // Change the margins X, Width - if (!$renderer->getRTL()) { - if ($this->padding) { - if (is_array($cM['cell'])) { - $renderer->SetLeftMargin($cX + $cM['padding_left']); - } else { - $renderer->SetLeftMargin($cX + $cM['cell']); - } - $renderer->SetRightMargin($renderer->getRemainingWidthPDF() - $cW + $cM['right']); - } else { - $renderer->SetLeftMargin($cX); - $renderer->SetRightMargin($renderer->getRemainingWidthPDF() - $cW + $cM['right']); - } - } else { - if ($this->padding) { - if (is_array($cM['cell'])) { - $renderer->SetRightMargin($cX + $cM['padding_right']); - } else { - $renderer->SetRightMargin($cX + $cM['cell']); - } - $renderer->SetLeftMargin($renderer->getRemainingWidthPDF() - $cW + $cM['left']); - } else { - $renderer->SetRightMargin($cX); - $renderer->SetLeftMargin($renderer->getRemainingWidthPDF() - $cW + $cM['left']); - } - } - // Save the current page number - $cPN = $renderer->getPage(); + // Setup the border and background color + $cS = ''; // Class Style + if ($this->border) { + $cS = 'D'; + } // D or empty string: Draw (default) + $match = []; + // Fill the background + if ($this->fill) { + if (!empty($this->bgcolor)) { + if (preg_match('/#?(..)(..)(..)/', $this->bgcolor, $match)) { + $cS .= 'F'; // F: Fill the background + $r = hexdec($match[1]); + $g = hexdec($match[2]); + $b = hexdec($match[3]); + $renderer->SetFillColor($r, $g, $b); + } + } + } + // Clean up a bit + unset($lw, $w, $match, $cE, $eH); + // Draw the border + if (!empty($cS)) { + if (!$renderer->getRTL()) { + $cXM = $cX; + } else { + $cXM = ($renderer->getPageWidth()) - $cX - $cW; + } + $renderer->Rect($cXM, $cY, $cW, $cH, $cS); + } + // Add cell padding if set and if any text (element) exist + if ($this->padding) { + if ($cHT > 0) { + if (is_array($cM['cell'])) { + $renderer->SetY($cY + $cM['padding_top']); + } else { + $renderer->SetY($cY + $cM['cell']); + } + } + } + // Change the margins X, Width + if (!$renderer->getRTL()) { + if ($this->padding) { + if (is_array($cM['cell'])) { + $renderer->SetLeftMargin($cX + $cM['padding_left']); + } else { + $renderer->SetLeftMargin($cX + $cM['cell']); + } + $renderer->SetRightMargin($renderer->getRemainingWidthPDF() - $cW + $cM['right']); + } else { + $renderer->SetLeftMargin($cX); + $renderer->SetRightMargin($renderer->getRemainingWidthPDF() - $cW + $cM['right']); + } + } else { + if ($this->padding) { + if (is_array($cM['cell'])) { + $renderer->SetRightMargin($cX + $cM['padding_right']); + } else { + $renderer->SetRightMargin($cX + $cM['cell']); + } + $renderer->SetLeftMargin($renderer->getRemainingWidthPDF() - $cW + $cM['left']); + } else { + $renderer->SetRightMargin($cX); + $renderer->SetLeftMargin($renderer->getRemainingWidthPDF() - $cW + $cM['left']); + } + } + // Save the current page number + $cPN = $renderer->getPage(); - // Render the elements (write text, print picture...) - foreach ($this->elements as $element) { - if (is_object($element)) { - $element->render($renderer); - } elseif (is_string($element) && $element == 'footnotetexts') { - $renderer->footnotes(); - } elseif (is_string($element) && $element == 'addpage') { - $renderer->newPage(); - } - } - // Restore the margins - $renderer->SetLeftMargin($cM['left']); - $renderer->SetRightMargin($cM['right']); + // Render the elements (write text, print picture...) + foreach ($this->elements as $element) { + if (is_object($element)) { + $element->render($renderer); + } elseif (is_string($element) && $element == 'footnotetexts') { + $renderer->footnotes(); + } elseif (is_string($element) && $element == 'addpage') { + $renderer->newPage(); + } + } + // Restore the margins + $renderer->SetLeftMargin($cM['left']); + $renderer->SetRightMargin($cM['right']); - // This will be mostly used to trick the multiple images last height - if ($this->reseth) { - $cH = 0; - // This can only happen with multiple images and with pagebreak - if ($cPN != $renderer->getPage()) { - $renderer->setPage($cPN); - } - } - // New line and some clean up - if (!$this->newline) { - $renderer->SetXY(($cX + $cW), $cY); - $renderer->lastCellHeight = $cH; - } else { - // addMarginX() also updates X - $renderer->addMarginX(0); - $renderer->SetY($cY + $cH); - $renderer->lastCellHeight = 0; - } + // This will be mostly used to trick the multiple images last height + if ($this->reseth) { + $cH = 0; + // This can only happen with multiple images and with pagebreak + if ($cPN != $renderer->getPage()) { + $renderer->setPage($cPN); + } + } + // New line and some clean up + if (!$this->newline) { + $renderer->SetXY(($cX + $cW), $cY); + $renderer->lastCellHeight = $cH; + } else { + // addMarginX() also updates X + $renderer->addMarginX(0); + $renderer->SetY($cY + $cH); + $renderer->lastCellHeight = 0; + } - return true; - } + return true; + } } diff --git a/app/Report/ReportTcpdf.php b/app/Report/ReportTcpdf.php index 7a7041c82f..6134f28537 100644 --- a/app/Report/ReportTcpdf.php +++ b/app/Report/ReportTcpdf.php @@ -22,378 +22,405 @@ use TCPDF; * * This class inherits from the TCPDF class and is used to generate the PDF document */ -class ReportTcpdf extends TCPDF { - /** @var ReportBaseElement[] Array of elements in the header */ - public $headerElements = []; +class ReportTcpdf extends TCPDF +{ + /** @var ReportBaseElement[] Array of elements in the header */ + public $headerElements = []; - /** @var ReportBaseElement[] Array of elements in the page header */ - public $pageHeaderElements = []; + /** @var ReportBaseElement[] Array of elements in the page header */ + public $pageHeaderElements = []; - /** @var ReportBaseElement[] Array of elements in the footer */ - public $footerElements = []; + /** @var ReportBaseElement[] Array of elements in the footer */ + public $footerElements = []; - /** @var ReportBaseElement[] Array of elements in the body */ - public $bodyElements = []; + /** @var ReportBaseElement[] Array of elements in the body */ + public $bodyElements = []; - /** @var ReportBaseFootnote[] Array of elements in the footer notes */ - public $printedfootnotes = []; + /** @var ReportBaseFootnote[] Array of elements in the footer notes */ + public $printedfootnotes = []; - /** @var string Currently used style name */ - public $currentStyle; + /** @var string Currently used style name */ + public $currentStyle; - /** @var int The last cell height */ - public $lastCellHeight = 0; + /** @var int The last cell height */ + public $lastCellHeight = 0; - /** @var int The largest font size within a TextBox to calculate the height */ - public $largestFontHeight = 0; + /** @var int The largest font size within a TextBox to calculate the height */ + public $largestFontHeight = 0; - /** @var int The last pictures page number */ - public $lastpicpage = 0; + /** @var int The last pictures page number */ + public $lastpicpage = 0; - /** @var ReportBase The current report. */ - public $wt_report; + /** @var ReportBase The current report. */ + public $wt_report; - /** - * PDF Header -PDF - */ - public function header() { - foreach ($this->headerElements as $element) { - if (is_object($element)) { - $element->render($this); - } elseif (is_string($element) && $element == 'footnotetexts') { - $this->footnotes(); - } elseif (is_string($element) && $element == 'addpage') { - $this->newPage(); - } - } - foreach ($this->pageHeaderElements as $element) { - if (is_object($element)) { - $element->render($this); - } elseif (is_string($element) && $element == 'footnotetexts') { - $this->footnotes(); - } elseif (is_string($element) && $element == 'addpage') { - $this->newPage(); - } - } - } + /** + * PDF Header -PDF + */ + public function header() + { + foreach ($this->headerElements as $element) { + if (is_object($element)) { + $element->render($this); + } elseif (is_string($element) && $element == 'footnotetexts') { + $this->footnotes(); + } elseif (is_string($element) && $element == 'addpage') { + $this->newPage(); + } + } + foreach ($this->pageHeaderElements as $element) { + if (is_object($element)) { + $element->render($this); + } elseif (is_string($element) && $element == 'footnotetexts') { + $this->footnotes(); + } elseif (is_string($element) && $element == 'addpage') { + $this->newPage(); + } + } + } - /** - * PDF Body -PDF - */ - public function body() { - $this->AddPage(); - foreach ($this->bodyElements as $key => $element) { - if (is_object($element)) { - $element->render($this); - } elseif (is_string($element) && $element == 'footnotetexts') { - $this->footnotes(); - } elseif (is_string($element) && $element == 'addpage') { - $this->newPage(); - } - // Delete used elements in hope to reduce 'some' memory usage - unset($this->bodyElements[$key]); - } - } + /** + * PDF Body -PDF + */ + public function body() + { + $this->AddPage(); + foreach ($this->bodyElements as $key => $element) { + if (is_object($element)) { + $element->render($this); + } elseif (is_string($element) && $element == 'footnotetexts') { + $this->footnotes(); + } elseif (is_string($element) && $element == 'addpage') { + $this->newPage(); + } + // Delete used elements in hope to reduce 'some' memory usage + unset($this->bodyElements[$key]); + } + } - /** - * PDF Footnotes -PDF - */ - public function footnotes() { - foreach ($this->printedfootnotes as $element) { - if (($this->GetY() + $element->getFootnoteHeight($this)) > $this->getPageHeight()) { - $this->AddPage(); - } - $element->renderFootnote($this); - if ($this->GetY() > $this->getPageHeight()) { - $this->AddPage(); - } - } - } + /** + * PDF Footnotes -PDF + */ + public function footnotes() + { + foreach ($this->printedfootnotes as $element) { + if (($this->GetY() + $element->getFootnoteHeight($this)) > $this->getPageHeight()) { + $this->AddPage(); + } + $element->renderFootnote($this); + if ($this->GetY() > $this->getPageHeight()) { + $this->AddPage(); + } + } + } - /** - * PDF Footer -PDF - */ - public function footer() { - foreach ($this->footerElements as $element) { - if (is_object($element)) { - $element->render($this); - } elseif (is_string($element) && $element == 'footnotetexts') { - $this->footnotes(); - } elseif (is_string($element) && $element == 'addpage') { - $this->newPage(); - } - } - } + /** + * PDF Footer -PDF + */ + public function footer() + { + foreach ($this->footerElements as $element) { + if (is_object($element)) { + $element->render($this); + } elseif (is_string($element) && $element == 'footnotetexts') { + $this->footnotes(); + } elseif (is_string($element) && $element == 'addpage') { + $this->newPage(); + } + } + } - /** - * Add an element to the Header -PDF - * - * @param object|string $element - * - * @return int The number of the Header elements - */ - public function addHeader($element) { - $this->headerElements[] = $element; + /** + * Add an element to the Header -PDF + * + * @param object|string $element + * + * @return int The number of the Header elements + */ + public function addHeader($element) + { + $this->headerElements[] = $element; - return count($this->headerElements) - 1; - } + return count($this->headerElements) - 1; + } - /** - * Add an element to the Page Header -PDF - * - * @param object|string $element - * - * @return int The number of the Page Header elements - */ - public function addPageHeader($element) { - $this->pageHeaderElements[] = $element; + /** + * Add an element to the Page Header -PDF + * + * @param object|string $element + * + * @return int The number of the Page Header elements + */ + public function addPageHeader($element) + { + $this->pageHeaderElements[] = $element; - return count($this->pageHeaderElements) - 1; - } + return count($this->pageHeaderElements) - 1; + } - /** - * Add an element to the Body -PDF - * - * @param object|string $element - * - * @return int The number of the Body elements - */ - public function addBody($element) { - $this->bodyElements[] = $element; + /** + * Add an element to the Body -PDF + * + * @param object|string $element + * + * @return int The number of the Body elements + */ + public function addBody($element) + { + $this->bodyElements[] = $element; - return count($this->bodyElements) - 1; - } + return count($this->bodyElements) - 1; + } - /** - * Add an element to the Footer -PDF - * - * @param object|string $element - * - * @return int The number of the Footer elements - */ - public function addFooter($element) { - $this->footerElements[] = $element; + /** + * Add an element to the Footer -PDF + * + * @param object|string $element + * + * @return int The number of the Footer elements + */ + public function addFooter($element) + { + $this->footerElements[] = $element; - return count($this->footerElements) - 1; - } + return count($this->footerElements) - 1; + } - /** - * Remove the header. - * - * @param $index - */ - public function removeHeader($index) { - unset($this->headerElements[$index]); - } + /** + * Remove the header. + * + * @param $index + */ + public function removeHeader($index) + { + unset($this->headerElements[$index]); + } - /** - * Remove the page header. - * - * @param $index - */ - public function removePageHeader($index) { - unset($this->pageHeaderElements[$index]); - } + /** + * Remove the page header. + * + * @param $index + */ + public function removePageHeader($index) + { + unset($this->pageHeaderElements[$index]); + } - /** - * Remove the body. - * - * @param $index - */ - public function removeBody($index) { - unset($this->bodyElements[$index]); - } + /** + * Remove the body. + * + * @param $index + */ + public function removeBody($index) + { + unset($this->bodyElements[$index]); + } - /** - * Remove the footer. - * - * @param $index - */ - public function removeFooter($index) { - unset($this->footerElements[$index]); - } + /** + * Remove the footer. + * + * @param $index + */ + public function removeFooter($index) + { + unset($this->footerElements[$index]); + } - /** - * Clear the Header -PDF - */ - public function clearHeader() { - unset($this->headerElements); - $this->headerElements = []; - } + /** + * Clear the Header -PDF + */ + public function clearHeader() + { + unset($this->headerElements); + $this->headerElements = []; + } - /** - * Clear the Page Header -PDF - */ - public function clearPageHeader() { - unset($this->pageHeaderElements); - $this->pageHeaderElements = []; - } + /** + * Clear the Page Header -PDF + */ + public function clearPageHeader() + { + unset($this->pageHeaderElements); + $this->pageHeaderElements = []; + } - /** - * Set the report. - * - * @param $r - */ - public function setReport($r) { - $this->wt_report = $r; - } + /** + * Set the report. + * + * @param $r + */ + public function setReport($r) + { + $this->wt_report = $r; + } - /** - * Get the currently used style name -PDF - * - * @return string - */ - public function getCurrentStyle() { - return $this->currentStyle; - } + /** + * Get the currently used style name -PDF + * + * @return string + */ + public function getCurrentStyle() + { + return $this->currentStyle; + } - /** - * Setup a style for usage -PDF - * - * @param string $s Style name - */ - public function setCurrentStyle($s) { - $this->currentStyle = $s; - $style = $this->wt_report->getStyle($s); - $this->SetFont($style['font'], $style['style'], $style['size']); - } + /** + * Setup a style for usage -PDF + * + * @param string $s Style name + */ + public function setCurrentStyle($s) + { + $this->currentStyle = $s; + $style = $this->wt_report->getStyle($s); + $this->SetFont($style['font'], $style['style'], $style['size']); + } - /** - * Get the style -PDF - * - * @param string $s Style name - * - * @return array - */ - public function getStyle($s) { - if (!isset($this->wt_report->Styles[$s])) { - $s = $this->getCurrentStyle(); - $this->wt_report->Styles[$s] = $s; - } + /** + * Get the style -PDF + * + * @param string $s Style name + * + * @return array + */ + public function getStyle($s) + { + if (!isset($this->wt_report->Styles[$s])) { + $s = $this->getCurrentStyle(); + $this->wt_report->Styles[$s] = $s; + } - return $this->wt_report->Styles[$s]; - } + return $this->wt_report->Styles[$s]; + } - /** - * Add margin when static horizontal position is used -PDF - * RTL supported - * - * @param float $x Static position - * - * @return float - */ - public function addMarginX($x) { - $m = $this->getMargins(); - if ($this->getRTL()) { - $x += $m['right']; - } else { - $x += $m['left']; - } - $this->SetX($x); + /** + * Add margin when static horizontal position is used -PDF + * RTL supported + * + * @param float $x Static position + * + * @return float + */ + public function addMarginX($x) + { + $m = $this->getMargins(); + if ($this->getRTL()) { + $x += $m['right']; + } else { + $x += $m['left']; + } + $this->SetX($x); - return $x; - } + return $x; + } - /** - * Get the maximum line width to draw from the curren position -PDF - * RTL supported - * - * @return float - */ - public function getMaxLineWidth() { - $m = $this->getMargins(); - if ($this->getRTL()) { - return ($this->getRemainingWidth() + $m['right']); - } else { - return ($this->getRemainingWidth() + $m['left']); - } - } + /** + * Get the maximum line width to draw from the curren position -PDF + * RTL supported + * + * @return float + */ + public function getMaxLineWidth() + { + $m = $this->getMargins(); + if ($this->getRTL()) { + return ($this->getRemainingWidth() + $m['right']); + } else { + return ($this->getRemainingWidth() + $m['left']); + } + } - /** - * Get the height of the footnote. - * - * @return int - */ - public function getFootnotesHeight() { - $h = 0; - foreach ($this->printedfootnotes as $element) { - $h += $element->getHeight($this); - } + /** + * Get the height of the footnote. + * + * @return int + */ + public function getFootnotesHeight() + { + $h = 0; + foreach ($this->printedfootnotes as $element) { + $h += $element->getHeight($this); + } - return $h; - } + return $h; + } - /** - * Returns the the current font size height -PDF - * - * @return int - */ - public function getCurrentStyleHeight() { - if (empty($this->currentStyle)) { - return $this->wt_report->defaultFontSize; - } - $style = $this->wt_report->getStyle($this->currentStyle); + /** + * Returns the the current font size height -PDF + * + * @return int + */ + public function getCurrentStyleHeight() + { + if (empty($this->currentStyle)) { + return $this->wt_report->defaultFontSize; + } + $style = $this->wt_report->getStyle($this->currentStyle); - return $style['size']; - } + return $style['size']; + } - /** - * Checks the Footnote and numbers them - * - * @param object $footnote - * - * @return bool false if not numbered befor | object if already numbered - */ - public function checkFootnote($footnote) { - $ct = count($this->printedfootnotes); - $val = $footnote->getValue(); - $i = 0; - while ($i < $ct) { - if ($this->printedfootnotes[$i]->getValue() == $val) { - // If this footnote already exist then set up the numbers for this object - $footnote->setNum($i + 1); - $footnote->setAddlink($i + 1); + /** + * Checks the Footnote and numbers them + * + * @param object $footnote + * + * @return bool false if not numbered befor | object if already numbered + */ + public function checkFootnote($footnote) + { + $ct = count($this->printedfootnotes); + $val = $footnote->getValue(); + $i = 0; + while ($i < $ct) { + if ($this->printedfootnotes[$i]->getValue() == $val) { + // If this footnote already exist then set up the numbers for this object + $footnote->setNum($i + 1); + $footnote->setAddlink($i + 1); - return $this->printedfootnotes[$i]; - } - $i++; - } - // If this Footnote has not been set up yet - $footnote->setNum($ct + 1); - $footnote->setAddlink($this->AddLink()); - $this->printedfootnotes[] = $footnote; + return $this->printedfootnotes[$i]; + } + $i++; + } + // If this Footnote has not been set up yet + $footnote->setNum($ct + 1); + $footnote->setAddlink($this->AddLink()); + $this->printedfootnotes[] = $footnote; - return false; - } + return false; + } - /** - * Used this function instead of AddPage() - * This function will make sure that images will not be overwritten - */ - public function newPage() { - if ($this->lastpicpage > $this->getPage()) { - $this->setPage($this->lastpicpage); - } - $this->AddPage(); - } + /** + * Used this function instead of AddPage() + * This function will make sure that images will not be overwritten + */ + public function newPage() + { + if ($this->lastpicpage > $this->getPage()) { + $this->setPage($this->lastpicpage); + } + $this->AddPage(); + } - /** - * Add a page if needed -PDF - * - * @param int $height Cell height - * - * @return bool true in case of page break, false otherwise - */ - public function checkPageBreakPDF($height) { - return $this->checkPageBreak($height); - } + /** + * Add a page if needed -PDF + * + * @param int $height Cell height + * + * @return bool true in case of page break, false otherwise + */ + public function checkPageBreakPDF($height) + { + return $this->checkPageBreak($height); + } - /** - * Returns the remaining width between the current position and margins -PDF - * - * @return float Remaining width - */ - public function getRemainingWidthPDF() { - return $this->getRemainingWidth(); - } + /** + * Returns the remaining width between the current position and margins -PDF + * + * @return float Remaining width + */ + public function getRemainingWidthPDF() + { + return $this->getRemainingWidth(); + } } |
