husb=Person::getInstance($data['f_husb']);
}
if ($data['f_wife']) {
$this->wife=Person::getInstance($data['f_wife']);
}
if (preg_match_all('/\n1 CHIL @('.WT_REGEX_XREF.')@/', $data['gedrec'], $matches)) {
$this->childrenIds=$matches[1];
}
$this->numChildren=$data['f_numchil'];
// Check for divorce, etc. *before* we privatize the data so
// we can correctly label spouses/ex-spouses/partners
$this->_isDivorced=(bool)preg_match('/\n1 ('.WT_EVENTS_DIV.')( Y|\n)/', $data['gedrec']);
$this->_isNotMarried=(bool)preg_match('/\n1 _NMR( Y|\n)/', $data['gedrec']);
} else {
// Construct from raw GEDCOM data
if (preg_match('/^1 HUSB @(.+)@/m', $data, $match)) {
$this->husb=Person::getInstance($match[1]);
}
if (preg_match('/^1 WIFE @(.+)@/m', $data, $match)) {
$this->wife=Person::getInstance($match[1]);
}
if (preg_match_all('/^1 CHIL @(.+)@/m', $data, $match)) {
$this->childrenIds=$match[1];
}
if (preg_match('/^1 NCHI (\d+)/m', $data, $match)) {
$this->numChildren=$match[1];
} else {
$this->numChildren=count($this->childrenIds);
}
// Check for divorce, etc. *before* we privatize the data so
// we can correctly label spouses/ex-spouses/partners
$this->_isDivorced=(bool)preg_match('/\n1 ('.WT_EVENTS_DIV.')( Y|\n)/', $data);
$this->_isNotMarried=(bool)preg_match('/\n1 _NMR( Y|\n)/', $data);
}
// Make sure husb/wife are the right way round.
if ($this->husb && $this->husb->getSex()=='F' || $this->wife && $this->wife->getSex()=='M') {
list($this->husb, $this->wife)=array($this->wife, $this->husb);
}
parent::__construct($data);
}
/**
* get the husbands ID
* @return string
*/
function getHusbId() {
if (!is_null($this->husb)) return $this->husb->getXref();
else return '';
}
/**
* get the wife ID
* @return string
*/
function getWifeId() {
if (!is_null($this->wife)) return $this->wife->getXref();
else return '';
}
/**
* get the husband's person object
* @return Person
*/
function &getHusband() {
return $this->husb;
}
/**
* get the wife's person object
* @return Person
*/
function &getWife() {
return $this->wife;
}
/**
* return the spouse of the given person
* @param Person $person
* @return Person
*/
function &getSpouse(&$person) {
if (is_null($this->wife) or is_null($this->husb)) return null;
if ($this->wife->equals($person)) return $this->husb;
if ($this->husb->equals($person)) return $this->wife;
return null;
}
/**
* return the spouse id of the given person id
* @param string $pid
* @return string
*/
function getSpouseId($pid) {
if (is_null($this->wife) or is_null($this->husb)) return null;
if ($this->wife->getXref()==$pid) return $this->husb->getXref();
if ($this->husb->getXref()==$pid) return $this->wife->getXref();
return null;
}
/**
* get the children
* @return array array of children Persons
*/
function getChildren() {
if (!$this->children_loaded) $this->loadChildren();
return $this->children;
}
/**
* get the children ids
* @return array array of children ids
*/
function getChildrenIds() {
if (!$this->children_loaded) $this->loadChildren();
return $this->childrenIds;
}
// Static helper function to sort an array of families by marriage date
static function CompareMarrDate($x, $y) {
return GedcomDate::Compare($x->getMarriageDate(), $y->getMarriageDate());
}
/**
* Load the children from the database
* We used to load the children when the family was created, but that has performance issues
* because we often don't need all the children
* now, children are only loaded as needed
*/
function loadChildren() {
if ($this->children_loaded) return;
$this->childrenIds = array();
$this->numChildren = preg_match_all('/1\s*CHIL\s*@(.*)@/', $this->gedrec, $smatch, PREG_SET_ORDER);
for ($i=0; $i<$this->numChildren; $i++) {
//-- get the childs ids
$chil = trim($smatch[$i][1]);
$this->childrenIds[] = $chil;
}
foreach ($this->childrenIds as $t=>$chil) {
$child=Person::getInstance($chil);
if (!is_null($child)) $this->children[] = $child;
}
$this->children_loaded = true;
}
/**
* get the number of children in this family
* @return int the number of children
*/
function getNumberOfChildren() {
if ($this->numChildren!==false) return $this->numChildren;
$this->numChildren = get_gedcom_value('NCHI', 1, $this->gedrec);
if ($this->numChildren!='') return $this->numChildren.'.';
$this->numChildren = preg_match_all('/1\s*CHIL\s*@(.*)@/', $this->gedrec, $smatch);
return $this->numChildren;
}
/**
* get updated Family
* If there is an updated family record in the gedcom file
* return a new family object for it
*/
function getUpdatedFamily() {
if ($this->getChanged()) {
return $this;
}
if (WT_USER_CAN_EDIT && $this->canDisplayDetails()) {
$newrec = find_updated_record($this->xref, $this->ged_id);
if (!is_null($newrec)) {
$newfamily = new Family($newrec);
$newfamily->setChanged(true);
return $newfamily;
}
}
return null;
}
/**
* check if this family has the given person
* as a parent in the family
* @param Person $person
*/
function hasParent(&$person) {
if (is_null($person)) return false;
if ($person->equals($this->husb)) return true;
if ($person->equals($this->wife)) return true;
return false;
}
/**
* check if this family has the given person
* as a child in the family
* @param Person $person
*/
function hasChild(&$person) {
if (is_null($person)) return false;
$this->loadChildren();
foreach ($this->children as $key=>$child) {
if ($person->equals($child)) return true;
}
return false;
}
/**
* parse marriage record
*/
function _parseMarriageRecord() {
$this->marriage = new Event(trim(get_sub_record(1, '1 MARR', $this->gedrec)), -1);
$this->marriage->setParentObject($this);
}
/**
* get the marriage event
*
* @return Event
*/
function getMarriage() {
if (is_null($this->marriage)) $this->_parseMarriageRecord();
return $this->marriage;
}
/**
* get marriage record
* @return string
*/
function getMarriageRecord() {
if (is_null($this->marriage)) $this->_parseMarriageRecord();
return $this->marriage->getGedcomRecord();
}
// Return whether or not this family ended in a divorce or was never married.
// Note that this is calculated prior to privatizing the data, so we can
// always distinguish spouses from ex-spouses. This apparant leaking of
// private data was discussed and agreed on the pgv forum.
function isDivorced() {
return $this->_isDivorced;
}
function isNotMarried() {
return $this->_isNotMarried;
}
/**
* get marriage date
* @return string
*/
function getMarriageDate() {
if (!$this->canDisplayDetails()) {
return new GedcomDate('');
}
if (is_null($this->marriage)) {
$this->_parseMarriageRecord();
}
return $this->marriage->getDate();
}
/**
* get the marriage year
* @return string
*/
function getMarriageYear($est = true, $cal = '') {
// TODO - change the design to use julian days, not gregorian years.
$mdate = $this->getMarriageDate();
$mdate = $mdate->MinDate();
if ($cal) $mdate = $mdate->convert_to_cal($cal);
return $mdate->y;
}
/**
* get the marriage month
* @return string
*/
function getMarriageMonth($est = true, $cal = '') {
// TODO - change the design to use julian days, not gregorian years.
$mdate = $this->getMarriageDate();
$mdate=$mdate->MinDate();
if ($cal) $mdate = $mdate->convert_to_cal($cal);
return $mdate->m;
}
/**
* get the type for this marriage
* @return string
*/
function getMarriageType() {
if (is_null($this->marriage)) $this->_parseMarriageRecord();
return $this->marriage->getType();
}
/**
* get the marriage place
* @return string
*/
function getMarriagePlace() {
$marriage = $this->getMarriage();
return $marriage->getPlace();
}
// Get all the dates/places for marriages - for the FAM lists
function getAllMarriageDates() {
if ($this->canDisplayDetails()) {
foreach (explode('|', WT_EVENTS_MARR) as $event) {
if ($array=$this->getAllEventDates($event)) {
return $array;
}
}
}
return array();
}
function getAllMarriagePlaces() {
if ($this->canDisplayDetails()) {
foreach (explode('|', WT_EVENTS_MARR) as $event) {
if ($array=$this->getAllEventPlaces($event)) {
return $array;
}
}
}
return array();
}
// Generate a URL to this record, suitable for use in HTML
public function getHtmlUrl() {
return parent::_getLinkUrl('family.php?famid=', '&');
}
// Generate a URL to this record, suitable for use in javascript, HTTP headers, etc.
public function getRawUrl() {
return parent::_getLinkUrl('family.php?famid=', '&');
}
// Get an array of structures containing all the names in the record
public function getAllNames() {
if (is_null($this->_getAllNames)) {
$husb=$this->husb ? $this->husb : new Person('1 SEX M');
$wife=$this->wife ? $this->wife : new Person('1 SEX F');
// Check the script used by each name, so we can match cyrillic with cyrillic, greek with greek, etc.
$husb_names=$husb->getAllNames();
foreach ($husb_names as $n=>$husb_name) {
$husb_names[$n]['script']=utf8_script($husb_name['surn']);
}
$wife_names=$wife->getAllNames();
foreach ($wife_names as $n=>$wife_name) {
$wife_names[$n]['script']=utf8_script($wife_name['surn']);
}
// Add the matched names first
foreach ($husb_names as $husb_name) {
foreach ($wife_names as $wife_name) {
if ($husb_name['type']!='_MARNM' && $wife_name['type']!='_MARNM' && $husb_name['script']==$wife_name['script']) {
$this->_getAllNames[]=array(
'type'=>$husb_name['type'],
'full'=>$husb_name['full'].' + '.$wife_name['full'],
'list'=>$husb_name['list'].$husb->getSexImage().'
'.$wife_name['list'].$wife->getSexImage(),
'sort'=>$husb_name['sort'].' + '.$wife_name['sort'],
);
}
}
}
// Add the unmatched names second (there may be no matched names)
foreach ($husb_names as $husb_name) {
foreach ($wife_names as $wife_name) {
if ($husb_name['type']!='_MARNM' && $wife_name['type']!='_MARNM' && $husb_name['script']!=$wife_name['script']) {
$this->_getAllNames[]=array(
'type'=>$husb_name['type'],
'full'=>$husb_name['full'].' + '.$wife_name['full'],
'list'=>$husb_name['list'].$husb->getSexImage().'
'.$wife_name['list'].$wife->getSexImage(),
'sort'=>$husb_name['sort'].' + '.$wife_name['sort'],
);
}
}
}
}
return $this->_getAllNames;
}
// Extra info to display when displaying this record in a list of
// selection items or favorites.
function format_list_details() {
return
$this->format_first_major_fact(WT_EVENTS_MARR, 1).
$this->format_first_major_fact(WT_EVENTS_DIV, 1);
}
}