xref: /webtrees/app/Module/HourglassChartModule.php (revision f1d4b4a2fcc65f3b3bd1d9fb6ff4b678a9e0aea4)
1168ff6f3Sric2016<?php
23976b470SGreg Roach
3168ff6f3Sric2016/**
4168ff6f3Sric2016 * webtrees: online genealogy
58fcd0d32SGreg Roach * Copyright (C) 2019 webtrees development team
6168ff6f3Sric2016 * This program is free software: you can redistribute it and/or modify
7168ff6f3Sric2016 * it under the terms of the GNU General Public License as published by
8168ff6f3Sric2016 * the Free Software Foundation, either version 3 of the License, or
9168ff6f3Sric2016 * (at your option) any later version.
10168ff6f3Sric2016 * This program is distributed in the hope that it will be useful,
11168ff6f3Sric2016 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12168ff6f3Sric2016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13168ff6f3Sric2016 * GNU General Public License for more details.
14168ff6f3Sric2016 * You should have received a copy of the GNU General Public License
15168ff6f3Sric2016 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16168ff6f3Sric2016 */
17e7f56f2aSGreg Roachdeclare(strict_types=1);
18e7f56f2aSGreg Roach
19168ff6f3Sric2016namespace Fisharebest\Webtrees\Module;
20168ff6f3Sric2016
2126684e68SGreg Roachuse Fisharebest\Webtrees\Auth;
22cb0eb4a9SGreg Roachuse Fisharebest\Webtrees\Family;
23168ff6f3Sric2016use Fisharebest\Webtrees\I18N;
24168ff6f3Sric2016use Fisharebest\Webtrees\Individual;
25e46b0479SScrutinizer Auto-Fixeruse Fisharebest\Webtrees\Menu;
2626684e68SGreg Roachuse Fisharebest\Webtrees\Tree;
27cb0eb4a9SGreg Roachuse Illuminate\Support\Collection;
286ccdf4f0SGreg Roachuse Psr\Http\Message\ResponseInterface;
296ccdf4f0SGreg Roachuse Psr\Http\Message\ServerRequestInterface;
303976b470SGreg Roach
31cb0eb4a9SGreg Roachuse function app;
32cb0eb4a9SGreg Roachuse function response;
33f4ba05e3SGreg Roachuse function view;
34168ff6f3Sric2016
35168ff6f3Sric2016/**
36168ff6f3Sric2016 * Class HourglassChartModule
37168ff6f3Sric2016 */
3837eb8894SGreg Roachclass HourglassChartModule extends AbstractModule implements ModuleChartInterface
39c1010edaSGreg Roach{
4049a243cbSGreg Roach    use ModuleChartTrait;
4149a243cbSGreg Roach
4226684e68SGreg Roach    // Defaults
4326684e68SGreg Roach    private const DEFAULT_GENERATIONS         = '3';
4426684e68SGreg Roach    private const DEFAULT_MAXIMUM_GENERATIONS = '9';
4526684e68SGreg Roach
4626684e68SGreg Roach    // Limits
47e759aebbSGreg Roach    private const MAXIMUM_GENERATIONS = 10;
4826684e68SGreg Roach    private const MINIMUM_GENERATIONS = 2;
4926684e68SGreg Roach
50168ff6f3Sric2016    /**
510cfd6963SGreg Roach     * How should this module be identified in the control panel, etc.?
52168ff6f3Sric2016     *
53168ff6f3Sric2016     * @return string
54168ff6f3Sric2016     */
5549a243cbSGreg Roach    public function title(): string
56c1010edaSGreg Roach    {
57bbb76c12SGreg Roach        /* I18N: Name of a module/chart */
58bbb76c12SGreg Roach        return I18N::translate('Hourglass chart');
59168ff6f3Sric2016    }
60168ff6f3Sric2016
61168ff6f3Sric2016    /**
62168ff6f3Sric2016     * A sentence describing what this module does.
63168ff6f3Sric2016     *
64168ff6f3Sric2016     * @return string
65168ff6f3Sric2016     */
6649a243cbSGreg Roach    public function description(): string
67c1010edaSGreg Roach    {
68bbb76c12SGreg Roach        /* I18N: Description of the “HourglassChart” module */
69bbb76c12SGreg Roach        return I18N::translate('An hourglass chart of an individual’s ancestors and descendants.');
70168ff6f3Sric2016    }
71168ff6f3Sric2016
72168ff6f3Sric2016    /**
73377a2979SGreg Roach     * CSS class for the URL.
74377a2979SGreg Roach     *
75377a2979SGreg Roach     * @return string
76377a2979SGreg Roach     */
77377a2979SGreg Roach    public function chartMenuClass(): string
78377a2979SGreg Roach    {
79377a2979SGreg Roach        return 'menu-chart-hourglass';
80377a2979SGreg Roach    }
81377a2979SGreg Roach
82377a2979SGreg Roach    /**
834eb71cfaSGreg Roach     * Return a menu item for this chart - for use in individual boxes.
844eb71cfaSGreg Roach     *
8560bc3e3fSGreg Roach     * @param Individual $individual
8660bc3e3fSGreg Roach     *
874eb71cfaSGreg Roach     * @return Menu|null
884eb71cfaSGreg Roach     */
89377a2979SGreg Roach    public function chartBoxMenu(Individual $individual): ?Menu
90c1010edaSGreg Roach    {
91e6562982SGreg Roach        return $this->chartMenu($individual);
92e6562982SGreg Roach    }
93e6562982SGreg Roach
94e6562982SGreg Roach    /**
9526684e68SGreg Roach     * A form to request the chart parameters.
96e6562982SGreg Roach     *
976ccdf4f0SGreg Roach     * @param ServerRequestInterface $request
98e6562982SGreg Roach     *
996ccdf4f0SGreg Roach     * @return ResponseInterface
100e6562982SGreg Roach     */
10157ab2231SGreg Roach    public function getChartAction(ServerRequestInterface $request): ResponseInterface
102e6562982SGreg Roach    {
10357ab2231SGreg Roach        $tree       = $request->getAttribute('tree');
10457ab2231SGreg Roach        $user       = $request->getAttribute('user');
1050b93976aSGreg Roach        $ajax       = $request->getQueryParams()['ajax'] ?? '';
1060b93976aSGreg Roach        $xref       = $request->getQueryParams()['xref'] ?? '';
10726684e68SGreg Roach        $individual = Individual::getInstance($xref, $tree);
10826684e68SGreg Roach
10926684e68SGreg Roach        Auth::checkIndividualAccess($individual);
1109867b2f0SGreg Roach        Auth::checkComponentAccess($this, 'chart', $tree, $user);
11126684e68SGreg Roach
1120b93976aSGreg Roach        $generations = (int) ($request->getQueryParams()['generations'] ?? self::DEFAULT_GENERATIONS);
11326684e68SGreg Roach
114e759aebbSGreg Roach        $generations = min($generations, self::MAXIMUM_GENERATIONS);
11526684e68SGreg Roach        $generations = max($generations, self::MINIMUM_GENERATIONS);
11626684e68SGreg Roach
1170b93976aSGreg Roach        $show_spouse = (bool) ($request->getQueryParams()['show_spouse'] ?? false);
11826684e68SGreg Roach
1190b93976aSGreg Roach        if ($ajax === '1') {
12026684e68SGreg Roach            return $this->chart($individual, $generations, $show_spouse);
12126684e68SGreg Roach        }
12226684e68SGreg Roach
12326684e68SGreg Roach        $ajax_url = $this->chartUrl($individual, [
1249b5537c3SGreg Roach            'ajax'        => true,
1252b29a33eSmakitso            'generations' => $generations,
1262f0ffe95SGreg Roach            'show_spouse' => $show_spouse,
12726684e68SGreg Roach        ]);
12826684e68SGreg Roach
1299b5537c3SGreg Roach        return $this->viewResponse('modules/hourglass-chart/page', [
13026684e68SGreg Roach            'ajax_url'            => $ajax_url,
13126684e68SGreg Roach            'generations'         => $generations,
13226684e68SGreg Roach            'individual'          => $individual,
133e759aebbSGreg Roach            'maximum_generations' => self::MAXIMUM_GENERATIONS,
13426684e68SGreg Roach            'minimum_generations' => self::MINIMUM_GENERATIONS,
13526684e68SGreg Roach            'module_name'         => $this->name(),
13626684e68SGreg Roach            'show_spouse'         => $show_spouse,
13726684e68SGreg Roach            'title'               => $this->chartTitle($individual),
13826684e68SGreg Roach        ]);
13926684e68SGreg Roach    }
14026684e68SGreg Roach
14126684e68SGreg Roach    /**
14226684e68SGreg Roach     * Generate the initial generations of the chart
14326684e68SGreg Roach     *
144e5a6b4d4SGreg Roach     * @param Individual $individual
145e5a6b4d4SGreg Roach     * @param int        $generations
146e5a6b4d4SGreg Roach     * @param bool       $show_spouse
14726684e68SGreg Roach     *
1486ccdf4f0SGreg Roach     * @return ResponseInterface
14926684e68SGreg Roach     */
1506ccdf4f0SGreg Roach    protected function chart(Individual $individual, int $generations, bool $show_spouse): ResponseInterface
15126684e68SGreg Roach    {
152cb0eb4a9SGreg Roach        $this->layout = 'layouts/ajax';
15326684e68SGreg Roach
154cb0eb4a9SGreg Roach        return $this->viewResponse('modules/hourglass-chart/chart', [
155cb0eb4a9SGreg Roach            'generations' => $generations,
156cb0eb4a9SGreg Roach            'individual'  => $individual,
157cb0eb4a9SGreg Roach            'show_spouse' => $show_spouse,
158cb0eb4a9SGreg Roach        ]);
159cb0eb4a9SGreg Roach    }
16026684e68SGreg Roach
161cb0eb4a9SGreg Roach    /**
162cb0eb4a9SGreg Roach     * Generate an extension to the chart
163cb0eb4a9SGreg Roach     *
164cb0eb4a9SGreg Roach     * @param ServerRequestInterface $request
165cb0eb4a9SGreg Roach     *
166cb0eb4a9SGreg Roach     * @return ResponseInterface
167cb0eb4a9SGreg Roach     */
168cb0eb4a9SGreg Roach    public function getAncestorsAction(ServerRequestInterface $request): ResponseInterface
169cb0eb4a9SGreg Roach    {
170*f1d4b4a2SGreg Roach        $tree = $request->getAttribute('tree');
171cb0eb4a9SGreg Roach        $xref = $request->getQueryParams()['xref'] ?? '';
172cb0eb4a9SGreg Roach
173cb0eb4a9SGreg Roach        $family = Family::getInstance($xref, $tree);
174cb0eb4a9SGreg Roach        Auth::checkFamilyAccess($family);
175cb0eb4a9SGreg Roach
176cb0eb4a9SGreg Roach        return response(view('modules/hourglass-chart/parents', [
177cb0eb4a9SGreg Roach            'family'      => $family,
178cb0eb4a9SGreg Roach            'generations' => 1,
17926684e68SGreg Roach        ]));
18026684e68SGreg Roach    }
18126684e68SGreg Roach
18226684e68SGreg Roach    /**
183cb0eb4a9SGreg Roach     * Generate an extension to the chart
184cb0eb4a9SGreg Roach     *
1856ccdf4f0SGreg Roach     * @param ServerRequestInterface $request
18626684e68SGreg Roach     *
1876ccdf4f0SGreg Roach     * @return ResponseInterface
18826684e68SGreg Roach     */
189cb0eb4a9SGreg Roach    public function getDescendantsAction(ServerRequestInterface $request): ResponseInterface
19026684e68SGreg Roach    {
191*f1d4b4a2SGreg Roach        $tree = $request->getAttribute('tree');
192cb0eb4a9SGreg Roach        $xref = $request->getQueryParams()['xref'] ?? '';
19326684e68SGreg Roach
194cb0eb4a9SGreg Roach        $show_spouse = (bool) ($request->getQueryParams()['show_spouse'] ?? false);
195cb0eb4a9SGreg Roach        $individual  = Individual::getInstance($xref, $tree);
196a21e5374SGreg Roach
19726684e68SGreg Roach        Auth::checkIndividualAccess($individual);
198a21e5374SGreg Roach
199a21e5374SGreg Roach        $children = $individual->spouseFamilies()->map(static function (Family $family): Collection {
200a21e5374SGreg Roach            return $family->children();
201a21e5374SGreg Roach        })->flatten();
20226684e68SGreg Roach
203cb0eb4a9SGreg Roach        return response(view('modules/hourglass-chart/children', [
204cb0eb4a9SGreg Roach            'children'    => $children,
205cb0eb4a9SGreg Roach            'generations' => 1,
206cb0eb4a9SGreg Roach            'show_spouse' => $show_spouse,
207cb0eb4a9SGreg Roach        ]));
208e6562982SGreg Roach    }
209168ff6f3Sric2016}
210