xref: /webtrees/app/Http/RequestHandlers/EditFactAction.php (revision 1f244d772ed55c1ea8eecba8f9ca36a77f054c34)
1<?php
2
3/**
4 * webtrees: online genealogy
5 * Copyright (C) 2020 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
18declare(strict_types=1);
19
20namespace Fisharebest\Webtrees\Http\RequestHandlers;
21
22use Fisharebest\Webtrees\Auth;
23use Fisharebest\Webtrees\Factory;
24use Fisharebest\Webtrees\Individual;
25use Fisharebest\Webtrees\Module\CensusAssistantModule;
26use Fisharebest\Webtrees\Services\GedcomEditService;
27use Fisharebest\Webtrees\Services\ModuleService;
28use Fisharebest\Webtrees\Tree;
29use Psr\Http\Message\ResponseInterface;
30use Psr\Http\Message\ServerRequestInterface;
31use Psr\Http\Server\RequestHandlerInterface;
32
33use function array_merge;
34use function array_unique;
35use function assert;
36use function explode;
37use function in_array;
38use function is_string;
39use function preg_match_all;
40use function redirect;
41use function trim;
42
43/**
44 * Save an updated GEDCOM fact.
45 */
46class EditFactAction implements RequestHandlerInterface
47{
48    /** @var GedcomEditService */
49    private $gedcom_edit_service;
50
51    /** @var ModuleService */
52    private $module_service;
53
54    /**
55     * EditFactAction constructor.
56     *
57     * @param GedcomEditService $gedcom_edit_service
58     * @param ModuleService     $module_service
59     */
60    public function __construct(GedcomEditService $gedcom_edit_service, ModuleService $module_service)
61    {
62        $this->gedcom_edit_service = $gedcom_edit_service;
63        $this->module_service      = $module_service;
64    }
65
66    /**
67     * @param ServerRequestInterface $request
68     *
69     * @return ResponseInterface
70     */
71    public function handle(ServerRequestInterface $request): ResponseInterface
72    {
73        $tree = $request->getAttribute('tree');
74        assert($tree instanceof Tree);
75
76        $xref = $request->getAttribute('xref');
77        assert(is_string($xref));
78
79        $fact_id = $request->getAttribute('fact_id') ?? '';
80        assert(is_string($fact_id));
81
82        $record = Factory::gedcomRecord()->make($xref, $tree);
83        $record = Auth::checkRecordAccess($record, true);
84
85        $params    = (array) $request->getParsedBody();
86        $keep_chan = (bool) ($params['keep_chan'] ?? false);
87
88        $this->gedcom_edit_service->glevels = $params['glevels'];
89        $this->gedcom_edit_service->tag     = $params['tag'];
90        $this->gedcom_edit_service->text    = $params['text'];
91        $this->gedcom_edit_service->islink  = $params['islink'];
92
93        // If the fact has a DATE or PLAC, then delete any value of Y
94        if ($this->gedcom_edit_service->text[0] === 'Y') {
95            foreach ($this->gedcom_edit_service->tag as $n => $value) {
96                if ($this->gedcom_edit_service->glevels[$n] == 2 && ($value === 'DATE' || $value === 'PLAC') && $this->gedcom_edit_service->text[$n] !== '') {
97                    $this->gedcom_edit_service->text[0] = '';
98                    break;
99                }
100            }
101        }
102
103        $newged = '';
104
105        $NAME = $params['NAME'] ?? '';
106
107        if ($NAME !== '') {
108            $newged     .= "\n1 NAME " . $NAME;
109            $name_facts = [
110                'TYPE',
111                'NPFX',
112                'GIVN',
113                'NICK',
114                'SPFX',
115                'SURN',
116                'NSFX',
117            ];
118            foreach ($name_facts as $name_fact) {
119                $NAME_FACT = $params[$name_fact] ?? '';
120                if ($NAME_FACT !== '') {
121                    $newged .= "\n2 " . $name_fact . ' ' . $NAME_FACT;
122                }
123            }
124        }
125
126        $newged = $this->gedcom_edit_service->handleUpdates($newged);
127
128        // Add new names after existing names
129        if ($NAME !== '') {
130            preg_match_all('/[_0-9A-Z]+/', $tree->getPreference('ADVANCED_NAME_FACTS'), $match);
131            $name_facts = array_unique(array_merge(['_MARNM'], $match[0]));
132            foreach ($name_facts as $name_fact) {
133                $NAME_FACT = $params[$name_fact] ?? '';
134                // Ignore advanced facts that duplicate standard facts.
135                if ($NAME_FACT !== '' && !in_array($name_fact, ['TYPE', 'NPFX', 'GIVN', 'NICK', 'SPFX', 'SURN', 'NSFX'], true)) {
136                    $newged .= "\n2 " . $name_fact . ' ' . $NAME_FACT;
137                }
138            }
139        }
140
141        $newged = trim($newged); // Remove leading newline
142
143        $census_assistant = $this->module_service->findByInterface(CensusAssistantModule::class)->first();
144        if ($census_assistant instanceof CensusAssistantModule && $record instanceof Individual) {
145            $newged = $census_assistant->updateCensusAssistant($request, $record, $fact_id, $newged, $keep_chan);
146        }
147
148        $record->updateFact($fact_id, $newged, !$keep_chan);
149
150        // For the GEDFact_assistant module
151        $pid_array = $params['pid_array'] ?? '';
152        if ($pid_array !== '') {
153            foreach (explode(',', $pid_array) as $pid) {
154                if ($pid !== $xref) {
155                    $indi = Factory::individual()->make($pid, $tree);
156                    if ($indi && $indi->canEdit()) {
157                        $indi->updateFact($fact_id, $newged, !$keep_chan);
158                    }
159                }
160            }
161        }
162
163        return redirect($params['url'] ?? $record->url());
164    }
165}
166