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