. */ 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 ''; echo $personLabel; if ($daboville !== '1' && $pid !== '' && $icon !== 'blank') { echo '
'; echo ''; echo view($icon); echo ''; } 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 ''; echo (string) $sosa; if ($sosa !== 1 && $pid !== '' && $icon !== '') { echo '
'; echo '' . e($pid); echo view($icon); echo ''; } 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 ''; // husband’s parents $hfam = $husb->primaryChildFamily(); if ($hfam) { // remove the|| test for $sosa echo ''; echo ''; } if ($hfam && ($sosa !== -1)) { echo ''; } if ($hfam) { // husband’s mother echo ''; } 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 father if ($hfam && $hfam->husband()) { 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 '
'; } elseif ($hfam && !$hfam->husband()) { // Empty box for grandfather echo ''; echo '
'; echo FunctionsPrint::printPedigreePerson($hfam->husband()); echo '
'; } echo '
'; echo '' . view('icons/arrow-right') . ''; echo '
'; if ($hfam && $hfam->wife()) { 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 '
'; } elseif ($hfam && !$hfam->wife()) { // Empty box for grandmother echo ''; echo '
'; echo FunctionsPrint::printPedigreePerson($hfam->wife()); echo '
'; } echo '
'; echo '
'; if ($sosa && $family->canShow()) { foreach ($family->facts(Gedcom::MARRIAGE_EVENTS) as $fact) { echo '' . $fact->summary() . ''; } } echo '
'; /** * wife side */ echo ''; // wife’s parents $wfam = $wife->primaryChildFamily(); if ($wfam) { echo ''; echo ''; } if ($wfam && ($sosa !== -1)) { echo ''; } if ($wfam) { // wife’s mother echo ''; } 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 father if ($wfam && $wfam->husband()) { 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 '
'; } elseif ($wfam && !$wfam->husband()) { // Empty box for grandfather echo ''; echo '
'; echo FunctionsPrint::printPedigreePerson($wfam->husband()); echo '
'; } echo '
'; echo '' . view('icons/arrow-right') . ''; echo '
'; if ($wfam && $wfam->wife()) { 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 '
'; } elseif ($wfam && !$wfam->wife()) { // Empty box for grandmother echo ''; echo '
'; echo FunctionsPrint::printPedigreePerson($wfam->wife()); 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) { 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 ''; 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 ''; } echo ''; // spouse information 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 ''; } } echo '
'; if ($numchil === 0) { echo I18N::translate('No children'); } else { echo I18N::plural('%s child', '%s children', $numchil, I18N::number($numchil)); } echo ''; if ($sosa === 0 && Auth::isEditor($family->tree())) { echo '
'; echo '' . I18N::translate('Add a child to this family') . ''; echo ' '; echo ' '; echo '

'; } echo '
'; } elseif ($child->isPendingDeletion()) { echo ''; } else { echo ''; } echo FunctionsPrint::printPedigreePerson($child); 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 ''; $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 ''; echo FunctionsPrint::printPedigreePerson($spouse); echo '
' . I18N::translate('This family remained childless') . '

'; } /** * 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 ''; if ($i < $ctkids) { echo ''; $i++; } } echo '
'; echo FunctionsPrint::printPedigreePerson($fchil); 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 ''; } }