. */ namespace Fisharebest\Webtrees; /** * Defined in session.php * * @global Tree $WT_TREE */ global $WT_TREE; use Fisharebest\Webtrees\Controller\PageController; use Fisharebest\Webtrees\Date\FrenchDate; use Fisharebest\Webtrees\Date\GregorianDate; use Fisharebest\Webtrees\Date\HijriDate; use Fisharebest\Webtrees\Date\JalaliDate; use Fisharebest\Webtrees\Date\JewishDate; use Fisharebest\Webtrees\Date\JulianDate; use Fisharebest\Webtrees\Functions\FunctionsDb; use Fisharebest\Webtrees\Functions\FunctionsPrint; define('WT_SCRIPT_NAME', 'calendar.php'); require './includes/session.php'; $CALENDAR_FORMAT = $WT_TREE->getPreference('CALENDAR_FORMAT'); $cal = Filter::get('cal', '@#D[A-Z ]+@'); $day = Filter::get('day', '\d\d?'); $month = Filter::get('month', '[A-Z]{3,5}'); $year = Filter::get('year', '\d{1,4}(?: B\.C\.)?|\d\d\d\d\/\d\d|\d+(-\d+|[?]+)?'); $view = Filter::get('view', 'day|month|year', 'day'); $filterev = Filter::get('filterev', '[_A-Z-]+', 'BIRT-MARR-DEAT'); $filterof = Filter::get('filterof', 'all|living|recent', 'all'); $filtersx = Filter::get('filtersx', '[MF]', ''); if ($cal . $day . $month . $year === '') { // No date specified? Use the most likely calendar $cal = I18N::defaultCalendar()->gedcomCalendarEscape(); } // Create a CalendarDate from the parameters // We cannot display new-style/old-style years, so convert to new style if (preg_match('/^(\d\d)\d\d\/(\d\d)$/', $year, $match)) { $year = $match[1] . $match[2]; } // advanced-year "year range" if (preg_match('/^(\d+)-(\d+)$/', $year, $match)) { if (strlen($match[1]) > strlen($match[2])) { $match[2] = substr($match[1], 0, strlen($match[1]) - strlen($match[2])) . $match[2]; } $ged_date = new Date("FROM {$cal} {$match[1]} TO {$cal} {$match[2]}"); $view = 'year'; } else { // advanced-year "decade/century wildcard" if (preg_match('/^(\d+)(\?+)$/', $year, $match)) { $y1 = $match[1] . str_replace('?', '0', $match[2]); $y2 = $match[1] . str_replace('?', '9', $match[2]); $ged_date = new Date("FROM {$cal} {$y1} TO {$cal} {$y2}"); $view = 'year'; } else { if ($year < 0) { $year = (-$year) . ' B.C.'; } // need BC to parse date $ged_date = new Date("{$cal} {$day} {$month} {$year}"); $year = $ged_date->minimumDate()->y; // need negative year for year entry field. } } $cal_date = $ged_date->minimumDate(); // Fill in any missing bits with todays date $today = $cal_date->today(); if ($cal_date->d === 0) { $cal_date->d = $today->d; } if ($cal_date->m === 0) { $cal_date->m = $today->m; } if ($cal_date->y === 0) { $cal_date->y = $today->y; } $cal_date->setJdFromYmd(); if ($year === 0) { $year = $cal_date->y; } // Extract values from date $days_in_month = $cal_date->daysInMonth(); $days_in_week = $cal_date->daysInWeek(); $cal_month = $cal_date->format('%O'); $today_month = $today->format('%O'); // Invalid dates? Go to monthly view, where they'll be found. if ($cal_date->d > $days_in_month && $view === 'day') { $view = 'month'; } // All further uses of $cal are to generate URLs $cal = rawurlencode($cal); $controller = new PageController; $controller->setPageTitle(I18N::translate('Anniversary calendar')); switch ($view) { case 'day': $controller->setPageTitle(I18N::translate('On this day…') . ' ' . $ged_date->display(false)); break; case 'month': $controller->setPageTitle(I18N::translate('In this month…') . ' ' . $ged_date->display(false, '%F %Y')); break; case 'year': $controller->setPageTitle(I18N::translate('In this year…') . ' ' . $ged_date->display(false, '%Y')); break; } $controller->pageHeader(); ?>

getPageTitle() ?>

format("%@ {$d} %O %E")); $d_fmt = $tmp->minimumDate()->format('%j'); if ($d === $cal_date->d) { echo '', $d_fmt, ''; } else { echo '', $d_fmt, ''; } echo ' | '; } ?> format('%@ %A %O %E')); echo $tmp->display() ?>
monthsInYear(); $n <= $months_in_year; ++$n) { $month_name = $cal_date->monthNameNominativeCase($n, $cal_date->isLeapYear()); $m = array_search($n, $cal_date::$MONTH_ABBREV); if ($n === 6 && $cal_date instanceof JewishDate && !$cal_date->isLeapYear()) { // No month 6 in Jewish non-leap years. continue; } if ($n === 7 && $cal_date instanceof JewishDate && !$cal_date->isLeapYear()) { // Month 7 is ADR in Jewish non-leap years. $m = 'ADR'; } if ($n === $cal_date->m) { $month_name = '' . $month_name . ''; } echo '', $month_name, ''; echo ' | '; } ?> format('%F %Y') ?>
-1 +1 | format('%Y') ?> getPreference('HIDE_LIVE_PEOPLE') || Auth::check()): ?> | |
| | $cal_name) { $tmp = $cal_date->convertToCalendar($newcal); if ($tmp->inValidRange()) { if ($n++) { echo ' | '; } if (get_class($tmp) === get_class($cal_date)) { echo '', $cal_name, ''; } else { $newcalesc = urlencode($tmp->format('%@')); $tmpmonth = $tmp->format('%O'); echo '', $cal_name, ''; } } } ?>
minJD, $filterev, $WT_TREE), $filterof, $filtersx); break; case 'month': $cal_date->d = 0; $cal_date->setJdFromYmd(); // Make a separate list for each day. Unspecified/invalid days go in day 0. for ($d = 0; $d <= $days_in_month; ++$d) { $found_facts[$d] = array(); } // Fetch events for each day for ($jd = $cal_date->minJD; $jd <= $cal_date->maxJD; ++$jd) { foreach (apply_filter(FunctionsDb::getAnniversaryEvents($jd, $filterev, $WT_TREE), $filterof, $filtersx) as $fact) { $tmp = $fact->getDate()->minimumDate(); if ($tmp->d >= 1 && $tmp->d <= $tmp->daysInMonth()) { // If the day is valid (for its own calendar), display it in the // anniversary day (for the display calendar). $found_facts[$jd - $cal_date->minJD + 1][] = $fact; } else { // Otherwise, display it in the "Day not set" box. $found_facts[0][] = $fact; } } } break; case 'year': $cal_date->m = 0; $cal_date->setJdFromYmd(); $found_facts = apply_filter(FunctionsDb::getCalendarEvents($ged_date->minimumJulianDay(), $ged_date->maximumJulianDay(), $filterev, $WT_TREE), $filterof, $filtersx); // Eliminate duplicates (e.g. BET JUL 1900 AND SEP 1900 will appear twice in 1900) $found_facts = array_unique($found_facts); break; } // Group the facts by family/individual $indis = array(); $fams = array(); $cal_facts = array(); switch ($view) { case 'year': case 'day': foreach ($found_facts as $fact) { $record = $fact->getParent(); $xref = $record->getXref(); if ($record instanceof Individual) { if (empty($indis[$xref])) { $indis[$xref] = calendar_fact_text($fact, true); } else { $indis[$xref] .= '
' . calendar_fact_text($fact, true); } } elseif ($record instanceof Family) { if (empty($indis[$xref])) { $fams[$xref] = calendar_fact_text($fact, true); } else { $fams[$xref] .= '
' . calendar_fact_text($fact, true); } } } break; case 'month': foreach ($found_facts as $d => $facts) { $cal_facts[$d] = array(); foreach ($facts as $fact) { $xref = $fact->getParent()->getXref(); if (empty($cal_facts[$d][$xref])) { $cal_facts[$d][$xref] = calendar_fact_text($fact, false); } else { $cal_facts[$d][$xref] .= '
' . calendar_fact_text($fact, false); } } } break; } switch ($view) { case 'year': case 'day': $males = 0; $females = 0; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo '
', I18N::translate('Individuals'), '', I18N::translate('Families'), '
'; $content = calendar_list_text($indis, '
  • ', '
  • ', true); if ($content) { echo '
      ', $content, '
    '; } echo '
    '; $content = calendar_list_text($fams, '
  • ', '
  • ', true); if ($content) { echo '
      ', $content, '
    '; } echo '
    ', I18N::translate('Total individuals: %s', count($indis)); echo '
    '; echo ' ', $males, ' '; echo ' ', $females, ' '; if (count($indis) !== $males + $females) { echo ' ', count($indis) - $males - $females; } echo '
    ', I18N::translate('Total families: %s', count($fams)), '
    '; break; case 'month': // We use JD%7 = 0/Mon…6/Sun. Standard definitions use 0/Sun…6/Sat. $week_start = (I18N::firstDay() + 6) % 7; $weekend_start = (I18N::weekendStart() + 6) % 7; $weekend_end = (I18N::weekendEnd() + 6) % 7; // The french calendar has a 10-day week, which starts on primidi if ($days_in_week === 10) { $week_start = 0; $weekend_start = -1; $weekend_end = -1; } echo ''; for ($week_day = 0; $week_day < $days_in_week; ++$week_day) { $day_name = $cal_date->dayNames(($week_day + $week_start) % $days_in_week); if ($week_day == $weekend_start || $week_day == $weekend_end) { echo ''; } else { echo ''; } } echo ''; echo ''; echo ''; // Print days 1 to n of the month, but extend to cover "empty" days before/after the month to make whole weeks. // e.g. instead of 1 -> 30 (=30 days), we might have -1 -> 33 (=35 days) $start_d = 1 - ($cal_date->minJD - $week_start) % $days_in_week; $end_d = $days_in_month + ($days_in_week - ($cal_date->maxJD - $week_start + 1) % $days_in_week) % $days_in_week; // Make sure that there is an empty box for any leap/missing days if ($start_d === 1 && $end_d === $days_in_month && count($found_facts[0]) > 0) { $end_d += $days_in_week; } for ($d = $start_d; $d <= $end_d; ++$d) { if (($d + $cal_date->minJD - $week_start) % $days_in_week === 1) { echo ''; } echo ''; if (($d + $cal_date->minJD - $week_start) % $days_in_week === 0) { echo ''; } } echo ''; echo '
    ', $day_name, '', $day_name, '
    '; if ($d < 1 || $d > $days_in_month) { if (count($cal_facts[0]) > 0) { echo '', I18N::translate('Day not set'), '
    '; echo '
    '; echo calendar_list_text($cal_facts[0], '', '', false); echo '
    '; $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 '', $d_fmt, ''; } else { echo '', $d_fmt, ''; } // 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': $alt_date = new JewishDate($cal_date->minJD + $d - 1); break; case 'julian': $alt_date = new JulianDate($cal_date->minJD + $d - 1); break; case 'hijri': $alt_date = new HijriDate($cal_date->minJD + $d - 1); break; case 'jalali': $alt_date = new JalaliDate($cal_date->minJD + $d - 1); break; default: break 2; } if (get_class($alt_date) !== get_class($cal_date)) { echo '' . $alt_date->format("%j %M") . ''; // Just show the first conversion break; } } echo '
    '; echo calendar_list_text($cal_facts[$d], '', '', false); echo '
    '; } echo '
    '; break; } echo '
    '; //close "calendar-page" /** * Filter a list of anniversaries * * @param Fact[] $facts * @param string $filterof * @param string $filtersx * * @return array */ function apply_filter($facts, $filterof, $filtersx) { $filtered = array(); $hundred_years = WT_CLIENT_JD - 36525; foreach ($facts as $fact) { $record = $fact->getParent(); if ($filtersx) { // Filter on sex if ($record instanceof Individual && $filtersx !== $record->getSex()) { continue; } // Can't display families if the sex filter is on. if ($record instanceof Family) { continue; } } // Filter living individuals if ($filterof === 'living') { if ($record instanceof Individual && $record->isDead()) { continue; } if ($record instanceof Family) { $husb = $record->getHusband(); $wife = $record->getWife(); if ($husb && $husb->isDead() || $wife && $wife->isDead()) { continue; } } } // Filter on recent events if ($filterof === 'recent' && $fact->getDate()->maximumJulianDay() < $hundred_years) { continue; } $filtered[] = $fact; } return $filtered; } /** * Format an anniversary display. * * @param Fact $fact * @param bool $show_places * * @return string */ function calendar_fact_text(Fact $fact, $show_places) { $text = $fact->getLabel() . ' — ' . $fact->getDate()->display(true, null, false); if ($fact->anniv) { $text .= ' (' . I18N::translate('%s year anniversary', $fact->anniv) . ')'; } if ($show_places && $fact->getAttribute('PLAC')) { $text .= ' — ' . $fact->getAttribute('PLAC'); } return $text; } /** * Format a list of facts for display * * @param Fact[] $list * @param string $tag1 * @param string $tag2 * @param bool $show_sex_symbols * * @return string */ function calendar_list_text($list, $tag1, $tag2, $show_sex_symbols) { global $males, $females, $WT_TREE; $html = ''; foreach ($list as $id => $facts) { $tmp = GedcomRecord::getInstance($id, $WT_TREE); $html .= $tag1 . '' . $tmp->getFullName() . ' '; if ($show_sex_symbols && $tmp instanceof Individual) { switch ($tmp->getSex()) { case 'M': $html .= ''; ++$males; break; case 'F': $html .= ''; ++$females; break; default: $html .= ''; break; } } $html .= '
    ' . $facts . '
    ' . $tag2; } return $html; }