Passed
Push — feature/code-analysis ( e964aa...4fe35d )
by Jonathan
14:33
created

SosaModule   A

Complexity

Total Complexity 21

Size/Duplication

Total Lines 256
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 98
dl 0
loc 256
rs 10
c 0
b 0
f 0
wmc 21

15 Methods

Rating   Name   Duplication   Size   Complexity  
A bodyContent() 0 3 1
A getSidebarContent() 0 10 2
A headContent() 0 3 1
A description() 0 4 1
A defaultMenuOrder() 0 3 1
A getMenu() 0 56 4
A hasSidebarContent() 0 6 2
A sidebarTitle() 0 7 2
A listGeoAnalyses() 0 4 1
A title() 0 3 1
A customModuleVersion() 0 3 1
A listSubscribedHooks() 0 4 1
A boot() 0 7 1
A loadRoutes() 0 26 1
A defaultSidebarOrder() 0 3 1
1
<?php
2
3
/**
4
 * webtrees-lib: MyArtJaub library for webtrees
5
 *
6
 * @package MyArtJaub\Webtrees
7
 * @subpackage Sosa
8
 * @author Jonathan Jaubart <[email protected]>
9
 * @copyright Copyright (c) 2009-2022, Jonathan Jaubart
10
 * @license http://www.gnu.org/licenses/gpl.html GNU General Public License, version 3
11
 */
12
13
declare(strict_types=1);
14
15
namespace MyArtJaub\Webtrees\Module\Sosa;
16
17
use Aura\Router\Map;
18
use Aura\Router\Route;
19
use Fisharebest\Webtrees\Auth;
20
use Fisharebest\Webtrees\DefaultUser;
21
use Fisharebest\Webtrees\I18N;
22
use Fisharebest\Webtrees\Individual;
23
use Fisharebest\Webtrees\Menu;
24
use Fisharebest\Webtrees\Registry;
25
use Fisharebest\Webtrees\Tree;
26
use Fisharebest\Webtrees\Validator;
27
use Fisharebest\Webtrees\Http\RequestHandlers\IndividualPage;
28
use Fisharebest\Webtrees\Module\AbstractModule;
29
use Fisharebest\Webtrees\Module\ModuleGlobalInterface;
30
use Fisharebest\Webtrees\Module\ModuleGlobalTrait;
31
use Fisharebest\Webtrees\Module\ModuleMenuInterface;
32
use Fisharebest\Webtrees\Module\ModuleMenuTrait;
33
use Fisharebest\Webtrees\Module\ModuleSidebarInterface;
34
use Fisharebest\Webtrees\Module\ModuleSidebarTrait;
35
use Fisharebest\Webtrees\Services\MigrationService;
36
use MyArtJaub\Webtrees\Contracts\GeoDispersion\ModuleGeoAnalysisProviderInterface;
37
use MyArtJaub\Webtrees\Contracts\Hooks\ModuleHookSubscriberInterface;
38
use MyArtJaub\Webtrees\Module\ModuleMyArtJaubInterface;
39
use MyArtJaub\Webtrees\Module\ModuleMyArtJaubTrait;
40
use MyArtJaub\Webtrees\Module\Sosa\GeoAnalyses\SosaByGenerationGeoAnalysis;
41
use MyArtJaub\Webtrees\Module\Sosa\Hooks\SosaIconHook;
42
use MyArtJaub\Webtrees\Module\Sosa\Http\RequestHandlers\AncestorsList;
43
use MyArtJaub\Webtrees\Module\Sosa\Http\RequestHandlers\AncestorsListFamily;
44
use MyArtJaub\Webtrees\Module\Sosa\Http\RequestHandlers\AncestorsListIndividual;
45
use MyArtJaub\Webtrees\Module\Sosa\Http\RequestHandlers\MissingAncestorsList;
46
use MyArtJaub\Webtrees\Module\Sosa\Http\RequestHandlers\PedigreeCollapseData;
47
use MyArtJaub\Webtrees\Module\Sosa\Http\RequestHandlers\SosaComputeAction;
48
use MyArtJaub\Webtrees\Module\Sosa\Http\RequestHandlers\SosaComputeModal;
49
use MyArtJaub\Webtrees\Module\Sosa\Http\RequestHandlers\SosaConfig;
50
use MyArtJaub\Webtrees\Module\Sosa\Http\RequestHandlers\SosaConfigAction;
51
use MyArtJaub\Webtrees\Module\Sosa\Http\RequestHandlers\SosaStatistics;
52
use MyArtJaub\Webtrees\Module\Sosa\Services\SosaRecordsService;
53
use Psr\Http\Message\ServerRequestInterface;
54
55
/**
56
 * MyArtJaub Sosa Module
57
 * Identify and produce statistics about Sosa ancestors
58
 */
