.
*/
namespace Fisharebest\Webtrees\Controller;
use Fisharebest\Webtrees\Filter;
use Fisharebest\Webtrees\Functions\FunctionsPrint;
use Fisharebest\Webtrees\I18N;
use Fisharebest\Webtrees\Individual;
use Fisharebest\Webtrees\Theme;
/**
* Controller for the familybook chart
*/
class FamilyBookController extends ChartController {
/** @var int Whether to show spouse details */
public $show_spouse;
/** @var int Number of descendancy generations to show */
public $descent;
/** @var int Number of ascendancy generations to show */
public $generations;
/** @var int Number of descendancy generations that exist */
private $dgenerations;
/** @var int Half height of personbox */
public $bhalfheight;
/**
* Create a family-book controller
*/
public function __construct() {
global $WT_TREE;
parent::__construct();
// Extract the request parameters
$this->show_spouse = Filter::getInteger('show_spouse', 0, 1);
$this->descent = Filter::getInteger('descent', 0, 9, 5);
$this->generations = Filter::getInteger('generations', 2, $WT_TREE->getPreference('MAX_DESCENDANCY_GENERATIONS'), 2);
$this->bhalfheight = $this->getBoxDimensions()->height / 2;
if ($this->root && $this->root->canShowName()) {
$this->setPageTitle(
/* I18N: %s is an individual’s name */
I18N::translate('Family book of %s', $this->root->getFullName())
);
} else {
$this->setPageTitle(I18N::translate('Family book'));
}
//Checks how many generations of descendency is for the person for formatting purposes
$this->dgenerations = $this->maxDescendencyGenerations($this->root->getXref(), 0);
if ($this->dgenerations < 1) {
$this->dgenerations = 1;
}
}
/**
* Prints descendency of passed in person
*
* @param Individual|null $person
* @param int $generation
*
* @return int
*/
private function printDescendency(Individual $person = null, $generation) {
if ($generation > $this->dgenerations) {
return 0;
}
echo '
';
$numkids = 0;
// Load children
$children = array();
if ($person) {
// Count is position from center to left, dgenerations is number of generations
if ($generation < $this->dgenerations) {
// All children, from all partners
foreach ($person->getSpouseFamilies() as $family) {
foreach ($family->getChildren() as $child) {
$children[] = $child;
}
}
}
}
if ($generation < $this->dgenerations) {
if ($children) {
// real people
echo '';
foreach ($children as $i => $child) {
echo '';
$kids = $this->printDescendency($child, $generation + 1);
$numkids += $kids;
echo ' | ';
// Print the lines
if (count($children) > 1) {
if ($i === 0) {
// Adjust for the first column on left
$h = round(((($this->getBoxDimensions()->height) * $kids) + 8) / 2); // Assumes border = 1 and padding = 3
// Adjust for other vertical columns
if ($kids > 1) {
$h = ($kids - 1) * 4 + $h;
}
echo '',
'->parameter('image-vline'), ') | ';
} elseif ($i === count($children) - 1) {
// Adjust for the first column on left
$h = round(((($this->getBoxDimensions()->height) * $kids) + 8) / 2);
// Adjust for other vertical columns
if ($kids > 1) {
$h = ($kids - 1) * 4 + $h;
}
echo '',
'->parameter('image-vline'), ') | ';
} else {
echo '',
'->parameter('image-spacer'), ') | ';
}
}
echo ' ';
}
echo ' ';
} else {
// Hidden/empty boxes - to preserve the layout
echo '';
$numkids += $this->printDescendency(null, $generation + 1);
echo ' | ';
}
echo ' | ';
echo '';
}
if ($numkids === 0) {
$numkids = 1;
}
echo '';
if ($person) {
FunctionsPrint::printPedigreePerson($person, $this->showFull());
echo ' | ',
' ';
} else {
echo '',
' | ';
}
// Print the spouse
if ($generation === 1) {
if ($this->show_spouse) {
foreach ($person->getSpouseFamilies() as $family) {
$spouse = $family->getSpouse($person);
echo ' | ';
FunctionsPrint::printPedigreePerson($spouse, $this->showFull());
$numkids += 0.95;
echo ' | ';
}
}
}
echo ' | ';
echo ' |
';
echo '
';
return $numkids;
}
/**
* Prints pedigree of the person passed in
*
* @param Individual $person
* @param int $count
*/
private function printPersonPedigree($person, $count) {
if ($count >= $this->generations) {
return;
}
$genoffset = $this->generations; // handle pedigree n generations lines
//-- calculate how tall the lines should be
$lh = ($this->bhalfheight + 4) * pow(2, ($genoffset - $count - 1));
//
//Prints empty table columns for children w/o parents up to the max generation
//This allows vertical line spacing to be consistent
if (count($person->getChildFamilies()) == 0) {
echo '';
$this->printEmptyBox($this->getBoxDimensions()->width, $this->getBoxDimensions()->height);
//-- recursively get the father’s family
$this->printPersonPedigree($person, $count + 1);
echo '';
$this->printEmptyBox($this->getBoxDimensions()->width, $this->getBoxDimensions()->height);
//-- recursively get the mother’s family
$this->printPersonPedigree($person, $count + 1);
echo ' | |
';
}
// Empty box section done, now for regular pedigree
foreach ($person->getChildFamilies() as $family) {
echo '';
// Determine line height for two or more spouces
// And then adjust the vertical line for the root person only
$famcount = 0;
if ($this->show_spouse) {
// count number of spouses
$famcount += count($person->getSpouseFamilies());
}
$savlh = $lh; // Save current line height
if ($count == 1 && $genoffset <= $famcount) {
$linefactor = 0;
// genoffset of 2 needs no adjustment
if ($genoffset > 2) {
$tblheight = $this->getBoxDimensions()->height + 8;
if ($genoffset == 3) {
if ($famcount == 3) {
$linefactor = $tblheight / 2;
} elseif ($famcount > 3) {
$linefactor = $tblheight;
}
}
if ($genoffset == 4) {
if ($famcount == 4) {
$linefactor = $tblheight;
} elseif ($famcount > 4) {
$linefactor = ($famcount - $genoffset) * ($tblheight * 1.5);
}
}
if ($genoffset == 5) {
if ($famcount == 5) {
$linefactor = 0;
} elseif ($famcount > 5) {
$linefactor = $tblheight * ($famcount - $genoffset);
}
}
}
$lh = (($famcount - 1) * ($this->getBoxDimensions()->height + 8) - ($linefactor));
if ($genoffset > 5) {
$lh = $savlh;
}
}
echo '->parameter('image-vline'), ') | ',
'',
'->parameter('image-hline'), ') | ',
'';
$lh = $savlh; // restore original line height
//-- print the father box
FunctionsPrint::printPedigreePerson($family->getHusband(), $this->showFull());
echo ' | ';
if ($family->getHusband()) {
echo '';
//-- recursively get the father’s family
$this->printPersonPedigree($family->getHusband(), $count + 1);
echo ' | ';
} else {
echo '';
if ($genoffset > $count) {
echo '';
for ($i = 1; $i < (pow(2, ($genoffset) - $count) / 2); $i++) {
$this->printEmptyBox($this->getBoxDimensions()->width, $this->getBoxDimensions()->height);
echo '';
}
echo ' ';
}
}
echo ' |
',
'->parameter('image-vline'), ') | ',
'->parameter('image-hline'), ') | ',
'';
//-- print the mother box
FunctionsPrint::printPedigreePerson($family->getWife(), $this->showFull());
echo ' | ';
if ($family->getWife()) {
echo '';
//-- recursively print the mother’s family
$this->printPersonPedigree($family->getWife(), $count + 1);
echo ' | ';
} else {
echo '';
if ($count < $genoffset - 1) {
echo '';
for ($i = 1; $i < (pow(2, ($genoffset - 1) - $count) / 2) + 1; $i++) {
$this->printEmptyBox();
echo '';
$this->printEmptyBox();
echo '';
}
echo ' ';
}
}
echo ' |
',
'
';
break;
}
}
/**
* Calculates number of generations a person has
*
* @param string $pid
* @param int $depth
*
* @return int
*/
private function maxDescendencyGenerations($pid, $depth) {
global $WT_TREE;
if ($depth > $this->generations) {
return $depth;
}
$person = Individual::getInstance($pid, $WT_TREE);
if (is_null($person)) {
return $depth;
}
$maxdc = $depth;
foreach ($person->getSpouseFamilies() as $family) {
foreach ($family->getChildren() as $child) {
$dc = $this->maxDescendencyGenerations($child->getXref(), $depth + 1);
if ($dc >= $this->generations) {
return $dc;
}
if ($dc > $maxdc) {
$maxdc = $dc;
}
}
}
$maxdc++;
if ($maxdc == 1) {
$maxdc++;
}
return $maxdc;
}
/**
* Print empty box
*/
private function printEmptyBox() {
echo $this->showFull() ? Theme::theme()->individualBoxEmpty() : Theme::theme()->individualBoxSmallEmpty();
}
/**
* Print a “Family Book” for an individual
*
* @param Individual $person
* @param int $descent_steps
*/
public function printFamilyBook(Individual $person, $descent_steps) {
if ($descent_steps == 0 || !$person->canShowName()) {
return;
}
$families = $person->getSpouseFamilies();
if ($families) {
echo
'',
/* I18N: A title/heading. %s is an individual’s name */ I18N::translate('Family of %s', $person->getFullName()),
'
',
'';
$this->dgenerations = $this->generations;
$this->printDescendency($person, 1);
echo ' | ';
$this->printPersonPedigree($person, 1);
echo ' |
';
foreach ($families as $family) {
foreach ($family->getChildren() as $child) {
$this->printFamilyBook($child, $descent_steps - 1);
}
}
}
}
}