Passed
Pull Request — main (#4796)
by
unknown
05:59
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
                            'style'       => $this->getBlockSetting($block_id, 'pedigree_style',
117
                                PedigreeChartModule::DEFAULT_STYLE),
118
                        ]);
119
                        $content   = view('modules/charts/chart', [
120
                            'block_id'  => $block_id,
121
                            'chart_url' => $chart_url,
122
                        ]);
123
                    } else {
124
                        $title   = I18N::translate('Pedigree');
125
                        $content = I18N::translate('The module “%s” has been disabled.', $title);
126
                    }
127
                    break;
128
129
                case 'descendants':
130
                    $module = $this->module_service->findByInterface(DescendancyChartModule::class)->first();
131
132
                    if ($module instanceof DescendancyChartModule) {
133
                        $title     = $module->chartTitle($individual);
134
                        $chart_url = $module->chartUrl($individual, [
135
                            'ajax'        => true,
136
                            'generations' => $this->getBlockSetting($block_id, 'descendants_generations', '2'),
137
                            'chart_style' => DescendancyChartModule::CHART_STYLE_TREE,
138
                        ]);
139
                        $content   = view('modules/charts/chart', [
140
                            'block_id'  => $block_id,
141
                            'chart_url' => $chart_url,
142
                        ]);
143
                    } else {
144
                        $title   = I18N::translate('Descendants');
145
                        $content = I18N::translate('The module “%s” has been disabled.', $title);
146
                    }
147
148
                    break;
149
150
                case 'hourglass':
151
                    $module = $this->module_service->findByInterface(HourglassChartModule::class)->first();
152
153
                    if ($module instanceof HourglassChartModule) {
154
                        $title     = $module->chartTitle($individual);
155
                        $chart_url = $module->chartUrl($individual, [
156
                            'ajax'        => true,
157
                            'generations' => $this->getBlockSetting($block_id, 'hourglass_generations', '2'),
158
                        ]);
159
                        $content   = view('modules/charts/chart', [
160
                            'block_id'  => $block_id,
161
                            'chart_url' => $chart_url,
162
                        ]);
163
                    } else {
164
                        $title   = I18N::translate('Hourglass chart');
165
                        $content = I18N::translate('The module “%s” has been disabled.', $title);
166
                    }
167
                    break;
168
169
                case 'treenav':
170
                    $module = $this->module_service->findByInterface(InteractiveTreeModule::class)->first();
171
172
                    if ($module instanceof InteractiveTreeModule) {
173
                        $title  = I18N::translate('Interactive tree of %s', $individual->fullName());
174
                        $tv     = new TreeView();
175
                        [$html, $js] = $tv->drawViewport($individual, 2);
176
                        $content = $html . '<script>' . $js . '</script>';
177
                    } else {
178
                        $title   = I18N::translate('Interactive tree');
179
                        $content = I18N::translate('The module “%s” has been disabled.', $title);
180
                    }
181
182
                    break;
183
            }
184
        } else {
185
            $content = I18N::translate('You must select an individual and a chart type in the block preferences');
186
        }
187
188
        if ($context !== self::CONTEXT_EMBED) {
189
            return view('modules/block-template', [
190
                'block'      => Str::kebab($this->name()),
191
                'id'         => $block_id,
192
                'config_url' => $this->configUrl($tree, $context, $block_id),
193
                'title'      => $title,
194
                'content'    => $content,
195
            ]);
196
        }
197
198
        return $content;
199
    }
200
201
    /**
202
     * Should this block load asynchronously using AJAX?
203
     *
204
     * Simple blocks are faster in-line, more complex ones can be loaded later.
205
     *
206
     * @return bool
207
     */
208
    public function loadAjax(): bool
209
    {
210
        return true;
211
    }
212
213
    /**
214
     * Can this block be shown on the tree’s home page?
215
     *
216
     * @return bool
217
     */
218
    public function isTreeBlock(): bool
219
    {
220
        return true;
221
    }
222
223
    /**
224
     * Update the configuration for a block.
225
     *
226
     * @param ServerRequestInterface $request
227
     * @param int     $block_id
228
     *
229
     * @return void
230
     */
231
    public function saveBlockConfiguration(ServerRequestInterface $request, int $block_id): void
