xref: /webtrees/app/Module/HourglassChartModule.php (revision cb0eb4a9463291c5ba2c9deef129f29c38ed947e)
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
2026684e68SGreg Roachuse Fisharebest\Webtrees\Auth;
21e5a6b4d4SGreg Roachuse Fisharebest\Webtrees\Contracts\UserInterface;
22*cb0eb4a9SGreg Roachuse Fisharebest\Webtrees\Family;
23168ff6f3Sric2016use Fisharebest\Webtrees\I18N;
24168ff6f3Sric2016use Fisharebest\Webtrees\Individual;
25e46b0479SScrutinizer Auto-Fixeruse Fisharebest\Webtrees\Menu;
2626684e68SGreg Roachuse Fisharebest\Webtrees\Tree;
27*cb0eb4a9SGreg Roachuse Illuminate\Support\Collection;
286ccdf4f0SGreg Roachuse Psr\Http\Message\ResponseInterface;
296ccdf4f0SGreg Roachuse Psr\Http\Message\ServerRequestInterface;
30*cb0eb4a9SGreg Roachuse function app;
31*cb0eb4a9SGreg Roachuse function response;
32f4ba05e3SGreg Roachuse function view;
33168ff6f3Sric2016
34168ff6f3Sric2016/**
35168ff6f3Sric2016 * Class HourglassChartModule
36168ff6f3Sric2016 */
3737eb8894SGreg Roachclass HourglassChartModule extends AbstractModule implements ModuleChartInterface
38c1010edaSGreg Roach{
3949a243cbSGreg Roach    use ModuleChartTrait;
4049a243cbSGreg Roach
4126684e68SGreg Roach    // Defaults
4226684e68SGreg Roach    private const DEFAULT_GENERATIONS         = '3';
4326684e68SGreg Roach    private const DEFAULT_MAXIMUM_GENERATIONS = '9';
4426684e68SGreg Roach
4526684e68SGreg Roach    // Limits
46e759aebbSGreg Roach    private const MAXIMUM_GENERATIONS = 10;
4726684e68SGreg Roach    private const MINIMUM_GENERATIONS = 2;
4826684e68SGreg Roach
49168ff6f3Sric2016    /**
500cfd6963SGreg Roach     * How should this module be identified in the control panel, etc.?
51168ff6f3Sric2016     *
52168ff6f3Sric2016     * @return string
53168ff6f3Sric2016     */
5449a243cbSGreg Roach    public function title(): string
55c1010edaSGreg Roach    {
56bbb76c12SGreg Roach        /* I18N: Name of a module/chart */
57bbb76c12SGreg Roach        return I18N::translate('Hourglass chart');
58168ff6f3Sric2016    }
59168ff6f3Sric2016
60168ff6f3Sric2016    /**
61168ff6f3Sric2016     * A sentence describing what this module does.
62168ff6f3Sric2016     *
63168ff6f3Sric2016     * @return string
64168ff6f3Sric2016     */
6549a243cbSGreg Roach    public function description(): string
66c1010edaSGreg Roach    {
67bbb76c12SGreg Roach        /* I18N: Description of the “HourglassChart” module */
68bbb76c12SGreg Roach        return I18N::translate('An hourglass chart of an individual’s ancestors and descendants.');
69168ff6f3Sric2016    }
70168ff6f3Sric2016
71168ff6f3Sric2016    /**
72377a2979SGreg Roach     * CSS class for the URL.
73377a2979SGreg Roach     *
74377a2979SGreg Roach     * @return string
75377a2979SGreg Roach     */
76377a2979SGreg Roach    public function chartMenuClass(): string
77377a2979SGreg Roach    {
78377a2979SGreg Roach        return 'menu-chart-hourglass';
79377a2979SGreg Roach    }
80377a2979SGreg Roach
81377a2979SGreg Roach    /**
824eb71cfaSGreg Roach     * Return a menu item for this chart - for use in individual boxes.
834eb71cfaSGreg Roach     *
8460bc3e3fSGreg Roach     * @param Individual $individual
8560bc3e3fSGreg Roach     *
864eb71cfaSGreg Roach     * @return Menu|null
874eb71cfaSGreg Roach     */
88377a2979SGreg Roach    public function chartBoxMenu(Individual $individual): ?Menu
89c1010edaSGreg Roach    {
90e6562982SGreg Roach        return $this->chartMenu($individual);
91e6562982SGreg Roach    }
92e6562982SGreg Roach
93e6562982SGreg Roach    /**
9426684e68SGreg Roach     * A form to request the chart parameters.
95e6562982SGreg Roach     *
966ccdf4f0SGreg Roach     * @param ServerRequestInterface $request
9726684e68SGreg Roach     * @param Tree                   $tree
98e5a6b4d4SGreg Roach     * @param UserInterface          $user
99e6562982SGreg Roach     *
1006ccdf4f0SGreg Roach     * @return ResponseInterface
101e6562982SGreg Roach     */
1026ccdf4f0SGreg Roach    public function getChartAction(ServerRequestInterface $request, Tree $tree, UserInterface $user): ResponseInterface
103e6562982SGreg Roach    {
1049b5537c3SGreg Roach        $ajax       = (bool) $request->get('ajax');
10526684e68SGreg Roach        $xref       = $request->get('xref', '');
10626684e68SGreg Roach        $individual = Individual::getInstance($xref, $tree);
10726684e68SGreg Roach
10826684e68SGreg Roach        Auth::checkIndividualAccess($individual);
1099867b2f0SGreg Roach        Auth::checkComponentAccess($this, 'chart', $tree, $user);
11026684e68SGreg Roach
111e759aebbSGreg Roach        $generations = (int) $request->get('generations', self::DEFAULT_GENERATIONS);
11226684e68SGreg Roach
113e759aebbSGreg Roach        $generations = min($generations, self::MAXIMUM_GENERATIONS);
11426684e68SGreg Roach        $generations = max($generations, self::MINIMUM_GENERATIONS);
11526684e68SGreg Roach
11626684e68SGreg Roach        $show_spouse = (bool) $request->get('show_spouse');
11726684e68SGreg Roach
1189b5537c3SGreg Roach        if ($ajax) {
11926684e68SGreg Roach            return $this->chart($individual, $generations, $show_spouse);
12026684e68SGreg Roach        }
12126684e68SGreg Roach
12226684e68SGreg Roach        $ajax_url = $this->chartUrl($individual, [
1239b5537c3SGreg Roach            'ajax'        => true,
1242b29a33eSmakitso            'generations' => $generations,
1252f0ffe95SGreg Roach            'show_spouse' => $show_spouse,
12626684e68SGreg Roach        ]);
12726684e68SGreg Roach
1289b5537c3SGreg Roach        return $this->viewResponse('modules/hourglass-chart/page', [
12926684e68SGreg Roach            'ajax_url'            => $ajax_url,
13026684e68SGreg Roach            'generations'         => $generations,
13126684e68SGreg Roach            'individual'          => $individual,
132e759aebbSGreg Roach            'maximum_generations' => self::MAXIMUM_GENERATIONS,
13326684e68SGreg Roach            'minimum_generations' => self::MINIMUM_GENERATIONS,
13426684e68SGreg Roach            'module_name'         => $this->name(),
13526684e68SGreg Roach            'show_spouse'         => $show_spouse,
13626684e68SGreg Roach            'title'               => $this->chartTitle($individual),
13726684e68SGreg Roach        ]);
13826684e68SGreg Roach    }
13926684e68SGreg Roach
14026684e68SGreg Roach    /**
14126684e68SGreg Roach     * Generate the initial generations of the chart
14226684e68SGreg Roach     *
143e5a6b4d4SGreg Roach     * @param Individual $individual
144e5a6b4d4SGreg Roach     * @param int        $generations
145e5a6b4d4SGreg Roach     * @param bool       $show_spouse
14626684e68SGreg Roach     *
1476ccdf4f0SGreg Roach     * @return ResponseInterface
14826684e68SGreg Roach     */
1496ccdf4f0SGreg Roach    protected function chart(Individual $individual, int $generations, bool $show_spouse): ResponseInterface
15026684e68SGreg Roach    {
151*cb0eb4a9SGreg Roach        $this->layout = 'layouts/ajax';
15226684e68SGreg Roach
153*cb0eb4a9SGreg Roach        return $this->viewResponse('modules/hourglass-chart/chart', [
154*cb0eb4a9SGreg Roach            'generations' => $generations,
155*cb0eb4a9SGreg Roach            'individual'  => $individual,
156*cb0eb4a9SGreg Roach            'show_spouse' => $show_spouse,
157*cb0eb4a9SGreg Roach        ]);
158*cb0eb4a9SGreg Roach    }
15926684e68SGreg Roach
160*cb0eb4a9SGreg Roach    /**
161*cb0eb4a9SGreg Roach     * Generate an extension to the chart
162*cb0eb4a9SGreg Roach     *
163*cb0eb4a9SGreg Roach     * @param ServerRequestInterface $request
164*cb0eb4a9SGreg Roach     *
165*cb0eb4a9SGreg Roach     * @return ResponseInterface
166*cb0eb4a9SGreg Roach     */
167*cb0eb4a9SGreg Roach    public function getAncestorsAction(ServerRequestInterface $request): ResponseInterface
168*cb0eb4a9SGreg Roach    {
169*cb0eb4a9SGreg Roach        $tree = app(Tree::class);
170*cb0eb4a9SGreg Roach        $xref = $request->getQueryParams()['xref'] ?? '';
171*cb0eb4a9SGreg Roach
172*cb0eb4a9SGreg Roach        $family = Family::getInstance($xref, $tree);
173*cb0eb4a9SGreg Roach        Auth::checkFamilyAccess($family);
174*cb0eb4a9SGreg Roach
175*cb0eb4a9SGreg Roach        return response(view('modules/hourglass-chart/parents', [
176*cb0eb4a9SGreg Roach            'family'      => $family,
177*cb0eb4a9SGreg Roach            'generations' => 1,
17826684e68SGreg Roach        ]));
17926684e68SGreg Roach    }
18026684e68SGreg Roach
18126684e68SGreg Roach    /**
182*cb0eb4a9SGreg Roach     * Generate an extension to the chart
183*cb0eb4a9SGreg Roach     *
1846ccdf4f0SGreg Roach     * @param ServerRequestInterface $request
18526684e68SGreg Roach     *
1866ccdf4f0SGreg Roach     * @return ResponseInterface
18726684e68SGreg Roach     */
188*cb0eb4a9SGreg Roach    public function getDescendantsAction(ServerRequestInterface $request): ResponseInterface
18926684e68SGreg Roach    {
190*cb0eb4a9SGreg Roach        $tree = app(Tree::class);
191*cb0eb4a9SGreg Roach        $xref = $request->getQueryParams()['xref'] ?? '';
19226684e68SGreg Roach
193*cb0eb4a9SGreg Roach        $show_spouse = (bool) ($request->getQueryParams()['show_spouse'] ?? false);
194*cb0eb4a9SGreg Roach        $individual  = Individual::getInstance($xref, $tree);
19526684e68SGreg Roach        Auth::checkIndividualAccess($individual);
196*cb0eb4a9SGreg Roach        $children = $individual->spouseFamilies()->map(static function (Family $family): Collection { return $family->children(); })->flatten();
19726684e68SGreg Roach
198*cb0eb4a9SGreg Roach        return response(view('modules/hourglass-chart/children', [
199*cb0eb4a9SGreg Roach            'children'    => $children,
200*cb0eb4a9SGreg Roach            'generations' => 1,
201*cb0eb4a9SGreg Roach            'show_spouse' => $show_spouse,
202*cb0eb4a9SGreg Roach        ]));
203e6562982SGreg Roach    }
204168ff6f3Sric2016}
205