/** * Check if a fact has a date and is sourced * Values: * - 0, if no date is found for the fact * - -1, if the date is not precise * - -2, if the date is precise, but no source is found * - 1, if the date is precise, and a source is found * - 2, if the date is precise, a source exists, and is supported by a certificate (requires _ACT usage) * - 3, if the date is precise, a source exists, and the certificate supporting the fact is within an acceptable range of date * * @return int Level of sources */ public function isSourced() { $isSourced = 0; $date = $this->fact->getDate(); if ($date->isOK()) { $isSourced = -1; if ($date->qual1 == '' && $date->minimumJulianDay() == $date->maximumJulianDay()) { $isSourced = -2; $citations = $this->fact->getCitations(); foreach ($citations as $citation) { $isSourced = max($isSourced, 1); if (preg_match('/3 _ACT (.*)/', $citation)) { $isSourced = max($isSourced, 2); preg_match_all("/4 DATE (.*)/", $citation, $datessource, PREG_SET_ORDER); foreach ($datessource as $daterec) { $datesource = new Date($daterec[1]); if (abs($datesource->julianDay() - $date->julianDay()) < self::DATE_PRECISION_MARGIN) { $isSourced = max($isSourced, 3); //If this level increases, do not forget to change the constant MAX_IS_SOURCED_LEVEL } } } } } } return $isSourced; }
/** * {@inhericDoc} * @see \MyArtJaub\Webtrees\Mvc\View\AbstractView::renderContent() */ protected function renderContent() { if ($this->data->get('has_sosa', false)) { $table_id = $this->data->get('table_id'); ?> <div id="sosa-indi-list" class="sosa-list"> <table id="<?php echo $table_id; ?> "> <thead> <tr> <th colspan="22"> <div class="btn-toolbar"> <div class="btn-group"> <button class="ui-state-default" data-filter-column="18" data-filter-value="M" title="<?php echo I18N::translate('Show only males.'); ?> " type="button" ><?php echo Individual::sexImage('M', 'large'); ?> </button> <button class="ui-state-default" data-filter-column="18" data-filter-value="F" title="<?php echo I18N::translate('Show only females.'); ?> " type="button" > <?php echo Individual::sexImage('F', 'large'); ?> </button> <button class="ui-state-default" data-filter-column="18" data-filter-value="U" title="<?php echo I18N::translate('Show only individuals for whom the gender is not known.'); ?> " type="button" > <?php echo Individual::sexImage('U', 'large'); ?> </button> </div> <div class="btn-group"> <button class="ui-state-default" data-filter-column="20" data-filter-value="N" title="<?php echo I18N::translate('Show individuals who are alive or couples where both partners are alive.'); ?> " type="button" > <?php echo I18N::translate('Alive'); ?> </button> <button class="ui-state-default" data-filter-column="20" data-filter-value="Y" title="<?php echo I18N::translate('Show individuals who are dead or couples where both partners are deceased.'); ?> " type="button" > <?php echo I18N::translate('Dead'); ?> </button> <button class="ui-state-default" data-filter-column="20" data-filter-value="YES" title="<?php echo I18N::translate('Show individuals who died more than 100 years ago.'); ?> " type="button" ><?php echo GedcomTag::getLabel('DEAT'); ?> >100 </button> <button class="ui-state-default" data-filter-column="20" data-filter-value="Y100" title="<?php echo I18N::translate('Show individuals who died within the last 100 years.'); ?> " type="button" ><?php echo GedcomTag::getLabel('DEAT'); ?> <=100 </button> </div> <div class="btn-group"> <button class="ui-state-default" data-filter-column="19" data-filter-value="YES" title="<?php echo I18N::translate('Show individuals born more than 100 years ago.'); ?> " type="button" ><?php echo GedcomTag::getLabel('BIRT'); ?> >100 </button> <button class="ui-state-default" data-filter-column="19" data-filter-value="Y100" title="<?php echo I18N::translate('Show individuals born within the last 100 years.'); ?> " type="button" ><?php echo GedcomTag::getLabel('BIRT'); ?> <=100 </button> </div> <div class="btn-group"> <button class="ui-state-default" data-filter-column="21" data-filter-value="R" title="<?php echo I18N::translate('Show “roots” couples or individuals. These individuals may also be called “patriarchs”. They are individuals who have no parents recorded in the database.'); ?> " type="button" > <?php echo I18N::translate('Roots'); ?> </button> <button class="ui-state-default" data-filter-column="21" data-filter-value="L" title="<?php echo I18N::translate('Show “leaves” couples or individuals. These are individuals who are alive but have no children recorded in the database.'); ?> " type="button" > <?php echo I18N::translate('Leaves'); ?> </button> </div> </div> </th> </tr> <tr> <th><?php echo I18N::translate('Sosa'); ?> </th> <th><?php echo GedcomTag::getLabel('INDI'); ?> </th> <th><?php echo GedcomTag::getLabel('GIVN'); ?> </th> <th><?php echo GedcomTag::getLabel('SURN'); ?> </th> <th>GIVN</th> <th>SURN</th> <th><?php echo GedcomTag::getLabel('BIRT'); ?> </th> <th>SORT_BIRT</th> <th><?php echo GedcomTag::getLabel('PLAC'); ?> </th> <?php if (ModuleManager::getInstance()->isOperational(Constants::MODULE_MAJ_ISSOURCED_NAME)) { ?> <th><i class="icon-source" title="<?php echo I18N::translate('Sourced birth'); ?> " border="0"></i></th> <th>SORT_BIRTSC</th> <?php } else { ?> <th></th> <th></th> <?php } ?> <th><?php echo GedcomTag::getLabel('DEAT'); ?> </th> <th>SORT_DEAT</th> <th><?php echo GedcomTag::getLabel('AGE'); ?> </th> <th>AGE</th> <th><?php echo GedcomTag::getLabel('PLAC'); ?> </th> <?php if (ModuleManager::getInstance()->isOperational(Constants::MODULE_MAJ_ISSOURCED_NAME)) { ?> <th><i class="icon-source" title="<?php echo I18N::translate('Sourced death'); ?> " border="0"></i></th> <th>SORT_DEATSC</th> <?php } else { ?> <th></th> <th></th> <?php } ?> <th>SEX</th> <th>BIRT</th> <th>DEAT</th> <th>TREE</th> </tr> </thead> <tbody> <?php foreach ($this->data->get('sosa_list') as $sosa => $person) { /** @var \Fisharebest\Webtrees\Individual $person */ if ($person->isPendingAddtion()) { $class = ' class="new"'; } elseif ($person->isPendingDeletion()) { $class = ' class="old"'; } else { $class = ''; } $dperson = new \MyArtJaub\Webtrees\Individual($person); ?> <tr <?php echo $class; ?> > <td class="transparent"><?php echo $sosa; ?> </td> <td class="transparent"><?php echo $person->getXref(); ?> </td> <td colspan="2"> <?php foreach ($person->getAllNames() as $num => $name) { if ($name['type'] == 'NAME') { $title = ''; } else { $title = 'title="' . strip_tags(GedcomTag::getLabel($name['type'], $person)) . '"'; } if ($num == $person->getPrimaryName()) { $class = ' class="name2"'; $sex_image = $person->getSexImage(); list($surn, $givn) = explode(',', $name['sort']); } else { $class = ''; $sex_image = ''; } ?> <a <?php echo $title . ' ' . $class; ?> href="<?php echo $person->getHtmlUrl(); ?> "> <?php echo \Fisharebest\Webtrees\Functions\FunctionsPrint::highlightSearchHits($name['full']); ?> </a> <?php echo $sex_image . FunctionsPrint::formatSosaNumbers($dperson->getSosaNumbers(), 1, 'smaller'); ?> <br/> <?php } echo $person->getPrimaryParentsNames('parents details1', 'none'); ?> </td> <td style="display:none;"></td> <td> <?php echo Filter::escapeHtml(str_replace('@P.N.', 'AAAA', $givn)) . 'AAAA' . Filter::escapeHtml(str_replace('@N.N.', 'AAAA', $surn)); ?> </td> <td> <?php echo Filter::escapeHtml(str_replace('@N.N.', 'AAAA', $surn)) . 'AAAA' . Filter::escapeHtml(str_replace('@P.N.', 'AAAA', $givn)); ?> </td> <td> <?php if ($birth_dates = $person->getAllBirthDates()) { foreach ($birth_dates as $num => $birth_date) { if ($num) { ?> <br/><?php } ?> <?php echo $birth_date->display(true); } } else { $birth_date = new Date(''); if ($person->getTree()->getPreference('SHOW_EST_LIST_DATES')) { $birth_date = $person->getEstimatedBirthDate(); echo $birth_date->display(true); } else { echo ' '; } $birth_dates[0] = new Date(''); } ?> </td> <td><?php echo $birth_date->julianDay(); ?> </td> <td> <?php foreach ($person->getAllBirthPlaces() as $n => $birth_place) { $tmp = new \Fisharebest\Webtrees\Place($birth_place, $person->getTree()); if ($n) { ?> <br><?php } ?> <a href="'<?php echo $tmp->getURL(); ?> " title="<?php echo strip_tags($tmp->getFullName()); ?> "> <?php echo \Fisharebest\Webtrees\Functions\FunctionsPrint::highlightSearchHits($tmp->getShortName()); ?> </a> <?php } ?> </td> <?php if (ModuleManager::getInstance()->isOperational(Constants::MODULE_MAJ_ISSOURCED_NAME)) { $isBSourced = $dperson->isBirthSourced(); ?> <td><?php echo FunctionsPrint::formatIsSourcedIcon('E', $isBSourced, 'BIRT', 1, 'medium'); ?> </td> <td><?php echo $isBSourced; ?> </td> <?php } else { ?> <td> </td> <td></td> <?php } ?> <td> <?php if ($death_dates = $person->getAllDeathDates()) { foreach ($death_dates as $num => $death_date) { if ($num) { ?> <br/><?php } ?> <?php echo $death_date->display(true); } } else { $death_date = $person->getEstimatedDeathDate(); if ($person->getTree()->getPreference('SHOW_EST_LIST_DATES') && $death_date->minimumJulianDay() < WT_CLIENT_JD) { echo $death_date->display(true); } elseif ($person->isDead()) { echo I18N::translate('yes'); $death_date = new Date(''); } else { echo ' '; $death_date = new Date(''); } $death_dates[0] = new Date(''); } ?> </td> <td><?php echo $death_date->julianDay(); ?> </td> <td><?php echo Date::getAge($birth_dates[0], $death_dates[0], 2); ?> </td> <td><?php echo Date::getAge($birth_dates[0], $death_dates[0], 1); ?> </td> <td> <?php foreach ($person->getAllDeathPlaces() as $n => $death_place) { $tmp = new Place($death_place, $person->getTree()); if ($n) { ?> <br><?php } ?> <a href="'<?php echo $tmp->getURL(); ?> " title="<?php echo strip_tags($tmp->getFullName()); ?> "> <?php echo \Fisharebest\Webtrees\Functions\FunctionsPrint::highlightSearchHits($tmp->getShortName()); ?> </a> <?php } ?> </td> <?php if (ModuleManager::getInstance()->isOperational(Constants::MODULE_MAJ_ISSOURCED_NAME)) { $isDSourced = $dperson->isDeathSourced(); ?> <td><?php echo FunctionsPrint::formatIsSourcedIcon('E', $isDSourced, 'DEAT', 1, 'medium'); ?> </td> <td><?php echo $isDSourced; ?> </td> <?php } else { ?> <td> </td> <td></td> <?php } ?> <td><?php echo $person->getSex(); ?> </td> <td> <?php if (!$person->canShow() || Date::compare($birth_date, new Date(date('Y') - 100)) > 0) { echo 'Y100'; } else { echo 'YES'; } ?> </td> <td> <?php if (Date::compare($death_dates[0], new Date(date('Y') - 100)) > 0) { echo 'Y100'; } elseif ($death_dates[0]->minimumJulianDay() || $person->isDead()) { echo 'YES'; } else { echo 'N'; } ?> </td> <td> <?php if (!$person->getChildFamilies()) { echo 'R'; } elseif (!$person->isDead() && $person->getNumberOfChildren() < 1) { echo 'L'; } else { echo ' '; } ?> </td> </tr> <?php } ?> </tbody> <tfoot> <tr> <th class="ui-state-default" colspan="22"> <div class="center"> <?php echo I18N::translate('Number of Sosa ancestors: %1$s known / %2$s theoretical (%3$s)', I18N::number($this->data->get('sosa_count')), I18N::number($this->data->get('sosa_theo')), I18N::percentage($this->data->get('sosa_ratio'), 2)); ?> <?php if ($this->data->get('sosa_hidden') > 0) { echo '[' . I18N::translate('%s hidden', I18N::number($this->data->get('sosa_hidden'))) . ']'; } ?> </div> </th> </tr> <tr> <th colspan="22"> <div class="btn-toolbar"> <div class="btn-group"> <button type="button" class="ui-state-default btn-toggle-parents"> <?php echo I18N::translate('Show parents'); ?> </button> <button id="btn-toggle-statistics-<?php echo $table_id; ?> " type="button" class="ui-state-default btn-toggle-statistics"> <?php echo I18N::translate('Show statistics charts'); ?> </button> </div> </div> </th> </tr> </tfoot> </table> <div id="indi_list_table-charts_<?php echo $table_id; ?> " style="display:none"> <table class="list-charts"> <tr> <td><?php echo $this->data->get('chart_births'); ?> </td> <td><?php echo $this->data->get('chart_deaths'); ?> </td> </tr> <tr> <td colspan="2"><?php echo $this->data->get('chart_ages'); ?> </td> </tr> </table> </div> </div> <?php } }
/** * Generate the HTML content of this block. * * @param int $block_id * @param bool $template * @param string[] $cfg * * @return string */ public function getBlock($block_id, $template = true, $cfg = array()) { global $ctype, $controller, $WT_TREE; $days = $this->getBlockSetting($block_id, 'days', '7'); $infoStyle = $this->getBlockSetting($block_id, 'infoStyle', 'table'); $calendar = $this->getBlockSetting($block_id, 'calendar', 'jewish'); $block = $this->getBlockSetting($block_id, 'block', '1'); foreach (array('days', 'infoStyle', 'block') as $name) { if (array_key_exists($name, $cfg)) { ${$name} = $cfg[$name]; } } $startjd = WT_CLIENT_JD; $endjd = WT_CLIENT_JD + $days - 1; $id = $this->getName() . $block_id; $class = $this->getName() . '_block'; if ($ctype === 'gedcom' && Auth::isManager($WT_TREE) || $ctype === 'user' && Auth::check()) { $title = '<a class="icon-admin" title="' . I18N::translate('Configure') . '" href="block_edit.php?block_id=' . $block_id . '&ged=' . $WT_TREE->getNameHtml() . '&ctype=' . $ctype . '"></a>'; } else { $title = ''; } $title .= $this->getTitle(); $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(); for ($jd = $startjd - 1; $jd <= $endjd + $days; ++$jd) { foreach (FunctionsDb::getAnniversaryEvents($jd, 'DEAT _YART', $WT_TREE) as $fact) { // Exact hebrew dates only $date = $fact->getDate(); if ($date->minimumDate() instanceof JewishDate && $date->minimumJulianDay() === $date->maximumJulianDay()) { $fact->jd = $jd; $yahrzeits[] = $fact; } } } // ...then adjust dates $jewish_calendar = new JewishCalendar(); foreach ($yahrzeits as $yahrzeit) { if ($yahrzeit->getTag() === 'DEAT') { $today = new JewishDate($yahrzeit->jd); $hd = $yahrzeit->getDate()->minimumDate(); $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->jd = $jewish_calendar->ymdToJd($today->y, 3, 1) - 1; } elseif ($hd->d == 30 && $hd->m == 3 && $hd->y != 0 && $hd1->daysInMonth() < 30) { // 30 KSL - Last day in KSL $yahrzeit->jd = $jewish_calendar->ymdToJd($today->y, 4, 1) - 1; } elseif ($hd->d == 30 && $hd->m == 6 && $hd->y != 0 && $today->daysInMonth() < 30 && !$today->isLeapYear()) { // 30 ADR - Last day in SHV $yahrzeit->jd = $jewish_calendar->ymdToJd($today->y, 6, 1) - 1; } } } switch ($infoStyle) { case 'list': foreach ($yahrzeits as $yahrzeit) { if ($yahrzeit->jd >= $startjd && $yahrzeit->jd < $startjd + $days) { $ind = $yahrzeit->getParent(); $content .= "<a href=\"" . $ind->getHtmlUrl() . "\" class=\"list_item name2\">" . $ind->getFullName() . "</a>" . $ind->getSexImage(); $content .= "<div class=\"indent\">"; $content .= $yahrzeit->getDate()->display(true); $content .= ', ' . I18N::translate('%s year anniversary', $yahrzeit->anniv); $content .= "</div>"; } } break; case 'table': default: $table_id = Uuid::uuid4(); // table requires a unique ID $controller->addExternalJavascript(WT_JQUERY_DATATABLES_JS_URL)->addInlineJavascript(' jQuery("#' . $table_id . '").dataTable({ dom: \'t\', ' . I18N::datatablesI18N() . ', autoWidth: false, paginate: false, lengthChange: false, filter: false, info: true, jQueryUI: true, sorting: [[5,"asc"]], columns: [ /* 0-name */ { dataSort: 1 }, /* 1-NAME */ { visible: false }, /* 2-date */ { dataSort: 3 }, /* 3-DATE */ { visible: false }, /* 4-Aniv */ { class: "center"}, /* 5-yart */ { dataSort: 6 }, /* 6-YART */ { visible: false } ] }); jQuery("#' . $table_id . '").css("visibility", "visible"); jQuery(".loading-image").css("display", "none"); '); $content = ''; $content .= '<div class="loading-image"> </div>'; $content .= '<table id="' . $table_id . '" class="width100" style="visibility:hidden;">'; $content .= '<thead><tr>'; $content .= '<th>' . GedcomTag::getLabel('NAME') . '</th>'; $content .= '<th>' . GedcomTag::getLabel('NAME') . '</th>'; $content .= '<th>' . GedcomTag::getLabel('DEAT') . '</th>'; $content .= '<th>DEAT</th>'; $content .= '<th><i class="icon-reminder" title="' . I18N::translate('Anniversary') . '"></i></th>'; $content .= '<th>' . GedcomTag::getLabel('_YART') . '</th>'; $content .= '<th>_YART</th>'; $content .= '</tr></thead><tbody>'; foreach ($yahrzeits as $yahrzeit) { if ($yahrzeit->jd >= $startjd && $yahrzeit->jd < $startjd + $days) { $content .= '<tr>'; $ind = $yahrzeit->getParent(); // Individual name(s) $name = $ind->getFullName(); $url = $ind->getHtmlUrl(); $content .= '<td>'; $content .= '<a href="' . $url . '">' . $name . '</a>'; $content .= $ind->getSexImage(); $addname = $ind->getAddName(); if ($addname) { $content .= '<br><a href="' . $url . '">' . $addname . '</a>'; } $content .= '</td>'; $content .= '<td>' . $ind->getSortName() . '</td>'; // death/yahrzeit event date $content .= '<td>' . $yahrzeit->getDate()->display() . '</td>'; $content .= '<td>' . $yahrzeit->getDate()->julianDay() . '</td>'; // sortable date // Anniversary $content .= '<td>' . $yahrzeit->anniv . '</td>'; // upcomming yahrzeit dates switch ($calendar) { case 'gregorian': $today = new GregorianDate($yahrzeit->jd); break; case 'jewish': default: $today = new JewishDate($yahrzeit->jd); break; } $td = new Date($today->format('%@ %A %O %E')); $content .= '<td>' . $td->display() . '</td>'; $content .= '<td>' . $td->julianDay() . '</td>'; // sortable date $content .= '</tr>'; } } $content .= '</tbody></table>'; break; } if ($template) { if ($block) { $class .= ' small_inner_block'; } return Theme::theme()->formatBlock($id, $title, $class, $content); } else { return $content; } }