function print_yahrzeit($block = true, $config = '', $side, $index) { global $pgv_lang, $factarray, $SHOW_ID_NUMBERS, $ctype, $TEXT_DIRECTION; global $PGV_IMAGE_DIR, $PGV_IMAGES, $PGV_BLOCKS; global $DAYS_TO_SHOW_LIMIT, $SHOW_MARRIED_NAMES, $SERVER_URL; $block = true; // Always restrict this block's height if (empty($config)) { $config = $PGV_BLOCKS['print_yahrzeit']['config']; } if (empty($config['infoStyle'])) { $config['infoStyle'] = 'style2'; } if (empty($config['allowDownload'])) { $config['allowDownload'] = 'yes'; } if (empty($config['days'])) { $config['days'] = $DAYS_TO_SHOW_LIMIT; } if ($config['days'] < 1) { $config['days'] = 1; } if ($config['days'] > $DAYS_TO_SHOW_LIMIT) { $config['days'] = $DAYS_TO_SHOW_LIMIT; } $startjd = server_jd(); $endjd = $startjd + max(min($config['days'], 1), $DAYS_TO_SHOW_LIMIT) - 1; if (!PGV_USER_ID) { $allowDownload = "no"; } $id = "yahrzeit"; $title = print_help_link('yahrzeit_help', 'qm', '', false, true); if ($PGV_BLOCKS['print_yahrzeit']['canconfig']) { if ($ctype == "gedcom" && PGV_USER_GEDCOM_ADMIN || $ctype == "user" && PGV_USER_ID) { if ($ctype == "gedcom") { $name = PGV_GEDCOM; } else { $name = PGV_USER_NAME; } $title .= "<a href=\"javascript: configure block\" onclick=\"window.open('" . encode_url("index_edit.php?name={$name}&ctype={$ctype}&action=configure&side={$side}&index={$index}") . "', '_blank', 'top=50,left=50,width=600,height=350,scrollbars=1,resizable=1'); return false;\">"; $title .= "<img class=\"adminicon\" src=\"{$PGV_IMAGE_DIR}/{$PGV_IMAGES['admin']['small']}\" width=\"15\" height=\"15\" border=\"0\" alt=\"{$pgv_lang['config_block']}\" /></a>"; } } $title .= $pgv_lang['yahrzeit_block']; $content = ""; // The standard anniversary rules cover most of the Yahrzeit rules, we just // need to handle a few special cases. // Fetch normal anniversaries... $yahrzeits = array(); $hidden = 0; for ($jd = $startjd - 1; $jd <= $endjd + 30; ++$jd) { foreach (get_anniversary_events($jd, 'DEAT _YART') as $fact) { // Extract hebrew dates only if ($fact['date']->date1->CALENDAR_ESCAPE() == '@#DHEBREW@' && $fact['date']->MinJD() == $fact['date']->MaxJD()) { // Apply privacy if (displayDetailsById($fact['id']) && showFactDetails($fact['fact'], $fact['id']) && !FactViewRestricted($fact['id'], $fact['factrec'])) { $yahrzeits[] = $fact; } else { ++$hidden; } } } } // ...then adjust dates foreach ($yahrzeits as $key => $yahrzeit) { if (strpos('1 DEAT', $yahrzeit['factrec']) !== false) { // Just DEAT, not _YART $today = new JewishDate($yahrzeit['jd']); $hd = $yahrzeit['date']->MinDate(); $hd1 = new JewishDate($hd); $hd1->y += 1; $hd1->SetJDFromYMD(); // Special rules. See http://www.hebcal.com/help/anniv.html // Everything else is taken care of by our standard anniversary rules. if ($hd->d == 30 && $hd->m == 2 && $hd->y != 0 && $hd1->DaysInMonth() < 30) { // 30 CSH // Last day in CSH $yahrzeit[$key]['jd'] = JewishDate::YMDtoJD($today->y, 3, 1) - 1; } if ($hd->d == 30 && $hd->m == 3 && $hd->y != 0 && $hd1->DaysInMonth() < 30) { // 30 KSL // Last day in KSL $yahrzeit[$key]['jd'] = JewishDate::YMDtoJD($today->y, 4, 1) - 1; } if ($hd->d == 30 && $hd->m == 6 && $hd->y != 0 && $today->DaysInMonth() < 30 && !$today->IsLeapYear()) { // 30 ADR // Last day in SHV $yahrzeit[$key]['jd'] = JewishDate::YMDtoJD($today->y, 6, 1) - 1; } } } switch ($config['infoStyle']) { case "style1": // List style foreach ($yahrzeits as $yahrzeit) { if ($yahrzeit['jd'] >= $startjd && $yahrzeit['jd'] < $startjd + $config['days']) { $ind = person::GetInstance($yahrzeit['id']); //@@ $content .= "<a href=\"".encode_url($ind->getLinkUrl())."\" class=\"list_item name2\">".$ind->getFullName()."</a>".$ind->getSexImage(); $content .= "<a href=\"" . encode_url($ind->getLinkUrl()) . "\" class=\"list_item name2\">" . PrintReady($ind->getFullName()) . "</a>" . $ind->getSexImage(); $content .= "<div class=\"indent\">"; $content .= $yahrzeit['date']->Display(true); $content .= ', ' . str_replace("#year_var#", $yahrzeit['anniv'], $pgv_lang["year_anniversary"]); $content .= "</div>"; } } break; case "style2": // Table style require_once PGV_ROOT . 'js/sorttable.js.htm'; require_once PGV_ROOT . 'includes/classes/class_gedcomrecord.php'; $table_id = "ID" . floor(microtime() * 1000000); // sorttable requires a unique ID $content .= "<table id=\"{$table_id}\" class=\"sortable list_table center\">"; $content .= "<tr>"; $content .= "<th class=\"list_label\">{$factarray['NAME']}</th>"; $content .= "<th style=\"display:none\">GIVN</th>"; $content .= "<th class=\"list_label\">{$factarray['DATE']}</th>"; $content .= "<th class=\"list_label\"><img src=\"./images/reminder.gif\" alt=\"{$pgv_lang['anniversary']}\" title=\"{$pgv_lang['anniversary']}\" border=\"0\" /></th>"; $content .= "<th class=\"list_label\">{$factarray['_YART']}</th>"; $content .= "</tr>"; $count = 0; foreach ($yahrzeits as $yahrzeit) { if ($yahrzeit['jd'] >= $startjd && $yahrzeit['jd'] < $startjd + $config['days']) { ++$count; $ind = person::GetInstance($yahrzeit['id']); $content .= "<tr class=\"vevent\">"; // hCalendar:vevent // Record name(s) $name = $ind->getFullName(); $url = $ind->getLinkUrl(); $content .= "<td class=\"list_value_wrap\" align=\"" . get_align($name) . "\">"; $content .= "<a href=\"" . encode_url($ind->getLinkUrl()) . "\" class=\"list_item name2\" dir=\"" . $TEXT_DIRECTION . "\">" . PrintReady($name) . "</a>"; $content .= $ind->getSexImage(); $addname = $ind->getAddName(); if ($addname) { $content .= "<br /><a href=\"" . encode_url($url) . "\" class=\"list_item\">" . PrintReady($addname) . "</a>"; } $content .= "</td>"; // GIVN for sorting $content .= "<td style=\"display:none\">"; $exp = explode(",", str_replace('<', ',', $name) . ","); $content .= $exp[1]; $content .= "</td>"; $today = new JewishDate($yahrzeit['jd']); $td = new GedcomDate($today->Format('@ A O E')); // death/yahrzeit event date $content .= "<td class=\"list_value_wrap\">"; $content .= "<a name='{$yahrzeit['jd']}'>" . $yahrzeit['date']->Display(true, NULL, array()) . "</a>"; $content .= "</td>"; // Anniversary $content .= "<td class=\"list_value_wrap rela\">"; $anniv = $yahrzeit['anniv']; if ($anniv == 0) { $content .= '<a name="0"> </a>'; } else { $content .= "<a name=\"{$anniv}\">{$anniv}</a>"; } if ($config['allowDownload'] == 'yes') { // hCalendar:dtstart and hCalendar:summary //TODO does this work?? $content .= "<abbr class=\"dtstart\" title=\"" . strip_tags($yahrzeit['date']->Display(false, 'Ymd', array())) . "\"></abbr>"; $content .= "<abbr class=\"summary\" title=\"" . $pgv_lang["anniversary"] . " #{$anniv} " . $factarray[$yahrzeit['fact']] . " : " . PrintReady(strip_tags($ind->getFullName())) . "\"></abbr>"; } // upcomming yahrzeit dates $content .= "<td class=\"list_value_wrap\">"; $content .= "<a href=\"" . $url . "\" class=\"list_item url\">" . $td->Display(true, NULL, array('gregorian')) . "</a>"; // hCalendar:url $content .= " </td>"; $content .= "</tr>"; } } // table footer $content .= "<tr class=\"sortbottom\">"; $content .= "<td class=\"list_label\">"; $content .= '<a href="javascript:;" onclick="sortByOtherCol(this,1)"><img src="images/topdown.gif" alt="" border="0" /> ' . $factarray["GIVN"] . '</a><br />'; $content .= $pgv_lang["total_names"] . ": " . $count; if ($hidden) { $content .= "<br /><span class=\"warning\">{$pgv_lang['hidden']} : {$hidden}</span>"; } $content .= "</td>"; $content .= "<td style=\"display:none\">GIVN</td>"; $content .= "<td>"; if ($config['allowDownload'] == 'yes') { $uri = $SERVER_URL . basename($_SERVER['REQUEST_URI']); global $whichFile; $whichFile = 'hCal-events.ics'; $alt = print_text('download_file', 0, 1); if (count($yahrzeits)) { $content .= "<a href=\"http://feeds.technorati.com/events/{$uri}\"><img src=\"images/hcal.png\" border=\"0\" alt=\"{$alt}\" title=\"{$alt}\" /></a>"; } } $content .= '</td><td> </td><td> </td></tr>'; $content .= '</table>'; break; } global $THEME_DIR; if ($block) { require $THEME_DIR . 'templates/block_small_temp.php'; } else { require $THEME_DIR . 'templates/block_main_temp.php'; } }
function get_anniversary_events($jd, $facts = '', $ged_id = PGV_GED_ID) { global $TBLPREFIX, $gBitDb; // 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(); foreach (array(new GregorianDate($jd), new JulianDate($jd), new FrenchRDate($jd), new JewishDate($jd), new HijriDate($jd)) as $anniv) { // Build a SQL where clause to match anniversaries in the appropriate calendar. $where = "WHERE d_type='" . $anniv->CALENDAR_ESCAPE() . "'"; // SIMPLE CASES: // a) Non-hebrew anniversaries // b) Hebrew months TVT, SHV, IYR, SVN, TMZ, AAV, ELL if ($anniv->CALENDAR_ESCAPE() != '@#DHEBREW@' || in_array($anniv->m, array(1, 5, 9, 10, 11, 12, 13))) { // Dates without days go on the first day of the month // Dates with invalid days go on the last day of the month if ($anniv->d == 1) { $where .= " AND d_day<=1"; } else { if ($anniv->d == $anniv->DaysInMonth()) { $where .= " AND d_day>={$anniv->d}"; } else { $where .= " AND d_day={$anniv->d}"; } } $where .= " AND d_mon={$anniv->m}"; } else { // SPECIAL CASES: switch ($anniv->m) { case 2: // 29 CSH does not include 30 CSH (but would include an invalid 31 CSH if there were no 30 CSH) if ($anniv->d == 1) { $where .= " AND d_day<=1 AND d_mon=2"; } elseif ($anniv->d == 30) { $where .= " AND d_day>=30 AND d_mon=2"; } elseif ($anniv->d == 29 && $anniv->DaysInMonth() == 29) { $where .= " AND (d_day=29 OR d_day>30) AND d_mon=2"; } else { $where .= " AND d_day={$anniv->d} AND d_mon=2"; } break; case 3: // 1 KSL includes 30 CSH (if this year didn't have 30 CSH) // 29 KSL does not include 30 KSL (but would include an invalid 31 KSL if there were no 30 KSL) if ($anniv->d == 1) { $tmp = new JewishDate(array($anniv->y, 'csh', 1)); if ($tmp->DaysInMonth() == 29) { $where .= " AND (d_day<=1 AND d_mon=3 OR d_day=30 AND d_mon=2)"; } else { $where .= " AND d_day<=1 AND d_mon=3"; } } else { if ($anniv->d == 30) { $where .= " AND d_day>=30 AND d_mon=3"; } elseif ($anniv->d == 29 && $anniv->DaysInMonth() == 29) { $where .= " AND (d_day=29 OR d_day>30) AND d_mon=3"; } else { $where .= " AND d_day={$anniv->d} AND d_mon=3"; } } break; case 4: // 1 TVT includes 30 KSL (if this year didn't have 30 KSL) if ($anniv->d == 1) { $tmp = new JewishDate($anniv->y, 'ksl', 1); if ($tmp->DaysInMonth() == 29) { $where .= " AND (d_day<=1 AND d_mon=4 OR d_day=30 AND d_mon=3)"; } else { $where .= " AND d_day<=1 AND d_mon=4"; } } else { if ($anniv->d == $anniv->DaysInMonth()) { $where .= " AND d_day>={$anniv->d} AND d_mon=4"; } else { $where .= " AND d_day={$anniv->d} AND d_mon=4"; } } break; case 6: // ADR (non-leap) includes ADS (leap) if ($anniv->d == 1) { $where .= " AND d_day<=1"; } elseif ($anniv->d == $anniv->DaysInMonth()) { $where .= " AND d_day>={$anniv->d}"; } else { $where .= " AND d_day={$anniv->d}"; } if ($anniv->IsLeapYear()) { $where .= " AND (d_mon=6 AND " . $gBitDb->mod_function("7*d_year+1", "19") . "<7)"; } else { $where .= " AND (d_mon=6 OR d_mon=7)"; } break; case 7: // ADS includes ADR (non-leap) if ($anniv->d == 1) { $where .= " AND d_day<=1"; } elseif ($anniv->d == $anniv->DaysInMonth()) { $where .= " AND d_day>={$anniv->d}"; } else { $where .= " AND d_day={$anniv->d}"; } $where .= " AND (d_mon=6 AND " . $gBitDb->mod_function("7*d_year+1", "19") . ">=7 OR d_mon=7)"; break; case 8: // 1 NSN includes 30 ADR, if this year is non-leap if ($anniv->d == 1) { if ($anniv->IsLeapYear()) { $where .= " AND d_day<=1 AND d_mon=8"; } else { $where .= " AND (d_day<=1 AND d_mon=8 OR d_day=30 AND d_mon=6)"; } } elseif ($anniv->d == $anniv->DaysInMonth()) { $where .= " AND d_day>={$anniv->d} AND d_mon=8"; } else { $where .= " AND d_day={$anniv->d} AND d_mon=8"; } break; } } // Only events in the past (includes dates without a year) $where .= " AND d_year<={$anniv->y}"; // 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=" . $ged_id; // Now fetch these anniversaries $ind_sql = "SELECT DISTINCT 'INDI' AS type, i_id AS xref, i_file AS ged_id, i_gedcom AS gedrec, i_isdead, i_sex, d_type, d_day, d_month, d_year, d_fact, d_type FROM {$TBLPREFIX}dates, {$TBLPREFIX}individuals {$where} AND d_gid=i_id AND d_file=i_file ORDER BY d_day ASC, d_year DESC"; $fam_sql = "SELECT DISTINCT 'FAM' AS type, f_id AS xref, f_file AS ged_id, f_gedcom AS gedrec, f_husb, f_wife, f_chil, f_numchil, d_type, d_day, d_month, d_year, d_fact, d_type FROM {$TBLPREFIX}dates, {$TBLPREFIX}families {$where} AND d_gid=f_id AND d_file=f_file ORDER BY d_day ASC, d_year DESC"; foreach (array($ind_sql, $fam_sql) as $sql) { $rows = $gBitDb->getAll($sql); foreach ($rows as $row) { if ($row['type'] == 'INDI') { $record = Person::getInstance($row); } else { $record = Family::getInstance($row); } // Generate a regex to match the retrieved date - so we can find it in the original gedcom record. // TODO having to go back to the original gedcom is lame. This is why it is so slow, and needs // to be cached. We should store the level1 fact here (or somewhere) if ($row['d_type'] == '@#DJULIAN@') { if ($row['d_year'] < 0) { $year_regex = $row['d_year'] . " ?[Bb]\\.? ?[Cc]\\.\\ ?"; } else { $year_regex = "({$row['d_year']}|" . ($row['d_year'] - 1) . "\\/" . $row['d_year'] % 100 . ")"; } } else { $year_regex = "0*" . $row['d_year']; } $ged_date_regex = "/2 DATE.*(" . ($row['d_day'] > 0 ? "0?{$row['d_day']}\\s*" : "") . $row['d_month'] . "\\s*" . ($row['d_year'] != 0 ? $year_regex : "") . ")/i"; foreach (get_all_subrecords($row['gedrec'], $skipfacts, false, false) as $factrec) { if (preg_match("/(^1 {$row['d_fact']}|^1 (FACT|EVEN).*\n2 TYPE {$row['d_fact']})/s", $factrec) && preg_match($ged_date_regex, $factrec) && preg_match('/2 DATE (.+)/', $factrec, $match)) { $date = new GedcomDate($match[1]); if (preg_match('/2 PLAC (.+)/', $factrec, $match)) { $plac = $match[1]; } else { $plac = ''; } if (showFactDetails($row['d_fact'], $row['xref']) && !FactViewRestricted($row['xref'], $factrec)) { $found_facts[] = array('record' => $record, 'id' => $row['xref'], 'objtype' => $row['type'], 'fact' => $row['d_fact'], 'factrec' => $factrec, 'jd' => $jd, 'anniv' => $row['d_year'] == 0 ? 0 : $anniv->y - $row['d_year'], 'date' => $date, 'plac' => $plac); } } } } } } return $found_facts; }