59
class SosaModule extends AbstractModule implements
60
    ModuleMyArtJaubInterface,
61
    ModuleGlobalInterface,
62
    ModuleMenuInterface,
63
    ModuleSidebarInterface,
64
    ModuleGeoAnalysisProviderInterface,
65
    ModuleHookSubscriberInterface
66
{
67
    use ModuleMyArtJaubTrait {
68
        boot as traitBoot;
69
    }
70
    use ModuleGlobalTrait;
71
    use ModuleMenuTrait;
72
    use ModuleSidebarTrait;
73
74
    // How to update the database schema for this module
75
    private const SCHEMA_TARGET_VERSION   = 3;
76
    private const SCHEMA_SETTING_NAME     = 'MAJ_SOSA_SCHEMA_VERSION';
77
    private const SCHEMA_MIGRATION_PREFIX = __NAMESPACE__ . '\Schema';
78
/**
79
     * {@inheritDoc}
80
     * @see \Fisharebest\Webtrees\Module\AbstractModule::title()
81
     */
82
    public function title(): string
83
    {
84
        return /* I18N: Name of the “Sosa” module */ I18N::translate('Sosa');
85
    }
86
87
    /**
88
     * {@inheritDoc}
89
     * @see \Fisharebest\Webtrees\Module\AbstractModule::description()
90
     */
91
    public function description(): string
92
    {
93
        //phpcs:ignore Generic.Files.LineLength.TooLong
94
        return /* I18N: Description of the “Sosa” module */ I18N::translate('Calculate and display Sosa ancestors of the root person.');
95
    }
96
97
    /**
98
     * {@inheritDoc}
99
     * @see \Fisharebest\Webtrees\Module\AbstractModule::boot()
100
     */
101
    public function boot(): void
102
    {
103
        $this->traitBoot();
104
        app(MigrationService::class)->updateSchema(
105
            self::SCHEMA_MIGRATION_PREFIX,
106
            self::SCHEMA_SETTING_NAME,
107
            self::SCHEMA_TARGET_VERSION
108
        );
109
    }
110
111
    /**
112
     * {@inheritDoc}
113
     * @see \MyArtJaub\Webtrees\Module\ModuleMyArtJaubInterface::loadRoutes()
114
     */
115
    public function loadRoutes(Map $router): void
116
    {
117
        $router->attach('', '', static function (Map $router): void {
118
119
            $router->attach('', '/module-maj/sosa', static function (Map $router): void {
120
121
                $router->attach('', '/list', static function (Map $router): void {
122
                    $router->tokens(['gen' => '\d+']);
123
                    $router->get(AncestorsList::class, '/ancestors/{tree}{/gen}', AncestorsList::class);
124
                    $router->get(AncestorsListIndividual::class, '/ancestors/{tree}/{gen}/tab/individuals', AncestorsListIndividual::class);    //phpcs:ignore Generic.Files.LineLength.TooLong
125
                    $router->get(AncestorsListFamily::class, '/ancestors/{tree}/{gen}/tab/families', AncestorsListFamily::class);   //phpcs:ignore Generic.Files.LineLength.TooLong
126
                    $router->get(MissingAncestorsList::class, '/missing/{tree}{/gen}', MissingAncestorsList::class);
127
                });
128
129
                $router->attach('', '/statistics/{tree}', static function (Map $router): void {
130
131
                    $router->get(SosaStatistics::class, '', SosaStatistics::class);
132
                    $router->get(PedigreeCollapseData::class, '/pedigreecollapse', PedigreeCollapseData::class);
133
                });
134
135
                $router->attach('', '/config/{tree}', static function (Map $router): void {
136
137
                    $router->get(SosaConfig::class, '', SosaConfig::class);
138
                    $router->post(SosaConfigAction::class, '', SosaConfigAction::class);
139
                    $router->get(SosaComputeModal::class, '/compute/{xref}', SosaComputeModal::class);
140
                    $router->post(SosaComputeAction::class, '/compute', SosaComputeAction::class);
141
                });
142
            });
143
        });
144
    }
145
146
    /**
147
     * {@inheritDoc}
148
     * @see \Fisharebest\Webtrees\Module\ModuleCustomInterface::customModuleVersion()
149
     */
150
    public function customModuleVersion(): string
151
    {
152
        return '2.1.1-v.1';
153
    }
154
155
    /**
156
     * {@inheritDoc}
157
     * @see \Fisharebest\Webtrees\Module\ModuleMenuInterface::defaultMenuOrder()
158
     */
159
    public function defaultMenuOrder(): int
160
    {
161
        return 7;
162
    }
163
164
    /**
165
     * {@inhericDoc}
166
     * @see \Fisharebest\Webtrees\Module\ModuleMenuInterface::getMenu()
167
     */
168
    public function getMenu(Tree $tree): ?Menu
169
    {
170
        $menu = new Menu(I18N::translate('Sosa Statistics'));
171
        $menu->setClass('menu-maj-sosa');
172
        $menu->setSubmenus([
173
            new Menu(
174
                I18N::translate('Sosa Ancestors'),
175
                route(AncestorsList::class, ['tree' => $tree->name()]),
176
                'menu-maj-sosa-list',
177
                ['rel' => 'nofollow']
178
            ),
179
            new Menu(
180
                I18N::translate('Missing Ancestors'),
181
                route(MissingAncestorsList::class, ['tree' => $tree->name()]),
182
                'menu-maj-sosa-missing',
183
                ['rel' => 'nofollow']
184
            ),
185
            new Menu(
186
                I18N::translate('Sosa Statistics'),
187
                route(SosaStatistics::class, ['tree' => $tree->name()]),
188
                'menu-maj-sosa-stats'
189
            )
190
        ]);
191
192
        if (Auth::check()) {
193
            $menu->addSubmenu(new Menu(
194
                I18N::translate('Sosa Configuration'),
195
                route(SosaConfig::class, ['tree' => $tree->name()]),
196
                'menu-maj-sosa-config'
197
            ));
198
199
            /** @var ServerRequestInterface $request */
200
            $request = app(ServerRequestInterface::class);
201
            $route = Validator::attributes($request)->route();
202
203
            $root_indi_id = $tree->getUserPreference(Auth::user(), 'MAJ_SOSA_ROOT_ID');
204
205
            if ($route->name === IndividualPage::class && mb_strlen($root_indi_id) > 0) {
206
                $xref = Validator::attributes($request)->isXref()->string('xref', '');
207
208
                $menu->addSubmenu(new Menu(
209
                    I18N::translate('Complete Sosas'),
210
                    '#',
211
                    'menu-maj-sosa-compute',
212
                    [
213
                        'rel'           => 'nofollow',
214
                        'data-wt-href'  => route(SosaComputeModal::class, ['tree' => $tree->name(), 'xref' => $xref]),
215
                        'data-bs-target'    => '#wt-ajax-modal',
216
                        'data-bs-toggle'    => 'modal',
217
                        'data-bs-backdrop'  => 'static'
218
                    ]
219
                ));
220
            }
221
        }
222
223
        return $menu;
224
    }
225
226
    /**
227
     * {@inheritDoc}
228
     * @see \Fisharebest\Webtrees\Module\ModuleGlobalInterface::headContent()
229
     */
230
    public function headContent(): string
231
    {
232
        return '<link rel="stylesheet" href="' . e($this->moduleCssUrl()) . '">';
233
    }
234
235
    /**
236
     * {@inheritDoc}
237
     * @see \Fisharebest\Webtrees\Module\ModuleGlobalInterface::bodyContent()
238
     */
239
    public function bodyContent(): string
240
    {
241
        return '<script src="' . $this->assetUrl('js/sosa.min.js') . '"></script>';
242
    }
243
244
    /**
245
     * {@inheritDoc}
246
     * @see \Fisharebest\Webtrees\Module\ModuleSidebarInterface::sidebarTitle()
247
     */
248
    public function sidebarTitle(Individual $individual): string
249
    {
250
        $user = Auth::check() ? Auth::user() : new DefaultUser();
251
252
        return view($this->name() . '::sidebar/title', [
253
            'module_name'   =>  $this->name(),
254
            'sosa_numbers'  =>  app(SosaRecordsService::class)->sosaNumbers($individual->tree(), $user, $individual)
255
        ]);
256
    }
257
258
    /**
259
     * {@inheritDoc}
260
     * @see \Fisharebest\Webtrees\Module\ModuleSidebarInterface::getSidebarContent()
261
     */
262
    public function getSidebarContent(Individual $individual): string
263
    {
264
        $sosa_root_xref = $individual->tree()->getUserPreference(Auth::user(), 'MAJ_SOSA_ROOT_ID');
265
        $sosa_root = Registry::individualFactory()->make($sosa_root_xref, $individual->tree());
266
        $user = Auth::check() ? Auth::user() : new DefaultUser();
267
268
        return view($this->name() . '::sidebar/content', [
269
            'sosa_ancestor' =>  $individual,
270
            'sosa_root'     =>  $sosa_root,
271
            'sosa_numbers'  =>  app(SosaRecordsService::class)->sosaNumbers($individual->tree(), $user, $individual)
272
        ]);
273
    }
274
275
    /**
276
     * {@inheritDoc}
277
     * @see \Fisharebest\Webtrees\Module\ModuleSidebarInterface::hasSidebarContent()
278
     */
279
    public function hasSidebarContent(Individual $individual): bool
280
    {
281
        $user = Auth::check() ? Auth::user() : new DefaultUser();
282
283
        return app(SosaRecordsService::class)
284
            ->sosaNumbers($individual->tree(), $user, $individual)->count() > 0;
285
    }
286
287
    /**
288
     * {@inheritDoc}
289
     * @see \Fisharebest\Webtrees\Module\ModuleSidebarInterface::defaultSidebarOrder()
290
     */
291
    public function defaultSidebarOrder(): int
292
    {
293
        return 1;
294
    }
295
296
    /**
297
     * {@inheritDoc}
298
     * @see \MyArtJaub\Webtrees\Contracts\GeoDispersion\ModuleGeoAnalysisProviderInterface::listGeoAnalyses()
299
     */
300
    public function listGeoAnalyses(): array
301
    {
302
        return [
303
            SosaByGenerationGeoAnalysis::class
304
        ];
305
    }
306
307
    /**
308
     * {@inheritDoc}
309
     * @see \MyArtJaub\Webtrees\Contracts\Hooks\ModuleHookSubscriberInterface::listSubscribedHooks()
310
     */
311
    public function listSubscribedHooks(): array
312
    {
313
        return [
314
            app()->makeWith(SosaIconHook::class, [ 'module' => $this ])
315
        ];
316
    }
317
}
318