setPageTitle(WT_I18N::translate('Anniversary calendar')); $controller->pageHeader(); if (isset($_REQUEST['cal'])) $cal = $_REQUEST['cal']; if (isset($_REQUEST['day'])) $day = $_REQUEST['day']; if (isset($_REQUEST['month'])) $month = $_REQUEST['month']; if (isset($_REQUEST['year'])) $year = $_REQUEST['year']; if (isset($_REQUEST['action'])) $action = $_REQUEST['action']; if (isset($_REQUEST['filterev'])) $filterev = $_REQUEST['filterev']; if (isset($_REQUEST['filterof'])) $filterof = $_REQUEST['filterof']; if (isset($_REQUEST['filtersx'])) $filtersx = $_REQUEST['filtersx']; // Set undefined parameters to defaults if (empty($cal )) $cal =''; if (empty($day )) $day =''; if (empty($month )) $month =''; if (empty($year )) $year =''; if (empty($action )) $action ='today'; if (empty($filterev)) $filterev='bdm'; if (empty($filterof)) $filterof='all'; if (empty($filtersx)) $filtersx=''; if ($cal.$day.$month.$year=='') { // No date specified? Use the most likely calendar switch (WT_LOCALE) { case 'fa': $cal='@#DJALALI@'; break; case 'ar': $cal='@#DHIJRI@'; break; case 'he': $cal='@#DHEBREW@'; break; default: $cal='@#DGREGORIAN@'; break; } } // Create a WT_Date_Calendar from the parameters // advance-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 WT_Date("FROM {$cal} {$match[1]} TO {$cal} {$match[2]}"); $action='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 WT_Date("FROM {$cal} {$y1} TO {$cal} {$y2}"); $action='year'; } else { if ($year<0) $year=(-$year)."B.C."; // need BC to parse date $ged_date=new WT_Date("{$cal} {$day} {$month} {$year}"); $year=$ged_date->date1->y; // need negative year for year entry field. } $cal_date=&$ged_date->date1; // Invalid month? Pick a sensible one. if ($cal_date->CALENDAR_ESCAPE()=='@#DHEBREW@' && $cal_date->m==7 && $cal_date->y!=0 && !$cal_date->IsLeapYear()) $cal_date->m=6; // 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 && $action=='today') $action='calendar'; echo "
"; // Calendar form echo '
'; echo ""; echo "d}\" />"; echo ""; echo "y}\" />"; echo ""; echo ""; echo ""; echo ""; echo ''; echo ''; // Day selector echo ''; // Month selector echo ''; echo ''; // Year selector echo ''; echo ' '; // Filtering options echo ''; echo ''; echo '

'; // All further uses of $cal are to generate URLs $cal=rawurlencode($cal); switch ($action) { case 'today': echo WT_I18N::translate('On This Day ...').'
'.$ged_date->Display(false); break; case 'calendar': echo WT_I18N::translate('In This Month ...').'
'.$ged_date->Display(false, '%F %Y'); break; case 'year': echo WT_I18N::translate('In This Year ...').'
'.$ged_date->Display(false, '%Y'); break; } echo '

