public static function showFact(WT_Fact $fact) { switch ($fact->getTag()) { case 'AFN': case 'CHAN': case 'IDNO': case 'REFN': case 'RFN': case 'RIN': case 'SSN': case '_UID': return true; default: return false; } }
function print_fact(WT_Fact $fact, WT_GedcomRecord $record) { global $HIDE_GEDCOM_ERRORS, $SHOW_FACT_ICONS; static $n_chil = 0, $n_gchi = 0; $parent = $fact->getParent(); // Some facts don't get printed here ... switch ($fact->getTag()) { case 'NOTE': print_main_notes($fact, 1); return; case 'SOUR': print_main_sources($fact, 1); return; case 'OBJE': print_main_media($fact, 1); return; case 'FAMC': case 'FAMS': case 'CHIL': case 'HUSB': case 'WIFE': // These are internal links, not facts return; case '_WT_OBJE_SORT': // These links are used internally to record the sort order. return; default: // Hide unrecognized/custom tags? if ($HIDE_GEDCOM_ERRORS && !WT_Gedcom_Tag::isTag($fact->getTag())) { return; } break; } // Who is this fact about? Need it to translate fact label correctly if ($parent instanceof WT_Family && $record instanceof WT_Individual) { // Family event $label_person = $fact->getParent()->getSpouse($record); } else { // Individual event $label_person = $parent; } // New or deleted facts need different styling $styleadd = ''; if ($fact->isNew()) { $styleadd = 'new'; } if ($fact->isOld()) { $styleadd = 'old'; } // Event of close relative if (preg_match('/^_[A-Z_]{3,5}_[A-Z0-9]{4}$/', $fact->getTag())) { $styleadd = trim($styleadd . ' rela'); } // Event of close associates if ($fact->getFactId() == 'asso') { $styleadd = trim($styleadd . ' rela'); } // historical facts if ($fact->getFactId() == 'histo') { $styleadd = trim($styleadd . ' histo'); } // Does this fact have a type? if (preg_match('/\\n2 TYPE (.+)/', $fact->getGedcom(), $match)) { $type = $match[1]; } else { $type = ''; } switch ($fact->getTag()) { case 'EVEN': case 'FACT': if (WT_Gedcom_Tag::isTag($type)) { // Some users (just Meliza?) use "1 EVEN/2 TYPE BIRT". Translate the TYPE. $label = WT_Gedcom_Tag::getLabel($type, $label_person); $type = ''; // Do not print this again } elseif ($type) { // We don't have a translation for $type - but a custom translation might exist. $label = WT_I18N::translate(WT_Filter::escapeHtml($type)); $type = ''; // Do not print this again } else { // An unspecified fact/event $label = $fact->getLabel(); } break; case 'MARR': // This is a hack for a proprietory extension. Is it still used/needed? $utype = strtoupper($type); if ($utype == 'CIVIL' || $utype == 'PARTNERS' || $utype == 'RELIGIOUS') { $label = WT_Gedcom_Tag::getLabel('MARR_' . $utype, $label_person); $type = ''; // Do not print this again } else { $label = $fact->getLabel(); } break; default: // Normal fact/event $label = $fact->getLabel(); break; } echo '<tr class="', $styleadd, '">'; echo '<td class="descriptionbox width20">'; if ($SHOW_FACT_ICONS) { echo $fact->Icon(), ' '; } if ($fact->getFactId() != 'histo' && $fact->canEdit()) { ?> <a href="#" title="<?php echo WT_I18N::translate('Edit'); ?> " onclick="return edit_record('<?php echo $parent->getXref(); ?> ', '<?php echo $fact->getFactId(); ?> ');" ><?php echo $label; ?> </a> <div class="editfacts"> <div class="editlink"> <a href="#" title="<?php echo WT_I18N::translate('Edit'); ?> " class="editicon" onclick="return edit_record('<?php echo $parent->getXref(); ?> ', '<?php echo $fact->getFactId(); ?> ');" ><span class="link_text"><?php echo WT_I18N::translate('Edit'); ?> </span></a> </div> <div class="copylink"> <a href="#" title="<?php echo WT_I18N::translate('Copy'); ?> " class="copyicon" onclick="return copy_fact('<?php echo $parent->getXref(); ?> ', '<?php echo $fact->getFactId(); ?> ');" ><span class="link_text"><?php echo WT_I18N::translate('Copy'); ?> </span></a> </div> <div class="deletelink"> <a href="#" title="<?php echo WT_I18N::translate('Delete'); ?> " class="deleteicon" onclick="return delete_fact('<?php echo WT_I18N::translate('Are you sure you want to delete this fact?'); ?> ', '<?php echo $parent->getXref(); ?> ', '<?php echo $fact->getFactId(); ?> ');" ><span class="link_text"><?php echo WT_I18N::translate('Delete'); ?> </span></a> </div> </div> <?php } else { echo $label; } switch ($fact->getTag()) { case '_BIRT_CHIL': echo '<br>', WT_I18N::translate('#%s', ++$n_chil); break; case '_BIRT_GCHI': case '_BIRT_GCH1': case '_BIRT_GCH2': echo '<br>', WT_I18N::translate('#%s', ++$n_gchi); break; } echo '</td><td class="optionbox ', $styleadd, ' wrap">'; // Event from another record? if ($parent !== $record) { if ($parent instanceof WT_Family) { foreach ($parent->getSpouses() as $spouse) { if ($record !== $spouse) { echo '<a href="', $spouse->getHtmlUrl(), '">', $spouse->getFullName(), '</a> — '; } } echo '<a href="', $parent->getHtmlUrl(), '">', WT_I18N::translate('View family'), '</a><br>'; } elseif ($parent instanceof WT_Individual) { echo '<a href="', $parent->getHtmlUrl(), '">', $parent->getFullName(), '</a><br>'; } } // Print the value of this fact/event switch ($fact->getTag()) { case 'ADDR': echo $fact->getValue(); break; case 'AFN': echo '<div class="field"><a href="https://familysearch.org/search/tree/results#count=20&query=afn:', rawurlencode($fact->getValue()), '" target="new">', WT_Filter::escapeHtml($fact->getValue()), '</a></div>'; break; case 'ASSO': // we handle this later, in format_asso_rela_record() break; case 'EMAIL': case 'EMAI': case '_EMAIL': echo '<div class="field"><a href="mailto:', WT_Filter::escapeHtml($fact->getValue()), '">', WT_Filter::escapeHtml($fact->getValue()), '</a></div>'; break; case 'FILE': if (WT_USER_CAN_EDIT || WT_USER_CAN_ACCEPT) { echo '<div class="field">', WT_Filter::escapeHtml($fact->getValue()), '</div>'; } break; case 'RESN': echo '<div class="field">'; switch ($fact->getValue()) { case 'none': // Note: "1 RESN none" is not valid gedcom. // However, webtrees privacy rules will interpret it as "show an otherwise private record to public". echo '<i class="icon-resn-none"></i> ', WT_I18N::translate('Show to visitors'); break; case 'privacy': echo '<i class="icon-class-none"></i> ', WT_I18N::translate('Show to members'); break; case 'confidential': echo '<i class="icon-confidential-none"></i> ', WT_I18N::translate('Show to managers'); break; case 'locked': echo '<i class="icon-locked-none"></i> ', WT_I18N::translate('Only managers can edit'); break; default: echo WT_Filter::escapeHtml($fact->getValue()); break; } echo '</div>'; break; case 'PUBL': // Publication details might contain URLs. echo '<div class="field">', WT_Filter::expandUrls($fact->getValue()), '</div>'; break; case 'REPO': if (preg_match('/^@(' . WT_REGEX_XREF . ')@$/', $fact->getValue(), $match)) { print_repository_record($match[1]); } else { echo '<div class="error">', WT_Filter::escapeHtml($fact->getValue()), '</div>'; } break; case 'URL': case '_URL': case 'WWW': echo '<div class="field"><a href="', WT_Filter::escapeHtml($fact->getValue()), '">', WT_Filter::escapeHtml($fact->getValue()), '</a></div>'; break; case 'TEXT': // 0 SOUR / 1 TEXT echo '<div class="field">', nl2br(WT_Filter::escapeHtml($fact->getValue()), false), '</div>'; break; default: // Display the value for all other facts/events switch ($fact->getValue()) { case '': // Nothing to display break; case 'N': // Not valid GEDCOM echo '<div class="field">', WT_I18N::translate('No'), '</div>'; break; case 'Y': // Do not display "Yes". break; default: if (preg_match('/^@(' . WT_REGEX_XREF . ')@$/', $fact->getValue(), $match)) { $target = WT_GedcomRecord::getInstance($match[1]); if ($target) { echo '<div><a href="', $target->getHtmlUrl(), '">', $target->getFullName(), '</a></div>'; } else { echo '<div class="error">', WT_Filter::escapeHtml($fact->getValue()), '</div>'; } } else { echo '<div class="field"><span dir="auto">', WT_Filter::escapeHtml($fact->getValue()), '</span></div>'; } break; } break; } // Print the type of this fact/event if ($type) { $utype = strtoupper($type); // Events of close relatives, e.g. _MARR_CHIL if (substr($fact->getTag(), 0, 6) == '_MARR_' && ($utype == 'CIVIL' || $utype == 'PARTNERS' || $utype == 'RELIGIOUS')) { // Translate MARR/TYPE using the code that supports MARR_CIVIL, etc. tags $type = WT_Gedcom_Tag::getLabel('MARR_' . $utype); } else { // Allow (custom) translations for other types $type = WT_I18N::translate($type); } echo WT_Gedcom_Tag::getLabelValue('TYPE', WT_Filter::escapeHtml($type)); } // Print the date of this fact/event echo format_fact_date($fact, $record, true, true); // Print the place of this fact/event echo '<div class="place">', format_fact_place($fact, true, true, true), '</div>'; // A blank line between the primary attributes (value, date, place) and the secondary ones echo '<br>'; $addr = $fact->getAttribute('ADDR'); if ($addr) { echo WT_Gedcom_Tag::getLabelValue('ADDR', $addr); } // Print the associates of this fact/event echo format_asso_rela_record($fact); // Print any other "2 XXXX" attributes, in the order in which they appear. preg_match_all('/\\n2 (' . WT_REGEX_TAG . ') (.+)/', $fact->getGedcom(), $matches, PREG_SET_ORDER); foreach ($matches as $match) { switch ($match[1]) { case 'DATE': case 'TIME': case 'AGE': case 'PLAC': case 'ADDR': case 'ALIA': case 'ASSO': case '_ASSO': case 'DESC': case 'RELA': case 'STAT': case 'TEMP': case 'TYPE': case 'FAMS': case 'CONT': // These were already shown at the beginning break; case 'NOTE': case 'OBJE': case 'SOUR': // These will be shown at the end break; case 'EVEN': // 0 SOUR / 1 DATA / 2 EVEN / 3 DATE / 3 PLAC $events = array(); foreach (preg_split('/ *, */', $match[2]) as $event) { $events[] = WT_Gedcom_Tag::getLabel($event); } if (count($events) == 1) { echo WT_Gedcom_Tag::getLabelValue('EVEN', $event); } else { echo WT_Gedcom_Tag::getLabelValue('EVEN', implode(WT_I18N::$list_separator, $events)); } if (preg_match('/\\n3 DATE (.+)/', $fact->getGedcom(), $date_match)) { $date = new WT_Date($date_match[1]); echo WT_Gedcom_Tag::getLabelValue('DATE', $date->Display()); } if (preg_match('/\\n3 PLAC (.+)/', $fact->getGedcom(), $plac_match)) { echo WT_Gedcom_Tag::getLabelValue('PLAC', $plac_match[1]); } break; case 'FAMC': // 0 INDI / 1 ADOP / 2 FAMC / 3 ADOP $family = WT_Family::getInstance(str_replace('@', '', $match[2])); if ($family) { // May be a pointer to a non-existant record echo WT_Gedcom_Tag::getLabelValue('FAM', '<a href="' . $family->getHtmlUrl() . '">' . $family->getFullName() . '</a>'); if (preg_match('/\\n3 ADOP (HUSB|WIFE|BOTH)/', $fact->getGedcom(), $match)) { echo WT_Gedcom_Tag::getLabelValue('ADOP', WT_Gedcom_Code_Adop::getValue($match[1], $label_person)); } } else { echo WT_Gedcom_Tag::getLabelValue('FAM', '<span class="error">' . $match[2] . '</span>'); } break; case '_WT_USER': $user = User::findByIdentifier($match[2]); // may not exist if ($user) { echo WT_Gedcom_Tag::getLabelValue('_WT_USER', WT_Filter::escapeHtml($user->getRealName())); } else { echo WT_Gedcom_Tag::getLabelValue('_WT_USER', WT_Filter::escapeHtml($match[2])); } break; case 'RESN': switch ($match[2]) { case 'none': // Note: "2 RESN none" is not valid gedcom. // However, webtrees privacy rules will interpret it as "show an otherwise private fact to public". echo WT_Gedcom_Tag::getLabelValue('RESN', '<i class="icon-resn-none"></i> ' . WT_I18N::translate('Show to visitors')); break; case 'privacy': echo WT_Gedcom_Tag::getLabelValue('RESN', '<i class="icon-resn-privacy"></i> ' . WT_I18N::translate('Show to members')); break; case 'confidential': echo WT_Gedcom_Tag::getLabelValue('RESN', '<i class="icon-resn-confidential"></i> ' . WT_I18N::translate('Show to managers')); break; case 'locked': echo WT_Gedcom_Tag::getLabelValue('RESN', '<i class="icon-resn-locked"></i> ' . WT_I18N::translate('Only managers can edit')); break; default: echo WT_Gedcom_Tag::getLabelValue('RESN', WT_Filter::escapeHtml($match[2])); break; } break; case 'CALN': echo WT_Gedcom_Tag::getLabelValue('CALN', WT_Filter::expandUrls($match[2])); break; case 'FORM': // 0 OBJE / 1 FILE / 2 FORM / 3 TYPE echo WT_Gedcom_Tag::getLabelValue('FORM', $match[2]); if (preg_match('/\\n3 TYPE (.+)/', $fact->getGedcom(), $type_match)) { echo WT_Gedcom_Tag::getLabelValue('TYPE', WT_Gedcom_Tag::getFileFormTypeValue($type_match[1])); } break; case 'URL': case '_URL': case 'WWW': $link = '<a href="' . WT_Filter::escapeHtml($match[2]) . '">' . WT_Filter::escapeHtml($match[2]) . '</a>'; echo WT_Gedcom_Tag::getLabelValue($fact->getTag() . ':' . $match[1], $link); break; default: if (!$HIDE_GEDCOM_ERRORS || WT_Gedcom_Tag::isTag($match[1])) { if (preg_match('/^@(' . WT_REGEX_XREF . ')@$/', $match[2], $xmatch)) { // Links $linked_record = WT_GedcomRecord::getInstance($xmatch[1]); if ($linked_record) { $link = '<a href="' . $linked_record->getHtmlUrl() . '">' . $linked_record->getFullName() . '</a>'; echo WT_Gedcom_Tag::getLabelValue($fact->getTag() . ':' . $match[1], $link); } else { echo WT_Gedcom_Tag::getLabelValue($fact->getTag() . ':' . $match[1], WT_Filter::escapeHtml($match[2])); } } else { // Non links echo WT_Gedcom_Tag::getLabelValue($fact->getTag() . ':' . $match[1], WT_Filter::escapeHtml($match[2])); } } break; } } echo print_fact_sources($fact->getGedcom(), 2); echo print_fact_notes($fact->getGedcom(), 2); print_media_links($fact->getGedcom(), 2); echo '</td></tr>'; }
function format_fact_date(WT_Fact $event, WT_GedcomRecord $record, $anchor = false, $time = false) { global $pid, $SEARCH_SPIDER, $SHOW_PARENTS_AGE; $factrec = $event->getGedcom(); $html = ''; // 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 if (preg_match('/2 DATE (.+)/', $factrec, $match)) { $date = new WT_Date($match[1]); $html .= ' ' . $date->Display($anchor && !$SEARCH_SPIDER); // time if ($time) { $timerec = get_sub_record(2, '2 TIME', $factrec); if ($timerec == '') { $timerec = get_sub_record(2, '2 DATE', $factrec); } if (preg_match('/[2-3] TIME (.*)/', $timerec, $tmatch)) { $html .= '<span class="date"> - ' . $tmatch[1] . '</span>'; } } $fact = $event->getTag(); if ($record instanceof WT_Individual) { // age of parents at child birth if ($fact == 'BIRT' && $SHOW_PARENTS_AGE) { $html .= format_parents_age($record, $date); } else { if ($fact != 'CHAN' && $fact != '_TODO') { $birth_date = $record->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 = $record->getFirstFact('DEAT'); if ($death_event) { $death_date = $death_event->getDate(); } else { $death_date = new WT_Date(''); } $ageText = ''; if (WT_Date::Compare($date, $death_date) <= 0 || !$record->isDead() || $fact == 'DEAT') { // Before death, print age $age = WT_Date::GetAgeGedcom($birth_date, $date); // Only show calculated age if it differs from recorded age if ($age != '') { if ($fact_age != '' && $fact_age != $age || $fact_age == '' && $husb_age == '' && $wife_age == '' || $husb_age != '' && $record->getSex() == 'M' && $husb_age != $age || $wife_age != '' && $record->getSex() == 'F' && $wife_age != $age) { if ($age != "0d") { $ageText = '(' . WT_I18N::translate('Age') . ' ' . get_age_at_event($age, false) . ')'; } } } } if ($fact != 'DEAT' && WT_Date::Compare($date, $death_date) >= 0) { // After death, print time since death $age = get_age_at_event(WT_Date::GetAgeGedcom($death_date, $date), true); if ($age != '') { if (WT_Date::GetAgeGedcom($death_date, $date) == "0d") { $ageText = '(' . WT_I18N::translate('on the date of death') . ')'; } else { $ageText = '(' . $age . ' ' . WT_I18N::translate('after death') . ')'; // Family events which occur after death are probably errors if ($event->getParent() instanceof WT_Family) { $ageText .= '<i class="icon-warning"></i>'; } } } } if ($ageText) { $html .= ' <span class="age">' . $ageText . '</span>'; } } } } elseif ($record instanceof WT_Family) { $indi = WT_Individual::getInstance($pid); if ($indi) { $birth_date = $indi->getBirthDate(); $death_date = $indi->getDeathDate(); $ageText = ''; if (WT_Date::Compare($date, $death_date) <= 0) { $age = WT_Date::GetAgeGedcom($birth_date, $date); // Only show calculated age if it differs from recorded age if ($age != '' && $age > 0) { if ($fact_age != '' && $fact_age != $age || $fact_age == '' && $husb_age == '' && $wife_age == '' || $husb_age != '' && $indi->getSex() == 'M' && $husb_age != $age || $wife_age != '' && $indi->getSex() == 'F' && $wife_age != $age) { $ageText = '(' . WT_I18N::translate('Age') . ' ' . get_age_at_event($age, false) . ')'; } } } if ($ageText) { $html .= ' <span class="age">' . $ageText . '</span>'; } } } } else { // 1 DEAT Y with no DATE => print YES // 1 BIRT 2 SOUR @S1@ => print YES // 1 DEAT N is not allowed // It is not proper GEDCOM form to use a N(o) value with an event tag to infer that it did not happen. $factdetail = explode(' ', trim($factrec)); if (isset($factdetail) && (count($factdetail) == 3 && strtoupper($factdetail[2]) == 'Y') || count($factdetail) == 4 && $factdetail[2] == 'SOUR') { $html .= WT_I18N::translate('yes'); } } // print gedcom ages foreach (array(WT_Gedcom_Tag::getLabel('AGE') => $fact_age, WT_Gedcom_Tag::getLabel('HUSB') => $husb_age, WT_Gedcom_Tag::getLabel('WIFE') => $wife_age) as $label => $age) { if ($age != '') { $html .= ' <span class="label">' . $label . ':</span> <span class="age">' . get_age_at_event($age, false) . '</span>'; } } return $html; }
function create_edit_form(WT_GedcomRecord $record, WT_Fact $fact) { global $ADVANCED_PLAC_FACTS, $date_and_time, $FULL_SOURCES, $tags; $pid = $record->getXref(); $tags = array(); $gedlines = explode("\n", $fact->getGedcom()); $linenum = 0; $fields = explode(' ', $gedlines[$linenum]); $glevel = $fields[0]; $level = $glevel; $type = $fact->getTag(); $parent = $fact->getParent(); $level0type = $parent::RECORD_TYPE; $level1type = $type; $i = $linenum; $inSource = false; $levelSource = 0; $add_date = true; // List of tags we would expect at the next level // NB add_missing_subtags() already takes care of the simple cases // where a level 1 tag is missing a level 2 tag. Here we only need to // handle the more complicated cases. $expected_subtags = array('SOUR' => array('PAGE', 'DATA'), 'DATA' => array('TEXT'), 'PLAC' => array('MAP'), 'MAP' => array('LATI', 'LONG')); if ($FULL_SOURCES) { $expected_subtags['SOUR'][] = 'QUAY'; $expected_subtags['DATA'][] = 'DATE'; } if (preg_match_all('/(' . WT_REGEX_TAG . ')/', $ADVANCED_PLAC_FACTS, $match)) { $expected_subtags['PLAC'] = array_merge($match[1], $expected_subtags['PLAC']); } $stack = array(0 => $level0type); // Loop on existing tags : while (true) { // Keep track of our hierarchy, e.g. 1=>BIRT, 2=>PLAC, 3=>FONE $stack[(int) $level] = $type; // Merge them together, e.g. BIRT:PLAC:FONE $label = implode(':', array_slice($stack, 1, $level)); $text = ''; for ($j = 2; $j < count($fields); $j++) { if ($j > 2) { $text .= ' '; } $text .= $fields[$j]; } $text = rtrim($text); while ($i + 1 < count($gedlines) && preg_match("/" . ($level + 1) . " CONT ?(.*)/", $gedlines[$i + 1], $cmatch) > 0) { $text .= "\n" . $cmatch[1]; $i++; } if ($type == "SOUR") { $inSource = true; $levelSource = $level; } elseif ($levelSource >= $level) { $inSource = false; } if ($type != "DATA" && $type != "CONT") { $tags[] = $type; $person = WT_Individual::getInstance($pid); $subrecord = $level . ' ' . $type . ' ' . $text; if ($inSource && $type == "DATE") { add_simple_tag($subrecord, '', WT_Gedcom_Tag::getLabel($label, $person)); } elseif (!$inSource && $type == "DATE") { add_simple_tag($subrecord, $level1type, WT_Gedcom_Tag::getLabel($label, $person)); $add_date = false; } elseif ($type == 'STAT') { add_simple_tag($subrecord, $level1type, WT_Gedcom_Tag::getLabel($label, $person)); } elseif ($level0type == 'REPO') { $repo = WT_Repository::getInstance($pid); add_simple_tag($subrecord, $level0type, WT_Gedcom_Tag::getLabel($label, $repo)); } else { add_simple_tag($subrecord, $level0type, WT_Gedcom_Tag::getLabel($label, $person)); } } // Get a list of tags present at the next level $subtags = array(); for ($ii = $i + 1; isset($gedlines[$ii]) && preg_match('/^\\s*(\\d+)\\s+(\\S+)/', $gedlines[$ii], $mm) && $mm[1] > $level; ++$ii) { if ($mm[1] == $level + 1) { $subtags[] = $mm[2]; } } // Insert missing tags if (!empty($expected_subtags[$type])) { foreach ($expected_subtags[$type] as $subtag) { if (!in_array($subtag, $subtags)) { if (!$inSource || $subtag != "DATA") { add_simple_tag($level + 1 . ' ' . $subtag, '', WT_Gedcom_Tag::getLabel("{$label}:{$subtag}")); } if (!empty($expected_subtags[$subtag])) { foreach ($expected_subtags[$subtag] as $subsubtag) { add_simple_tag($level + 2 . ' ' . $subsubtag, '', WT_Gedcom_Tag::getLabel("{$label}:{$subtag}:{$subsubtag}")); } } } } } // Awkward special cases if ($level == 2 && $type == 'DATE' && in_array($level1type, $date_and_time) && !in_array('TIME', $subtags)) { add_simple_tag("3 TIME"); // TIME is NOT a valid 5.5.1 tag } if ($level == 2 && $type == 'STAT' && WT_Gedcom_Code_Temp::isTagLDS($level1type) && !in_array('DATE', $subtags)) { add_simple_tag("3 DATE", '', WT_Gedcom_Tag::getLabel('STAT:DATE')); } $i++; if (isset($gedlines[$i])) { $fields = explode(' ', $gedlines[$i]); $level = $fields[0]; if (isset($fields[1])) { $type = trim($fields[1]); } else { $level = 0; } } else { $level = 0; } if ($level <= $glevel) { break; } } if ($level1type != '_PRIM') { insert_missing_subtags($level1type, $add_date); } return $level1type; }
/** * Static method to compare two events by their type. * * @param WT_Fact $a Fact one * @param WT_Fact $b Fact two * * @return integer */ public static function CompareType(WT_Fact $a, WT_Fact $b) { global $factsort; if (empty($factsort)) { $factsort = array_flip(array('BIRT', '_HNM', 'ALIA', '_AKA', '_AKAN', 'ADOP', '_ADPF', '_ADPF', '_BRTM', 'CHR', 'BAPM', 'FCOM', 'CONF', 'BARM', 'BASM', 'EDUC', 'GRAD', '_DEG', 'EMIG', 'IMMI', 'NATU', '_MILI', '_MILT', 'ENGA', 'MARB', 'MARC', 'MARL', '_MARI', '_MBON', 'MARR', 'MARR_CIVIL', 'MARR_RELIGIOUS', 'MARR_PARTNERS', 'MARR_UNKNOWN', '_COML', '_STAT', '_SEPR', 'DIVF', 'MARS', '_BIRT_CHIL', 'DIV', 'ANUL', '_BIRT_', '_MARR_', '_DEAT_', '_BURI_', 'CENS', 'OCCU', 'RESI', 'PROP', 'CHRA', 'RETI', 'FACT', 'EVEN', '_NMR', '_NMAR', 'NMR', 'NCHI', 'WILL', '_HOL', '_????_', 'DEAT', '_FNRL', 'CREM', 'BURI', '_INTE', '_YART', '_NLIV', 'PROB', 'TITL', 'COMM', 'NATI', 'CITN', 'CAST', 'RELI', 'SSN', 'IDNO', 'TEMP', 'SLGC', 'BAPL', 'CONL', 'ENDL', 'SLGS', 'ADDR', 'PHON', 'EMAIL', '_EMAIL', 'EMAL', 'FAX', 'WWW', 'URL', '_URL', 'FILE', 'AFN', 'REFN', '_PRMN', 'REF', 'RIN', '_UID', 'OBJE', 'NOTE', 'SOUR', 'CHAN', '_TODO')); } // Facts from same families stay grouped together // Keep MARR and DIV from the same families from mixing with events from other FAMs // Use the original order in which the facts were added if ($a->parent instanceof WT_Family && $b->parent instanceof WT_Family && $a->parent !== $b->parent) { return $a->sortOrder - $b->sortOrder; } $atag = $a->getTag(); $btag = $b->getTag(); // Events not in the above list get mapped onto one that is. if (!array_key_exists($atag, $factsort)) { if (preg_match('/^(_(BIRT|MARR|DEAT|BURI)_)/', $atag, $match)) { $atag = $match[1]; } else { $atag = "_????_"; } } if (!array_key_exists($btag, $factsort)) { if (preg_match('/^(_(BIRT|MARR|DEAT|BURI)_)/', $btag, $match)) { $btag = $match[1]; } else { $btag = "_????_"; } } // - Don't let dated after DEAT/BURI facts sort non-dated facts before DEAT/BURI // - Treat dated after BURI facts as BURI instead if ($a->getAttribute('DATE') != null && $factsort[$atag] > $factsort['BURI'] && $factsort[$atag] < $factsort['CHAN']) { $atag = 'BURI'; } if ($b->getAttribute('DATE') != null && $factsort[$btag] > $factsort['BURI'] && $factsort[$btag] < $factsort['CHAN']) { $btag = 'BURI'; } $ret = $factsort[$atag] - $factsort[$btag]; // If facts are the same then put dated facts before non-dated facts if ($ret == 0) { if ($a->getAttribute('DATE') != null && $b->getAttribute('DATE') == null) { return -1; } if ($b->getAttribute('DATE') != null && $a->getAttribute('DATE') == null) { return 1; } // If no sorting preference, then keep original ordering $ret = $a->sortOrder - $b->sortOrder; } return $ret; }