rtl = true; } // Set the character setting $this->charset = 'UTF-8'; // Set the Keywords $this->rkeywords = $META_KEYWORDS; // 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); // Only admin should see the version number if (WT_USER_IS_ADMIN) { $this->generatedby .= " ".WT_VERSION_TEXT; } // For known size pages if (($this->pagew == 0) AND ($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": {$sizes = array(4767.86,6740.79);break;} // ISO 216, 1682 mm x 2378 mm case "2A0": {$sizes = array(3370.39,4767.86);break;} // ISO 216, 1189 mm x 1682 mm case "A0": {$sizes = array(2383.94,3370.39);break;} // ISO 216, 841 mm x 1189mm case "A1": {$sizes = array(1683.78,2383.94);break;} // ISO 216, 594 mm x 841 mm case "A2": {$sizes = array(1190.55,1683.78);break;} // ISO 216, 420 mm x 594 mm case "A3": {$sizes = array(841.89,1190.55);break;} // ISO 216, 297 mm x 420 mm case "A4": default:{ // For unknown Page Size Name $sizes = array(595.28,841.89); // ISO 216, 210 mm 297 mm $this->pageFormat = "A4"; break;} case "A5": {$sizes = array(419.53,595.28);break;} // ISO 216, 148 mm x 210 mm case "A6": {$sizes = array(297.64,419.53);break;} // ISO 216, 105 mm x 148 mm case "A7": {$sizes = array(209.76,297.64);break;} // ISO 216, 74 mm x 105 mm case "A8": {$sizes = array(147.40,209.76);break;} // ISO 216, 52 mm x 74 mm case "A9": {$sizes = array(104.88,147.40);break;} // ISO 216, 37 mm x 52 mm case "A10": {$sizes = array(73.70,104.88);break;} // ISO 216, 26 mm x 37 mm // ISO B series case "B0": {$sizes = array(2834.65,4008.19);break;} // ISO 216, 1000 mm x 1414 mm case "B1": {$sizes = array(2004.09,2834.65);break;} // ISO 216, 707 mm x 1000 mm case "B2": {$sizes = array(1417.32,2004.09);break;} // ISO 216, 500 mm x 707 mm case "B3": {$sizes = array(1000.63,1417.32);break;} // ISO 216, 353 mm x 500 mm case "B4": {$sizes = array(708.66,1000.63);break;} // ISO 216, 250 mm x 353 mm case "B5": {$sizes = array(498.90,708.66);break;} // ISO 216, 176 mm x 250 mm case "B6": {$sizes = array(354.33,498.90);break;} // ISO 216, 125 mm x 176 mm case "B7": {$sizes = array(249.45,354.33);break;} // ISO 216, 88 mm x 125 mm case "B8": {$sizes = array(175.75,249.45);break;} // ISO 216, 62 mm x 88 mm case "B9": {$sizes = array(124.72,175.75);break;} // ISO 216, 44 mm x 62 mm case "B10": {$sizes = array(87.87,124.72);break;} // ISO 216, 31 mm x 44 mm // ISO C series, Envelope case "C0": {$sizes = array(2599.37,3676.54);break;} // ISO 269, 917 mm x 1297 mm, For flat A0 sheet case "C1": {$sizes = array(1836.85,2599.37);break;} // ISO 269, 648 mm x 917 mm, For flat A1 sheet case "C2": {$sizes = array(1298.27,1836.85);break;} // ISO 269, 458 mm x 648 mm, For flat A2 sheet, A1 folded in half case "C3": {$sizes = array(918.43,1298.27);break;} // ISO 269, 324 mm x 458 mm, For flat A3 sheet, A2 folded in half case "C4": {$sizes = array(649.13,918.43);break;} // ISO 269, 229 mm x 324 mm, For flat A4 sheet, A3 folded in half case "C5": {$sizes = array(459.21,649.13);break;} // ISO 269, 162 mm x 229 mm, For flat A5 sheet, A4 folded in half case "C6/5":{$sizes = array(323.15,649.13);break;} // ISO 269, 114 mm x 229 mm. A5 folded twice = 1/3 A4. Alternative for the DL envelope case "C6": {$sizes = array(323.15,459.21);break;} // ISO 269, 114 mm x 162 mm, For A5 folded in half case "C7/6":{$sizes = array(229.61,459.21);break;} // ISO 269, 81 mm x 162 mm, For A5 sheet folded in thirds case "C7": {$sizes = array(229.61,323.15);break;} // ISO 269, 81 mm x 114 mm, For A5 folded in quarters case "C8": {$sizes = array(161.57,229.61);break;} // ISO 269, 57 mm x 81 mm case "C9": {$sizes = array(113.39,161.57);break;} // ISO 269, 40 mm x 57 mm case "C10": {$sizes = array(79.37,113.39);break;} // ISO 269, 28 mm x 40 mm case "DL": {$sizes = array(311.81,623.62);break;} // 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 // Untrimmed stock sizes for the ISO-A Series - ISO primary range case "RA0": {$sizes = array(2437.80,3458.27);break;} // ISO 478, 860 mm x 1220 mm case "RA1": {$sizes = array(1729.13,2437.80);break;} // ISO 478, 610 mm x 860 mm case "RA2": {$sizes = array(1218.90,1729.13);break;} // ISO 478, 430 mm x 610 mm case "RA3": {$sizes = array(864.57,1218.90);break;} // ISO 478, 305 mm x 430 mm case "RA4": {$sizes = array(609.45,864.57);break;} // ISO 478, 215 mm x 305 mm // Untrimmed stock sizes for the ISO-A Series - ISO supplementary range case "SRA0": {$sizes = array(2551.18,3628.35);break;} // ISO 593, 900 mm x 1280 mm case "SRA1": {$sizes = array(1814.17,2551.18);break;} // ISO 593, 640 mm x 900 mm case "SRA2": {$sizes = array(1275.59,1814.17);break;} // ISO 593, 450 mm x 640 mm case "SRA3": {$sizes = array(907.09,1275.59);break;} // ISO 593, 320 mm x 450 mm case "SRA4": {$sizes = array(637.80,907.09);break;} // ISO 593, 225 mm x 320 mm // ISO size variations case "A2EXTRA": {$sizes = array(1261.42,1754.65);break;} // ISO 216, 445 mm x 619 mm case "A2SUPER": {$sizes = array(864.57,1440.00);break;} // ISO 216, 305 mm x 508 mm case "A3EXTRA": {$sizes = array(912.76,1261.42);break;} // ISO 216, 322 mm x 445 mm case "SUPERA3": {$sizes = array(864.57,1380.47);break;} // ISO 216, 305 mm x 487 mm case "A4EXTRA": {$sizes = array(666.14,912.76);break;} // ISO 216, 235 mm x 322 mm case "A4LONG": {$sizes = array(595.28,986.46);break;} // ISO 216, 210 mm x 348 mm case "A4SUPER": {$sizes = array(649.13,912.76);break;} // ISO 216, 229 mm x 322 mm case "SUPERA4": {$sizes = array(643.46,1009.13);break;} // ISO 216, 227 mm x 356 mm case "A5EXTRA": {$sizes = array(490.39,666.14);break;} // ISO 216, 173 mm x 235 mm case "SOB5EXTRA": {$sizes = array(572.60,782.36);break;} // ISO 216, 202 mm x 276 mm // Japanese version of the ISO 216 B series case "JB0": {$sizes = array(2919.69,4127.24);break;} // JIS P 0138-61, 1030 mm x 1456 mm case "JB1": {$sizes = array(2063.62,2919.69);break;} // JIS P 0138-61, 728 mm x 1030 mm case "JB2": {$sizes = array(1459.84,2063.62);break;} // JIS P 0138-61, 515 mm x 728 mm case "JB3": {$sizes = array(1031.81,1459.84);break;} // JIS P 0138-61, 364 mm x 515 mm case "JB4": {$sizes = array(728.50,1031.81);break;} // JIS P 0138-61, 257 mm x 364 mm case "JB5": {$sizes = array(515.91,728.50);break;} // JIS P 0138-61, 182 mm x 257 mm case "JB6": {$sizes = array(362.83,515.91);break;} // JIS P 0138-61, 128 mm x 182 mm case "JB7": {$sizes = array(257.95,362.83);break;} // JIS P 0138-61, 91 mm x 128 mm case "JB8": {$sizes = array(181.42,257.95);break;} // JIS P 0138-61, 64 mm x 91 mm case "JB9": {$sizes = array(127.56,181.42);break;} // JIS P 0138-61, 45 mm x 64 mm case "JB10":{$sizes = array(90.71,127.56);break;} // JIS P 0138-61, 32 mm x 45 mm // US pages case "EXECUTIVE": {$sizes = array(522.00,756.00); break;} // 7.25 in x 10.5 in case "FOLIO": {$sizes = array(612.00,936.00); break;} // 8.5 in x 13 in case "FOOLSCAP":{$sizes = array(972.00,1224.00); break;} // 13.5 in x 17 in case "LEDGER": {$sizes = array(792.00,1224.00); break;} // 11 in x 17 in case "LEGAL": {$sizes = array(612.00,1008.00); break;} // 8.5 in x 14 in case "LETTER": {$sizes = array(612.00,792.00); break;} // 8.5 in x 11 in case "QUARTO": {$sizes = array(609.12,777.5); break;} // 8.46 in x 10.8 in case "STATEMENT": {$sizes = array(396.00,612.00); break;} // 5.5 in x 8.5 in case "USGOVT": {$sizes = array(576.00,792.00); break;} // 8 in x 11 in } $this->pagew = $sizes[0]; $this->pageh = $sizes[1]; } else { if ($this->pagew < 10) { die("REPORT ERROR PGVReportBase::setup(): For custom size pages you must set \"customwidth\" larger then this in the XML file"); } if ($this->pageh < 10) { die("REPORT ERROR PGVReportBase::setup(): For custom size pages you must set \"customheight\" larger then this in the XML file"); } } return 0; } /** * Process the Header , Page header, Body or Footer - PGVReportBase * * @param string $p Header (H), Page header (PH), Body (B) or Footer (F) */ function setProcessing($p) { $this->processing = $p; return 0; } /** * Add the Title when raw character data is used in PGVRTitle - PGVReportBase * * @param string $data */ function addTitle($data) { $this->title .= $data; return 0; } /** * Add the Description when raw character data is used in PGVRDescription - PGVReportBase * * @param string $data */ function addDescription($data) { $this->rsubject .= $data; return 0; } /** * Add Style to PGVRStyles array - PGVReportBase * * @see PGVRStyleSHandler() * @param array $style */ function addStyle($style) { $this->PGVRStyles[$style["name"]] = $style; return 0; } /** * Get a style from the PGVRStyles array - PGVReportBase * * @param string $s Style name * @return array */ function getStyle($s) { if (!isset($this->PGVRStyles[$s])) { return current($this->PGVRStyles); } return $this->PGVRStyles[$s]; } // static callback functions to sort data static function CompareBirthDate($x, $y) { return GedcomDate::Compare($x->getBirthDate(), $y->getBirthDate()); } static function CompareDeathDate($x, $y) { return GedcomDate::Compare($x->getDeathDate(), $y->getDeathDate()); } /** * @deprecated * @todo Is this a deprecated function or a future feature? * function get_type() { // remove this die line only if it's cousing problem - It confirms that it's not used die("REPORT ERROR PGVReportBase::get_type: It is used"); return "PGVReportBase"; } */ } /** * Main PGV Report Element class that all other page elements are extended from * * @package webtrees * @subpackage Reports */ class PGVRElement { /** * @var string */ public $text = ""; /** * Element renderer * @param &$renderer */ function render(&$renderer) { // print "Nothing rendered. Something bad happened"; // debug_print_backtrace(); //-- to be implemented in inherited classes return 0; } function getHeight(&$renderer) { return 0; } function getWidth(&$renderer) { return 0; } function addText($t) { global $embed_fonts, $SpecialOrds, $pgvreport, $reportTitle, $reportDescription; foreach($SpecialOrds as $ord) { if (strpos($t, chr($ord))!==false) { $embed_fonts = true; } } $t = trim($t, "\r\n\t"); $t = str_replace(array("
", " "), array("\n", " "), $t); if (!WT_RNEW) { $t = strip_tags($t); $t = unhtmlentities($t); } $this->text .= $t; // Adding the title and description to the Document Properties if ($reportTitle) { $pgvreport->addTitle($t); } elseif ($reportDescription) { $pgvreport->addDescription($t); } return 0; } function addNewline() { $this->text .= "\n"; return 0; } function getValue() { return $this->text; } function setWrapWidth($wrapwidth, $cellwidth) { return 0; } function renderFootnote(&$renderer) { return false; //-- to be implemented in inherited classes } /** * Get the Class name type * * @return string PGVRElementBase */ function get_type() { return "PGVRElementBase"; } function setText($text) { $this->text = $text; return 0; } } //-- END PGVRElement /** * HTML element class * * @package webtrees * @subpackage Reports * @todo add info */ class PGVRHtml extends PGVRElement { public $tag; public $attrs; public $elements = array(); function PGVRHtml($tag, $attrs) { $this->tag = $tag; $this->attrs = $attrs; return 0; } function getStart() { $str = "<".$this->tag." "; foreach($this->attrs as $key=>$value) { $str .= $key."=\"".$value."\" "; } $str .= ">"; return $str; } function getEnd() { return "tag.">"; } function addElement($element) { $this->elements[] = $element; return 0; } /** * Get the class type * @return string PGVRHtml */ function get_type() { return "PGVRHtml"; } } /** * Cell element class * * @package webtrees * @subpackage Reports */ class PGVRCell extends PGVRElement { /** * Allows to center or align the text. Possible values are: * @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): * @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: * @var int */ public $newline; /** * The name of the PGVRStyle that should be used to render the text. * @var string */ public $styleName; /** * Stretch carachter mode: * @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; public $reseth; /** * CELL - PGVRElement * * @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 */ function PGVRCell($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; } /** * Get the cell height * @todo add param * @return float */ function getHeight(&$renderer) { return $this->height; } /** * Sets the current cells URL * @param string $url The URL address to save */ function setUrl($url) { $this->url = $url; return 0; } /** * Get the cell width * @todo add param * @return float */ function getWidth(&$renderer) { return $this->width; } /** * Get the class type * @return string PGVRCell */ function get_type() { return "PGVRCell"; } } /** * TextBox element class * * @package webtrees * @subpackage Reports * @todo add info */ class PGVRTextBox extends PGVRElement { /** * Array of elements in the TextBox * @var array */ public $elements = array(); /** * Background color in HTML code * @var string */ public $bgcolor; /** * Whether or not paint the background * @var boolean */ public $fill; /** * Position the left corner of this box on the page(expressed in points). The default is the current position. * @var mix */ public $left; /** * Position the top corner of this box on the page(expressed in points). the default is the current position * @var mix */ 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 boolean */ public $newline; /** * @var boolean */ public $pagecheck; /** * Whether or not a border should be printed around this box. 0 = no border, 1 = border. Default is 0 * @var boolean */ public $border; /** * Style of rendering * * * @var string */ public $style; /** * @var array $borderstyle Border style of rectangle. Array with keys among the following: * * 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 boolean $padding */ public $padding; /** * Resets this box last height after it's done */ public $reseth; /** * TextBox - PGVRElement - Base * * @param float $width Text box width * @param float $height Text box height * @param boolean $border * @param string $bgcolor Background color code in HTML * @param boolean $newline * @param mixed $left * @param mixed $top * @param boolean $pagecheck * @param string $style * @param boolean $fill * @param boolean $padding * @param boolean $reseth */ function PGVRTextBox($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; } /** * Add an element to the TextBox * @param object|string &$element */ function addElement($element) { $this->elements[] = $element; return 0; } /** * Get the class type * @return string PGVRTextBox */ function get_type() { return "PGVRTextBox"; } } /** * Text element class * * @package webtrees * @subpackage Reports * @todo add info */ class PGVRText extends PGVRElement { /** * 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 */ function PGVRText($style, $color) { $this->text = ""; $this->color = $color; $this->wrapWidthRemaining = 0; $this->styleName = $style; return 0; } function setWrapWidth($wrapwidth, $cellwidth) { $this->wrapWidthCell = $cellwidth; if (strpos($this->text, "\n")!==false) { $this->wrapWidthRemaining = $cellwidth; } else { $this->wrapWidthRemaining = $wrapwidth; } return $this->wrapWidthRemaining; } function getStyleName() { return $this->styleName; } /** * Get the class type * @return string PGVRText */ function get_type() { return "PGVRText"; } } /** * Footnote element class * * @package webtrees * @subpackage Reports * @todo add info */ class PGVRFootnote extends PGVRElement { /** * The name of the style for this element * @var string */ public $styleName = ""; /** * Numbers for the links * @var int */ public $num; /** * 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; /** * Original width of a cell * @var float User unit (points) */ public $wrapWidthCell; public $addlink; function PGVRFootnote($style="") { $this->text = ""; if (!empty($style)) { $this->styleName = $style; } else { $this->styleName="footnote"; } return 0; } function rerender($renderer) { return false; } function addText($t) { global $embed_fonts, $SpecialOrds; foreach($SpecialOrds as $ord) { if (strpos($t, chr($ord))!==false) { $embed_fonts = true; } } $t = trim($t, "\r\n\t"); $t = str_replace(array("
", " "), array("\n", " "), $t); if (!WT_RNEW) { $t = strip_tags($t); $t = unhtmlentities($t); } $this->text .= $t; return 0; } function setWrapWidth($wrapwidth, $cellwidth) { $this->wrapWidthCell = $cellwidth; if (strpos($this->numText, "\n")!==false) { $this->wrapWidthRemaining = $cellwidth; } else { $this->wrapWidthRemaining = $wrapwidth; } return $this->wrapWidthRemaining; } function setNum($n) { $this->num = $n; //@@ $this->numText = "$n"; $this->numText = "$n "; //@@ source numbers return 0; } function setAddlink($a) { $this->addlink = $a; return 0; } /** * Get the class type * @return string PGVRFootnote */ function get_type() { return "PGVRFootnote"; } } /** * PageHeader element class * * @package webtrees * @subpackage Reports * @todo add info */ class PGVRPageHeader extends PGVRElement { public $elements = array(); function PGVRTextBox() { $this->elements = array(); return 0; } function PGVRPageHeader() { $this->elements = array(); return 0; } /** * Add element - PGVRPageHeader * @param $element */ function addElement($element) { $this->elements[] = $element; return 0; } /** * Get the class type * @return string PGVRPageHeader */ function get_type() { return "PGVRPageHeader"; } } /** * Image element class * * @package webtrees * @subpackage Reports * @todo add info */ class PGVRImage extends PGVRElement { /** * File name 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 = ""; /** * PGVRImage class function - Base * * @param string $file File name 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 */ function PGVRImage($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; } function getHeight(&$renderer) { return $this->height; } function getWidth(&$renderer) { return $this->width; } /** * Get the class type * @return string PGVRImage */ function get_type() { return "PGVRImage"; } } /** * Line element class * * @package webtrees * @subpackage Reports * @todo add info */ class PGVRLine extends PGVRElement { /** * 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 */ function PGVRLine($x1, $y1, $x2, $y2) { $this->x1 = $x1; $this->y1 = $y1; $this->x2 = $x2; $this->y2 = $y2; return 0; } function getHeight(&$renderer) { return abs($this->y2 - $this->y1); } function getWidth(&$renderer) { return abs($this->x2 - $this->x1); } /** * Get the class type * @return string PGVRLine */ function get_type() { return "PGVRLine"; } } /** * element handlers array * * Converts XML element names into functions * @global array $elementHandler */ $elementHandler = array(); $elementHandler["br"]["start"] = "brSHandler"; $elementHandler["PGVRBody"]["start"] = "PGVRBodySHandler"; $elementHandler["PGVRCell"]["end"] = "PGVRCellEHandler"; $elementHandler["PGVRCell"]["start"] = "PGVRCellSHandler"; $elementHandler["PGVRDescription"]["end"] = "PGVRDescriptionEHandler"; $elementHandler["PGVRDescription"]["start"] = "PGVRDescriptionSHandler"; $elementHandler["PGVRDoc"]["end"] = "PGVRDocEHandler"; $elementHandler["PGVRDoc"]["start"] = "PGVRDocSHandler"; $elementHandler["PGVReport"]["end"] = ""; $elementHandler["PGVReport"]["start"] = ""; $elementHandler["PGVRFacts"]["end"] = "PGVRFactsEHandler"; $elementHandler["PGVRFacts"]["start"] = "PGVRFactsSHandler"; $elementHandler["PGVRFooter"]["start"] = "PGVRFooterSHandler"; $elementHandler["PGVRFootnote"]["end"] = "PGVRFootnoteEHandler"; $elementHandler["PGVRFootnote"]["start"] = "PGVRFootnoteSHandler"; $elementHandler["PGVRFootnoteTexts"]["start"] = "PGVRFootnoteTextsSHandler"; $elementHandler["PGVRGedcom"]["end"] = "PGVRGedcomEHandler"; $elementHandler["PGVRGedcom"]["start"] = "PGVRGedcomSHandler"; $elementHandler["PGVRGedcomValue"]["start"] = "PGVRGedcomValueSHandler"; $elementHandler["PGVRGeneration"]["start"] = "PGVRGenerationSHandler"; $elementHandler["PGVRGetPersonName"]["start"] = "PGVRGetPersonNameSHandler"; $elementHandler["PGVRHeader"]["start"] = "PGVRHeaderSHandler"; $elementHandler["PGVRHighlightedImage"]["start"]= "PGVRHighlightedImageSHandler"; $elementHandler["PGVRif"]["end"] = "PGVRifEHandler"; $elementHandler["PGVRif"]["start"] = "PGVRifSHandler"; $elementHandler["PGVRImage"]["start"] = "PGVRImageSHandler"; $elementHandler["PGVRInput"]["end"] = ""; $elementHandler["PGVRInput"]["start"] = ""; $elementHandler["PGVRLine"]["start"] = "PGVRLineSHandler"; $elementHandler["PGVRList"]["end"] = "PGVRListEHandler"; $elementHandler["PGVRList"]["start"] = "PGVRListSHandler"; $elementHandler["PGVRListTotal"]["start"] = "PGVRListTotalSHandler"; $elementHandler["PGVRNewPage"]["start"] = "PGVRNewPageSHandler"; $elementHandler["PGVRNow"]["start"] = "PGVRNowSHandler"; $elementHandler["PGVRPageHeader"]["end"] = "PGVRPageHeaderEHandler"; $elementHandler["PGVRPageHeader"]["start"] = "PGVRPageHeaderSHandler"; $elementHandler["PGVRPageNum"]["start"] = "PGVRPageNumSHandler"; $elementHandler["PGVRRelatives"]["end"] = "PGVRRelativesEHandler"; $elementHandler["PGVRRelatives"]["start"] = "PGVRRelativesSHandler"; $elementHandler["PGVRRepeatTag"]["end"] = "PGVRRepeatTagEHandler"; $elementHandler["PGVRRepeatTag"]["start"] = "PGVRRepeatTagSHandler"; $elementHandler["PGVRSetVar"]["start"] = "PGVRSetVarSHandler"; $elementHandler["PGVRStyle"]["start"] = "PGVRStyleSHandler"; $elementHandler["PGVRText"]["end"] = "PGVRTextEHandler"; $elementHandler["PGVRText"]["start"] = "PGVRTextSHandler"; $elementHandler["PGVRTextBox"]["end"] = "PGVRTextBoxEHandler"; $elementHandler["PGVRTextBox"]["start"] = "PGVRTextBoxSHandler"; $elementHandler["PGVRTitle"]["end"] = "PGVRTitleEHandler"; $elementHandler["PGVRTitle"]["start"] = "PGVRTitleSHandler"; $elementHandler["PGVRTotalPages"]["start"] = "PGVRTotalPagesSHandler"; $elementHandler["PGVRvar"]["start"] = "PGVRvarSHandler"; $elementHandler["PGVRvarLetter"]["start"] = "PGVRvarLetterSHandler"; $elementHandler["sp"]["start"] = "spSHandler"; /** * A new object of the currently used element class * * @global object $currentElement */ $currentElement = new PGVRElement(); /** * Should character data be printed * * This variable is turned on or off by the element handlers to tell whether the inner character * Data should be printed * @global boolean $printData */ $printData = false; /** * Title collector. Mark it if it has already been used * * @global boolean $reportTitle */ $reportTitle = false; /** * Description collector. Mark it if it has already been used * * @global boolean $reportDescription */ $reportDescription = false; /** * Print data stack * * As the XML is being processed there will be times when we need to turn on and off the * $printData variable as we encounter entinties in the XML. The stack allows us to * keep track of when to turn $printData on and off. * @global array $printDataStack */ $printDataStack = array(); /** * @todo add info * @global array $pgvreportStack */ $pgvreportStack = array(); /** * @todo add info * @global array $gedrecStack */ $gedrecStack = array(); /** * @todo add info * @global array $repeatsStack */ $repeatsStack = array(); /** * @todo add info * @global array $parserStack */ $parserStack = array(); /** * @todo add info * @global array $repeats */ $repeats = array(); /** * @todo add info * @global string $gedrec */ $gedrec = ""; /** * @todo add info * @global ???? $repeatBytes */ $repeatBytes = 0; /** * @todo add info * @global resource $parser */ $parser = ""; /** * @todo add info * @global int $processRepeats */ $processRepeats = 0; /** * @todo add info * @global ???? $processIfs */ $processIfs = 0; /** * @todo add info * @global ???? $processGedcoms */ $processGedcoms = 0; /** * Wether or not to print footnote * true = print, false = don't print */ $processFootnote = true; /** *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 * @see endElement() */ function startElement($parser, $name, $attrs) { global $elementHandler, $processIfs, $processGedcoms, $processRepeats, $vars; global $processFootnote; $newattrs = array(); $match = array(); foreach($attrs as $key=>$value) { if (preg_match("/^\\$(\w+)$/", $value, $match)) { if ((isset($vars[$match[1]]["id"]))&&(!isset($vars[$match[1]]["gedcom"]))) { $value = $vars[$match[1]]["id"]; } } $newattrs[$key] = $value; } $attrs = $newattrs; if (($processFootnote)&&($processIfs==0 || $name=="PGVRif")&&($processGedcoms==0 || $name=="PGVRGedcom")&&($processRepeats==0 || $name=="PGVRFacts" || $name=="PGVRRepeatTag")) { if (isset($elementHandler[$name]["start"])) { if ($elementHandler[$name]["start"] != "") { call_user_func($elementHandler[$name]["start"], $attrs); } } elseif (!isset($elementHandler[$name]["end"])) { HTMLSHandler($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 * @see startElement() */ function endElement($parser, $name) { global $elementHandler, $processIfs, $processGedcoms, $processRepeats; global $processFootnote; if (($processFootnote || $name=="PGVRFootnote")&&($processIfs==0 || $name=="PGVRif")&&($processGedcoms==0 || $name=="PGVRGedcom")&&($processRepeats==0 || $name=="PGVRFacts" || $name=="PGVRRepeatTag" || $name=="PGVRList" || $name=="PGVRRelatives")) { if (isset($elementHandler[$name]["end"])) { if ($elementHandler[$name]["end"]!="") { call_user_func($elementHandler[$name]["end"]); } } elseif (!isset($elementHandler[$name]["start"])) { HTMLEHandler($name); } } } /** * XML character data handler * * This function is called whenever raw character data is reached * just print it to the screen * @param resource $parser the resource handler for the XML parser * @param string $data the name of the XML element parsed * @todo check this */ function characterData($parser, $data) { global $printData, $currentElement, $processGedcoms, $processIfs, $processRepeats, $reportTitle, $pgvreport, $reportDescription; // global $processFootnote; if ($printData && ($processGedcoms==0) && ($processIfs==0)&&($processRepeats==0)) { $currentElement->addText($data); } elseif ($reportTitle) { $pgvreport->addTitle($data); } elseif ($reportDescription) { $pgvreport->addDescription($data); } } /** * XML elemnt handler * * @param array $attrs an array of key value pairs for the attributes * @see PGVReportBase::$defaultFont * @see PGVReportBase::$defaultFontSize * @see PGVReportBase::addStyle() * @todo add info - update wiki */ function PGVRStyleSHandler($attrs) { global $pgvreport; if (empty($attrs["name"])) { die("REPORT ERROR PGVRStyle: The \"name\" of the style is missing or not set in the XML file."); } // array Style that will be passed on $s = array(); // string Name af the style $s["name"] = $attrs["name"]; // string Name of the DEFAULT font $s["font"] = $pgvreport->defaultFont; if (!empty($attrs["font"])) $s["font"] = $attrs["font"]; // int The size of the font in points $s["size"] = $pgvreport->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"]; $pgvreport->addStyle($s); } /** * XML start elemnt handler * * Sets up the basics of the document proparties * @param array $attrs an array of key value pairs for the attributes * @see PGVRDocEHandler() * @see PGVReportBase::setup() * @todo add showGeneratedBy, height, width param to wiki and update the defaults */ function PGVRDocSHandler($attrs) { global $parser, $xml_parser, $pgvreport; $parser = $xml_parser; // Custom page width if (!empty($attrs["customwidth"])) $pgvreport->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"])) $pgvreport->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") $pgvreport->leftmargin = 0; elseif (!empty($attrs["leftmargin"])) { $pgvreport->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") $pgvreport->rightmargin = 0; elseif (!empty($attrs["rightmargin"])) { $pgvreport->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") $pgvreport->topmargin = 0; elseif (!empty($attrs["topmargin"])) { $pgvreport->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") $pgvreport->bottommargin = 0; elseif (!empty($attrs["bottommargin"])) { $pgvreport->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") $pgvreport->headermargin = 0; elseif (!empty($attrs["headermargin"])) { $pgvreport->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") $pgvreport->footermargin = 0; elseif (!empty($attrs["footermargin"])) { $pgvreport->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") $pgvreport->orientation = "landscape"; elseif ($attrs["orientation"] == "portrait") { $pgvreport->orientation = "portrait"; } } // Page Size if (!empty($attrs["pageSize"])) $pgvreport->pageFormat = strtoupper($attrs["pageSize"]); // Show Generated By... if (isset($attrs["showGeneratedBy"])) { if ($attrs["showGeneratedBy"] === "0") $pgvreport->showGenText = false; elseif ($attrs["showGeneratedBy"] === "1") { $pgvreport->showGenText = true; } } $pgvreport->setup(); } /** * XML end elemnt handler * * @see PGVRDocSHandler() */ function PGVRDocEHandler() { global $pgvreport; $pgvreport->run(); } /** * XML start elemnt handler * * @see PGVReportBase::setProcessing() */ function PGVRHeaderSHandler() { global $pgvreport; // Clear the Header before any new elements are added $pgvreport->clearHeader(); $pgvreport->setProcessing("H"); } /** * XML start elemnt handler * * @param array $attrs an array of key value pairs for the attributes * @see PGVRPageHeaderEHandler() */ function PGVRPageHeaderSHandler($attrs) { global $printDataStack, $printData, $pgvreportStack, $pgvreport, $PGVReportRoot; array_push($printDataStack, $printData); $printData = false; array_push($pgvreportStack, $pgvreport); $pgvreport = $PGVReportRoot->createPageHeader(); } /** * XML end elemnt handler * * @see PGVRPageHeaderSHandler() */ function PGVRPageHeaderEHandler() { global $printData, $printDataStack, $pgvreport, $currentElement, $pgvreportStack; $printData = array_pop($printDataStack); $currentElement = $pgvreport; $pgvreport = array_pop($pgvreportStack); $pgvreport->addElement($currentElement); } /** * XML start elemnt handler */ function PGVRBodySHandler() { global $pgvreport; $pgvreport->setProcessing("B"); } /** * XML start elemnt handler */ function PGVRFooterSHandler() { global $pgvreport; $pgvreport->setProcessing("F"); } /** * XML start elemnt handler * * @param array $attrs an array of key value pairs for the attributes * @see PGVRCellEHandler() * @see PGVRCell * @todo defaults to wiki */ function PGVRCellSHandler($attrs) { global $printData, $printDataStack, $currentElement, $PGVReportRoot, $pgvreport; // 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 ($pgvreport->rtl) { $align = "left"; } else { $align = "right"; } } elseif ($align == "leftrtl") { if ($pgvreport->rtl) { $align = "right"; } else { $align = "left"; } } } // 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; } } $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"]; // @test Print all borders for testing // $border = 1; // 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 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; } } // string The name of the PGVRStyle 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"]; // 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"; } array_push($printDataStack, $printData); $printData = true; $currentElement = $PGVReportRoot->createCell($width, $height, $border, $align, $bgcolor, $style, $ln, $top, $left, $fill, $stretch, $bocolor, $tcolor, $reseth); } /** * XML end elemnt handler * * @see PGVRCellSHandler() * @final */ function PGVRCellEHandler() { global $printData, $printDataStack, $currentElement, $pgvreport; $printData = array_pop($printDataStack); $pgvreport->addElement($currentElement); } /** * XML elemnt handler * * @see PGVRElement::addText() * @final */ function PGVRNowSHandler() { global $currentElement; $g = timestamp_to_gedcom_date(client_time()); $currentElement->addText($g->Display()); } /** * XML elemnt handler * * @see PGVRElement::addText() * @final */ function PGVRPageNumSHandler() { global $currentElement; $currentElement->addText("#PAGENUM#"); } /** * XML elemnt handler * * @see PGVRElement::addText() * @final */ function PGVRTotalPagesSHandler() { global $currentElement; $currentElement->addText("{{nb}}"); } /** * @see PGVRGedcomEHandler() * @todo add info * @param array $attrs an array of key value pairs for the attributes */ function PGVRGedcomSHandler($attrs) { global $vars, $gedrec, $gedrecStack, $processGedcoms, $fact, $desc, $ged_level; if ($processGedcoms>0) { $processGedcoms++; return; } $id = ""; $match = array(); if (preg_match("/0 @(.+)@/", $gedrec, $match)) { $id = $match[1]; } $tag = $attrs["id"]; $tag = str_replace("@fact", $fact, $tag); $tags = explode(":", $tag); $newgedrec = ""; if (count($tags)<2) { $newgedrec = find_gedcom_record($attrs["id"], WT_GED_ID); } if (empty($newgedrec)) { $tgedrec = $gedrec; $newgedrec = ""; foreach($tags as $tag) { if (preg_match("/\\$(.+)/", $tag, $match)) { if (isset($vars[$match[1]]["gedcom"])) { $newgedrec = $vars[$match[1]]["gedcom"]; } else { $newgedrec = find_gedcom_record($match[1], WT_GED_ID); } } else { if (preg_match("/@(.+)/", $tag, $match)) { $gmatch = array(); if (preg_match("/\d $match[1] @([^@]+)@/", $tgedrec, $gmatch)) { $newgedrec = find_gedcom_record($gmatch[1], WT_GED_ID); $tgedrec = $newgedrec; } else { $newgedrec = ""; break; } } else { $temp = explode(" ", trim($tgedrec)); $level = $temp[0] + 1; if (showFact($tag, $id) && showFactDetails($tag, $id)) { $newgedrec = get_sub_record($level, "$level $tag", $tgedrec); $tgedrec = $newgedrec; } else { $newgedrec = ""; break; } } } } } if (!empty($newgedrec)) { $gedObj = new GedcomRecord($newgedrec); array_push($gedrecStack, array($gedrec, $fact, $desc)); $gedrec = $gedObj->getGedcomRecord(); if (preg_match("/(\d+) (_?[A-Z0-9]+) (.*)/", $gedrec, $match)) { $ged_level = $match[1]; $fact = $match[2]; $desc = trim($match[3]); } } else { $processGedcoms++; } } /** * @see PGVRGedcomSHandler() * @todo add info */ function PGVRGedcomEHandler() { global $gedrec, $gedrecStack, $processGedcoms, $fact, $desc; if ($processGedcoms>0) { $processGedcoms--; } else { $temp = array_pop($gedrecStack); $gedrec = $temp[0]; $fact = $temp[1]; $desc = $temp[2]; } } /** * XML start elemnt handler * * @param array $attrs an array of key value pairs for the attributes * @see PGVRTextBoxEHandler() * @todo defaults to wiki */ function PGVRTextBoxSHandler($attrs) { global $printData, $printDataStack, $pgvreport, $currentElement, $pgvreportStack, $PGVReportRoot; // 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; } } // 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; } } // @test Print all borders for testing // $border = true; /** * Border style of rectangle. Array with keys among the following *
  • L, T, R, B or combinations: Line style of left, top, right or bottom border.
