function print_simple_footer() { global $pgv_lang; global $start_time, $buildindex; global $VERSION, $SHOW_STATS; global $SCRIPT_NAME, $QUERY_STRING; global $PGV_IMAGE_DIR, $PGV_IMAGES; if (empty($SCRIPT_NAME)) { $SCRIPT_NAME = $_SERVER["SCRIPT_NAME"]; $QUERY_STRING = $_SERVER["QUERY_STRING"]; } print "\n\t<br /><br /><div align=\"center\" style=\"width: 99%;\">"; print_contact_links(); print "\n\t<a href=\"http://www.phpgedview.net\" target=\"_blank\"><img src=\"" . $PGV_IMAGE_DIR . "/" . $PGV_IMAGES["gedview"]["other"] . "\" border=\"0\" alt=\"Bitweaver PhpGedView Version {$VERSION}\" title=\"Bitweaver PhpGedView Version {$VERSION}\" /></a><br />"; if ($SHOW_STATS || isset($DEBUG) && $DEBUG == true) { print_execution_stats(); } print "</div>"; print "\n\t</body>\n</html>"; }
/** * Get relationship between two individuals in the gedcom * * function to calculate the relationship between two people it uses hueristics based on the * individuals birthdate to try and calculate the shortest path between the two individuals * it uses a node cache to help speed up calculations when using relationship privacy * this cache is indexed using the string "$pid1-$pid2" * @param string $pid1 the ID of the first person to compute the relationship from * @param string $pid2 the ID of the second person to compute the relatiohip to * @param bool $followspouse whether to add spouses to the path * @param int $maxlenght the maximim length of path * @param bool $ignore_cache enable or disable the relationship cache * @param int $path_to_find which path in the relationship to find, 0 is the shortest path, 1 is the next shortest path, etc */ function get_relationship($pid1, $pid2, $followspouse = true, $maxlength = 0, $ignore_cache = false, $path_to_find = 0) { global $TIME_LIMIT, $start_time, $pgv_lang, $NODE_CACHE, $NODE_CACHE_LENGTH, $USE_RELATIONSHIP_PRIVACY, $pgv_changes, $GEDCOM; $pid1 = strtoupper($pid1); $pid2 = strtoupper($pid2); if (isset($pgv_changes[$pid2 . "_" . $GEDCOM]) && PGV_USER_CAN_EDIT) { $indirec = find_updated_record($pid2); } else { $indirec = find_person_record($pid2); } //-- check the cache if ($USE_RELATIONSHIP_PRIVACY && !$ignore_cache) { if (isset($NODE_CACHE["{$pid1}-{$pid2}"])) { if ($NODE_CACHE["{$pid1}-{$pid2}"] == "NOT FOUND") { return false; } if ($maxlength == 0 || count($NODE_CACHE["{$pid1}-{$pid2}"]["path"]) - 1 <= $maxlength) { return $NODE_CACHE["{$pid1}-{$pid2}"]; } else { return false; } } //-- check the cache for person 2's children $famids = array(); $ct = preg_match_all("/1\\sFAMS\\s@(.*)@/", $indirec, $match, PREG_SET_ORDER); for ($i = 0; $i < $ct; $i++) { $famids[$i] = $match[$i][1]; } foreach ($famids as $indexval => $fam) { if (isset($pgv_changes[$fam . "_" . $GEDCOM]) && PGV_USER_CAN_EDIT) { $famrec = find_updated_record($fam); } else { $famrec = find_family_record($fam); } $ct = preg_match_all("/1 CHIL @(.*)@/", $famrec, $match, PREG_SET_ORDER); for ($i = 0; $i < $ct; $i++) { $child = $match[$i][1]; if (!empty($child)) { if (isset($NODE_CACHE["{$pid1}-{$child}"])) { if ($maxlength == 0 || count($NODE_CACHE["{$pid1}-{$child}"]["path"]) + 1 <= $maxlength) { $node1 = $NODE_CACHE["{$pid1}-{$child}"]; if ($node1 != "NOT FOUND") { $node1["path"][] = $pid2; $node1["pid"] = $pid2; $ct = preg_match("/1 SEX F/", $indirec, $match); if ($ct > 0) { $node1["relations"][] = "mother"; } else { $node1["relations"][] = "father"; } } $NODE_CACHE["{$pid1}-{$pid2}"] = $node1; if ($node1 == "NOT FOUND") { return false; } return $node1; } else { return false; } } } } } if (!empty($NODE_CACHE_LENGTH) && $maxlength > 0) { if ($NODE_CACHE_LENGTH >= $maxlength) { return false; } } } //-- end cache checking //-- get the birth year of p2 for calculating heuristics $birthrec = get_sub_record(1, "1 BIRT", $indirec); $byear2 = -1; if ($birthrec !== false) { $dct = preg_match("/2 DATE .*(\\d\\d\\d\\d)/", $birthrec, $match); if ($dct > 0) { $byear2 = $match[1]; } } if ($byear2 == -1) { $numfams = preg_match_all("/1\\s*FAMS\\s*@(.*)@/", $indirec, $fmatch, PREG_SET_ORDER); for ($j = 0; $j < $numfams; $j++) { // Get the family record if (isset($pgv_changes[$fmatch[$j][1] . "_" . $GEDCOM]) && PGV_USER_CAN_EDIT) { $famrec = find_updated_record($fmatch[$j][1]); } else { $famrec = find_family_record($fmatch[$j][1]); } // Get the set of children $ct = preg_match_all("/1 CHIL @(.*)@/", $famrec, $cmatch, PREG_SET_ORDER); for ($i = 0; $i < $ct; $i++) { // Get each child's record if (isset($pgv_changes[$cmatch[$i][1] . "_" . $GEDCOM]) && PGV_USER_CAN_EDIT) { $childrec = find_updated_record($cmatch[$i][1]); } else { $childrec = find_person_record($cmatch[$i][1]); } $birthrec = get_sub_record(1, "1 BIRT", $childrec); if ($birthrec !== false) { $dct = preg_match("/2 DATE .*(\\d\\d\\d\\d)/", $birthrec, $bmatch); if ($dct > 0) { $byear2 = $bmatch[1] - 25; } if ($byear2 > 2100) { $byear2 -= 3760; } // Crude conversion from jewish to gregorian } } } } //-- end of approximating birth year //-- current path nodes $p1nodes = array(); //-- ids visited $visited = array(); //-- set up first node for person1 $node1 = array(); $node1["path"] = array(); $node1["path"][] = $pid1; $node1["length"] = 0; $node1["pid"] = $pid1; $node1["relations"] = array(); $node1["relations"][] = "self"; $p1nodes[] = $node1; $visited[$pid1] = true; $found = false; $count = 0; while (!$found) { //-- the following 2 lines ensure that the user can abort a long relationship calculation //-- refer to http://www.php.net/manual/en/features.connection-handling.php for more //-- information about why these lines are included if (headers_sent()) { print " "; if ($count % 100 == 0) { flush(); } } $count++; $end_time = microtime(true); $exectime = $end_time - $start_time; if ($TIME_LIMIT > 1 && $exectime > $TIME_LIMIT - 1) { print "<span class=\"error\">" . $pgv_lang["timeout_error"] . "</span>\n"; return false; } if (count($p1nodes) == 0) { if ($maxlength != 0) { if (!isset($NODE_CACHE_LENGTH)) { $NODE_CACHE_LENGTH = $maxlength; } else { if ($NODE_CACHE_LENGTH < $maxlength) { $NODE_CACHE_LENGTH = $maxlength; } } } if (headers_sent()) { print "\n<!-- Relationship {$pid1}-{$pid2} NOT FOUND | Visited " . count($visited) . " nodes | Required {$count} iterations.<br />\n"; print_execution_stats(); print "-->\n"; } $NODE_CACHE["{$pid1}-{$pid2}"] = "NOT FOUND"; return false; } //-- search the node list for the shortest path length $shortest = -1; foreach ($p1nodes as $index => $node) { if ($shortest == -1) { $shortest = $index; } else { $node1 = $p1nodes[$shortest]; if ($node1["length"] > $node["length"]) { $shortest = $index; } } } if ($shortest == -1) { return false; } $node = $p1nodes[$shortest]; if ($maxlength == 0 || count($node["path"]) <= $maxlength) { if ($node["pid"] == $pid2) { } else { //-- hueristic values $fatherh = 1; $motherh = 1; $siblingh = 2; $spouseh = 2; $childh = 3; //-- generate heuristic values based of the birthdates of the current node and p2 if (isset($pgv_changes[$node["pid"] . "_" . $GEDCOM]) && PGV_USER_CAN_EDIT) { $indirec = find_updated_record($node["pid"]); } else { $indirec = find_person_record($node["pid"]); } $byear1 = -1; $birthrec = get_sub_record(1, "1 BIRT", $indirec); if ($birthrec !== false) { $dct = preg_match("/2 DATE .*(\\d\\d\\d\\d)/", $birthrec, $match); if ($dct > 0) { $byear1 = $match[1]; } if ($byear1 > 2100) { $byear1 -= 3760; } // Crude conversion from jewish to gregorian } if ($byear1 != -1 && $byear2 != -1) { $yeardiff = $byear1 - $byear2; if ($yeardiff < -140) { $fatherh = 20; $motherh = 20; $siblingh = 15; $spouseh = 15; $childh = 1; } else { if ($yeardiff < -100) { $fatherh = 15; $motherh = 15; $siblingh = 10; $spouseh = 10; $childh = 1; } else { if ($yeardiff < -60) { $fatherh = 10; $motherh = 10; $siblingh = 5; $spouseh = 5; $childh = 1; } else { if ($yeardiff < -20) { $fatherh = 5; $motherh = 5; $siblingh = 3; $spouseh = 3; $childh = 1; } else { if ($yeardiff < 20) { $fatherh = 3; $motherh = 3; $siblingh = 1; $spouseh = 1; $childh = 5; } else { if ($yeardiff < 60) { $fatherh = 1; $motherh = 1; $siblingh = 5; $spouseh = 2; $childh = 10; } else { if ($yeardiff < 100) { $fatherh = 1; $motherh = 1; $siblingh = 10; $spouseh = 3; $childh = 15; } else { $fatherh = 1; $motherh = 1; $siblingh = 15; $spouseh = 4; $childh = 20; } } } } } } } } //-- check all parents and siblings of this node $famids = array(); $ct = preg_match_all("/1\\sFAMC\\s@(.*)@/", $indirec, $match, PREG_SET_ORDER); for ($i = 0; $i < $ct; $i++) { if (!isset($visited[$match[$i][1]])) { $famids[$i] = $match[$i][1]; } } foreach ($famids as $indexval => $fam) { $visited[$fam] = true; if (isset($pgv_changes[$fam . "_" . $GEDCOM]) && PGV_USER_CAN_EDIT) { $famrec = find_updated_record($fam); } else { $famrec = find_family_record($fam); } $parents = find_parents_in_record($famrec); if (!empty($parents["HUSB"]) && !isset($visited[$parents["HUSB"]])) { $node1 = $node; $node1["length"] += $fatherh; $node1["path"][] = $parents["HUSB"]; $node1["pid"] = $parents["HUSB"]; $node1["relations"][] = "father"; $p1nodes[] = $node1; if ($node1["pid"] == $pid2) { if ($path_to_find > 0) { $path_to_find--; } else { $found = true; $resnode = $node1; } } else { $visited[$parents["HUSB"]] = true; } if ($USE_RELATIONSHIP_PRIVACY) { $NODE_CACHE["{$pid1}-" . $node1["pid"]] = $node1; } } if (!empty($parents["WIFE"]) && !isset($visited[$parents["WIFE"]])) { $node1 = $node; $node1["length"] += $motherh; $node1["path"][] = $parents["WIFE"]; $node1["pid"] = $parents["WIFE"]; $node1["relations"][] = "mother"; $p1nodes[] = $node1; if ($node1["pid"] == $pid2) { if ($path_to_find > 0) { $path_to_find--; } else { $found = true; $resnode = $node1; } } else { $visited[$parents["WIFE"]] = true; } if ($USE_RELATIONSHIP_PRIVACY) { $NODE_CACHE["{$pid1}-" . $node1["pid"]] = $node1; } } $ct = preg_match_all("/1 CHIL @(.*)@/", $famrec, $match, PREG_SET_ORDER); for ($i = 0; $i < $ct; $i++) { $child = $match[$i][1]; if (!empty($child) && !isset($visited[$child])) { $node1 = $node; $node1["length"] += $siblingh; $node1["path"][] = $child; $node1["pid"] = $child; $node1["relations"][] = "sibling"; $p1nodes[] = $node1; if ($node1["pid"] == $pid2) { if ($path_to_find > 0) { $path_to_find--; } else { $found = true; $resnode = $node1; } } else { $visited[$child] = true; } if ($USE_RELATIONSHIP_PRIVACY) { $NODE_CACHE["{$pid1}-" . $node1["pid"]] = $node1; } } } } //-- check all spouses and children of this node $famids = array(); $ct = preg_match_all("/1\\sFAMS\\s@(.*)@/", $indirec, $match, PREG_SET_ORDER); for ($i = 0; $i < $ct; $i++) { $famids[$i] = $match[$i][1]; } foreach ($famids as $indexval => $fam) { $visited[$fam] = true; if (isset($pgv_changes[$fam . "_" . $GEDCOM]) && PGV_USER_CAN_EDIT) { $famrec = find_updated_record($fam); } else { $famrec = find_family_record($fam); } if ($followspouse) { $parents = find_parents_in_record($famrec); if (!empty($parents["HUSB"]) && (!in_arrayr($parents["HUSB"], $node1) || !isset($visited[$parents["HUSB"]]))) { $node1 = $node; $node1["length"] += $spouseh; $node1["path"][] = $parents["HUSB"]; $node1["pid"] = $parents["HUSB"]; $node1["relations"][] = "spouse"; $p1nodes[] = $node1; if ($node1["pid"] == $pid2) { if ($path_to_find > 0) { $path_to_find--; } else { $found = true; $resnode = $node1; } } else { $visited[$parents["HUSB"]] = true; } if ($USE_RELATIONSHIP_PRIVACY) { $NODE_CACHE["{$pid1}-" . $node1["pid"]] = $node1; } } if (!empty($parents["WIFE"]) && (!in_arrayr($parents["WIFE"], $node1) || !isset($visited[$parents["WIFE"]]))) { $node1 = $node; $node1["length"] += $spouseh; $node1["path"][] = $parents["WIFE"]; $node1["pid"] = $parents["WIFE"]; $node1["relations"][] = "spouse"; $p1nodes[] = $node1; if ($node1["pid"] == $pid2) { if ($path_to_find > 0) { $path_to_find--; } else { $found = true; $resnode = $node1; } } else { $visited[$parents["WIFE"]] = true; } if ($USE_RELATIONSHIP_PRIVACY) { $NODE_CACHE["{$pid1}-" . $node1["pid"]] = $node1; } } } $ct = preg_match_all("/1 CHIL @(.*)@/", $famrec, $match, PREG_SET_ORDER); for ($i = 0; $i < $ct; $i++) { $child = $match[$i][1]; if (!empty($child) && !isset($visited[$child])) { $node1 = $node; $node1["length"] += $childh; $node1["path"][] = $child; $node1["pid"] = $child; $node1["relations"][] = "child"; $p1nodes[] = $node1; if ($node1["pid"] == $pid2) { if ($path_to_find > 0) { $path_to_find--; } else { $found = true; $resnode = $node1; } } else { $visited[$child] = true; } if ($USE_RELATIONSHIP_PRIVACY) { $NODE_CACHE["{$pid1}-" . $node1["pid"]] = $node1; } } } } } } unset($p1nodes[$shortest]); } //-- end while loop if (headers_sent()) { print "\n<!-- Relationship {$pid1}-{$pid2} | Visited " . count($visited) . " nodes | Required {$count} iterations.<br />\n"; print_execution_stats(); print "-->\n"; } return $resnode; }