.
*/
declare(strict_types=1);
namespace Fisharebest\Webtrees\Functions;
use Fisharebest\Webtrees\Auth;
use Fisharebest\Webtrees\Family;
use Fisharebest\Webtrees\Gedcom;
use Fisharebest\Webtrees\I18N;
use Fisharebest\Webtrees\Individual;
use Fisharebest\Webtrees\Module\ModuleThemeInterface;
/**
* Class FunctionsCharts - common functions
*/
class FunctionsCharts
{
/**
* print a table cell with sosa number
*
* @param string $daboville
* @param string $pid optional pid
* @param string $icon which arrow to use
*
* @return void
*/
public static function printDabovilleNumber(string $daboville, string $pid = '', string $icon = ''): void
{
// Remove trailing "."
$personLabel = substr($daboville, 0, -1);
if ($icon === '') {
$visibility = 'hidden';
} else {
$visibility = 'normal';
}
echo '
';
}
/**
* print a table cell with sosa number
*
* @param int $sosa
* @param string $pid optional pid
* @param string $icon which arrow to use
*
* @return void
*/
public static function printSosaNumber(int $sosa, string $pid = '', string $icon = ''): void
{
if ($icon === '') {
$visibility = 'hidden';
} else {
$visibility = 'normal';
}
echo '';
}
/**
* print the parents table for a family
*
* @param Family $family family gedcom ID
* @param int $sosa child sosa number
* @param string $daboville indi label (descendancy booklet)
* @param string $parid parent ID (descendancy booklet)
* @param string $gparid gd-parent ID (descendancy booklet)
*
* @return void
*/
public static function printFamilyParents(Family $family, int $sosa = 0, string $daboville = '', string $parid = '', string $gparid = ''): void
{
$pbheight = app(ModuleThemeInterface::class)->parameter('chart-box-y') + 14;
$husb = $family->husband();
if ($husb) {
echo '';
} else {
$husb = new Individual('M', "0 @M@ INDI\n1 SEX M", null, $family->tree());
}
$wife = $family->wife();
if ($wife) {
echo '';
} else {
$wife = new Individual('F', "0 @F@ INDI\n1 SEX F", null, $family->tree());
}
if ($sosa) {
echo '', $family->fullName(), '
';
}
/**
* husband side
*/
echo '';
echo '';
if ($parid) {
if ($husb->xref() === $parid) {
self::printDabovilleNumber($daboville, '', 'blank');
} else {
self::printDabovilleNumber($daboville, '', '');
}
} elseif ($sosa) {
self::printSosaNumber($sosa * 2, '', '');
}
if ($husb->isPendingAddition()) {
echo '| ';
} elseif ($husb->isPendingDeletion()) {
echo ' | ';
} else {
echo ' | ';
}
echo FunctionsPrint::printPedigreePerson($husb);
echo ' | ';
echo ' | ';
// husband’s parents
$hfam = $husb->primaryChildFamily();
if ($hfam instanceof Family) {
echo ') . ') | ) . ') | ';
echo ') . ') | ';
// husband’s father
if ($hfam->husband() instanceof Individual) {
echo '';
if ($sosa > 0) {
self::printSosaNumber($sosa * 4, $hfam->husband()->xref(), 'icons/arrow-down');
}
if (!empty($gparid) && $hfam->husband()->xref() === $gparid) {
self::printDabovilleNumber(trim(substr($daboville, 0, -3), '.') . '.', '', 'icons/arrow-up');
}
echo '| ';
echo FunctionsPrint::printPedigreePerson($hfam->husband());
echo ' | ';
} else {
// Empty box for grandfather
echo '';
echo '| ';
echo FunctionsPrint::printPedigreePerson(null);
echo ' | ';
}
echo ' | ';
if ($sosa !== -1) {
echo '';
echo '' . view('icons/arrow-right') . '';
echo ' | ';
}
// husband’s mother
echo '
) . ') | ';
if ($hfam->wife() instanceof Individual) {
echo '';
if ($sosa > 0) {
self::printSosaNumber($sosa * 4 + 1, $hfam->wife()->xref(), 'icons/arrow-down');
}
if (!empty($gparid) && $hfam->wife()->xref() === $gparid) {
self::printDabovilleNumber(trim(substr($daboville, 0, -3), '.') . '.', '', 'icons/arrow-up');
}
echo '| ';
echo FunctionsPrint::printPedigreePerson($hfam->wife());
echo ' | ';
} else {
// Empty box for grandmother
echo '';
echo '| ';
echo FunctionsPrint::printPedigreePerson(null);
echo ' | ';
}
echo ' | ';
}
echo '
';
echo '
';
if ($sosa && $family->canShow()) {
foreach ($family->facts(Gedcom::MARRIAGE_EVENTS) as $fact) {
echo '' . $fact->summary() . '';
}
}
echo '
';
/**
* wife side
*/
echo '';
echo '';
if ($parid) {
if ($wife->xref() === $parid) {
self::printDabovilleNumber($daboville, '', 'blank');
} else {
self::printDabovilleNumber($daboville, '', '');
}
} elseif ($sosa) {
self::printSosaNumber($sosa * 2 + 1, '', '');
}
if ($wife->isPendingAddition()) {
echo '| ';
} elseif ($wife->isPendingDeletion()) {
echo ' | ';
} else {
echo ' | ';
}
echo FunctionsPrint::printPedigreePerson($wife);
echo ' | ';
echo ' | ';
// wife’s parents
$wfam = $wife->primaryChildFamily();
if ($wfam instanceof Family) {
echo ') . ') | ) . ') | ';
echo ') . ') | ';
// wife’s father
if ($wfam->husband() instanceof Individual) {
echo '';
if ($sosa > 0) {
self::printSosaNumber($sosa * 4 + 2, $wfam->husband()->xref(), 'icons/arrow-down');
}
if (!empty($gparid) && $wfam->husband()->xref() === $gparid) {
self::printDabovilleNumber(trim(substr($daboville, 0, -3), '.') . '.', '', 'icons/arrow-up');
}
echo '| ';
echo FunctionsPrint::printPedigreePerson($wfam->husband());
echo ' | ';
} else {
// Empty box for grandfather
echo '';
echo '| ';
echo FunctionsPrint::printPedigreePerson(null);
echo ' | ';
}
echo ' | ';
if ($sosa !== -1) {
echo '';
echo '' . view('icons/arrow-right') . '';
echo ' | ';
}
// wife’s mother
echo '
) . ') | ';
if ($wfam->wife() instanceof Individual) {
echo '';
if ($sosa > 0) {
self::printSosaNumber($sosa * 4 + 3, $wfam->wife()->xref(), 'icons/arrow-down');
}
if (!empty($gparid) && $wfam->wife()->xref() === $gparid) {
self::printDabovilleNumber(trim(substr($daboville, 0, -3), '.') . '.', '', 'icons/arrow-up');
}
echo '| ';
echo FunctionsPrint::printPedigreePerson($wfam->wife());
echo ' | ';
} else {
// Empty box for grandmother
echo '';
echo '| ';
echo FunctionsPrint::printPedigreePerson(null);
echo ' | ';
}
echo ' | ';
}
echo '
';
}
/**
* print the children table for a family
*
* @param Family $family family
* @param string $childid child ID
* @param int $sosa child sosa number
* @param string $label indi label (descendancy booklet)
* @param bool $show_cousins display cousins on chart
*
* @return void
*/
public static function printFamilyChildren(
Family $family,
string $childid = '',
int $sosa = 0,
string $label = '',
bool $show_cousins = false
): void {
$bheight = app(ModuleThemeInterface::class)->parameter('chart-box-y');
$pbheight = $bheight + 14;
$children = $family->children();
$numchil = $children->count();
echo '';
if ($sosa > 0) {
echo ' | ';
}
echo '';
if ($sosa === 0 && Auth::isEditor($family->tree())) {
echo ' ';
echo '' . I18N::translate('Add a child to this family') . '';
echo ' ';
echo ' ';
echo '
';
}
echo ' | ';
if ($sosa > 0) {
echo ' | | ';
}
echo '
';
$nchi = 1;
if ($children->isNotEmpty()) {
foreach ($children as $child) {
echo '';
if ($sosa !== 0) {
if ($child->xref() === $childid) {
self::printSosaNumber($sosa, $childid, 'icons/arrow-up');
} elseif (empty($label)) {
self::printDabovilleNumber('', '', 'icons/arrow-up');
} else {
self::printDabovilleNumber($label . ($nchi++) . '.', '', 'icons/arrow-up');
}
}
if ($child->isPendingAddition()) {
echo '| ';
} elseif ($child->isPendingDeletion()) {
echo ' | ';
} else {
echo ' | ';
}
echo FunctionsPrint::printPedigreePerson($child);
echo ' | ';
if ($sosa !== 0) {
// loop for all families where current child is a spouse
$famids = $child->spouseFamilies();
$maxfam = count($famids) - 1;
for ($f = 0; $f <= $maxfam; $f++) {
// multiple marriages
if ($f > 0) {
echo '
| ';
echo '';
//find out how many cousins there are to establish vertical line on second families
$kids = $famids[$f]->children()->count();
if ($show_cousins) {
if ($kids > 0) {
echo ' ';
echo ' | ';
}
echo '';
$spouse = $famids[$f]->spouse($child);
$marr = $famids[$f]->facts(['MARR'])->first();
$div = $famids[$f]->facts(['DIV'])->first();
if ($marr) {
// marriage date
echo $marr->date()->minimumDate()->format('%Y');
// divorce date
if ($div) {
echo '–', $div->date()->minimumDate()->format('%Y');
}
echo ' ';
} else {
echo ' ';
}
echo ' | ';
// spouse information
echo '';
echo FunctionsPrint::printPedigreePerson($spouse);
echo ' | ';
// cousins
if ($show_cousins) {
self::printCousins($famids[$f]);
}
}
}
echo '
';
}
} elseif ($sosa < 1) {
// message 'no children' except for sosa
if (preg_match('/\n1 NCHI (\d+)/', $family->gedcom(), $match) && $match[1] === '0') {
echo '| ' . I18N::translate('This family remained childless') . ' |
';
}
}
echo '
';
}
/**
* print a family with Sosa-Stradonitz numbering system
* ($rootid=1, father=2, mother=3 ...)
*
* @param Family $family family gedcom
* @param string $childid tree root ID
* @param int $sosa Sosa-Stradonitz number
* @param string $daboville d'Aboville number
* @param string $parid parent ID (descendancy booklet)
* @param string $gparid gd-parent ID (descendancy booklet)
* @param bool $show_cousins display cousins on chart
*
* @return void
*/
public static function printSosaFamily(
Family $family,
string $childid,
int $sosa,
string $daboville,
string $parid,
string $gparid,
bool $show_cousins
): void {
echo '
';
echo '';
echo '';
self::printFamilyParents($family, $sosa, $daboville, $parid, $gparid);
echo '
';
echo '
| ';
self::printFamilyChildren($family, $childid, $sosa, $daboville, $show_cousins);
echo ' |
';
echo '
';
}
/**
* builds and returns sosa relationship name in the active language
*
* @param int $sosa Sosa number
*
* @return string
*/
public static function getSosaName(int $sosa): string
{
$path = '';
while ($sosa > 1) {
if ($sosa % 2 === 1) {
$path = 'mot' . $path;
} else {
$path = 'fat' . $path;
}
$sosa = intdiv($sosa, 2);
}
return Functions::getRelationshipNameFromPath($path, null, null);
}
/**
* print cousins list
*
* @param Family $family
*
* @return void
*/
private static function printCousins(Family $family): void
{
$bheight = app(ModuleThemeInterface::class)->parameter('chart-box-y');
$fchildren = $family->children();
$kids = $fchildren->count();
echo '';
if ($fchildren->isNotEmpty()) {
echo '';
if ($fchildren->count() > 1) {
echo '), ') | ';
}
$ctkids = $fchildren->count();
$i = 1;
foreach ($fchildren as $fchil) {
if ($i === 1) {
echo '![]() ), ') | ';
echo FunctionsPrint::printPedigreePerson($fchil);
echo ' | ';
if ($i < $ctkids) {
echo '';
$i++;
}
}
echo ' ';
} elseif (preg_match('/\n1 NCHI (\d+)/', $family->gedcom(), $match) && $match[1] === '0') {
// If there is known that there are no children (as opposed to no known children)
echo ' ';
}
echo ' | ';
}
}