* @var string */ /** not yet in use $borderstyle = ""; if (!empty($attrs["borderstyle"])) $borderstyle = $attrs["borderstyle"]; */ // 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; } } // string Style of rendering $style = ""; // fill and border is enought for now for user input // if (!empty($attrs["style"])) $style = $attrs["style"]; array_push($printDataStack, $printData); $printData = false; array_push($pgvreportStack, $pgvreport); $pgvreport = $PGVReportRoot->createTextBox($width, $height, $border, $bgcolor, $newline, $left, $top, $pagecheck, $style, $fill, $padding, $reseth); } /** * XML end elemnt handler * * @see PGVRTextBoxSHandler() */ function PGVRTextBoxEHandler() { global $printData, $printDataStack, $pgvreport, $currentElement, $pgvreportStack; $printData = array_pop($printDataStack); $currentElement = $pgvreport; $pgvreport = array_pop($pgvreportStack); $pgvreport->addElement($currentElement); } /** * @see PGVRTextEHandler() * @todo add info to wiki about "color" * @todo more variables in PGVRText class, check it out * @param array $attrs an array of key value pairs for the attributes */ function PGVRTextSHandler($attrs) { global $printData, $printDataStack, $currentElement, $PGVReportRoot; array_push($printDataStack, $printData); $printData = true; // string The name of the PGVRStyle 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"]; $currentElement = $PGVReportRoot->createText($style, $color); } /** * @see PGVRTextSHandler() */ function PGVRTextEHandler() { global $printData, $printDataStack, $pgvreport, $currentElement; $printData = array_pop($printDataStack); $pgvreport->addElement($currentElement); } /** * XML start elemnt handler * 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 */ function PGVRGetPersonNameSHandler($attrs) { // @deprecated global $currentElement, $vars, $gedrec; $id = ""; $match = array(); if (empty($attrs["id"])) { if (preg_match("/0 @(.+)@/", $gedrec, $match)) { $id = $match[1]; } } else { if (preg_match("/\\$(.+)/", $attrs["id"], $match)) { if (isset($vars[$match[1]]["id"])) { $id = $vars[$match[1]]["id"]; } } else { if (preg_match("/@(.+)/", $attrs["id"], $match)) { $gmatch = array(); if (preg_match("/\d $match[1] @([^@]+)@/", $gedrec, $gmatch)) { $id = $gmatch[1]; } } else { $id = $attrs["id"]; } } } if (!empty($id)) { $record = GedcomRecord::getInstance($id); if (is_null($record)) { return; } if (!$record->canDisplayName()) { $currentElement->addText(i18n::translate('Private')); } else { $name = $record->getFullName(); $name = preg_replace("/(.*)<\/span> ?/", "\\1* ", $name); //restores the * for underlining a given name if (!WT_RNEW) { $name = strip_tags($name); } if (!empty($attrs["truncate"])) { //short-circuit with the faster strlen if (strlen($name)>$attrs["truncate"] && utf8_strlen($name)>$attrs["truncate"]) { $name = preg_replace("/\(.*\) ?/", "", $name); //removes () and text inbetween - what about ", [ and { etc? $words = explode(" ", $name); $name = $words[count($words)-1]; for($i=count($words)-2; $i>=0; $i--) { $len = utf8_strlen($name); for($j=count($words)-3; $j>=0; $j--) { $len += utf8_strlen($words[$j]); } if ($len>$attrs["truncate"]) { $first_letter = utf8_substr($words[$i], 0, 1); //do not show " of nick-names if ($first_letter != "\"") $name = utf8_substr($words[$i], 0, 1).". ".$name; } else { $name = $words[$i]." ".$name; } } } } else { $addname = $record->getAddName(); $addname = preg_replace("/(.*)<\/span> ?/", "\\1* ", $addname); //@@ restores the * for underlining a given name if (!WT_RNEW) { $addname = strip_tags($addname);//@@ } if (!empty($addname)) { $name .= " ".$addname; } } $currentElement->addText(trim($name)); } } } /** * XML start elemnt handler * * @param array $attrs an array of key value pairs for the attributes */ function PGVRGedcomValueSHandler($attrs) { // @deprecated global $currentElement, $gedrec, $fact, $desc; $id = ""; $match = array(); if (preg_match("/0 @(.+)@/", $gedrec, $match)) { $id = $match[1]; } if (isset($attrs["newline"]) && $attrs["newline"]=="1") { $useBreak = "1"; } else { $useBreak = "0"; } $tag = $attrs["tag"]; if (!empty($tag)) { if ($tag=="@desc") { if (showFact($fact, $id) or showFactDetails($fact, $id)) { $value = $desc; } else { $value = ""; } $value = trim($value); $currentElement->addText($value); } if ($tag=="@id") { $currentElement->addText($id); } else { $tag = str_replace("@fact", $fact, $tag); if (empty($attrs["level"])) { $temp = explode(" ", trim($gedrec)); $level = $temp[0]; if ($level==0) { $level++; } } else { $level = $attrs["level"]; } $truncate = ""; if (isset($attrs["truncate"])) { $truncate=$attrs["truncate"]; } $tags = explode(":", $tag); //-- check all tags for privacy foreach($tags as $subtag) { if (!empty($subtag)) { if (!showFact($subtag, $id) or !showFactDetails($subtag, $id)) { return; } } } if (showFact($fact, $id) or showFactDetails($fact, $id)) { $value = get_gedcom_value($tag, $level, $gedrec, $truncate); if ($useBreak == "1") { // Insert
when multiple dates exist. // This works around a TCPDF bug that incorrectly wraps RTL dates on LTR pages $value = str_replace('(', '
(', $value); $value = str_replace('
', '
', $value); $value = str_replace('
', '
', $value); if (substr($value, 0, 6) == '
') { $value = substr($value, 6); } } $currentElement->addText($value); } } } } /** * XML start elemnt handler * * @see PGVRRepeatTagEHandler() * @param array $attrs an array of key value pairs for the attributes */ function PGVRRepeatTagSHandler($attrs) { // @deprecated // global $repeats, $repeatsStack, $gedrec, $repeatBytes, $parser, $parserStack, $processRepeats, $fact, $desc; global $repeats, $repeatsStack, $gedrec, $repeatBytes, $parser, $processRepeats, $fact, $desc; $processRepeats++; if ($processRepeats>1) return; array_push($repeatsStack, array($repeats, $repeatBytes)); $repeats = array(); $repeatBytes = xml_get_current_line_number($parser); $id = ""; $match = array(); if (preg_match("/0 @(.+)@/", $gedrec, $match)) { $id = $match[1]; } $tag = ""; if (isset($attrs["tag"])) { $tag = $attrs["tag"]; } if (!empty($tag)) { if ($tag=="@desc") { if (showFact($fact, $id) and showFactDetails($fact, $id)) { $value = $desc; } else { $value = ""; } $value = trim($value); $currentElement->addText($value); } else { $tag = str_replace("@fact", $fact, $tag); $tags = explode(":", $tag); $temp = explode(" ", trim($gedrec)); $level = $temp[0]; if ($level == 0) { $level++; } $subrec = $gedrec; $t = $tag; $count = count($tags); $i = 0; while ($i < $count) { $t = $tags[$i]; if (!empty($t)) { if (($level==1) && (strpos("CHIL,FAMS,FAMC", $t)===false) and (!showFact($t, $id) or !showFactDetails($t, $id))) { return; } if ($i < ($count-1)) { $subrec = get_sub_record($level, "$level $t", $subrec); if (empty($subrec)) { $level--; $subrec = get_sub_record($level, "@ $t", $gedrec); if (empty($subrec)) { return; } } } $level++; } $i++; } $level--; if ( (($level > 0) or (strpos("CHIL,FAMS,FAMC", $t) !== false)) or ((showFact($t, $id)) or (showFactDetails($t, $id))) ) { $count = preg_match_all("/$level $t(.*)/", $subrec, $match, PREG_SET_ORDER); $i = 0; while ($i < $count) { // Check for privacy if (showFact($t, $id) and showFactDetails($t, $id)) { $rec = get_sub_record($level, "$level $t", $subrec, $i + 1); $repeats[] = trim($rec); } $i++; } } } } } /** * XML end elemnt handler * * @see PGVRRepeatTagSHandler() */ function PGVRRepeatTagEHandler() { global $processRepeats, $repeats, $repeatsStack, $repeatBytes; $processRepeats--; if ($processRepeats>0) { return; } // Check if there is anything to repeat if (count($repeats)>0) { // No need to load them if not used... global $parser, $parserStack, $report, $gedrec; // @deprecated // $line = xml_get_current_line_number($parser)-1; $lineoffset = 0; foreach($repeatsStack as $rep) { $lineoffset += $rep[1]; } //-- read the xml from the file $lines = file($report); while(strpos($lines[$lineoffset + $repeatBytes], " element * * If the variable is a date and 'date="1"' attribute is set then the date will be reformated * from Sep to September * * @param array $attrs an array of key value pairs for the attributes * @see PGVRSetVarSHandler() */ function PGVRvarSHandler($attrs) { // @deprecated global $currentElement, $type, $parser; // Retrievable variables global $desc, $fact, $language_settings, $vars; if (empty($attrs["var"])) { die("REPORT ERROR PGVRvar: The attribute \"var=\" is missing or not set in the XML file on line: ".xml_get_current_line_number($parser)); } $var = $attrs["var"]; // PGVRSetVar element preset variables if (!empty($vars[$var]["id"])) { $var = $vars[$var]["id"]; } else { $tfact = $fact; if (($fact == "EVEN" or $fact == "FACT") and $type != " ") { // Use : // n TYPE This text if string $tfact = $type; } $var = str_replace(array("[", "]", "@fact", "@desc"), array("['", "']", $tfact, $desc), $var); eval("if (!empty(\$$var)) \$var = \$$var;"); $match = array(); if (preg_match("/factarray\['(.*)'\]/", $var, $match)) { $var = $match[1]; } } // Check if variable is set as a date and reformat the date if (isset($attrs["date"])) { if ($attrs["date"] === "1") { $g = new GedcomDate($var); $var = $g->Display(); } } $currentElement->addText($var); } /** * Variable lookup, retrieve the first letter only * * @param array $attrs an array of key value pairs for the attributes */ function PGVRvarLetterSHandler($attrs) { global $currentElement, $fact, $desc; if (empty($attrs["var"])) { die("REPORT ERROR PGVRvarLetter: The attribute \"var=\" is missing or not set in the XML file."); } $var = $attrs["var"]; if (!empty($var)) { $abbrev = substr(strrchr(substr($var, 0, -1), "["), 1); $tfact = $fact; $var = str_replace(array("[", "]", "@fact", "@desc"), array("['", "']", $tfact, $desc), $var); eval("if (!empty(\$$var)) \$var = \$$var;"); $letter = utf8_substr($var, 0, 1); $currentElement->addText($letter); } } /** * @todo add info * @param array $attrs an array of key value pairs for the attributes * @see PGVRFactsEHandler() */ function PGVRFactsSHandler($attrs) { // @deprecated // global $repeats, $repeatsStack, $gedrec, $parser, $parserStack, $repeatBytes, $processRepeats, $vars; global $repeats, $repeatsStack, $gedrec, $parser, $repeatBytes, $processRepeats, $vars; $processRepeats++; if ($processRepeats>1) return; // @todo Why is this here when its not used? $families = 1; if (isset($attrs["families"])) { $families = $attrs["families"]; } array_push($repeatsStack, array($repeats, $repeatBytes)); $repeats = array(); $repeatBytes = xml_get_current_line_number($parser); $id = ""; $match = array(); if (preg_match("/0 @(.+)@/", $gedrec, $match)) { $id = $match[1]; } $tag = ""; if (isset($attrs["ignore"])) { $tag .= $attrs["ignore"]; } if (preg_match("/\\$(.+)/", $tag, $match)) { $tag = $vars[$match[1]]["id"]; } if (empty($attrs["diff"]) && !empty($id)) { $record = GedcomRecord::getInstance($id); $facts = $record->getFacts(explode(",", $tag)); if (!is_array($facts)) { $facts = array($facts); } sort_facts($facts); $repeats = array(); foreach($facts as $event) { if (strpos($tag.",", $event->getTag())===false) { $repeats[]=$event->getGedComRecord(); } } } else { global $nonfacts; $nonfacts = preg_split("/[\s,;:]/", $tag); $record = new GedcomRecord($gedrec); switch ($record->getType()) { case "INDI": $record=new Person($gedrec); break; case "FAM": $record=new Family($gedrec); break; case "SOUR": $record=new Source($gedrec); break; case "REPO": $record=new Repository($gedrec); break; case "NOTE": $record=new Note($gedrec); break; } $oldrecord = GedcomRecord::getInstance($record->getXref()); $oldrecord->diffMerge($record); $facts = $oldrecord->getFacts(); foreach ($facts as $fact) { if (strpos($fact->getGedcomRecord(), "WT_NEW")!==false) { $repeats[]=$fact->getGedcomRecord(); } } } } /** * XML end elemnt handler * * @see PGVRFactsSHandler() */ function PGVRFactsEHandler() { global $repeats, $repeatsStack, $repeatBytes, $parser, $parserStack, $report, $gedrec, $fact, $desc, $type, $processRepeats; $processRepeats--; if ($processRepeats>0) { return; } // Check if there is anything to repeat if (count($repeats) > 0) { $line = xml_get_current_line_number($parser)-1; $lineoffset = 0; foreach($repeatsStack as $rep) { $lineoffset += $rep[1]; } //-- read the xml from the file $lines = file($report); while(($lineoffset + $repeatBytes > 0) and (strpos($lines[$lineoffset + $repeatBytes], "REPORT ERROR PGVRvar: The attribute \"name=\" is missing or not set in the XML file"); } $name = $attrs["name"]; $value = $attrs["value"]; $match = array(); // Current GEDCOM record strings if ($value == "@ID") { if (preg_match("/0 @(.+)@/", $gedrec, $match)) { $value = $match[1]; } } elseif ($value == "@fact") { $value = $fact; } elseif ($value == "@desc") { $value = $desc; } elseif ($value == "@generation") { $value = $generation; } elseif (preg_match("/@(\w+)/", $value, $match)) { $gmatch = array(); if (preg_match("/\d $match[1] (.+)/", $gedrec, $gmatch)) { $value = str_replace("@", "", trim($gmatch[1])); } } if (preg_match("/\\$(\w+)/", $name, $match)) { $name = $vars["'".$match[1]."'"]["id"]; } // TODO: find an alternative that doesn't use pgv_lang //if ((substr($value, 0, 10) == "\$pgv_lang[") or (substr($value, 0, 11) == "\$factarray[")) { // $var = str_replace(array("[", "]"), array("['", "']"), $value); // eval("\$value = $var;"); //} //$count = preg_match_all("/\\$(\w+)/", $value, $match, PREG_SET_ORDER); //$i=0; //while($i<$count) { // $t = $vars[$match[$i][1]]["id"]; // $value = preg_replace("/\\$".$match[$i][1]."/", $t, $value, 1); // $i++; //} // 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=""; } $vars[$name]["id"]=$value; } /** * XML start element * @see PGVRifEHandler() * @param array $attrs an array of key value pairs for the attributes */ function PGVRifSHandler($attrs) { global $vars, $gedrec, $processIfs, $fact, $desc, $generation, $POSTAL_CODE; if ($processIfs>0) { $processIfs++; return; } $vars["POSTAL_CODE"]["id"] = $POSTAL_CODE; $condition = $attrs["condition"]; $condition = preg_replace("/\\$(\w+)/", "\$vars[\"$1\"][\"id\"]", $condition); $condition = str_replace(array(" LT ", " GT "), array("<", ">"), $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", $fact, $condition); $match = array(); $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 @(.+)@/", $gedrec, $match)) { $value = "'".$match[1]."'"; } } elseif ($id=="fact") { $value = "\"$fact\""; } elseif ($id=="desc") { $value = "\"$desc\""; } elseif ($id=="generation") { $value = "\"$generation\""; } else { $temp = explode(" ", trim($gedrec)); $level = $temp[0]; if ($level==0) { $level++; } $value = get_gedcom_value($id, $level, $gedrec, "", false); if (empty($value)) { $level++; $value = get_gedcom_value($id, $level, $gedrec, "", false); } $value = "\"".str_replace(array("'", '"'), array("\'", '\"'), $value)."\""; } $condition = str_replace("@$id", $value, $condition); $i++; } $condition = "if ($condition) return true; else return false;"; $ret = @eval($condition); if (!$ret) { $processIfs++; } } /** * XML end element * @see PGVRifSHandler() */ function PGVRifEHandler() { global $processIfs; if ($processIfs>0) $processIfs--; } /** * XML 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 * @see PGVRFootnoteEHandler() */ function PGVRFootnoteSHandler($attrs) { global $printData, $printDataStack, $currentElement, $footnoteElement, $processFootnote, $gedrec, $PGVReportRoot; $match = array(); $id=""; $tag=""; if (preg_match("/[0-9] (.+) @(.+)@/", $gedrec, $match)) { $tag = $match[1]; $id = $match[2]; } if (displayDetailsById($id, $tag)) { array_push($printDataStack, $printData); $printData = true; $style = ""; if (!empty($attrs["style"])) { $style=$attrs["style"]; } $footnoteElement = $currentElement; $currentElement = $PGVReportRoot->createFootnote($style); } else { $printData = false; $processFootnote = false; } } /** * XML end element * Print the collected Footnote data * * @see PGVRFootnoteSHandler() */ function PGVRFootnoteEHandler() { // @deprecated // global $printData, $printDataStack, $currentElement, $footnoteElement, $processFootnote, $gedrec, $pgvreport; global $printData, $printDataStack, $currentElement, $footnoteElement, $processFootnote, $pgvreport; if ($processFootnote) { $printData = array_pop($printDataStack); $temp = trim($currentElement->getValue()); if (strlen($temp)>3) { $pgvreport->addElement($currentElement); } $currentElement = $footnoteElement; } else { $processFootnote = true; } } /** * XML element * * @param array $attrs an array of key value pairs for the attributes */ function PGVRFootnoteTextsSHandler() { global $pgvreport; $temp = "footnotetexts"; $pgvreport->addElement($temp); } /** * XML element Forced line break handler - HTML code * */ function brSHandler() { global $printData, $currentElement, $processGedcoms; if ($printData && ($processGedcoms==0)) $currentElement->addText("
"); } /** * XML element Forced space handler * * @todo add info to wiki - missing function */ function spSHandler() { global $printData, $currentElement, $processGedcoms; if ($printData && ($processGedcoms==0)) $currentElement->addText(" "); } /** * @todo add info * @param array $attrs an array of key value pairs for the attributes */ function PGVRHighlightedImageSHandler($attrs) { global $gedrec, $pgvreport, $PGVReportRoot; $id = ""; $match = array(); if (preg_match("/0 @(.+)@/", $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 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 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"]; if (showFact("OBJE", $id)) { $media = find_highlighted_object($id, WT_GED_ID, $gedrec); if (!empty($media["file"])) { if (preg_match("/(jpg)|(jpeg)|(png)$/i", $media["file"])) { if (file_exists($media["file"])) { $size = findImageSize($media["file"]); if (($width>0) and ($height==0)) { $perc = $width / $size[0]; $height= round($size[1]*$perc); } elseif (($height>0) and ($width==0)) { $perc = $height / $size[1]; $width= round($size[0]*$perc); } else { $width = $size[0]; $height = $size[1]; } $image = $PGVReportRoot->createImage($media["file"], $left, $top, $width, $height, $align, $ln); $pgvreport->addElement($image); } } } } } /** * @todo add info * @param array $attrs an array of key value pairs for the attributes */ function PGVRImageSHandler($attrs) { global $gedrec, $pgvreport, $MEDIA_DIRECTORY, $PGVReportRoot; // 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"]; } } // 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"]; $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 = array(); if (preg_match("/\d OBJE @(.+)@/", $gedrec, $match)) { $orec = find_gedcom_record($match[1], WT_GED_ID); } else { $orec = $gedrec; } if (!empty($orec)) { $fullpath = extract_fullpath($orec); $filename = ""; $filename = extract_filename($fullpath); $filename = $MEDIA_DIRECTORY.$filename; $filename = trim($filename); if (!empty($filename)) { if (preg_match("/(jpg)|(jpeg)|(png)$/i", $filename)) { if (file_exists($filename)) { $size = findImageSize($filename); if (($width > 0) and ($height == 0)) { $perc = $width / $size[0]; $height= round($size[1]*$perc); } elseif (($height > 0) and ($width == 0)) { $perc = $height / $size[1]; $width= round($size[0]*$perc); } else { $width = $size[0]; $height = $size[1]; } $image = $PGVReportRoot->createImage($filename, $left, $top, $width, $height, $align, $ln); $pgvreport->addElement($image); } } } } } else { $filename = $file; if (preg_match("/(jpg)|(jpeg)|(png)|(gif)$/i", $filename)) { if (file_exists($filename)) { $size = findImageSize($filename); if (($width>0) and ($height==0)) { $perc = $width / $size[0]; $height= round($size[1]*$perc); } elseif (($height>0) and ($width==0)) { $perc = $height / $size[1]; $width= round($size[0]*$perc); } else { $width = $size[0]; $height = $size[1]; } $image = $PGVReportRoot->createImage($filename, $left, $top, $width, $height, $align, $ln); $pgvreport->addElement($image); } } } } /** * XML elemnt handler * * @param array $attrs an array of key value pairs for the attributes */ function PGVRLineSHandler($attrs) { global $pgvreport, $PGVReportRoot; // 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 = $PGVReportRoot->createLine($x1, $y1, $x2, $y2); $pgvreport->addElement($line); } /** * XML start elemnt handler * * @see PGVRListEHandler() * @param array $attrs an array of key value pairs for the attributes */ function PGVRListSHandler($attrs) { global $gedrec, $repeats, $repeatBytes, $list, $repeatsStack, $processRepeats, $parser, $vars, $sortby; global $GEDCOM, $TBLPREFIX; $processRepeats++; if ($processRepeats > 1) return; $match = array(); if (isset($attrs["sortby"])) { $sortby = $attrs["sortby"]; if (preg_match("/\\$(\w+)/", $sortby, $match)) { $sortby = $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=WT_DB::prepare( "SELECT CASE new_gedcom WHEN '' THEN old_gedcom ELSE new_gedcom END AS gedcom". " FROM {$TBLPREFIX}change". " WHERE (xref, change_id) IN (". " SELECT xref, MAX(change_id)". " FROM {$TBLPREFIX}change". " WHERE status='pending' AND gedcom_id=?". " GROUP BY xref". " )" )->execute(array(WT_GED_ID))->fetchAll(); $list=array(); foreach ($rows as $row) { $list[]=new GedcomRecord($row->gedcom); } break; case "individual": case "family": $sql_col_prefix=substr($listname, 0, 1)."_"; // i_ for individual, f_ for family, etc. $sql_join=array(); $sql_where=array($sql_col_prefix."file=".WT_GED_ID); $sql_order_by=array(); foreach ($attrs as $attr=>$value) { if ((strpos($attr, "filter")===0) && $value) { // Substitute global vars $value=preg_replace('/\$(\w+)/e', '$vars["\\1"]["id"]', $value); // Convert the various filters into SQL if (preg_match('/^(\w+):DATE (LTE|GTE) (.+)$/', $value, $match)) { $sql_join[]="JOIN {$TBLPREFIX}dates AS {$attr} ON ({$attr}.d_file={$sql_col_prefix}file AND {$attr}.d_gid={$sql_col_prefix}id)"; $sql_where[]="{$attr}.d_fact='{$match[1]}'"; $date=new GedcomDate($match[3]); if ($match[2]=="LTE") { $sql_where[]="{$attr}.d_julianday2<=".$date->minJD(); } else { $sql_where[]="{$attr}.d_julianday1>=".$date->minJD(); } if ($sortby==$match[1]) { $sortby=""; $sql_order_by[]="{$attr}.d_julianday1"; } unset($attrs[$attr]); // This filter has been fully processed } elseif (($listname=="individual") && (preg_match('/^NAME CONTAINS (.*)$/', $value, $match))){ // Do nothing, unless you have to if (($match[1] != "") or ($sortby=="NAME")){ $sql_join[]="JOIN {$TBLPREFIX}name AS {$attr} ON (n_file={$sql_col_prefix}file AND n_id={$sql_col_prefix}id)"; // Search the DB only if there is any name supplied if ($match[1] != ""){ $names = explode(" ", $match[1]); foreach ($names as $name){ $sql_where[]="{$attr}.n_full LIKE ".WT_DB::quote(utf8_strtoupper("%{$name}%")); } } // Let the DB do the name sorting even when no name was entered if ($sortby=="NAME"){ $sortby=""; $sql_order_by[]="{$attr}.n_sort"; } } unset($attrs[$attr]); // This filter has been fully processed } elseif (($listname=="family") && (preg_match('/^NAME CONTAINS (.+)$/', $value, $match))) { // Eventually, family "names" will be stored in pgv_name. Until then, an extra is needed.... $sql_join[]="JOIN {$TBLPREFIX}link AS {$attr}a ON ({$attr}a.l_file={$sql_col_prefix}file AND {$attr}a.l_from={$sql_col_prefix}id)"; $sql_join[]="JOIN {$TBLPREFIX}name AS {$attr}b ON ({$attr}b.n_file={$sql_col_prefix}file AND n_id={$sql_col_prefix}id)"; $sql_where[]="{$attr}a.l_type=IN ('HUSB, 'WIFE')"; $sql_where[]="{$attr}.n_full LIKE ".WT_DB::quote(utf8_strtoupper("%{$match[1]}%")); if ($sortby=="NAME") { $sortby=""; $sql_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 {$TBLPREFIX}places AS {$attr}a ON ({$attr}a.p_file={$sql_col_prefix}file)"; $sql_join[]="JOIN {$TBLPREFIX}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={$sql_col_prefix}id)"; $sql_where[]="{$attr}a.p_place LIKE ".WT_DB::quote(utf8_strtoupper("%{$match[1]}%")); // Don't unset this filter. This is just the first primary PLAC filter to reduce the returned list from the DB } /** * General Purpose DB Filter for Individual and Family Lists * Place any other filter before these filters because they will pick up any filters that has not been processed * Also, do not unset() these two filters. These are just the first primary filters to reduce the returned list from the DB */ elseif (($listname=="individual") and (preg_match('/^(\w*):*(\w*) CONTAINS (.*)$/', $value, $match))){ $query = ""; // Level 1 tag if ($match[1] != "") $query .= "%1 {$match[1]}%"; // Level 2 tag if ($match[2] != "") $query .= "%2 {$match[2]}%"; // Contains what? if ($match[3] != "") $query .= "%{$match[3]}%"; $sql_where[] = "i_gedcom LIKE ".WT_DB::quote(utf8_strtoupper($query)); unset($query); } elseif (($listname=="family") and (preg_match('/^(\w*):*(\w*) CONTAINS (.*)$/', $value, $match))){ $query = ""; // Level 1 tag if ($match[1] != "") $query .= "%1 {$match[1]}%"; // Level 2 tag if ($match[2] != "") $query .= "%2 {$match[2]}%"; // Contains what? if ($match[3] != "") $query .= "%{$match[3]}%"; $sql_where[] = "f_gedcom LIKE ".WT_DB::quote(utf8_strtoupper($query)); unset($query); } else { // TODO: what other filters can we apply in SQL? } } } if ($listname=="family") { $list=search_fams_custom($sql_join, $sql_where, $sql_order_by); } else { $list=search_indis_custom($sql_join, $sql_where, $sql_order_by); } // Clean up the SQL queries - they will not be used again unset($sql_join, $sql_where, $sql_order_by); break; default: die("Invalid list name: $listname"); } $filters = array(); $filters2 = array(); if ((isset($attrs["filter1"])) and (count($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 @(.+)@/", $gedrec, $match)) { $value = "'".$match[1]."'"; } } elseif ($id=="fact") { $value = "'$fact'"; } elseif ($id=="desc") { $value = "'$desc'"; } else { if (preg_match("/\d $id (.+)/", $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 = $vars[$match[1]]["id"]; $val = trim($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: if (!empty($val)) { $filters2[] = array("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 ($list as $key=>$record) { foreach ($filters as $filter) { if (!preg_match("/".$filter."/i", $record->getGedcomRecord())) { unset($list[$key]); break; } } } } if ($filters2) { $mylist = array(); foreach($list as $indi) { $key=$indi->getXref(); $grec=$indi->getGedcomRecord(); $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 = get_gedcom_value($tag, 1, $grec, "", false); //-- 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 = get_sub_record(1, $tag, $grec); } $level = count($tags); switch ($expr) { case "GTE": if ($t=="DATE") { $date1 = new GedcomDate($v); $date2 = new GedcomDate($val); $keep = (GedcomDate::Compare($date1, $date2)>=0); } elseif ($val >= $v) { $keep=true; } break; case "LTE": if ($t=="DATE") { $date1 = new GedcomDate($v); $date2 = new GedcomDate($val); $keep = (GedcomDate::Compare($date1, $date2)<=0); } elseif ($val >= $v) { $keep=true; } break; case "SUBCONTAINS": $v = get_sub_record($level, $level." ".$tag, $grec); if (empty($v) && $tag=="ADDR") { $v = get_sub_record($level+1, ($level+1)." ".$tag, $grec); } if (strripos($v, $val)!==false) { $keep = true; } else { $keep = false; } break; default: if ($v==$val) { $keep=true; } else { $keep = false; } break; } } } if ($keep) $mylist[$key]=$indi; } $list = $mylist; } switch ($sortby) { case "NAME": uasort($list, array("GedcomRecord", "Compare")); break; case "ID": uasort($list, array("GedcomRecord", "CompareId")); break; case "CHAN": uasort($list, array("GedcomRecord", "CompareChanDate")); break; case "BIRT:DATE": uasort($list, array("Person", "CompareBirtDate")); break; case "DEAT:DATE": uasort($list, array("Person", "CompareDeatDate")); break; case "MARR:DATE": uasort($list, array("Family", "CompareMarrDate")); break; default: // unsorted or already sorted by SQL break; } array_push($repeatsStack, array($repeats, $repeatBytes)); $repeatBytes = xml_get_current_line_number($parser)+1; } /** * XML end elemnt handler * @see PGVRListSHandler() */ function PGVRListEHandler() { global $list, $repeats, $repeatsStack, $repeatBytes, $parser, $parserStack, $report, $gedrec, $processRepeats, $list_total, $list_private; $processRepeats--; if ($processRepeats>0) { return; } // Check if there is any list if (count($list) > 0) { // @deprecated // $line = xml_get_current_line_number($parser)-1; $lineoffset = 0; foreach($repeatsStack as $rep) { $lineoffset += $rep[1]; } //-- read the xml from the file $lines = file($report); while((strpos($lines[$lineoffset + $repeatBytes], " 0)) { $lineoffset--; } $lineoffset++; $reportxml = "\n"; $line_nr = $lineoffset + $repeatBytes; // List Level counter $count = 1; while(0 < $count) { if (strpos($lines[$line_nr], "canDisplayDetails()) { $gedrec = $record->getGedcomRecord(); //-- start the sax parser $repeat_parser = xml_parser_create(); $parser = $repeat_parser; //-- make sure everything is case sensitive xml_parser_set_option($repeat_parser, XML_OPTION_CASE_FOLDING, false); //-- set the main element handler functions xml_set_element_handler($repeat_parser, "startElement", "endElement"); //-- set the character data handler xml_set_character_data_handler($repeat_parser, "characterData"); if (!xml_parse($repeat_parser, $reportxml, true)) { printf($reportxml."\nPGVRListEHandler XML error: %s at line %d", xml_error_string(xml_get_error_code($repeat_parser)), xml_get_current_line_number($repeat_parser)); print_r($repeatsStack); debug_print_backtrace(); exit; } xml_parser_free($repeat_parser); } else $list_private++; } // Clean up the GLOBAL list array unset($list); $parser = array_pop($parserStack); $gedrec = $oldgedrec; } $temp = array_pop($repeatsStack); $repeats = $temp[0]; $repeatBytes = $temp[1]; } /** * XML elemnt handler * * Prints the total number of records in a list * The total number is collected from * PGVRList and PGVRRelatives * @param array $attrs an array of key value pairs for the attributes */ function PGVRListTotalSHandler() { global $list_total, $list_private, $currentElement; if (empty($list_total)) $list_total = 0; if ($list_private==0) { $currentElement->addText($list_total); } else { $currentElement->addText(($list_total - $list_private)." / ".$list_total); } } /** * @todo add info * @param array $attrs an array of key value pairs for the attributes * @see PGVRRelativesEHandler() */ function PGVRRelativesSHandler($attrs) { global $repeats, $repeatBytes, $list, $repeatsStack, $processRepeats, $parser, $vars, $sortby; $processRepeats++; if ($processRepeats>1) return; $sortby = "NAME"; if (isset($attrs["sortby"])) $sortby = $attrs["sortby"]; $match = array(); if (preg_match("/\\$(\w+)/", $sortby, $match)) { $sortby = $vars[$match[1]]["id"]; $sortby = trim($sortby); } $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 = $vars[$match[1]]["id"]; $group = trim($group); } $id = ""; if (isset($attrs["id"])) $id = $attrs["id"]; if (preg_match("/\\$(\w+)/", $id, $match)) { $id = $vars[$match[1]]["id"]; $id = trim($id); } $showempty = false; if (isset($attrs["showempty"])) $showempty = $attrs["showempty"]; if (preg_match("/\\$(\w+)/", $showempty, $match)) { $showempty = $vars[$match[1]]["id"]; $showempty = trim($showempty); } $list = array(); $person = Person::getInstance($id); if (!empty($person)) { $list[$id] = $person; switch ($group) { case "child-family": $famids = $person->getChildFamilies(); foreach($famids as $family) { $husband = $family->getHusband(); $wife = $family->getWife(); if (!empty($husband)) { $list[$husband->getXref()] = $husband; } if (!empty($wife)) { $list[$wife->getXref()] = $wife; } $children = $family->getChildren(); foreach($children as $child) { if (!empty($child)) $list[$child->getXref()] = $child; } } break; case "spouse-family": $famids = $person->getSpouseFamilies(); foreach($famids as $family) { $husband = $family->getHusband(); $wife = $family->getWife(); if (!empty($husband)) { $list[$husband->getXref()] = $husband; } if (!empty($wife)) { $list[$wife->getXref()] = $wife; } $children = $family->getChildren(); foreach($children as $child) { if (!empty($child)) $list[$child->getXref()] = $child; } } break; case "direct-ancestors": add_ancestors($list, $id, false, $maxgen, $showempty); break; case "ancestors": add_ancestors($list, $id, true, $maxgen, $showempty); break; case "descendants": $list[$id]->generation = 1; add_descendancy($list, $id, false, $maxgen); break; case "all": add_ancestors($list, $id, true, $maxgen, $showempty); add_descendancy($list, $id, true, $maxgen); break; } } switch ($sortby) { case "NAME": uasort($list, array("GedcomRecord", "Compare")); break; case "ID": uasort($list, array("GedcomRecord", "CompareId")); break; case "BIRT:DATE": uasort($list, array("PGVReportBase", "CompareBirthDate")); break; case "DEAT:DATE": uasort($list, array("PGVReportBase", "CompareDeathDate")); break; case "generation": $newarray = array(); reset($list); $genCounter = 1; while (count($newarray) < count($list)) { foreach ($list as $key => $value) { $generation = $value->generation; if ($generation == $genCounter) { $newarray[$key]->generation=$generation; } } $genCounter++; } $list = $newarray; break; default: // unsorted break; } array_push($repeatsStack, array($repeats, $repeatBytes)); $repeatBytes = xml_get_current_line_number($parser)+1; } /** * XML end elemnt handler * * @see PGVRRelativesSHandler() */ function PGVRRelativesEHandler() { global $list, $repeats, $repeatsStack, $repeatBytes, $parser, $parserStack, $report, $gedrec, $processRepeats, $list_total, $list_private, $generation; $processRepeats--; if ($processRepeats>0) { return; } // Check if there is any relatives if (count($list) > 0) { // @deprecated // $line = xml_get_current_line_number($parser)-1; $lineoffset = 0; foreach($repeatsStack as $rep) { $lineoffset += $rep[1]; } //-- read the xml from the file $lines = file($report); while((strpos($lines[$lineoffset + $repeatBytes], " 0)) { $lineoffset--; } $lineoffset++; $reportxml = "\n"; $line_nr = $lineoffset + $repeatBytes; // Relatives Level counter $count = 1; while(0 < $count) { if (strpos($lines[$line_nr], " $value) { if (isset($value->generation)) { $generation = $value->generation; } if (strpos($key, "empty")===0) { continue; // key can be something like "empty7" } $tmp=GedcomRecord::getInstance($key); $gedrec = $tmp->getGedcomRecord(); //-- start the sax parser $repeat_parser = xml_parser_create(); $parser = $repeat_parser; //-- make sure everything is case sensitive xml_parser_set_option($repeat_parser, XML_OPTION_CASE_FOLDING, false); //-- set the main element handler functions xml_set_element_handler($repeat_parser, "startElement", "endElement"); //-- set the character data handler xml_set_character_data_handler($repeat_parser, "characterData"); if (!xml_parse($repeat_parser, $reportxml, true)) { printf($reportxml."\nPGVRRelativesEHandler XML error: %s at line %d", xml_error_string(xml_get_error_code($repeat_parser)), xml_get_current_line_number($repeat_parser)); print_r($repeatsStack); debug_print_backtrace(); exit; } xml_parser_free($repeat_parser); } // Clean up the GLOBAL list array unset($list); $parser = array_pop($parserStack); $gedrec = $oldgedrec; } $temp = array_pop($repeatsStack); $repeats = $temp[0]; $repeatBytes = $temp[1]; } /** * XML elemnt handler * * Prints the number of generations * @todo no info on wiki * @see PGVRElement::addText() */ function PGVRGenerationSHandler() { global $generation, $currentElement; if (empty($generation)) $generation = 1; $currentElement->addText($generation); } /** * XML elemnt handler * * Has to be placed in an element (header, pageheader, body or footer) * @final * @todo update wiki, this element is missing */ function PGVRNewPageSHandler() { global $pgvreport; $temp = "addpage"; $pgvreport->addElement($temp); } /** * @todo add info * @todo not on wiki * @param array $attrs an array of key value pairs for the attributes * @param string $tag HTML tag name * @see HTMLEHandler() * @see PGVReportBase::createHTML() */ function HTMLSHandler($tag, $attrs) { global $printData, $printDataStack, $pgvreportStack, $pgvreport, $currentElement, $PGVReportRoot; if ($tag=="tempdoc") return; array_push($pgvreportStack, $pgvreport); $pgvreport = $PGVReportRoot->createHTML($tag, $attrs); $currentElement = $pgvreport; array_push($printDataStack, $printData); $printData = true; } /** * @todo add info * @param array $attrs an array of key value pairs for the attributes * @see HTMLSHandler() */ function HTMLEHandler($tag) { global $printData, $printDataStack, $pgvreport, $currentElement, $pgvreportStack; if ($tag=="tempdoc") return; $printData = array_pop($printDataStack); $currentElement = $pgvreport; $pgvreport = array_pop($pgvreportStack); if (!is_null($pgvreport)) $pgvreport->addElement($currentElement); else $pgvreport = $currentElement; } /** * XML start elemnt handler * * @todo add to wiki * @see PGVRTitleEHandler() * @final */ function PGVRTitleSHandler() { global $reportTitle; $reportTitle = true; } /** * XML end elemnt handler * * @see PGVRTitleSHandler() * @final */ function PGVRTitleEHandler() { global $reportTitle; $reportTitle = false; } /** * XML start elemnt handler * * @todo add to wiki * @see PGVRDescriptionEHandler() * @final */ function PGVRDescriptionSHandler() { global $reportDescription; $reportDescription = true; } /** * XML end elemnt handler * * @see PGVRDescriptionSHandler() * @final */ function PGVRDescriptionEHandler() { global $reportDescription; $reportDescription = false; } ?>