summaryrefslogtreecommitdiff
path: root/app/Report/ReportParserGenerate.php
diff options
context:
space:
mode:
authorGreg Roach <fisharebest@webtrees.net>2018-07-16 08:20:33 +0100
committerGreg Roach <fisharebest@webtrees.net>2018-07-16 08:20:33 +0100
commitc1010eda29c0909ed4d5d463f32d32bfefdd4dfe (patch)
treefbb656ebc014aa1295ac8e6176f41e89f94b91e7 /app/Report/ReportParserGenerate.php
parent782f08d9bd2bfa06635da947ee34f8e1afd65088 (diff)
downloadwebtrees-c1010eda29c0909ed4d5d463f32d32bfefdd4dfe.tar.gz
webtrees-c1010eda29c0909ed4d5d463f32d32bfefdd4dfe.tar.bz2
webtrees-c1010eda29c0909ed4d5d463f32d32bfefdd4dfe.zip
Use PSR2 code style
Diffstat (limited to 'app/Report/ReportParserGenerate.php')
-rw-r--r--app/Report/ReportParserGenerate.php5233
1 files changed, 2694 insertions, 2539 deletions
diff --git a/app/Report/ReportParserGenerate.php b/app/Report/ReportParserGenerate.php
index ba74ed910e..2267f52af8 100644
--- a/app/Report/ReportParserGenerate.php
+++ b/app/Report/ReportParserGenerate.php
@@ -35,2730 +35,2885 @@ use Fisharebest\Webtrees\Tree;
/**
* Class ReportParserGenerate - parse a report.xml file and generate the report.
*/
-class ReportParserGenerate extends ReportParserBase {
- /** @var bool Are we collecting data from <Footnote> elements */
- private $process_footnote = true;
+class ReportParserGenerate extends ReportParserBase
+{
+ /** @var bool Are we collecting data from <Footnote> elements */
+ private $process_footnote = true;
- /** @var bool Are we currently outputing data? */
- private $print_data = false;
+ /** @var bool Are we currently outputing data? */
+ private $print_data = false;
- /** @var bool[] Push-down stack of $print_data */
- private $print_data_stack = [];
+ /** @var bool[] Push-down stack of $print_data */
+ private $print_data_stack = [];
- /** @var int Are we processing GEDCOM data */
- private $process_gedcoms = 0;
+ /** @var int Are we processing GEDCOM data */
+ private $process_gedcoms = 0;
- /** @var int Are we processing conditionals */
- private $process_ifs = 0;
+ /** @var int Are we processing conditionals */
+ private $process_ifs = 0;
- /** @var int Are we processing repeats*/
- private $process_repeats = 0;
+ /** @var int Are we processing repeats */
+ private $process_repeats = 0;
- /** @var int Quantity of data to repeat during loops */
- private $repeat_bytes = 0;
+ /** @var int Quantity of data to repeat during loops */
+ private $repeat_bytes = 0;
- /** @var array[] Repeated data when iterating over loops */
- private $repeats = [];
+ /** @var array[] Repeated data when iterating over loops */
+ private $repeats = [];
- /** @var array[] Nested repeating data */
- private $repeats_stack = [];
+ /** @var array[] Nested repeating data */
+ private $repeats_stack = [];
- /** @var ReportBase[] Nested repeating data */
- private $wt_report_stack = [];
+ /** @var ReportBase[] Nested repeating data */
+ private $wt_report_stack = [];
- /** @var resource Nested repeating data */
- private $parser;
+ /** @var resource Nested repeating data */
+ private $parser;
- /** @var resource[] Nested repeating data */
- private $parser_stack = [];
+ /** @var resource[] Nested repeating data */
+ private $parser_stack = [];
- /** @var string The current GEDCOM record */
- private $gedrec = '';
+ /** @var string The current GEDCOM record */
+ private $gedrec = '';
- /** @var string[] Nested GEDCOM records */
- private $gedrec_stack = [];
+ /** @var string[] Nested GEDCOM records */
+ private $gedrec_stack = [];
- /** @var ReportBaseElement The currently processed element */
- private $current_element;
+ /** @var ReportBaseElement The currently processed element */
+ private $current_element;
- /** @var ReportBaseElement The currently processed element */
- private $footnote_element;
+ /** @var ReportBaseElement The currently processed element */
+ private $footnote_element;
- /** @var string The GEDCOM fact currently being processed */
- private $fact = '';
+ /** @var string The GEDCOM fact currently being processed */
+ private $fact = '';
- /** @var string The GEDCOM value currently being processed */
- private $desc = '';
+ /** @var string The GEDCOM value currently being processed */
+ private $desc = '';
- /** @var string The GEDCOM type currently being processed */
- private $type = '';
+ /** @var string The GEDCOM type currently being processed */
+ private $type = '';
- /** @var int The current generational level */
- private $generation = 1;
+ /** @var int The current generational level */
+ private $generation = 1;
- /** @var array Source data for processing lists */
- private $list = [];
+ /** @var array Source data for processing lists */
+ private $list = [];
- /** @var int Number of items in lists */
- private $list_total = 0;
+ /** @var int Number of items in lists */
+ private $list_total = 0;
- /** @var int Number of items filtered from lists */
- private $list_private = 0;
+ /** @var int Number of items filtered from lists */
+ private $list_private = 0;
- /** @var string The filename of the XML report */
- protected $report;
+ /** @var string The filename of the XML report */
+ protected $report;
- /** @var ReportBase A factory for creating report elements */
- private $report_root;
+ /** @var ReportBase A factory for creating report elements */
+ private $report_root;
- /** @var ReportBase Nested report elements */
- private $wt_report;
+ /** @var ReportBase Nested report elements */
+ private $wt_report;
- /** @var string[][] Variables defined in the report at run-time */
- private $vars;
+ /** @var string[][] Variables defined in the report at run-time */
+ private $vars;
- /** @var Tree The current tree */
- private $tree;
+ /** @var Tree The current tree */
+ private $tree;
- /**
- * Create a parser for a report
- *
- * @param string $report The XML filename
- * @param ReportBase $report_root
- * @param string[][] $vars
- * @param Tree $tree
- */
- public function __construct($report, ReportBase $report_root, array $vars, Tree $tree) {
- $this->report = $report;
- $this->report_root = $report_root;
- $this->wt_report = $report_root;
- $this->current_element = new ReportBaseElement;
- $this->vars = $vars;
- $this->tree = $tree;
+ /**
+ * Create a parser for a report
+ *
+ * @param string $report The XML filename
+ * @param ReportBase $report_root
+ * @param string[][] $vars
+ * @param Tree $tree
+ */
+ public function __construct($report, ReportBase $report_root, array $vars, Tree $tree)
+ {
+ $this->report = $report;
+ $this->report_root = $report_root;
+ $this->wt_report = $report_root;
+ $this->current_element = new ReportBaseElement;
+ $this->vars = $vars;
+ $this->tree = $tree;
- parent::__construct($report, $report_root, $vars, $tree);
- }
+ parent::__construct($report, $report_root, $vars, $tree);
+ }
- /**
- * XML start element handler
- *
- * This function is called whenever a starting element is reached
- * The element handler will be called if found, otherwise it must be HTML
- *
- * @param resource $parser the resource handler for the XML parser
- * @param string $name the name of the XML element parsed
- * @param array $attrs an array of key value pairs for the attributes
- */
- protected function startElement($parser, $name, $attrs) {
- $newattrs = [];
+ /**
+ * XML start element handler
+ *
+ * This function is called whenever a starting element is reached
+ * The element handler will be called if found, otherwise it must be HTML
+ *
+ * @param resource $parser the resource handler for the XML parser
+ * @param string $name the name of the XML element parsed
+ * @param array $attrs an array of key value pairs for the attributes
+ */
+ protected function startElement($parser, $name, $attrs)
+ {
+ $newattrs = [];
- foreach ($attrs as $key => $value) {
- if (preg_match("/^\\$(\w+)$/", $value, $match)) {
- if ((isset($this->vars[$match[1]]['id'])) && (!isset($this->vars[$match[1]]['gedcom']))) {
- $value = $this->vars[$match[1]]['id'];
- }
- }
- $newattrs[$key] = $value;
- }
- $attrs = $newattrs;
- if ($this->process_footnote && ($this->process_ifs === 0 || $name === 'if') && ($this->process_gedcoms === 0 || $name === 'Gedcom') && ($this->process_repeats === 0 || $name === 'Facts' || $name === 'RepeatTag')) {
- $start_method = $name . 'StartHandler';
- $end_method = $name . 'EndHandler';
- if (method_exists($this, $start_method)) {
- $this->$start_method($attrs);
- } elseif (!method_exists($this, $end_method)) {
- $this->htmlStartHandler($name, $attrs);
- }
- }
- }
+ foreach ($attrs as $key => $value) {
+ if (preg_match("/^\\$(\w+)$/", $value, $match)) {
+ if ((isset($this->vars[$match[1]]['id'])) && (!isset($this->vars[$match[1]]['gedcom']))) {
+ $value = $this->vars[$match[1]]['id'];
+ }
+ }
+ $newattrs[$key] = $value;
+ }
+ $attrs = $newattrs;
+ if ($this->process_footnote && ($this->process_ifs === 0 || $name === 'if') && ($this->process_gedcoms === 0 || $name === 'Gedcom') && ($this->process_repeats === 0 || $name === 'Facts' || $name === 'RepeatTag')) {
+ $start_method = $name . 'StartHandler';
+ $end_method = $name . 'EndHandler';
+ if (method_exists($this, $start_method)) {
+ $this->$start_method($attrs);
+ } elseif (!method_exists($this, $end_method)) {
+ $this->htmlStartHandler($name, $attrs);
+ }
+ }
+ }
- /**
- * XML end element handler
- *
- * This function is called whenever an ending element is reached
- * The element handler will be called if found, otherwise it must be HTML
- *
- * @param resource $parser the resource handler for the XML parser
- * @param string $name the name of the XML element parsed
- */
- protected function endElement($parser, $name) {
- if (($this->process_footnote || $name === 'Footnote') && ($this->process_ifs === 0 || $name === 'if') && ($this->process_gedcoms === 0 || $name === 'Gedcom') && ($this->process_repeats === 0 || $name === 'Facts' || $name === 'RepeatTag' || $name === 'List' || $name === 'Relatives')) {
- $start_method = $name . 'StartHandler';
- $end_method = $name . 'EndHandler';
- if (method_exists($this, $end_method)) {
- $this->$end_method();
- } elseif (!method_exists($this, $start_method)) {
- $this->htmlEndHandler($name);
- }
- }
- }
+ /**
+ * XML end element handler
+ *
+ * This function is called whenever an ending element is reached
+ * The element handler will be called if found, otherwise it must be HTML
+ *
+ * @param resource $parser the resource handler for the XML parser
+ * @param string $name the name of the XML element parsed
+ */
+ protected function endElement($parser, $name)
+ {
+ if (($this->process_footnote || $name === 'Footnote') && ($this->process_ifs === 0 || $name === 'if') && ($this->process_gedcoms === 0 || $name === 'Gedcom') && ($this->process_repeats === 0 || $name === 'Facts' || $name === 'RepeatTag' || $name === 'List' || $name === 'Relatives')) {
+ $start_method = $name . 'StartHandler';
+ $end_method = $name . 'EndHandler';
+ if (method_exists($this, $end_method)) {
+ $this->$end_method();
+ } elseif (!method_exists($this, $start_method)) {
+ $this->htmlEndHandler($name);
+ }
+ }
+ }
- /**
- * XML character data handler
- *
- * @param resource $parser the resource handler for the XML parser
- * @param string $data the name of the XML element parsed
- */
- protected function characterData($parser, $data) {
- if ($this->print_data && $this->process_gedcoms === 0 && $this->process_ifs === 0 && $this->process_repeats === 0) {
- $this->current_element->addText($data);
- }
- }
+ /**
+ * XML character data handler
+ *
+ * @param resource $parser the resource handler for the XML parser
+ * @param string $data the name of the XML element parsed
+ */
+ protected function characterData($parser, $data)
+ {
+ if ($this->print_data && $this->process_gedcoms === 0 && $this->process_ifs === 0 && $this->process_repeats === 0) {
+ $this->current_element->addText($data);
+ }
+ }
- /**
- * XML <style>
- *
- * @param array $attrs an array of key value pairs for the attributes
- */
- private function styleStartHandler($attrs) {
- if (empty($attrs['name'])) {
- throw new \DomainException('REPORT ERROR Style: The "name" of the style is missing or not set in the XML file.');
- }
+ /**
+ * XML <style>
+ *
+ * @param array $attrs an array of key value pairs for the attributes
+ */
+ private function styleStartHandler($attrs)
+ {
+ if (empty($attrs['name'])) {
+ throw new \DomainException('REPORT ERROR Style: The "name" of the style is missing or not set in the XML file.');
+ }
- // array Style that will be passed on
- $s = [];
+ // array Style that will be passed on
+ $s = [];
- // string Name af the style
- $s['name'] = $attrs['name'];
+ // string Name af the style
+ $s['name'] = $attrs['name'];
- // string Name of the DEFAULT font
- $s['font'] = $this->wt_report->defaultFont;
- if (!empty($attrs['font'])) {
- $s['font'] = $attrs['font'];
- }
+ // string Name of the DEFAULT font
+ $s['font'] = $this->wt_report->defaultFont;
+ if (!empty($attrs['font'])) {
+ $s['font'] = $attrs['font'];
+ }
- // int The size of the font in points
- $s['size'] = $this->wt_report->defaultFontSize;
- if (!empty($attrs['size'])) {
- $s['size'] = (int) $attrs['size'];
- } // Get it as int to ignore all decimal points or text (if any text then int(0))
+ // int The size of the font in points
+ $s['size'] = $this->wt_report->defaultFontSize;
+ if (!empty($attrs['size'])) {
+ $s['size'] = (int)$attrs['size'];
+ } // Get it as int to ignore all decimal points or text (if any text then int(0))
- // string B: bold, I: italic, U: underline, D: line trough, The default value is regular.
- $s['style'] = '';
- if (!empty($attrs['style'])) {
- $s['style'] = $attrs['style'];
- }
+ // string B: bold, I: italic, U: underline, D: line trough, The default value is regular.
+ $s['style'] = '';
+ if (!empty($attrs['style'])) {
+ $s['style'] = $attrs['style'];
+ }
- $this->wt_report->addStyle($s);
- }
+ $this->wt_report->addStyle($s);
+ }
- /**
- * XML <Doc>
- *
- * Sets up the basics of the document proparties
- *
- * @param array $attrs an array of key value pairs for the attributes
- */
- private function docStartHandler($attrs) {
- $this->parser = $this->xml_parser;
+ /**
+ * XML <Doc>
+ *
+ * Sets up the basics of the document proparties
+ *
+ * @param array $attrs an array of key value pairs for the attributes
+ */
+ private function docStartHandler($attrs)
+ {
+ $this->parser = $this->xml_parser;
- // Custom page width
- if (!empty($attrs['customwidth'])) {
- $this->wt_report->pagew = (int) $attrs['customwidth'];
- } // Get it as int to ignore all decimal points or text (if any text then int(0))
- // Custom Page height
- if (!empty($attrs['customheight'])) {
- $this->wt_report->pageh = (int) $attrs['customheight'];
- } // Get it as int to ignore all decimal points or text (if any text then int(0))
+ // Custom page width
+ if (!empty($attrs['customwidth'])) {
+ $this->wt_report->pagew = (int)$attrs['customwidth'];
+ } // Get it as int to ignore all decimal points or text (if any text then int(0))
+ // Custom Page height
+ if (!empty($attrs['customheight'])) {
+ $this->wt_report->pageh = (int)$attrs['customheight'];
+ } // Get it as int to ignore all decimal points or text (if any text then int(0))
- // Left Margin
- if (isset($attrs['leftmargin'])) {
- if ($attrs['leftmargin'] === '0') {
- $this->wt_report->leftmargin = 0;
- } elseif (!empty($attrs['leftmargin'])) {
- $this->wt_report->leftmargin = (int) $attrs['leftmargin']; // Get it as int to ignore all decimal points or text (if any text then int(0))
- }
- }
- // Right Margin
- if (isset($attrs['rightmargin'])) {
- if ($attrs['rightmargin'] === '0') {
- $this->wt_report->rightmargin = 0;
- } elseif (!empty($attrs['rightmargin'])) {
- $this->wt_report->rightmargin = (int) $attrs['rightmargin']; // Get it as int to ignore all decimal points or text (if any text then int(0))
- }
- }
- // Top Margin
- if (isset($attrs['topmargin'])) {
- if ($attrs['topmargin'] === '0') {
- $this->wt_report->topmargin = 0;
- } elseif (!empty($attrs['topmargin'])) {
- $this->wt_report->topmargin = (int) $attrs['topmargin']; // Get it as int to ignore all decimal points or text (if any text then int(0))
- }
- }
- // Bottom Margin
- if (isset($attrs['bottommargin'])) {
- if ($attrs['bottommargin'] === '0') {
- $this->wt_report->bottommargin = 0;
- } elseif (!empty($attrs['bottommargin'])) {
- $this->wt_report->bottommargin = (int) $attrs['bottommargin']; // Get it as int to ignore all decimal points or text (if any text then int(0))
- }
- }
- // Header Margin
- if (isset($attrs['headermargin'])) {
- if ($attrs['headermargin'] === '0') {
- $this->wt_report->headermargin = 0;
- } elseif (!empty($attrs['headermargin'])) {
- $this->wt_report->headermargin = (int) $attrs['headermargin']; // Get it as int to ignore all decimal points or text (if any text then int(0))
- }
- }
- // Footer Margin
- if (isset($attrs['footermargin'])) {
- if ($attrs['footermargin'] === '0') {
- $this->wt_report->footermargin = 0;
- } elseif (!empty($attrs['footermargin'])) {
- $this->wt_report->footermargin = (int) $attrs['footermargin']; // Get it as int to ignore all decimal points or text (if any text then int(0))
- }
- }
+ // Left Margin
+ if (isset($attrs['leftmargin'])) {
+ if ($attrs['leftmargin'] === '0') {
+ $this->wt_report->leftmargin = 0;
+ } elseif (!empty($attrs['leftmargin'])) {
+ $this->wt_report->leftmargin = (int)$attrs['leftmargin']; // Get it as int to ignore all decimal points or text (if any text then int(0))
+ }
+ }
+ // Right Margin
+ if (isset($attrs['rightmargin'])) {
+ if ($attrs['rightmargin'] === '0') {
+ $this->wt_report->rightmargin = 0;
+ } elseif (!empty($attrs['rightmargin'])) {
+ $this->wt_report->rightmargin = (int)$attrs['rightmargin']; // Get it as int to ignore all decimal points or text (if any text then int(0))
+ }
+ }
+ // Top Margin
+ if (isset($attrs['topmargin'])) {
+ if ($attrs['topmargin'] === '0') {
+ $this->wt_report->topmargin = 0;
+ } elseif (!empty($attrs['topmargin'])) {
+ $this->wt_report->topmargin = (int)$attrs['topmargin']; // Get it as int to ignore all decimal points or text (if any text then int(0))
+ }
+ }
+ // Bottom Margin
+ if (isset($attrs['bottommargin'])) {
+ if ($attrs['bottommargin'] === '0') {
+ $this->wt_report->bottommargin = 0;
+ } elseif (!empty($attrs['bottommargin'])) {
+ $this->wt_report->bottommargin = (int)$attrs['bottommargin']; // Get it as int to ignore all decimal points or text (if any text then int(0))
+ }
+ }
+ // Header Margin
+ if (isset($attrs['headermargin'])) {
+ if ($attrs['headermargin'] === '0') {
+ $this->wt_report->headermargin = 0;
+ } elseif (!empty($attrs['headermargin'])) {
+ $this->wt_report->headermargin = (int)$attrs['headermargin']; // Get it as int to ignore all decimal points or text (if any text then int(0))
+ }
+ }
+ // Footer Margin
+ if (isset($attrs['footermargin'])) {
+ if ($attrs['footermargin'] === '0') {
+ $this->wt_report->footermargin = 0;
+ } elseif (!empty($attrs['footermargin'])) {
+ $this->wt_report->footermargin = (int)$attrs['footermargin']; // Get it as int to ignore all decimal points or text (if any text then int(0))
+ }
+ }
- // Page Orientation
- if (!empty($attrs['orientation'])) {
- if ($attrs['orientation'] == 'landscape') {
- $this->wt_report->orientation = 'landscape';
- } elseif ($attrs['orientation'] == 'portrait') {
- $this->wt_report->orientation = 'portrait';
- }
- }
- // Page Size
- if (!empty($attrs['pageSize'])) {
- $this->wt_report->pageFormat = strtoupper($attrs['pageSize']);
- }
+ // Page Orientation
+ if (!empty($attrs['orientation'])) {
+ if ($attrs['orientation'] == 'landscape') {
+ $this->wt_report->orientation = 'landscape';
+ } elseif ($attrs['orientation'] == 'portrait') {
+ $this->wt_report->orientation = 'portrait';
+ }
+ }
+ // Page Size
+ if (!empty($attrs['pageSize'])) {
+ $this->wt_report->pageFormat = strtoupper($attrs['pageSize']);
+ }
- // Show Generated By...
- if (isset($attrs['showGeneratedBy'])) {
- if ($attrs['showGeneratedBy'] === '0') {
- $this->wt_report->showGenText = false;
- } elseif ($attrs['showGeneratedBy'] === '1') {
- $this->wt_report->showGenText = true;
- }
- }
+ // Show Generated By...
+ if (isset($attrs['showGeneratedBy'])) {
+ if ($attrs['showGeneratedBy'] === '0') {
+ $this->wt_report->showGenText = false;
+ } elseif ($attrs['showGeneratedBy'] === '1') {
+ $this->wt_report->showGenText = true;
+ }
+ }
- $this->wt_report->setup();
- }
+ $this->wt_report->setup();
+ }
- /**
- * XML </Doc>
- */
- private function docEndHandler() {
- $this->wt_report->run();
- }
+ /**
+ * XML </Doc>
+ */
+ private function docEndHandler()
+ {
+ $this->wt_report->run();
+ }
- /**
- * XML <Header>
- */
- private function headerStartHandler() {
- // Clear the Header before any new elements are added
- $this->wt_report->clearHeader();
- $this->wt_report->setProcessing('H');
- }
+ /**
+ * XML <Header>
+ */
+ private function headerStartHandler()
+ {
+ // Clear the Header before any new elements are added
+ $this->wt_report->clearHeader();
+ $this->wt_report->setProcessing('H');
+ }
- /**
- * XML <PageHeader>
- */
- private function pageHeaderStartHandler() {
- array_push($this->print_data_stack, $this->print_data);
- $this->print_data = false;
- array_push($this->wt_report_stack, $this->wt_report);
- $this->wt_report = $this->report_root->createPageHeader();
- }
+ /**
+ * XML <PageHeader>
+ */
+ private function pageHeaderStartHandler()
+ {
+ array_push($this->print_data_stack, $this->print_data);
+ $this->print_data = false;
+ array_push($this->wt_report_stack, $this->wt_report);
+ $this->wt_report = $this->report_root->createPageHeader();
+ }
- /**
- * XML <pageHeaderEndHandler>
- */
- private function pageHeaderEndHandler() {
- $this->print_data = array_pop($this->print_data_stack);
- $this->current_element = $this->wt_report;
- $this->wt_report = array_pop($this->wt_report_stack);
- $this->wt_report->addElement($this->current_element);
- }
+ /**
+ * XML <pageHeaderEndHandler>
+ */
+ private function pageHeaderEndHandler()
+ {
+ $this->print_data = array_pop($this->print_data_stack);
+ $this->current_element = $this->wt_report;
+ $this->wt_report = array_pop($this->wt_report_stack);
+ $this->wt_report->addElement($this->current_element);
+ }
- /**
- * XML <bodyStartHandler>
- */
- private function bodyStartHandler() {
- $this->wt_report->setProcessing('B');
- }
+ /**
+ * XML <bodyStartHandler>
+ */
+ private function bodyStartHandler()
+ {
+ $this->wt_report->setProcessing('B');
+ }
- /**
- * XML <footerStartHandler>
- */
- private function footerStartHandler() {
- $this->wt_report->setProcessing('F');
- }
+ /**
+ * XML <footerStartHandler>
+ */
+ private function footerStartHandler()
+ {
+ $this->wt_report->setProcessing('F');
+ }
- /**
- * XML <Cell>
- *
- * @param array $attrs an array of key value pairs for the attributes
- */
- private function cellStartHandler($attrs) {
- // string The text alignment of the text in this box.
- $align = '';
- if (!empty($attrs['align'])) {
- $align = $attrs['align'];
- // RTL supported left/right alignment
- if ($align == 'rightrtl') {
- if ($this->wt_report->rtl) {
- $align = 'left';
- } else {
- $align = 'right';
- }
- } elseif ($align == 'leftrtl') {
- if ($this->wt_report->rtl) {
- $align = 'right';
- } else {
- $align = 'left';
- }
- }
- }
+ /**
+ * XML <Cell>
+ *
+ * @param array $attrs an array of key value pairs for the attributes
+ */
+ private function cellStartHandler($attrs)
+ {
+ // string The text alignment of the text in this box.
+ $align = '';
+ if (!empty($attrs['align'])) {
+ $align = $attrs['align'];
+ // RTL supported left/right alignment
+ if ($align == 'rightrtl') {
+ if ($this->wt_report->rtl) {
+ $align = 'left';
+ } else {
+ $align = 'right';
+ }
+ } elseif ($align == 'leftrtl') {
+ if ($this->wt_report->rtl) {
+ $align = 'right';
+ } else {
+ $align = 'left';
+ }
+ }
+ }
- // string The color to fill the background of this cell
- $bgcolor = '';
- if (!empty($attrs['bgcolor'])) {
- $bgcolor = $attrs['bgcolor'];
- }
+ // string The color to fill the background of this cell
+ $bgcolor = '';
+ if (!empty($attrs['bgcolor'])) {
+ $bgcolor = $attrs['bgcolor'];
+ }
- // int Whether or not the background should be painted
- $fill = 1;
- if (isset($attrs['fill'])) {
- if ($attrs['fill'] === '0') {
- $fill = 0;
- } elseif ($attrs['fill'] === '1') {
- $fill = 1;
- }
- }
+ // int Whether or not the background should be painted
+ $fill = 1;
+ if (isset($attrs['fill'])) {
+ if ($attrs['fill'] === '0') {
+ $fill = 0;
+ } elseif ($attrs['fill'] === '1') {
+ $fill = 1;
+ }
+ }
- $reseth = true;
- // boolean if true reset the last cell height (default true)
- if (isset($attrs['reseth'])) {
- if ($attrs['reseth'] === '0') {
- $reseth = false;
- } elseif ($attrs['reseth'] === '1') {
- $reseth = true;
- }
- }
+ $reseth = true;
+ // boolean if true reset the last cell height (default true)
+ if (isset($attrs['reseth'])) {
+ if ($attrs['reseth'] === '0') {
+ $reseth = false;
+ } elseif ($attrs['reseth'] === '1') {
+ $reseth = true;
+ }
+ }
- // mixed Whether or not a border should be printed around this box
- $border = 0;
- if (!empty($attrs['border'])) {
- $border = $attrs['border'];
- }
- // string Border color in HTML code
- $bocolor = '';
- if (!empty($attrs['bocolor'])) {
- $bocolor = $attrs['bocolor'];
- }
+ // mixed Whether or not a border should be printed around this box
+ $border = 0;
+ if (!empty($attrs['border'])) {
+ $border = $attrs['border'];
+ }
+ // string Border color in HTML code
+ $bocolor = '';
+ if (!empty($attrs['bocolor'])) {
+ $bocolor = $attrs['bocolor'];
+ }
- // int Cell height (expressed in points) The starting height of this cell. If the text wraps the height will automatically be adjusted.
- $height = 0;
- if (!empty($attrs['height'])) {
- $height = (int) $attrs['height'];
- }
- // int Cell width (expressed in points) Setting the width to 0 will make it the width from the current location to the right margin.
- $width = 0;
- if (!empty($attrs['width'])) {
- $width = (int) $attrs['width'];
- }
+ // int Cell height (expressed in points) The starting height of this cell. If the text wraps the height will automatically be adjusted.
+ $height = 0;
+ if (!empty($attrs['height'])) {
+ $height = (int)$attrs['height'];
+ }
+ // int Cell width (expressed in points) Setting the width to 0 will make it the width from the current location to the right margin.
+ $width = 0;
+ if (!empty($attrs['width'])) {
+ $width = (int)$attrs['width'];
+ }
- // int Stretch carachter mode
- $stretch = 0;
- if (!empty($attrs['stretch'])) {
- $stretch = (int) $attrs['stretch'];
- }
+ // int Stretch carachter mode
+ $stretch = 0;
+ if (!empty($attrs['stretch'])) {
+ $stretch = (int)$attrs['stretch'];
+ }
- // mixed Position the left corner of this box on the page. The default is the current position.
- $left = '.';
- if (isset($attrs['left'])) {
- if ($attrs['left'] === '.') {
- $left = '.';
- } elseif (!empty($attrs['left'])) {
- $left = (int) $attrs['left'];
- } elseif ($attrs['left'] === '0') {
- $left = 0;
- }
- }
- // mixed Position the top corner of this box on the page. the default is the current position
- $top = '.';
- if (isset($attrs['top'])) {
- if ($attrs['top'] === '.') {
- $top = '.';
- } elseif (!empty($attrs['top'])) {
- $top = (int) $attrs['top'];
- } elseif ($attrs['top'] === '0') {
- $top = 0;
- }
- }
+ // mixed Position the left corner of this box on the page. The default is the current position.
+ $left = '.';
+ if (isset($attrs['left'])) {
+ if ($attrs['left'] === '.') {
+ $left = '.';
+ } elseif (!empty($attrs['left'])) {
+ $left = (int)$attrs['left'];
+ } elseif ($attrs['left'] === '0') {
+ $left = 0;
+ }
+ }
+ // mixed Position the top corner of this box on the page. the default is the current position
+ $top = '.';
+ if (isset($attrs['top'])) {
+ if ($attrs['top'] === '.') {
+ $top = '.';
+ } elseif (!empty($attrs['top'])) {
+ $top = (int)$attrs['top'];
+ } elseif ($attrs['top'] === '0') {
+ $top = 0;
+ }
+ }
- // string The name of the Style that should be used to render the text.
- $style = '';
- if (!empty($attrs['style'])) {
- $style = $attrs['style'];
- }
+ // string The name of the Style that should be used to render the text.
+ $style = '';
+ if (!empty($attrs['style'])) {
+ $style = $attrs['style'];
+ }
- // string Text color in html code
- $tcolor = '';
- if (!empty($attrs['tcolor'])) {
- $tcolor = $attrs['tcolor'];
- }
+ // string Text color in html code
+ $tcolor = '';
+ if (!empty($attrs['tcolor'])) {
+ $tcolor = $attrs['tcolor'];
+ }
- // int Indicates where the current position should go after the call.
- $ln = 0;
- if (isset($attrs['newline'])) {
- if (!empty($attrs['newline'])) {
- $ln = (int) $attrs['newline'];
- } elseif ($attrs['newline'] === '0') {
- $ln = 0;
- }
- }
+ // int Indicates where the current position should go after the call.
+ $ln = 0;
+ if (isset($attrs['newline'])) {
+ if (!empty($attrs['newline'])) {
+ $ln = (int)$attrs['newline'];
+ } elseif ($attrs['newline'] === '0') {
+ $ln = 0;
+ }
+ }
- if ($align == 'left') {
- $align = 'L';
- } elseif ($align == 'right') {
- $align = 'R';
- } elseif ($align == 'center') {
- $align = 'C';
- } elseif ($align == 'justify') {
- $align = 'J';
- }
+ if ($align == 'left') {
+ $align = 'L';
+ } elseif ($align == 'right') {
+ $align = 'R';
+ } elseif ($align == 'center') {
+ $align = 'C';
+ } elseif ($align == 'justify') {
+ $align = 'J';
+ }
- array_push($this->print_data_stack, $this->print_data);
- $this->print_data = true;
+ array_push($this->print_data_stack, $this->print_data);
+ $this->print_data = true;
- $this->current_element = $this->report_root->createCell(
- $width,
- $height,
- $border,
- $align,
- $bgcolor,
- $style,
- $ln,
- $top,
- $left,
- $fill,
- $stretch,
- $bocolor,
- $tcolor,
- $reseth
- );
- }
+ $this->current_element = $this->report_root->createCell(
+ $width,
+ $height,
+ $border,
+ $align,
+ $bgcolor,
+ $style,
+ $ln,
+ $top,
+ $left,
+ $fill,
+ $stretch,
+ $bocolor,
+ $tcolor,
+ $reseth
+ );
+ }
- /**
- * XML </Cell>
- */
- private function cellEndHandler() {
- $this->print_data = array_pop($this->print_data_stack);
- $this->wt_report->addElement($this->current_element);
- }
+ /**
+ * XML </Cell>
+ */
+ private function cellEndHandler()
+ {
+ $this->print_data = array_pop($this->print_data_stack);
+ $this->wt_report->addElement($this->current_element);
+ }
- /**
- * XML <Now /> element handler
- */
- private function nowStartHandler() {
- $g = FunctionsDate::timestampToGedcomDate(WT_TIMESTAMP + WT_TIMESTAMP_OFFSET);
- $this->current_element->addText($g->display());
- }
+ /**
+ * XML <Now /> element handler
+ */
+ private function nowStartHandler()
+ {
+ $g = FunctionsDate::timestampToGedcomDate(WT_TIMESTAMP + WT_TIMESTAMP_OFFSET);
+ $this->current_element->addText($g->display());
+ }
- /**
- * XML <PageNum /> element handler
- */
- private function pageNumStartHandler() {
- $this->current_element->addText('#PAGENUM#');
- }
+ /**
+ * XML <PageNum /> element handler
+ */
+ private function pageNumStartHandler()
+ {
+ $this->current_element->addText('#PAGENUM#');
+ }
- /**
- * XML <TotalPages /> element handler
- */
- private function totalPagesStartHandler() {
- $this->current_element->addText('{{:ptp:}}');
- }
+ /**
+ * XML <TotalPages /> element handler
+ */
+ private function totalPagesStartHandler()
+ {
+ $this->current_element->addText('{{:ptp:}}');
+ }
- /**
- * Called at the start of an element.
- *
- * @param array $attrs an array of key value pairs for the attributes
- */
- private function gedcomStartHandler($attrs) {
- if ($this->process_gedcoms > 0) {
- $this->process_gedcoms++;
+ /**
+ * Called at the start of an element.
+ *
+ * @param array $attrs an array of key value pairs for the attributes
+ */
+ private function gedcomStartHandler($attrs)
+ {
+ if ($this->process_gedcoms > 0) {
+ $this->process_gedcoms++;
- return;
- }
+ return;
+ }
- $tag = $attrs['id'];
- $tag = str_replace('@fact', $this->fact, $tag);
- $tags = explode(':', $tag);
- $newgedrec = '';
- if (count($tags) < 2) {
- $tmp = GedcomRecord::getInstance($attrs['id'], $this->tree);
- $newgedrec = $tmp ? $tmp->privatizeGedcom(Auth::accessLevel($this->tree)) : '';
- }
- if (empty($newgedrec)) {
- $tgedrec = $this->gedrec;
- $newgedrec = '';
- foreach ($tags as $tag) {
- if (preg_match('/\$(.+)/', $tag, $match)) {
- if (isset($this->vars[$match[1]]['gedcom'])) {
- $newgedrec = $this->vars[$match[1]]['gedcom'];
- } else {
- $tmp = GedcomRecord::getInstance($match[1], $this->tree);
- $newgedrec = $tmp ? $tmp->privatizeGedcom(Auth::accessLevel($this->tree)) : '';
- }
- } else {
- if (preg_match('/@(.+)/', $tag, $match)) {
- $gmatch = [];
- if (preg_match("/\d $match[1] @([^@]+)@/", $tgedrec, $gmatch)) {
- $tmp = GedcomRecord::getInstance($gmatch[1], $this->tree);
- $newgedrec = $tmp ? $tmp->privatizeGedcom(Auth::accessLevel($this->tree)) : '';
- $tgedrec = $newgedrec;
- } else {
- $newgedrec = '';
- break;
- }
- } else {
- $temp = explode(' ', trim($tgedrec));
- $level = $temp[0] + 1;
- $newgedrec = Functions::getSubRecord($level, "$level $tag", $tgedrec);
- $tgedrec = $newgedrec;
- }
- }
- }
- }
- if (!empty($newgedrec)) {
- array_push($this->gedrec_stack, [$this->gedrec, $this->fact, $this->desc]);
- $this->gedrec = $newgedrec;
- if (preg_match("/(\d+) (_?[A-Z0-9]+) (.*)/", $this->gedrec, $match)) {
- $this->fact = $match[2];
- $this->desc = trim($match[3]);
- }
- } else {
- $this->process_gedcoms++;
- }
- }
+ $tag = $attrs['id'];
+ $tag = str_replace('@fact', $this->fact, $tag);
+ $tags = explode(':', $tag);
+ $newgedrec = '';
+ if (count($tags) < 2) {
+ $tmp = GedcomRecord::getInstance($attrs['id'], $this->tree);
+ $newgedrec = $tmp ? $tmp->privatizeGedcom(Auth::accessLevel($this->tree)) : '';
+ }
+ if (empty($newgedrec)) {
+ $tgedrec = $this->gedrec;
+ $newgedrec = '';
+ foreach ($tags as $tag) {
+ if (preg_match('/\$(.+)/', $tag, $match)) {
+ if (isset($this->vars[$match[1]]['gedcom'])) {
+ $newgedrec = $this->vars[$match[1]]['gedcom'];
+ } else {
+ $tmp = GedcomRecord::getInstance($match[1], $this->tree);
+ $newgedrec = $tmp ? $tmp->privatizeGedcom(Auth::accessLevel($this->tree)) : '';
+ }
+ } else {
+ if (preg_match('/@(.+)/', $tag, $match)) {
+ $gmatch = [];
+ if (preg_match("/\d $match[1] @([^@]+)@/", $tgedrec, $gmatch)) {
+ $tmp = GedcomRecord::getInstance($gmatch[1], $this->tree);
+ $newgedrec = $tmp ? $tmp->privatizeGedcom(Auth::accessLevel($this->tree)) : '';
+ $tgedrec = $newgedrec;
+ } else {
+ $newgedrec = '';
+ break;
+ }
+ } else {
+ $temp = explode(' ', trim($tgedrec));
+ $level = $temp[0] + 1;
+ $newgedrec = Functions::getSubRecord($level, "$level $tag", $tgedrec);
+ $tgedrec = $newgedrec;
+ }
+ }
+ }
+ }
+ if (!empty($newgedrec)) {
+ array_push($this->gedrec_stack, [
+ $this->gedrec,
+ $this->fact,
+ $this->desc,
+ ]);
+ $this->gedrec = $newgedrec;
+ if (preg_match("/(\d+) (_?[A-Z0-9]+) (.*)/", $this->gedrec, $match)) {
+ $this->fact = $match[2];
+ $this->desc = trim($match[3]);
+ }
+ } else {
+ $this->process_gedcoms++;
+ }
+ }
- /**
- * Called at the end of an element.
- */
- private function gedcomEndHandler() {
- if ($this->process_gedcoms > 0) {
- $this->process_gedcoms--;
- } else {
- list($this->gedrec, $this->fact, $this->desc) = array_pop($this->gedrec_stack);
- }
- }
+ /**
+ * Called at the end of an element.
+ */
+ private function gedcomEndHandler()
+ {
+ if ($this->process_gedcoms > 0) {
+ $this->process_gedcoms--;
+ } else {
+ list($this->gedrec, $this->fact, $this->desc) = array_pop($this->gedrec_stack);
+ }
+ }
- /**
- * XML <textBoxStartHandler>
- *
- * @param array $attrs an array of key value pairs for the attributes
- */
- private function textBoxStartHandler($attrs) {
- // string Background color code
- $bgcolor = '';
- if (!empty($attrs['bgcolor'])) {
- $bgcolor = $attrs['bgcolor'];
- }
+ /**
+ * XML <textBoxStartHandler>
+ *
+ * @param array $attrs an array of key value pairs for the attributes
+ */
+ private function textBoxStartHandler($attrs)
+ {
+ // string Background color code
+ $bgcolor = '';
+ if (!empty($attrs['bgcolor'])) {
+ $bgcolor = $attrs['bgcolor'];
+ }
- // boolean Wether or not fill the background color
- $fill = true;
- if (isset($attrs['fill'])) {
- if ($attrs['fill'] === '0') {
- $fill = false;
- } elseif ($attrs['fill'] === '1') {
- $fill = true;
- }
- }
+ // boolean Wether or not fill the background color
+ $fill = true;
+ if (isset($attrs['fill'])) {
+ if ($attrs['fill'] === '0') {
+ $fill = false;
+ } elseif ($attrs['fill'] === '1') {
+ $fill = true;
+ }
+ }
- // var boolean Whether or not a border should be printed around this box. 0 = no border, 1 = border. Default is 0
- $border = false;
- if (isset($attrs['border'])) {
- if ($attrs['border'] === '1') {
- $border = true;
- } elseif ($attrs['border'] === '0') {
- $border = false;
- }
- }
+ // var boolean Whether or not a border should be printed around this box. 0 = no border, 1 = border. Default is 0
+ $border = false;
+ if (isset($attrs['border'])) {
+ if ($attrs['border'] === '1') {
+ $border = true;
+ } elseif ($attrs['border'] === '0') {
+ $border = false;
+ }
+ }
- // int The starting height of this cell. If the text wraps the height will automatically be adjusted
- $height = 0;
- if (!empty($attrs['height'])) {
- $height = (int) $attrs['height'];
- }
- // int Setting the width to 0 will make it the width from the current location to the margin
- $width = 0;
- if (!empty($attrs['width'])) {
- $width = (int) $attrs['width'];
- }
+ // int The starting height of this cell. If the text wraps the height will automatically be adjusted
+ $height = 0;
+ if (!empty($attrs['height'])) {
+ $height = (int)$attrs['height'];
+ }
+ // int Setting the width to 0 will make it the width from the current location to the margin
+ $width = 0;
+ if (!empty($attrs['width'])) {
+ $width = (int)$attrs['width'];
+ }
- // mixed Position the left corner of this box on the page. The default is the current position.
- $left = '.';
- if (isset($attrs['left'])) {
- if ($attrs['left'] === '.') {
- $left = '.';
- } elseif (!empty($attrs['left'])) {
- $left = (int) $attrs['left'];
- } elseif ($attrs['left'] === '0') {
- $left = 0;
- }
- }
- // mixed Position the top corner of this box on the page. the default is the current position
- $top = '.';
- if (isset($attrs['top'])) {
- if ($attrs['top'] === '.') {
- $top = '.';
- } elseif (!empty($attrs['top'])) {
- $top = (int) $attrs['top'];
- } elseif ($attrs['top'] === '0') {
- $top = 0;
- }
- }
- // boolean After this box is finished rendering, should the next section of text start immediately after the this box or should it start on a new line under this box. 0 = no new line, 1 = force new line. Default is 0
- $newline = false;
- if (isset($attrs['newline'])) {
- if ($attrs['newline'] === '1') {
- $newline = true;
- } elseif ($attrs['newline'] === '0') {
- $newline = false;
- }
- }
- // boolean
- $pagecheck = true;
- if (isset($attrs['pagecheck'])) {
- if ($attrs['pagecheck'] === '0') {
- $pagecheck = false;
- } elseif ($attrs['pagecheck'] === '1') {
- $pagecheck = true;
- }
- }
- // boolean Cell padding
- $padding = true;
- if (isset($attrs['padding'])) {
- if ($attrs['padding'] === '0') {
- $padding = false;
- } elseif ($attrs['padding'] === '1') {
- $padding = true;
- }
- }
- // boolean Reset this box Height
- $reseth = false;
- if (isset($attrs['reseth'])) {
- if ($attrs['reseth'] === '1') {
- $reseth = true;
- } elseif ($attrs['reseth'] === '0') {
- $reseth = false;
- }
- }
+ // mixed Position the left corner of this box on the page. The default is the current position.
+ $left = '.';
+ if (isset($attrs['left'])) {
+ if ($attrs['left'] === '.') {
+ $left = '.';
+ } elseif (!empty($attrs['left'])) {
+ $left = (int)$attrs['left'];
+ } elseif ($attrs['left'] === '0') {
+ $left = 0;
+ }
+ }
+ // mixed Position the top corner of this box on the page. the default is the current position
+ $top = '.';
+ if (isset($attrs['top'])) {
+ if ($attrs['top'] === '.') {
+ $top = '.';
+ } elseif (!empty($attrs['top'])) {
+ $top = (int)$attrs['top'];
+ } elseif ($attrs['top'] === '0') {
+ $top = 0;
+ }
+ }
+ // boolean After this box is finished rendering, should the next section of text start immediately after the this box or should it start on a new line under this box. 0 = no new line, 1 = force new line. Default is 0
+ $newline = false;
+ if (isset($attrs['newline'])) {
+ if ($attrs['newline'] === '1') {
+ $newline = true;
+ } elseif ($attrs['newline'] === '0') {
+ $newline = false;
+ }
+ }
+ // boolean
+ $pagecheck = true;
+ if (isset($attrs['pagecheck'])) {
+ if ($attrs['pagecheck'] === '0') {
+ $pagecheck = false;
+ } elseif ($attrs['pagecheck'] === '1') {
+ $pagecheck = true;
+ }
+ }
+ // boolean Cell padding
+ $padding = true;
+ if (isset($attrs['padding'])) {
+ if ($attrs['padding'] === '0') {
+ $padding = false;
+ } elseif ($attrs['padding'] === '1') {
+ $padding = true;
+ }
+ }
+ // boolean Reset this box Height
+ $reseth = false;
+ if (isset($attrs['reseth'])) {
+ if ($attrs['reseth'] === '1') {
+ $reseth = true;
+ } elseif ($attrs['reseth'] === '0') {
+ $reseth = false;
+ }
+ }
- // string Style of rendering
- $style = '';
+ // string Style of rendering
+ $style = '';
- array_push($this->print_data_stack, $this->print_data);
- $this->print_data = false;
+ array_push($this->print_data_stack, $this->print_data);
+ $this->print_data = false;
- array_push($this->wt_report_stack, $this->wt_report);
- $this->wt_report = $this->report_root->createTextBox(
- $width,
- $height,
- $border,
- $bgcolor,
- $newline,
- $left,
- $top,
- $pagecheck,
- $style,
- $fill,
- $padding,
- $reseth
- );
- }
+ array_push($this->wt_report_stack, $this->wt_report);
+ $this->wt_report = $this->report_root->createTextBox(
+ $width,
+ $height,
+ $border,
+ $bgcolor,
+ $newline,
+ $left,
+ $top,
+ $pagecheck,
+ $style,
+ $fill,
+ $padding,
+ $reseth
+ );
+ }
- /**
- * XML <textBoxEndHandler>
- */
- private function textBoxEndHandler() {
- $this->print_data = array_pop($this->print_data_stack);
- $this->current_element = $this->wt_report;
- $this->wt_report = array_pop($this->wt_report_stack);
- $this->wt_report->addElement($this->current_element);
- }
+ /**
+ * XML <textBoxEndHandler>
+ */
+ private function textBoxEndHandler()
+ {
+ $this->print_data = array_pop($this->print_data_stack);
+ $this->current_element = $this->wt_report;
+ $this->wt_report = array_pop($this->wt_report_stack);
+ $this->wt_report->addElement($this->current_element);
+ }
- /**
- * XLM <Text>.
- *
- * @param array $attrs an array of key value pairs for the attributes
- */
- private function textStartHandler($attrs) {
- array_push($this->print_data_stack, $this->print_data);
- $this->print_data = true;
+ /**
+ * XLM <Text>.
+ *
+ * @param array $attrs an array of key value pairs for the attributes
+ */
+ private function textStartHandler($attrs)
+ {
+ array_push($this->print_data_stack, $this->print_data);
+ $this->print_data = true;
- // string The name of the Style that should be used to render the text.
- $style = '';
- if (!empty($attrs['style'])) {
- $style = $attrs['style'];
- }
+ // string The name of the Style that should be used to render the text.
+ $style = '';
+ if (!empty($attrs['style'])) {
+ $style = $attrs['style'];
+ }
- // string The color of the text - Keep the black color as default
- $color = '';
- if (!empty($attrs['color'])) {
- $color = $attrs['color'];
- }
+ // string The color of the text - Keep the black color as default
+ $color = '';
+ if (!empty($attrs['color'])) {
+ $color = $attrs['color'];
+ }
- $this->current_element = $this->report_root->createText($style, $color);
- }
+ $this->current_element = $this->report_root->createText($style, $color);
+ }
- /**
- * XML </Text>
- */
- private function textEndHandler() {
- $this->print_data = array_pop($this->print_data_stack);
- $this->wt_report->addElement($this->current_element);
- }
+ /**
+ * XML </Text>
+ */
+ private function textEndHandler()
+ {
+ $this->print_data = array_pop($this->print_data_stack);
+ $this->wt_report->addElement($this->current_element);
+ }
- /**
- * XML <GetPersonName/>
- *
- * Get the name
- * 1. id is empty - current GEDCOM record
- * 2. id is set with a record id
- *
- * @param array $attrs an array of key value pairs for the attributes
- */
- private function getPersonNameStartHandler($attrs) {
- $id = '';
- $match = [];
- if (empty($attrs['id'])) {
- if (preg_match('/0 @(.+)@/', $this->gedrec, $match)) {
- $id = $match[1];
- }
- } else {
- if (preg_match('/\$(.+)/', $attrs['id'], $match)) {
- if (isset($this->vars[$match[1]]['id'])) {
- $id = $this->vars[$match[1]]['id'];
- }
- } else {
- if (preg_match('/@(.+)/', $attrs['id'], $match)) {
- $gmatch = [];
- if (preg_match("/\d $match[1] @([^@]+)@/", $this->gedrec, $gmatch)) {
- $id = $gmatch[1];
- }
- } else {
- $id = $attrs['id'];
- }
- }
- }
- if (!empty($id)) {
- $record = GedcomRecord::getInstance($id, $this->tree);
- if (is_null($record)) {
- return;
- }
- if (!$record->canShowName()) {
- $this->current_element->addText(I18N::translate('Private'));
- } else {
- $name = $record->getFullName();
- $name = preg_replace(
- ['/<span class="starredname">/', '/<\/span><\/span>/', '/<\/span>/'],
- ['«', '', '»'],
- $name
- );
- $name = strip_tags($name);
- if (!empty($attrs['truncate'])) {
- if (mb_strlen($name) > $attrs['truncate']) {
- $name = preg_replace("/\(.*\) ?/", '', $name); //removes () and text inbetween - what about ", [ and { etc?
- $words = preg_split('/[, -]+/', $name); // names separated with space, comma or hyphen - any others?
- $name = $words[count($words) - 1];
- for ($i = count($words) - 2; $i >= 0; $i--) {
- $len = mb_strlen($name);
- for ($j = count($words) - 3; $j >= 0; $j--) {
- $len += mb_strlen($words[$j]);
- }
- if ($len > $attrs['truncate']) {
- $first_letter = mb_substr($words[$i], 0, 1);
- // Do not show " of nick-names
- if ($first_letter != '"') {
- $name = mb_substr($words[$i], 0, 1) . '. ' . $name;
- }
- } else {
- $name = $words[$i] . ' ' . $name;
- }
- }
- }
- } else {
- $addname = $record->getAddName();
- $addname = preg_replace(
- ['/<span class="starredname">/', '/<\/span><\/span>/', '/<\/span>/'],
- ['«', '', '»'],
- $addname
- );
- $addname = strip_tags($addname);
- if (!empty($addname)) {
- $name .= ' ' . $addname;
- }
- }
- $this->current_element->addText(trim($name));
- }
- }
- }
+ /**
+ * XML <GetPersonName/>
+ *
+ * Get the name
+ * 1. id is empty - current GEDCOM record
+ * 2. id is set with a record id
+ *
+ * @param array $attrs an array of key value pairs for the attributes
+ */
+ private function getPersonNameStartHandler($attrs)
+ {
+ $id = '';
+ $match = [];
+ if (empty($attrs['id'])) {
+ if (preg_match('/0 @(.+)@/', $this->gedrec, $match)) {
+ $id = $match[1];
+ }
+ } else {
+ if (preg_match('/\$(.+)/', $attrs['id'], $match)) {
+ if (isset($this->vars[$match[1]]['id'])) {
+ $id = $this->vars[$match[1]]['id'];
+ }
+ } else {
+ if (preg_match('/@(.+)/', $attrs['id'], $match)) {
+ $gmatch = [];
+ if (preg_match("/\d $match[1] @([^@]+)@/", $this->gedrec, $gmatch)) {
+ $id = $gmatch[1];
+ }
+ } else {
+ $id = $attrs['id'];
+ }
+ }
+ }
+ if (!empty($id)) {
+ $record = GedcomRecord::getInstance($id, $this->tree);
+ if (is_null($record)) {
+ return;
+ }
+ if (!$record->canShowName()) {
+ $this->current_element->addText(I18N::translate('Private'));
+ } else {
+ $name = $record->getFullName();
+ $name = preg_replace(
+ [
+ '/<span class="starredname">/',
+ '/<\/span><\/span>/',
+ '/<\/span>/',
+ ],
+ [
+ '«',
+ '',
+ '»',
+ ],
+ $name
+ );
+ $name = strip_tags($name);
+ if (!empty($attrs['truncate'])) {
+ if (mb_strlen($name) > $attrs['truncate']) {
+ $name = preg_replace("/\(.*\) ?/", '', $name); //removes () and text inbetween - what about ", [ and { etc?
+ $words = preg_split('/[, -]+/', $name); // names separated with space, comma or hyphen - any others?
+ $name = $words[count($words) - 1];
+ for ($i = count($words) - 2; $i >= 0; $i--) {
+ $len = mb_strlen($name);
+ for ($j = count($words) - 3; $j >= 0; $j--) {
+ $len += mb_strlen($words[$j]);
+ }
+ if ($len > $attrs['truncate']) {
+ $first_letter = mb_substr($words[$i], 0, 1);
+ // Do not show " of nick-names
+ if ($first_letter != '"') {
+ $name = mb_substr($words[$i], 0, 1) . '. ' . $name;
+ }
+ } else {
+ $name = $words[$i] . ' ' . $name;
+ }
+ }
+ }
+ } else {
+ $addname = $record->getAddName();
+ $addname = preg_replace(
+ [
+ '/<span class="starredname">/',
+ '/<\/span><\/span>/',
+ '/<\/span>/',
+ ],
+ [
+ '«',
+ '',
+ '»',
+ ],
+ $addname
+ );
+ $addname = strip_tags($addname);
+ if (!empty($addname)) {
+ $name .= ' ' . $addname;
+ }
+ }
+ $this->current_element->addText(trim($name));
+ }
+ }
+ }
- /**
- * XML <GedcomValue/>
- *
- * @param array $attrs an array of key value pairs for the attributes
- */
- private function gedcomValueStartHandler($attrs) {
- $id = '';
- $match = [];
- if (preg_match('/0 @(.+)@/', $this->gedrec, $match)) {
- $id = $match[1];
- }
+ /**
+ * XML <GedcomValue/>
+ *
+ * @param array $attrs an array of key value pairs for the attributes
+ */
+ private function gedcomValueStartHandler($attrs)
+ {
+ $id = '';
+ $match = [];
+ if (preg_match('/0 @(.+)@/', $this->gedrec, $match)) {
+ $id = $match[1];
+ }
- if (isset($attrs['newline']) && $attrs['newline'] == '1') {
- $useBreak = '1';
- } else {
- $useBreak = '0';
- }
+ if (isset($attrs['newline']) && $attrs['newline'] == '1') {
+ $useBreak = '1';
+ } else {
+ $useBreak = '0';
+ }
- $tag = $attrs['tag'];
- if (!empty($tag)) {
- if ($tag == '@desc') {
- $value = $this->desc;
- $value = trim($value);
- $this->current_element->addText($value);
- }
- if ($tag == '@id') {
- $this->current_element->addText($id);
- } else {
- $tag = str_replace('@fact', $this->fact, $tag);
- if (empty($attrs['level'])) {
- $temp = explode(' ', trim($this->gedrec));
- $level = $temp[0];
- if ($level == 0) {
- $level++;
- }
- } else {
- $level = $attrs['level'];
- }
- $tags = preg_split('/[: ]/', $tag);
- $value = $this->getGedcomValue($tag, $level, $this->gedrec);
- switch (end($tags)) {
- case 'DATE':
- $tmp = new Date($value);
- $value = $tmp->display();
- break;
- case 'PLAC':
- $tmp = new Place($value, $this->tree);
- $value = $tmp->getShortName();
- break;
- }
- if ($useBreak == '1') {
- // Insert <br> when multiple dates exist.
- // This works around a TCPDF bug that incorrectly wraps RTL dates on LTR pages
- $value = str_replace('(', '<br>(', $value);
- $value = str_replace('<span dir="ltr"><br>', '<br><span dir="ltr">', $value);
- $value = str_replace('<span dir="rtl"><br>', '<br><span dir="rtl">', $value);
- if (substr($value, 0, 6) == '<br>') {
- $value = substr($value, 6);
- }
- }
- $tmp = explode(':', $tag);
- if (in_array(end($tmp), ['NOTE', 'TEXT'])) {
- $value = Filter::formatText($value, $this->tree); // We'll strip HTML in addText()
- }
- $this->current_element->addText($value);
- }
- }
- }
+ $tag = $attrs['tag'];
+ if (!empty($tag)) {
+ if ($tag == '@desc') {
+ $value = $this->desc;
+ $value = trim($value);
+ $this->current_element->addText($value);
+ }
+ if ($tag == '@id') {
+ $this->current_element->addText($id);
+ } else {
+ $tag = str_replace('@fact', $this->fact, $tag);
+ if (empty($attrs['level'])) {
+ $temp = explode(' ', trim($this->gedrec));
+ $level = $temp[0];
+ if ($level == 0) {
+ $level++;
+ }
+ } else {
+ $level = $attrs['level'];
+ }
+ $tags = preg_split('/[: ]/', $tag);
+ $value = $this->getGedcomValue($tag, $level, $this->gedrec);
+ switch (end($tags)) {
+ case 'DATE':
+ $tmp = new Date($value);
+ $value = $tmp->display();
+ break;
+ case 'PLAC':
+ $tmp = new Place($value, $this->tree);
+ $value = $tmp->getShortName();
+ break;
+ }
+ if ($useBreak == '1') {
+ // Insert <br> when multiple dates exist.
+ // This works around a TCPDF bug that incorrectly wraps RTL dates on LTR pages
+ $value = str_replace('(', '<br>(', $value);
+ $value = str_replace('<span dir="ltr"><br>', '<br><span dir="ltr">', $value);
+ $value = str_replace('<span dir="rtl"><br>', '<br><span dir="rtl">', $value);
+ if (substr($value, 0, 6) == '<br>') {
+ $value = substr($value, 6);
+ }
+ }
+ $tmp = explode(':', $tag);
+ if (in_array(end($tmp), [
+ 'NOTE',
+ 'TEXT',
+ ])) {
+ $value = Filter::formatText($value, $this->tree); // We'll strip HTML in addText()
+ }
+ $this->current_element->addText($value);
+ }
+ }
+ }
- /**
- * XML <RepeatTag>
- *
- * @param array $attrs an array of key value pairs for the attributes
- */
- private function repeatTagStartHandler($attrs) {
- $this->process_repeats++;
- if ($this->process_repeats > 1) {
- return;
- }
+ /**
+ * XML <RepeatTag>
+ *
+ * @param array $attrs an array of key value pairs for the attributes
+ */
+ private function repeatTagStartHandler($attrs)
+ {
+ $this->process_repeats++;
+ if ($this->process_repeats > 1) {
+ return;
+ }
- array_push($this->repeats_stack, [$this->repeats, $this->repeat_bytes]);
- $this->repeats = [];
- $this->repeat_bytes = xml_get_current_line_number($this->parser);
+ array_push($this->repeats_stack, [
+ $this->repeats,
+ $this->repeat_bytes,
+ ]);
+ $this->repeats = [];
+ $this->repeat_bytes = xml_get_current_line_number($this->parser);
- $tag = '';
- if (isset($attrs['tag'])) {
- $tag = $attrs['tag'];
- }
- if (!empty($tag)) {
- if ($tag == '@desc') {
- $value = $this->desc;
- $value = trim($value);
- $this->current_element->addText($value);
- } else {
- $tag = str_replace('@fact', $this->fact, $tag);
- $tags = explode(':', $tag);
- $temp = explode(' ', trim($this->gedrec));
- $level = $temp[0];
- if ($level == 0) {
- $level++;
- }
- $subrec = $this->gedrec;
- $t = $tag;
- $count = count($tags);
- $i = 0;
- while ($i < $count) {
- $t = $tags[$i];
- if (!empty($t)) {
- if ($i < ($count - 1)) {
- $subrec = Functions::getSubRecord($level, "$level $t", $subrec);
- if (empty($subrec)) {
- $level--;
- $subrec = Functions::getSubRecord($level, "@ $t", $this->gedrec);
- if (empty($subrec)) {
- return;
- }
- }
- }
- $level++;
- }
- $i++;
- }
- $level--;
- $count = preg_match_all("/$level $t(.*)/", $subrec, $match, PREG_SET_ORDER);
- $i = 0;
- while ($i < $count) {
- $i++;
- // Privacy check - is this a link, and are we allowed to view the linked object?
- $subrecord = Functions::getSubRecord($level, "$level $t", $subrec, $i);
- if (preg_match('/^\d ' . WT_REGEX_TAG . ' @(' . WT_REGEX_XREF . ')@/', $subrecord, $xref_match)) {
- $linked_object = GedcomRecord::getInstance($xref_match[1], $this->tree);
- if ($linked_object && !$linked_object->canShow()) {
- continue;
- }
- }
- $this->repeats[] = $subrecord;
- }
- }
- }
- }
+ $tag = '';
+ if (isset($attrs['tag'])) {
+ $tag = $attrs['tag'];
+ }
+ if (!empty($tag)) {
+ if ($tag == '@desc') {
+ $value = $this->desc;
+ $value = trim($value);
+ $this->current_element->addText($value);
+ } else {
+ $tag = str_replace('@fact', $this->fact, $tag);
+ $tags = explode(':', $tag);
+ $temp = explode(' ', trim($this->gedrec));
+ $level = $temp[0];
+ if ($level == 0) {
+ $level++;
+ }
+ $subrec = $this->gedrec;
+ $t = $tag;
+ $count = count($tags);
+ $i = 0;
+ while ($i < $count) {
+ $t = $tags[$i];
+ if (!empty($t)) {
+ if ($i < ($count - 1)) {
+ $subrec = Functions::getSubRecord($level, "$level $t", $subrec);
+ if (empty($subrec)) {
+ $level--;
+ $subrec = Functions::getSubRecord($level, "@ $t", $this->gedrec);
+ if (empty($subrec)) {
+ return;
+ }
+ }
+ }
+ $level++;
+ }
+ $i++;
+ }
+ $level--;
+ $count = preg_match_all("/$level $t(.*)/", $subrec, $match, PREG_SET_ORDER);
+ $i = 0;
+ while ($i < $count) {
+ $i++;
+ // Privacy check - is this a link, and are we allowed to view the linked object?
+ $subrecord = Functions::getSubRecord($level, "$level $t", $subrec, $i);
+ if (preg_match('/^\d ' . WT_REGEX_TAG . ' @(' . WT_REGEX_XREF . ')@/', $subrecord, $xref_match)) {
+ $linked_object = GedcomRecord::getInstance($xref_match[1], $this->tree);
+ if ($linked_object && !$linked_object->canShow()) {
+ continue;
+ }
+ }
+ $this->repeats[] = $subrecord;
+ }
+ }
+ }
+ }
- /**
- * XML </ RepeatTag>
- */
- private function repeatTagEndHandler() {
- $this->process_repeats--;
- if ($this->process_repeats > 0) {
- return;
- }
+ /**
+ * XML </ RepeatTag>
+ */
+ private function repeatTagEndHandler()
+ {
+ $this->process_repeats--;
+ if ($this->process_repeats > 0) {
+ return;
+ }
- // Check if there is anything to repeat
- if (count($this->repeats) > 0) {
- // No need to load them if not used...
+ // Check if there is anything to repeat
+ if (count($this->repeats) > 0) {
+ // No need to load them if not used...
- $lineoffset = 0;
- foreach ($this->repeats_stack as $rep) {
- $lineoffset += $rep[1];
- }
- //-- read the xml from the file
- $lines = file($this->report);
- while (strpos($lines[$lineoffset + $this->repeat_bytes], '<RepeatTag') === false) {
- $lineoffset--;
- }
- $lineoffset++;
- $reportxml = "<tempdoc>\n";
- $line_nr = $lineoffset + $this->repeat_bytes;
- // RepeatTag Level counter
- $count = 1;
- while (0 < $count) {
- if (strstr($lines[$line_nr], '<RepeatTag') !== false) {
- $count++;
- } elseif (strstr($lines[$line_nr], '</RepeatTag') !== false) {
- $count--;
- }
- if (0 < $count) {
- $reportxml .= $lines[$line_nr];
- }
- $line_nr++;
- }
- // No need to drag this
- unset($lines);
- $reportxml .= "</tempdoc>\n";
- // Save original values
- array_push($this->parser_stack, $this->parser);
- $oldgedrec = $this->gedrec;
- foreach ($this->repeats as $gedrec) {
- $this->gedrec = $gedrec;
- $repeat_parser = xml_parser_create();
- $this->parser = $repeat_parser;
- xml_parser_set_option($repeat_parser, XML_OPTION_CASE_FOLDING, false);
- xml_set_element_handler($repeat_parser, [$this, 'startElement'], [$this, 'endElement']);
- xml_set_character_data_handler($repeat_parser, [$this, 'characterData']);
- if (!xml_parse($repeat_parser, $reportxml, true)) {
- throw new \DomainException(sprintf(
- 'RepeatTagEHandler XML error: %s at line %d',
- xml_error_string(xml_get_error_code($repeat_parser)),
- xml_get_current_line_number($repeat_parser)
- ));
- }
- xml_parser_free($repeat_parser);
- }
- // Restore original values
- $this->gedrec = $oldgedrec;
- $this->parser = array_pop($this->parser_stack);
- }
- list($this->repeats, $this->repeat_bytes) = array_pop($this->repeats_stack);
- }
+ $lineoffset = 0;
+ foreach ($this->repeats_stack as $rep) {
+ $lineoffset += $rep[1];
+ }
+ //-- read the xml from the file
+ $lines = file($this->report);
+ while (strpos($lines[$lineoffset + $this->repeat_bytes], '<RepeatTag') === false) {
+ $lineoffset--;
+ }
+ $lineoffset++;
+ $reportxml = "<tempdoc>\n";
+ $line_nr = $lineoffset + $this->repeat_bytes;
+ // RepeatTag Level counter
+ $count = 1;
+ while (0 < $count) {
+ if (strstr($lines[$line_nr], '<RepeatTag') !== false) {
+ $count++;
+ } elseif (strstr($lines[$line_nr], '</RepeatTag') !== false) {
+ $count--;
+ }
+ if (0 < $count) {
+ $reportxml .= $lines[$line_nr];
+ }
+ $line_nr++;
+ }
+ // No need to drag this
+ unset($lines);
+ $reportxml .= "</tempdoc>\n";
+ // Save original values
+ array_push($this->parser_stack, $this->parser);
+ $oldgedrec = $this->gedrec;
+ foreach ($this->repeats as $gedrec) {
+ $this->gedrec = $gedrec;
+ $repeat_parser = xml_parser_create();
+ $this->parser = $repeat_parser;
+ xml_parser_set_option($repeat_parser, XML_OPTION_CASE_FOLDING, false);
+ xml_set_element_handler($repeat_parser, [
+ $this,
+ 'startElement',
+ ], [
+ $this,
+ 'endElement',
+ ]);
+ xml_set_character_data_handler($repeat_parser, [
+ $this,
+ 'characterData',
+ ]);
+ if (!xml_parse($repeat_parser, $reportxml, true)) {
+ throw new \DomainException(sprintf(
+ 'RepeatTagEHandler XML error: %s at line %d',
+ xml_error_string(xml_get_error_code($repeat_parser)),
+ xml_get_current_line_number($repeat_parser)
+ ));
+ }
+ xml_parser_free($repeat_parser);
+ }
+ // Restore original values
+ $this->gedrec = $oldgedrec;
+ $this->parser = array_pop($this->parser_stack);
+ }
+ list($this->repeats, $this->repeat_bytes) = array_pop($this->repeats_stack);
+ }
- /**
- * Variable lookup
- *
- * Retrieve predefined variables :
- *
- * @ desc GEDCOM fact description, example:
- * 1 EVEN This is a description
- * @ fact GEDCOM fact tag, such as BIRT, DEAT etc.
- * $ I18N::translate('....')
- * $ language_settings[]
- *
- * @param array $attrs an array of key value pairs for the attributes
- */
- private function varStartHandler($attrs) {
- if (empty($attrs['var'])) {
- throw new \DomainException('REPORT ERROR var: The attribute "var=" is missing or not set in the XML file on line: ' . xml_get_current_line_number($this->parser));
- }
+ /**
+ * Variable lookup
+ *
+ * Retrieve predefined variables :
+ *
+ * @ desc GEDCOM fact description, example:
+ * 1 EVEN This is a description
+ * @ fact GEDCOM fact tag, such as BIRT, DEAT etc.
+ * $ I18N::translate('....')
+ * $ language_settings[]
+ *
+ * @param array $attrs an array of key value pairs for the attributes
+ */
+ private function varStartHandler($attrs)
+ {
+ if (empty($attrs['var'])) {
+ throw new \DomainException('REPORT ERROR var: The attribute "var=" is missing or not set in the XML file on line: ' . xml_get_current_line_number($this->parser));
+ }
- $var = $attrs['var'];
- // SetVar element preset variables
- if (!empty($this->vars[$var]['id'])) {
- $var = $this->vars[$var]['id'];
- } else {
- $tfact = $this->fact;
- if (($this->fact === 'EVEN' || $this->fact === 'FACT') && $this->type !== ' ') {
- // Use :
- // n TYPE This text if string
- $tfact = $this->type;
- }
- $var = str_replace(['@fact', '@desc'], [GedcomTag::getLabel($tfact), $this->desc], $var);
- if (preg_match('/^I18N::number\((.+)\)$/', $var, $match)) {
- $var = I18N::number($match[1]);
- } elseif (preg_match('/^I18N::translate\(\'(.+)\'\)$/', $var, $match)) {
- $var = I18N::translate($match[1]);
- } elseif (preg_match('/^I18N::translateContext\(\'(.+)\', *\'(.+)\'\)$/', $var, $match)) {
- $var = I18N::translateContext($match[1], $match[2]);
- }
- }
- // Check if variable is set as a date and reformat the date
- if (isset($attrs['date'])) {
- if ($attrs['date'] === '1') {
- $g = new Date($var);
- $var = $g->display();
- }
- }
- $this->current_element->addText($var);
- $this->text = $var; // Used for title/descriptio
- }
+ $var = $attrs['var'];
+ // SetVar element preset variables
+ if (!empty($this->vars[$var]['id'])) {
+ $var = $this->vars[$var]['id'];
+ } else {
+ $tfact = $this->fact;
+ if (($this->fact === 'EVEN' || $this->fact === 'FACT') && $this->type !== ' ') {
+ // Use :
+ // n TYPE This text if string
+ $tfact = $this->type;
+ }
+ $var = str_replace([
+ '@fact',
+ '@desc',
+ ], [
+ GedcomTag::getLabel($tfact),
+ $this->desc,
+ ], $var);
+ if (preg_match('/^I18N::number\((.+)\)$/', $var, $match)) {
+ $var = I18N::number($match[1]);
+ } elseif (preg_match('/^I18N::translate\(\'(.+)\'\)$/', $var, $match)) {
+ $var = I18N::translate($match[1]);
+ } elseif (preg_match('/^I18N::translateContext\(\'(.+)\', *\'(.+)\'\)$/', $var, $match)) {
+ $var = I18N::translateContext($match[1], $match[2]);
+ }
+ }
+ // Check if variable is set as a date and reformat the date
+ if (isset($attrs['date'])) {
+ if ($attrs['date'] === '1') {
+ $g = new Date($var);
+ $var = $g->display();
+ }
+ }
+ $this->current_element->addText($var);
+ $this->text = $var; // Used for title/descriptio
+ }
- /**
- * XML <Facts>
- *
- * @param array $attrs an array of key value pairs for the attributes
- */
- private function factsStartHandler($attrs) {
- $this->process_repeats++;
- if ($this->process_repeats > 1) {
- return;
- }
+ /**
+ * XML <Facts>
+ *
+ * @param array $attrs an array of key value pairs for the attributes
+ */
+ private function factsStartHandler($attrs)
+ {
+ $this->process_repeats++;
+ if ($this->process_repeats > 1) {
+ return;
+ }
- array_push($this->repeats_stack, [$this->repeats, $this->repeat_bytes]);
- $this->repeats = [];
- $this->repeat_bytes = xml_get_current_line_number($this->parser);
+ array_push($this->repeats_stack, [
+ $this->repeats,
+ $this->repeat_bytes,
+ ]);
+ $this->repeats = [];
+ $this->repeat_bytes = xml_get_current_line_number($this->parser);
- $id = '';
- $match = [];
- if (preg_match('/0 @(.+)@/', $this->gedrec, $match)) {
- $id = $match[1];
- }
- $tag = '';
- if (isset($attrs['ignore'])) {
- $tag .= $attrs['ignore'];
- }
- if (preg_match('/\$(.+)/', $tag, $match)) {
- $tag = $this->vars[$match[1]]['id'];
- }
+ $id = '';
+ $match = [];
+ if (preg_match('/0 @(.+)@/', $this->gedrec, $match)) {
+ $id = $match[1];
+ }
+ $tag = '';
+ if (isset($attrs['ignore'])) {
+ $tag .= $attrs['ignore'];
+ }
+ if (preg_match('/\$(.+)/', $tag, $match)) {
+ $tag = $this->vars[$match[1]]['id'];
+ }
- $record = GedcomRecord::getInstance($id, $this->tree);
- if (empty($attrs['diff']) && !empty($id)) {
- $facts = $record->getFacts();
- Functions::sortFacts($facts);
- $this->repeats = [];
- $nonfacts = explode(',', $tag);
- foreach ($facts as $event) {
- if (!in_array($event->getTag(), $nonfacts)) {
- $this->repeats[] = $event->getGedcom();
- }
- }
- } else {
- foreach ($record->getFacts() as $fact) {
- if ($fact->isPendingAddition() && $fact->getTag() !== 'CHAN') {
- $this->repeats[] = $fact->getGedcom();
- }
- }
- }
- }
+ $record = GedcomRecord::getInstance($id, $this->tree);
+ if (empty($attrs['diff']) && !empty($id)) {
+ $facts = $record->getFacts();
+ Functions::sortFacts($facts);
+ $this->repeats = [];
+ $nonfacts = explode(',', $tag);
+ foreach ($facts as $event) {
+ if (!in_array($event->getTag(), $nonfacts)) {
+ $this->repeats[] = $event->getGedcom();
+ }
+ }
+ } else {
+ foreach ($record->getFacts() as $fact) {
+ if ($fact->isPendingAddition() && $fact->getTag() !== 'CHAN') {
+ $this->repeats[] = $fact->getGedcom();
+ }
+ }
+ }
+ }
- /**
- * XML </Facts>
- */
- private function factsEndHandler() {
- $this->process_repeats--;
- if ($this->process_repeats > 0) {
- return;
- }
+ /**
+ * XML </Facts>
+ */
+ private function factsEndHandler()
+ {
+ $this->process_repeats--;
+ if ($this->process_repeats > 0) {
+ return;
+ }
- // Check if there is anything to repeat
- if (count($this->repeats) > 0) {
- $line = xml_get_current_line_number($this->parser) - 1;
- $lineoffset = 0;
- foreach ($this->repeats_stack as $rep) {
- $lineoffset += $rep[1];
- }
+ // Check if there is anything to repeat
+ if (count($this->repeats) > 0) {
+ $line = xml_get_current_line_number($this->parser) - 1;
+ $lineoffset = 0;
+ foreach ($this->repeats_stack as $rep) {
+ $lineoffset += $rep[1];
+ }
- //-- read the xml from the file
- $lines = file($this->report);
- while ($lineoffset + $this->repeat_bytes > 0 && strpos($lines[$lineoffset + $this->repeat_bytes], '<Facts ') === false) {
- $lineoffset--;
- }
- $lineoffset++;
- $reportxml = "<tempdoc>\n";
- $i = $line + $lineoffset;
- $line_nr = $this->repeat_bytes + $lineoffset;
- while ($line_nr < $i) {
- $reportxml .= $lines[$line_nr];
- $line_nr++;
- }
- // No need to drag this
- unset($lines);
- $reportxml .= "</tempdoc>\n";
- // Save original values
- array_push($this->parser_stack, $this->parser);
- $oldgedrec = $this->gedrec;
- $count = count($this->repeats);
- $i = 0;
- while ($i < $count) {
- $this->gedrec = $this->repeats[$i];
- $this->fact = '';
- $this->desc = '';
- if (preg_match('/1 (\w+)(.*)/', $this->gedrec, $match)) {
- $this->fact = $match[1];
- if ($this->fact === 'EVEN' || $this->fact === 'FACT') {
- $tmatch = [];
- if (preg_match('/2 TYPE (.+)/', $this->gedrec, $tmatch)) {
- $this->type = trim($tmatch[1]);
- } else {
- $this->type = ' ';
- }
- }
- $this->desc = trim($match[2]);
- $this->desc .= Functions::getCont(2, $this->gedrec);
- }
- $repeat_parser = xml_parser_create();
- $this->parser = $repeat_parser;
- xml_parser_set_option($repeat_parser, XML_OPTION_CASE_FOLDING, false);
- xml_set_element_handler($repeat_parser, [$this, 'startElement'], [$this, 'endElement']);
- xml_set_character_data_handler($repeat_parser, [$this, 'characterData']);
- if (!xml_parse($repeat_parser, $reportxml, true)) {
- throw new \DomainException(sprintf(
- 'FactsEHandler XML error: %s at line %d',
- xml_error_string(xml_get_error_code($repeat_parser)),
- xml_get_current_line_number($repeat_parser)
- ));
- }
- xml_parser_free($repeat_parser);
- $i++;
- }
- // Restore original values
- $this->parser = array_pop($this->parser_stack);
- $this->gedrec = $oldgedrec;
- }
- list($this->repeats, $this->repeat_bytes) = array_pop($this->repeats_stack);
- }
+ //-- read the xml from the file
+ $lines = file($this->report);
+ while ($lineoffset + $this->repeat_bytes > 0 && strpos($lines[$lineoffset + $this->repeat_bytes], '<Facts ') === false) {
+ $lineoffset--;
+ }
+ $lineoffset++;
+ $reportxml = "<tempdoc>\n";
+ $i = $line + $lineoffset;
+ $line_nr = $this->repeat_bytes + $lineoffset;
+ while ($line_nr < $i) {
+ $reportxml .= $lines[$line_nr];
+ $line_nr++;
+ }
+ // No need to drag this
+ unset($lines);
+ $reportxml .= "</tempdoc>\n";
+ // Save original values
+ array_push($this->parser_stack, $this->parser);
+ $oldgedrec = $this->gedrec;
+ $count = count($this->repeats);
+ $i = 0;
+ while ($i < $count) {
+ $this->gedrec = $this->repeats[$i];
+ $this->fact = '';
+ $this->desc = '';
+ if (preg_match('/1 (\w+)(.*)/', $this->gedrec, $match)) {
+ $this->fact = $match[1];
+ if ($this->fact === 'EVEN' || $this->fact === 'FACT') {
+ $tmatch = [];
+ if (preg_match('/2 TYPE (.+)/', $this->gedrec, $tmatch)) {
+ $this->type = trim($tmatch[1]);
+ } else {
+ $this->type = ' ';
+ }
+ }
+ $this->desc = trim($match[2]);
+ $this->desc .= Functions::getCont(2, $this->gedrec);
+ }
+ $repeat_parser = xml_parser_create();
+ $this->parser = $repeat_parser;
+ xml_parser_set_option($repeat_parser, XML_OPTION_CASE_FOLDING, false);
+ xml_set_element_handler($repeat_parser, [
+ $this,
+ 'startElement',
+ ], [
+ $this,
+ 'endElement',
+ ]);
+ xml_set_character_data_handler($repeat_parser, [
+ $this,
+ 'characterData',
+ ]);
+ if (!xml_parse($repeat_parser, $reportxml, true)) {
+ throw new \DomainException(sprintf(
+ 'FactsEHandler XML error: %s at line %d',
+ xml_error_string(xml_get_error_code($repeat_parser)),
+ xml_get_current_line_number($repeat_parser)
+ ));
+ }
+ xml_parser_free($repeat_parser);
+ $i++;
+ }
+ // Restore original values
+ $this->parser = array_pop($this->parser_stack);
+ $this->gedrec = $oldgedrec;
+ }
+ list($this->repeats, $this->repeat_bytes) = array_pop($this->repeats_stack);
+ }
- /**
- * Setting upp or changing variables in the XML
- * The XML variable name and value is stored in $this->vars
- *
- * @param array $attrs an array of key value pairs for the attributes
- */
- private function setVarStartHandler($attrs) {
- if (empty($attrs['name'])) {
- throw new \DomainException('REPORT ERROR var: The attribute "name" is missing or not set in the XML file');
- }
+ /**
+ * Setting upp or changing variables in the XML
+ * The XML variable name and value is stored in $this->vars
+ *
+ * @param array $attrs an array of key value pairs for the attributes
+ */
+ private function setVarStartHandler($attrs)
+ {
+ if (empty($attrs['name'])) {
+ throw new \DomainException('REPORT ERROR var: The attribute "name" is missing or not set in the XML file');
+ }
- $name = $attrs['name'];
- $value = $attrs['value'];
- $match = [];
- // Current GEDCOM record strings
- if ($value == '@ID') {
- if (preg_match('/0 @(.+)@/', $this->gedrec, $match)) {
- $value = $match[1];
- }
- } elseif ($value == '@fact') {
- $value = $this->fact;
- } elseif ($value == '@desc') {
- $value = $this->desc;
- } elseif ($value == '@generation') {
- $value = $this->generation;
- } elseif (preg_match("/@(\w+)/", $value, $match)) {
- $gmatch = [];
- if (preg_match("/\d $match[1] (.+)/", $this->gedrec, $gmatch)) {
- $value = str_replace('@', '', trim($gmatch[1]));
- }
- }
- if (preg_match("/\\$(\w+)/", $name, $match)) {
- $name = $this->vars["'" . $match[1] . "'"]['id'];
- }
- $count = preg_match_all("/\\$(\w+)/", $value, $match, PREG_SET_ORDER);
- $i = 0;
- while ($i < $count) {
- $t = $this->vars[$match[$i][1]]['id'];
- $value = preg_replace('/\$' . $match[$i][1] . '/', $t, $value, 1);
- $i++;
- }
- if (preg_match('/^I18N::number\((.+)\)$/', $value, $match)) {
- $value = I18N::number($match[1]);
- } elseif (preg_match('/^I18N::translate\(\'(.+)\'\)$/', $value, $match)) {
- $value = I18N::translate($match[1]);
- } elseif (preg_match('/^I18N::translateContext\(\'(.+)\', *\'(.+)\'\)$/', $value, $match)) {
- $value = I18N::translateContext($match[1], $match[2]);
- }
- // Arithmetic functions
- if (preg_match("/(\d+)\s*([\-\+\*\/])\s*(\d+)/", $value, $match)) {
- switch ($match[2]) {
- case '+':
- $t = $match[1] + $match[3];
- $value = preg_replace('/' . $match[1] . "\s*([\-\+\*\/])\s*" . $match[3] . '/', $t, $value);
- break;
- case '-':
- $t = $match[1] - $match[3];
- $value = preg_replace('/' . $match[1] . "\s*([\-\+\*\/])\s*" . $match[3] . '/', $t, $value);
- break;
- case '*':
- $t = $match[1] * $match[3];
- $value = preg_replace('/' . $match[1] . "\s*([\-\+\*\/])\s*" . $match[3] . '/', $t, $value);
- break;
- case '/':
- $t = $match[1] / $match[3];
- $value = preg_replace('/' . $match[1] . "\s*([\-\+\*\/])\s*" . $match[3] . '/', $t, $value);
- break;
- }
- }
- if (strpos($value, '@') !== false) {
- $value = '';
- }
- $this->vars[$name]['id'] = $value;
- }
+ $name = $attrs['name'];
+ $value = $attrs['value'];
+ $match = [];
+ // Current GEDCOM record strings
+ if ($value == '@ID') {
+ if (preg_match('/0 @(.+)@/', $this->gedrec, $match)) {
+ $value = $match[1];
+ }
+ } elseif ($value == '@fact') {
+ $value = $this->fact;
+ } elseif ($value == '@desc') {
+ $value = $this->desc;
+ } elseif ($value == '@generation') {
+ $value = $this->generation;
+ } elseif (preg_match("/@(\w+)/", $value, $match)) {
+ $gmatch = [];
+ if (preg_match("/\d $match[1] (.+)/", $this->gedrec, $gmatch)) {
+ $value = str_replace('@', '', trim($gmatch[1]));
+ }
+ }
+ if (preg_match("/\\$(\w+)/", $name, $match)) {
+ $name = $this->vars["'" . $match[1] . "'"]['id'];
+ }
+ $count = preg_match_all("/\\$(\w+)/", $value, $match, PREG_SET_ORDER);
+ $i = 0;
+ while ($i < $count) {
+ $t = $this->vars[$match[$i][1]]['id'];
+ $value = preg_replace('/\$' . $match[$i][1] . '/', $t, $value, 1);
+ $i++;
+ }
+ if (preg_match('/^I18N::number\((.+)\)$/', $value, $match)) {
+ $value = I18N::number($match[1]);
+ } elseif (preg_match('/^I18N::translate\(\'(.+)\'\)$/', $value, $match)) {
+ $value = I18N::translate($match[1]);
+ } elseif (preg_match('/^I18N::translateContext\(\'(.+)\', *\'(.+)\'\)$/', $value, $match)) {
+ $value = I18N::translateContext($match[1], $match[2]);
+ }
+ // Arithmetic functions
+ if (preg_match("/(\d+)\s*([\-\+\*\/])\s*(\d+)/", $value, $match)) {
+ switch ($match[2]) {
+ case '+':
+ $t = $match[1] + $match[3];
+ $value = preg_replace('/' . $match[1] . "\s*([\-\+\*\/])\s*" . $match[3] . '/', $t, $value);
+ break;
+ case '-':
+ $t = $match[1] - $match[3];
+ $value = preg_replace('/' . $match[1] . "\s*([\-\+\*\/])\s*" . $match[3] . '/', $t, $value);
+ break;
+ case '*':
+ $t = $match[1] * $match[3];
+ $value = preg_replace('/' . $match[1] . "\s*([\-\+\*\/])\s*" . $match[3] . '/', $t, $value);
+ break;
+ case '/':
+ $t = $match[1] / $match[3];
+ $value = preg_replace('/' . $match[1] . "\s*([\-\+\*\/])\s*" . $match[3] . '/', $t, $value);
+ break;
+ }
+ }
+ if (strpos($value, '@') !== false) {
+ $value = '';
+ }
+ $this->vars[$name]['id'] = $value;
+ }
- /**
- * XML <if > start element
- *
- * @param array $attrs an array of key value pairs for the attributes
- */
- private function ifStartHandler($attrs) {
- if ($this->process_ifs > 0) {
- $this->process_ifs++;
+ /**
+ * XML <if > start element
+ *
+ * @param array $attrs an array of key value pairs for the attributes
+ */
+ private function ifStartHandler($attrs)
+ {
+ if ($this->process_ifs > 0) {
+ $this->process_ifs++;
- return;
- }
+ return;
+ }
- $condition = $attrs['condition'];
- $condition = $this->substituteVars($condition, true);
- $condition = str_replace([' LT ', ' GT '], ['<', '>'], $condition);
- // Replace the first accurance only once of @fact:DATE or in any other combinations to the current fact, such as BIRT
- $condition = str_replace('@fact:', $this->fact . ':', $condition);
- $match = [];
- $count = preg_match_all("/@([\w:\.]+)/", $condition, $match, PREG_SET_ORDER);
- $i = 0;
- while ($i < $count) {
- $id = $match[$i][1];
- $value = '""';
- if ($id == 'ID') {
- if (preg_match('/0 @(.+)@/', $this->gedrec, $match)) {
- $value = "'" . $match[1] . "'";
- }
- } elseif ($id === 'fact') {
- $value = '"' . $this->fact . '"';
- } elseif ($id === 'desc') {
- $value = '"' . addslashes($this->desc) . '"';
- } elseif ($id === 'generation') {
- $value = '"' . $this->generation . '"';
- } else {
- $temp = explode(' ', trim($this->gedrec));
- $level = $temp[0];
- if ($level == 0) {
- $level++;
- }
- $value = $this->getGedcomValue($id, $level, $this->gedrec);
- if (empty($value)) {
- $level++;
- $value = $this->getGedcomValue($id, $level, $this->gedrec);
- }
- $value = preg_replace('/^@(' . WT_REGEX_XREF . ')@$/', '$1', $value);
- $value = '"' . addslashes($value) . '"';
- }
- $condition = str_replace("@$id", $value, $condition);
- $i++;
- }
- $ret = eval("return (bool) ($condition);");
- if (!$ret) {
- $this->process_ifs++;
- }
- }
+ $condition = $attrs['condition'];
+ $condition = $this->substituteVars($condition, true);
+ $condition = str_replace([
+ ' LT ',
+ ' GT ',
+ ], [
+ '<',
+ '>',
+ ], $condition);
+ // Replace the first accurance only once of @fact:DATE or in any other combinations to the current fact, such as BIRT
+ $condition = str_replace('@fact:', $this->fact . ':', $condition);
+ $match = [];
+ $count = preg_match_all("/@([\w:\.]+)/", $condition, $match, PREG_SET_ORDER);
+ $i = 0;
+ while ($i < $count) {
+ $id = $match[$i][1];
+ $value = '""';
+ if ($id == 'ID') {
+ if (preg_match('/0 @(.+)@/', $this->gedrec, $match)) {
+ $value = "'" . $match[1] . "'";
+ }
+ } elseif ($id === 'fact') {
+ $value = '"' . $this->fact . '"';
+ } elseif ($id === 'desc') {
+ $value = '"' . addslashes($this->desc) . '"';
+ } elseif ($id === 'generation') {
+ $value = '"' . $this->generation . '"';
+ } else {
+ $temp = explode(' ', trim($this->gedrec));
+ $level = $temp[0];
+ if ($level == 0) {
+ $level++;
+ }
+ $value = $this->getGedcomValue($id, $level, $this->gedrec);
+ if (empty($value)) {
+ $level++;
+ $value = $this->getGedcomValue($id, $level, $this->gedrec);
+ }
+ $value = preg_replace('/^@(' . WT_REGEX_XREF . ')@$/', '$1', $value);
+ $value = '"' . addslashes($value) . '"';
+ }
+ $condition = str_replace("@$id", $value, $condition);
+ $i++;
+ }
+ $ret = eval("return (bool) ($condition);");
+ if (!$ret) {
+ $this->process_ifs++;
+ }
+ }
- /**
- * XML <if /> end element
- */
- private function ifEndHandler() {
- if ($this->process_ifs > 0) {
- $this->process_ifs--;
- }
- }
+ /**
+ * XML <if /> end element
+ */
+ private function ifEndHandler()
+ {
+ if ($this->process_ifs > 0) {
+ $this->process_ifs--;
+ }
+ }
- /**
- * XML <Footnote > start element
- * Collect the Footnote links
- * GEDCOM Records that are protected by Privacy setting will be ignore
- *
- * @param array $attrs an array of key value pairs for the attributes
- */
- private function footnoteStartHandler($attrs) {
- $id = '';
- if (preg_match('/[0-9] (.+) @(.+)@/', $this->gedrec, $match)) {
- $id = $match[2];
- }
- $record = GedcomRecord::getInstance($id, $this->tree);
- if ($record && $record->canShow()) {
- array_push($this->print_data_stack, $this->print_data);
- $this->print_data = true;
- $style = '';
- if (!empty($attrs['style'])) {
- $style = $attrs['style'];
- }
- $this->footnote_element = $this->current_element;
- $this->current_element = $this->report_root->createFootnote($style);
- } else {
- $this->print_data = false;
- $this->process_footnote = false;
- }
- }
+ /**
+ * XML <Footnote > start element
+ * Collect the Footnote links
+ * GEDCOM Records that are protected by Privacy setting will be ignore
+ *
+ * @param array $attrs an array of key value pairs for the attributes
+ */
+ private function footnoteStartHandler($attrs)
+ {
+ $id = '';
+ if (preg_match('/[0-9] (.+) @(.+)@/', $this->gedrec, $match)) {
+ $id = $match[2];
+ }
+ $record = GedcomRecord::getInstance($id, $this->tree);
+ if ($record && $record->canShow()) {
+ array_push($this->print_data_stack, $this->print_data);
+ $this->print_data = true;
+ $style = '';
+ if (!empty($attrs['style'])) {
+ $style = $attrs['style'];
+ }
+ $this->footnote_element = $this->current_element;
+ $this->current_element = $this->report_root->createFootnote($style);
+ } else {
+ $this->print_data = false;
+ $this->process_footnote = false;
+ }
+ }
- /**
- * XML <Footnote /> end element
- * Print the collected Footnote data
- */
- private function footnoteEndHandler() {
- if ($this->process_footnote) {
- $this->print_data = array_pop($this->print_data_stack);
- $temp = trim($this->current_element->getValue());
- if (strlen($temp) > 3) {
- $this->wt_report->addElement($this->current_element);
- }
- $this->current_element = $this->footnote_element;
- } else {
- $this->process_footnote = true;
- }
- }
+ /**
+ * XML <Footnote /> end element
+ * Print the collected Footnote data
+ */
+ private function footnoteEndHandler()
+ {
+ if ($this->process_footnote) {
+ $this->print_data = array_pop($this->print_data_stack);
+ $temp = trim($this->current_element->getValue());
+ if (strlen($temp) > 3) {
+ $this->wt_report->addElement($this->current_element);
+ }
+ $this->current_element = $this->footnote_element;
+ } else {
+ $this->process_footnote = true;
+ }
+ }
- /**
- * XML <FootnoteTexts /> element
- */
- private function footnoteTextsStartHandler() {
- $temp = 'footnotetexts';
- $this->wt_report->addElement($temp);
- }
+ /**
+ * XML <FootnoteTexts /> element
+ */
+ private function footnoteTextsStartHandler()
+ {
+ $temp = 'footnotetexts';
+ $this->wt_report->addElement($temp);
+ }
- /**
- * XML <AgeAtDeath /> element handler
- */
- private function ageAtDeathStartHandler() {
- // This duplicates functionality in FunctionsPrint::format_fact_date()
- global $factrec;
+ /**
+ * XML <AgeAtDeath /> element handler
+ */
+ private function ageAtDeathStartHandler()
+ {
+ // This duplicates functionality in FunctionsPrint::format_fact_date()
+ global $factrec;
- $match = [];
- if (preg_match('/0 @(.+)@/', $this->gedrec, $match)) {
- $person = Individual::getInstance($match[1], $this->tree);
- // Recorded age
- if (preg_match('/\n2 AGE (.+)/', $factrec, $match)) {
- $fact_age = $match[1];
- } else {
- $fact_age = '';
- }
- if (preg_match('/\n2 HUSB\n3 AGE (.+)/', $factrec, $match)) {
- $husb_age = $match[1];
- } else {
- $husb_age = '';
- }
- if (preg_match('/\n2 WIFE\n3 AGE (.+)/', $factrec, $match)) {
- $wife_age = $match[1];
- } else {
- $wife_age = '';
- }
+ $match = [];
+ if (preg_match('/0 @(.+)@/', $this->gedrec, $match)) {
+ $person = Individual::getInstance($match[1], $this->tree);
+ // Recorded age
+ if (preg_match('/\n2 AGE (.+)/', $factrec, $match)) {
+ $fact_age = $match[1];
+ } else {
+ $fact_age = '';
+ }
+ if (preg_match('/\n2 HUSB\n3 AGE (.+)/', $factrec, $match)) {
+ $husb_age = $match[1];
+ } else {
+ $husb_age = '';
+ }
+ if (preg_match('/\n2 WIFE\n3 AGE (.+)/', $factrec, $match)) {
+ $wife_age = $match[1];
+ } else {
+ $wife_age = '';
+ }
- // Calculated age
- $birth_date = $person->getBirthDate();
- // Can't use getDeathDate(), as this also gives BURI/CREM events, which
- // wouldn't give the correct "days after death" result for people with
- // no DEAT.
- $death_event = $person->getFirstFact('DEAT');
- if ($death_event) {
- $death_date = $death_event->getDate();
- } else {
- $death_date = new Date('');
- }
- $value = '';
- if (Date::compare($birth_date, $death_date) <= 0 || !$person->isDead()) {
- $age = Date::getAgeGedcom($birth_date, $death_date);
- // Only show calculated age if it differs from recorded age
- if ($age != '' && $age != '0d') {
- if ($fact_age != '' && $fact_age != $age || $fact_age == '' && $husb_age == '' && $wife_age == '' || $husb_age != '' && $person->getSex() == 'M' && $husb_age != $age || $wife_age != '' && $person->getSex() == 'F' && $wife_age != $age
- ) {
- $value = FunctionsDate::getAgeAtEvent($age);
- $abbrev = substr($value, 0, strpos($value, ' ') + 5);
- if ($value !== $abbrev) {
- $value = $abbrev . '.';
- }
- }
- }
- }
- $this->current_element->addText($value);
- }
- }
+ // Calculated age
+ $birth_date = $person->getBirthDate();
+ // Can't use getDeathDate(), as this also gives BURI/CREM events, which
+ // wouldn't give the correct "days after death" result for people with
+ // no DEAT.
+ $death_event = $person->getFirstFact('DEAT');
+ if ($death_event) {
+ $death_date = $death_event->getDate();
+ } else {
+ $death_date = new Date('');
+ }
+ $value = '';
+ if (Date::compare($birth_date, $death_date) <= 0 || !$person->isDead()) {
+ $age = Date::getAgeGedcom($birth_date, $death_date);
+ // Only show calculated age if it differs from recorded age
+ if ($age != '' && $age != '0d') {
+ if ($fact_age != '' && $fact_age != $age || $fact_age == '' && $husb_age == '' && $wife_age == '' || $husb_age != '' && $person->getSex() == 'M' && $husb_age != $age || $wife_age != '' && $person->getSex() == 'F' && $wife_age != $age
+ ) {
+ $value = FunctionsDate::getAgeAtEvent($age);
+ $abbrev = substr($value, 0, strpos($value, ' ') + 5);
+ if ($value !== $abbrev) {
+ $value = $abbrev . '.';
+ }
+ }
+ }
+ }
+ $this->current_element->addText($value);
+ }
+ }
- /**
- * XML element Forced line break handler - HTML code
- */
- private function brStartHandler() {
- if ($this->print_data && $this->process_gedcoms === 0) {
- $this->current_element->addText('<br>');
- }
- }
+ /**
+ * XML element Forced line break handler - HTML code
+ */
+ private function brStartHandler()
+ {
+ if ($this->print_data && $this->process_gedcoms === 0) {
+ $this->current_element->addText('<br>');
+ }
+ }
- /**
- * XML <sp />element Forced space handler
- */
- private function spStartHandler() {
- if ($this->print_data && $this->process_gedcoms === 0) {
- $this->current_element->addText(' ');
- }
- }
+ /**
+ * XML <sp />element Forced space handler
+ */
+ private function spStartHandler()
+ {
+ if ($this->print_data && $this->process_gedcoms === 0) {
+ $this->current_element->addText(' ');
+ }
+ }
- /**
- * XML <HighlightedImage/>
- *
- * @param array $attrs an array of key value pairs for the attributes
- */
- private function highlightedImageStartHandler($attrs) {
- $id = '';
- $match = [];
- if (preg_match('/0 @(.+)@/', $this->gedrec, $match)) {
- $id = $match[1];
- }
+ /**
+ * XML <HighlightedImage/>
+ *
+ * @param array $attrs an array of key value pairs for the attributes
+ */
+ private function highlightedImageStartHandler($attrs)
+ {
+ $id = '';
+ $match = [];
+ if (preg_match('/0 @(.+)@/', $this->gedrec, $match)) {
+ $id = $match[1];
+ }
- // mixed Position the top corner of this box on the page. the default is the current position
- $top = '.';
- if (isset($attrs['top'])) {
- if ($attrs['top'] === '0') {
- $top = 0;
- } elseif ($attrs['top'] === '.') {
- $top = '.';
- } elseif (!empty($attrs['top'])) {
- $top = (int) $attrs['top'];
- }
- }
+ // mixed Position the top corner of this box on the page. the default is the current position
+ $top = '.';
+ if (isset($attrs['top'])) {
+ if ($attrs['top'] === '0') {
+ $top = 0;
+ } elseif ($attrs['top'] === '.') {
+ $top = '.';
+ } elseif (!empty($attrs['top'])) {
+ $top = (int)$attrs['top'];
+ }
+ }
- // mixed Position the left corner of this box on the page. the default is the current position
- $left = '.';
- if (isset($attrs['left'])) {
- if ($attrs['left'] === '0') {
- $left = 0;
- } elseif ($attrs['left'] === '.') {
- $left = '.';
- } elseif (!empty($attrs['left'])) {
- $left = (int) $attrs['left'];
- }
- }
+ // mixed Position the left corner of this box on the page. the default is the current position
+ $left = '.';
+ if (isset($attrs['left'])) {
+ if ($attrs['left'] === '0') {
+ $left = 0;
+ } elseif ($attrs['left'] === '.') {
+ $left = '.';
+ } elseif (!empty($attrs['left'])) {
+ $left = (int)$attrs['left'];
+ }
+ }
- // string Align the image in left, center, right
- $align = '';
- if (!empty($attrs['align'])) {
- $align = $attrs['align'];
- }
+ // string Align the image in left, center, right
+ $align = '';
+ if (!empty($attrs['align'])) {
+ $align = $attrs['align'];
+ }
- // string Next Line should be T:next to the image, N:next line
- $ln = '';
- if (!empty($attrs['ln'])) {
- $ln = $attrs['ln'];
- }
+ // string Next Line should be T:next to the image, N:next line
+ $ln = '';
+ if (!empty($attrs['ln'])) {
+ $ln = $attrs['ln'];
+ }
- $width = 0;
- $height = 0;
- if (!empty($attrs['width'])) {
- $width = (int) $attrs['width'];
- }
- if (!empty($attrs['height'])) {
- $height = (int) $attrs['height'];
- }
+ $width = 0;
+ $height = 0;
+ if (!empty($attrs['width'])) {
+ $width = (int)$attrs['width'];
+ }
+ if (!empty($attrs['height'])) {
+ $height = (int)$attrs['height'];
+ }
- $person = Individual::getInstance($id, $this->tree);
- $media_file = $person->findHighlightedMediaFile();
+ $person = Individual::getInstance($id, $this->tree);
+ $media_file = $person->findHighlightedMediaFile();
- if ($media_file !== null && $media_file->fileExists()) {
- $attributes = getimagesize($media_file->getServerFilename()) ?: [0, 0];
- if ($width > 0 && $height == 0) {
- $perc = $width / $attributes[0];
- $height = round($attributes[1] * $perc);
- } elseif ($height > 0 && $width == 0) {
- $perc = $height / $attributes[1];
- $width = round($attributes[0] * $perc);
- } else {
- $width = $attributes[0];
- $height = $attributes[1];
- }
- $image = $this->report_root->createImageFromObject($media_file, $left, $top, $width, $height, $align, $ln);
- $this->wt_report->addElement($image);
- }
- }
+ if ($media_file !== null && $media_file->fileExists()) {
+ $attributes = getimagesize($media_file->getServerFilename()) ?: [
+ 0,
+ 0,
+ ];
+ if ($width > 0 && $height == 0) {
+ $perc = $width / $attributes[0];
+ $height = round($attributes[1] * $perc);
+ } elseif ($height > 0 && $width == 0) {
+ $perc = $height / $attributes[1];
+ $width = round($attributes[0] * $perc);
+ } else {
+ $width = $attributes[0];
+ $height = $attributes[1];
+ }
+ $image = $this->report_root->createImageFromObject($media_file, $left, $top, $width, $height, $align, $ln);
+ $this->wt_report->addElement($image);
+ }
+ }
- /**
- * XML <Image/>
- *
- * @param array $attrs an array of key value pairs for the attributes
- */
- private function imageStartHandler($attrs) {
- // mixed Position the top corner of this box on the page. the default is the current position
- $top = '.';
- if (isset($attrs['top'])) {
- if ($attrs['top'] === '0') {
- $top = 0;
- } elseif ($attrs['top'] === '.') {
- $top = '.';
- } elseif (!empty($attrs['top'])) {
- $top = (int) $attrs['top'];
- }
- }
+ /**
+ * XML <Image/>
+ *
+ * @param array $attrs an array of key value pairs for the attributes
+ */
+ private function imageStartHandler($attrs)
+ {
+ // mixed Position the top corner of this box on the page. the default is the current position
+ $top = '.';
+ if (isset($attrs['top'])) {
+ if ($attrs['top'] === '0') {
+ $top = 0;
+ } elseif ($attrs['top'] === '.') {
+ $top = '.';
+ } elseif (!empty($attrs['top'])) {
+ $top = (int)$attrs['top'];
+ }
+ }
- // mixed Position the left corner of this box on the page. the default is the current position
- $left = '.';
- if (isset($attrs['left'])) {
- if ($attrs['left'] === '0') {
- $left = 0;
- } elseif ($attrs['left'] === '.') {
- $left = '.';
- } elseif (!empty($attrs['left'])) {
- $left = (int) $attrs['left'];
- }
- }
+ // mixed Position the left corner of this box on the page. the default is the current position
+ $left = '.';
+ if (isset($attrs['left'])) {
+ if ($attrs['left'] === '0') {
+ $left = 0;
+ } elseif ($attrs['left'] === '.') {
+ $left = '.';
+ } elseif (!empty($attrs['left'])) {
+ $left = (int)$attrs['left'];
+ }
+ }
- // string Align the image in left, center, right
- $align = '';
- if (!empty($attrs['align'])) {
- $align = $attrs['align'];
- }
+ // string Align the image in left, center, right
+ $align = '';
+ if (!empty($attrs['align'])) {
+ $align = $attrs['align'];
+ }
- // string Next Line should be T:next to the image, N:next line
- $ln = 'T';
- if (!empty($attrs['ln'])) {
- $ln = $attrs['ln'];
- }
+ // string Next Line should be T:next to the image, N:next line
+ $ln = 'T';
+ if (!empty($attrs['ln'])) {
+ $ln = $attrs['ln'];
+ }
- $width = 0;
- $height = 0;
- if (!empty($attrs['width'])) {
- $width = (int) $attrs['width'];
- }
- if (!empty($attrs['height'])) {
- $height = (int) $attrs['height'];
- }
+ $width = 0;
+ $height = 0;
+ if (!empty($attrs['width'])) {
+ $width = (int)$attrs['width'];
+ }
+ if (!empty($attrs['height'])) {
+ $height = (int)$attrs['height'];
+ }
- $file = '';
- if (!empty($attrs['file'])) {
- $file = $attrs['file'];
- }
- if ($file == '@FILE') {
- $match = [];
- if (preg_match("/\d OBJE @(.+)@/", $this->gedrec, $match)) {
- $mediaobject = Media::getInstance($match[1], $this->tree);
- $media_file = $mediaobject->firstImageFile();
+ $file = '';
+ if (!empty($attrs['file'])) {
+ $file = $attrs['file'];
+ }
+ if ($file == '@FILE') {
+ $match = [];
+ if (preg_match("/\d OBJE @(.+)@/", $this->gedrec, $match)) {
+ $mediaobject = Media::getInstance($match[1], $this->tree);
+ $media_file = $mediaobject->firstImageFile();
- if ($media_file !== null && $media_file->fileExists()) {
- $attributes = getimagesize($media_file->getServerFilename()) ?: [0, 0];
- if ($width > 0 && $height == 0) {
- $perc = $width / $attributes[0];
- $height = round($attributes[1] * $perc);
- } elseif ($height > 0 && $width == 0) {
- $perc = $height / $attributes[1];
- $width = round($attributes[0] * $perc);
- } else {
- $width = $attributes[0];
- $height = $attributes[1];
- }
- $image = $this->report_root->createImageFromObject($media_file, $left, $top, $width, $height, $align, $ln);
- $this->wt_report->addElement($image);
- }
- }
- } else {
- if (file_exists($file) && preg_match('/(jpg|jpeg|png|gif)$/i', $file)) {
- $size = getimagesize($file);
- if ($width > 0 && $height == 0) {
- $perc = $width / $size[0];
- $height = round($size[1] * $perc);
- } elseif ($height > 0 && $width == 0) {
- $perc = $height / $size[1];
- $width = round($size[0] * $perc);
- } else {
- $width = $size[0];
- $height = $size[1];
- }
- $image = $this->report_root->createImage($file, $left, $top, $width, $height, $align, $ln);
- $this->wt_report->addElement($image);
- }
- }
- }
+ if ($media_file !== null && $media_file->fileExists()) {
+ $attributes = getimagesize($media_file->getServerFilename()) ?: [
+ 0,
+ 0,
+ ];
+ if ($width > 0 && $height == 0) {
+ $perc = $width / $attributes[0];
+ $height = round($attributes[1] * $perc);
+ } elseif ($height > 0 && $width == 0) {
+ $perc = $height / $attributes[1];
+ $width = round($attributes[0] * $perc);
+ } else {
+ $width = $attributes[0];
+ $height = $attributes[1];
+ }
+ $image = $this->report_root->createImageFromObject($media_file, $left, $top, $width, $height, $align, $ln);
+ $this->wt_report->addElement($image);
+ }
+ }
+ } else {
+ if (file_exists($file) && preg_match('/(jpg|jpeg|png|gif)$/i', $file)) {
+ $size = getimagesize($file);
+ if ($width > 0 && $height == 0) {
+ $perc = $width / $size[0];
+ $height = round($size[1] * $perc);
+ } elseif ($height > 0 && $width == 0) {
+ $perc = $height / $size[1];
+ $width = round($size[0] * $perc);
+ } else {
+ $width = $size[0];
+ $height = $size[1];
+ }
+ $image = $this->report_root->createImage($file, $left, $top, $width, $height, $align, $ln);
+ $this->wt_report->addElement($image);
+ }
+ }
+ }
- /**
- * XML <Line> element handler
- *
- * @param array $attrs an array of key value pairs for the attributes
- */
- private function lineStartHandler($attrs) {
- // Start horizontal position, current position (default)
- $x1 = '.';
- if (isset($attrs['x1'])) {
- if ($attrs['x1'] === '0') {
- $x1 = 0;
- } elseif ($attrs['x1'] === '.') {
- $x1 = '.';
- } elseif (!empty($attrs['x1'])) {
- $x1 = (int) $attrs['x1'];
- }
- }
- // Start vertical position, current position (default)
- $y1 = '.';
- if (isset($attrs['y1'])) {
- if ($attrs['y1'] === '0') {
- $y1 = 0;
- } elseif ($attrs['y1'] === '.') {
- $y1 = '.';
- } elseif (!empty($attrs['y1'])) {
- $y1 = (int) $attrs['y1'];
- }
- }
- // End horizontal position, maximum width (default)
- $x2 = '.';
- if (isset($attrs['x2'])) {
- if ($attrs['x2'] === '0') {
- $x2 = 0;
- } elseif ($attrs['x2'] === '.') {
- $x2 = '.';
- } elseif (!empty($attrs['x2'])) {
- $x2 = (int) $attrs['x2'];
- }
- }
- // End vertical position
- $y2 = '.';
- if (isset($attrs['y2'])) {
- if ($attrs['y2'] === '0') {
- $y2 = 0;
- } elseif ($attrs['y2'] === '.') {
- $y2 = '.';
- } elseif (!empty($attrs['y2'])) {
- $y2 = (int) $attrs['y2'];
- }
- }
+ /**
+ * XML <Line> element handler
+ *
+ * @param array $attrs an array of key value pairs for the attributes
+ */
+ private function lineStartHandler($attrs)
+ {
+ // Start horizontal position, current position (default)
+ $x1 = '.';
+ if (isset($attrs['x1'])) {
+ if ($attrs['x1'] === '0') {
+ $x1 = 0;
+ } elseif ($attrs['x1'] === '.') {
+ $x1 = '.';
+ } elseif (!empty($attrs['x1'])) {
+ $x1 = (int)$attrs['x1'];
+ }
+ }
+ // Start vertical position, current position (default)
+ $y1 = '.';
+ if (isset($attrs['y1'])) {
+ if ($attrs['y1'] === '0') {
+ $y1 = 0;
+ } elseif ($attrs['y1'] === '.') {
+ $y1 = '.';
+ } elseif (!empty($attrs['y1'])) {
+ $y1 = (int)$attrs['y1'];
+ }
+ }
+ // End horizontal position, maximum width (default)
+ $x2 = '.';
+ if (isset($attrs['x2'])) {
+ if ($attrs['x2'] === '0') {
+ $x2 = 0;
+ } elseif ($attrs['x2'] === '.') {
+ $x2 = '.';
+ } elseif (!empty($attrs['x2'])) {
+ $x2 = (int)$attrs['x2'];
+ }
+ }
+ // End vertical position
+ $y2 = '.';
+ if (isset($attrs['y2'])) {
+ if ($attrs['y2'] === '0') {
+ $y2 = 0;
+ } elseif ($attrs['y2'] === '.') {
+ $y2 = '.';
+ } elseif (!empty($attrs['y2'])) {
+ $y2 = (int)$attrs['y2'];
+ }
+ }
- $line = $this->report_root->createLine($x1, $y1, $x2, $y2);
- $this->wt_report->addElement($line);
- }
+ $line = $this->report_root->createLine($x1, $y1, $x2, $y2);
+ $this->wt_report->addElement($line);
+ }
- /**
- * XML <List>
- *
- * @param array $attrs an array of key value pairs for the attributes
- */
- private function listStartHandler($attrs) {
- $this->process_repeats++;
- if ($this->process_repeats > 1) {
- return;
- }
+ /**
+ * XML <List>
+ *
+ * @param array $attrs an array of key value pairs for the attributes
+ */
+ private function listStartHandler($attrs)
+ {
+ $this->process_repeats++;
+ if ($this->process_repeats > 1) {
+ return;
+ }
- $match = [];
- if (isset($attrs['sortby'])) {
- $sortby = $attrs['sortby'];
- if (preg_match("/\\$(\w+)/", $sortby, $match)) {
- $sortby = $this->vars[$match[1]]['id'];
- $sortby = trim($sortby);
- }
- } else {
- $sortby = 'NAME';
- }
+ $match = [];
+ if (isset($attrs['sortby'])) {
+ $sortby = $attrs['sortby'];
+ if (preg_match("/\\$(\w+)/", $sortby, $match)) {
+ $sortby = $this->vars[$match[1]]['id'];
+ $sortby = trim($sortby);
+ }
+ } else {
+ $sortby = 'NAME';
+ }
- if (isset($attrs['list'])) {
- $listname = $attrs['list'];
- } else {
- $listname = 'individual';
- }
- // Some filters/sorts can be applied using SQL, while others require PHP
- switch ($listname) {
- case 'pending':
- $rows = Database::prepare(
- "SELECT xref, CASE new_gedcom WHEN '' THEN old_gedcom ELSE new_gedcom END AS gedcom" .
- " FROM `##change`" . " WHERE (xref, change_id) IN (" .
- " SELECT xref, MAX(change_id)" .
- " FROM `##change`" .
- " WHERE status = 'pending' AND gedcom_id = :tree_id" .
- " GROUP BY xref" .
- " )"
- )->execute([
- 'tree_id' => $this->tree->getTreeId(),
- ])->fetchAll();
- $this->list = [];
- foreach ($rows as $row) {
- $this->list[] = GedcomRecord::getInstance($row->xref, $this->tree, $row->gedcom);
- }
- break;
- case 'individual':
- $sql_select = "SELECT i_id AS xref, i_gedcom AS gedcom FROM `##individuals` ";
- $sql_join = "";
- $sql_where = " WHERE i_file = :tree_id";
- $sql_order_by = "";
- $sql_params = ['tree_id' => $this->tree->getTreeId()];
- foreach ($attrs as $attr => $value) {
- if (strpos($attr, 'filter') === 0 && $value) {
- $value = $this->substituteVars($value, false);
- // Convert the various filters into SQL
- if (preg_match('/^(\w+):DATE (LTE|GTE) (.+)$/', $value, $match)) {
- $sql_join .= " JOIN `##dates` AS {$attr} ON ({$attr}.d_file=i_file AND {$attr}.d_gid=i_id)";
- $sql_where .= " AND {$attr}.d_fact = :{$attr}fact";
- $sql_params[$attr . 'fact'] = $match[1];
- $date = new Date($match[3]);
- if ($match[2] == 'LTE') {
- $sql_where .= " AND {$attr}.d_julianday2 <= :{$attr}date";
- $sql_params[$attr . 'date'] = $date->maximumJulianDay();
- } else {
- $sql_where .= " AND {$attr}.d_julianday1 >= :{$attr}date";
- $sql_params[$attr . 'date'] = $date->minimumJulianDay();
- }
- if ($sortby == $match[1]) {
- $sortby = "";
- $sql_order_by .= ($sql_order_by ? ", " : " ORDER BY ") . "{$attr}.d_julianday1";
- }
- unset($attrs[$attr]); // This filter has been fully processed
- } elseif (preg_match('/^NAME CONTAINS (.*)$/', $value, $match)) {
- // Do nothing, unless you have to
- if ($match[1] != '' || $sortby == 'NAME') {
- $sql_join .= " JOIN `##name` AS {$attr} ON (n_file=i_file AND n_id=i_id)";
- // Search the DB only if there is any name supplied
- if ($match[1] != '') {
- $names = explode(' ', $match[1]);
- foreach ($names as $n => $name) {
- $sql_where .= " AND {$attr}.n_full LIKE CONCAT('%', :{$attr}name{$n}, '%')";
- $sql_params[$attr . 'name' . $n] = $name;
- }
- }
- // Let the DB do the name sorting even when no name was entered
- if ($sortby == 'NAME') {
- $sortby = '';
- $sql_order_by .= ($sql_order_by ? ', ' : ' ORDER BY ') . "{$attr}.n_sort";
- }
- }
- unset($attrs[$attr]); // This filter has been fully processed
- } elseif (preg_match('/^REGEXP \/(.+)\//', $value, $match)) {
- $sql_where .= " AND i_gedcom REGEXP :{$attr}gedcom";
- // PDO helpfully escapes backslashes for us, preventing us from matching "\n1 FACT"
- $sql_params[$attr . 'gedcom'] = str_replace('\n', "\n", $match[1]);
- unset($attrs[$attr]); // This filter has been fully processed
- } elseif (preg_match('/^(?:\w+):PLAC CONTAINS (.+)$/', $value, $match)) {
- $sql_join .= " JOIN `##places` AS {$attr}a ON ({$attr}a.p_file = i_file)";
- $sql_join .= " JOIN `##placelinks` AS {$attr}b ON ({$attr}a.p_file = {$attr}b.pl_file AND {$attr}b.pl_p_id = {$attr}a.p_id AND {$attr}b.pl_gid = i_id)";
- $sql_where .= " AND {$attr}a.p_place LIKE CONCAT('%', :{$attr}place, '%')";
- $sql_params[$attr . 'place'] = $match[1];
- // Don't unset this filter. This is just initial filtering
- } elseif (preg_match('/^(\w*):*(\w*) CONTAINS (.+)$/', $value, $match)) {
- $sql_where .= " AND i_gedcom LIKE CONCAT('%', :{$attr}contains1, '%', :{$attr}contains2, '%', :{$attr}contains3, '%')";
- $sql_params[$attr . 'contains1'] = $match[1];
- $sql_params[$attr . 'contains2'] = $match[2];
- $sql_params[$attr . 'contains3'] = $match[3];
- // Don't unset this filter. This is just initial filtering
- }
- }
- }
+ if (isset($attrs['list'])) {
+ $listname = $attrs['list'];
+ } else {
+ $listname = 'individual';
+ }
+ // Some filters/sorts can be applied using SQL, while others require PHP
+ switch ($listname) {
+ case 'pending':
+ $rows = Database::prepare(
+ "SELECT xref, CASE new_gedcom WHEN '' THEN old_gedcom ELSE new_gedcom END AS gedcom" .
+ " FROM `##change`" . " WHERE (xref, change_id) IN (" .
+ " SELECT xref, MAX(change_id)" .
+ " FROM `##change`" .
+ " WHERE status = 'pending' AND gedcom_id = :tree_id" .
+ " GROUP BY xref" .
+ " )"
+ )->execute([
+ 'tree_id' => $this->tree->getTreeId(),
+ ])->fetchAll();
+ $this->list = [];
+ foreach ($rows as $row) {
+ $this->list[] = GedcomRecord::getInstance($row->xref, $this->tree, $row->gedcom);
+ }
+ break;
+ case 'individual':
+ $sql_select = "SELECT i_id AS xref, i_gedcom AS gedcom FROM `##individuals` ";
+ $sql_join = "";
+ $sql_where = " WHERE i_file = :tree_id";
+ $sql_order_by = "";
+ $sql_params = ['tree_id' => $this->tree->getTreeId()];
+ foreach ($attrs as $attr => $value) {
+ if (strpos($attr, 'filter') === 0 && $value) {
+ $value = $this->substituteVars($value, false);
+ // Convert the various filters into SQL
+ if (preg_match('/^(\w+):DATE (LTE|GTE) (.+)$/', $value, $match)) {
+ $sql_join .= " JOIN `##dates` AS {$attr} ON ({$attr}.d_file=i_file AND {$attr}.d_gid=i_id)";
+ $sql_where .= " AND {$attr}.d_fact = :{$attr}fact";
+ $sql_params[$attr . 'fact'] = $match[1];
+ $date = new Date($match[3]);
+ if ($match[2] == 'LTE') {
+ $sql_where .= " AND {$attr}.d_julianday2 <= :{$attr}date";
+ $sql_params[$attr . 'date'] = $date->maximumJulianDay();
+ } else {
+ $sql_where .= " AND {$attr}.d_julianday1 >= :{$attr}date";
+ $sql_params[$attr . 'date'] = $date->minimumJulianDay();
+ }
+ if ($sortby == $match[1]) {
+ $sortby = "";
+ $sql_order_by .= ($sql_order_by ? ", " : " ORDER BY ") . "{$attr}.d_julianday1";
+ }
+ unset($attrs[$attr]); // This filter has been fully processed
+ } elseif (preg_match('/^NAME CONTAINS (.*)$/', $value, $match)) {
+ // Do nothing, unless you have to
+ if ($match[1] != '' || $sortby == 'NAME') {
+ $sql_join .= " JOIN `##name` AS {$attr} ON (n_file=i_file AND n_id=i_id)";
+ // Search the DB only if there is any name supplied
+ if ($match[1] != '') {
+ $names = explode(' ', $match[1]);
+ foreach ($names as $n => $name) {
+ $sql_where .= " AND {$attr}.n_full LIKE CONCAT('%', :{$attr}name{$n}, '%')";
+ $sql_params[$attr . 'name' . $n] = $name;
+ }
+ }
+ // Let the DB do the name sorting even when no name was entered
+ if ($sortby == 'NAME') {
+ $sortby = '';
+ $sql_order_by .= ($sql_order_by ? ', ' : ' ORDER BY ') . "{$attr}.n_sort";
+ }
+ }
+ unset($attrs[$attr]); // This filter has been fully processed
+ } elseif (preg_match('/^REGEXP \/(.+)\//', $value, $match)) {
+ $sql_where .= " AND i_gedcom REGEXP :{$attr}gedcom";
+ // PDO helpfully escapes backslashes for us, preventing us from matching "\n1 FACT"
+ $sql_params[$attr . 'gedcom'] = str_replace('\n', "\n", $match[1]);
+ unset($attrs[$attr]); // This filter has been fully processed
+ } elseif (preg_match('/^(?:\w+):PLAC CONTAINS (.+)$/', $value, $match)) {
+ $sql_join .= " JOIN `##places` AS {$attr}a ON ({$attr}a.p_file = i_file)";
+ $sql_join .= " JOIN `##placelinks` AS {$attr}b ON ({$attr}a.p_file = {$attr}b.pl_file AND {$attr}b.pl_p_id = {$attr}a.p_id AND {$attr}b.pl_gid = i_id)";
+ $sql_where .= " AND {$attr}a.p_place LIKE CONCAT('%', :{$attr}place, '%')";
+ $sql_params[$attr . 'place'] = $match[1];
+ // Don't unset this filter. This is just initial filtering
+ } elseif (preg_match('/^(\w*):*(\w*) CONTAINS (.+)$/', $value, $match)) {
+ $sql_where .= " AND i_gedcom LIKE CONCAT('%', :{$attr}contains1, '%', :{$attr}contains2, '%', :{$attr}contains3, '%')";
+ $sql_params[$attr . 'contains1'] = $match[1];
+ $sql_params[$attr . 'contains2'] = $match[2];
+ $sql_params[$attr . 'contains3'] = $match[3];
+ // Don't unset this filter. This is just initial filtering
+ }
+ }
+ }
- $this->list = [];
- $rows = Database::prepare(
- $sql_select . $sql_join . $sql_where . $sql_order_by
- )->execute($sql_params)->fetchAll();
+ $this->list = [];
+ $rows = Database::prepare(
+ $sql_select . $sql_join . $sql_where . $sql_order_by
+ )->execute($sql_params)->fetchAll();
- foreach ($rows as $row) {
- $this->list[$row->xref] = Individual::getInstance($row->xref, $this->tree, $row->gedcom);
- }
- break;
+ foreach ($rows as $row) {
+ $this->list[$row->xref] = Individual::getInstance($row->xref, $this->tree, $row->gedcom);
+ }
+ break;
- case 'family':
- $sql_select = "SELECT f_id AS xref, f_gedcom AS gedcom FROM `##families`";
- $sql_join = "";
- $sql_where = " WHERE f_file = :tree_id";
- $sql_order_by = "";
- $sql_params = ['tree_id' => $this->tree->getTreeId()];
- foreach ($attrs as $attr => $value) {
- if (strpos($attr, 'filter') === 0 && $value) {
- $value = $this->substituteVars($value, false);
- // Convert the various filters into SQL
- if (preg_match('/^(\w+):DATE (LTE|GTE) (.+)$/', $value, $match)) {
- $sql_join .= " JOIN `##dates` AS {$attr} ON ({$attr}.d_file=f_file AND {$attr}.d_gid=f_id)";
- $sql_where .= " AND {$attr}.d_fact = :{$attr}fact";
- $sql_params[$attr . 'fact'] = $match[1];
- $date = new Date($match[3]);
- if ($match[2] == 'LTE') {
- $sql_where .= " AND {$attr}.d_julianday2 <= :{$attr}date";
- $sql_params[$attr . 'date'] = $date->maximumJulianDay();
- } else {
- $sql_where .= " AND {$attr}.d_julianday1 >= :{$attr}date";
- $sql_params[$attr . 'date'] = $date->minimumJulianDay();
- }
- if ($sortby == $match[1]) {
- $sortby = '';
- $sql_order_by .= ($sql_order_by ? ', ' : ' ORDER BY ') . "{$attr}.d_julianday1";
- }
- unset($attrs[$attr]); // This filter has been fully processed
- } elseif (preg_match('/^REGEXP \/(.+)\//', $value, $match)) {
- $sql_where .= " AND f_gedcom REGEXP :{$attr}gedcom";
- // PDO helpfully escapes backslashes for us, preventing us from matching "\n1 FACT"
- $sql_params[$attr . 'gedcom'] = str_replace('\n', "\n", $match[1]);
- unset($attrs[$attr]); // This filter has been fully processed
- } elseif (preg_match('/^NAME CONTAINS (.+)$/', $value, $match)) {
- // Do nothing, unless you have to
- if ($match[1] != '' || $sortby == 'NAME') {
- $sql_join .= " JOIN `##name` AS {$attr} ON n_file = f_file AND n_id IN (f_husb, f_wife)";
- // Search the DB only if there is any name supplied
- if ($match[1] != '') {
- $names = explode(' ', $match[1]);
- foreach ($names as $n => $name) {
- $sql_where .= " AND {$attr}.n_full LIKE CONCAT('%', :{$attr}name{$n}, '%')";
- $sql_params[$attr . 'name' . $n] = $name;
- }
- }
- // Let the DB do the name sorting even when no name was entered
- if ($sortby == 'NAME') {
- $sortby = '';
- $sql_order_by .= ($sql_order_by ? ', ' : ' ORDER BY ') . "{$attr}.n_sort";
- }
- }
- unset($attrs[$attr]); // This filter has been fully processed
- } elseif (preg_match('/^(?:\w+):PLAC CONTAINS (.+)$/', $value, $match)) {
- $sql_join .= " JOIN `##places` AS {$attr}a ON ({$attr}a.p_file=f_file)";
- $sql_join .= " JOIN `##placelinks` AS {$attr}b ON ({$attr}a.p_file={$attr}b.pl_file AND {$attr}b.pl_p_id={$attr}a.p_id AND {$attr}b.pl_gid=f_id)";
- $sql_where .= " AND {$attr}a.p_place LIKE CONCAT('%', :{$attr}place, '%')";
- $sql_params[$attr . 'place'] = $match[1];
- // Don't unset this filter. This is just initial filtering
- } elseif (preg_match('/^(\w*):*(\w*) CONTAINS (.+)$/', $value, $match)) {
- $sql_where .= " AND f_gedcom LIKE CONCAT('%', :{$attr}contains1, '%', :{$attr}contains2, '%', :{$attr}contains3, '%')";
- $sql_params[$attr . 'contains1'] = $match[1];
- $sql_params[$attr . 'contains2'] = $match[2];
- $sql_params[$attr . 'contains3'] = $match[3];
- // Don't unset this filter. This is just initial filtering
- }
- }
- }
+ case 'family':
+ $sql_select = "SELECT f_id AS xref, f_gedcom AS gedcom FROM `##families`";
+ $sql_join = "";
+ $sql_where = " WHERE f_file = :tree_id";
+ $sql_order_by = "";
+ $sql_params = ['tree_id' => $this->tree->getTreeId()];
+ foreach ($attrs as $attr => $value) {
+ if (strpos($attr, 'filter') === 0 && $value) {
+ $value = $this->substituteVars($value, false);
+ // Convert the various filters into SQL
+ if (preg_match('/^(\w+):DATE (LTE|GTE) (.+)$/', $value, $match)) {
+ $sql_join .= " JOIN `##dates` AS {$attr} ON ({$attr}.d_file=f_file AND {$attr}.d_gid=f_id)";
+ $sql_where .= " AND {$attr}.d_fact = :{$attr}fact";
+ $sql_params[$attr . 'fact'] = $match[1];
+ $date = new Date($match[3]);
+ if ($match[2] == 'LTE') {
+ $sql_where .= " AND {$attr}.d_julianday2 <= :{$attr}date";
+ $sql_params[$attr . 'date'] = $date->maximumJulianDay();
+ } else {
+ $sql_where .= " AND {$attr}.d_julianday1 >= :{$attr}date";
+ $sql_params[$attr . 'date'] = $date->minimumJulianDay();
+ }
+ if ($sortby == $match[1]) {
+ $sortby = '';
+ $sql_order_by .= ($sql_order_by ? ', ' : ' ORDER BY ') . "{$attr}.d_julianday1";
+ }
+ unset($attrs[$attr]); // This filter has been fully processed
+ } elseif (preg_match('/^REGEXP \/(.+)\//', $value, $match)) {
+ $sql_where .= " AND f_gedcom REGEXP :{$attr}gedcom";
+ // PDO helpfully escapes backslashes for us, preventing us from matching "\n1 FACT"
+ $sql_params[$attr . 'gedcom'] = str_replace('\n', "\n", $match[1]);
+ unset($attrs[$attr]); // This filter has been fully processed
+ } elseif (preg_match('/^NAME CONTAINS (.+)$/', $value, $match)) {
+ // Do nothing, unless you have to
+ if ($match[1] != '' || $sortby == 'NAME') {
+ $sql_join .= " JOIN `##name` AS {$attr} ON n_file = f_file AND n_id IN (f_husb, f_wife)";
+ // Search the DB only if there is any name supplied
+ if ($match[1] != '') {
+ $names = explode(' ', $match[1]);
+ foreach ($names as $n => $name) {
+ $sql_where .= " AND {$attr}.n_full LIKE CONCAT('%', :{$attr}name{$n}, '%')";
+ $sql_params[$attr . 'name' . $n] = $name;
+ }
+ }
+ // Let the DB do the name sorting even when no name was entered
+ if ($sortby == 'NAME') {
+ $sortby = '';
+ $sql_order_by .= ($sql_order_by ? ', ' : ' ORDER BY ') . "{$attr}.n_sort";
+ }
+ }
+ unset($attrs[$attr]); // This filter has been fully processed
+ } elseif (preg_match('/^(?:\w+):PLAC CONTAINS (.+)$/', $value, $match)) {
+ $sql_join .= " JOIN `##places` AS {$attr}a ON ({$attr}a.p_file=f_file)";
+ $sql_join .= " JOIN `##placelinks` AS {$attr}b ON ({$attr}a.p_file={$attr}b.pl_file AND {$attr}b.pl_p_id={$attr}a.p_id AND {$attr}b.pl_gid=f_id)";
+ $sql_where .= " AND {$attr}a.p_place LIKE CONCAT('%', :{$attr}place, '%')";
+ $sql_params[$attr . 'place'] = $match[1];
+ // Don't unset this filter. This is just initial filtering
+ } elseif (preg_match('/^(\w*):*(\w*) CONTAINS (.+)$/', $value, $match)) {
+ $sql_where .= " AND f_gedcom LIKE CONCAT('%', :{$attr}contains1, '%', :{$attr}contains2, '%', :{$attr}contains3, '%')";
+ $sql_params[$attr . 'contains1'] = $match[1];
+ $sql_params[$attr . 'contains2'] = $match[2];
+ $sql_params[$attr . 'contains3'] = $match[3];
+ // Don't unset this filter. This is just initial filtering
+ }
+ }
+ }
- $this->list = [];
- $rows = Database::prepare(
- $sql_select . $sql_join . $sql_where . $sql_order_by
- )->execute($sql_params)->fetchAll();
+ $this->list = [];
+ $rows = Database::prepare(
+ $sql_select . $sql_join . $sql_where . $sql_order_by
+ )->execute($sql_params)->fetchAll();
- foreach ($rows as $row) {
- $this->list[$row->xref] = Family::getInstance($row->xref, $this->tree, $row->gedcom);
- }
- break;
+ foreach ($rows as $row) {
+ $this->list[$row->xref] = Family::getInstance($row->xref, $this->tree, $row->gedcom);
+ }
+ break;
- default:
- throw new \DomainException('Invalid list name: ' . $listname);
- }
+ default:
+ throw new \DomainException('Invalid list name: ' . $listname);
+ }
- $filters = [];
- $filters2 = [];
- if (isset($attrs['filter1']) && count($this->list) > 0) {
- foreach ($attrs as $key => $value) {
- if (preg_match("/filter(\d)/", $key)) {
- $condition = $value;
- if (preg_match("/@(\w+)/", $condition, $match)) {
- $id = $match[1];
- $value = "''";
- if ($id == 'ID') {
- if (preg_match('/0 @(.+)@/', $this->gedrec, $match)) {
- $value = "'" . $match[1] . "'";
- }
- } elseif ($id == 'fact') {
- $value = "'" . $this->fact . "'";
- } elseif ($id == 'desc') {
- $value = "'" . $this->desc . "'";
- } else {
- if (preg_match("/\d $id (.+)/", $this->gedrec, $match)) {
- $value = "'" . str_replace('@', '', trim($match[1])) . "'";
- }
- }
- $condition = preg_replace("/@$id/", $value, $condition);
- }
- //-- handle regular expressions
- if (preg_match("/([A-Z:]+)\s*([^\s]+)\s*(.+)/", $condition, $match)) {
- $tag = trim($match[1]);
- $expr = trim($match[2]);
- $val = trim($match[3]);
- if (preg_match("/\\$(\w+)/", $val, $match)) {
- $val = $this->vars[$match[1]]['id'];
- $val = trim($val);
- }
- if ($val) {
- $searchstr = '';
- $tags = explode(':', $tag);
- //-- only limit to a level number if we are specifically looking at a level
- if (count($tags) > 1) {
- $level = 1;
- foreach ($tags as $t) {
- if (!empty($searchstr)) {
- $searchstr .= "[^\n]*(\n[2-9][^\n]*)*\n";
- }
- //-- search for both EMAIL and _EMAIL... silly double gedcom standard
- if ($t == 'EMAIL' || $t == '_EMAIL') {
- $t = '_?EMAIL';
- }
- $searchstr .= $level . ' ' . $t;
- $level++;
- }
- } else {
- if ($tag == 'EMAIL' || $tag == '_EMAIL') {
- $tag = '_?EMAIL';
- }
- $t = $tag;
- $searchstr = '1 ' . $tag;
- }
- switch ($expr) {
- case 'CONTAINS':
- if ($t == 'PLAC') {
- $searchstr .= "[^\n]*[, ]*" . $val;
- } else {
- $searchstr .= "[^\n]*" . $val;
- }
- $filters[] = $searchstr;
- break;
- default:
- $filters2[] = ['tag' => $tag, 'expr' => $expr, 'val' => $val];
- break;
- }
- }
- }
- }
- }
- }
- //-- apply other filters to the list that could not be added to the search string
- if ($filters) {
- foreach ($this->list as $key => $record) {
- foreach ($filters as $filter) {
- if (!preg_match('/' . $filter . '/i', $record->privatizeGedcom(Auth::accessLevel($this->tree)))) {
- unset($this->list[$key]);
- break;
- }
- }
- }
- }
- if ($filters2) {
- $mylist = [];
- foreach ($this->list as $indi) {
- $key = $indi->getXref();
- $grec = $indi->privatizeGedcom(Auth::accessLevel($this->tree));
- $keep = true;
- foreach ($filters2 as $filter) {
- if ($keep) {
- $tag = $filter['tag'];
- $expr = $filter['expr'];
- $val = $filter['val'];
- if ($val == "''") {
- $val = '';
- }
- $tags = explode(':', $tag);
- $t = end($tags);
- $v = $this->getGedcomValue($tag, 1, $grec);
- //-- check for EMAIL and _EMAIL (silly double gedcom standard :P)
- if ($t == 'EMAIL' && empty($v)) {
- $tag = str_replace('EMAIL', '_EMAIL', $tag);
- $tags = explode(':', $tag);
- $t = end($tags);
- $v = Functions::getSubRecord(1, $tag, $grec);
- }
+ $filters = [];
+ $filters2 = [];
+ if (isset($attrs['filter1']) && count($this->list) > 0) {
+ foreach ($attrs as $key => $value) {
+ if (preg_match("/filter(\d)/", $key)) {
+ $condition = $value;
+ if (preg_match("/@(\w+)/", $condition, $match)) {
+ $id = $match[1];
+ $value = "''";
+ if ($id == 'ID') {
+ if (preg_match('/0 @(.+)@/', $this->gedrec, $match)) {
+ $value = "'" . $match[1] . "'";
+ }
+ } elseif ($id == 'fact') {
+ $value = "'" . $this->fact . "'";
+ } elseif ($id == 'desc') {
+ $value = "'" . $this->desc . "'";
+ } else {
+ if (preg_match("/\d $id (.+)/", $this->gedrec, $match)) {
+ $value = "'" . str_replace('@', '', trim($match[1])) . "'";
+ }
+ }
+ $condition = preg_replace("/@$id/", $value, $condition);
+ }
+ //-- handle regular expressions
+ if (preg_match("/([A-Z:]+)\s*([^\s]+)\s*(.+)/", $condition, $match)) {
+ $tag = trim($match[1]);
+ $expr = trim($match[2]);
+ $val = trim($match[3]);
+ if (preg_match("/\\$(\w+)/", $val, $match)) {
+ $val = $this->vars[$match[1]]['id'];
+ $val = trim($val);
+ }
+ if ($val) {
+ $searchstr = '';
+ $tags = explode(':', $tag);
+ //-- only limit to a level number if we are specifically looking at a level
+ if (count($tags) > 1) {
+ $level = 1;
+ foreach ($tags as $t) {
+ if (!empty($searchstr)) {
+ $searchstr .= "[^\n]*(\n[2-9][^\n]*)*\n";
+ }
+ //-- search for both EMAIL and _EMAIL... silly double gedcom standard
+ if ($t == 'EMAIL' || $t == '_EMAIL') {
+ $t = '_?EMAIL';
+ }
+ $searchstr .= $level . ' ' . $t;
+ $level++;
+ }
+ } else {
+ if ($tag == 'EMAIL' || $tag == '_EMAIL') {
+ $tag = '_?EMAIL';
+ }
+ $t = $tag;
+ $searchstr = '1 ' . $tag;
+ }
+ switch ($expr) {
+ case 'CONTAINS':
+ if ($t == 'PLAC') {
+ $searchstr .= "[^\n]*[, ]*" . $val;
+ } else {
+ $searchstr .= "[^\n]*" . $val;
+ }
+ $filters[] = $searchstr;
+ break;
+ default:
+ $filters2[] = [
+ 'tag' => $tag,
+ 'expr' => $expr,
+ 'val' => $val,
+ ];
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ //-- apply other filters to the list that could not be added to the search string
+ if ($filters) {
+ foreach ($this->list as $key => $record) {
+ foreach ($filters as $filter) {
+ if (!preg_match('/' . $filter . '/i', $record->privatizeGedcom(Auth::accessLevel($this->tree)))) {
+ unset($this->list[$key]);
+ break;
+ }
+ }
+ }
+ }
+ if ($filters2) {
+ $mylist = [];
+ foreach ($this->list as $indi) {
+ $key = $indi->getXref();
+ $grec = $indi->privatizeGedcom(Auth::accessLevel($this->tree));
+ $keep = true;
+ foreach ($filters2 as $filter) {
+ if ($keep) {
+ $tag = $filter['tag'];
+ $expr = $filter['expr'];
+ $val = $filter['val'];
+ if ($val == "''") {
+ $val = '';
+ }
+ $tags = explode(':', $tag);
+ $t = end($tags);
+ $v = $this->getGedcomValue($tag, 1, $grec);
+ //-- check for EMAIL and _EMAIL (silly double gedcom standard :P)
+ if ($t == 'EMAIL' && empty($v)) {
+ $tag = str_replace('EMAIL', '_EMAIL', $tag);
+ $tags = explode(':', $tag);
+ $t = end($tags);
+ $v = Functions::getSubRecord(1, $tag, $grec);
+ }
- switch ($expr) {
- case 'GTE':
- if ($t == 'DATE') {
- $date1 = new Date($v);
- $date2 = new Date($val);
- $keep = (Date::compare($date1, $date2) >= 0);
- } elseif ($val >= $v) {
- $keep = true;
- }
- break;
- case 'LTE':
- if ($t == 'DATE') {
- $date1 = new Date($v);
- $date2 = new Date($val);
- $keep = (Date::compare($date1, $date2) <= 0);
- } elseif ($val >= $v) {
- $keep = true;
- }
- break;
- default:
- if ($v == $val) {
- $keep = true;
- } else {
- $keep = false;
- }
- break;
- }
- }
- }
- if ($keep) {
- $mylist[$key] = $indi;
- }
- }
- $this->list = $mylist;
- }
+ switch ($expr) {
+ case 'GTE':
+ if ($t == 'DATE') {
+ $date1 = new Date($v);
+ $date2 = new Date($val);
+ $keep = (Date::compare($date1, $date2) >= 0);
+ } elseif ($val >= $v) {
+ $keep = true;
+ }
+ break;
+ case 'LTE':
+ if ($t == 'DATE') {
+ $date1 = new Date($v);
+ $date2 = new Date($val);
+ $keep = (Date::compare($date1, $date2) <= 0);
+ } elseif ($val >= $v) {
+ $keep = true;
+ }
+ break;
+ default:
+ if ($v == $val) {
+ $keep = true;
+ } else {
+ $keep = false;
+ }
+ break;
+ }
+ }
+ }
+ if ($keep) {
+ $mylist[$key] = $indi;
+ }
+ }
+ $this->list = $mylist;
+ }
- switch ($sortby) {
- case 'NAME':
- uasort($this->list, '\Fisharebest\Webtrees\GedcomRecord::compare');
- break;
- case 'CHAN':
- uasort($this->list, function (GedcomRecord $x, GedcomRecord $y) {
- return $y->lastChangeTimestamp(true) - $x->lastChangeTimestamp(true);
- });
- break;
- case 'BIRT:DATE':
- uasort($this->list, '\Fisharebest\Webtrees\Individual::compareBirthDate');
- break;
- case 'DEAT:DATE':
- uasort($this->list, '\Fisharebest\Webtrees\Individual::compareDeathDate');
- break;
- case 'MARR:DATE':
- uasort($this->list, '\Fisharebest\Webtrees\Family::compareMarrDate');
- break;
- default:
- // unsorted or already sorted by SQL
- break;
- }
+ switch ($sortby) {
+ case 'NAME':
+ uasort($this->list, '\Fisharebest\Webtrees\GedcomRecord::compare');
+ break;
+ case 'CHAN':
+ uasort($this->list, function (GedcomRecord $x, GedcomRecord $y) {
+ return $y->lastChangeTimestamp(true) - $x->lastChangeTimestamp(true);
+ });
+ break;
+ case 'BIRT:DATE':
+ uasort($this->list, '\Fisharebest\Webtrees\Individual::compareBirthDate');
+ break;
+ case 'DEAT:DATE':
+ uasort($this->list, '\Fisharebest\Webtrees\Individual::compareDeathDate');
+ break;
+ case 'MARR:DATE':
+ uasort($this->list, '\Fisharebest\Webtrees\Family::compareMarrDate');
+ break;
+ default:
+ // unsorted or already sorted by SQL
+ break;
+ }
- array_push($this->repeats_stack, [$this->repeats, $this->repeat_bytes]);
- $this->repeat_bytes = xml_get_current_line_number($this->parser) + 1;
- }
+ array_push($this->repeats_stack, [
+ $this->repeats,
+ $this->repeat_bytes,
+ ]);
+ $this->repeat_bytes = xml_get_current_line_number($this->parser) + 1;
+ }
- /**
- * XML <List>
- */
- private function listEndHandler() {
- $this->process_repeats--;
- if ($this->process_repeats > 0) {
- return;
- }
+ /**
+ * XML <List>
+ */
+ private function listEndHandler()
+ {
+ $this->process_repeats--;
+ if ($this->process_repeats > 0) {
+ return;
+ }
- // Check if there is any list
- if (count($this->list) > 0) {
- $lineoffset = 0;
- foreach ($this->repeats_stack as $rep) {
- $lineoffset += $rep[1];
- }
- //-- read the xml from the file
- $lines = file($this->report);
- while ((strpos($lines[$lineoffset + $this->repeat_bytes], '<List') === false) && (($lineoffset + $this->repeat_bytes) > 0)) {
- $lineoffset--;
- }
- $lineoffset++;
- $reportxml = "<tempdoc>\n";
- $line_nr = $lineoffset + $this->repeat_bytes;
- // List Level counter
- $count = 1;
- while (0 < $count) {
- if (strpos($lines[$line_nr], '<List') !== false) {
- $count++;
- } elseif (strpos($lines[$line_nr], '</List') !== false) {
- $count--;
- }
- if (0 < $count) {
- $reportxml .= $lines[$line_nr];
- }
- $line_nr++;
- }
- // No need to drag this
- unset($lines);
- $reportxml .= '</tempdoc>';
- // Save original values
- array_push($this->parser_stack, $this->parser);
- $oldgedrec = $this->gedrec;
+ // Check if there is any list
+ if (count($this->list) > 0) {
+ $lineoffset = 0;
+ foreach ($this->repeats_stack as $rep) {
+ $lineoffset += $rep[1];
+ }
+ //-- read the xml from the file
+ $lines = file($this->report);
+ while ((strpos($lines[$lineoffset + $this->repeat_bytes], '<List') === false) && (($lineoffset + $this->repeat_bytes) > 0)) {
+ $lineoffset--;
+ }
+ $lineoffset++;
+ $reportxml = "<tempdoc>\n";
+ $line_nr = $lineoffset + $this->repeat_bytes;
+ // List Level counter
+ $count = 1;
+ while (0 < $count) {
+ if (strpos($lines[$line_nr], '<List') !== false) {
+ $count++;
+ } elseif (strpos($lines[$line_nr], '</List') !== false) {
+ $count--;
+ }
+ if (0 < $count) {
+ $reportxml .= $lines[$line_nr];
+ }
+ $line_nr++;
+ }
+ // No need to drag this
+ unset($lines);
+ $reportxml .= '</tempdoc>';
+ // Save original values
+ array_push($this->parser_stack, $this->parser);
+ $oldgedrec = $this->gedrec;
- $this->list_total = count($this->list);
- $this->list_private = 0;
- foreach ($this->list as $record) {
- if ($record->canShow()) {
- $this->gedrec = $record->privatizeGedcom(Auth::accessLevel($record->getTree()));
- //-- start the sax parser
- $repeat_parser = xml_parser_create();
- $this->parser = $repeat_parser;
- xml_parser_set_option($repeat_parser, XML_OPTION_CASE_FOLDING, false);
- xml_set_element_handler($repeat_parser, [$this, 'startElement'], [$this, 'endElement']);
- xml_set_character_data_handler($repeat_parser, [$this, 'characterData']);
- if (!xml_parse($repeat_parser, $reportxml, true)) {
- throw new \DomainException(sprintf(
- 'ListEHandler XML error: %s at line %d',
- xml_error_string(xml_get_error_code($repeat_parser)),
- xml_get_current_line_number($repeat_parser)
- ));
- }
- xml_parser_free($repeat_parser);
- } else {
- $this->list_private++;
- }
- }
- $this->list = [];
- $this->parser = array_pop($this->parser_stack);
- $this->gedrec = $oldgedrec;
- }
- list($this->repeats, $this->repeat_bytes) = array_pop($this->repeats_stack);
- }
+ $this->list_total = count($this->list);
+ $this->list_private = 0;
+ foreach ($this->list as $record) {
+ if ($record->canShow()) {
+ $this->gedrec = $record->privatizeGedcom(Auth::accessLevel($record->getTree()));
+ //-- start the sax parser
+ $repeat_parser = xml_parser_create();
+ $this->parser = $repeat_parser;
+ xml_parser_set_option($repeat_parser, XML_OPTION_CASE_FOLDING, false);
+ xml_set_element_handler($repeat_parser, [
+ $this,
+ 'startElement',
+ ], [
+ $this,
+ 'endElement',
+ ]);
+ xml_set_character_data_handler($repeat_parser, [
+ $this,
+ 'characterData',
+ ]);
+ if (!xml_parse($repeat_parser, $reportxml, true)) {
+ throw new \DomainException(sprintf(
+ 'ListEHandler XML error: %s at line %d',
+ xml_error_string(xml_get_error_code($repeat_parser)),
+ xml_get_current_line_number($repeat_parser)
+ ));
+ }
+ xml_parser_free($repeat_parser);
+ } else {
+ $this->list_private++;
+ }
+ }
+ $this->list = [];
+ $this->parser = array_pop($this->parser_stack);
+ $this->gedrec = $oldgedrec;
+ }
+ list($this->repeats, $this->repeat_bytes) = array_pop($this->repeats_stack);
+ }
- /**
- * XML <ListTotal> element handler
- *
- * Prints the total number of records in a list
- * The total number is collected from
- * List and Relatives
- */
- private function listTotalStartHandler() {
- if ($this->list_private == 0) {
- $this->current_element->addText($this->list_total);
- } else {
- $this->current_element->addText(($this->list_total - $this->list_private) . ' / ' . $this->list_total);
- }
- }
+ /**
+ * XML <ListTotal> element handler
+ *
+ * Prints the total number of records in a list
+ * The total number is collected from
+ * List and Relatives
+ */
+ private function listTotalStartHandler()
+ {
+ if ($this->list_private == 0) {
+ $this->current_element->addText($this->list_total);
+ } else {
+ $this->current_element->addText(($this->list_total - $this->list_private) . ' / ' . $this->list_total);
+ }
+ }
- /**
- * XML <Relatives>
- *
- * @param array $attrs an array of key value pairs for the attributes
- */
- private function relativesStartHandler($attrs) {
- $this->process_repeats++;
- if ($this->process_repeats > 1) {
- return;
- }
+ /**
+ * XML <Relatives>
+ *
+ * @param array $attrs an array of key value pairs for the attributes
+ */
+ private function relativesStartHandler($attrs)
+ {
+ $this->process_repeats++;
+ if ($this->process_repeats > 1) {
+ return;
+ }
- $sortby = 'NAME';
- if (isset($attrs['sortby'])) {
- $sortby = $attrs['sortby'];
- }
- $match = [];
- if (preg_match("/\\$(\w+)/", $sortby, $match)) {
- $sortby = $this->vars[$match[1]]['id'];
- $sortby = trim($sortby);
- }
+ $sortby = 'NAME';
+ if (isset($attrs['sortby'])) {
+ $sortby = $attrs['sortby'];
+ }
+ $match = [];
+ if (preg_match("/\\$(\w+)/", $sortby, $match)) {
+ $sortby = $this->vars[$match[1]]['id'];
+ $sortby = trim($sortby);
+ }
- $maxgen = -1;
- if (isset($attrs['maxgen'])) {
- $maxgen = $attrs['maxgen'];
- }
- if ($maxgen == '*') {
- $maxgen = -1;
- }
+ $maxgen = -1;
+ if (isset($attrs['maxgen'])) {
+ $maxgen = $attrs['maxgen'];
+ }
+ if ($maxgen == '*') {
+ $maxgen = -1;
+ }
- $group = 'child-family';
- if (isset($attrs['group'])) {
- $group = $attrs['group'];
- }
- if (preg_match("/\\$(\w+)/", $group, $match)) {
- $group = $this->vars[$match[1]]['id'];
- $group = trim($group);
- }
+ $group = 'child-family';
+ if (isset($attrs['group'])) {
+ $group = $attrs['group'];
+ }
+ if (preg_match("/\\$(\w+)/", $group, $match)) {
+ $group = $this->vars[$match[1]]['id'];
+ $group = trim($group);
+ }
- $id = '';
- if (isset($attrs['id'])) {
- $id = $attrs['id'];
- }
- if (preg_match("/\\$(\w+)/", $id, $match)) {
- $id = $this->vars[$match[1]]['id'];
- $id = trim($id);
- }
+ $id = '';
+ if (isset($attrs['id'])) {
+ $id = $attrs['id'];
+ }
+ if (preg_match("/\\$(\w+)/", $id, $match)) {
+ $id = $this->vars[$match[1]]['id'];
+ $id = trim($id);
+ }
- $this->list = [];
- $person = Individual::getInstance($id, $this->tree);
- if (!empty($person)) {
- $this->list[$id] = $person;
- switch ($group) {
- case 'child-family':
- foreach ($person->getChildFamilies() as $family) {
- $husband = $family->getHusband();
- $wife = $family->getWife();
- if (!empty($husband)) {
- $this->list[$husband->getXref()] = $husband;
- }
- if (!empty($wife)) {
- $this->list[$wife->getXref()] = $wife;
- }
- $children = $family->getChildren();
- foreach ($children as $child) {
- if (!empty($child)) {
- $this->list[$child->getXref()] = $child;
- }
- }
- }
- break;
- case 'spouse-family':
- foreach ($person->getSpouseFamilies() as $family) {
- $husband = $family->getHusband();
- $wife = $family->getWife();
- if (!empty($husband)) {
- $this->list[$husband->getXref()] = $husband;
- }
- if (!empty($wife)) {
- $this->list[$wife->getXref()] = $wife;
- }
- $children = $family->getChildren();
- foreach ($children as $child) {
- if (!empty($child)) {
- $this->list[$child->getXref()] = $child;
- }
- }
- }
- break;
- case 'direct-ancestors':
- $this->addAncestors($this->list, $id, false, $maxgen);
- break;
- case 'ancestors':
- $this->addAncestors($this->list, $id, true, $maxgen);
- break;
- case 'descendants':
- $this->list[$id]->generation = 1;
- $this->addDescendancy($this->list, $id, false, $maxgen);
- break;
- case 'all':
- $this->addAncestors($this->list, $id, true, $maxgen);
- $this->addDescendancy($this->list, $id, true, $maxgen);
- break;
- }
- }
+ $this->list = [];
+ $person = Individual::getInstance($id, $this->tree);
+ if (!empty($person)) {
+ $this->list[$id] = $person;
+ switch ($group) {
+ case 'child-family':
+ foreach ($person->getChildFamilies() as $family) {
+ $husband = $family->getHusband();
+ $wife = $family->getWife();
+ if (!empty($husband)) {
+ $this->list[$husband->getXref()] = $husband;
+ }
+ if (!empty($wife)) {
+ $this->list[$wife->getXref()] = $wife;
+ }
+ $children = $family->getChildren();
+ foreach ($children as $child) {
+ if (!empty($child)) {
+ $this->list[$child->getXref()] = $child;
+ }
+ }
+ }
+ break;
+ case 'spouse-family':
+ foreach ($person->getSpouseFamilies() as $family) {
+ $husband = $family->getHusband();
+ $wife = $family->getWife();
+ if (!empty($husband)) {
+ $this->list[$husband->getXref()] = $husband;
+ }
+ if (!empty($wife)) {
+ $this->list[$wife->getXref()] = $wife;
+ }
+ $children = $family->getChildren();
+ foreach ($children as $child) {
+ if (!empty($child)) {
+ $this->list[$child->getXref()] = $child;
+ }
+ }
+ }
+ break;
+ case 'direct-ancestors':
+ $this->addAncestors($this->list, $id, false, $maxgen);
+ break;
+ case 'ancestors':
+ $this->addAncestors($this->list, $id, true, $maxgen);
+ break;
+ case 'descendants':
+ $this->list[$id]->generation = 1;
+ $this->addDescendancy($this->list, $id, false, $maxgen);
+ break;
+ case 'all':
+ $this->addAncestors($this->list, $id, true, $maxgen);
+ $this->addDescendancy($this->list, $id, true, $maxgen);
+ break;
+ }
+ }
- switch ($sortby) {
- case 'NAME':
- uasort($this->list, '\Fisharebest\Webtrees\GedcomRecord::compare');
- break;
- case 'BIRT:DATE':
- uasort($this->list, '\Fisharebest\Webtrees\Individual::compareBirthDate');
- break;
- case 'DEAT:DATE':
- uasort($this->list, '\Fisharebest\Webtrees\Individual::compareDeathDate');
- break;
- case 'generation':
- $newarray = [];
- reset($this->list);
- $genCounter = 1;
- while (count($newarray) < count($this->list)) {
- foreach ($this->list as $key => $value) {
- $this->generation = $value->generation;
- if ($this->generation == $genCounter) {
- $newarray[$key] = new \stdClass;
- $newarray[$key]->generation = $this->generation;
- }
- }
- $genCounter++;
- }
- $this->list = $newarray;
- break;
- default:
- // unsorted
- break;
- }
- array_push($this->repeats_stack, [$this->repeats, $this->repeat_bytes]);
- $this->repeat_bytes = xml_get_current_line_number($this->parser) + 1;
- }
+ switch ($sortby) {
+ case 'NAME':
+ uasort($this->list, '\Fisharebest\Webtrees\GedcomRecord::compare');
+ break;
+ case 'BIRT:DATE':
+ uasort($this->list, '\Fisharebest\Webtrees\Individual::compareBirthDate');
+ break;
+ case 'DEAT:DATE':
+ uasort($this->list, '\Fisharebest\Webtrees\Individual::compareDeathDate');
+ break;
+ case 'generation':
+ $newarray = [];
+ reset($this->list);
+ $genCounter = 1;
+ while (count($newarray) < count($this->list)) {
+ foreach ($this->list as $key => $value) {
+ $this->generation = $value->generation;
+ if ($this->generation == $genCounter) {
+ $newarray[$key] = new \stdClass;
+ $newarray[$key]->generation = $this->generation;
+ }
+ }
+ $genCounter++;
+ }
+ $this->list = $newarray;
+ break;
+ default:
+ // unsorted
+ break;
+ }
+ array_push($this->repeats_stack, [
+ $this->repeats,
+ $this->repeat_bytes,
+ ]);
+ $this->repeat_bytes = xml_get_current_line_number($this->parser) + 1;
+ }
- /**
- * XML </ Relatives>
- */
- private function relativesEndHandler() {
- $this->process_repeats--;
- if ($this->process_repeats > 0) {
- return;
- }
+ /**
+ * XML </ Relatives>
+ */
+ private function relativesEndHandler()
+ {
+ $this->process_repeats--;
+ if ($this->process_repeats > 0) {
+ return;
+ }
- // Check if there is any relatives
- if (count($this->list) > 0) {
- $lineoffset = 0;
- foreach ($this->repeats_stack as $rep) {
- $lineoffset += $rep[1];
- }
- //-- read the xml from the file
- $lines = file($this->report);
- while ((strpos($lines[$lineoffset + $this->repeat_bytes], '<Relatives') === false) && (($lineoffset + $this->repeat_bytes) > 0)) {
- $lineoffset--;
- }
- $lineoffset++;
- $reportxml = "<tempdoc>\n";
- $line_nr = $lineoffset + $this->repeat_bytes;
- // Relatives Level counter
- $count = 1;
- while (0 < $count) {
- if (strpos($lines[$line_nr], '<Relatives') !== false) {
- $count++;
- } elseif (strpos($lines[$line_nr], '</Relatives') !== false) {
- $count--;
- }
- if (0 < $count) {
- $reportxml .= $lines[$line_nr];
- }
- $line_nr++;
- }
- // No need to drag this
- unset($lines);
- $reportxml .= "</tempdoc>\n";
- // Save original values
- array_push($this->parser_stack, $this->parser);
- $oldgedrec = $this->gedrec;
+ // Check if there is any relatives
+ if (count($this->list) > 0) {
+ $lineoffset = 0;
+ foreach ($this->repeats_stack as $rep) {
+ $lineoffset += $rep[1];
+ }
+ //-- read the xml from the file
+ $lines = file($this->report);
+ while ((strpos($lines[$lineoffset + $this->repeat_bytes], '<Relatives') === false) && (($lineoffset + $this->repeat_bytes) > 0)) {
+ $lineoffset--;
+ }
+ $lineoffset++;
+ $reportxml = "<tempdoc>\n";
+ $line_nr = $lineoffset + $this->repeat_bytes;
+ // Relatives Level counter
+ $count = 1;
+ while (0 < $count) {
+ if (strpos($lines[$line_nr], '<Relatives') !== false) {
+ $count++;
+ } elseif (strpos($lines[$line_nr], '</Relatives') !== false) {
+ $count--;
+ }
+ if (0 < $count) {
+ $reportxml .= $lines[$line_nr];
+ }
+ $line_nr++;
+ }
+ // No need to drag this
+ unset($lines);
+ $reportxml .= "</tempdoc>\n";
+ // Save original values
+ array_push($this->parser_stack, $this->parser);
+ $oldgedrec = $this->gedrec;
- $this->list_total = count($this->list);
- $this->list_private = 0;
- foreach ($this->list as $key => $value) {
- if (isset($value->generation)) {
- $this->generation = $value->generation;
- }
- $tmp = GedcomRecord::getInstance($key, $this->tree);
- $this->gedrec = $tmp->privatizeGedcom(Auth::accessLevel($this->tree));
+ $this->list_total = count($this->list);
+ $this->list_private = 0;
+ foreach ($this->list as $key => $value) {
+ if (isset($value->generation)) {
+ $this->generation = $value->generation;
+ }
+ $tmp = GedcomRecord::getInstance($key, $this->tree);
+ $this->gedrec = $tmp->privatizeGedcom(Auth::accessLevel($this->tree));
- $repeat_parser = xml_parser_create();
- $this->parser = $repeat_parser;
- xml_parser_set_option($repeat_parser, XML_OPTION_CASE_FOLDING, false);
- xml_set_element_handler($repeat_parser, [$this, 'startElement'], [$this, 'endElement']);
- xml_set_character_data_handler($repeat_parser, [$this, 'characterData']);
+ $repeat_parser = xml_parser_create();
+ $this->parser = $repeat_parser;
+ xml_parser_set_option($repeat_parser, XML_OPTION_CASE_FOLDING, false);
+ xml_set_element_handler($repeat_parser, [
+ $this,
+ 'startElement',
+ ], [
+ $this,
+ 'endElement',
+ ]);
+ xml_set_character_data_handler($repeat_parser, [
+ $this,
+ 'characterData',
+ ]);
- if (!xml_parse($repeat_parser, $reportxml, true)) {
- throw new \DomainException(sprintf('RelativesEHandler XML error: %s at line %d', xml_error_string(xml_get_error_code($repeat_parser)), xml_get_current_line_number($repeat_parser)));
- }
- xml_parser_free($repeat_parser);
- }
- // Clean up the list array
- $this->list = [];
- $this->parser = array_pop($this->parser_stack);
- $this->gedrec = $oldgedrec;
- }
- list($this->repeats, $this->repeat_bytes) = array_pop($this->repeats_stack);
- }
+ if (!xml_parse($repeat_parser, $reportxml, true)) {
+ throw new \DomainException(sprintf('RelativesEHandler XML error: %s at line %d', xml_error_string(xml_get_error_code($repeat_parser)), xml_get_current_line_number($repeat_parser)));
+ }
+ xml_parser_free($repeat_parser);
+ }
+ // Clean up the list array
+ $this->list = [];
+ $this->parser = array_pop($this->parser_stack);
+ $this->gedrec = $oldgedrec;
+ }
+ list($this->repeats, $this->repeat_bytes) = array_pop($this->repeats_stack);
+ }
- /**
- * XML <Generation /> element handler
- *
- * Prints the number of generations
- */
- private function generationStartHandler() {
- $this->current_element->addText($this->generation);
- }
+ /**
+ * XML <Generation /> element handler
+ *
+ * Prints the number of generations
+ */
+ private function generationStartHandler()
+ {
+ $this->current_element->addText($this->generation);
+ }
- /**
- * XML <NewPage /> element handler
- *
- * Has to be placed in an element (header, pageheader, body or footer)
- */
- private function newPageStartHandler() {
- $temp = 'addpage';
- $this->wt_report->addElement($temp);
- }
+ /**
+ * XML <NewPage /> element handler
+ *
+ * Has to be placed in an element (header, pageheader, body or footer)
+ */
+ private function newPageStartHandler()
+ {
+ $temp = 'addpage';
+ $this->wt_report->addElement($temp);
+ }
- /**
- * XML <html>
- *
- * @param string $tag HTML tag name
- * @param array[] $attrs an array of key value pairs for the attributes
- */
- private function htmlStartHandler($tag, $attrs) {
- if ($tag === 'tempdoc') {
- return;
- }
- array_push($this->wt_report_stack, $this->wt_report);
- $this->wt_report = $this->report_root->createHTML($tag, $attrs);
- $this->current_element = $this->wt_report;
+ /**
+ * XML <html>
+ *
+ * @param string $tag HTML tag name
+ * @param array[] $attrs an array of key value pairs for the attributes
+ */
+ private function htmlStartHandler($tag, $attrs)
+ {
+ if ($tag === 'tempdoc') {
+ return;
+ }
+ array_push($this->wt_report_stack, $this->wt_report);
+ $this->wt_report = $this->report_root->createHTML($tag, $attrs);
+ $this->current_element = $this->wt_report;
- array_push($this->print_data_stack, $this->print_data);
- $this->print_data = true;
- }
+ array_push($this->print_data_stack, $this->print_data);
+ $this->print_data = true;
+ }
- /**
- * XML </html>
- *
- * @param string $tag
- */
- private function htmlEndHandler($tag) {
- if ($tag === 'tempdoc') {
- return;
- }
+ /**
+ * XML </html>
+ *
+ * @param string $tag
+ */
+ private function htmlEndHandler($tag)
+ {
+ if ($tag === 'tempdoc') {
+ return;
+ }
- $this->print_data = array_pop($this->print_data_stack);
- $this->current_element = $this->wt_report;
- $this->wt_report = array_pop($this->wt_report_stack);
- if (!is_null($this->wt_report)) {
- $this->wt_report->addElement($this->current_element);
- } else {
- $this->wt_report = $this->current_element;
- }
- }
+ $this->print_data = array_pop($this->print_data_stack);
+ $this->current_element = $this->wt_report;
+ $this->wt_report = array_pop($this->wt_report_stack);
+ if (!is_null($this->wt_report)) {
+ $this->wt_report->addElement($this->current_element);
+ } else {
+ $this->wt_report = $this->current_element;
+ }
+ }
- /**
- * Handle <Input>
- */
- private function inputStartHandler() {
- // Dummy function, to prevent the default HtmlStartHandler() being called
- }
+ /**
+ * Handle <Input>
+ */
+ private function inputStartHandler()
+ {
+ // Dummy function, to prevent the default HtmlStartHandler() being called
+ }
- /**
- * Handle </Input>
- */
- private function inputEndHandler() {
- // Dummy function, to prevent the default HtmlEndHandler() being called
- }
+ /**
+ * Handle </Input>
+ */
+ private function inputEndHandler()
+ {
+ // Dummy function, to prevent the default HtmlEndHandler() being called
+ }
- /**
- * Handle <Report>
- */
- private function reportStartHandler() {
- // Dummy function, to prevent the default HtmlStartHandler() being called
- }
+ /**
+ * Handle <Report>
+ */
+ private function reportStartHandler()
+ {
+ // Dummy function, to prevent the default HtmlStartHandler() being called
+ }
- /**
- * Handle </Report>
- */
- private function reportEndHandler() {
- // Dummy function, to prevent the default HtmlEndHandler() being called
- }
+ /**
+ * Handle </Report>
+ */
+ private function reportEndHandler()
+ {
+ // Dummy function, to prevent the default HtmlEndHandler() being called
+ }
- /**
- * XML </titleEndHandler>
- */
- private function titleEndHandler() {
- $this->report_root->addTitle($this->text);
- }
+ /**
+ * XML </titleEndHandler>
+ */
+ private function titleEndHandler()
+ {
+ $this->report_root->addTitle($this->text);
+ }
- /**
- * XML </descriptionEndHandler>
- */
- private function descriptionEndHandler() {
- $this->report_root->addDescription($this->text);
- }
+ /**
+ * XML </descriptionEndHandler>
+ */
+ private function descriptionEndHandler()
+ {
+ $this->report_root->addDescription($this->text);
+ }
- /**
- * Create a list of all descendants.
- *
- * @param string[] $list
- * @param string $pid
- * @param bool $parents
- * @param int $generations
- */
- private function addDescendancy(&$list, $pid, $parents = false, $generations = -1) {
- $person = Individual::getInstance($pid, $this->tree);
- if ($person === null) {
- return;
- }
- if (!isset($list[$pid])) {
- $list[$pid] = $person;
- }
- if (!isset($list[$pid]->generation)) {
- $list[$pid]->generation = 0;
- }
- foreach ($person->getSpouseFamilies() as $family) {
- if ($parents) {
- $husband = $family->getHusband();
- $wife = $family->getWife();
- if ($husband) {
- $list[$husband->getXref()] = $husband;
- if (isset($list[$pid]->generation)) {
- $list[$husband->getXref()]->generation = $list[$pid]->generation - 1;
- } else {
- $list[$husband->getXref()]->generation = 1;
- }
- }
- if ($wife) {
- $list[$wife->getXref()] = $wife;
- if (isset($list[$pid]->generation)) {
- $list[$wife->getXref()]->generation = $list[$pid]->generation - 1;
- } else {
- $list[$wife->getXref()]->generation = 1;
- }
- }
- }
- $children = $family->getChildren();
- foreach ($children as $child) {
- if ($child) {
- $list[$child->getXref()] = $child;
- if (isset($list[$pid]->generation)) {
- $list[$child->getXref()]->generation = $list[$pid]->generation + 1;
- } else {
- $list[$child->getXref()]->generation = 2;
- }
- }
- }
- if ($generations == -1 || $list[$pid]->generation + 1 < $generations) {
- foreach ($children as $child) {
- $this->addDescendancy($list, $child->getXref(), $parents, $generations); // recurse on the childs family
- }
- }
- }
- }
+ /**
+ * Create a list of all descendants.
+ *
+ * @param string[] $list
+ * @param string $pid
+ * @param bool $parents
+ * @param int $generations
+ */
+ private function addDescendancy(&$list, $pid, $parents = false, $generations = -1)
+ {
+ $person = Individual::getInstance($pid, $this->tree);
+ if ($person === null) {
+ return;
+ }
+ if (!isset($list[$pid])) {
+ $list[$pid] = $person;
+ }
+ if (!isset($list[$pid]->generation)) {
+ $list[$pid]->generation = 0;
+ }
+ foreach ($person->getSpouseFamilies() as $family) {
+ if ($parents) {
+ $husband = $family->getHusband();
+ $wife = $family->getWife();
+ if ($husband) {
+ $list[$husband->getXref()] = $husband;
+ if (isset($list[$pid]->generation)) {
+ $list[$husband->getXref()]->generation = $list[$pid]->generation - 1;
+ } else {
+ $list[$husband->getXref()]->generation = 1;
+ }
+ }
+ if ($wife) {
+ $list[$wife->getXref()] = $wife;
+ if (isset($list[$pid]->generation)) {
+ $list[$wife->getXref()]->generation = $list[$pid]->generation - 1;
+ } else {
+ $list[$wife->getXref()]->generation = 1;
+ }
+ }
+ }
+ $children = $family->getChildren();
+ foreach ($children as $child) {
+ if ($child) {
+ $list[$child->getXref()] = $child;
+ if (isset($list[$pid]->generation)) {
+ $list[$child->getXref()]->generation = $list[$pid]->generation + 1;
+ } else {
+ $list[$child->getXref()]->generation = 2;
+ }
+ }
+ }
+ if ($generations == -1 || $list[$pid]->generation + 1 < $generations) {
+ foreach ($children as $child) {
+ $this->addDescendancy($list, $child->getXref(), $parents, $generations); // recurse on the childs family
+ }
+ }
+ }
+ }
- /**
- * Create a list of all ancestors.
- *
- * @param string[] $list
- * @param string $pid
- * @param bool $children
- * @param int $generations
- */
- private function addAncestors(&$list, $pid, $children = false, $generations = -1) {
- $genlist = [$pid];
- $list[$pid]->generation = 1;
- while (count($genlist) > 0) {
- $id = array_shift($genlist);
- if (strpos($id, 'empty') === 0) {
- continue; // id can be something like “empty7”
- }
- $person = Individual::getInstance($id, $this->tree);
- foreach ($person->getChildFamilies() as $family) {
- $husband = $family->getHusband();
- $wife = $family->getWife();
- if ($husband) {
- $list[$husband->getXref()] = $husband;
- $list[$husband->getXref()]->generation = $list[$id]->generation + 1;
- }
- if ($wife) {
- $list[$wife->getXref()] = $wife;
- $list[$wife->getXref()]->generation = $list[$id]->generation + 1;
- }
- if ($generations == -1 || $list[$id]->generation + 1 < $generations) {
- if ($husband) {
- array_push($genlist, $husband->getXref());
- }
- if ($wife) {
- array_push($genlist, $wife->getXref());
- }
- }
- if ($children) {
- foreach ($family->getChildren() as $child) {
- $list[$child->getXref()] = $child;
- if (isset($list[$id]->generation)) {
- $list[$child->getXref()]->generation = $list[$id]->generation;
- } else {
- $list[$child->getXref()]->generation = 1;
- }
- }
- }
- }
- }
- }
+ /**
+ * Create a list of all ancestors.
+ *
+ * @param string[] $list
+ * @param string $pid
+ * @param bool $children
+ * @param int $generations
+ */
+ private function addAncestors(&$list, $pid, $children = false, $generations = -1)
+ {
+ $genlist = [$pid];
+ $list[$pid]->generation = 1;
+ while (count($genlist) > 0) {
+ $id = array_shift($genlist);
+ if (strpos($id, 'empty') === 0) {
+ continue; // id can be something like “empty7”
+ }
+ $person = Individual::getInstance($id, $this->tree);
+ foreach ($person->getChildFamilies() as $family) {
+ $husband = $family->getHusband();
+ $wife = $family->getWife();
+ if ($husband) {
+ $list[$husband->getXref()] = $husband;
+ $list[$husband->getXref()]->generation = $list[$id]->generation + 1;
+ }
+ if ($wife) {
+ $list[$wife->getXref()] = $wife;
+ $list[$wife->getXref()]->generation = $list[$id]->generation + 1;
+ }
+ if ($generations == -1 || $list[$id]->generation + 1 < $generations) {
+ if ($husband) {
+ array_push($genlist, $husband->getXref());
+ }
+ if ($wife) {
+ array_push($genlist, $wife->getXref());
+ }
+ }
+ if ($children) {
+ foreach ($family->getChildren() as $child) {
+ $list[$child->getXref()] = $child;
+ if (isset($list[$id]->generation)) {
+ $list[$child->getXref()]->generation = $list[$id]->generation;
+ } else {
+ $list[$child->getXref()]->generation = 1;
+ }
+ }
+ }
+ }
+ }
+ }
- /**
- * get gedcom tag value
- *
- * @param string $tag The tag to find, use : to delineate subtags
- * @param int $level The gedcom line level of the first tag to find, setting level to 0 will cause it to use 1+ the level of the incoming record
- * @param string $gedrec The gedcom record to get the value from
- *
- * @return string the value of a gedcom tag from the given gedcom record
- */
- private function getGedcomValue($tag, $level, $gedrec) {
- if (empty($gedrec)) {
- return '';
- }
- $tags = explode(':', $tag);
- $origlevel = $level;
- if ($level == 0) {
- $level = $gedrec[0] + 1;
- }
+ /**
+ * get gedcom tag value
+ *
+ * @param string $tag The tag to find, use : to delineate subtags
+ * @param int $level The gedcom line level of the first tag to find, setting level to 0 will cause it to use 1+ the level of the incoming record
+ * @param string $gedrec The gedcom record to get the value from
+ *
+ * @return string the value of a gedcom tag from the given gedcom record
+ */
+ private function getGedcomValue($tag, $level, $gedrec)
+ {
+ if (empty($gedrec)) {
+ return '';
+ }
+ $tags = explode(':', $tag);
+ $origlevel = $level;
+ if ($level == 0) {
+ $level = $gedrec[0] + 1;
+ }
- $subrec = $gedrec;
- foreach ($tags as $t) {
- $lastsubrec = $subrec;
- $subrec = Functions::getSubRecord($level, "$level $t", $subrec);
- if (empty($subrec) && $origlevel == 0) {
- $level--;
- $subrec = Functions::getSubRecord($level, "$level $t", $lastsubrec);
- }
- if (empty($subrec)) {
- if ($t == 'TITL') {
- $subrec = Functions::getSubRecord($level, "$level ABBR", $lastsubrec);
- if (!empty($subrec)) {
- $t = 'ABBR';
- }
- }
- if (empty($subrec)) {
- if ($level > 0) {
- $level--;
- }
- $subrec = Functions::getSubRecord($level, "@ $t", $gedrec);
- if (empty($subrec)) {
- return '';
- }
- }
- }
- $level++;
- }
- $level--;
- $ct = preg_match("/$level $t(.*)/", $subrec, $match);
- if ($ct == 0) {
- $ct = preg_match("/$level @.+@ (.+)/", $subrec, $match);
- }
- if ($ct == 0) {
- $ct = preg_match("/@ $t (.+)/", $subrec, $match);
- }
- if ($ct > 0) {
- $value = trim($match[1]);
- if ($t == 'NOTE' && preg_match('/^@(.+)@$/', $value, $match)) {
- $note = Note::getInstance($match[1], $this->tree);
- if ($note) {
- $value = $note->getNote();
- } else {
- //-- set the value to the id without the @
- $value = $match[1];
- }
- }
- if ($level != 0 || $t != 'NOTE') {
- $value .= Functions::getCont($level + 1, $subrec);
- }
+ $subrec = $gedrec;
+ foreach ($tags as $t) {
+ $lastsubrec = $subrec;
+ $subrec = Functions::getSubRecord($level, "$level $t", $subrec);
+ if (empty($subrec) && $origlevel == 0) {
+ $level--;
+ $subrec = Functions::getSubRecord($level, "$level $t", $lastsubrec);
+ }
+ if (empty($subrec)) {
+ if ($t == 'TITL') {
+ $subrec = Functions::getSubRecord($level, "$level ABBR", $lastsubrec);
+ if (!empty($subrec)) {
+ $t = 'ABBR';
+ }
+ }
+ if (empty($subrec)) {
+ if ($level > 0) {
+ $level--;
+ }
+ $subrec = Functions::getSubRecord($level, "@ $t", $gedrec);
+ if (empty($subrec)) {
+ return '';
+ }
+ }
+ }
+ $level++;
+ }
+ $level--;
+ $ct = preg_match("/$level $t(.*)/", $subrec, $match);
+ if ($ct == 0) {
+ $ct = preg_match("/$level @.+@ (.+)/", $subrec, $match);
+ }
+ if ($ct == 0) {
+ $ct = preg_match("/@ $t (.+)/", $subrec, $match);
+ }
+ if ($ct > 0) {
+ $value = trim($match[1]);
+ if ($t == 'NOTE' && preg_match('/^@(.+)@$/', $value, $match)) {
+ $note = Note::getInstance($match[1], $this->tree);
+ if ($note) {
+ $value = $note->getNote();
+ } else {
+ //-- set the value to the id without the @
+ $value = $match[1];
+ }
+ }
+ if ($level != 0 || $t != 'NOTE') {
+ $value .= Functions::getCont($level + 1, $subrec);
+ }
- return $value;
- }
+ return $value;
+ }
- return '';
- }
+ return '';
+ }
- /**
- * Replace variable identifiers with their values.
- *
- * @param string $expression An expression such as "$foo == 123"
- * @param bool $quote Whether to add quotation marks
- *
- * @return string
- */
- private function substituteVars($expression, $quote) {
- return preg_replace_callback(
- '/\$(\w+)/',
- function ($matches) use ($quote) {
- if (isset($this->vars[$matches[1]]['id'])) {
- if ($quote) {
- return "'" . addcslashes($this->vars[$matches[1]]['id'], "'") . "'";
- } else {
- return $this->vars[$matches[1]]['id'];
- }
- } else {
- Log::addErrorLog(sprintf('Undefined variable $%s in report', $matches[1]));
+ /**
+ * Replace variable identifiers with their values.
+ *
+ * @param string $expression An expression such as "$foo == 123"
+ * @param bool $quote Whether to add quotation marks
+ *
+ * @return string
+ */
+ private function substituteVars($expression, $quote)
+ {
+ return preg_replace_callback(
+ '/\$(\w+)/',
+ function ($matches) use ($quote) {
+ if (isset($this->vars[$matches[1]]['id'])) {
+ if ($quote) {
+ return "'" . addcslashes($this->vars[$matches[1]]['id'], "'") . "'";
+ } else {
+ return $this->vars[$matches[1]]['id'];
+ }
+ } else {
+ Log::addErrorLog(sprintf('Undefined variable $%s in report', $matches[1]));
- return '$' . $matches[1];
- }
- },
- $expression
- );
- }
+ return '$' . $matches[1];
+ }
+ },
+ $expression
+ );
+ }
}