summaryrefslogtreecommitdiff
path: root/includes/classes/class_reportbase.php
diff options
context:
space:
mode:
authorVeit Olschinski <veit@olschinski.de>2010-04-05 10:29:41 +0000
committerVeit Olschinski <veit@olschinski.de>2010-04-05 10:29:41 +0000
commit5bc7b36708d272081ffd2df5658ddf12275447dd (patch)
tree7884d88bd634f62d94e0239c911305ac4349dba8 /includes/classes/class_reportbase.php
parent5dbb23df7f03aeb32c6c5a3fa6139dd479f9c0b4 (diff)
downloadwebtrees-5bc7b36708d272081ffd2df5658ddf12275447dd.tar.gz
webtrees-5bc7b36708d272081ffd2df5658ddf12275447dd.tar.bz2
webtrees-5bc7b36708d272081ffd2df5658ddf12275447dd.zip
Diffstat (limited to 'includes/classes/class_reportbase.php')
-rw-r--r--includes/classes/class_reportbase.php3940
1 files changed, 3940 insertions, 0 deletions
diff --git a/includes/classes/class_reportbase.php b/includes/classes/class_reportbase.php
new file mode 100644
index 0000000000..e4d6bf3931
--- /dev/null
+++ b/includes/classes/class_reportbase.php
@@ -0,0 +1,3940 @@
+<?php
+/**
+ * Base Report Generator
+ *
+ * used by the SAX parser to generate reports from the XML report file.
+ *
+ * webtrees: Web based Family History software
+ * Copyright (C) 2010 webtrees development team.
+ *
+ * Derived from PhpGedView
+ * Copyright (C) 2002 to 2009 PGV Development Team. All rights reserved.
+ *
+ * Modifications Copyright (c) 2010 Greg Roach
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * @package webtrees
+ * @subpackage Reports
+ * @version $Id$
+ */
+
+if (!defined('WT_WEBTREES')) {
+ header('HTTP/1.0 403 Forbidden');
+ exit;
+}
+
+/**
+ * Enable HTML code to pass for testing
+ * false = use the old style, HTML disabled
+ * true = use the new style, HTML enabled
+ */
+define("WT_RNEW", false);
+
+define("WT_CLASS_REPORTBASE_PHP", "");
+
+$ascii_langs = array("en", "da", "nl", "fr", "he", "hu", "de", "nn", "es");
+
+//-- setup special characters array to force embedded fonts
+$SpecialOrds = $RTLOrd;
+for($i=195; $i<215; $i++) $SpecialOrds[] = $i;
+
+if (!isset($embed_fonts)) {
+ if (in_array(WT_LOCALE, $ascii_langs)) {
+ $embed_fonts = false;
+ } else {
+ $embed_fonts = true;
+ }
+}
+
+/**
+ * Main PGV Report Class
+ *
+ * Document wide functions and variable defaults that will be inherited of the report modules
+ * @package webtrees
+ * @subpackage Reports
+ */
+class PGVReportBase {
+ /**
+ * Left Margin (expressed in points) Default: 17.99 mm, 0.7083 inch
+ * @see PGVRDocSHandler()
+ * @var float
+ */
+ public $leftmargin = 51;
+ /**
+ * Right Margin (expressed in points) Default: 9.87 mm, 0.389 inch
+ * @see PGVRDocSHandler()
+ * @var float
+ */
+ public $rightmargin = 28;
+ /**
+ * Top Margin (expressed in points) Default: 26.81 mm
+ * @see PGVRDocSHandler()
+ * @var float
+ */
+ public $topmargin = 76;
+ /**
+ * Bottom Margin (expressed in points) Default: 21.6 mm
+ * @see PGVRDocSHandler()
+ * @var float
+ */
+ public $bottommargin = 60;
+ /**
+ * Header Margin (expressed in points) Default: 4.93 mm
+ * @see PGVRDocSHandler()
+ * @var float
+ */
+ public $headermargin = 14;
+ /**
+ * Footer Margin (expressed in points) Default: 9.88 mm, 0.389 inch
+ * @see PGVRDocSHandler()
+ * @var float
+ */
+ public $footermargin = 28;
+
+ /**
+ * Page orientation (portrait, landscape)
+ * @see PGVRDocSHandler()
+ * @var string
+ */
+ public $orientation = "portrait";
+ /**
+ * Page format name
+ * @see PGVRDocSHandler()
+ * @see PGVReportBase::setup()
+ * @var string
+ */
+ public $pageFormat = "A4";
+
+ /**
+ * Height of page format in points
+ * @see PGVRDocSHandler()
+ * @see PGVReportBase::setup()
+ * @var float
+ */
+ public $pageh = 0.0;
+ /**
+ * Width of page format in points
+ * @see PGVRDocSHandler()
+ * @see PGVReportBase::setup()
+ * @var float
+ */
+ public $pagew = 0.0;
+
+ /**
+ * An array of the PGVRStyles elements found in the document
+ * @see PGVRStyleSHandler()
+ * @var array
+ */
+ public $PGVRStyles = array();
+ /**
+ * The default Report font name
+ * @see PGVRStyleSHandler()
+ * @var string
+ */
+ public $defaultFont = "dejavusans";
+ /**
+ * The default Report font size
+ * @see PGVRStyleSHandler()
+ * @var int
+ */
+ public $defaultFontSize = 12;
+
+ /**
+ * Header (H), Page header (PH), Body (B) or Footer (F)
+ * @var string
+ */
+ public $processing = "H";
+
+ /**
+ * RTL Language (false=LTR, true=RTL)
+ * @see PGVReportBase::setup()
+ * @var boolean
+ */
+ public $rtl = false;
+
+ /**
+ * User measure unit.
+ * @var string const
+ */
+ const unit = "pt";
+
+ /**
+ * Character set
+ * @see PGVReportBase::setup()
+ * @var string
+ */
+ public $charset = "UTF-8";
+
+ /**
+ * Show the Generated by... (true=show the text)
+ * @see PGVRDocSHandler()
+ * @var boolean
+ */
+ public $showGenText = true;
+ /**
+ * Generated By... text
+ * @see PGVReportBase::setup()
+ * @var string
+ */
+ public $generatedby = "";
+
+ /**
+ * webtrees URL
+ * @var string const
+ */
+ const pgv_url = WT_WEBTREES_URL;
+
+ /**
+ * The report title
+ * @see PGVReportBase::addTitle()
+ * @var string
+ */
+ public $title = "";
+ /**
+ * Author of the report, the users full name
+ * @var string
+ * @todo add the author support
+ */
+// var $rauthor = "";
+ /**
+ * Keywords
+ * @see PGVReportBase::setup()
+ * @var string
+ */
+ public $rkeywords = "";
+ /**
+ * Report Description / Subject
+ * @see PGVReportBase::addDescription()
+ * @var string
+ */
+ public $rsubject = "";
+
+ /**
+ * Initial Setup - PGVReportBase
+ *
+ * Setting up document wide defaults that will be inherited of the report modules
+ * As DEFAULT A4 and Portrait will be used if not set
+ *
+ * @see PGVRDocSHandler()
+ * @todo add page sizes to wiki
+ */
+ function setup() {
+ global $TEXT_DIRECTION, $META_KEYWORDS;
+
+ // Set RTL direction
+ if ($TEXT_DIRECTION == "rtl") {
+ $this->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("<strong>REPORT ERROR PGVReportBase::setup(): </strong>For custom size pages you must set \"customwidth\" larger then this in the XML file");
+ }
+ if ($this->pageh < 10) {
+ die("<strong>REPORT ERROR PGVReportBase::setup(): </strong>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("<strong>REPORT ERROR PGVReportBase::get_type: </strong> 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("<br />", "&nbsp;"), 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 "</".$this->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:<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 PGVRStyle 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;
+
+ 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
+ *
+ * <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 $borderstyle 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 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("<br />", "&nbsp;"), 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
+ * <var>$printData</var> variable as we encounter entinties in the XML. The stack allows us to
+ * keep track of when to turn <var>$printData</var> 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 <PGVRStyleSHandler /> 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("<strong>REPORT ERROR PGVRStyle: </strong> 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 <PGVRDoc> 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 </PGVRDoc> end elemnt handler
+*
+* @see PGVRDocSHandler()
+*/
+function PGVRDocEHandler() {
+ global $pgvreport;
+ $pgvreport->run();
+}
+
+/**
+* XML <PGVRHeader> 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 <PGVRPageHeader> 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 <PGVRPageHeaderEHandler> 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 <PGVRBodySHandler> start elemnt handler
+*/
+function PGVRBodySHandler() {
+ global $pgvreport;
+ $pgvreport->setProcessing("B");
+}
+
+/**
+* XML <PGVRFooterSHandler> start elemnt handler
+*/
+function PGVRFooterSHandler() {
+ global $pgvreport;
+ $pgvreport->setProcessing("F");
+}
+
+/**
+* XML <PGVRCell> 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 </PGVRCell> end elemnt handler
+*
+* @see PGVRCellSHandler()
+* @final
+*/
+function PGVRCellEHandler() {
+ global $printData, $printDataStack, $currentElement, $pgvreport;
+
+ $printData = array_pop($printDataStack);
+ $pgvreport->addElement($currentElement);
+}
+
+/**
+* XML <PGVRNow /> elemnt handler
+*
+* @see PGVRElement::addText()
+* @final
+*/
+function PGVRNowSHandler() {
+ global $currentElement;
+
+ $g = timestamp_to_gedcom_date(client_time());
+ $currentElement->addText($g->Display());
+}
+
+/**
+* XML <PGVRPageNum /> elemnt handler
+*
+* @see PGVRElement::addText()
+* @final
+*/
+function PGVRPageNumSHandler() {
+ global $currentElement;
+ $currentElement->addText("#PAGENUM#");
+}
+
+/**
+* XML <PGVRTotalPages /> 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 <PGVRTextBoxSHandler> 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
+ * <ul><li>L, T, R, B or combinations: Line style of left, top, right or bottom border.</li></ul>
+ * @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 <PGVRTextBoxEHandler> 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 <PGVRGetPersonName> 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 class=\"starredname\">(.*)<\/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 class=\"starredname\">(.*)<\/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 <PGVRGedcomValue> 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 <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);
+ }
+ }
+ $currentElement->addText($value);
+ }
+ }
+ }
+}
+
+/**
+* XML <PGVRRepeatTag> 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 </ PGVRRepeatTag> 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], "<PGVRRepeatTag")===false) {
+ $lineoffset--;
+ }
+ $lineoffset++;
+ $reportxml = "<tempdoc>\n";
+ $line_nr = $lineoffset + $repeatBytes;
+ // RepeatTag Level counter
+ $count = 1;
+ while(0 < $count) {
+ if (strstr($lines[$line_nr], "<PGVRRepeatTag")!==false) {
+ $count++;
+ } elseif (strstr($lines[$line_nr], "</PGVRRepeatTag")!==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($parserStack, $parser);
+ $oldgedrec = $gedrec;
+// PHP 5.2.3 has a bug with foreach(), so don't use that here, while 5.2.3 is on the market
+ // while() has the fastest execution speed
+ $count = count($repeats);
+ $i = 0;
+ while($i < $count) {
+ $gedrec = $repeats[$i];
+ //-- 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."\nPGVRRepeatTagEHandler 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);
+ $i++;
+ }
+ // Restore original values
+ $gedrec = $oldgedrec;
+ $parser = array_pop($parserStack);
+ }
+ $temp = array_pop($repeatsStack);
+ $repeats = $temp[0];
+ $repeatBytes = $temp[1];
+}
+
+/**
+* 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.
+* $ pgv_lang[]
+* $ factarray[]
+* $ language_settings[]
+*
+*
+* Or retrieve variables preset with <PGVRSetVar> 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("<strong>REPORT ERROR PGVRvar: </strong> 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("<strong>REPORT ERROR PGVRvarLetter: </strong> 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 </ PGVRFacts> 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], "<PGVRFacts ")) === false) {
+ $lineoffset--;
+ }
+ $lineoffset++;
+ $reportxml = "<tempdoc>\n";
+ $i = $line + $lineoffset;
+ $line_nr = $repeatBytes + $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($parserStack, $parser);
+ $oldgedrec = $gedrec;
+ $count = count($repeats);
+ $i = 0;
+ $match = array();
+ while($i < $count) {
+ $gedrec = $repeats[$i];
+ $fact = "";
+ $desc = "";
+ if (preg_match("/1 (\w+)(.*)/", $gedrec, $match)) {
+ $fact = $match[1];
+ if ($fact=="EVEN" or $fact=="FACT") {
+ $tmatch = array();
+ if (preg_match("/2 TYPE (.+)/", $gedrec, $tmatch)) {
+ $type = trim($tmatch[1]);
+ } else {
+ $type = " ";
+ }
+ }
+ $desc = trim($match[2]);
+ $desc .= get_cont(2, $gedrec);
+ }
+ //-- 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)) {
+ die(sprintf($reportxml."\nPGVRFactsEHandler 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
+ $parser = array_pop($parserStack);
+ $gedrec = $oldgedrec;
+ }
+ $temp = array_pop($repeatsStack);
+ $repeats = $temp[0];
+ $repeatBytes = $temp[1];
+}
+
+/**
+* Setting upp or changing variables in the XML
+* The XML variable name and value is stored in the global variable $vars
+* @param array $attrs an array of key value pairs for the attributes
+*/
+function PGVRSetVarSHandler($attrs) {
+ global $vars, $gedrec, $fact, $desc, $type, $generation;
+
+ if (empty($attrs["name"])) {
+ die("<strong>REPORT ERROR PGVRvar: </strong> 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 <PGVRif > 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 <PGVRif /> end element
+* @see PGVRifSHandler()
+*/
+function PGVRifEHandler() {
+ global $processIfs;
+ if ($processIfs>0) $processIfs--;
+}
+
+/**
+* XML <PGVRFootnote > 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 <PGVRFootnote /> 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 <PGVRFootnoteTexts /> 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("<br />");
+}
+
+/**
+* XML <sp />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 <PGVRLine> 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 <PGVRList> 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 $pgv_changes, $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":
+ $list=array();
+ foreach ($pgv_changes as $changes) {
+ $change=end($changes);
+ if ($change["gedcom"]==$GEDCOM) {
+ switch ($change["type"]) {
+ case "replace":
+ // Update - show the latest version of the record
+ $list[]=new GedcomRecord($change["undo"]);
+ break;
+ case "delete":
+ // Delete - show the last accepted version of the record
+ $list[]=GedcomRecord::getInstance($change["gid"]);
+ break;
+ }
+ }
+ }
+ 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 <PGVRList> 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], "<PGVRList")===false) && (($lineoffset + $repeatBytes) > 0)) {
+ $lineoffset--;
+ }
+ $lineoffset++;
+ $reportxml = "<tempdoc>\n";
+ $line_nr = $lineoffset + $repeatBytes;
+ // List Level counter
+ $count = 1;
+ while(0 < $count) {
+ if (strpos($lines[$line_nr], "<PGVRList")!==false) {
+ $count++;
+ } elseif (strpos($lines[$line_nr], "</PGVRList")!==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($parserStack, $parser);
+ $oldgedrec = $gedrec;
+
+ $list_total = count($list);
+ $list_private = 0;
+ foreach ($list as $record) {
+ if ($record->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 <PGVRListTotal> 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 </ PGVRRelatives> 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], "<PGVRRelatives")===false) && (($lineoffset + $repeatBytes) > 0)) {
+ $lineoffset--;
+ }
+ $lineoffset++;
+ $reportxml = "<tempdoc>\n";
+ $line_nr = $lineoffset + $repeatBytes;
+ // Relatives Level counter
+ $count = 1;
+ while(0 < $count) {
+ if (strpos($lines[$line_nr], "<PGVRRelatives")!==false) {
+ $count++;
+ } elseif (strpos($lines[$line_nr], "</PGVRRelatives")!==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($parserStack, $parser);
+ $oldgedrec = $gedrec;
+
+ $list_total = count($list);
+ $list_private = 0;
+ foreach($list as $key => $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 <PGVRGeneration /> 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 <PGVRNewPage /> 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 <PGVRTitleSHandler> start elemnt handler
+*
+* @todo add to wiki
+* @see PGVRTitleEHandler()
+* @final
+*/
+function PGVRTitleSHandler() {
+ global $reportTitle;
+ $reportTitle = true;
+}
+
+/**
+* XML </PGVRTitleEHandler> end elemnt handler
+*
+* @see PGVRTitleSHandler()
+* @final
+*/
+function PGVRTitleEHandler() {
+ global $reportTitle;
+ $reportTitle = false;
+}
+
+/**
+* XML <PGVRDescriptionSHandler> start elemnt handler
+*
+* @todo add to wiki
+* @see PGVRDescriptionEHandler()
+* @final
+*/
+function PGVRDescriptionSHandler() {
+ global $reportDescription;
+ $reportDescription = true;
+}
+
+/**
+* XML </PGVRDescriptionEHandler> end elemnt handler
+*
+* @see PGVRDescriptionSHandler()
+* @final
+*/
+function PGVRDescriptionEHandler() {
+ global $reportDescription;
+ $reportDescription = false;
+}
+?>