232
    {
233
        $type = Validator::parsedBody($request)->string('type');
234
        $xref = Validator::parsedBody($request)->isXref()->string('xref');
235
        $pedigree_generations = Validator::parsedBody($request)->integer('pedigree_generations');
236
        $pedigree_style = Validator::parsedBody($request)->string('pedigree_style');
237
        $descendants_generations = Validator::parsedBody($request)->integer('descendants_generations');
238
        $hourglass_generations = Validator::parsedBody($request)->integer('hourglass_generations');
239
240
        $this->setBlockSetting($block_id, 'type', $type);
241
        $this->setBlockSetting($block_id, 'pid', $xref);
242
        $this->setBlockSetting($block_id, 'pedigree_generations', (string) $pedigree_generations);
243
        $this->setBlockSetting($block_id, 'pedigree_style', $pedigree_style);
244
        $this->setBlockSetting($block_id, 'descendants_generations', (string) $descendants_generations);
245
        $this->setBlockSetting($block_id, 'hourglass_generations', (string) $hourglass_generations);
246
    }
247
248
    /**
249
     * An HTML form to edit block settings
250
     *
251
     * @param Tree $tree
252
     * @param int  $block_id
253
     *
254
     * @return string
255
     */
256
    public function editBlockConfiguration(Tree $tree, int $block_id): string
257
    {
258
        $PEDIGREE_ROOT_ID = $tree->getPreference('PEDIGREE_ROOT_ID');
259
        $gedcomid         = $tree->getUserPreference(Auth::user(), UserInterface::PREF_TREE_ACCOUNT_XREF);
260
        $default_xref     = $gedcomid ?: $PEDIGREE_ROOT_ID;
261
262
        $type = $this->getBlockSetting($block_id, 'type', 'pedigree');
263
        $xref = $this->getBlockSetting($block_id, 'pid', $default_xref);
264
265
        $charts = [];
266
        // Only add charts that are available
267
        $pedigreeModule = $this->module_service->findByInterface(PedigreeChartModule::class)->first();
268
        if ($pedigreeModule instanceof PedigreeChartModule) {
269
            $charts['pedigree'] = I18N::translate('Pedigree');
270
            $pedigree_max_generations = $pedigreeModule::MAXIMUM_GENERATIONS;
271
            $pedigree_min_generations = $pedigreeModule::MINIMUM_GENERATIONS;
272
            $pedigree_styles = $pedigreeModule->styles(I18N::direction());
273
        }
274
        $descendantsModule = $this->module_service->findByInterface(DescendancyChartModule::class)->first();
275
        if ($descendantsModule instanceof DescendancyChartModule) {
276
            $charts['descendants'] = I18N::translate('Descendants');
277
            $descendants_max_generations = $descendantsModule::MAXIMUM_GENERATIONS;
278
            $descendants_min_generations = $descendantsModule::MINIMUM_GENERATIONS;
279
        }
280
        $hourglassModule = $this->module_service->findByInterface(HourglassChartModule::class)->first();
281
        if ($hourglassModule instanceof HourglassChartModule) {
282
            $charts['hourglass'] = I18N::translate('Hourglass chart');
283
            $hourglass_max_generations = $hourglassModule::MAXIMUM_GENERATIONS;
284
            $hourglass_min_generations = $hourglassModule::MINIMUM_GENERATIONS;
285
        }
286
        $treeModule = $this->module_service->findByInterface(InteractiveTreeModule::class)->first();
287
        if ($treeModule instanceof InteractiveTreeModule) {
288
            $charts['treenav'] = I18N::translate('Interactive tree');
289
        }
290
        uasort($charts, I18N::comparator());
291
292
        $pedigree_generations = $this->getBlockSetting($block_id, 'pedigree_generations', '3');
293
        $pedigree_style = $this->getBlockSetting($block_id, 'pedigree_style', $pedigreeModule::DEFAULT_STYLE);
294
        $descendants_generations = $this->getBlockSetting($block_id, 'descendants_generations', '2');
295
        $hourglass_generations = $this->getBlockSetting($block_id, 'hourglass_generations', '2');
296
297
        $individual = Registry::individualFactory()->make($xref, $tree);
298
299
        return view('modules/charts/config', [
300
            'charts'                      => $charts,
301
            'individual'                  => $individual,
302
            'tree'                        => $tree,
303
            'type'                        => $type,
304
            'pedigree_generations'        => $pedigree_generations ?? null,
305
            'pedigree_max_generations'    => $pedigree_max_generations ?? null,
306
            'pedigree_min_generations'    => $pedigree_min_generations ?? null,
307
            'pedigree_style'              => $pedigree_style ?? null,
308
            'pedigree_styles'             => $pedigree_styles ?? null,
309
            'descendants_generations'     => $descendants_generations ?? null,
310
            'descendants_max_generations' => $descendants_max_generations ?? null,
311
            'descendants_min_generations' => $descendants_min_generations ?? null,
312
            'hourglass_generations'       => $hourglass_generations ?? null,
313
            'hourglass_max_generations'   => $hourglass_max_generations ?? null,
314
            'hourglass_min_generations'   => $hourglass_min_generations ?? null,
315
        ]);
316
    }
317
}
318