Passed
Push — master ( 01202f...713784 )
by Greg
07:38
created

FamilyBookChartModule::getChartAction()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 42
Code Lines 31

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 31
nc 2
nop 1
dl 0
loc 42
rs 9.424
c 0
b 0
f 0

3 Methods

Rating   Name   Duplication   Size   Complexity  
A FamilyBookChartModule::chartBoxMenu() 0 3 1
A FamilyBookChartModule::chartTitle() 0 4 1
A FamilyBookChartModule::chartUrl() 0 6 1
1
<?php
2
3
/**
4
 * webtrees: online genealogy
5
 * Copyright (C) 2019 webtrees development team
6
 * This program is free software: you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation, either version 3 of the License, or
9
 * (at your option) any later version.
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
 * GNU General Public License for more details.
14
 * You should have received a copy of the GNU General Public License
15
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16
 */
17
declare(strict_types=1);
18
19
namespace Fisharebest\Webtrees\Module;
20
21
use Aura\Router\RouterContainer;
22
use Fig\Http\Message\RequestMethodInterface;
23
use Fisharebest\Webtrees\Auth;
24
use Fisharebest\Webtrees\I18N;
25
use Fisharebest\Webtrees\Individual;
26
use Fisharebest\Webtrees\Menu;
27
use Psr\Http\Message\ResponseInterface;
28
use Psr\Http\Message\ServerRequestInterface;
29
use Psr\Http\Server\RequestHandlerInterface;
30
31
use function max;
32
use function min;
33
use function route;
34
35
/**
36
 * Class FamilyBookChartModule
37
 */