'; echo WT_I18N::translate('Day'), help_link('annivers_date_select'), ''; for ($d=1; $d<=$days_in_month; $d++) { // Format the day number using the calendar $tmp=new WT_Date($cal_date->Format("%@ {$d} %O %E")); $d_fmt=$tmp->date1->Format('%j'); if ($d==$cal_date->d) echo "{$d_fmt}"; else echo "y}&filterev={$filterev}&filterof={$filterof}&filtersx={$filtersx}&action={$action}"."\">{$d_fmt}"; echo ' | '; } $tmp=new WT_Date($today->Format('%@ %A %O %E')); // Need a WT_Date object to get localisation echo "d}&month={$today_month}&year={$today->y}&filterev={$filterev}&filterof={$filterof}&filtersx={$filtersx}&action={$action}\">".$tmp->Display(false, NULL, array()).''; echo '
'; echo WT_I18N::translate('Month'), help_link('annivers_month_select'), ''; for ($n=1; $n<=$cal_date->NUM_MONTHS(); ++$n) { $month_name=$cal_date->NUM_TO_MONTH_NOMINATIVE($n, $cal_date->IsLeapYear()); $m=$cal_date->NUM_TO_GEDCOM_MONTH($n, $cal_date->IsLeapYear()); if ($m=='ADS' && $cal_date->CALENDAR_ESCAPE()=='@#DHEBREW@' && !$cal_date->IsLeapYear()) { // No month 7 in Jewish leap years. continue; } if ($n==$cal_date->m) $month_name="{$month_name}"; echo "d}&month={$m}&year={$cal_date->y}&filterev={$filterev}&filterof={$filterof}&filtersx={$filtersx}&action={$action}\">{$month_name}"; echo ' | '; } echo "d, $today->DaysInMonth())."&month={$today_month}&year={$today->y}&filterev={$filterev}&filterof={$filterof}&filtersx={$filtersx}&action={$action}\">".$today->Format('%F %Y').'
'; echo WT_I18N::translate('Year'), help_link('annivers_year_select'), ''; echo "d}&month={$cal_month}&year=".($cal_date->y==1?-1:$cal_date->y-1)."&filterev={$filterev}&filterof={$filterof}&filtersx={$filtersx}&action={$action}\">-1"; echo " "; echo "d}&month={$cal_month}&year=".($cal_date->y==-1?1:$cal_date->y+1)."&filterev={$filterev}&filterof={$filterof}&filtersx={$filtersx}&action={$action}\">+1"; echo " | d}&month={$cal_month}&year={$today->y}&filterev={$filterev}&filterof={$filterof}&filtersx={$filtersx}&action={$action}\">".$today->Format('%Y').""; echo ''; echo WT_I18N::translate('Show'), help_link('annivers_show'), ''; echo ''; echo '   |   '; if ($filtersx=="") { echo WT_Person::sexImage('M', 'large', 'vertical-align: middle', WT_I18N::translate('All People')); echo WT_Person::sexImage('F', 'large', 'vertical-align: middle', WT_I18N::translate('All People')), ' | '; } else { echo "d}&month={$cal_month}&year={$cal_date->y}&filterev={$filterev}&filterof={$filterof}&filtersx=&action={$action}\">"; echo WT_Person::sexImage('M', 'small', 'vertical-align: middle', WT_I18N::translate('All People')); echo WT_Person::sexImage('F', 'small', 'vertical-align: middle', WT_I18N::translate('All People')), ' | '; } if ($filtersx=="M") { echo WT_Person::sexImage('M', 'large', 'vertical-align: middle', WT_I18N::translate('Males')), ' | '; } else { echo "d}&month={$cal_month}&year={$cal_date->y}&filterev={$filterev}&filterof={$filterof}&filtersx=M&action={$action}\">"; echo WT_Person::sexImage('M', 'small', 'vertical-align: middle', WT_I18N::translate('Males')), ' | '; } if ($filtersx=="F") echo WT_Person::sexImage('F', 'large', 'vertical-align: middle', WT_I18N::translate('Females')), ' | '; else { echo "d}&month={$cal_month}&year={$cal_date->y}&filterev={$filterev}&filterof={$filterof}&filtersx=F&action={$action}\">"; echo WT_Person::sexImage('F', 'small', 'vertical-align: middle', WT_I18N::translate('Females')), ''; } echo '   |   '; echo ""; echo ''; echo '
'; echo ""; // Day/Month/Year and calendar selector echo '"; echo "
'; if ($action=='today') { echo '', WT_I18N::translate('View Day'), ''; } else { echo "d}&month={$cal_month}&year={$cal_date->y}&filterev={$filterev}&filterof={$filterof}&filtersx={$filtersx}&action=today\">", WT_I18N::translate('View Day'), ""; } if ($action=='calendar') { echo ' | ', WT_I18N::translate('View Month'), ''; } else { echo " | d}&month={$cal_month}&year={$cal_date->y}&filterev={$filterev}&filterof={$filterof}&filtersx={$filtersx}&action=calendar\">", WT_I18N::translate('View Month'), ""; } if ($action=='year') { echo ' | ', WT_I18N::translate('View Year'), ''; } else { echo " | d}&month={$cal_month}&year={$cal_date->y}&filterev={$filterev}&filterof={$filterof}&filtersx={$filtersx}&action=year\">", WT_I18N::translate('View Year'), ""; } echo help_link('day_month'); echo ''; $n=0; foreach (array( 'gregorian'=>WT_Date_Gregorian::calendarName(), 'julian' =>WT_Date_Julian::calendarName(), 'jewish' =>WT_Date_Jewish::calendarName(), 'french' =>WT_Date_French::calendarName(), 'hijri' =>WT_Date_Hijri::calendarName(), 'jalali' =>WT_Date_Jalali::calendarName(), ) as $newcal=>$cal_name) { $tmp=$cal_date->convert_to_cal($newcal); if ($tmp->InValidRange()) { if ($n++) { echo ' | '; } if ($tmp->CALENDAR_ESCAPE()==$cal_date->CALENDAR_ESCAPE()) { echo "{$cal_name}"; } else { $newcalesc=urlencode($tmp->CALENDAR_ESCAPE()); $tmpmonth=$tmp->FormatGedcomMonth(); echo "d}&month={$tmpmonth}&year={$tmp->y}&filterev={$filterev}&filterof={$filterof}&filtersx={$filtersx}&action={$action}\">{$cal_name}"; } } } echo "
"; // Convert event filter option to a list of gedcom event codes if ($filterev=='all') { $events=''; } else { if ($filterev=='bdm') { $events='BIRT MARR DEAT'; } else { $events=$filterev; } } // Fetch data for day/month/year views switch ($action) { case 'today': $found_facts=apply_filter(get_anniversary_events($cal_date->minJD, $events), $filterof, $filtersx); break; case 'calendar': $cal_date->d=0; $cal_date->SetJDfromYMD(); // Make a separate list for each day. Unspecified/invalid days go in day 0. $found_facts=array(); 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(get_anniversary_events($jd, $events), $filterof, $filtersx) as $event) { $tmp=$event['date']->MinDate(); if ($tmp->d>=1 && $tmp->d<=$tmp->DaysInMonth()) $d=$jd-$cal_date->minJD+1; else $d=0; $found_facts[$d][]=$event; } break; case 'year': $cal_date->m=0; $cal_date->SetJDfromYMD(); $found_facts=apply_filter(get_calendar_events($ged_date->MinJD(), $ged_date->MaxJD(), $events), $filterof, $filtersx); // Eliminate duplictes (e.g. BET JUL 1900 AND SEP 1900 will appear twice in 1900) foreach ($found_facts as $key=>$value) $found_facts[$key]=serialize($found_facts[$key]); $found_facts=array_unique($found_facts); foreach ($found_facts as $key=>$value) $found_facts[$key]=unserialize($found_facts[$key]); break; } // Group the facts by family/individual switch ($action) { case 'year': case 'today': $indis=array(); $fams=array(); foreach ($found_facts as $fact) { $fact_text=calendar_fact_text($fact, true); switch ($fact['objtype']) { case 'INDI': if (empty($indis[$fact['id']])) $indis[$fact['id']]=$fact_text; else $indis[$fact['id']].='
'.$fact_text; break; case 'FAM': if (empty($fams[$fact['id']])) $fams[$fact['id']]=$fact_text; else $fams[$fact['id']].='
'.$fact_text; break; } } break; case 'calendar': $cal_facts=array(); foreach ($found_facts as $d=>$facts) { $cal_facts[$d]=array(); foreach ($facts as $fact) { $id=$fact['id']; if (empty($cal_facts[$d][$id])) $cal_facts[$d][$id]=calendar_fact_text($fact, false); else $cal_facts[$d][$id].='
'.calendar_fact_text($fact, false); } } break; } switch ($action) { case 'year': case 'today': echo ""; // Table headings echo ""; echo ""; echo ""; // Table rows $males=0; $females=0; $numfams=0; echo "'; echo "'; echo ""; // Table footers echo ''; echo ''; echo '
"; if (isset($WT_IMAGES['indis'])) echo "\"",   "; echo WT_I18N::translate('Individuals'), ""; if (isset($WT_IMAGES['cfamily'])) echo "\"",   "; echo WT_I18N::translate('Families'), "
"; // Avoid an empty unordered list ob_start(); echo calendar_list_text($indis, "
  • ", "
  • ", true); $content = ob_get_clean(); if (!empty($content)) { echo '
      ', $content, '
    '; } echo '
    "; // Avoid an empty unordered list ob_start(); echo calendar_list_text($fams, "
  • ", "
  • ", true); $content = ob_get_clean(); if (!empty($content)) { echo '
      ', $content, '
    '; } echo '
    ', WT_I18N::translate('Total individuals: %s', count($indis)); echo '
    '; echo WT_Person::sexImage('M', 'small', 'vertical-align: middle', WT_I18N::translate('Males')), " {$males}    "; echo WT_Person::sexImage('F', 'small', 'vertical-align: middle', WT_I18N::translate('Females')), " {$females}    "; if (count($indis)!=$males+$females) echo WT_Person::sexImage('U', 'small', 'vertical-align: middle', WT_I18N::translate('All People')), ' ', count($indis)-$males-$females; echo '
    ', WT_I18N::translate('Total families: %s', count($fams)), '
    '; break; case 'calendar': // We use JD%7 = 0/Mon...6/Sun. Config files use 0/Sun...6/Sat. Add 6 to convert. $week_start=($WEEK_START+6)%$days_in_week; // The french calendar has a 10-day week, but our config only lets us choose // mon-sun as a start day. Force french calendars to start on primidi if ($days_in_week==10) { $week_start=0; } echo ""; for ($week_day=0; $week_day<$days_in_week; ++$week_day) { $day_name=$cal_date->LONG_DAYS_OF_WEEK(($week_day+$week_start) % $days_in_week); echo ""; } echo ""; // Print days 1-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 '
    {$day_name}
    "; if ($d<1 || $d>$days_in_month) if (count($cal_facts[0])>0) { echo "", WT_I18N::translate('Day not set'), "
    "; echo "
    "; echo calendar_list_text($cal_facts[0], "", "", false); echo "
    "; $cal_facts[0]=array(); } else echo ' '; else { // Format the day number using the calendar $tmp=new WT_Date($cal_date->Format("%@ {$d} %O %E")); $d_fmt=$tmp->date1->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) { $alt_date=$cal_date->convert_to_cal($convcal); if ($alt_date->CALENDAR_ESCAPE()!=$cal_date->CALENDAR_ESCAPE()) { list($alt_date->y, $alt_date->m, $alt_date->d)=$alt_date->JDtoYMD($cal_date->minJD+$d-1); $alt_date->SetJDfromYMD(); echo "".$alt_date->Format("%j %M").""; break; } } echo '
    '; echo calendar_list_text($cal_facts[$d], "", "", false); echo '
    '; } echo '
    '; break; } echo '

    '; ///////////////////////////////////////////////////////////////////////////////// // Filter a list of facts ///////////////////////////////////////////////////////////////////////////////// function apply_filter($facts, $filterof, $filtersx) { $filtered=array(); $hundred_years=WT_SERVER_JD-36525; foreach ($facts as $fact) { $tmp=WT_GedcomRecord::GetInstance($fact['id']); // Filter on sex if ($fact['objtype']=='INDI' && $filtersx!='' && $filtersx!=$tmp->getSex()) continue; // Can't display families if the sex filter is on. // TODO: but we could show same-sex partnerships.... if ($fact['objtype']=='FAM' && $filtersx!='') continue; // Filter on age of event if ($filterof=='living') { if ($fact['objtype']=='INDI' && $tmp->isDead()) continue; if ($fact['objtype']=='FAM') { $husb=$tmp->getHusband(); $wife=$tmp->getWife(); if (!empty($husb) && $husb->isDead()) continue; if (!empty($wife) && $wife->isDead()) continue; } } if ($filterof=='recent' && $fact['date']->MaxJD()<$hundred_years) continue; // Finally, check for privacy rules before adding fact. if ($tmp->canDisplayDetails()) $filtered[]=$fact; } return $filtered; } //////////////////////////////////////////////////////////////////////////////// // Format a fact for display. Include the date, the event type, and optionally // the place. //////////////////////////////////////////////////////////////////////////////// function calendar_fact_text($fact, $show_places) { $text=WT_Gedcom_Tag::getLabel($fact['fact']).' - '.$fact['date']->Display(true, "", array()); if ($fact['anniv']>0) $text.=' ('.WT_I18N::translate('%s year anniversary', $fact['anniv']).')'; if ($show_places && !empty($fact['plac'])) $text.=' - '.$fact['plac']; return $text; } //////////////////////////////////////////////////////////////////////////////// // Format a list of facts for display //////////////////////////////////////////////////////////////////////////////// function calendar_list_text($list, $tag1, $tag2, $show_sex_symbols) { global $WT_IMAGES, $males, $females; foreach ($list as $id=>$facts) { $tmp=WT_GedcomRecord::GetInstance($id); echo $tag1, '', $tmp->getFullName(), ' '; if ($show_sex_symbols && $tmp->getType()=='INDI') switch ($tmp->getSex()) { case 'M': echo WT_Person::sexImage('M', 'small', 'vertical-align: middle', WT_I18N::translate('Male')); ++$males; break; case 'F': echo WT_Person::sexImage('F', 'small', 'vertical-align: middle', WT_I18N::translate('Female')); ++$females; break; default: echo WT_Person::sexImage('U', 'small', 'vertical-align: middle', WT_I18N::translate_c('unknown gender', 'Unknown')); break; } echo '
    ', $facts, '
    ', $tag2; } }