Passed
Pull Request — main (#4796)
by
unknown
05:51
created

ChartsBlockModule::editBlockConfiguration()   B

Complexity

Conditions 6
Paths 16

Size

Total Lines 59
Code Lines 47

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 47
nc 16
nop 2
dl 0
loc 59
rs 8.5341
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * webtrees: online genealogy
5
 * Copyright (C) 2023 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 <https://www.gnu.org/licenses/>.
16
 */
17
18
declare(strict_types=1);
19
20
namespace Fisharebest\Webtrees\Module;
21
22
use Fisharebest\Webtrees\Auth;
23
use Fisharebest\Webtrees\Contracts\UserInterface;
24
use Fisharebest\Webtrees\I18N;
25
use Fisharebest\Webtrees\Individual;
26
use Fisharebest\Webtrees\Module\InteractiveTree\TreeView;
27
use Fisharebest\Webtrees\Registry;
28
use Fisharebest\Webtrees\Services\ModuleService;
29
use Fisharebest\Webtrees\Tree;
30
use Fisharebest\Webtrees\Validator;
31
use Illuminate\Support\Str;
32
use Psr\Http\Message\ServerRequestInterface;
33
34
use function extract;
35
use function uasort;
36
use function view;
37
38
use const EXTR_OVERWRITE;
39
40
/**
41
 * Class ChartsBlockModule
42
 */
43
class ChartsBlockModule extends AbstractModule implements ModuleBlockInterface
44
{
45
    use ModuleBlockTrait;
46
47
    private ModuleService $module_service;
48
49
    /**
50
     * ChartsBlockModule constructor.
51
     *
52
     * @param ModuleService $module_service
53
     */
54
    public function __construct(ModuleService $module_service)
55
    {
56
        $this->module_service = $module_service;
57
    }
58
59
    /**
60
     * How should this module be identified in the control panel, etc.?
61
     *
62
     * @return string
63
     */
64
    public function title(): string
65
    {
66
        /* I18N: Name of a module/block */
67
        return I18N::translate('Charts');
68
    }
69
70
    /**
71
     * A sentence describing what this module does.
72
     *
73
     * @return string
74
     */
75
    public function description(): string
76
    {
77
        /* I18N: Description of the “Charts” module */
78
        return I18N::translate('An alternative way to display charts.');
79
    }
80
81
    /**
82
     * Generate the HTML content of this block.
83
     *
84
     * @param Tree                 $tree
85
     * @param int                  $block_id
86
     * @param string               $context
87
     * @param array<string,string> $config
88
     *
89
     * @return string
90
     */
91
    public function getBlock(Tree $tree, int $block_id, string $context, array $config = []): string
92
    {
93
        $PEDIGREE_ROOT_ID = $tree->getPreference('PEDIGREE_ROOT_ID');
94
        $gedcomid         = $tree->getUserPreference(Auth::user(), UserInterface::PREF_TREE_ACCOUNT_XREF);
95
        $default_xref     = $gedcomid ?: $PEDIGREE_ROOT_ID;
96
97
        $type = $this->getBlockSetting($block_id, 'type', 'pedigree');
98
        $xref = $this->getBlockSetting($block_id, 'pid', $default_xref);
99
100
        extract($config, EXTR_OVERWRITE);
101
102
        $individual = Registry::individualFactory()->make($xref, $tree);
103
104
        $title = $this->title();
105
106
        if ($individual instanceof Individual) {
107
            switch ($type) {
108
                default:
109
                case 'pedigree':
110
                    $module = $this->module_service->findByInterface(PedigreeChartModule::class)->first();
111
                    if ($module instanceof PedigreeChartModule) {
112
                        $title     = $module->chartTitle($individual);
113
                        $chart_url = $module->chartUrl($individual, [
114
                            'ajax'        => true,
115
                            'generations' => $this->getBlockSetting($block_id, 'pedigree_generations', '3'),
116
                            'layout'      => $this->getBlockSetting($block_id, 'pedigree_style',
117
                                PedigreeChartModule::DEFAULT_STYLE),
118
                            'style'       => $this->getBlockSetting($block_id, 'pedigree_style',
119
                                PedigreeChartModule::DEFAULT_STYLE),
120
                            // Note: some modules use 'layout', others 'style'
121
                        ]);
122
                        $content   = view('modules/charts/chart', [
123
                            'block_id'  => $block_id,
124
                            'chart_url' => $chart_url,
125
                        ]);
126
                    } else {
127
                        $title   = I18N::translate('Pedigree');
128
                        $content = I18N::translate('The module “%s” has been disabled.', $title);
129
                    }
130
                    break;
131
132
                case 'descendants':
133
                    $module = $this->module_service->findByInterface(DescendancyChartModule::class)->first();
134
135
                    if ($module instanceof DescendancyChartModule) {
136
                        $title     = $module->chartTitle($individual);
137
                        $chart_url = $module->chartUrl($individual, [
138
                            'ajax'        => true,
139
                            'generations' => $this->getBlockSetting($block_id, 'descendants_generations', '2'),
140
                            'chart_style' => DescendancyChartModule::CHART_STYLE_TREE,
141
                        ]);
142
                        $content   = view('modules/charts/chart', [
143
                            'block_id'  => $block_id,
144
                            'chart_url' => $chart_url,
145
                        ]);
146
                    } else {
147
                        $title   = I18N::translate('Descendants');
148
                        $content = I18N::translate('The module “%s” has been disabled.', $title);
149
                    }
150
151
                    break;
152
153
                case 'hourglass':
154
                    $module = $this->module_service->findByInterface(HourglassChartModule::class)->first();
155
156
                    if ($module instanceof HourglassChartModule) {
157
                        $title     = $module->chartTitle($individual);
158
                        $chart_url = $module->chartUrl($individual, [
159
                            'ajax'        => true,
160
                            'generations' => $this->getBlockSetting($block_id, 'hourglass_generations', '2'),
161
                        ]);
162
                        $content   = view('modules/charts/chart', [
163
                            'block_id'  => $block_id,
164
                            'chart_url' => $chart_url,
165
                        ]);
166
                    } else {
167
                        $title   = I18N::translate('Hourglass chart');
168
                        $content = I18N::translate('The module “%s” has been disabled.', $title);
169
                    }
170
                    break;
171
172
                case 'treenav':
173
                    $module = $this->module_service->findByInterface(InteractiveTreeModule::class)->first();
174
175
                    if ($module instanceof InteractiveTreeModule) {
176
                        $title  = I18N::translate('Interactive tree of %s', $individual->fullName());
177
                        $tv     = new TreeView();
178
                        [$html, $js] = $tv->drawViewport($individual, 2);
179
                        $content = $html . '<script>' . $js . '</script>';
180
                    } else {
181
                        $title   = I18N::translate('Interactive tree');
182
                        $content = I18N::translate('The module “%s” has been disabled.', $title);
183
                    }
184
185
                    break;
186
            }
187
        } else {
188
            $content = I18N::translate('You must select an individual and a chart type in the block preferences');
189
        }
190
191
        if ($context !== self::CONTEXT_EMBED) {
192
            return view('modules/block-template', [
193
                'block'      => Str::kebab($this->name()),
194
                'id'         => $block_id,
195
                'config_url' => $this->configUrl($tree, $context, $block_id),
196
                'title'      => $title,
197
                'content'    => $content,
198
            ]);
199
        }
200
201
        return $content;
202
    }
203
204
    /**
205
     * Should this block load asynchronously using AJAX?
206
     *
207
     * Simple blocks are faster in-line, more complex ones can be loaded later.
208
     *
209
     * @return bool
210
     */
211
    public function loadAjax(): bool
212
    {
213
        return true;
214
    }
215
216
    /**
217
     * Can this block be shown on the tree’s home page?
218
     *
219
     * @return bool
220
     */
221
    public function isTreeBlock(): bool
222
    {
223
        return true;
224
    }
225
226
    /**
227
     * Update the configuration for a block.
228
     *
229
     * @param ServerRequestInterface $request
230
     * @param int     $block_id
231
     *
232
     * @return void
233
     */
234
    public function saveBlockConfiguration(ServerRequestInterface $request, int $block_id): void
235
    {
236
        $type = Validator::parsedBody($request)->string('type');
237
        $xref = Validator::parsedBody($request)->isXref()->string('xref');
238
        $pedigree_generations = Validator::parsedBody($request)->integer('pedigree_generations');
239
        $pedigree_style = Validator::parsedBody($request)->string('pedigree_style');
240
        $descendants_generations = Validator::parsedBody($request)->integer('descendants_generations');
241
        $hourglass_generations = Validator::parsedBody($request)->integer('hourglass_generations');
242
243
        $this->setBlockSetting($block_id, 'type', $type);
244
        $this->setBlockSetting($block_id, 'pid', $xref);
245
        $this->setBlockSetting($block_id, 'pedigree_generations', (string) $pedigree_generations);
246
        $this->setBlockSetting($block_id, 'pedigree_style', $pedigree_style);
247
        $this->setBlockSetting($block_id, 'descendants_generations', (string) $descendants_generations);
248
        $this->setBlockSetting($block_id, 'hourglass_generations', (string) $hourglass_generations);
249
    }
250
251
    /**
252
     * An HTML form to edit block settings
253
     *
254
     * @param Tree $tree
255
     * @param int  $block_id
256
     *
257
     * @return string
258
     */
259
    public function editBlockConfiguration(Tree $tree, int $block_id): string
260
    {
261
        $PEDIGREE_ROOT_ID = $tree->getPreference('PEDIGREE_ROOT_ID');
262
        $gedcomid         = $tree->getUserPreference(Auth::user(), UserInterface::PREF_TREE_ACCOUNT_XREF);
263
        $default_xref     = $gedcomid ?: $PEDIGREE_ROOT_ID;
264
265
        $type = $this->getBlockSetting($block_id, 'type', 'pedigree');
266
        $xref = $this->getBlockSetting($block_id, 'pid', $default_xref);
267
268
        $charts = [];
269
        // Only add charts that are available
270
        $pedigreeModule = $this->module_service->findByInterface(PedigreeChartModule::class)->first();
271
        if ($pedigreeModule instanceof PedigreeChartModule) {
272
            $charts['pedigree'] = I18N::translate('Pedigree');
273
            $pedigree_max_generations = $pedigreeModule::MAXIMUM_GENERATIONS;
274
            $pedigree_min_generations = $pedigreeModule::MINIMUM_GENERATIONS;
275
            $pedigree_styles = $pedigreeModule->styles(I18N::direction());
276
        }
277
        $descendantsModule = $this->module_service->findByInterface(DescendancyChartModule::class)->first();
278
        if ($descendantsModule instanceof DescendancyChartModule) {
279
            $charts['descendants'] = I18N::translate('Descendants');
280
            $descendants_max_generations = $descendantsModule::MAXIMUM_GENERATIONS;
281
            $descendants_min_generations = $descendantsModule::MINIMUM_GENERATIONS;
282
        }
283
        $hourglassModule = $this->module_service->findByInterface(HourglassChartModule::class)->first();
284
        if ($hourglassModule instanceof HourglassChartModule) {
285
            $charts['hourglass'] = I18N::translate('Hourglass chart');
286
            $hourglass_max_generations = $hourglassModule::MAXIMUM_GENERATIONS;
287
            $hourglass_min_generations = $hourglassModule::MINIMUM_GENERATIONS;
288
        }
289
        $treeModule = $this->module_service->findByInterface(InteractiveTreeModule::class)->first();
290
        if ($treeModule instanceof InteractiveTreeModule) {
291
            $charts['treenav'] = I18N::translate('Interactive tree');
292
        }
293
        uasort($charts, I18N::comparator());
294
295
        $pedigree_generations = $this->getBlockSetting($block_id, 'pedigree_generations', '3');
296
        $pedigree_style = $this->getBlockSetting($block_id, 'pedigree_style', $pedigreeModule::DEFAULT_STYLE);
297
        $descendants_generations = $this->getBlockSetting($block_id, 'descendants_generations', '2');
298
        $hourglass_generations = $this->getBlockSetting($block_id, 'hourglass_generations', '2');
299
300
        $individual = Registry::individualFactory()->make($xref, $tree);
301
302
        return view('modules/charts/config', [
303
            'charts'                      => $charts,
304
            'individual'                  => $individual,
305
            'tree'                        => $tree,
306
            'type'                        => $type,
307
            'pedigree_generations'        => $pedigree_generations ?? null,
308
            'pedigree_max_generations'    => $pedigree_max_generations ?? null,
309
            'pedigree_min_generations'    => $pedigree_min_generations ?? null,
310
            'pedigree_style'              => $pedigree_style ?? null,
311
            'pedigree_styles'             => $pedigree_styles ?? null,
312
            'descendants_generations'     => $descendants_generations ?? null,
313
            'descendants_max_generations' => $descendants_max_generations ?? null,
314
            'descendants_min_generations' => $descendants_min_generations ?? null,
315
            'hourglass_generations'       => $hourglass_generations ?? null,
316
            'hourglass_max_generations'   => $hourglass_max_generations ?? null,
317
            'hourglass_min_generations'   => $hourglass_min_generations ?? null,
318
        ]);
319
    }
320
}
321