xref: /webtrees/app/Module/DescendancyChartModule.php (revision e5a6b4d4f6f6e7ff2fba7ae2cf27546ae68a79cc)
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>&nbsp;';
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 . '">&nbsp;' . $this->dabo_num[$i] . '&nbsp;</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>&nbsp;';
36654452b04SGreg Roach        echo '</td></tr>';
36754452b04SGreg Roach
36854452b04SGreg Roach        // children
36954452b04SGreg Roach        $children = $family->getChildren();
37054452b04SGreg Roach        echo '<tr><td colspan="3" class="details1" >&nbsp;&nbsp;';
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