Example #1
0
 /**
  * Print a new fact box on details pages
  *
  * @param string $id the id of the person, family, source etc the fact will be added to
  * @param array $usedfacts an array of facts already used in this record
  * @param string $type the type of record INDI, FAM, SOUR etc
  */
 public static function printAddNewFact($id, $usedfacts, $type)
 {
     global $WT_TREE;
     // -- Add from clipboard
     if (is_array(Session::get('clipboard'))) {
         $newRow = true;
         foreach (array_reverse(Session::get('clipboard'), true) as $fact_id => $fact) {
             if ($fact["type"] == $type || $fact["type"] == 'all') {
                 if ($newRow) {
                     $newRow = false;
                     echo '<tr><td class="descriptionbox">';
                     echo I18N::translate('Add from clipboard'), '</td>';
                     echo '<td class="optionbox wrap"><form method="get" name="newFromClipboard" action="?" onsubmit="return false;">';
                     echo '<select id="newClipboardFact">';
                 }
                 echo '<option value="', Filter::escapeHtml($fact_id), '">', GedcomTag::getLabel($fact['fact']);
                 // TODO use the event class to store/parse the clipboard events
                 if (preg_match('/^2 DATE (.+)/m', $fact['factrec'], $match)) {
                     $tmp = new Date($match[1]);
                     echo '; ', $tmp->minimumDate()->format('%Y');
                 }
                 if (preg_match('/^2 PLAC ([^,\\n]+)/m', $fact['factrec'], $match)) {
                     echo '; ', $match[1];
                 }
                 echo '</option>';
             }
         }
         if (!$newRow) {
             echo '</select>';
             echo '&nbsp;&nbsp;<input type="button" value="', I18N::translate('Add'), "\" onclick=\"return paste_fact('{$id}', '#newClipboardFact');\"> ";
             echo '</form></td></tr>', "\n";
         }
     }
     // -- Add from pick list
     switch ($type) {
         case "INDI":
             $addfacts = preg_split("/[, ;:]+/", $WT_TREE->getPreference('INDI_FACTS_ADD'), -1, PREG_SPLIT_NO_EMPTY);
             $uniquefacts = preg_split("/[, ;:]+/", $WT_TREE->getPreference('INDI_FACTS_UNIQUE'), -1, PREG_SPLIT_NO_EMPTY);
             $quickfacts = preg_split("/[, ;:]+/", $WT_TREE->getPreference('INDI_FACTS_QUICK'), -1, PREG_SPLIT_NO_EMPTY);
             break;
         case "FAM":
             $addfacts = preg_split("/[, ;:]+/", $WT_TREE->getPreference('FAM_FACTS_ADD'), -1, PREG_SPLIT_NO_EMPTY);
             $uniquefacts = preg_split("/[, ;:]+/", $WT_TREE->getPreference('FAM_FACTS_UNIQUE'), -1, PREG_SPLIT_NO_EMPTY);
             $quickfacts = preg_split("/[, ;:]+/", $WT_TREE->getPreference('FAM_FACTS_QUICK'), -1, PREG_SPLIT_NO_EMPTY);
             break;
         case "SOUR":
             $addfacts = preg_split("/[, ;:]+/", $WT_TREE->getPreference('SOUR_FACTS_ADD'), -1, PREG_SPLIT_NO_EMPTY);
             $uniquefacts = preg_split("/[, ;:]+/", $WT_TREE->getPreference('SOUR_FACTS_UNIQUE'), -1, PREG_SPLIT_NO_EMPTY);
             $quickfacts = preg_split("/[, ;:]+/", $WT_TREE->getPreference('SOUR_FACTS_QUICK'), -1, PREG_SPLIT_NO_EMPTY);
             break;
         case "NOTE":
             $addfacts = preg_split("/[, ;:]+/", $WT_TREE->getPreference('NOTE_FACTS_ADD'), -1, PREG_SPLIT_NO_EMPTY);
             $uniquefacts = preg_split("/[, ;:]+/", $WT_TREE->getPreference('NOTE_FACTS_UNIQUE'), -1, PREG_SPLIT_NO_EMPTY);
             $quickfacts = preg_split("/[, ;:]+/", $WT_TREE->getPreference('NOTE_FACTS_QUICK'), -1, PREG_SPLIT_NO_EMPTY);
             break;
         case "REPO":
             $addfacts = preg_split("/[, ;:]+/", $WT_TREE->getPreference('REPO_FACTS_ADD'), -1, PREG_SPLIT_NO_EMPTY);
             $uniquefacts = preg_split("/[, ;:]+/", $WT_TREE->getPreference('REPO_FACTS_UNIQUE'), -1, PREG_SPLIT_NO_EMPTY);
             $quickfacts = preg_split("/[, ;:]+/", $WT_TREE->getPreference('REPO_FACTS_QUICK'), -1, PREG_SPLIT_NO_EMPTY);
             break;
         default:
             return;
     }
     $addfacts = array_merge(self::checkFactUnique($uniquefacts, $usedfacts, $type), $addfacts);
     $quickfacts = array_intersect($quickfacts, $addfacts);
     $translated_addfacts = array();
     foreach ($addfacts as $addfact) {
         $translated_addfacts[$addfact] = GedcomTag::getLabel($addfact);
     }
     uasort($translated_addfacts, function ($x, $y) {
         return I18N::strcasecmp(I18N::translate($x), I18N::translate($y));
     });
     echo '<tr><td class="descriptionbox">';
     echo I18N::translate('Fact or event');
     echo '</td>';
     echo '<td class="optionbox wrap">';
     echo '<form method="get" name="newfactform" action="?" onsubmit="return false;">';
     echo '<select id="newfact" name="newfact">';
     echo '<option value="" disabled selected>' . I18N::translate('&lt;select&gt;') . '</option>';
     foreach ($translated_addfacts as $fact => $fact_name) {
         echo '<option value="', $fact, '">', $fact_name, '</option>';
     }
     if ($type == 'INDI' || $type == 'FAM') {
         echo '<option value="FACT">', I18N::translate('Custom fact'), '</option>';
         echo '<option value="EVEN">', I18N::translate('Custom event'), '</option>';
     }
     echo '</select>';
     echo '<input type="button" value="', I18N::translate('Add'), '" onclick="add_record(\'' . $id . '\', \'newfact\');">';
     echo '<span class="quickfacts">';
     foreach ($quickfacts as $fact) {
         echo '<a href="#" onclick="add_new_record(\'' . $id . '\', \'' . $fact . '\');return false;">', GedcomTag::getLabel($fact), '</a>';
     }
     echo '</span></form>';
     echo '</td></tr>';
 }
