mirror of
https://github.com/YunoHost-Apps/webtrees_ynh.git
synced 2024-09-03 18:26:37 +02:00
551 lines
18 KiB
PHP
551 lines
18 KiB
PHP
<?php
|
||
/**
|
||
* webtrees: online genealogy
|
||
* Copyright (C) 2016 webtrees development team
|
||
* This program is free software: you can redistribute it and/or modify
|
||
* it under the terms of the GNU General Public License as published by
|
||
* the Free Software Foundation, either version 3 of the License, or
|
||
* (at your option) any later version.
|
||
* This program is distributed in the hope that it will be useful,
|
||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
* GNU General Public License for more details.
|
||
* You should have received a copy of the GNU General Public License
|
||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
*/
|
||
namespace Fisharebest\Webtrees\Functions;
|
||
|
||
use Fisharebest\Webtrees\Auth;
|
||
use Fisharebest\Webtrees\Family;
|
||
use Fisharebest\Webtrees\I18N;
|
||
use Fisharebest\Webtrees\Individual;
|
||
use Fisharebest\Webtrees\Theme;
|
||
|
||
/**
|
||
* Class FunctionsCharts - common functions
|
||
*/
|
||
class FunctionsCharts {
|
||
/**
|
||
* print a table cell with sosa number
|
||
*
|
||
* @param int $sosa
|
||
* @param string $pid optional pid
|
||
* @param string $arrowDirection direction of link arrow
|
||
*/
|
||
public static function printSosaNumber($sosa, $pid = "", $arrowDirection = "up") {
|
||
if (substr($sosa, -1, 1) == ".") {
|
||
$personLabel = substr($sosa, 0, -1);
|
||
} else {
|
||
$personLabel = $sosa;
|
||
}
|
||
if ($arrowDirection == "blank") {
|
||
$visibility = "hidden";
|
||
} else {
|
||
$visibility = "normal";
|
||
}
|
||
echo "<td class=\"subheaders center\" style=\"vertical-align: middle; text-indent: 0px; margin-top: 0px; white-space: nowrap; visibility: ", $visibility, ";\">";
|
||
echo $personLabel;
|
||
if ($sosa != "1" && $pid != "") {
|
||
if ($arrowDirection == "left") {
|
||
$dir = 0;
|
||
} elseif ($arrowDirection == "right") {
|
||
$dir = 1;
|
||
} elseif ($arrowDirection == "down") {
|
||
$dir = 3;
|
||
} else {
|
||
$dir = 2; // either 'blank' or 'up'
|
||
}
|
||
echo '<br>';
|
||
self::printUrlArrow('#' . $pid, $pid, $dir);
|
||
}
|
||
echo '</td>';
|
||
}
|
||
|
||
/**
|
||
* print the parents table for a family
|
||
*
|
||
* @param Family $family family gedcom ID
|
||
* @param int $sosa child sosa number
|
||
* @param string $label indi label (descendancy booklet)
|
||
* @param string $parid parent ID (descendancy booklet)
|
||
* @param string $gparid gd-parent ID (descendancy booklet)
|
||
* @param int $show_full large or small box
|
||
*/
|
||
public static function printFamilyParents(Family $family, $sosa = 0, $label = '', $parid = '', $gparid = '', $show_full = 1) {
|
||
|
||
if ($show_full) {
|
||
$pbheight = Theme::theme()->parameter('chart-box-y') + 14;
|
||
} else {
|
||
$pbheight = Theme::theme()->parameter('compact-chart-box-y') + 14;
|
||
}
|
||
|
||
$husb = $family->getHusband();
|
||
if ($husb) {
|
||
echo '<a name="', $husb->getXref(), '"></a>';
|
||
} else {
|
||
$husb = new Individual('M', "0 @M@ INDI\n1 SEX M", null, $family->getTree());
|
||
}
|
||
$wife = $family->getWife();
|
||
if ($wife) {
|
||
echo '<a name="', $wife->getXref(), '"></a>';
|
||
} else {
|
||
$wife = new Individual('F', "0 @F@ INDI\n1 SEX F", null, $family->getTree());
|
||
}
|
||
|
||
if ($sosa) {
|
||
echo '<p class="name_head">', $family->getFullName(), '</p>';
|
||
}
|
||
|
||
/**
|
||
* husband side
|
||
*/
|
||
echo '<table cellspacing="0" cellpadding="0" border="0"><tr><td rowspan="2">';
|
||
echo '<table border="0"><tr>';
|
||
|
||
if ($parid) {
|
||
if ($husb->getXref() == $parid) {
|
||
self::printSosaNumber($label);
|
||
} else {
|
||
self::printSosaNumber($label, '', 'blank');
|
||
}
|
||
} elseif ($sosa) {
|
||
self::printSosaNumber($sosa * 2);
|
||
}
|
||
if ($husb->isPendingAddtion()) {
|
||
echo '<td class="facts_value new">';
|
||
} elseif ($husb->isPendingDeletion()) {
|
||
echo '<td class="facts_value old">';
|
||
} else {
|
||
echo '<td>';
|
||
}
|
||
FunctionsPrint::printPedigreePerson($husb, $show_full);
|
||
echo '</td></tr></table>';
|
||
echo '</td>';
|
||
// husband’s parents
|
||
$hfam = $husb->getPrimaryChildFamily();
|
||
if ($hfam) {
|
||
// remove the|| test for $sosa
|
||
echo '<td rowspan="2"><img src="' . Theme::theme()->parameter('image-hline') . '"></td><td rowspan="2"><img src="' . Theme::theme()->parameter('image-vline') . '" width="3" height="' . ($pbheight + 9) . '"></td>';
|
||
echo '<td><img class="line5" src="' . Theme::theme()->parameter('image-hline') . '"></td><td>';
|
||
// husband’s father
|
||
if ($hfam && $hfam->getHusband()) {
|
||
echo '<table border="0"><tr>';
|
||
if ($sosa > 0) {
|
||
self::printSosaNumber($sosa * 4, $hfam->getHusband()->getXref(), 'down');
|
||
}
|
||
if (!empty($gparid) && $hfam->getHusband()->getXref() == $gparid) {
|
||
self::printSosaNumber(trim(substr($label, 0, -3), '.') . '.');
|
||
}
|
||
echo '<td>';
|
||
FunctionsPrint::printPedigreePerson($hfam->getHusband(), $show_full);
|
||
echo '</td></tr></table>';
|
||
} elseif ($hfam && !$hfam->getHusband()) {
|
||
// Empty box for grandfather
|
||
echo '<table border="0"><tr>';
|
||
echo '<td>';
|
||
FunctionsPrint::printPedigreePerson($hfam->getHusband(), $show_full);
|
||
echo '</td></tr></table>';
|
||
}
|
||
echo '</td>';
|
||
}
|
||
if ($hfam && ($sosa != -1)) {
|
||
echo '<td rowspan="2">';
|
||
self::printUrlArrow(($sosa == 0 ? '?famid=' . $hfam->getXref() . '&ged=' . $hfam->getTree()->getNameUrl() : '#' . $hfam->getXref()), $hfam->getXref(), 1);
|
||
echo '</td>';
|
||
}
|
||
if ($hfam) {
|
||
// husband’s mother
|
||
echo '</tr><tr><td><img src="' . Theme::theme()->parameter('image-hline') . '"></td><td>';
|
||
if ($hfam && $hfam->getWife()) {
|
||
echo '<table border=\'0\'><tr>';
|
||
if ($sosa > 0) {
|
||
self::printSosaNumber($sosa * 4 + 1, $hfam->getWife()->getXref(), 'down');
|
||
}
|
||
if (!empty($gparid) && $hfam->getWife()->getXref() == $gparid) {
|
||
self::printSosaNumber(trim(substr($label, 0, -3), '.') . '.');
|
||
}
|
||
echo '<td>';
|
||
FunctionsPrint::printPedigreePerson($hfam->getWife(), $show_full);
|
||
echo '</td></tr></table>';
|
||
} elseif ($hfam && !$hfam->getWife()) {
|
||
// Empty box for grandmother
|
||
echo '<table border="0"><tr>';
|
||
echo '<td>';
|
||
FunctionsPrint::printPedigreePerson($hfam->getWife(), $show_full);
|
||
echo '</td></tr></table>';
|
||
}
|
||
echo '</td>';
|
||
}
|
||
echo '</tr></table>';
|
||
if ($sosa && $family->canShow()) {
|
||
foreach ($family->getFacts(WT_EVENTS_MARR) as $fact) {
|
||
echo '<a href="', $family->getHtmlUrl(), '" class="details1">';
|
||
echo str_repeat(' ', 10);
|
||
echo $fact->summary();
|
||
echo '</a>';
|
||
}
|
||
} else {
|
||
echo '<br>';
|
||
}
|
||
|
||
/**
|
||
* wife side
|
||
*/
|
||
echo '<table cellspacing="0" cellpadding="0" border="0"><tr><td rowspan="2">';
|
||
echo '<table><tr>';
|
||
if ($parid) {
|
||
if ($wife->getXref() == $parid) {
|
||
self::printSosaNumber($label);
|
||
} else {
|
||
self::printSosaNumber($label, '', 'blank');
|
||
}
|
||
} elseif ($sosa) {
|
||
self::printSosaNumber($sosa * 2 + 1);
|
||
}
|
||
if ($wife->isPendingAddtion()) {
|
||
echo '<td class="facts_value new">';
|
||
} elseif ($wife->isPendingDeletion()) {
|
||
echo '<td class="facts_value old">';
|
||
} else {
|
||
echo '<td>';
|
||
}
|
||
FunctionsPrint::printPedigreePerson($wife, $show_full);
|
||
echo '</td></tr></table>';
|
||
echo '</td>';
|
||
// wife’s parents
|
||
$hfam = $wife->getPrimaryChildFamily();
|
||
|
||
if ($hfam) {
|
||
echo '<td rowspan="2"><img src="' . Theme::theme()->parameter('image-hline') . '"></td><td rowspan="2"><img src="' . Theme::theme()->parameter('image-vline') . '" width="3" height="' . ($pbheight + 9) . '"></td>';
|
||
echo '<td><img class="line5" src="' . Theme::theme()->parameter('image-hline') . '"></td><td>';
|
||
// wife’s father
|
||
if ($hfam && $hfam->getHusband()) {
|
||
echo '<table><tr>';
|
||
if ($sosa > 0) {
|
||
self::printSosaNumber($sosa * 4 + 2, $hfam->getHusband()->getXref(), 'down');
|
||
}
|
||
if (!empty($gparid) && $hfam->getHusband()->getXref() == $gparid) {
|
||
self::printSosaNumber(trim(substr($label, 0, -3), '.') . '.');
|
||
}
|
||
echo '<td>';
|
||
FunctionsPrint::printPedigreePerson($hfam->getHusband(), $show_full);
|
||
echo '</td></tr></table>';
|
||
} elseif ($hfam && !$hfam->getHusband()) {
|
||
// Empty box for grandfather
|
||
echo '<table border="0"><tr>';
|
||
echo '<td>';
|
||
FunctionsPrint::printPedigreePerson($hfam->getHusband(), $show_full);
|
||
echo '</td></tr></table>';
|
||
}
|
||
echo '</td>';
|
||
}
|
||
if ($hfam && ($sosa != -1)) {
|
||
echo '<td rowspan="2">';
|
||
self::printUrlArrow(($sosa == 0 ? '?famid=' . $hfam->getXref() . '&ged=' . $hfam->getTree()->getNameUrl() : '#' . $hfam->getXref()), $hfam->getXref(), 1);
|
||
echo '</td>';
|
||
}
|
||
if ($hfam) {
|
||
// wife’s mother
|
||
echo '</tr><tr><td><img src="' . Theme::theme()->parameter('image-hline') . '"></td><td>';
|
||
if ($hfam && $hfam->getWife()) {
|
||
echo '<table><tr>';
|
||
if ($sosa > 0) {
|
||
self::printSosaNumber($sosa * 4 + 3, $hfam->getWife()->getXref(), 'down');
|
||
}
|
||
if (!empty($gparid) && $hfam->getWife()->getXref() == $gparid) {
|
||
self::printSosaNumber(trim(substr($label, 0, -3), '.') . '.');
|
||
}
|
||
echo '<td>';
|
||
FunctionsPrint::printPedigreePerson($hfam->getWife(), $show_full);
|
||
echo '</td></tr></table>';
|
||
} elseif ($hfam && !$hfam->getWife()) {
|
||
// Empty box for grandmother
|
||
echo '<table border="0"><tr>';
|
||
echo '<td>';
|
||
FunctionsPrint::printPedigreePerson($hfam->getWife(), $show_full);
|
||
echo '</td></tr></table>';
|
||
}
|
||
echo '</td>';
|
||
}
|
||
echo '</tr></table>';
|
||
}
|
||
|
||
/**
|
||
* 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 int $show_cousins display cousins on chart
|
||
* @param int $show_full large or small box
|
||
*/
|
||
public static function printFamilyChildren(Family $family, $childid = '', $sosa = 0, $label = '', $show_cousins = 0, $show_full = 1) {
|
||
|
||
if ($show_full) {
|
||
$bheight = Theme::theme()->parameter('chart-box-y');
|
||
} else {
|
||
$bheight = Theme::theme()->parameter('compact-chart-box-y');
|
||
}
|
||
|
||
$pbheight = $bheight + 14;
|
||
|
||
$children = $family->getChildren();
|
||
$numchil = count($children);
|
||
|
||
echo '<table border="0" cellpadding="0" cellspacing="2"><tr>';
|
||
if ($sosa > 0) {
|
||
echo '<td></td>';
|
||
}
|
||
echo '<td><span class="subheaders">';
|
||
if ($numchil == 0) {
|
||
echo I18N::translate('No children');
|
||
} else {
|
||
echo I18N::plural('%s child', '%s children', $numchil, $numchil);
|
||
}
|
||
echo '</span>';
|
||
|
||
if ($sosa == 0 && Auth::isEditor($family->getTree())) {
|
||
echo '<br>';
|
||
echo "<a href=\"#\" onclick=\"return add_child_to_family('", $family->getXref(), "', 'U');\">" . I18N::translate('Add a child to this family') . "</a>";
|
||
echo ' <a class="icon-sex_m_15x15" href="#" onclick="return add_child_to_family(\'', $family->getXref(), '\', \'M\');" title="', I18N::translate('son'), '"></a>';
|
||
echo ' <a class="icon-sex_f_15x15" href="#" onclick="return add_child_to_family(\'', $family->getXref(), '\', \'F\');" title="', I18N::translate('daughter'), '"></a>';
|
||
echo '<br><br>';
|
||
}
|
||
echo '</td>';
|
||
if ($sosa > 0) {
|
||
echo '<td></td><td></td>';
|
||
}
|
||
echo '</tr>';
|
||
|
||
$nchi = 1;
|
||
if ($children) {
|
||
foreach ($children as $child) {
|
||
echo '<tr>';
|
||
if ($sosa != 0) {
|
||
if ($child->getXref() == $childid) {
|
||
self::printSosaNumber($sosa, $childid);
|
||
} elseif (empty($label)) {
|
||
self::printSosaNumber("");
|
||
} else {
|
||
self::printSosaNumber($label . ($nchi++) . ".");
|
||
}
|
||
}
|
||
if ($child->isPendingAddtion()) {
|
||
echo '<td class="new">';
|
||
} elseif ($child->isPendingDeletion()) {
|
||
echo '<td class="old">';
|
||
} else {
|
||
echo '<td>';
|
||
}
|
||
FunctionsPrint::printPedigreePerson($child, $show_full);
|
||
echo '</td>';
|
||
if ($sosa != 0) {
|
||
// loop for all families where current child is a spouse
|
||
$famids = $child->getSpouseFamilies();
|
||
|
||
$maxfam = count($famids) - 1;
|
||
for ($f = 0; $f <= $maxfam; $f++) {
|
||
$famid_child = $famids[$f]->getXref();
|
||
// multiple marriages
|
||
if ($f > 0) {
|
||
echo '</tr><tr><td></td>';
|
||
echo '<td style="text-align:end; vertical-align: top;">';
|
||
|
||
//find out how many cousins there are to establish vertical line on second families
|
||
$fchildren = $famids[$f]->getChildren();
|
||
$kids = count($fchildren);
|
||
$Pheader = ($bheight - 1) * $kids;
|
||
$PBadj = 6; // default
|
||
if ($show_cousins > 0) {
|
||
if ($kids) {
|
||
$PBadj = max(0, $Pheader / 2 + $kids * 4.5);
|
||
}
|
||
}
|
||
|
||
if ($f == $maxfam) {
|
||
echo '<img height="' . ((($bheight / 2)) + $PBadj) . 'px"';
|
||
} else {
|
||
echo '<img height="' . $pbheight . 'px"';
|
||
}
|
||
echo ' width="3" src="' . Theme::theme()->parameter('image-vline') . '">';
|
||
echo '</td>';
|
||
}
|
||
echo '<td class="details1" style="text-align:center;">';
|
||
$spouse = $famids[$f]->getSpouse($child);
|
||
|
||
$marr = $famids[$f]->getFirstFact('MARR');
|
||
$div = $famids[$f]->getFirstFact('DIV');
|
||
if ($marr) {
|
||
// marriage date
|
||
echo $marr->getDate()->minimumDate()->format('%Y');
|
||
// divorce date
|
||
if ($div) {
|
||
echo '–', $div->getDate()->minimumDate()->format('%Y');
|
||
}
|
||
}
|
||
echo "<br><img width=\"100%\" class=\"line5\" height=\"3\" src=\"" . Theme::theme()->parameter('image-hline') . "\" alt=\"\">";
|
||
echo "</td>";
|
||
// spouse information
|
||
echo "<td style=\"vertical-align: center;";
|
||
if (!empty($divrec)) {
|
||
echo " filter:alpha(opacity=40);opacity:0.4;\">";
|
||
} else {
|
||
echo "\">";
|
||
}
|
||
FunctionsPrint::printPedigreePerson($spouse, $show_full);
|
||
echo "</td>";
|
||
// cousins
|
||
if ($show_cousins) {
|
||
self::printCousins($famid_child, $show_full);
|
||
}
|
||
}
|
||
}
|
||
echo "</tr>";
|
||
}
|
||
} elseif ($sosa < 1) {
|
||
// message 'no children' except for sosa
|
||
if (preg_match('/\n1 NCHI (\d+)/', $family->getGedcom(), $match) && $match[1] == 0) {
|
||
echo '<tr><td><i class="icon-childless"></i> ' . I18N::translate('This family remained childless') . '</td></tr>';
|
||
}
|
||
}
|
||
echo "</table><br>";
|
||
}
|
||
|
||
/**
|
||
* print a family with Sosa-Stradonitz numbering system
|
||
* ($rootid=1, father=2, mother=3 ...)
|
||
*
|
||
* @param string $famid family gedcom ID
|
||
* @param string $childid tree root ID
|
||
* @param int $sosa starting sosa number
|
||
* @param string $label indi label (descendancy booklet)
|
||
* @param string $parid parent ID (descendancy booklet)
|
||
* @param string $gparid gd-parent ID (descendancy booklet)
|
||
* @param int $show_cousins display cousins on chart
|
||
* @param int $show_full large or small box
|
||
*/
|
||
public static function printSosaFamily($famid, $childid, $sosa, $label = '', $parid = '', $gparid = '', $show_cousins = 0, $show_full = 1) {
|
||
global $WT_TREE;
|
||
|
||
echo '<hr>';
|
||
echo '<p style="page-break-before: always;">';
|
||
if (!empty($famid)) {
|
||
echo '<a name="', $famid, '"></a>';
|
||
}
|
||
self::printFamilyParents(Family::getInstance($famid, $WT_TREE), $sosa, $label, $parid, $gparid, $show_full);
|
||
echo '<br>';
|
||
echo '<table><tr><td>';
|
||
self::printFamilyChildren(Family::getInstance($famid, $WT_TREE), $childid, $sosa, $label, $show_cousins, $show_full);
|
||
echo '</td></tr></table>';
|
||
echo '<br>';
|
||
}
|
||
|
||
/**
|
||
* print an arrow to a new url
|
||
*
|
||
* @param string $url target url
|
||
* @param string $label arrow label
|
||
* @param int $dir arrow direction 0=left 1=right 2=up 3=down (default=2)
|
||
*/
|
||
public static function printUrlArrow($url, $label, $dir = 2) {
|
||
if ($url === '') {
|
||
return;
|
||
}
|
||
|
||
// arrow direction
|
||
$adir = $dir;
|
||
if (I18N::direction() === 'rtl' && $dir === 0) {
|
||
$adir = 1;
|
||
}
|
||
if (I18N::direction() === 'rtl' && $dir === 1) {
|
||
$adir = 0;
|
||
}
|
||
|
||
// arrow style 0 1 2 3
|
||
$array_style = array('icon-larrow', 'icon-rarrow', 'icon-uarrow', 'icon-darrow');
|
||
$astyle = $array_style[$adir];
|
||
|
||
// Labels include people’s names, which may contain markup
|
||
echo '<a href="' . $url . '" title="' . strip_tags($label) . '" class="' . $astyle . '"></a>';
|
||
}
|
||
|
||
/**
|
||
* builds and returns sosa relationship name in the active language
|
||
*
|
||
* @param string $sosa sosa number
|
||
*
|
||
* @return string
|
||
*/
|
||
public static function getSosaName($sosa) {
|
||
$path = '';
|
||
while ($sosa > 1) {
|
||
if ($sosa % 2 == 1) {
|
||
$sosa -= 1;
|
||
$path = 'mot' . $path;
|
||
} else {
|
||
$path = 'fat' . $path;
|
||
}
|
||
$sosa /= 2;
|
||
}
|
||
|
||
return Functions::getRelationshipNameFromPath($path, null, null);
|
||
}
|
||
|
||
/**
|
||
* print cousins list
|
||
*
|
||
* @param string $famid family ID
|
||
* @param int $show_full large or small box
|
||
*/
|
||
public static function printCousins($famid, $show_full = 1) {
|
||
global $WT_TREE;
|
||
|
||
if ($show_full) {
|
||
$bheight = Theme::theme()->parameter('chart-box-y');
|
||
} else {
|
||
$bheight = Theme::theme()->parameter('compact-chart-box-y');
|
||
}
|
||
|
||
$family = Family::getInstance($famid, $WT_TREE);
|
||
$fchildren = $family->getChildren();
|
||
|
||
$kids = count($fchildren);
|
||
|
||
echo '<td>';
|
||
if ($kids) {
|
||
echo '<table cellspacing="0" cellpadding="0" border="0" ><tr>';
|
||
if ($kids > 1) {
|
||
echo '<td rowspan="', $kids, '"><img width="3px" height="', (($bheight + 9) * ($kids - 1)), 'px" src="', Theme::theme()->parameter('image-vline'), '"></td>';
|
||
}
|
||
$ctkids = count($fchildren);
|
||
$i = 1;
|
||
foreach ($fchildren as $fchil) {
|
||
if ($i == 1) {
|
||
echo '<td><img width="10px" height="3px" style="vertical-align:top"';
|
||
} else {
|
||
echo '<td><img width="10px" height="3px"';
|
||
}
|
||
if (I18N::direction() === 'ltr') {
|
||
echo ' style="padding-right: 2px;"';
|
||
} else {
|
||
echo ' style="padding-left: 2px;"';
|
||
}
|
||
echo ' src="', Theme::theme()->parameter('image-hline'), '"></td><td>';
|
||
FunctionsPrint::printPedigreePerson($fchil, $show_full);
|
||
echo '</td></tr>';
|
||
if ($i < $ctkids) {
|
||
echo '<tr>';
|
||
$i++;
|
||
}
|
||
}
|
||
echo '</table>';
|
||
} else {
|
||
// If there is known that there are no children (as opposed to no known children)
|
||
if (preg_match('/\n1 NCHI (\d+)/', $family->getGedcom(), $match) && $match[1] == 0) {
|
||
echo ' <i class="icon-childless" title="', I18N::translate('This family remained childless'), '"></i>';
|
||
}
|
||
}
|
||
echo '</td>';
|
||
}
|
||
}
|