1168ff6f3Sric2016<?php 2168ff6f3Sric2016/** 3168ff6f3Sric2016 * webtrees: online genealogy 48fcd0d32SGreg Roach * Copyright (C) 2019 webtrees development team 5168ff6f3Sric2016 * This program is free software: you can redistribute it and/or modify 6168ff6f3Sric2016 * it under the terms of the GNU General Public License as published by 7168ff6f3Sric2016 * the Free Software Foundation, either version 3 of the License, or 8168ff6f3Sric2016 * (at your option) any later version. 9168ff6f3Sric2016 * This program is distributed in the hope that it will be useful, 10168ff6f3Sric2016 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11168ff6f3Sric2016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12168ff6f3Sric2016 * GNU General Public License for more details. 13168ff6f3Sric2016 * You should have received a copy of the GNU General Public License 14168ff6f3Sric2016 * along with this program. If not, see <http://www.gnu.org/licenses/>. 15168ff6f3Sric2016 */ 16e7f56f2aSGreg Roachdeclare(strict_types=1); 17e7f56f2aSGreg Roach 18168ff6f3Sric2016namespace Fisharebest\Webtrees\Module; 19168ff6f3Sric2016 2054452b04SGreg Roachuse Fisharebest\Webtrees\Auth; 21*e5a6b4d4SGreg Roachuse Fisharebest\Webtrees\Contracts\UserInterface; 2254452b04SGreg Roachuse Fisharebest\Webtrees\Family; 2354452b04SGreg Roachuse Fisharebest\Webtrees\FontAwesome; 2454452b04SGreg Roachuse Fisharebest\Webtrees\Functions\FunctionsCharts; 2554452b04SGreg Roachuse Fisharebest\Webtrees\Functions\FunctionsPrint; 2654452b04SGreg Roachuse Fisharebest\Webtrees\Gedcom; 2754452b04SGreg Roachuse Fisharebest\Webtrees\GedcomTag; 28168ff6f3Sric2016use Fisharebest\Webtrees\I18N; 29168ff6f3Sric2016use Fisharebest\Webtrees\Individual; 30e46b0479SScrutinizer Auto-Fixeruse Fisharebest\Webtrees\Menu; 3154452b04SGreg Roachuse Fisharebest\Webtrees\Services\ChartService; 3254452b04SGreg Roachuse Fisharebest\Webtrees\Tree; 3354452b04SGreg Roachuse Illuminate\Support\Collection; 3454452b04SGreg Roachuse Ramsey\Uuid\Uuid; 3554452b04SGreg Roachuse Symfony\Component\HttpFoundation\Request; 3654452b04SGreg Roachuse Symfony\Component\HttpFoundation\Response; 37168ff6f3Sric2016 38168ff6f3Sric2016/** 39168ff6f3Sric2016 * Class DescendancyChartModule 40168ff6f3Sric2016 */ 4137eb8894SGreg Roachclass DescendancyChartModule extends AbstractModule implements ModuleChartInterface 42c1010edaSGreg Roach{ 4349a243cbSGreg Roach use ModuleChartTrait; 4449a243cbSGreg Roach 4554452b04SGreg Roach // Chart styles 46677aaceaSGreg Roach public const CHART_STYLE_LIST = 0; 47677aaceaSGreg Roach public const CHART_STYLE_BOOKLET = 1; 48677aaceaSGreg Roach public const CHART_STYLE_INDIVIDUALS = 2; 49677aaceaSGreg Roach public const CHART_STYLE_FAMILIES = 3; 5054452b04SGreg Roach 5154452b04SGreg Roach // Defaults 52677aaceaSGreg Roach public const DEFAULT_STYLE = self::CHART_STYLE_LIST; 53677aaceaSGreg Roach public const DEFAULT_GENERATIONS = '3'; 54677aaceaSGreg Roach public const DEFAULT_MAXIMUM_GENERATIONS = '9'; 5554452b04SGreg Roach 5654452b04SGreg Roach /** @var int[] */ 5754452b04SGreg Roach protected $dabo_num = []; 5854452b04SGreg Roach 5954452b04SGreg Roach /** @var string[] */ 6054452b04SGreg Roach protected $dabo_sex = []; 6154452b04SGreg Roach 62168ff6f3Sric2016 /** 63168ff6f3Sric2016 * How should this module be labelled on tabs, menus, etc.? 64168ff6f3Sric2016 * 65168ff6f3Sric2016 * @return string 66168ff6f3Sric2016 */ 6749a243cbSGreg Roach public function title(): string 68c1010edaSGreg Roach { 69bbb76c12SGreg Roach /* I18N: Name of a module/chart */ 70bbb76c12SGreg Roach return I18N::translate('Descendants'); 71168ff6f3Sric2016 } 72168ff6f3Sric2016 73168ff6f3Sric2016 /** 74168ff6f3Sric2016 * A sentence describing what this module does. 75168ff6f3Sric2016 * 76168ff6f3Sric2016 * @return string 77168ff6f3Sric2016 */ 7849a243cbSGreg Roach public function description(): string 79c1010edaSGreg Roach { 80bbb76c12SGreg Roach /* I18N: Description of the “DescendancyChart” module */ 81bbb76c12SGreg Roach return I18N::translate('A chart of an individual’s descendants.'); 82168ff6f3Sric2016 } 83168ff6f3Sric2016 84168ff6f3Sric2016 /** 85377a2979SGreg Roach * CSS class for the URL. 86377a2979SGreg Roach * 87377a2979SGreg Roach * @return string 88377a2979SGreg Roach */ 89377a2979SGreg Roach public function chartMenuClass(): string 90377a2979SGreg Roach { 91377a2979SGreg Roach return 'menu-chart-descendants'; 92377a2979SGreg Roach } 93377a2979SGreg Roach 94377a2979SGreg Roach /** 954eb71cfaSGreg Roach * Return a menu item for this chart - for use in individual boxes. 964eb71cfaSGreg Roach * 9760bc3e3fSGreg Roach * @param Individual $individual 9860bc3e3fSGreg Roach * 994eb71cfaSGreg Roach * @return Menu|null 1004eb71cfaSGreg Roach */ 101377a2979SGreg Roach public function chartBoxMenu(Individual $individual): ?Menu 102c1010edaSGreg Roach { 103e6562982SGreg Roach return $this->chartMenu($individual); 104e6562982SGreg Roach } 105e6562982SGreg Roach 106e6562982SGreg Roach /** 107e6562982SGreg Roach * The title for a specific instance of this chart. 108e6562982SGreg Roach * 109e6562982SGreg Roach * @param Individual $individual 110e6562982SGreg Roach * 111e6562982SGreg Roach * @return string 112e6562982SGreg Roach */ 113e6562982SGreg Roach public function chartTitle(Individual $individual): string 114e6562982SGreg Roach { 115e6562982SGreg Roach /* I18N: %s is an individual’s name */ 116e6562982SGreg Roach return I18N::translate('Descendants of %s', $individual->getFullName()); 117e6562982SGreg Roach } 118e6562982SGreg Roach 119e6562982SGreg Roach /** 12054452b04SGreg Roach * A form to request the chart parameters. 12154452b04SGreg Roach * 12254452b04SGreg Roach * @param Request $request 12354452b04SGreg Roach * @param Tree $tree 124*e5a6b4d4SGreg Roach * @param UserInterface $user 12554452b04SGreg Roach * @param ChartService $chart_service 12654452b04SGreg Roach * 12754452b04SGreg Roach * @return Response 12854452b04SGreg Roach */ 129*e5a6b4d4SGreg Roach public function getChartAction(Request $request, Tree $tree, UserInterface $user, ChartService $chart_service): Response 13054452b04SGreg Roach { 1319b5537c3SGreg Roach $ajax = (bool) $request->get('ajax'); 13254452b04SGreg Roach $xref = $request->get('xref', ''); 13354452b04SGreg Roach $individual = Individual::getInstance($xref, $tree); 13454452b04SGreg Roach 13554452b04SGreg Roach Auth::checkIndividualAccess($individual); 1369867b2f0SGreg Roach Auth::checkComponentAccess($this, 'chart', $tree, $user); 13754452b04SGreg Roach 13854452b04SGreg Roach $minimum_generations = 2; 13954452b04SGreg Roach $maximum_generations = (int) $tree->getPreference('MAX_DESCENDANCY_GENERATIONS', self::DEFAULT_MAXIMUM_GENERATIONS); 14054452b04SGreg Roach $default_generations = (int) $tree->getPreference('DEFAULT_PEDIGREE_GENERATIONS', self::DEFAULT_GENERATIONS); 14154452b04SGreg Roach 14254452b04SGreg Roach $chart_style = (int) $request->get('chart_style', self::DEFAULT_STYLE); 14354452b04SGreg Roach $generations = (int) $request->get('generations', $default_generations); 14454452b04SGreg Roach 14554452b04SGreg Roach $generations = min($generations, $maximum_generations); 14654452b04SGreg Roach $generations = max($generations, $minimum_generations); 14754452b04SGreg Roach 1489b5537c3SGreg Roach if ($ajax) { 14954452b04SGreg Roach return $this->chart($request, $tree, $chart_service); 15054452b04SGreg Roach } 15154452b04SGreg Roach 15254452b04SGreg Roach $ajax_url = $this->chartUrl($individual, [ 15354452b04SGreg Roach 'chart_style' => $chart_style, 15454452b04SGreg Roach 'generations' => $generations, 1559b5537c3SGreg Roach 'ajax' => true, 15654452b04SGreg Roach ]); 15754452b04SGreg Roach 1589b5537c3SGreg Roach return $this->viewResponse('modules/descendancy_chart/page', [ 15954452b04SGreg Roach 'ajax_url' => $ajax_url, 16054452b04SGreg Roach 'chart_style' => $chart_style, 16154452b04SGreg Roach 'chart_styles' => $this->chartStyles(), 16254452b04SGreg Roach 'default_generations' => $default_generations, 16354452b04SGreg Roach 'generations' => $generations, 16454452b04SGreg Roach 'individual' => $individual, 16554452b04SGreg Roach 'maximum_generations' => $maximum_generations, 16654452b04SGreg Roach 'minimum_generations' => $minimum_generations, 16726684e68SGreg Roach 'module_name' => $this->name(), 16854452b04SGreg Roach 'title' => $this->chartTitle($individual), 16954452b04SGreg Roach ]); 17054452b04SGreg Roach } 17154452b04SGreg Roach 17254452b04SGreg Roach /** 17354452b04SGreg Roach * @param Request $request 17454452b04SGreg Roach * @param Tree $tree 17554452b04SGreg Roach * @param ChartService $chart_service 17654452b04SGreg Roach * 17754452b04SGreg Roach * @return Response 17854452b04SGreg Roach */ 17954452b04SGreg Roach public function chart(Request $request, Tree $tree, ChartService $chart_service): Response 18054452b04SGreg Roach { 18154452b04SGreg Roach $this->layout = 'layouts/ajax'; 18254452b04SGreg Roach 18354452b04SGreg Roach $xref = $request->get('xref', ''); 18454452b04SGreg Roach $individual = Individual::getInstance($xref, $tree); 18554452b04SGreg Roach 18654452b04SGreg Roach Auth::checkIndividualAccess($individual); 18754452b04SGreg Roach 18854452b04SGreg Roach $minimum_generations = 2; 18954452b04SGreg Roach $maximum_generations = (int) $tree->getPreference('MAX_PEDIGREE_GENERATIONS', self::DEFAULT_MAXIMUM_GENERATIONS); 19054452b04SGreg Roach $default_generations = (int) $tree->getPreference('DEFAULT_PEDIGREE_GENERATIONS', self::DEFAULT_GENERATIONS); 19154452b04SGreg Roach 19254452b04SGreg Roach $chart_style = (int) $request->get('chart_style', self::DEFAULT_STYLE); 19354452b04SGreg Roach $generations = (int) $request->get('generations', $default_generations); 19454452b04SGreg Roach 19554452b04SGreg Roach $generations = min($generations, $maximum_generations); 19654452b04SGreg Roach $generations = max($generations, $minimum_generations); 19754452b04SGreg Roach 19854452b04SGreg Roach switch ($chart_style) { 19954452b04SGreg Roach case self::CHART_STYLE_LIST: 20054452b04SGreg Roach default: 20154452b04SGreg Roach return $this->descendantsList($individual, $generations); 20254452b04SGreg Roach 20354452b04SGreg Roach case self::CHART_STYLE_BOOKLET: 20454452b04SGreg Roach return $this->descendantsBooklet($individual, $generations); 20554452b04SGreg Roach 20654452b04SGreg Roach case self::CHART_STYLE_INDIVIDUALS: 20754452b04SGreg Roach $individuals = $chart_service->descendants($individual, $generations - 1); 20854452b04SGreg Roach 20954452b04SGreg Roach return $this->descendantsIndividuals($tree, $individuals); 21054452b04SGreg Roach 21154452b04SGreg Roach case self::CHART_STYLE_FAMILIES: 21254452b04SGreg Roach $families = $chart_service->descendantFamilies($individual, $generations - 1); 21354452b04SGreg Roach 21454452b04SGreg Roach return $this->descendantsFamilies($tree, $families); 21554452b04SGreg Roach } 21654452b04SGreg Roach } 21754452b04SGreg Roach 21854452b04SGreg Roach /** 21954452b04SGreg Roach * Show a hierarchical list of descendants 22054452b04SGreg Roach * 22154452b04SGreg Roach * @TODO replace ob_start() with views. 222e6562982SGreg Roach * 223e6562982SGreg Roach * @param Individual $individual 22454452b04SGreg Roach * @param int $generations 225e6562982SGreg Roach * 22654452b04SGreg Roach * @return Response 227e6562982SGreg Roach */ 22854452b04SGreg Roach private function descendantsList(Individual $individual, int $generations): Response 229e6562982SGreg Roach { 23054452b04SGreg Roach ob_start(); 23154452b04SGreg Roach 23254452b04SGreg Roach echo '<ul class="chart_common">'; 23354452b04SGreg Roach $this->printChildDescendancy($individual, $generations, $generations); 23454452b04SGreg Roach echo '</ul>'; 23554452b04SGreg Roach 23654452b04SGreg Roach $html = ob_get_clean(); 23754452b04SGreg Roach 23854452b04SGreg Roach return new Response($html); 23954452b04SGreg Roach } 24054452b04SGreg Roach 24154452b04SGreg Roach /** 24254452b04SGreg Roach * print a child descendancy 24354452b04SGreg Roach * 24454452b04SGreg Roach * @param Individual $person 24554452b04SGreg Roach * @param int $depth the descendancy depth to show 24654452b04SGreg Roach * @param int $generations 24754452b04SGreg Roach * 24854452b04SGreg Roach * @return void 24954452b04SGreg Roach */ 25054452b04SGreg Roach private function printChildDescendancy(Individual $person, $depth, int $generations) 25154452b04SGreg Roach { 25254452b04SGreg Roach echo '<li>'; 25354452b04SGreg Roach echo '<table><tr><td>'; 25454452b04SGreg Roach if ($depth == $generations) { 2558136679eSGreg Roach echo '<img alt="" role="presentation" src="' . app()->make(ModuleThemeInterface::class)->parameter('image-spacer') . '" height="3" width="15"></td><td>'; 25654452b04SGreg Roach } else { 2578136679eSGreg Roach echo '<img src="' . app()->make(ModuleThemeInterface::class)->parameter('image-spacer') . '" height="3" width="3">'; 2588136679eSGreg Roach echo '<img src="' . app()->make(ModuleThemeInterface::class)->parameter('image-hline') . '" height="3" width="', 12, '"></td><td>'; 25954452b04SGreg Roach } 26054452b04SGreg Roach echo FunctionsPrint::printPedigreePerson($person); 26154452b04SGreg Roach echo '</td>'; 26254452b04SGreg Roach 26354452b04SGreg Roach // check if child has parents and add an arrow 26454452b04SGreg Roach echo '<td></td>'; 26554452b04SGreg Roach echo '<td>'; 26654452b04SGreg Roach foreach ($person->getChildFamilies() as $cfamily) { 26754452b04SGreg Roach foreach ($cfamily->getSpouses() as $parent) { 268*e5a6b4d4SGreg Roach echo FontAwesome::linkIcon('arrow-up', I18N::translate('Start at parents'), [ 269*e5a6b4d4SGreg Roach 'href' => route('descendants', [ 270*e5a6b4d4SGreg Roach 'ged' => $parent->tree()->name(), 27154452b04SGreg Roach 'xref' => $parent->xref(), 27254452b04SGreg Roach 'generations' => $generations, 27354452b04SGreg Roach ]), 27454452b04SGreg Roach ]); 27554452b04SGreg Roach // only show the arrow for one of the parents 27654452b04SGreg Roach break; 27754452b04SGreg Roach } 27854452b04SGreg Roach } 27954452b04SGreg Roach 28054452b04SGreg Roach // d'Aboville child number 28154452b04SGreg Roach $level = $generations - $depth; 28254452b04SGreg Roach echo '<br><br> '; 28354452b04SGreg Roach echo '<span dir="ltr">'; //needed so that RTL languages will display this properly 28454452b04SGreg Roach if (!isset($this->dabo_num[$level])) { 28554452b04SGreg Roach $this->dabo_num[$level] = 0; 28654452b04SGreg Roach } 28754452b04SGreg Roach $this->dabo_num[$level]++; 28854452b04SGreg Roach $this->dabo_num[$level + 1] = 0; 28954452b04SGreg Roach $this->dabo_sex[$level] = $person->getSex(); 29054452b04SGreg Roach for ($i = 0; $i <= $level; $i++) { 29154452b04SGreg Roach $isf = $this->dabo_sex[$i]; 29254452b04SGreg Roach if ($isf === 'M') { 29354452b04SGreg Roach $isf = ''; 29454452b04SGreg Roach } 29554452b04SGreg Roach if ($isf === 'U') { 29654452b04SGreg Roach $isf = 'NN'; 29754452b04SGreg Roach } 29854452b04SGreg Roach echo '<span class="person_box' . $isf . '"> ' . $this->dabo_num[$i] . ' </span>'; 29954452b04SGreg Roach if ($i < $level) { 30054452b04SGreg Roach echo '.'; 30154452b04SGreg Roach } 30254452b04SGreg Roach } 30354452b04SGreg Roach echo '</span>'; 30454452b04SGreg Roach echo '</td></tr>'; 30554452b04SGreg Roach echo '</table>'; 30654452b04SGreg Roach echo '</li>'; 30754452b04SGreg Roach 30854452b04SGreg Roach // loop for each spouse 30954452b04SGreg Roach foreach ($person->getSpouseFamilies() as $family) { 31054452b04SGreg Roach $this->printFamilyDescendancy($person, $family, $depth, $generations); 31154452b04SGreg Roach } 31254452b04SGreg Roach } 31354452b04SGreg Roach 31454452b04SGreg Roach /** 31554452b04SGreg Roach * print a family descendancy 31654452b04SGreg Roach * 31754452b04SGreg Roach * @param Individual $person 31854452b04SGreg Roach * @param Family $family 31954452b04SGreg Roach * @param int $depth the descendancy depth to show 32054452b04SGreg Roach * @param int $generations 32154452b04SGreg Roach * 32254452b04SGreg Roach * @return void 32354452b04SGreg Roach */ 32454452b04SGreg Roach private function printFamilyDescendancy(Individual $person, Family $family, int $depth, int $generations) 32554452b04SGreg Roach { 32654452b04SGreg Roach $uid = Uuid::uuid4()->toString(); // create a unique ID 32754452b04SGreg Roach // print marriage info 32854452b04SGreg Roach echo '<li>'; 3298136679eSGreg Roach echo '<img src="', app()->make(ModuleThemeInterface::class)->parameter('image-spacer'), '" height="2" width="', 19, '">'; 33054452b04SGreg Roach echo '<span class="details1">'; 33154452b04SGreg Roach echo '<a href="#" onclick="expand_layer(\'' . $uid . '\'); return false;" class="top"><i id="' . $uid . '_img" class="icon-minus" title="' . I18N::translate('View this family') . '"></i></a>'; 33254452b04SGreg Roach if ($family->canShow()) { 33354452b04SGreg Roach foreach ($family->facts(Gedcom::MARRIAGE_EVENTS) as $fact) { 33454452b04SGreg Roach echo ' <a href="', e($family->url()), '" class="details1">', $fact->summary(), '</a>'; 33554452b04SGreg Roach } 33654452b04SGreg Roach } 33754452b04SGreg Roach echo '</span>'; 33854452b04SGreg Roach 33954452b04SGreg Roach // print spouse 34054452b04SGreg Roach $spouse = $family->getSpouse($person); 34154452b04SGreg Roach echo '<ul class="generations" id="' . $uid . '">'; 34254452b04SGreg Roach echo '<li>'; 34354452b04SGreg Roach echo '<table><tr><td>'; 34454452b04SGreg Roach echo FunctionsPrint::printPedigreePerson($spouse); 34554452b04SGreg Roach echo '</td>'; 34654452b04SGreg Roach 34754452b04SGreg Roach // check if spouse has parents and add an arrow 34854452b04SGreg Roach echo '<td></td>'; 34954452b04SGreg Roach echo '<td>'; 35054452b04SGreg Roach if ($spouse) { 35154452b04SGreg Roach foreach ($spouse->getChildFamilies() as $cfamily) { 35254452b04SGreg Roach foreach ($cfamily->getSpouses() as $parent) { 353*e5a6b4d4SGreg Roach echo FontAwesome::linkIcon('arrow-up', I18N::translate('Start at parents'), [ 354*e5a6b4d4SGreg Roach 'href' => route('descendants', [ 355*e5a6b4d4SGreg Roach 'ged' => $parent->tree()->name(), 35654452b04SGreg Roach 'xref' => $parent->xref(), 35754452b04SGreg Roach 'generations' => $generations, 35854452b04SGreg Roach ]), 35954452b04SGreg Roach ]); 36054452b04SGreg Roach // only show the arrow for one of the parents 36154452b04SGreg Roach break; 36254452b04SGreg Roach } 36354452b04SGreg Roach } 36454452b04SGreg Roach } 36554452b04SGreg Roach echo '<br><br> '; 36654452b04SGreg Roach echo '</td></tr>'; 36754452b04SGreg Roach 36854452b04SGreg Roach // children 36954452b04SGreg Roach $children = $family->getChildren(); 37054452b04SGreg Roach echo '<tr><td colspan="3" class="details1" > '; 37154452b04SGreg Roach if (!empty($children)) { 37254452b04SGreg Roach echo GedcomTag::getLabel('NCHI') . ': ' . count($children); 37354452b04SGreg Roach } else { 37454452b04SGreg Roach // Distinguish between no children (NCHI 0) and no recorded 37554452b04SGreg Roach // children (no CHIL records) 37654452b04SGreg Roach if (strpos($family->gedcom(), '\n1 NCHI 0') !== false) { 37754452b04SGreg Roach echo GedcomTag::getLabel('NCHI') . ': ' . count($children); 37854452b04SGreg Roach } else { 37954452b04SGreg Roach echo I18N::translate('No children'); 38054452b04SGreg Roach } 38154452b04SGreg Roach } 38254452b04SGreg Roach echo '</td></tr></table>'; 38354452b04SGreg Roach echo '</li>'; 38454452b04SGreg Roach if ($depth > 1) { 38554452b04SGreg Roach foreach ($children as $child) { 38654452b04SGreg Roach $this->printChildDescendancy($child, $depth - 1, $generations); 38754452b04SGreg Roach } 38854452b04SGreg Roach } 38954452b04SGreg Roach echo '</ul>'; 39054452b04SGreg Roach echo '</li>'; 39154452b04SGreg Roach } 39254452b04SGreg Roach 39354452b04SGreg Roach /** 39454452b04SGreg Roach * Show a tabular list of individual descendants. 39554452b04SGreg Roach * 39654452b04SGreg Roach * @param Tree $tree 39754452b04SGreg Roach * @param Collection $individuals 39854452b04SGreg Roach * 39954452b04SGreg Roach * @return Response 40054452b04SGreg Roach */ 40154452b04SGreg Roach private function descendantsIndividuals(Tree $tree, Collection $individuals): Response 40254452b04SGreg Roach { 40354452b04SGreg Roach $this->layout = 'layouts/ajax'; 40454452b04SGreg Roach 40554452b04SGreg Roach return $this->viewResponse('lists/individuals-table', [ 40654452b04SGreg Roach 'individuals' => $individuals, 40754452b04SGreg Roach 'sosa' => false, 40854452b04SGreg Roach 'tree' => $tree, 40954452b04SGreg Roach ]); 41054452b04SGreg Roach } 41154452b04SGreg Roach 41254452b04SGreg Roach /** 41354452b04SGreg Roach * Show a tabular list of individual descendants. 41454452b04SGreg Roach * 41554452b04SGreg Roach * @param Tree $tree 41654452b04SGreg Roach * @param Collection $families 41754452b04SGreg Roach * 41854452b04SGreg Roach * @return Response 41954452b04SGreg Roach */ 42054452b04SGreg Roach private function descendantsFamilies(Tree $tree, Collection $families): Response 42154452b04SGreg Roach { 42254452b04SGreg Roach $this->layout = 'layouts/ajax'; 42354452b04SGreg Roach 42454452b04SGreg Roach return $this->viewResponse('lists/families-table', [ 42554452b04SGreg Roach 'families' => $families, 42654452b04SGreg Roach 'tree' => $tree, 42754452b04SGreg Roach ]); 42854452b04SGreg Roach } 42954452b04SGreg Roach 43054452b04SGreg Roach /** 43154452b04SGreg Roach * Show a booklet view of descendants 43254452b04SGreg Roach * 43354452b04SGreg Roach * @TODO replace ob_start() with views. 43454452b04SGreg Roach * 43554452b04SGreg Roach * @param Individual $individual 43654452b04SGreg Roach * @param int $generations 43754452b04SGreg Roach * 43854452b04SGreg Roach * @return Response 43954452b04SGreg Roach */ 44054452b04SGreg Roach private function descendantsBooklet(Individual $individual, int $generations): Response 44154452b04SGreg Roach { 44254452b04SGreg Roach ob_start(); 44354452b04SGreg Roach 44454452b04SGreg Roach $this->printChildFamily($individual, $generations); 44554452b04SGreg Roach 44654452b04SGreg Roach $html = ob_get_clean(); 44754452b04SGreg Roach 44854452b04SGreg Roach return new Response($html); 44954452b04SGreg Roach } 45054452b04SGreg Roach 45154452b04SGreg Roach /** 45254452b04SGreg Roach * Print a child family 45354452b04SGreg Roach * 45454452b04SGreg Roach * @param Individual $individual 45554452b04SGreg Roach * @param int $depth - the descendancy depth to show 45654452b04SGreg Roach * @param string $daboville - d'Aboville number 45754452b04SGreg Roach * @param string $gpid 45854452b04SGreg Roach * 45954452b04SGreg Roach * @return void 46054452b04SGreg Roach */ 46154452b04SGreg Roach private function printChildFamily(Individual $individual, $depth, $daboville = '1.', $gpid = '') 46254452b04SGreg Roach { 46354452b04SGreg Roach if ($depth < 2) { 46454452b04SGreg Roach return; 46554452b04SGreg Roach } 46654452b04SGreg Roach 46754452b04SGreg Roach $i = 1; 46854452b04SGreg Roach 46954452b04SGreg Roach foreach ($individual->getSpouseFamilies() as $family) { 47054452b04SGreg Roach FunctionsCharts::printSosaFamily($family, '', -1, $daboville, $individual->xref(), $gpid, false); 47154452b04SGreg Roach foreach ($family->getChildren() as $child) { 47254452b04SGreg Roach $this->printChildFamily($child, $depth - 1, $daboville . ($i++) . '.', $individual->xref()); 47354452b04SGreg Roach } 47454452b04SGreg Roach } 47554452b04SGreg Roach } 47654452b04SGreg Roach 47754452b04SGreg Roach /** 47854452b04SGreg Roach * This chart can display its output in a number of styles 47954452b04SGreg Roach * 48054452b04SGreg Roach * @return array 48154452b04SGreg Roach */ 48254452b04SGreg Roach private function chartStyles(): array 48354452b04SGreg Roach { 48454452b04SGreg Roach return [ 48554452b04SGreg Roach self::CHART_STYLE_LIST => I18N::translate('List'), 48654452b04SGreg Roach self::CHART_STYLE_BOOKLET => I18N::translate('Booklet'), 48754452b04SGreg Roach self::CHART_STYLE_INDIVIDUALS => I18N::translate('Individuals'), 48854452b04SGreg Roach self::CHART_STYLE_FAMILIES => I18N::translate('Families'), 48954452b04SGreg Roach ]; 490e6562982SGreg Roach } 491168ff6f3Sric2016} 492