38
class FamilyBookChartModule extends AbstractModule implements ModuleChartInterface, RequestHandlerInterface
39
{
40
    use ModuleChartTrait;
41
42
    private const ROUTE_NAME = 'family-book-chart';
43
    private const ROUTE_URL  = '/tree/{tree}/family-book-{book_size}-{generations}-{spouses}/{xref}';
44
45
    // Defaults
46
    public const    DEFAULT_GENERATIONS            = '2';
47
    public const    DEFAULT_DESCENDANT_GENERATIONS = '5';
48
    public const    DEFAULT_MAXIMUM_GENERATIONS    = '9';
49
    protected const DEFAULT_PARAMETERS             = [
50
        'book_size'   => self::DEFAULT_GENERATIONS,
51
        'generations' => self::DEFAULT_DESCENDANT_GENERATIONS,
52
        'spouses'     => false,
53
    ];
54
55
    // Limits
56
    protected const MINIMUM_GENERATIONS = 2;
57
    protected const MAXIMUM_GENERATIONS = 10;
58
59
    /**
60
     * Initialization.
61
     *
62
     * @param RouterContainer $router_container
63
     */
64
    public function boot(RouterContainer $router_container)
65
    {
66
        $router_container->getMap()
67
            ->get(self::ROUTE_NAME, self::ROUTE_URL, self::class)
68
            ->allows(RequestMethodInterface::METHOD_POST)
69
            ->tokens([
70
                'book_size'   => '\d+',
71
                'generations' => '\d+',
72
                'spouses'     => '1?',
73
            ]);
74
    }
75
76
    /**
77
     * How should this module be identified in the control panel, etc.?
78
     *
79
     * @return string
80
     */
81
    public function title(): string
82
    {
83
        /* I18N: Name of a module/chart */
84
        return I18N::translate('Family book');
85
    }
86
87
    /**
88
     * A sentence describing what this module does.
89
     *
90
     * @return string
91
     */
92
    public function description(): string
93
    {
94
        /* I18N: Description of the “FamilyBookChart” module */
95
        return I18N::translate('A chart of an individual’s ancestors and descendants, as a family book.');
96
    }
97
98
    /**
99
     * CSS class for the URL.
100
     *
101
     * @return string
102
     */
103
    public function chartMenuClass(): string
104
    {
105
        return 'menu-chart-familybook';
106
    }
107
108
    /**
109
     * Return a menu item for this chart - for use in individual boxes.
110
     *
111
     * @param Individual $individual
112
     *
113
     * @return Menu|null
114
     */
115
    public function chartBoxMenu(Individual $individual): ?Menu
116
    {
117
        return $this->chartMenu($individual);
118
    }
119
120
    /**
121
     * The title for a specific instance of this chart.
122
     *
123
     * @param Individual $individual
124
     *
125
     * @return string
126
     */
127
    public function chartTitle(Individual $individual): string
128
    {
129
        /* I18N: %s is an individual’s name */
130
        return I18N::translate('Family book of %s', $individual->fullName());
131
    }
132
133
    /**
134
     * The URL for a page showing chart options.
135
     *
136
     * @param Individual $individual
137
     * @param string[]   $parameters
138
     *
139
     * @return string
140
     */
141
    public function chartUrl(Individual $individual, array $parameters = []): string
142
    {
143
        return route(self::ROUTE_NAME, [
144
                'xref' => $individual->xref(),
145
                'tree' => $individual->tree()->name(),
146
            ] + $parameters + self::DEFAULT_PARAMETERS);
147
    }
148
149
    /**
150
     * @param ServerRequestInterface $request
151
     *
152
     * @return ResponseInterface
153
     */
154
    public function handle(ServerRequestInterface $request): ResponseInterface
155
    {
156
        $tree        = $request->getAttribute('tree');
157
        $user        = $request->getAttribute('user');
158
        $xref        = $request->getAttribute('xref');
159
        $book_size   = (int) $request->getAttribute('book_size');
160
        $generations = (int) $request->getAttribute('generations');
161
        $spouses     = (bool) $request->getAttribute('spouses');
162
        $ajax        = $request->getQueryParams()['ajax'] ?? '';
163
        $individual  = Individual::getInstance($xref, $tree);
164
165
        // Convert POST requests into GET requests for pretty URLs.
166
        if ($request->getMethod() === RequestMethodInterface::METHOD_POST) {
167
            return redirect(route(self::ROUTE_NAME, [
168
                'tree'        => $request->getAttribute('tree')->name(),
169
                'xref'        => $request->getParsedBody()['xref'],
170
                'book_size'   => $request->getParsedBody()['book_size'],
171
                'generations' => $request->getParsedBody()['generations'],
172
                'spouses'     => $request->getParsedBody()['spouses'] ?? false,
173
            ]));
174
        }
175
176
        Auth::checkIndividualAccess($individual);
177
        Auth::checkComponentAccess($this, 'chart', $tree, $user);
178
179
        $generations = min($generations, self::MAXIMUM_GENERATIONS);
180
        $generations = max($generations, self::MINIMUM_GENERATIONS);
181
182
        // Generations of ancestors/descendants in each mini-tree.
183
        $book_size = min($book_size, 5);
184
        $book_size = max($book_size, 2);
185
186
        if ($ajax === '1') {
187
            $this->layout = 'layouts/ajax';
188
189
            return $this->viewResponse('modules/family-book-chart/chart', [
190
                'individual'  => $individual,
191
                'generations' => $generations,
192
                'book_size'   => $book_size,
193
                'spouses'     => $spouses,
194
            ]);
195
        }
196
197
        $ajax_url = $this->chartUrl($individual, [
198
            'ajax'        => true,
199
            'book_size'   => $book_size,
200
            'generations' => $generations,
201
            'spouses'     => $spouses,
202
        ]);
203
204
        return $this->viewResponse('modules/family-book-chart/page', [
205
            'ajax_url'            => $ajax_url,
206
            'book_size'           => $book_size,
207
            'generations'         => $generations,
208
            'individual'          => $individual,
209
            'maximum_generations' => self::MAXIMUM_GENERATIONS,
210
            'minimum_generations' => self::MINIMUM_GENERATIONS,
211
            'module'              => $this->name(),
212
            'spouses'             => $spouses,
213
            'title'               => $this->chartTitle($individual),
214
        ]);
215
    }
216
}
217