gedcom = $gedcom; $this->parent = $parent; $this->fact_id = $fact_id; $this->tag = $match[1]; } else { // TODO need to rewrite code that passes dummy data to this function //throw new Exception('Invalid GEDCOM data passed to WT_Fact::_construct('.$gedcom.')'); } } // Get the value of level 1 data in the fact // Allow for multi-line values public function getValue() { if (preg_match('/^1 (?:' . $this->tag . ') ?(.*(?:(?:\n2 CONT ?.*)*))/', $this->gedcom, $match)) { return preg_replace("/\n2 CONT ?/", "\n", $match[1]); } else { return null; } } // Get the record to which this fact links public function getTarget() { $xref = trim($this->getValue(), '@'); switch ($this->tag) { case 'FAMC': case 'FAMS': return WT_Family::getInstance($xref, $this->getParent()->getGedcomId()); case 'HUSB': case 'WIFE': case 'CHIL': return WT_Individual::getInstance($xref, $this->getParent()->getGedcomId()); case 'SOUR': return WT_Source::getInstance($xref, $this->getParent()->getGedcomId()); case 'OBJE': return WT_Media::getInstance($xref, $this->getParent()->getGedcomId()); case 'REPO': return WT_Repository::getInstance($xref, $this->getParent()->getGedcomId()); case 'NOTE': return WT_Note::getInstance($xref, $this->getParent()->getGedcomId()); default: return WT_GedcomRecord::getInstance($xref, $this->getParent()->getGedcomId()); } } // Get the value of level 2 data in the fact public function getAttribute($tag) { if (preg_match('/\n2 (?:' . $tag . ') ?(.*(?:(?:\n3 CONT ?.*)*)*)/', $this->gedcom, $match)) { return preg_replace("/\n3 CONT ?/", "\n", $match[1]); } else { return null; } } // Do the privacy rules allow us to display this fact to the current user public function canShow($access_level=WT_USER_ACCESS_LEVEL) { // TODO - use the privacy settings for $this->gedcom_id, not the default gedcom. global $person_facts, $global_facts; // Does this record have an explicit RESN? if (strpos($this->gedcom, "\n2 RESN confidential")) { return WT_PRIV_NONE >= $access_level; } if (strpos($this->gedcom, "\n2 RESN privacy")) { return WT_PRIV_USER >= $access_level; } if (strpos($this->gedcom, "\n2 RESN none")) { return true; } // Does this record have a default RESN? $xref = $this->parent->getXref(); if (isset($person_facts[$xref][$this->tag])) { return $person_facts[$xref][$this->tag] >= $access_level; } if (isset($global_facts[$this->tag])) { return $global_facts[$this->tag] >= $access_level; } // No restrictions - it must be public return true; } // Check whether this fact is protected against edit public function canEdit() { // Managers can edit anything // Members cannot edit RESN, CHAN and locked records return $this->parent->canEdit() && !$this->isOld() && ( WT_USER_GEDCOM_ADMIN || WT_USER_CAN_EDIT && strpos($this->gedcom, "\n2 RESN locked")===false && $this->getTag()!='RESN' && $this->getTag()!='CHAN' ); } // The place where the event occured. public function getPlace() { if ($this->place === null) { $this->place = new WT_Place($this->getAttribute('PLAC'), $this->getParent()->getGedcomId()); } return $this->place; } // We can call this function many times, especially when sorting, // so keep a copy of the date. public function getDate() { if ($this->date === null) { $this->date = new WT_Date($this->getAttribute('DATE')); } return $this->date; } // The raw GEDCOM data for this fact public function getGedcom() { return $this->gedcom; } // Unique identifier for the fact public function getFactId() { return $this->fact_id; } // What sort of fact is this? public function getTag() { return $this->tag; } // Used to convert a real fact (e.g. BIRT) into a close-relative’s fact (e.g. _BIRT_CHIL) public function setTag($tag) { $this->tag = $tag; } // The Person/Family record where this WT_Fact came from public function getParent() { return $this->parent; } public function getLabel() { switch($this->tag) { case 'EVEN': case 'FACT': if ($this->getAttribute('TYPE')) { // Custom FACT/EVEN - with a TYPE return WT_I18N::translate(WT_Filter::escapeHtml($this->getAttribute('TYPE'))); } // no break - drop into next case default: return WT_Gedcom_Tag::getLabel($this->tag, $this->parent); } } // Is this a pending edit? public function setIsOld() { $this->is_old = true; $this->is_new = false; } public function isOld() { return $this->is_old; } public function setIsNew() { $this->is_new = true; $this->is_old = false; } public function isNew() { return $this->is_new; } // Source citations linked to this fact public function getCitations() { preg_match_all('/\n(2 SOUR @(' . WT_REGEX_XREF . ')@(?:\n[3-9] .*)*)/', $this->getGedcom(), $matches, PREG_SET_ORDER); $citations = array(); foreach ($matches as $match) { $source = WT_Source::getInstance($match[2], $this->getParent()->getGedcomId()); if ($source->canShow()) { $citations[] = $match[1]; } } return $citations; } // Notes (inline and objects) linked to this fact public function getNotes() { $notes = array(); preg_match_all('/\n2 NOTE ?(.*(?:\n3.*)*)/', $this->getGedcom(), $matches); foreach ($matches[1] as $match) { $note = preg_replace("/\n3 CONT ?/", "\n", $match); if (preg_match('/@(' . WT_REGEX_XREF . ')@/', $note, $nmatch)) { $note = WT_Note::getInstance($nmatch[1], $this->getParent()->getGedcomId()); if ($note && $note->canShow()) { // A note object $notes[] = $note; } } else { // An inline note $notes[] = $note; } } return $notes; } // Media objects linked to this fact public function getMedia() { $media = array(); preg_match_all('/\n2 OBJE @(' . WT_REGEX_XREF . ')@/', $this->getGedcom(), $matches); foreach ($matches[1] as $match) { $obje = WT_Media::getInstance($match, $this->getParent()->getGedcomId()); if ($obje->canShow()) { $media[] = $obje; } } return $media; } // A one-line summary of the fact - for charts, etc. public function summary() { global $SHOW_PARENTS_AGE; $attributes = array(); $target = $this->getTarget(); if ($target) { $attributes[] = $target->getFullName(); } else { $value = $this->getValue(); if ($value && $value!='Y') { $attributes[] = '' . WT_Filter::escapeHtml($value) . ''; } $date = $this->getDate(); if ($this->getTag() == 'BIRT' && $SHOW_PARENTS_AGE && $this->getParent() instanceof WT_Individual) { $attributes[] = $date->display() . format_parents_age($this->getParent(), $date); } else { $attributes[] = $date->display(); } $place = $this->getPlace()->getShortName(); if ($place) { $attributes[] = $place; } } $html = WT_Gedcom_Tag::getLabelValue($this->getTag(), implode(' — ', $attributes), $this->getParent()); if ($this->isNew()) { return '
' . $html . '
'; } elseif ($this->isOld()) { return '
' . $html . '
'; } else { return $html; } } // Display an icon for this fact. // Icons are held in a theme subfolder. Not all themes provide icons. public function Icon() { $icon = 'images/facts/' . $this->getTag() . '.png'; $dir = substr(WT_CSS_URL, strlen(WT_STATIC_URL)); if (file_exists($dir . $icon)) { return ''; } elseif (file_exists($dir . 'images/facts/NULL.png')) { // Spacer image - for alignment - until we move to a sprite. return ''; } else { return ''; } } // Static Helper functions to sort events static function CompareDate($a, $b) { if ($a->getDate()->isOK() && $b->getDate()->isOK()) { // If both events have dates, compare by date $ret=WT_Date::Compare($a->getDate(), $b->getDate()); if ($ret==0) { // If dates are the same, compare by fact type $ret=self::CompareType($a, $b); // If the fact type is also the same, retain the initial order if ($ret==0) { $ret=$a->sortOrder - $b->sortOrder; } } return $ret; } else { // One or both events have no date - retain the initial orde return $a->sortOrder - $b->sortOrder; } } // Static method to Compare two events by their type static function CompareType($a, $b) { global $factsort; if (empty($factsort)) $factsort=array_flip(array( 'OBJE', 'NOTE', 'SOUR', // On the individual tabs, show 1 OBJE before 1 XXXX/2 OBJE '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_', // other events of close relatives 'CENS', 'OCCU', 'RESI', 'PROP', 'CHRA', 'RETI', 'FACT', 'EVEN', '_NMR', '_NMAR', 'NMR', 'NCHI', 'WILL', '_HOL', '_????_', 'DEAT', '_FNRL', 'BURI', 'CREM', '_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', 'AFN', 'REFN', '_PRMN', 'REF', 'RIN', '_UID', '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; } // Allow native PHP functions such as array_unique() to work with objects public function __toString() { return $this->fact_id . '@' . $this->parent->getXref(); } }