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