Example #2
0
 if (($d + $cal_date->minJD - $week_start) % $days_in_week === 1) {
     echo '<tr>';
 }
 echo '<td class="optionbox wrap">';
 if ($d < 1 || $d > $days_in_month) {
     if (count($cal_facts[0]) > 0) {
         echo '<span class="cal_day">', I18N::translate('Day not set'), '</span><br style="clear: both;">';
         echo '<div class="details1" style="height: 180px; overflow: auto;">';
         echo calendar_list_text($cal_facts[0], '', '', false);
         echo '</div>';
         $cal_facts[0] = array();
     }
 } else {
     // Format the day number using the calendar
     $tmp = new Date($cal_date->format("%@ {$d} %O %E"));
     $d_fmt = $tmp->minimumDate()->format('%j');
     if ($d === $today->d && $cal_date->m === $today->m) {
         echo '<span class="cal_day current_day">', $d_fmt, '</span>';
     } else {
         echo '<span class="cal_day">', $d_fmt, '</span>';
     }
     // Show a converted date
     foreach (explode('_and_', $CALENDAR_FORMAT) as $convcal) {
         switch ($convcal) {
             case 'french':
                 $alt_date = new FrenchDate($cal_date->minJD + $d - 1);
                 break;
             case 'gregorian':
                 $alt_date = new GregorianDate($cal_date->minJD + $d - 1);
                 break;
             case 'jewish':
Example #3
0
use Fisharebest\Webtrees\Controller\SimpleController;
use Fisharebest\Webtrees\Module\CensusAssistantModule;
/** @var SimpleController $controller */
global $controller;
/** @var Tree $WT_TREE */
global $WT_TREE;
$xref = Filter::get('xref', WT_REGEX_XREF);
$census = Filter::get('census');
$head = Individual::getInstance($xref, $WT_TREE);
check_record_access($head);
$controller->restrictAccess(class_exists($census));
/** @var CensusInterface */
$census = new $census();
$controller->restrictAccess($census instanceof CensusInterface);
$date = new Date($census->censusDate());
$year = $date->minimumDate()->format('%Y');
$headImg = '<i class="icon-button_head"></i>';
$controller->setPageTitle(I18N::translate('Create a shared note using the census assistant'))->addInlineJavascript('jQuery("head").append(\'<link rel="stylesheet" href="' . WT_STATIC_URL . WT_MODULES_DIR . 'GEDFact_assistant/census/style.css" type="text/css">\');' . 'jQuery("#tblSample").on("click", ".icon-remove", function() { jQuery(this).closest("tr").remove(); });')->pageHeader();
?>

<h2>
	<?php 
echo $controller->getPageTitle();
?>
</h2>

<form method="post" action="edit_interface.php" onsubmit="updateCensusText();">
	<input type="hidden" name="action" value="addnoteaction_assisted">
	<input id="pid_array" type="hidden" name="pid_array" value="none">
	<input type="hidden" name="NOTE" id="NOTE">
	<?php 
Example #4
0
 /**
  * Startup activity
  */
 public function __construct()
 {
     global $WT_TREE;
     parent::__construct();
     $this->setPageTitle(I18N::translate('Lifespans'));
     $this->facts = explode('|', WT_EVENTS_BIRT . '|' . WT_EVENTS_DEAT . '|' . WT_EVENTS_MARR . '|' . WT_EVENTS_DIV);
     $tmp = explode('\\', get_class(I18N::defaultCalendar()));
     $cal = strtolower(array_pop($tmp));
     $this->defaultCalendar = str_replace('calendar', '', $cal);
     $filterPids = false;
     // Request parameters
     $clear = Filter::getBool('clear');
     $newpid = Filter::get('newpid', WT_REGEX_XREF);
     $addfam = Filter::getBool('addFamily');
     $this->place = Filter::get('place');
     $this->beginYear = Filter::getInteger('beginYear', 0, PHP_INT_MAX, null);
     $this->endYear = Filter::getInteger('endYear', 0, PHP_INT_MAX, null);
     $this->calendar = Filter::get('calendar', null, $this->defaultCalendar);
     $this->strictDate = Filter::getBool('strictDate');
     // Set up base color parameters
     $this->colors['M'] = new ColorGenerator(240, self::SATURATION, self::LIGHTNESS, self::ALPHA, self::RANGE * -1);
     $this->colors['F'] = new ColorGenerator(00, self::SATURATION, self::LIGHTNESS, self::ALPHA, self::RANGE);
     // Build a list of people based on the input parameters
     if ($clear) {
         // Empty list & reset form
         $xrefs = array();
         $this->place = null;
         $this->beginYear = null;
         $this->endYear = null;
         $this->calendar = $this->defaultCalendar;
     } elseif ($this->place) {
         // Get all individual & family records found for a place
         $this->place_obj = new Place($this->place, $WT_TREE);
         $xrefs = Database::prepare("SELECT DISTINCT `i_id` FROM `##placelinks`" . " JOIN `##individuals` ON `pl_gid`=`i_id` AND `pl_file`=`i_file`" . " WHERE `i_file`=:tree_id" . " AND `pl_p_id`=:place_id" . " UNION" . " SELECT DISTINCT `f_id` FROM `##placelinks`" . " JOIN `##families` ON `pl_gid`=`f_id` AND `pl_file`=`f_file`" . " WHERE `f_file`=:tree_id" . " AND `pl_p_id`=:place_id")->execute(array('tree_id' => $WT_TREE->getTreeId(), 'place_id' => $this->place_obj->getPlaceId()))->fetchOneColumn();
     } else {
         // Modify an existing list of records
         $xrefs = Session::get(self::SESSION_DATA, array());
         if ($newpid) {
             $xrefs = array_merge($xrefs, $this->addFamily(Individual::getInstance($newpid, $WT_TREE), $addfam));
             $xrefs = array_unique($xrefs);
         } elseif (!$xrefs) {
             $xrefs = $this->addFamily($this->getSignificantIndividual(), false);
         }
     }
     $tmp = $this->getCalendarDate(unixtojd());
     $this->currentYear = $tmp->today()->y;
     $tmp = strtoupper(strtr($this->calendar, array('jewish' => 'hebrew', 'french' => 'french r')));
     $this->calendarEscape = sprintf('@#D%s@', $tmp);
     if ($xrefs) {
         // ensure date ranges are valid in preparation for filtering list
         if ($this->beginYear || $this->endYear) {
             $filterPids = true;
             if (!$this->beginYear) {
                 $tmp = new Date($this->calendarEscape . ' 1');
                 $this->beginYear = $tmp->minimumDate()->y;
             }
             if (!$this->endYear) {
                 $this->endYear = $this->currentYear;
             }
             $this->startDate = new Date($this->calendarEscape . $this->beginYear);
             $this->endDate = new Date($this->calendarEscape . $this->endYear);
         }
         // Test each xref to see if the search criteria are met
         foreach ($xrefs as $key => $xref) {
             $valid = false;
             $person = Individual::getInstance($xref, $WT_TREE);
             if ($person) {
                 if ($person->canShow()) {
                     foreach ($person->getFacts() as $fact) {
                         if ($this->checkFact($fact)) {
                             $this->people[] = $person;
                             $valid = true;
                             break;
                         }
                     }
                 }
             } else {
                 $family = Family::getInstance($xref, $WT_TREE);
                 if ($family && $family->canShow() && $this->checkFact($family->getMarriage())) {
                     $valid = true;
                     $this->people[] = $family->getHusband();
                     $this->people[] = $family->getWife();
                 }
             }
             if (!$valid) {
                 unset($xrefs[$key]);
                 // no point in storing a xref if we can't use it
             }
         }
         Session::put(self::SESSION_DATA, $xrefs);
     } else {
         Session::forget(self::SESSION_DATA);
     }
     $this->people = array_filter(array_unique($this->people));
     $count = count($this->people);
     if ($count) {
         // Build the subtitle
         if ($this->place && $filterPids) {
             $this->subtitle = I18N::plural('%s individual with events in %s between %s and %s', '%s individuals with events in %s between %s and %s', $count, I18N::number($count), $this->place, $this->startDate->display(false, '%Y'), $this->endDate->display(false, '%Y'));
         } elseif ($this->place) {
             $this->subtitle = I18N::plural('%s individual with events in %s', '%s individuals with events in %s', $count, I18N::number($count), $this->place);
         } elseif ($filterPids) {
             $this->subtitle = I18N::plural('%s individual with events between %s and %s', '%s individuals with events between %s and %s', $count, I18N::number($count), $this->startDate->display(false, '%Y'), $this->endDate->display(false, '%Y'));
         } else {
             $this->subtitle = I18N::plural('%s individual', '%s individuals', $count, I18N::number($count));
         }
         // Sort the array in order of birth year
         usort($this->people, function (Individual $a, Individual $b) {
             return Date::compare($a->getEstimatedBirthDate(), $b->getEstimatedBirthDate());
         });
         //Find the mimimum birth year and maximum death year from the individuals in the array.
         $bdate = $this->getCalendarDate($this->people[0]->getEstimatedBirthDate()->minimumJulianDay());
         $minyear = $bdate->y;
         $that = $this;
         // PHP5.3 cannot access $this inside a closure
         $maxyear = array_reduce($this->people, function ($carry, Individual $item) use($that) {
             $date = $that->getCalendarDate($item->getEstimatedDeathDate()->maximumJulianDay());
             return max($carry, $date->y);
         }, 0);
     } elseif ($filterPids) {
         $minyear = $this->endYear;
         $maxyear = $this->endYear;
     } else {
         $minyear = $this->currentYear;
         $maxyear = $this->currentYear;
     }
     $maxyear = min($maxyear, $this->currentYear);
     // Limit maximum year to current year as we can't forecast the future
     $minyear = min($minyear, $maxyear - $WT_TREE->getPreference('MAX_ALIVE_AGE'));
     // Set default minimum chart length
     $this->timelineMinYear = (int) floor($minyear / 10) * 10;
     // round down to start of the decade
     $this->timelineMaxYear = (int) ceil($maxyear / 10) * 10;
     // round up to start of next decade
 }
Example #5
0
 /**
  * Extract all the dates from the given record and insert them into the database.
  *
  * @param string $xref
  * @param int    $ged_id
  * @param string $gedrec
  */
 public static function updateDates($xref, $ged_id, $gedrec)
 {
     if (strpos($gedrec, '2 DATE ') && preg_match_all("/\n1 (\\w+).*(?:\n[2-9].*)*(?:\n2 DATE (.+))(?:\n[2-9].*)*/", $gedrec, $matches, PREG_SET_ORDER)) {
         foreach ($matches as $match) {
             $fact = $match[1];
             if (($fact == 'FACT' || $fact == 'EVEN') && preg_match("/\n2 TYPE ([A-Z]{3,5})/", $match[0], $tmatch)) {
                 $fact = $tmatch[1];
             }
             $date = new Date($match[2]);
             Database::prepare("INSERT INTO `##dates` (d_day,d_month,d_mon,d_year,d_julianday1,d_julianday2,d_fact,d_gid,d_file,d_type) VALUES (?,?,?,?,?,?,?,?,?,?)")->execute(array($date->minimumDate()->d, $date->minimumDate()->format('%O'), $date->minimumDate()->m, $date->minimumDate()->y, $date->minimumDate()->minJD, $date->minimumDate()->maxJD, $fact, $xref, $ged_id, $date->minimumDate()->format('%@')));
             if ($date->minimumDate() !== $date->maximumDate()) {
                 Database::prepare("INSERT INTO `##dates` (d_day,d_month,d_mon,d_year,d_julianday1,d_julianday2,d_fact,d_gid,d_file,d_type) VALUES (?,?,?,?,?,?,?,?,?,?)")->execute(array($date->maximumDate()->d, $date->maximumDate()->format('%O'), $date->maximumDate()->m, $date->maximumDate()->y, $date->maximumDate()->minJD, $date->maximumDate()->maxJD, $fact, $xref, $ged_id, $date->maximumDate()->format('%@')));
             }
         }
     }
 }
Example #6
0
 /**
  * Calculate the the age of a person, on a date.
  *
  * @param Date $d1
  * @param Date $d2
  * @param int  $format
  *
  * @throws \InvalidArgumentException
  *
  * @return int|string
  */
 public static function getAge(Date $d1, Date $d2 = null, $format = 0)
 {
     if ($d2) {
         if ($d2->maximumJulianDay() >= $d1->minimumJulianDay() && $d2->minimumJulianDay() <= $d1->minimumJulianDay()) {
             // Overlapping dates
             $jd = $d1->minimumJulianDay();
         } else {
             // Non-overlapping dates
             $jd = $d2->minimumJulianDay();
         }
     } else {
         // If second date not specified, use today’s date
         $jd = WT_CLIENT_JD;
     }
     switch ($format) {
         case 0:
             // Years - integer only (for statistics, rather than for display)
             if ($jd && $d1->minimumJulianDay() && $d1->minimumJulianDay() <= $jd) {
                 return $d1->minimumDate()->getAge(false, $jd, false);
             } else {
                 return -1;
             }
         case 1:
             // Days - integer only (for sorting, rather than for display)
             if ($jd && $d1->minimumJulianDay()) {
                 return $jd - $d1->minimumJulianDay();
             } else {
                 return -1;
             }
         case 2:
             // Just years, in local digits, with warning for negative/
             if ($jd && $d1->minimumJulianDay()) {
                 if ($d1->minimumJulianDay() > $jd) {
                     return '<i class="icon-warning"></i>';
                 } else {
                     return I18N::number($d1->minimumDate()->getAge(false, $jd));
                 }
             } else {
                 return '';
             }
         default:
             throw new \InvalidArgumentException('format: ' . $format);
     }
 }
Example #7
0
    /**
     * Genearate a <select> element, with the dates/places of all known censuses
     *
     *
     * @param string $locale - Sort the censuses for this locale
     * @param string $xref   - The individual for whom we are adding a census
     */
    public static function censusDateSelector($locale, $xref)
    {
        global $controller;
        // Show more likely census details at the top of the list.
        switch (WT_LOCALE) {
            case 'cs':
                $census_places = array(new CensusOfCzechRepublic());
                break;
            case 'en-AU':
            case 'en-GB':
                $census_places = array(new CensusOfEngland(), new CensusOfWales(), new CensusOfScotland());
                break;
            case 'en-US':
                $census_places = array(new CensusOfUnitedStates());
                break;
            case 'fr':
            case 'fr-CA':
                $census_places = array(new CensusOfFrance());
                break;
            case 'da':
                $census_places = array(new CensusOfDenmark());
                break;
            default:
                $census_places = array();
                break;
        }
        foreach (Census::allCensusPlaces() as $census_place) {
            if (!in_array($census_place, $census_places)) {
                $census_places[] = $census_place;
            }
        }
        $controller->addInlineJavascript('
				function selectCensus(el) {
					var option = jQuery(":selected", el);
					jQuery("input.DATE", jQuery(el).closest("table")).val(option.val());
					jQuery("input.PLAC", jQuery(el).closest("table")).val(option.data("place"));
					jQuery("input.census-class", jQuery(el).closest("table")).val(option.data("census"));
					if (option.data("place")) {
						jQuery("#assistant-link").show();
					} else {
						jQuery("#assistant-link").hide();
					}
				}
				function set_pid_array(pa) {
					jQuery("#pid_array").val(pa);
				}
				function activateCensusAssistant() {
					if (jQuery("#newshared_note_img").hasClass("icon-plus")) {
						expand_layer("newshared_note");
					}
					var field  = jQuery("#newshared_note input.NOTE")[0];
					var xref   = jQuery("input[name=xref]").val();
					var census = jQuery(".census-assistant-selector :selected").data("census");
					return addnewnote_assisted(field, xref, census);
				}
			');
        $options = '<option value="">' . I18N::translate('Census date') . '</option>';
        foreach ($census_places as $census_place) {
            $options .= '<option value=""></option>';
            foreach ($census_place->allCensusDates() as $census) {
                $date = new Date($census->censusDate());
                $year = $date->minimumDate()->format('%Y');
                $place_hierarchy = explode(', ', $census->censusPlace());
                $options .= '<option value="' . $census->censusDate() . '" data-place="' . $census->censusPlace() . '" data-census="' . get_class($census) . '">' . $place_hierarchy[0] . ' ' . $year . '</option>';
            }
        }
        return '<input type="hidden" id="pid_array" name="pid_array" value="">' . '<select class="census-assistant-selector" onchange="selectCensus(this);">' . $options . '</select>';
    }
Example #8
0
>
		<?php 
echo Filter::getCsrf();
$summary = $person->formatFirstMajorFact(WT_EVENTS_BIRT, 2);
if (!$person->isDead()) {
    // If alive display age
    $bdate = $person->getBirthDate();
    $age = Date::getAgeGedcom($bdate);
    if ($age != "") {
        $summary .= "<span class=\"label\">" . I18N::translate('Age') . ":</span><span class=\"field\"> " . FunctionsDate::getAgeAtEvent($age, true) . "</span>";
    }
}
$summary .= $person->formatFirstMajorFact(WT_EVENTS_DEAT, 2);
global $summary, $censyear, $censdate;
$censdate = new Date('31 MAR 1901');
$censyear = $censdate->minimumDate()->y;
$ctry = 'UK';
// === Set $married to "Not married as we only want the Birth name here" ===
$married = -1;
$nam = $person->getAllNames();
if ($person->getDeathYear() == 0) {
    $DeathYr = '';
} else {
    $DeathYr = $person->getDeathYear();
}
if ($person->getBirthYear() == 0) {
    $BirthYr = '';
} else {
    $BirthYr = $person->getBirthYear();
}
$fulln = rtrim($nam[0]['givn'], '*') . " " . $nam[0]['surname'];
Example #9
0
 /**
  * Get a list of events which occured during a given date range.
  *
  * @param int $jd1 the start range of julian day
  * @param int $jd2 the end range of julian day
  * @param string $facts restrict the search to just these facts or leave blank for all
  * @param Tree $tree the tree to search
  *
  * @return Fact[]
  */
 public static function getCalendarEvents($jd1, $jd2, $facts, Tree $tree)
 {
     // If no facts specified, get all except these
     $skipfacts = "CHAN,BAPL,SLGC,SLGS,ENDL,CENS,RESI,NOTE,ADDR,OBJE,SOUR,PAGE,DATA,TEXT";
     if ($facts != '_TODO') {
         $skipfacts .= ',_TODO';
     }
     $found_facts = array();
     // Events that start or end during the period
     $where = "WHERE (d_julianday1>={$jd1} AND d_julianday1<={$jd2} OR d_julianday2>={$jd1} AND d_julianday2<={$jd2})";
     // Restrict to certain types of fact
     if (empty($facts)) {
         $excl_facts = "'" . preg_replace('/\\W+/', "','", $skipfacts) . "'";
         $where .= " AND d_fact NOT IN ({$excl_facts})";
     } else {
         $incl_facts = "'" . preg_replace('/\\W+/', "','", $facts) . "'";
         $where .= " AND d_fact IN ({$incl_facts})";
     }
     // Only get events from the current gedcom
     $where .= " AND d_file=" . $tree->getTreeId();
     // Now fetch these events
     $ind_sql = "SELECT d_gid AS xref, i_gedcom AS gedcom, d_type, d_day, d_month, d_year, d_fact, d_type FROM `##dates`, `##individuals` {$where} AND d_gid=i_id AND d_file=i_file ORDER BY d_julianday1";
     $fam_sql = "SELECT d_gid AS xref, f_gedcom AS gedcom, d_type, d_day, d_month, d_year, d_fact, d_type FROM `##dates`, `##families`    {$where} AND d_gid=f_id AND d_file=f_file ORDER BY d_julianday1";
     foreach (array('INDI' => $ind_sql, 'FAM' => $fam_sql) as $type => $sql) {
         $rows = Database::prepare($sql)->fetchAll();
         foreach ($rows as $row) {
             if ($type === 'INDI') {
                 $record = Individual::getInstance($row->xref, $tree, $row->gedcom);
             } else {
                 $record = Family::getInstance($row->xref, $tree, $row->gedcom);
             }
             $anniv_date = new Date($row->d_type . ' ' . $row->d_day . ' ' . $row->d_month . ' ' . $row->d_year);
             foreach ($record->getFacts() as $fact) {
                 if (($fact->getDate()->minimumDate() == $anniv_date->minimumDate() || $fact->getDate()->maximumDate() == $anniv_date->minimumDate()) && $fact->getTag() === $row->d_fact) {
                     $fact->anniv = 0;
                     $found_facts[] = $fact;
                 }
             }
         }
     }
     return $found_facts;
 }