diff options
| author | Greg Roach <greg@subaqua.co.uk> | 2020-06-26 09:08:51 +0100 |
|---|---|---|
| committer | Greg Roach <greg@subaqua.co.uk> | 2020-06-26 10:53:31 +0100 |
| commit | 042e1af7d52350f0ac38d75aa9ee6d71ce2e46b1 (patch) | |
| tree | ac62ffea62458dda38a5f54687a89e4f069ad9ed | |
| parent | 788f881d1edc37597655c820c8babac60c767a55 (diff) | |
| download | webtrees-042e1af7d52350f0ac38d75aa9ee6d71ce2e46b1.tar.gz webtrees-042e1af7d52350f0ac38d75aa9ee6d71ce2e46b1.tar.bz2 webtrees-042e1af7d52350f0ac38d75aa9ee6d71ce2e46b1.zip | |
Add data-fix for NAME subtags (See #794)
| -rw-r--r-- | app/Module/FixNameTags.php | 201 | ||||
| -rw-r--r-- | app/Module/FixPrimaryTag.php | 4 | ||||
| -rw-r--r-- | app/Services/ModuleService.php | 2 | ||||
| -rw-r--r-- | phpstan-baseline.neon | 31 |
4 files changed, 222 insertions, 16 deletions
diff --git a/app/Module/FixNameTags.php b/app/Module/FixNameTags.php new file mode 100644 index 0000000000..a000089f79 --- /dev/null +++ b/app/Module/FixNameTags.php @@ -0,0 +1,201 @@ +<?php + +/** + * webtrees: online genealogy + * Copyright (C) 2020 webtrees development team + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +declare(strict_types=1); + +namespace Fisharebest\Webtrees\Module; + +use Fisharebest\Webtrees\Fact; +use Fisharebest\Webtrees\GedcomRecord; +use Fisharebest\Webtrees\I18N; +use Fisharebest\Webtrees\Services\DataFixService; +use Fisharebest\Webtrees\Tree; +use Illuminate\Database\Capsule\Manager as DB; +use Illuminate\Database\Query\Builder; +use Illuminate\Support\Collection; + +use function array_keys; +use function implode; +use function preg_match; +use function str_replace; + +/** + * Class FixNameTags + */ +class FixNameTags extends AbstractModule implements ModuleDataFixInterface +{ + use ModuleDataFixTrait; + + // https://legacyfamilytree.se/WEB_US/user_defined_gedcom_tags.htm + private const CONVERT = [ + '_ADPN' => 'adopted', // Adopted name + '_AKA' => 'aka', // Also known as + '_AKAN' => 'aka', // Also known as + '_BIRN' => 'birth', // Birth name + '_CENN' => '', // Census name + '_CURN' => '', // Currently known as + '_FARN' => 'estate', // Farm name + '_FKAN' => 'aka', // Formerly known as + '_GERN' => '', // German name + '_HEB' => '', // Hebrew name + '_HEBN' => '', // Hebrew name + '_INDN' => '', // Indian name + '_MARNM' => 'married', // Married name + '_OTHN' => 'aka', // Other name + '_RELN' => 'religious', // Religious name + '_SHON' => 'aka', // Short name + '_SLDN' => 'aka', // Soldier name + ]; + + /** @var DataFixService */ + private $data_fix_service; + + /** + * FixMissingDeaths constructor. + * + * @param DataFixService $data_fix_service + */ + public function __construct(DataFixService $data_fix_service) + { + $this->data_fix_service = $data_fix_service; + } + + /** + * How should this module be identified in the control panel, etc.? + * + * @return string + */ + public function title(): string + { + /* I18N: Name of a module */ + return I18N::translate('Convert NAME:_XXX tags to GEDCOM 5.5.1'); + } + + /** + * A sentence describing what this module does. + * + * @return string + */ + public function description(): string + { + /* I18N: Description of a “Data fix” module */ + return I18N::translate('Some genelealogy applications store all names in a single name record, using custom tags such as _MARNM and _AKA. An alternative is to create a new name record for each name.'); + } + + /** + * XREFs of media records that might need fixing. + * + * @param Tree $tree + * @param array<string,string> $params + * + * @return Collection<string> + */ + public function individualsToFix(Tree $tree, array $params): Collection + { + return DB::table('individuals') + ->where('i_file', '=', $tree->id()) + ->where(static function (Builder $query): void { + foreach (array_keys(self::CONVERT) as $tag) { + $query->orWhere('i_gedcom', 'LIKE', "%\n2 " . $tag . " %"); + } + }) + ->pluck('i_id'); + } + + /** + * Does a record need updating? + * + * @param GedcomRecord $record + * @param array<string,string> $params + * + * @return bool + */ + public function doesRecordNeedUpdate(GedcomRecord $record, array $params): bool + { + $tags = implode('|', array_keys(self::CONVERT)); + + return preg_match('/\n1 NAME.*(?:\n[2-9] .*)*\n2 (' . $tags . ')/', $record->gedcom()) === 1; + } + + /** + * Show the changes we would make + * + * @param GedcomRecord $record + * @param array<string,string> $params + * + * @return string + */ + public function previewUpdate(GedcomRecord $record, array $params): string + { + $diffs = []; + + foreach ($record->facts(['NAME'], false, null, true) as $name) { + $old = $name->gedcom(); + $new = $this->updateGedcom($name); + + if ($old !== $new) { + $diffs[] = $this->data_fix_service->gedcomDiff($record->tree(), $old, $new); + } + } + + return implode('<hr>', $diffs); + } + + /** + * Fix a record + * + * @param GedcomRecord $record + * @param array<string,string> $params + * + * @return void + */ + public function updateRecord(GedcomRecord $record, array $params): void + { + $names = $record->facts(['NAME'], false, null, true); + + foreach ($names as $name) { + $old = $name->gedcom(); + $new = $this->updateGedcom($name); + + if ($old !== $new) { + $record->updateFact($name->id(), $new, false); + } + } + } + + /** + * @param Fact $fact + * + * @return string + */ + private function updateGedcom(Fact $fact): string + { + $gedcom = $fact->gedcom(); + + foreach (self::CONVERT as $tag => $type) { + if ($type !== '') { + $type = "\n2 TYPE " . $type; + } + + while (preg_match('/\n2 ' . $tag . ' (.+)(?:\n[3-9].*)*/', $gedcom, $match)) { + $gedcom = str_replace($match[0], '', $gedcom) . "\n1 NAME " . $match[1] . $type; + } + } + + return $gedcom; + } +} diff --git a/app/Module/FixPrimaryTag.php b/app/Module/FixPrimaryTag.php index 22247338c9..a1931d71e8 100644 --- a/app/Module/FixPrimaryTag.php +++ b/app/Module/FixPrimaryTag.php @@ -145,9 +145,7 @@ class FixPrimaryTag extends AbstractModule implements ModuleDataFixInterface */ private function updateMediaLinks(Individual $individual, string $xref, bool $primary): void { - $facts = $individual->facts()->filter(static function (Fact $fact): bool { - return !$fact->isPendingDeletion(); - }); + $facts = $individual->facts([], false, null, true); $facts1 = new Collection(); $facts2 = new Collection(); diff --git a/app/Services/ModuleService.php b/app/Services/ModuleService.php index 963a285ee8..e57cf63dc3 100644 --- a/app/Services/ModuleService.php +++ b/app/Services/ModuleService.php @@ -64,6 +64,7 @@ use Fisharebest\Webtrees\Module\FamilyTreeFavoritesModule; use Fisharebest\Webtrees\Module\FamilyTreeNewsModule; use Fisharebest\Webtrees\Module\FamilyTreeStatisticsModule; use Fisharebest\Webtrees\Module\FanChartModule; +use Fisharebest\Webtrees\Module\FixNameTags; use Fisharebest\Webtrees\Module\FrenchHistory; use Fisharebest\Webtrees\Module\FixCemeteryTag; use Fisharebest\Webtrees\Module\FixDuplicateLinks; @@ -321,6 +322,7 @@ class ModuleService 'fix-ceme-tag' => FixCemeteryTag::class, 'fix-duplicate-links' => FixDuplicateLinks::class, 'fix-name-slashes-spaces' => FixNameSlashesAndSpaces::class, + 'fix-name-tags' => FixNameTags::class, 'fix-place-names' => FixPlaceNames::class, 'fix-prim-tag' => FixPrimaryTag::class, 'fix-search-and-replace' => FixSearchAndReplace::class, diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 3ec4fad7e3..37e516dd98 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -591,16 +591,6 @@ parameters: path: app/Http/Controllers/PlaceHierarchyController.php - - message: "#^Parameter \\#1 \\$value of function e expects Illuminate\\\\Contracts\\\\Support\\\\Htmlable\\|string, string\\|false given\\.$#" - count: 1 - path: app/Http/RequestHandlers/SetupWizard.php - - - - message: "#^Parameter \\#1 \\$str of function substr expects string, string\\|false given\\.$#" - count: 1 - path: app/Http/RequestHandlers/SetupWizard.php - - - message: "#^Parameter \\#1 \\$path of method Psr\\\\Http\\\\Message\\\\UriInterface\\:\\:withPath\\(\\) expects string, string\\|false given\\.$#" count: 1 path: app/Http/Middleware/BaseUrl.php @@ -791,6 +781,16 @@ parameters: path: app/Http/RequestHandlers/Select2Place.php - + message: "#^Parameter \\#1 \\$value of function e expects Illuminate\\\\Contracts\\\\Support\\\\Htmlable\\|string, string\\|false given\\.$#" + count: 1 + path: app/Http/RequestHandlers/SetupWizard.php + + - + message: "#^Parameter \\#1 \\$str of function substr expects string, string\\|false given\\.$#" + count: 1 + path: app/Http/RequestHandlers/SetupWizard.php + + - message: "#^Cannot call method local\\(\\) on Fisharebest\\\\Webtrees\\\\Carbon\\|null\\.$#" count: 1 path: app/Http/RequestHandlers/SiteLogsData.php @@ -1098,7 +1098,7 @@ parameters: - message: "#^Parameter \\#1 \\$string of function strlen expects string, string\\|false given\\.$#" count: 1 - path: modules_v4/example-middleware.disable/module.php + path: modules_v4/example.disable/module.php - message: "#^Parameter \\#1 \\$string of function strlen expects string, string\\|false given\\.$#" @@ -1108,7 +1108,7 @@ parameters: - message: "#^Parameter \\#1 \\$string of function strlen expects string, string\\|false given\\.$#" count: 1 - path: modules_v4/example.disable/module.php + path: modules_v4/example-footer.disable/module.php - message: "#^Parameter \\#1 \\$string of function strlen expects string, string\\|false given\\.$#" @@ -1118,7 +1118,7 @@ parameters: - message: "#^Parameter \\#1 \\$string of function strlen expects string, string\\|false given\\.$#" count: 1 - path: modules_v4/example-footer.disable/module.php + path: modules_v4/example-middleware.disable/module.php - message: "#^Parameter \\#1 \\$string of function strlen expects string, string\\|false given\\.$#" @@ -1136,6 +1136,11 @@ parameters: path: app/Module/FixMissingDeaths.php - + message: "#^Method Fisharebest\\\\Webtrees\\\\Module\\\\FixNameTags\\:\\:mergePendingRecords\\(\\) should return Illuminate\\\\Support\\\\Collection&iterable\\<stdClass\\> but returns Illuminate\\\\Support\\\\Collection&iterable\\<string\\>\\.$#" + count: 1 + path: app/Module/FixNameTags.php + + - message: "#^Method Fisharebest\\\\Webtrees\\\\Module\\\\FixPrimaryTag\\:\\:mergePendingRecords\\(\\) should return Illuminate\\\\Support\\\\Collection&iterable\\<stdClass\\> but returns Illuminate\\\\Support\\\\Collection&iterable\\<string\\>\\.$#" count: 1 path: app/Module/FixPrimaryTag.php |
