summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGreg Roach <greg@subaqua.co.uk>2020-06-26 09:08:51 +0100
committerGreg Roach <greg@subaqua.co.uk>2020-06-26 10:53:31 +0100
commit042e1af7d52350f0ac38d75aa9ee6d71ce2e46b1 (patch)
treeac62ffea62458dda38a5f54687a89e4f069ad9ed
parent788f881d1edc37597655c820c8babac60c767a55 (diff)
downloadwebtrees-042e1af7d52350f0ac38d75aa9ee6d71ce2e46b1.tar.gz
webtrees-042e1af7d52350f0ac38d75aa9ee6d71ce2e46b1.tar.bz2
webtrees-042e1af7d52350f0ac38d75aa9ee6d71ce2e46b1.zip
Add data-fix for NAME subtags (See #794)
-rw-r--r--app/Module/FixNameTags.php201
-rw-r--r--app/Module/FixPrimaryTag.php4
-rw-r--r--app/Services/ModuleService.php2
-rw-r--r--phpstan-baseline.neon31
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