xref: /webtrees/app/Module/DescendancyChartModule.php (revision 54452b04856df5056fa76d9764beb95110c35d02)
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
20*54452b04SGreg Roachuse Fisharebest\Webtrees\Auth;
21*54452b04SGreg Roachuse Fisharebest\Webtrees\Family;
22*54452b04SGreg Roachuse Fisharebest\Webtrees\FontAwesome;
23*54452b04SGreg Roachuse Fisharebest\Webtrees\Functions\FunctionsCharts;
24*54452b04SGreg Roachuse Fisharebest\Webtrees\Functions\FunctionsPrint;
25*54452b04SGreg Roachuse Fisharebest\Webtrees\Gedcom;
26*54452b04SGreg Roachuse Fisharebest\Webtrees\GedcomTag;
27168ff6f3Sric2016use Fisharebest\Webtrees\I18N;
28168ff6f3Sric2016use Fisharebest\Webtrees\Individual;
29e46b0479SScrutinizer Auto-Fixeruse Fisharebest\Webtrees\Menu;
30*54452b04SGreg Roachuse Fisharebest\Webtrees\Services\ChartService;
31*54452b04SGreg Roachuse Fisharebest\Webtrees\Theme;
32*54452b04SGreg Roachuse Fisharebest\Webtrees\Tree;
33*54452b04SGreg Roachuse Illuminate\Support\Collection;
34*54452b04SGreg Roachuse Ramsey\Uuid\Uuid;
35*54452b04SGreg Roachuse Symfony\Component\HttpFoundation\Request;
36*54452b04SGreg Roachuse Symfony\Component\HttpFoundation\Response;
37168ff6f3Sric2016
38168ff6f3Sric2016/**
39168ff6f3Sric2016 * Class DescendancyChartModule
40168ff6f3Sric2016 */
4149a243cbSGreg Roachclass DescendancyChartModule extends AbstractModule implements ModuleInterface, ModuleChartInterface
42c1010edaSGreg Roach{
4349a243cbSGreg Roach    use ModuleChartTrait;
4449a243cbSGreg Roach
45*54452b04SGreg Roach    // Chart styles
46*54452b04SGreg Roach    private const CHART_STYLE_LIST        = 0;
47*54452b04SGreg Roach    private const CHART_STYLE_BOOKLET     = 1;
48*54452b04SGreg Roach    private const CHART_STYLE_INDIVIDUALS = 2;
49*54452b04SGreg Roach    private const CHART_STYLE_FAMILIES    = 3;
50*54452b04SGreg Roach
51*54452b04SGreg Roach    // Defaults
52*54452b04SGreg Roach    private const DEFAULT_STYLE               = self::CHART_STYLE_LIST;
53*54452b04SGreg Roach    private const DEFAULT_GENERATIONS         = '3';
54*54452b04SGreg Roach    private const DEFAULT_MAXIMUM_GENERATIONS = '9';
55*54452b04SGreg Roach
56*54452b04SGreg Roach    /** @var int[] */
57*54452b04SGreg Roach    protected $dabo_num = [];
58*54452b04SGreg Roach
59*54452b04SGreg Roach    /** @var string[] */
60*54452b04SGreg Roach    protected $dabo_sex = [];
61*54452b04SGreg 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    /**
120*54452b04SGreg Roach     * A form to request the chart parameters.
121*54452b04SGreg Roach     *
122*54452b04SGreg Roach     * @param Request      $request
123*54452b04SGreg Roach     * @param Tree         $tree
124*54452b04SGreg Roach     * @param ChartService $chart_service
125*54452b04SGreg Roach     *
126*54452b04SGreg Roach     * @return Response
127*54452b04SGreg Roach     */
128*54452b04SGreg Roach    public function getChartAction(Request $request, Tree $tree, ChartService $chart_service): Response
129*54452b04SGreg Roach    {
130*54452b04SGreg Roach        $ajax       = $request->get('ajax', '');
131*54452b04SGreg Roach        $xref       = $request->get('xref', '');
132*54452b04SGreg Roach        $individual = Individual::getInstance($xref, $tree);
133*54452b04SGreg Roach
134*54452b04SGreg Roach        Auth::checkIndividualAccess($individual);
135*54452b04SGreg Roach
136*54452b04SGreg Roach        $minimum_generations = 2;
137*54452b04SGreg Roach        $maximum_generations = (int) $tree->getPreference('MAX_DESCENDANCY_GENERATIONS', self::DEFAULT_MAXIMUM_GENERATIONS);
138*54452b04SGreg Roach        $default_generations = (int) $tree->getPreference('DEFAULT_PEDIGREE_GENERATIONS', self::DEFAULT_GENERATIONS);
139*54452b04SGreg Roach
140*54452b04SGreg Roach        $chart_style = (int) $request->get('chart_style', self::DEFAULT_STYLE);
141*54452b04SGreg Roach        $generations = (int) $request->get('generations', $default_generations);
142*54452b04SGreg Roach
143*54452b04SGreg Roach        $generations = min($generations, $maximum_generations);
144*54452b04SGreg Roach        $generations = max($generations, $minimum_generations);
145*54452b04SGreg Roach
146*54452b04SGreg Roach        if ($ajax === '1') {
147*54452b04SGreg Roach            return $this->chart($request, $tree, $chart_service);
148*54452b04SGreg Roach        }
149*54452b04SGreg Roach
150*54452b04SGreg Roach        $ajax_url = $this->chartUrl($individual, [
151*54452b04SGreg Roach            'chart_style' => $chart_style,
152*54452b04SGreg Roach            'generations' => $generations,
153*54452b04SGreg Roach            'ajax'        => '1',
154*54452b04SGreg Roach        ]);
155*54452b04SGreg Roach
156*54452b04SGreg Roach        return $this->viewResponse('modules/descendancy_chart/chart-page', [
157*54452b04SGreg Roach            'ajax_url'            => $ajax_url,
158*54452b04SGreg Roach            'chart_style'         => $chart_style,
159*54452b04SGreg Roach            'chart_styles'        => $this->chartStyles(),
160*54452b04SGreg Roach            'default_generations' => $default_generations,
161*54452b04SGreg Roach            'generations'         => $generations,
162*54452b04SGreg Roach            'individual'          => $individual,
163*54452b04SGreg Roach            'maximum_generations' => $maximum_generations,
164*54452b04SGreg Roach            'minimum_generations' => $minimum_generations,
165*54452b04SGreg Roach            'module'              => $this,
166*54452b04SGreg Roach            'title'               => $this->chartTitle($individual),
167*54452b04SGreg Roach        ]);
168*54452b04SGreg Roach    }
169*54452b04SGreg Roach
170*54452b04SGreg Roach    /**
171*54452b04SGreg Roach     * @param Request      $request
172*54452b04SGreg Roach     * @param Tree         $tree
173*54452b04SGreg Roach     * @param ChartService $chart_service
174*54452b04SGreg Roach     *
175*54452b04SGreg Roach     * @return Response
176*54452b04SGreg Roach     */
177*54452b04SGreg Roach    public function chart(Request $request, Tree $tree, ChartService $chart_service): Response
178*54452b04SGreg Roach    {
179*54452b04SGreg Roach        $this->layout = 'layouts/ajax';
180*54452b04SGreg Roach
181*54452b04SGreg Roach        $xref       = $request->get('xref', '');
182*54452b04SGreg Roach        $individual = Individual::getInstance($xref, $tree);
183*54452b04SGreg Roach
184*54452b04SGreg Roach        Auth::checkIndividualAccess($individual);
185*54452b04SGreg Roach
186*54452b04SGreg Roach        $minimum_generations = 2;
187*54452b04SGreg Roach        $maximum_generations = (int) $tree->getPreference('MAX_PEDIGREE_GENERATIONS', self::DEFAULT_MAXIMUM_GENERATIONS);
188*54452b04SGreg Roach        $default_generations = (int) $tree->getPreference('DEFAULT_PEDIGREE_GENERATIONS', self::DEFAULT_GENERATIONS);
189*54452b04SGreg Roach
190*54452b04SGreg Roach        $chart_style = (int) $request->get('chart_style', self::DEFAULT_STYLE);
191*54452b04SGreg Roach        $generations = (int) $request->get('generations', $default_generations);
192*54452b04SGreg Roach
193*54452b04SGreg Roach        $generations = min($generations, $maximum_generations);
194*54452b04SGreg Roach        $generations = max($generations, $minimum_generations);
195*54452b04SGreg Roach
196*54452b04SGreg Roach        switch ($chart_style) {
197*54452b04SGreg Roach            case self::CHART_STYLE_LIST:
198*54452b04SGreg Roach            default:
199*54452b04SGreg Roach                return $this->descendantsList($individual, $generations);
200*54452b04SGreg Roach
201*54452b04SGreg Roach            case self::CHART_STYLE_BOOKLET:
202*54452b04SGreg Roach                return $this->descendantsBooklet($individual, $generations);
203*54452b04SGreg Roach
204*54452b04SGreg Roach            case self::CHART_STYLE_INDIVIDUALS:
205*54452b04SGreg Roach                $individuals = $chart_service->descendants($individual, $generations - 1);
206*54452b04SGreg Roach
207*54452b04SGreg Roach                return $this->descendantsIndividuals($tree, $individuals);
208*54452b04SGreg Roach
209*54452b04SGreg Roach            case self::CHART_STYLE_FAMILIES:
210*54452b04SGreg Roach                $families = $chart_service->descendantFamilies($individual, $generations - 1);
211*54452b04SGreg Roach
212*54452b04SGreg Roach                return $this->descendantsFamilies($tree, $families);
213*54452b04SGreg Roach        }
214*54452b04SGreg Roach    }
215*54452b04SGreg Roach
216*54452b04SGreg Roach    /**
217*54452b04SGreg Roach     * Show a hierarchical list of descendants
218*54452b04SGreg Roach     *
219*54452b04SGreg Roach     * @TODO replace ob_start() with views.
220e6562982SGreg Roach     *
221e6562982SGreg Roach     * @param Individual $individual
222*54452b04SGreg Roach     * @param int        $generations
223e6562982SGreg Roach     *
224*54452b04SGreg Roach     * @return Response
225e6562982SGreg Roach     */
226*54452b04SGreg Roach    private function descendantsList(Individual $individual, int $generations): Response
227e6562982SGreg Roach    {
228*54452b04SGreg Roach        ob_start();
229*54452b04SGreg Roach
230*54452b04SGreg Roach        echo '<ul class="chart_common">';
231*54452b04SGreg Roach        $this->printChildDescendancy($individual, $generations, $generations);
232*54452b04SGreg Roach        echo '</ul>';
233*54452b04SGreg Roach
234*54452b04SGreg Roach        $html = ob_get_clean();
235*54452b04SGreg Roach
236*54452b04SGreg Roach        return new Response($html);
237*54452b04SGreg Roach    }
238*54452b04SGreg Roach
239*54452b04SGreg Roach    /**
240*54452b04SGreg Roach     * print a child descendancy
241*54452b04SGreg Roach     *
242*54452b04SGreg Roach     * @param Individual $person
243*54452b04SGreg Roach     * @param int        $depth the descendancy depth to show
244*54452b04SGreg Roach     * @param int        $generations
245*54452b04SGreg Roach     *
246*54452b04SGreg Roach     * @return void
247*54452b04SGreg Roach     */
248*54452b04SGreg Roach    private function printChildDescendancy(Individual $person, $depth, int $generations)
249*54452b04SGreg Roach    {
250*54452b04SGreg Roach        echo '<li>';
251*54452b04SGreg Roach        echo '<table><tr><td>';
252*54452b04SGreg Roach        if ($depth == $generations) {
253*54452b04SGreg Roach            echo '<img alt="" role="presentation" src="' . Theme::theme()->parameter('image-spacer') . '" height="3" width="15"></td><td>';
254*54452b04SGreg Roach        } else {
255*54452b04SGreg Roach            echo '<img src="' . Theme::theme()->parameter('image-spacer') . '" height="3" width="3">';
256*54452b04SGreg Roach            echo '<img src="' . Theme::theme()->parameter('image-hline') . '" height="3" width="', 12, '"></td><td>';
257*54452b04SGreg Roach        }
258*54452b04SGreg Roach        echo FunctionsPrint::printPedigreePerson($person);
259*54452b04SGreg Roach        echo '</td>';
260*54452b04SGreg Roach
261*54452b04SGreg Roach        // check if child has parents and add an arrow
262*54452b04SGreg Roach        echo '<td></td>';
263*54452b04SGreg Roach        echo '<td>';
264*54452b04SGreg Roach        foreach ($person->getChildFamilies() as $cfamily) {
265*54452b04SGreg Roach            foreach ($cfamily->getSpouses() as $parent) {
266*54452b04SGreg Roach                echo FontAwesome::linkIcon('arrow-up', I18N::translate('Start at parents'), ['href' => route('descendants', ['ged'         => $parent->tree()->name(),
267*54452b04SGreg Roach                                                                                                                             'xref'        => $parent->xref(),
268*54452b04SGreg Roach                                                                                                                             'generations' => $generations,
269*54452b04SGreg Roach                ]),
270*54452b04SGreg Roach                ]);
271*54452b04SGreg Roach                // only show the arrow for one of the parents
272*54452b04SGreg Roach                break;
273*54452b04SGreg Roach            }
274*54452b04SGreg Roach        }
275*54452b04SGreg Roach
276*54452b04SGreg Roach        // d'Aboville child number
277*54452b04SGreg Roach        $level = $generations - $depth;
278*54452b04SGreg Roach        echo '<br><br>&nbsp;';
279*54452b04SGreg Roach        echo '<span dir="ltr">'; //needed so that RTL languages will display this properly
280*54452b04SGreg Roach        if (!isset($this->dabo_num[$level])) {
281*54452b04SGreg Roach            $this->dabo_num[$level] = 0;
282*54452b04SGreg Roach        }
283*54452b04SGreg Roach        $this->dabo_num[$level]++;
284*54452b04SGreg Roach        $this->dabo_num[$level + 1] = 0;
285*54452b04SGreg Roach        $this->dabo_sex[$level]     = $person->getSex();
286*54452b04SGreg Roach        for ($i = 0; $i <= $level; $i++) {
287*54452b04SGreg Roach            $isf = $this->dabo_sex[$i];
288*54452b04SGreg Roach            if ($isf === 'M') {
289*54452b04SGreg Roach                $isf = '';
290*54452b04SGreg Roach            }
291*54452b04SGreg Roach            if ($isf === 'U') {
292*54452b04SGreg Roach                $isf = 'NN';
293*54452b04SGreg Roach            }
294*54452b04SGreg Roach            echo '<span class="person_box' . $isf . '">&nbsp;' . $this->dabo_num[$i] . '&nbsp;</span>';
295*54452b04SGreg Roach            if ($i < $level) {
296*54452b04SGreg Roach                echo '.';
297*54452b04SGreg Roach            }
298*54452b04SGreg Roach        }
299*54452b04SGreg Roach        echo '</span>';
300*54452b04SGreg Roach        echo '</td></tr>';
301*54452b04SGreg Roach        echo '</table>';
302*54452b04SGreg Roach        echo '</li>';
303*54452b04SGreg Roach
304*54452b04SGreg Roach        // loop for each spouse
305*54452b04SGreg Roach        foreach ($person->getSpouseFamilies() as $family) {
306*54452b04SGreg Roach            $this->printFamilyDescendancy($person, $family, $depth, $generations);
307*54452b04SGreg Roach        }
308*54452b04SGreg Roach    }
309*54452b04SGreg Roach
310*54452b04SGreg Roach    /**
311*54452b04SGreg Roach     * print a family descendancy
312*54452b04SGreg Roach     *
313*54452b04SGreg Roach     * @param Individual $person
314*54452b04SGreg Roach     * @param Family     $family
315*54452b04SGreg Roach     * @param int        $depth the descendancy depth to show
316*54452b04SGreg Roach     * @param int        $generations
317*54452b04SGreg Roach     *
318*54452b04SGreg Roach     * @return void
319*54452b04SGreg Roach     */
320*54452b04SGreg Roach    private function printFamilyDescendancy(Individual $person, Family $family, int $depth, int $generations)
321*54452b04SGreg Roach    {
322*54452b04SGreg Roach        $uid = Uuid::uuid4()->toString(); // create a unique ID
323*54452b04SGreg Roach        // print marriage info
324*54452b04SGreg Roach        echo '<li>';
325*54452b04SGreg Roach        echo '<img src="', Theme::theme()->parameter('image-spacer'), '" height="2" width="', 19, '">';
326*54452b04SGreg Roach        echo '<span class="details1">';
327*54452b04SGreg 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>';
328*54452b04SGreg Roach        if ($family->canShow()) {
329*54452b04SGreg Roach            foreach ($family->facts(Gedcom::MARRIAGE_EVENTS) as $fact) {
330*54452b04SGreg Roach                echo ' <a href="', e($family->url()), '" class="details1">', $fact->summary(), '</a>';
331*54452b04SGreg Roach            }
332*54452b04SGreg Roach        }
333*54452b04SGreg Roach        echo '</span>';
334*54452b04SGreg Roach
335*54452b04SGreg Roach        // print spouse
336*54452b04SGreg Roach        $spouse = $family->getSpouse($person);
337*54452b04SGreg Roach        echo '<ul class="generations" id="' . $uid . '">';
338*54452b04SGreg Roach        echo '<li>';
339*54452b04SGreg Roach        echo '<table><tr><td>';
340*54452b04SGreg Roach        echo FunctionsPrint::printPedigreePerson($spouse);
341*54452b04SGreg Roach        echo '</td>';
342*54452b04SGreg Roach
343*54452b04SGreg Roach        // check if spouse has parents and add an arrow
344*54452b04SGreg Roach        echo '<td></td>';
345*54452b04SGreg Roach        echo '<td>';
346*54452b04SGreg Roach        if ($spouse) {
347*54452b04SGreg Roach            foreach ($spouse->getChildFamilies() as $cfamily) {
348*54452b04SGreg Roach                foreach ($cfamily->getSpouses() as $parent) {
349*54452b04SGreg Roach                    echo FontAwesome::linkIcon('arrow-up', I18N::translate('Start at parents'), ['href' => route('descendants', ['ged'         => $parent->tree()->name(),
350*54452b04SGreg Roach                                                                                                                                 'xref'        => $parent->xref(),
351*54452b04SGreg Roach                                                                                                                                 'generations' => $generations,
352*54452b04SGreg Roach                    ]),
353*54452b04SGreg Roach                    ]);
354*54452b04SGreg Roach                    // only show the arrow for one of the parents
355*54452b04SGreg Roach                    break;
356*54452b04SGreg Roach                }
357*54452b04SGreg Roach            }
358*54452b04SGreg Roach        }
359*54452b04SGreg Roach        echo '<br><br>&nbsp;';
360*54452b04SGreg Roach        echo '</td></tr>';
361*54452b04SGreg Roach
362*54452b04SGreg Roach        // children
363*54452b04SGreg Roach        $children = $family->getChildren();
364*54452b04SGreg Roach        echo '<tr><td colspan="3" class="details1" >&nbsp;&nbsp;';
365*54452b04SGreg Roach        if (!empty($children)) {
366*54452b04SGreg Roach            echo GedcomTag::getLabel('NCHI') . ': ' . count($children);
367*54452b04SGreg Roach        } else {
368*54452b04SGreg Roach            // Distinguish between no children (NCHI 0) and no recorded
369*54452b04SGreg Roach            // children (no CHIL records)
370*54452b04SGreg Roach            if (strpos($family->gedcom(), '\n1 NCHI 0') !== false) {
371*54452b04SGreg Roach                echo GedcomTag::getLabel('NCHI') . ': ' . count($children);
372*54452b04SGreg Roach            } else {
373*54452b04SGreg Roach                echo I18N::translate('No children');
374*54452b04SGreg Roach            }
375*54452b04SGreg Roach        }
376*54452b04SGreg Roach        echo '</td></tr></table>';
377*54452b04SGreg Roach        echo '</li>';
378*54452b04SGreg Roach        if ($depth > 1) {
379*54452b04SGreg Roach            foreach ($children as $child) {
380*54452b04SGreg Roach                $this->printChildDescendancy($child, $depth - 1, $generations);
381*54452b04SGreg Roach            }
382*54452b04SGreg Roach        }
383*54452b04SGreg Roach        echo '</ul>';
384*54452b04SGreg Roach        echo '</li>';
385*54452b04SGreg Roach    }
386*54452b04SGreg Roach
387*54452b04SGreg Roach    /**
388*54452b04SGreg Roach     * Show a tabular list of individual descendants.
389*54452b04SGreg Roach     *
390*54452b04SGreg Roach     * @param Tree       $tree
391*54452b04SGreg Roach     * @param Collection $individuals
392*54452b04SGreg Roach     *
393*54452b04SGreg Roach     * @return Response
394*54452b04SGreg Roach     */
395*54452b04SGreg Roach    private function descendantsIndividuals(Tree $tree, Collection $individuals): Response
396*54452b04SGreg Roach    {
397*54452b04SGreg Roach        $this->layout = 'layouts/ajax';
398*54452b04SGreg Roach
399*54452b04SGreg Roach        return $this->viewResponse('lists/individuals-table', [
400*54452b04SGreg Roach            'individuals' => $individuals,
401*54452b04SGreg Roach            'sosa'        => false,
402*54452b04SGreg Roach            'tree'        => $tree,
403*54452b04SGreg Roach        ]);
404*54452b04SGreg Roach    }
405*54452b04SGreg Roach
406*54452b04SGreg Roach    /**
407*54452b04SGreg Roach     * Show a tabular list of individual descendants.
408*54452b04SGreg Roach     *
409*54452b04SGreg Roach     * @param Tree       $tree
410*54452b04SGreg Roach     * @param Collection $families
411*54452b04SGreg Roach     *
412*54452b04SGreg Roach     * @return Response
413*54452b04SGreg Roach     */
414*54452b04SGreg Roach    private function descendantsFamilies(Tree $tree, Collection $families): Response
415*54452b04SGreg Roach    {
416*54452b04SGreg Roach        $this->layout = 'layouts/ajax';
417*54452b04SGreg Roach
418*54452b04SGreg Roach        return $this->viewResponse('lists/families-table', [
419*54452b04SGreg Roach            'families' => $families,
420*54452b04SGreg Roach            'tree'     => $tree,
421*54452b04SGreg Roach        ]);
422*54452b04SGreg Roach    }
423*54452b04SGreg Roach
424*54452b04SGreg Roach    /**
425*54452b04SGreg Roach     * Show a booklet view of descendants
426*54452b04SGreg Roach     *
427*54452b04SGreg Roach     * @TODO replace ob_start() with views.
428*54452b04SGreg Roach     *
429*54452b04SGreg Roach     * @param Individual $individual
430*54452b04SGreg Roach     * @param int        $generations
431*54452b04SGreg Roach     *
432*54452b04SGreg Roach     * @return Response
433*54452b04SGreg Roach     */
434*54452b04SGreg Roach    private function descendantsBooklet(Individual $individual, int $generations): Response
435*54452b04SGreg Roach    {
436*54452b04SGreg Roach        ob_start();
437*54452b04SGreg Roach
438*54452b04SGreg Roach        $this->printChildFamily($individual, $generations);
439*54452b04SGreg Roach
440*54452b04SGreg Roach        $html = ob_get_clean();
441*54452b04SGreg Roach
442*54452b04SGreg Roach        return new Response($html);
443*54452b04SGreg Roach    }
444*54452b04SGreg Roach
445*54452b04SGreg Roach
446*54452b04SGreg Roach    /**
447*54452b04SGreg Roach     * Print a child family
448*54452b04SGreg Roach     *
449*54452b04SGreg Roach     * @param Individual $individual
450*54452b04SGreg Roach     * @param int        $depth     - the descendancy depth to show
451*54452b04SGreg Roach     * @param string     $daboville - d'Aboville number
452*54452b04SGreg Roach     * @param string     $gpid
453*54452b04SGreg Roach     *
454*54452b04SGreg Roach     * @return void
455*54452b04SGreg Roach     */
456*54452b04SGreg Roach    private function printChildFamily(Individual $individual, $depth, $daboville = '1.', $gpid = '')
457*54452b04SGreg Roach    {
458*54452b04SGreg Roach        if ($depth < 2) {
459*54452b04SGreg Roach            return;
460*54452b04SGreg Roach        }
461*54452b04SGreg Roach
462*54452b04SGreg Roach        $i = 1;
463*54452b04SGreg Roach
464*54452b04SGreg Roach        foreach ($individual->getSpouseFamilies() as $family) {
465*54452b04SGreg Roach            FunctionsCharts::printSosaFamily($family, '', -1, $daboville, $individual->xref(), $gpid, false);
466*54452b04SGreg Roach            foreach ($family->getChildren() as $child) {
467*54452b04SGreg Roach                $this->printChildFamily($child, $depth - 1, $daboville . ($i++) . '.', $individual->xref());
468*54452b04SGreg Roach            }
469*54452b04SGreg Roach        }
470*54452b04SGreg Roach    }
471*54452b04SGreg Roach
472*54452b04SGreg Roach    /**
473*54452b04SGreg Roach     * This chart can display its output in a number of styles
474*54452b04SGreg Roach     *
475*54452b04SGreg Roach     * @return array
476*54452b04SGreg Roach     */
477*54452b04SGreg Roach    private function chartStyles(): array
478*54452b04SGreg Roach    {
479*54452b04SGreg Roach        return [
480*54452b04SGreg Roach            self::CHART_STYLE_LIST        => I18N::translate('List'),
481*54452b04SGreg Roach            self::CHART_STYLE_BOOKLET     => I18N::translate('Booklet'),
482*54452b04SGreg Roach            self::CHART_STYLE_INDIVIDUALS => I18N::translate('Individuals'),
483*54452b04SGreg Roach            self::CHART_STYLE_FAMILIES    => I18N::translate('Families'),
484*54452b04SGreg Roach        ];
485e6562982SGreg Roach    }
486168ff6f3Sric2016}
487