xref: /webtrees/app/Module/AncestorsChartModule.php (revision 0b93976a9c83f1ad374620df2dc12a210d5be076)
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
20e539f5c6SGreg Roachuse Fisharebest\Webtrees\Auth;
21e5a6b4d4SGreg Roachuse Fisharebest\Webtrees\Contracts\UserInterface;
22168ff6f3Sric2016use Fisharebest\Webtrees\I18N;
23168ff6f3Sric2016use Fisharebest\Webtrees\Individual;
24e46b0479SScrutinizer Auto-Fixeruse Fisharebest\Webtrees\Menu;
25e539f5c6SGreg Roachuse Fisharebest\Webtrees\Services\ChartService;
26e539f5c6SGreg Roachuse Fisharebest\Webtrees\Tree;
27e539f5c6SGreg Roachuse Illuminate\Support\Collection;
286ccdf4f0SGreg Roachuse Psr\Http\Message\ResponseInterface;
296ccdf4f0SGreg Roachuse Psr\Http\Message\ServerRequestInterface;
30f4ba05e3SGreg Roachuse function view;
31168ff6f3Sric2016
32168ff6f3Sric2016/**
33168ff6f3Sric2016 * Class AncestorsChartModule
34168ff6f3Sric2016 */
3537eb8894SGreg Roachclass AncestorsChartModule extends AbstractModule implements ModuleChartInterface
36c1010edaSGreg Roach{
3749a243cbSGreg Roach    use ModuleChartTrait;
3849a243cbSGreg Roach
39e539f5c6SGreg Roach    // Chart styles
400f1e0f10SGreg Roach    protected const CHART_STYLE_TREE        = 'tree';
41e539f5c6SGreg Roach    protected const CHART_STYLE_INDIVIDUALS = 'individuals';
42e539f5c6SGreg Roach    protected const CHART_STYLE_FAMILIES    = 'families';
43e539f5c6SGreg Roach
44e539f5c6SGreg Roach    // Defaults
450f1e0f10SGreg Roach    protected const DEFAULT_STYLE               = self::CHART_STYLE_TREE;
460cf94a7cSGreg Roach    protected const DEFAULT_GENERATIONS         = '4';
47e759aebbSGreg Roach
48e759aebbSGreg Roach    // Limits
49e759aebbSGreg Roach    protected const MINIMUM_GENERATIONS = 2;
50e759aebbSGreg Roach    protected const MAXIMUM_GENERATIONS = 10;
51e539f5c6SGreg Roach
52168ff6f3Sric2016    /**
530cfd6963SGreg Roach     * How should this module be identified in the control panel, etc.?
54168ff6f3Sric2016     *
55168ff6f3Sric2016     * @return string
56168ff6f3Sric2016     */
5749a243cbSGreg Roach    public function title(): string
58c1010edaSGreg Roach    {
59bbb76c12SGreg Roach        /* I18N: Name of a module/chart */
60bbb76c12SGreg Roach        return I18N::translate('Ancestors');
61168ff6f3Sric2016    }
62168ff6f3Sric2016
63168ff6f3Sric2016    /**
64168ff6f3Sric2016     * A sentence describing what this module does.
65168ff6f3Sric2016     *
66168ff6f3Sric2016     * @return string
67168ff6f3Sric2016     */
6849a243cbSGreg Roach    public function description(): string
69c1010edaSGreg Roach    {
70bbb76c12SGreg Roach        /* I18N: Description of the “AncestorsChart” module */
71bbb76c12SGreg Roach        return I18N::translate('A chart of an individual’s ancestors.');
72168ff6f3Sric2016    }
73168ff6f3Sric2016
74168ff6f3Sric2016    /**
75377a2979SGreg Roach     * CSS class for the URL.
76377a2979SGreg Roach     *
77377a2979SGreg Roach     * @return string
78377a2979SGreg Roach     */
79377a2979SGreg Roach    public function chartMenuClass(): string
80377a2979SGreg Roach    {
81377a2979SGreg Roach        return 'menu-chart-ancestry';
82377a2979SGreg Roach    }
83377a2979SGreg Roach
84377a2979SGreg Roach    /**
854eb71cfaSGreg Roach     * Return a menu item for this chart - for use in individual boxes.
864eb71cfaSGreg Roach     *
8760bc3e3fSGreg Roach     * @param Individual $individual
8860bc3e3fSGreg Roach     *
894eb71cfaSGreg Roach     * @return Menu|null
904eb71cfaSGreg Roach     */
91377a2979SGreg Roach    public function chartBoxMenu(Individual $individual): ?Menu
92c1010edaSGreg Roach    {
93e6562982SGreg Roach        return $this->chartMenu($individual);
94e6562982SGreg Roach    }
95e6562982SGreg Roach
96e6562982SGreg Roach    /**
97e6562982SGreg Roach     * The title for a specific instance of this chart.
98e6562982SGreg Roach     *
99e6562982SGreg Roach     * @param Individual $individual
100e6562982SGreg Roach     *
101e6562982SGreg Roach     * @return string
102e6562982SGreg Roach     */
103e6562982SGreg Roach    public function chartTitle(Individual $individual): string
104e6562982SGreg Roach    {
105e6562982SGreg Roach        /* I18N: %s is an individual’s name */
10639ca88baSGreg Roach        return I18N::translate('Ancestors of %s', $individual->fullName());
107e6562982SGreg Roach    }
108e6562982SGreg Roach
109e6562982SGreg Roach    /**
110e539f5c6SGreg Roach     * A form to request the chart parameters.
111e539f5c6SGreg Roach     *
1126ccdf4f0SGreg Roach     * @param ServerRequestInterface $request
113e539f5c6SGreg Roach     * @param Tree                   $tree
114e5a6b4d4SGreg Roach     * @param UserInterface          $user
115e539f5c6SGreg Roach     * @param ChartService           $chart_service
116e539f5c6SGreg Roach     *
1176ccdf4f0SGreg Roach     * @return ResponseInterface
118e539f5c6SGreg Roach     */
1196ccdf4f0SGreg Roach    public function getChartAction(ServerRequestInterface $request, Tree $tree, UserInterface $user, ChartService $chart_service): ResponseInterface
120e539f5c6SGreg Roach    {
121*0b93976aSGreg Roach        $ajax       = $request->getQueryParams()['ajax'] ?? '';
122*0b93976aSGreg Roach        $xref       = $request->getQueryParams()['xref'] ?? '';
123e539f5c6SGreg Roach        $individual = Individual::getInstance($xref, $tree);
124e539f5c6SGreg Roach
125e539f5c6SGreg Roach        Auth::checkIndividualAccess($individual);
1269867b2f0SGreg Roach        Auth::checkComponentAccess($this, 'chart', $tree, $user);
127e539f5c6SGreg Roach
128*0b93976aSGreg Roach        $chart_style  = $request->getQueryParams()['chart_style'] ?? self::DEFAULT_STYLE;
129*0b93976aSGreg Roach        $generations  = (int) ($request->getQueryParams()['generations'] ?? self::DEFAULT_GENERATIONS);
130e539f5c6SGreg Roach
1310cf94a7cSGreg Roach        $generations = min($generations, self::MAXIMUM_GENERATIONS);
1320cf94a7cSGreg Roach        $generations = max($generations, self::MINIMUM_GENERATIONS);
133e539f5c6SGreg Roach
134*0b93976aSGreg Roach        if ($ajax === '1') {
135e539f5c6SGreg Roach            $ancestors = $chart_service->sosaStradonitzAncestors($individual, $generations);
136e539f5c6SGreg Roach
137e539f5c6SGreg Roach            switch ($chart_style) {
138e539f5c6SGreg Roach                default:
1390f1e0f10SGreg Roach                case self::CHART_STYLE_TREE:
1400f1e0f10SGreg Roach                    return response(view('modules/ancestors-chart/tree', ['individual' => $individual, 'parents' => $individual->primaryChildFamily(), 'generations' => $generations, 'sosa' => 1]));
141e539f5c6SGreg Roach
142e539f5c6SGreg Roach                case self::CHART_STYLE_INDIVIDUALS:
143e539f5c6SGreg Roach                    return $this->ancestorsIndividuals($tree, $ancestors);
144e539f5c6SGreg Roach
145e539f5c6SGreg Roach                case self::CHART_STYLE_FAMILIES:
146e539f5c6SGreg Roach                    return $this->ancestorsFamilies($tree, $ancestors);
147e539f5c6SGreg Roach            }
148e539f5c6SGreg Roach        }
149e539f5c6SGreg Roach
15054452b04SGreg Roach        $ajax_url = $this->chartUrl($individual, [
15154452b04SGreg Roach            'generations'  => $generations,
15254452b04SGreg Roach            'chart_style'  => $chart_style,
1539b5537c3SGreg Roach            'ajax'         => true,
15454452b04SGreg Roach        ]);
15554452b04SGreg Roach
1569b5537c3SGreg Roach        return $this->viewResponse('modules/ancestors-chart/page', [
15754452b04SGreg Roach            'ajax_url'            => $ajax_url,
158e539f5c6SGreg Roach            'chart_style'         => $chart_style,
159e539f5c6SGreg Roach            'chart_styles'        => $this->chartStyles(),
160e759aebbSGreg Roach            'default_generations' => self::DEFAULT_GENERATIONS,
161e539f5c6SGreg Roach            'generations'         => $generations,
162e539f5c6SGreg Roach            'individual'          => $individual,
163e759aebbSGreg Roach            'maximum_generations' => self::MAXIMUM_GENERATIONS,
164e759aebbSGreg Roach            'minimum_generations' => self::MINIMUM_GENERATIONS,
16526684e68SGreg Roach            'module_name'         => $this->name(),
166e539f5c6SGreg Roach            'title'               => $this->chartTitle($individual),
167e539f5c6SGreg Roach        ]);
168e539f5c6SGreg Roach    }
169e539f5c6SGreg Roach
170e539f5c6SGreg Roach    /**
171e539f5c6SGreg Roach     * Show a tabular list of individual ancestors.
172e539f5c6SGreg Roach     *
173e539f5c6SGreg Roach     * @param Tree       $tree
174e539f5c6SGreg Roach     * @param Collection $ancestors
175e539f5c6SGreg Roach     *
1766ccdf4f0SGreg Roach     * @return ResponseInterface
177e539f5c6SGreg Roach     */
1786ccdf4f0SGreg Roach    protected function ancestorsIndividuals(Tree $tree, Collection $ancestors): ResponseInterface
179e539f5c6SGreg Roach    {
180e539f5c6SGreg Roach        $this->layout = 'layouts/ajax';
181e539f5c6SGreg Roach
182e539f5c6SGreg Roach        return $this->viewResponse('lists/individuals-table', [
183e539f5c6SGreg Roach            'individuals' => $ancestors,
184e539f5c6SGreg Roach            'sosa'        => true,
185e539f5c6SGreg Roach            'tree'        => $tree,
186e539f5c6SGreg Roach        ]);
187e539f5c6SGreg Roach    }
188e539f5c6SGreg Roach
189e539f5c6SGreg Roach    /**
190e539f5c6SGreg Roach     * Show a tabular list of individual ancestors.
191e539f5c6SGreg Roach     *
192e539f5c6SGreg Roach     * @param Tree       $tree
193e539f5c6SGreg Roach     * @param Collection $ancestors
194e539f5c6SGreg Roach     *
1956ccdf4f0SGreg Roach     * @return ResponseInterface
196e539f5c6SGreg Roach     */
1976ccdf4f0SGreg Roach    protected function ancestorsFamilies(Tree $tree, Collection $ancestors): ResponseInterface
198e539f5c6SGreg Roach    {
199e539f5c6SGreg Roach        $this->layout = 'layouts/ajax';
200e539f5c6SGreg Roach
201e539f5c6SGreg Roach        $families = [];
202e539f5c6SGreg Roach        foreach ($ancestors as $individual) {
20339ca88baSGreg Roach            foreach ($individual->childFamilies() as $family) {
204e539f5c6SGreg Roach                $families[$family->xref()] = $family;
205e539f5c6SGreg Roach            }
206e539f5c6SGreg Roach        }
207e539f5c6SGreg Roach
208e539f5c6SGreg Roach        return $this->viewResponse('lists/families-table', [
209e539f5c6SGreg Roach            'families' => $families,
210e539f5c6SGreg Roach            'tree'     => $tree,
211e539f5c6SGreg Roach        ]);
212e539f5c6SGreg Roach    }
213e539f5c6SGreg Roach
214e539f5c6SGreg Roach    /**
215e539f5c6SGreg Roach     * This chart can display its output in a number of styles
216e539f5c6SGreg Roach     *
217e539f5c6SGreg Roach     * @return array
218e539f5c6SGreg Roach     */
219e539f5c6SGreg Roach    protected function chartStyles(): array
220e539f5c6SGreg Roach    {
221e539f5c6SGreg Roach        return [
2220f1e0f10SGreg Roach            self::CHART_STYLE_TREE        => I18N::translate('Tree'),
223e539f5c6SGreg Roach            self::CHART_STYLE_INDIVIDUALS => I18N::translate('Individuals'),
224e539f5c6SGreg Roach            self::CHART_STYLE_FAMILIES    => I18N::translate('Families'),
225e539f5c6SGreg Roach        ];
226e539f5c6SGreg Roach    }
227168ff6f3Sric2016}
228