xref: /webtrees/app/Gedcom.php (revision 1b85c7f5de205a5e1708adf7e5d0ea0b9067b473)
10f471f91SGreg Roach<?php
23976b470SGreg Roach
30f471f91SGreg Roach/**
40f471f91SGreg Roach * webtrees: online genealogy
5d11be702SGreg Roach * Copyright (C) 2023 webtrees development team
60f471f91SGreg Roach * This program is free software: you can redistribute it and/or modify
70f471f91SGreg Roach * it under the terms of the GNU General Public License as published by
80f471f91SGreg Roach * the Free Software Foundation, either version 3 of the License, or
90f471f91SGreg Roach * (at your option) any later version.
100f471f91SGreg Roach * This program is distributed in the hope that it will be useful,
110f471f91SGreg Roach * but WITHOUT ANY WARRANTY; without even the implied warranty of
120f471f91SGreg Roach * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
130f471f91SGreg Roach * GNU General Public License for more details.
140f471f91SGreg Roach * You should have received a copy of the GNU General Public License
1589f7189bSGreg Roach * along with this program. If not, see <https://www.gnu.org/licenses/>.
160f471f91SGreg Roach */
17fcfa147eSGreg Roach
18e7f56f2aSGreg Roachdeclare(strict_types=1);
19e7f56f2aSGreg Roach
200f471f91SGreg Roachnamespace Fisharebest\Webtrees;
210f471f91SGreg Roach
22e669bb4bSGreg Roachuse Fisharebest\Webtrees\Contracts\ElementFactoryInterface;
2300c92694SGreg Roachuse Fisharebest\Webtrees\Contracts\ElementInterface;
24864236f5SGreg Roachuse Fisharebest\Webtrees\CustomTags\Aldfaer;
25864236f5SGreg Roachuse Fisharebest\Webtrees\CustomTags\Ancestry;
26864236f5SGreg Roachuse Fisharebest\Webtrees\CustomTags\BrothersKeeper;
27864236f5SGreg Roachuse Fisharebest\Webtrees\CustomTags\FamilySearch;
28864236f5SGreg Roachuse Fisharebest\Webtrees\CustomTags\FamilyTreeBuilder;
29864236f5SGreg Roachuse Fisharebest\Webtrees\CustomTags\FamilyTreeMaker;
30864236f5SGreg Roachuse Fisharebest\Webtrees\CustomTags\Gedcom7;
31864236f5SGreg Roachuse Fisharebest\Webtrees\CustomTags\GedcomL;
32864236f5SGreg Roachuse Fisharebest\Webtrees\CustomTags\Geneatique;
33864236f5SGreg Roachuse Fisharebest\Webtrees\CustomTags\GenPlusWin;
34864236f5SGreg Roachuse Fisharebest\Webtrees\CustomTags\Heredis;
35864236f5SGreg Roachuse Fisharebest\Webtrees\CustomTags\Legacy;
36864236f5SGreg Roachuse Fisharebest\Webtrees\CustomTags\MyHeritage;
37864236f5SGreg Roachuse Fisharebest\Webtrees\CustomTags\PersonalAncestralFile;
38864236f5SGreg Roachuse Fisharebest\Webtrees\CustomTags\PhpGedView;
39864236f5SGreg Roachuse Fisharebest\Webtrees\CustomTags\ProGen;
40864236f5SGreg Roachuse Fisharebest\Webtrees\CustomTags\Reunion;
41864236f5SGreg Roachuse Fisharebest\Webtrees\CustomTags\RootsMagic;
42*1b85c7f5SGreg Roachuse Fisharebest\Webtrees\CustomTags\TheMasterGenealogist;
43*1b85c7f5SGreg Roachuse Fisharebest\Webtrees\CustomTags\TheNextGeneration;
4400c92694SGreg Roachuse Fisharebest\Webtrees\Elements\AddressCity;
4500c92694SGreg Roachuse Fisharebest\Webtrees\Elements\AddressCountry;
4600c92694SGreg Roachuse Fisharebest\Webtrees\Elements\AddressEmail;
4700c92694SGreg Roachuse Fisharebest\Webtrees\Elements\AddressFax;
4800c92694SGreg Roachuse Fisharebest\Webtrees\Elements\AddressLine;
4900c92694SGreg Roachuse Fisharebest\Webtrees\Elements\AddressLine1;
5000c92694SGreg Roachuse Fisharebest\Webtrees\Elements\AddressLine2;
5100c92694SGreg Roachuse Fisharebest\Webtrees\Elements\AddressLine3;
5200c92694SGreg Roachuse Fisharebest\Webtrees\Elements\AddressPostalCode;
5300c92694SGreg Roachuse Fisharebest\Webtrees\Elements\AddressState;
5400c92694SGreg Roachuse Fisharebest\Webtrees\Elements\AddressWebPage;
5500c92694SGreg Roachuse Fisharebest\Webtrees\Elements\AdoptedByWhichParent;
5600c92694SGreg Roachuse Fisharebest\Webtrees\Elements\Adoption;
5700c92694SGreg Roachuse Fisharebest\Webtrees\Elements\AdultChristening;
5800c92694SGreg Roachuse Fisharebest\Webtrees\Elements\AgeAtEvent;
5900c92694SGreg Roachuse Fisharebest\Webtrees\Elements\AncestralFileNumber;
6000c92694SGreg Roachuse Fisharebest\Webtrees\Elements\Annulment;
6100c92694SGreg Roachuse Fisharebest\Webtrees\Elements\ApprovedSystemId;
6200c92694SGreg Roachuse Fisharebest\Webtrees\Elements\AutomatedRecordId;
6300c92694SGreg Roachuse Fisharebest\Webtrees\Elements\Baptism;
6400c92694SGreg Roachuse Fisharebest\Webtrees\Elements\BarMitzvah;
6500c92694SGreg Roachuse Fisharebest\Webtrees\Elements\BasMitzvah;
6600c92694SGreg Roachuse Fisharebest\Webtrees\Elements\Birth;
6700c92694SGreg Roachuse Fisharebest\Webtrees\Elements\Blessing;
6800c92694SGreg Roachuse Fisharebest\Webtrees\Elements\Burial;
6900c92694SGreg Roachuse Fisharebest\Webtrees\Elements\CasteName;
7000c92694SGreg Roachuse Fisharebest\Webtrees\Elements\CauseOfEvent;
7100c92694SGreg Roachuse Fisharebest\Webtrees\Elements\Census;
7200c92694SGreg Roachuse Fisharebest\Webtrees\Elements\CertaintyAssessment;
7300c92694SGreg Roachuse Fisharebest\Webtrees\Elements\Change;
7400c92694SGreg Roachuse Fisharebest\Webtrees\Elements\ChangeDate;
7500c92694SGreg Roachuse Fisharebest\Webtrees\Elements\CharacterSet;
7600c92694SGreg Roachuse Fisharebest\Webtrees\Elements\ChildLinkageStatus;
7700c92694SGreg Roachuse Fisharebest\Webtrees\Elements\Christening;
7800c92694SGreg Roachuse Fisharebest\Webtrees\Elements\Confirmation;
7900c92694SGreg Roachuse Fisharebest\Webtrees\Elements\ContentDescription;
8000c92694SGreg Roachuse Fisharebest\Webtrees\Elements\Coordinates;
8100c92694SGreg Roachuse Fisharebest\Webtrees\Elements\CopyrightFile;
8200c92694SGreg Roachuse Fisharebest\Webtrees\Elements\CopyrightSourceData;
8300c92694SGreg Roachuse Fisharebest\Webtrees\Elements\CountOfChildren;
84f9340759SGreg Roachuse Fisharebest\Webtrees\Elements\CountOfChildrenFam;
8500c92694SGreg Roachuse Fisharebest\Webtrees\Elements\CountOfMarriages;
8600c92694SGreg Roachuse Fisharebest\Webtrees\Elements\Cremation;
8700c92694SGreg Roachuse Fisharebest\Webtrees\Elements\CustomElement;
8800c92694SGreg Roachuse Fisharebest\Webtrees\Elements\DateLdsOrd;
8900c92694SGreg Roachuse Fisharebest\Webtrees\Elements\DateValue;
90099c152eSGreg Roachuse Fisharebest\Webtrees\Elements\DateValueExact;
9100c92694SGreg Roachuse Fisharebest\Webtrees\Elements\Death;
9200c92694SGreg Roachuse Fisharebest\Webtrees\Elements\DescriptiveTitle;
9300c92694SGreg Roachuse Fisharebest\Webtrees\Elements\Divorce;
9400c92694SGreg Roachuse Fisharebest\Webtrees\Elements\DivorceFiled;
9500c92694SGreg Roachuse Fisharebest\Webtrees\Elements\Emigration;
9600c92694SGreg Roachuse Fisharebest\Webtrees\Elements\EmptyElement;
9700c92694SGreg Roachuse Fisharebest\Webtrees\Elements\Engagement;
9800c92694SGreg Roachuse Fisharebest\Webtrees\Elements\EventOrFactClassification;
9900c92694SGreg Roachuse Fisharebest\Webtrees\Elements\EventsRecorded;
10000c92694SGreg Roachuse Fisharebest\Webtrees\Elements\EventTypeCitedFrom;
10100c92694SGreg Roachuse Fisharebest\Webtrees\Elements\FamilyCensus;
1025d2c6313SGreg Roachuse Fisharebest\Webtrees\Elements\FamilyEvent;
10300c92694SGreg Roachuse Fisharebest\Webtrees\Elements\FamilyRecord;
10400c92694SGreg Roachuse Fisharebest\Webtrees\Elements\FileName;
10500c92694SGreg Roachuse Fisharebest\Webtrees\Elements\FirstCommunion;
10600c92694SGreg Roachuse Fisharebest\Webtrees\Elements\Form;
10700c92694SGreg Roachuse Fisharebest\Webtrees\Elements\GedcomElement;
10800c92694SGreg Roachuse Fisharebest\Webtrees\Elements\GenerationsOfAncestors;
10900c92694SGreg Roachuse Fisharebest\Webtrees\Elements\GenerationsOfDescendants;
11000c92694SGreg Roachuse Fisharebest\Webtrees\Elements\Graduation;
11100c92694SGreg Roachuse Fisharebest\Webtrees\Elements\HeaderRecord;
11200c92694SGreg Roachuse Fisharebest\Webtrees\Elements\Immigration;
1135d2c6313SGreg Roachuse Fisharebest\Webtrees\Elements\IndividualEvent;
1145d2c6313SGreg Roachuse Fisharebest\Webtrees\Elements\IndividualFact;
11500c92694SGreg Roachuse Fisharebest\Webtrees\Elements\IndividualRecord;
11600c92694SGreg Roachuse Fisharebest\Webtrees\Elements\LanguageId;
11700c92694SGreg Roachuse Fisharebest\Webtrees\Elements\LdsBaptism;
11800c92694SGreg Roachuse Fisharebest\Webtrees\Elements\LdsBaptismDateStatus;
11900c92694SGreg Roachuse Fisharebest\Webtrees\Elements\LdsChildSealing;
12000c92694SGreg Roachuse Fisharebest\Webtrees\Elements\LdsChildSealingDateStatus;
12100c92694SGreg Roachuse Fisharebest\Webtrees\Elements\LdsConfirmation;
12200c92694SGreg Roachuse Fisharebest\Webtrees\Elements\LdsEndowment;
12300c92694SGreg Roachuse Fisharebest\Webtrees\Elements\LdsEndowmentDateStatus;
12400c92694SGreg Roachuse Fisharebest\Webtrees\Elements\LdsSpouseSealing;
12500c92694SGreg Roachuse Fisharebest\Webtrees\Elements\LdsSpouseSealingDateStatus;
12600c92694SGreg Roachuse Fisharebest\Webtrees\Elements\Marriage;
12700c92694SGreg Roachuse Fisharebest\Webtrees\Elements\MarriageBanns;
12800c92694SGreg Roachuse Fisharebest\Webtrees\Elements\MarriageContract;
12900c92694SGreg Roachuse Fisharebest\Webtrees\Elements\MarriageLicence;
13000c92694SGreg Roachuse Fisharebest\Webtrees\Elements\MarriageSettlement;
13100c92694SGreg Roachuse Fisharebest\Webtrees\Elements\MarriageType;
13200c92694SGreg Roachuse Fisharebest\Webtrees\Elements\MediaRecord;
13300c92694SGreg Roachuse Fisharebest\Webtrees\Elements\MultimediaFileReference;
13400c92694SGreg Roachuse Fisharebest\Webtrees\Elements\MultimediaFormat;
13500c92694SGreg Roachuse Fisharebest\Webtrees\Elements\NameOfBusiness;
13600c92694SGreg Roachuse Fisharebest\Webtrees\Elements\NameOfFamilyFile;
13700c92694SGreg Roachuse Fisharebest\Webtrees\Elements\NameOfProduct;
13800c92694SGreg Roachuse Fisharebest\Webtrees\Elements\NameOfRepository;
13900c92694SGreg Roachuse Fisharebest\Webtrees\Elements\NameOfSourceData;
14000c92694SGreg Roachuse Fisharebest\Webtrees\Elements\NamePersonal;
14100c92694SGreg Roachuse Fisharebest\Webtrees\Elements\NamePhoneticVariation;
14200c92694SGreg Roachuse Fisharebest\Webtrees\Elements\NamePieceGiven;
14300c92694SGreg Roachuse Fisharebest\Webtrees\Elements\NamePieceNickname;
14400c92694SGreg Roachuse Fisharebest\Webtrees\Elements\NamePiecePrefix;
14500c92694SGreg Roachuse Fisharebest\Webtrees\Elements\NamePieceSuffix;
14600c92694SGreg Roachuse Fisharebest\Webtrees\Elements\NamePieceSurname;
14700c92694SGreg Roachuse Fisharebest\Webtrees\Elements\NamePieceSurnamePrefix;
14800c92694SGreg Roachuse Fisharebest\Webtrees\Elements\NameRomanizedVariation;
14900c92694SGreg Roachuse Fisharebest\Webtrees\Elements\NameType;
15000c92694SGreg Roachuse Fisharebest\Webtrees\Elements\NationalIdNumber;
151f15544dcSGreg Roachuse Fisharebest\Webtrees\Elements\NationalOrTribalOrigin;
15200c92694SGreg Roachuse Fisharebest\Webtrees\Elements\Naturalization;
15300c92694SGreg Roachuse Fisharebest\Webtrees\Elements\NobilityTypeTitle;
15400c92694SGreg Roachuse Fisharebest\Webtrees\Elements\NoteRecord;
15500c92694SGreg Roachuse Fisharebest\Webtrees\Elements\NoteStructure;
15600c92694SGreg Roachuse Fisharebest\Webtrees\Elements\Occupation;
15700c92694SGreg Roachuse Fisharebest\Webtrees\Elements\OrdinanceProcessFlag;
15800c92694SGreg Roachuse Fisharebest\Webtrees\Elements\Ordination;
15900c92694SGreg Roachuse Fisharebest\Webtrees\Elements\PedigreeLinkageType;
16000c92694SGreg Roachuse Fisharebest\Webtrees\Elements\PermanentRecordFileNumber;
16100c92694SGreg Roachuse Fisharebest\Webtrees\Elements\PhoneNumber;
16200c92694SGreg Roachuse Fisharebest\Webtrees\Elements\PhoneticType;
16300c92694SGreg Roachuse Fisharebest\Webtrees\Elements\PhysicalDescription;
16400c92694SGreg Roachuse Fisharebest\Webtrees\Elements\PlaceHierarchy;
16500c92694SGreg Roachuse Fisharebest\Webtrees\Elements\PlaceLatitude;
16600c92694SGreg Roachuse Fisharebest\Webtrees\Elements\PlaceLivingOrdinance;
16700c92694SGreg Roachuse Fisharebest\Webtrees\Elements\PlaceLongtitude;
16800c92694SGreg Roachuse Fisharebest\Webtrees\Elements\PlaceName;
16900c92694SGreg Roachuse Fisharebest\Webtrees\Elements\PlacePhoneticVariation;
17000c92694SGreg Roachuse Fisharebest\Webtrees\Elements\PlaceRomanizedVariation;
17100c92694SGreg Roachuse Fisharebest\Webtrees\Elements\Possessions;
17200c92694SGreg Roachuse Fisharebest\Webtrees\Elements\Probate;
17300c92694SGreg Roachuse Fisharebest\Webtrees\Elements\PublicationDate;
17400c92694SGreg Roachuse Fisharebest\Webtrees\Elements\ReceivingSystemName;
17500c92694SGreg Roachuse Fisharebest\Webtrees\Elements\RelationIsDescriptor;
17600c92694SGreg Roachuse Fisharebest\Webtrees\Elements\ReligiousAffiliation;
17700c92694SGreg Roachuse Fisharebest\Webtrees\Elements\RepositoryRecord;
17800c92694SGreg Roachuse Fisharebest\Webtrees\Elements\Residence;
1793b2b4f4aSGreg Roachuse Fisharebest\Webtrees\Elements\ResidenceWithValue;
18000c92694SGreg Roachuse Fisharebest\Webtrees\Elements\ResponsibleAgency;
18100c92694SGreg Roachuse Fisharebest\Webtrees\Elements\RestrictionNotice;
18200c92694SGreg Roachuse Fisharebest\Webtrees\Elements\Retirement;
18300c92694SGreg Roachuse Fisharebest\Webtrees\Elements\RoleInEvent;
18400c92694SGreg Roachuse Fisharebest\Webtrees\Elements\RomanizedType;
18500c92694SGreg Roachuse Fisharebest\Webtrees\Elements\ScholasticAchievement;
18600c92694SGreg Roachuse Fisharebest\Webtrees\Elements\SexValue;
18700c92694SGreg Roachuse Fisharebest\Webtrees\Elements\SocialSecurityNumber;
18800c92694SGreg Roachuse Fisharebest\Webtrees\Elements\SourceCallNumber;
18900c92694SGreg Roachuse Fisharebest\Webtrees\Elements\SourceData;
19000c92694SGreg Roachuse Fisharebest\Webtrees\Elements\SourceFiledByEntry;
19100c92694SGreg Roachuse Fisharebest\Webtrees\Elements\SourceJurisdictionPlace;
19200c92694SGreg Roachuse Fisharebest\Webtrees\Elements\SourceMediaType;
19300c92694SGreg Roachuse Fisharebest\Webtrees\Elements\SourceOriginator;
19400c92694SGreg Roachuse Fisharebest\Webtrees\Elements\SourcePublicationFacts;
19500c92694SGreg Roachuse Fisharebest\Webtrees\Elements\SourceRecord;
19600c92694SGreg Roachuse Fisharebest\Webtrees\Elements\SubmissionRecord;
19700c92694SGreg Roachuse Fisharebest\Webtrees\Elements\SubmitterName;
19800c92694SGreg Roachuse Fisharebest\Webtrees\Elements\SubmitterRecord;
19900c92694SGreg Roachuse Fisharebest\Webtrees\Elements\SubmitterRegisteredRfn;
20000c92694SGreg Roachuse Fisharebest\Webtrees\Elements\SubmitterText;
20100c92694SGreg Roachuse Fisharebest\Webtrees\Elements\TempleCode;
20200c92694SGreg Roachuse Fisharebest\Webtrees\Elements\TextFromSource;
203099c152eSGreg Roachuse Fisharebest\Webtrees\Elements\TimeValueNow;
20400c92694SGreg Roachuse Fisharebest\Webtrees\Elements\TransmissionDate;
20500c92694SGreg Roachuse Fisharebest\Webtrees\Elements\UserReferenceNumber;
20600c92694SGreg Roachuse Fisharebest\Webtrees\Elements\UserReferenceType;
20700c92694SGreg Roachuse Fisharebest\Webtrees\Elements\VersionNumber;
20800c92694SGreg Roachuse Fisharebest\Webtrees\Elements\WebtreesUser;
20900c92694SGreg Roachuse Fisharebest\Webtrees\Elements\WhereWithinSource;
21000c92694SGreg Roachuse Fisharebest\Webtrees\Elements\Will;
21100c92694SGreg Roachuse Fisharebest\Webtrees\Elements\XrefAssociate;
21200c92694SGreg Roachuse Fisharebest\Webtrees\Elements\XrefFamily;
21300c92694SGreg Roachuse Fisharebest\Webtrees\Elements\XrefIndividual;
21400c92694SGreg Roachuse Fisharebest\Webtrees\Elements\XrefMedia;
21500c92694SGreg Roachuse Fisharebest\Webtrees\Elements\XrefRepository;
21600c92694SGreg Roachuse Fisharebest\Webtrees\Elements\XrefSource;
21700c92694SGreg Roachuse Fisharebest\Webtrees\Elements\XrefSubmission;
21800c92694SGreg Roachuse Fisharebest\Webtrees\Elements\XrefSubmitter;
21900c92694SGreg Roach
2200f471f91SGreg Roach/**
2210f471f91SGreg Roach * GEDCOM 5.5.1 specification
2220f471f91SGreg Roach */
223c1010edaSGreg Roachclass Gedcom
224c1010edaSGreg Roach{
2250f471f91SGreg Roach    // 255 less the EOL character.
22616d6367aSGreg Roach    public const LINE_LENGTH = 253;
2278d0ebef0SGreg Roach
2288d0ebef0SGreg Roach    // Gedcom tags which indicate the start of life.
22969d5bee2SGreg Roach    public const BIRTH_EVENTS = ['BIRT', 'CHR', 'BAPM'];
2308d0ebef0SGreg Roach
2318d0ebef0SGreg Roach    // Gedcom tags which indicate the end of life.
23216d6367aSGreg Roach    public const DEATH_EVENTS = ['DEAT', 'BURI', 'CREM'];
2338d0ebef0SGreg Roach
2348d0ebef0SGreg Roach    // Gedcom tags which indicate the start of a relationship.
23516d6367aSGreg Roach    public const MARRIAGE_EVENTS = ['MARR', '_NMR'];
2368d0ebef0SGreg Roach
2378d0ebef0SGreg Roach    // Gedcom tags which indicate the end of a relationship.
23816d6367aSGreg Roach    public const DIVORCE_EVENTS = ['DIV', 'ANUL', '_SEPR'];
2398d0ebef0SGreg Roach
2408d0ebef0SGreg Roach    // Regular expression to match a GEDCOM tag.
24116d6367aSGreg Roach    public const REGEX_TAG = '[_A-Z][_A-Z0-9]*';
2428d0ebef0SGreg Roach
2438d0ebef0SGreg Roach    // Regular expression to match a GEDCOM XREF.
244f81cefe9SGreg Roach    public const REGEX_XREF = '[A-Za-z0-9:_.-]{1,20}';
2458d0ebef0SGreg Roach
246c67b9b50SGreg Roach    // Regular expression to match a GEDCOM fact/event for editing raw GEDCOM.
2478c21b414SGreg Roach    private const REGEX_VALUE   = '( .+)?';
2488c21b414SGreg Roach    private const REGEX_LEVEL_9 = '\n9 ' . self::REGEX_TAG . self::REGEX_VALUE;
2498c21b414SGreg Roach    private const REGEX_LEVEL_8 = '\n8 ' . self::REGEX_TAG . self::REGEX_VALUE . '(' . self::REGEX_LEVEL_9 . ')*';
2508c21b414SGreg Roach    private const REGEX_LEVEL_7 = '\n7 ' . self::REGEX_TAG . self::REGEX_VALUE . '(' . self::REGEX_LEVEL_8 . ')*';
2518c21b414SGreg Roach    private const REGEX_LEVEL_6 = '\n6 ' . self::REGEX_TAG . self::REGEX_VALUE . '(' . self::REGEX_LEVEL_7 . ')*';
2528c21b414SGreg Roach    private const REGEX_LEVEL_5 = '\n5 ' . self::REGEX_TAG . self::REGEX_VALUE . '(' . self::REGEX_LEVEL_6 . ')*';
2538c21b414SGreg Roach    private const REGEX_LEVEL_4 = '\n4 ' . self::REGEX_TAG . self::REGEX_VALUE . '(' . self::REGEX_LEVEL_5 . ')*';
2548c21b414SGreg Roach    private const REGEX_LEVEL_3 = '\n3 ' . self::REGEX_TAG . self::REGEX_VALUE . '(' . self::REGEX_LEVEL_4 . ')*';
2558c21b414SGreg Roach    private const REGEX_LEVEL_2 = '\n2 ' . self::REGEX_TAG . self::REGEX_VALUE . '(' . self::REGEX_LEVEL_3 . ')*';
256c67b9b50SGreg Roach    public const REGEX_FACT     = '1 ' . self::REGEX_TAG . self::REGEX_VALUE . '(' . self::REGEX_LEVEL_2 . ')*\n?';
2578c21b414SGreg Roach
2581c6adce8SGreg Roach    // Separates the parts of a place name.
259ead61980SGreg Roach    public const PLACE_SEPARATOR = ', ';
260392561bbSGreg Roach
261392561bbSGreg Roach    // Regex to match a (badly formed) GEDCOM place separator.
26290949315SGreg Roach    public const PLACE_SEPARATOR_REGEX = '/ *,[, ]*/';
26390949315SGreg Roach
26490949315SGreg Roach    // LATI and LONG tags
26590949315SGreg Roach    public const LATITUDE_NORTH = 'N';
26690949315SGreg Roach    public const LATITUDE_SOUTH = 'S';
26790949315SGreg Roach    public const LONGITUDE_EAST = 'E';
26890949315SGreg Roach    public const LONGITUDE_WEST = 'W';
26971f696adSGreg Roach
27071f696adSGreg Roach    // Not all record types allow a CHAN event.
27171f696adSGreg Roach    public const RECORDS_WITH_CHAN = [
27271f696adSGreg Roach        Family::RECORD_TYPE,
27371f696adSGreg Roach        Individual::RECORD_TYPE,
27471f696adSGreg Roach        Media::RECORD_TYPE,
27571f696adSGreg Roach        Note::RECORD_TYPE,
27671f696adSGreg Roach        Repository::RECORD_TYPE,
27771f696adSGreg Roach        Source::RECORD_TYPE,
27871f696adSGreg Roach        Submitter::RECORD_TYPE,
27971f696adSGreg Roach    ];
280c8183f29SGreg Roach
281c8183f29SGreg Roach    // These preferences control multiple tag definitions
282c8183f29SGreg Roach    public const HIDDEN_TAGS = [
283c8183f29SGreg Roach        // Individual names
284c8183f29SGreg Roach        'NAME_NPFX'  => ['INDI:NAME:NPFX', 'INDI:NAME:FONE:NPFX', 'INDI:NAME:ROMN:NPFX'],
285c8183f29SGreg Roach        'NAME_SPFX'  => ['INDI:NAME:SPFX', 'INDI:NAME:FONE:SPFX', 'INDI:NAME:ROMN:SPFX'],
286c8183f29SGreg Roach        'NAME_NSFX'  => ['INDI:NAME:NSFX', 'INDI:NAME:FONE:NSFX', 'INDI:NAME:ROMN:NSFX'],
287c8183f29SGreg Roach        'NAME_NICK'  => ['INDI:NAME:NICK', 'INDI:NAME:FONE:NICK', 'INDI:NAME:ROMN:NICK'],
288c8183f29SGreg Roach        'NAME_FONE'  => ['INDI:NAME:FONE'],
289c8183f29SGreg Roach        'NAME_ROMN'  => ['INDI:NAME:ROMN'],
29003c55594SGreg Roach        'NAME_NOTE'  => ['INDI:NAME:NOTE', 'INDI:NAME:FONE:NOTE', 'INDI:NAME:ROMN:NOTE'],
29103c55594SGreg Roach        'NAME_SOUR'  => ['INDI:NAME:SOUR', 'INDI:NAME:FONE:SOUR', 'INDI:NAME:ROMN:SOUR'],
292c8183f29SGreg Roach        // Places
293302fdb8dSGreg Roach        'PLAC_MAP'   => [':PLAC:MAP'],
294302fdb8dSGreg Roach        'PLAC_FONE'  => [':PLAC:FONE'],
295302fdb8dSGreg Roach        'PLAC_ROMN'  => [':PLAC:ROMN'],
296302fdb8dSGreg Roach        'PLAC_FORM'  => [':PLAC:FORM', 'HEAD:PLAC'],
297302fdb8dSGreg Roach        'PLAC_NOTE'  => [':PLAC:NOTE'],
298c8183f29SGreg Roach        // Addresses
299302fdb8dSGreg Roach        'ADDR_EMAIL' => [':EMAIL'],
300302fdb8dSGreg Roach        'ADDR_PHON'  => [':PHON'],
301302fdb8dSGreg Roach        'ADDR_WWW'   => [':WWW'],
302c8183f29SGreg Roach        // Source citations
303c8183f29SGreg Roach        'SOUR_EVEN'  => [':SOUR:EVEN'],
304c8183f29SGreg Roach        'SOUR_DATE'  => [':SOUR:DATA:DATE'],
305c8183f29SGreg Roach        'SOUR_NOTE'  => [':SOUR:NOTE'],
306c8183f29SGreg Roach        'SOUR_QUAY'  => [':SOUR:QUAY'],
307c8183f29SGreg Roach        // Sources
30840c249dcSGreg Roach        'SOUR_DATA'  => ['SOUR:DATA:EVEN', 'SOUR:DATA:AGNC', 'SOUR:DATA:NOTE'],
309c8183f29SGreg Roach        // Individuals
310c8183f29SGreg Roach        'BIRT_FAMC'  => ['INDI:BIRT:FAMC'],
311c8183f29SGreg Roach        'RELI'       => ['INDI:RELI'],
312c8183f29SGreg Roach        'BAPM'       => ['INDI:BAPM'],
313c8183f29SGreg Roach        'CHR'        => ['INDI:CHR', 'INDI:CHRA'],
314c8183f29SGreg Roach        'FCOM'       => ['INDI:FCOM', 'INDI:CONF'],
315c8183f29SGreg Roach        'ORDN'       => ['INDI:ORDN'],
316c8183f29SGreg Roach        'BARM'       => ['INDI:BARM', 'INDI:BASM'],
317c8183f29SGreg Roach        'ALIA'       => ['INDI:ALIA'],
318c8183f29SGreg Roach        'ASSO'       => ['INDI:ASSO'],
319c8183f29SGreg Roach        // Families
320c8183f29SGreg Roach        'ENGA'       => ['FAM:ENGA'],
321c8183f29SGreg Roach        'MARB'       => ['FAM:MARB'],
322c8183f29SGreg Roach        'MARC'       => ['FAM:MARC'],
323c8183f29SGreg Roach        'MARL'       => ['FAM:MARL'],
324c8183f29SGreg Roach        'MARS'       => ['FAM:MARS'],
325c8183f29SGreg Roach        'ANUL'       => ['FAM:ANUL'],
326c8183f29SGreg Roach        'DIVF'       => ['FAM:DIVF'],
327c8183f29SGreg Roach        'FAM_RESI'   => ['FAM:RESI'],
328c8183f29SGreg Roach        'FAM_CENS'   => ['FAM:CENS'],
329c8183f29SGreg Roach        // LDS church
330c8183f29SGreg Roach        'LDS'        => ['INDI:BAPL', 'INDI:CONL', 'INDI:ENDL', 'INDI:SLGC', 'FAM:SLGS', 'HEAD:SUBN'],
331c8183f29SGreg Roach        // Identifiers
332c8183f29SGreg Roach        'AFN'        => ['INDI:AFN'],
333c8183f29SGreg Roach        'IDNO'       => ['INDI:IDNO'],
334c8183f29SGreg Roach        'SSN'        => ['INDI:SSN'],
335302fdb8dSGreg Roach        'RFN'        => [':RFN'],
336302fdb8dSGreg Roach        'REFN'       => [':REFN'],
337302fdb8dSGreg Roach        'RIN'        => [':RIN'],
338c8183f29SGreg Roach        // Submitters
339c8183f29SGreg Roach        'SUBM'       => ['INDI:SUBM', 'FAM:SUBM'],
340c8183f29SGreg Roach        'ANCI'       => ['INDI:ANCI', 'INDI:DESI'],
341c8183f29SGreg Roach    ];
34200c92694SGreg Roach
34300c92694SGreg Roach    // Custom GEDCOM tags that can be created in webtrees.
34400c92694SGreg Roach    public const CUSTOM_FAMILY_TAGS = [
34538f085bcSGreg Roach        'FACT',
34600c92694SGreg Roach        '_COML',
34700c92694SGreg Roach        '_MARI',
34800c92694SGreg Roach        '_MBON',
34900c92694SGreg Roach        '_NMR',
35000c92694SGreg Roach        '_SEPR',
35100c92694SGreg Roach    ];
35200c92694SGreg Roach
35300c92694SGreg Roach    public const CUSTOM_INDIVIDUAL_TAGS = [
35400c92694SGreg Roach        '_BRTM',
35500c92694SGreg Roach        '_CIRC',
35600c92694SGreg Roach        '_DEG',
35700c92694SGreg Roach        '_DNA',
35800c92694SGreg Roach        '_EXCM',
35900c92694SGreg Roach        '_EYEC',
36000c92694SGreg Roach        '_FNRL',
36100c92694SGreg Roach        '_FSFTID',
36200c92694SGreg Roach        '_HAIR',
36300c92694SGreg Roach        '_HEIG',
36400c92694SGreg Roach        '_INTE',
36500c92694SGreg Roach        '_MDCL',
36600c92694SGreg Roach        '_MEDC',
36700c92694SGreg Roach        '_MILI',
36800c92694SGreg Roach        '_MILT',
36900c92694SGreg Roach        '_NAMS',
370a49c80d4SGreg Roach        '_NMAR',
37100c92694SGreg Roach        '_PRMN',
37200c92694SGreg Roach        '_WEIG',
37300c92694SGreg Roach        '_YART',
37400c92694SGreg Roach    ];
37500c92694SGreg Roach
376356588a1SGreg Roach    // Some applications create GEDCOM files containing records without XREFS.
377356588a1SGreg Roach    // We cannot process these.
378356588a1SGreg Roach    public const CUSTOM_RECORDS_WITHOUT_XREFS = [
379356588a1SGreg Roach        'EMOTIONALRELATIONSHIP', // GenoPro
380356588a1SGreg Roach        'GENOMAP', // GenoPro
381356588a1SGreg Roach        'GLOBAL', // GenoPro
382356588a1SGreg Roach        'LABEL', // GenoPro
383356588a1SGreg Roach        'PEDIGREELINK', // GenoPro
384356588a1SGreg Roach        'SOCIALRELATIONSHIP', // GenoPro
385356588a1SGreg Roach        '_EVDEF', // RootsMagic
386356588a1SGreg Roach        '_EVENT_DEFN', // PAF and Legacy
387356588a1SGreg Roach        '_HASHTAG_DEFN', // Legacy
38854671e98SGreg Roach        '_PUBLISH', // MyHeritage
3890e542193SGreg Roach        '_TASK', // Ages
390356588a1SGreg Roach        '_TODO', // Legacy
391356588a1SGreg Roach    ];
392356588a1SGreg Roach
39300c92694SGreg Roach    /**
39400c92694SGreg Roach     * Definitions for GEDCOM 5.5.1.
39500c92694SGreg Roach     *
39600c92694SGreg Roach     * @return array<string,ElementInterface>
39700c92694SGreg Roach     */
39800c92694SGreg Roach    private function gedcom551Tags(): array
39900c92694SGreg Roach    {
40000c92694SGreg Roach        return [
40100c92694SGreg Roach            'FAM'                        => new FamilyRecord(I18N::translate('Family')),
40200c92694SGreg Roach            'FAM:*:ADDR'                 => new AddressLine(I18N::translate('Address')),
40300c92694SGreg Roach            'FAM:*:ADDR:ADR1'            => new AddressLine1(I18N::translate('Address line 1')),
40400c92694SGreg Roach            'FAM:*:ADDR:ADR2'            => new AddressLine2(I18N::translate('Address line 2')),
40500c92694SGreg Roach            'FAM:*:ADDR:ADR3'            => new AddressLine3(I18N::translate('Address line 3')),
40600c92694SGreg Roach            'FAM:*:ADDR:CITY'            => new AddressCity(I18N::translate('City')),
40700c92694SGreg Roach            'FAM:*:ADDR:CTRY'            => new AddressCountry(I18N::translate('Country')),
40800c92694SGreg Roach            'FAM:*:ADDR:POST'            => new AddressPostalCode(I18N::translate('Postal code')),
40900c92694SGreg Roach            'FAM:*:ADDR:STAE'            => new AddressState(I18N::translate('State')),
41000c92694SGreg Roach            'FAM:*:AGNC'                 => new ResponsibleAgency(I18N::translate('Agency')),
41100c92694SGreg Roach            'FAM:*:CAUS'                 => new CauseOfEvent(I18N::translate('Cause')),
41200c92694SGreg Roach            'FAM:*:DATE'                 => new DateValue(I18N::translate('Date')),
41300c92694SGreg Roach            'FAM:*:EMAIL'                => new AddressEmail(I18N::translate('Email address')),
41400c92694SGreg Roach            'FAM:*:FAX'                  => new AddressFax(I18N::translate('Fax')),
41500c92694SGreg Roach            'FAM:*:HUSB'                 => new EmptyElement(I18N::translate('Husband'), ['AGE' => '0:1']),
41600c92694SGreg Roach            'FAM:*:HUSB:AGE'             => new AgeAtEvent(I18N::translate('Husband’s age')),
41700c92694SGreg Roach            'FAM:*:NOTE'                 => new NoteStructure(I18N::translate('Note')),
41800c92694SGreg Roach            'FAM:*:OBJE'                 => new XrefMedia(I18N::translate('Media object')),
41900c92694SGreg Roach            'FAM:*:PHON'                 => new PhoneNumber(I18N::translate('Phone')),
42000c92694SGreg Roach            'FAM:*:PLAC'                 => new PlaceName(I18N::translate('Place')),
42100c92694SGreg Roach            'FAM:*:PLAC:FONE'            => new PlacePhoneticVariation(I18N::translate('Phonetic place')),
42200c92694SGreg Roach            'FAM:*:PLAC:FONE:TYPE'       => new PhoneticType(I18N::translate('Type')),
42300c92694SGreg Roach            'FAM:*:PLAC:FORM'            => new PlaceHierarchy(I18N::translate('Format')),
42400c92694SGreg Roach            'FAM:*:PLAC:MAP'             => new Coordinates(I18N::translate('Coordinates')),
42500c92694SGreg Roach            'FAM:*:PLAC:MAP:LATI'        => new PlaceLatitude(I18N::translate('Latitude')),
42600c92694SGreg Roach            'FAM:*:PLAC:MAP:LONG'        => new PlaceLongtitude(I18N::translate('Longitude')),
427d64c51bcSGreg Roach            'FAM:*:PLAC:NOTE'            => new NoteStructure(I18N::translate('Note on place')),
42800c92694SGreg Roach            'FAM:*:PLAC:ROMN'            => new PlaceRomanizedVariation(I18N::translate('Romanized place')),
42900c92694SGreg Roach            'FAM:*:PLAC:ROMN:TYPE'       => new RomanizedType(I18N::translate('Type')),
43000c92694SGreg Roach            'FAM:*:RELI'                 => new ReligiousAffiliation(I18N::translate('Religion'), []),
43100c92694SGreg Roach            'FAM:*:RESN'                 => new RestrictionNotice(I18N::translate('Restriction')),
43200c92694SGreg Roach            'FAM:*:SOUR'                 => new XrefSource(I18N::translate('Source citation')),
43300c92694SGreg Roach            'FAM:*:SOUR:DATA'            => new SourceData(I18N::translate('Data')),
434352bd396SGreg Roach            'FAM:*:SOUR:DATA:DATE'       => new DateValue(I18N::translate('Date of entry in original source')),
43500c92694SGreg Roach            'FAM:*:SOUR:DATA:TEXT'       => new TextFromSource(I18N::translate('Text')),
43600c92694SGreg Roach            'FAM:*:SOUR:EVEN'            => new EventTypeCitedFrom(I18N::translate('Event')),
43700c92694SGreg Roach            'FAM:*:SOUR:EVEN:ROLE'       => new RoleInEvent(I18N::translate('Role')),
438d64c51bcSGreg Roach            'FAM:*:SOUR:NOTE'            => new NoteStructure(I18N::translate('Note on source citation')),
43900c92694SGreg Roach            'FAM:*:SOUR:OBJE'            => new XrefMedia(I18N::translate('Media object')),
44000c92694SGreg Roach            'FAM:*:SOUR:PAGE'            => new WhereWithinSource(I18N::translate('Citation details')),
44100c92694SGreg Roach            'FAM:*:SOUR:QUAY'            => new CertaintyAssessment(I18N::translate('Quality of data')),
44200c92694SGreg Roach            'FAM:*:TYPE'                 => new EventOrFactClassification(I18N::translate('Type')),
44300c92694SGreg Roach            'FAM:*:WIFE'                 => new EmptyElement(I18N::translate('Wife'), ['AGE' => '0:1']),
44400c92694SGreg Roach            'FAM:*:WIFE:AGE'             => new AgeAtEvent(I18N::translate('Wife’s age')),
44500c92694SGreg Roach            'FAM:*:WWW'                  => new AddressWebPage(I18N::translate('URL')),
44600c92694SGreg Roach            'FAM:ANUL'                   => new Annulment(I18N::translate('Annulment')),
44700c92694SGreg Roach            'FAM:CENS'                   => new FamilyCensus(I18N::translate('Family census')),
44800c92694SGreg Roach            'FAM:CHAN'                   => new Change(I18N::translate('Last change')),
44900c92694SGreg Roach            'FAM:CHAN:DATE'              => new ChangeDate(I18N::translate('Date of last change')),
450099c152eSGreg Roach            'FAM:CHAN:DATE:TIME'         => new TimeValueNow(I18N::translate('Time of last change')),
451d64c51bcSGreg Roach            'FAM:CHAN:NOTE'              => new NoteStructure(I18N::translate('Note on last change')),
45200c92694SGreg Roach            'FAM:CHIL'                   => new XrefIndividual(I18N::translate('Child')),
45300c92694SGreg Roach            'FAM:DIV'                    => new Divorce(I18N::translate('Divorce')),
45400c92694SGreg Roach            'FAM:DIV:DATE'               => new DateValue(I18N::translate('Date of divorce')),
45500c92694SGreg Roach            'FAM:DIVF'                   => new DivorceFiled(I18N::translate('Divorce filed')),
45600c92694SGreg Roach            'FAM:ENGA'                   => new Engagement(I18N::translate('Engagement')),
45700c92694SGreg Roach            'FAM:ENGA:DATE'              => new DateValue(I18N::translate('Date of engagement')),
45800c92694SGreg Roach            'FAM:ENGA:PLAC'              => new PlaceName(I18N::translate('Place of engagement')),
4595d2c6313SGreg Roach            'FAM:EVEN'                   => new FamilyEvent(I18N::translate('Event')),
4605d2c6313SGreg Roach            'FAM:EVEN:TYPE'              => new EventOrFactClassification(I18N::translate('Type of event')),
46100c92694SGreg Roach            'FAM:HUSB'                   => new XrefIndividual(I18N::translate('Husband')),
46200c92694SGreg Roach            'FAM:MARB'                   => new MarriageBanns(I18N::translate('Marriage banns')),
46300c92694SGreg Roach            'FAM:MARB:DATE'              => new DateValue(I18N::translate('Date of marriage banns')),
46400c92694SGreg Roach            'FAM:MARB:PLAC'              => new PlaceName(I18N::translate('Place of marriage banns')),
46500c92694SGreg Roach            'FAM:MARC'                   => new MarriageContract(I18N::translate('Marriage contract')),
46600c92694SGreg Roach            'FAM:MARL'                   => new MarriageLicence(I18N::translate('Marriage license')),
46700c92694SGreg Roach            'FAM:MARR'                   => new Marriage(I18N::translate('Marriage')),
46800c92694SGreg Roach            'FAM:MARR:DATE'              => new DateValue(I18N::translate('Date of marriage')),
46900c92694SGreg Roach            'FAM:MARR:PLAC'              => new PlaceName(I18N::translate('Place of marriage')),
47000c92694SGreg Roach            'FAM:MARR:TYPE'              => new MarriageType(I18N::translate('Type of marriage')),
47100c92694SGreg Roach            'FAM:MARS'                   => new MarriageSettlement(I18N::translate('Marriage settlement')),
472f9340759SGreg Roach            'FAM:NCHI'                   => new CountOfChildrenFam(I18N::translate('Number of children')),
47300c92694SGreg Roach            'FAM:NOTE'                   => new NoteStructure(I18N::translate('Note')),
47400c92694SGreg Roach            'FAM:OBJE'                   => new XrefMedia(I18N::translate('Media object')),
47500c92694SGreg Roach            'FAM:REFN'                   => new UserReferenceNumber(I18N::translate('Reference number')),
47600c92694SGreg Roach            'FAM:REFN:TYPE'              => new UserReferenceType(I18N::translate('Type of reference number')),
4773b2b4f4aSGreg Roach            'FAM:RESI'                   => new Residence(I18N::translate('Family residence')),
47800c92694SGreg Roach            'FAM:RESN'                   => new RestrictionNotice(I18N::translate('Restriction')),
47900c92694SGreg Roach            'FAM:RIN'                    => new AutomatedRecordId(I18N::translate('Record ID number')),
48000c92694SGreg Roach            'FAM:SLGS'                   => new LdsSpouseSealing(I18N::translate('LDS spouse sealing')),
48100c92694SGreg Roach            'FAM:SLGS:DATE'              => new DateLdsOrd(I18N::translate('Date of LDS spouse sealing')),
48200c92694SGreg Roach            'FAM:SLGS:PLAC'              => new PlaceLivingOrdinance(I18N::translate('Place of LDS spouse sealing')),
48300c92694SGreg Roach            'FAM:SLGS:STAT'              => new LdsSpouseSealingDateStatus(I18N::translate('Status')),
484099c152eSGreg Roach            'FAM:SLGS:STAT:DATE'         => new DateValueExact(I18N::translate('Status change date')),
48500c92694SGreg Roach            'FAM:SLGS:TEMP'              => new TempleCode(I18N::translate('Temple')),
48600c92694SGreg Roach            'FAM:SOUR'                   => new XrefSource(I18N::translate('Source citation')),
48700c92694SGreg Roach            'FAM:SOUR:DATA'              => new SourceData(I18N::translate('Data')),
488352bd396SGreg Roach            'FAM:SOUR:DATA:DATE'         => new DateValue(I18N::translate('Date of entry in original source')),
48900c92694SGreg Roach            'FAM:SOUR:DATA:TEXT'         => new TextFromSource(I18N::translate('Text')),
49000c92694SGreg Roach            'FAM:SOUR:EVEN'              => new EventTypeCitedFrom(I18N::translate('Event')),
49100c92694SGreg Roach            'FAM:SOUR:EVEN:ROLE'         => new RoleInEvent(I18N::translate('Role')),
492d64c51bcSGreg Roach            'FAM:SOUR:NOTE'              => new NoteStructure(I18N::translate('Note on source citation')),
49300c92694SGreg Roach            'FAM:SOUR:OBJE'              => new XrefMedia(I18N::translate('Media object')),
49400c92694SGreg Roach            'FAM:SOUR:PAGE'              => new WhereWithinSource(I18N::translate('Citation details')),
49500c92694SGreg Roach            'FAM:SOUR:QUAY'              => new CertaintyAssessment(I18N::translate('Quality of data')),
49600c92694SGreg Roach            'FAM:SUBM'                   => new XrefSubmitter(I18N::translate('Submitter')),
49700c92694SGreg Roach            'FAM:WIFE'                   => new XrefIndividual(I18N::translate('Wife')),
49800c92694SGreg Roach            'HEAD'                       => new HeaderRecord(I18N::translate('Header')),
49900c92694SGreg Roach            'HEAD:CHAR'                  => new CharacterSet(I18N::translate('Character set')),
50000c92694SGreg Roach            'HEAD:CHAR:VERS'             => new VersionNumber(I18N::translate('Version')),
50100c92694SGreg Roach            'HEAD:COPR'                  => new CopyrightFile(I18N::translate('Copyright')),
50200c92694SGreg Roach            'HEAD:DATE'                  => new TransmissionDate(I18N::translate('Date')),
503099c152eSGreg Roach            'HEAD:DATE:TIME'             => new TimeValueNow(I18N::translate('Time')),
50400c92694SGreg Roach            'HEAD:DEST'                  => new ReceivingSystemName(I18N::translate('Destination')),
50500c92694SGreg Roach            'HEAD:FILE'                  => new FileName(I18N::translate('Filename')),
50600c92694SGreg Roach            'HEAD:GEDC'                  => new GedcomElement(I18N::translate('GEDCOM')),
50700c92694SGreg Roach            'HEAD:GEDC:FORM'             => new Form(I18N::translate('Format')),
50800c92694SGreg Roach            'HEAD:GEDC:VERS'             => new VersionNumber(I18N::translate('Version')),
50900c92694SGreg Roach            'HEAD:LANG'                  => new LanguageId(I18N::translate('Language')),
51000c92694SGreg Roach            'HEAD:NOTE'                  => new ContentDescription(I18N::translate('Note')),
51100c92694SGreg Roach            'HEAD:PLAC'                  => new EmptyElement(I18N::translate('Place hierarchy'), ['FORM' => '1:1']),
51200c92694SGreg Roach            'HEAD:PLAC:FORM'             => new PlaceHierarchy(I18N::translate('Format')),
5134c10b11dSGreg Roach            'HEAD:SOUR'                  => new ApprovedSystemId(I18N::translate('Application ID')),
51400c92694SGreg Roach            'HEAD:SOUR:CORP'             => new NameOfBusiness(I18N::translate('Corporation')),
51500c92694SGreg Roach            'HEAD:SOUR:CORP:ADDR'        => new AddressLine(I18N::translate('Address')),
51600c92694SGreg Roach            'HEAD:SOUR:CORP:ADDR:ADR1'   => new AddressLine1(I18N::translate('Address line 1')),
51700c92694SGreg Roach            'HEAD:SOUR:CORP:ADDR:ADR2'   => new AddressLine2(I18N::translate('Address line 2')),
51800c92694SGreg Roach            'HEAD:SOUR:CORP:ADDR:ADR3'   => new AddressLine3(I18N::translate('Address line 3')),
51900c92694SGreg Roach            'HEAD:SOUR:CORP:ADDR:CITY'   => new AddressCity(I18N::translate('City')),
52000c92694SGreg Roach            'HEAD:SOUR:CORP:ADDR:CTRY'   => new AddressCountry(I18N::translate('Country')),
52100c92694SGreg Roach            'HEAD:SOUR:CORP:ADDR:POST'   => new AddressPostalCode(I18N::translate('Postal code')),
52200c92694SGreg Roach            'HEAD:SOUR:CORP:ADDR:STAE'   => new AddressState(I18N::translate('State')),
52300c92694SGreg Roach            'HEAD:SOUR:CORP:EMAIL'       => new AddressEmail(I18N::translate('Email address')),
52400c92694SGreg Roach            'HEAD:SOUR:CORP:FAX'         => new AddressFax(I18N::translate('Fax')),
52500c92694SGreg Roach            'HEAD:SOUR:CORP:PHON'        => new PhoneNumber(I18N::translate('Phone')),
52600c92694SGreg Roach            'HEAD:SOUR:CORP:WWW'         => new AddressWebPage(I18N::translate('URL')),
5274c10b11dSGreg Roach            'HEAD:SOUR:DATA'             => new NameOfSourceData(I18N::translate('Data')),
52800c92694SGreg Roach            'HEAD:SOUR:DATA:COPR'        => new CopyrightSourceData(I18N::translate('Copyright')),
52900c92694SGreg Roach            'HEAD:SOUR:DATA:DATE'        => new PublicationDate(I18N::translate('Date')),
5304c10b11dSGreg Roach            'HEAD:SOUR:NAME'             => new NameOfProduct(I18N::translate('Application name')),
53100c92694SGreg Roach            'HEAD:SOUR:VERS'             => new VersionNumber(I18N::translate('Version')),
53200c92694SGreg Roach            'HEAD:SUBM'                  => new XrefSubmitter(I18N::translate('Submitter')),
53300c92694SGreg Roach            'HEAD:SUBN'                  => new XrefSubmission(I18N::translate('Submission')),
53400c92694SGreg Roach            'INDI'                       => new IndividualRecord(I18N::translate('Individual')),
53500c92694SGreg Roach            'INDI:*:ADDR'                => new AddressLine(I18N::translate('Address')),
53600c92694SGreg Roach            'INDI:*:ADDR:ADR1'           => new AddressLine1(I18N::translate('Address line 1')),
53700c92694SGreg Roach            'INDI:*:ADDR:ADR2'           => new AddressLine2(I18N::translate('Address line 2')),
53800c92694SGreg Roach            'INDI:*:ADDR:ADR3'           => new AddressLine3(I18N::translate('Address line 3')),
53900c92694SGreg Roach            'INDI:*:ADDR:CITY'           => new AddressCity(I18N::translate('City')),
54000c92694SGreg Roach            'INDI:*:ADDR:CTRY'           => new AddressCountry(I18N::translate('Country')),
54100c92694SGreg Roach            'INDI:*:ADDR:POST'           => new AddressPostalCode(I18N::translate('Postal code')),
54200c92694SGreg Roach            'INDI:*:ADDR:STAE'           => new AddressState(I18N::translate('State')),
54300c92694SGreg Roach            'INDI:*:AGE'                 => new AgeAtEvent(I18N::translate('Age')),
54400c92694SGreg Roach            'INDI:*:AGNC'                => new ResponsibleAgency(I18N::translate('Agency')),
54500c92694SGreg Roach            'INDI:*:CAUS'                => new CauseOfEvent(I18N::translate('Cause')),
54600c92694SGreg Roach            'INDI:*:DATE'                => new DateValue(I18N::translate('Date')),
54700c92694SGreg Roach            'INDI:*:EMAIL'               => new AddressEmail(I18N::translate('Email address')),
54800c92694SGreg Roach            'INDI:*:FAX'                 => new AddressFax(I18N::translate('Fax')),
54900c92694SGreg Roach            'INDI:*:NOTE'                => new NoteStructure(I18N::translate('Note')),
55000c92694SGreg Roach            'INDI:*:OBJE'                => new XrefMedia(I18N::translate('Media object')),
55100c92694SGreg Roach            'INDI:*:PHON'                => new PhoneNumber(I18N::translate('Phone')),
55200c92694SGreg Roach            'INDI:*:PLAC'                => new PlaceName(I18N::translate('Place')),
55300c92694SGreg Roach            'INDI:*:PLAC:FONE'           => new PlacePhoneticVariation(I18N::translate('Phonetic place')),
55400c92694SGreg Roach            'INDI:*:PLAC:FONE:TYPE'      => new PhoneticType(I18N::translate('Type')),
55500c92694SGreg Roach            'INDI:*:PLAC:FORM'           => new PlaceHierarchy(I18N::translate('Format')),
55600c92694SGreg Roach            'INDI:*:PLAC:MAP'            => new Coordinates(I18N::translate('Coordinates')),
55700c92694SGreg Roach            'INDI:*:PLAC:MAP:LATI'       => new PlaceLatitude(I18N::translate('Latitude')),
55800c92694SGreg Roach            'INDI:*:PLAC:MAP:LONG'       => new PlaceLongtitude(I18N::translate('Longitude')),
559d64c51bcSGreg Roach            'INDI:*:PLAC:NOTE'           => new NoteStructure(I18N::translate('Note on place')),
56000c92694SGreg Roach            'INDI:*:PLAC:ROMN'           => new PlaceRomanizedVariation(I18N::translate('Romanized place')),
56100c92694SGreg Roach            'INDI:*:PLAC:ROMN:TYPE'      => new RomanizedType(I18N::translate('Type')),
56200c92694SGreg Roach            'INDI:*:RELI'                => new ReligiousAffiliation(I18N::translate('Religion'), []),
56300c92694SGreg Roach            'INDI:*:RESN'                => new RestrictionNotice(I18N::translate('Restriction')),
56400c92694SGreg Roach            'INDI:*:SOUR'                => new XrefSource(I18N::translate('Source citation')),
56500c92694SGreg Roach            'INDI:*:SOUR:DATA'           => new SourceData(I18N::translate('Data')),
566352bd396SGreg Roach            'INDI:*:SOUR:DATA:DATE'      => new DateValue(I18N::translate('Date of entry in original source')),
56700c92694SGreg Roach            'INDI:*:SOUR:DATA:TEXT'      => new TextFromSource(I18N::translate('Text')),
56800c92694SGreg Roach            'INDI:*:SOUR:EVEN'           => new EventTypeCitedFrom(I18N::translate('Event')),
56900c92694SGreg Roach            'INDI:*:SOUR:EVEN:ROLE'      => new RoleInEvent(I18N::translate('Role')),
570d64c51bcSGreg Roach            'INDI:*:SOUR:NOTE'           => new NoteStructure(I18N::translate('Note on source citation')),
57100c92694SGreg Roach            'INDI:*:SOUR:OBJE'           => new XrefMedia(I18N::translate('Media object')),
57200c92694SGreg Roach            'INDI:*:SOUR:PAGE'           => new WhereWithinSource(I18N::translate('Citation details')),
57300c92694SGreg Roach            'INDI:*:SOUR:QUAY'           => new CertaintyAssessment(I18N::translate('Quality of data')),
57400c92694SGreg Roach            'INDI:*:TYPE'                => new EventOrFactClassification(I18N::translate('Type')),
57500c92694SGreg Roach            'INDI:*:WWW'                 => new AddressWebPage(I18N::translate('URL')),
57600c92694SGreg Roach            'INDI:ADOP'                  => new Adoption(I18N::translate('Adoption')),
57700c92694SGreg Roach            'INDI:ADOP:DATE'             => new DateValue(I18N::translate('Date of adoption')),
578185ccc3fSGreg Roach            'INDI:ADOP:FAMC'             => new XrefFamily(I18N::translate('Adoptive parents'), ['ADOP' => '0:1']),
57900c92694SGreg Roach            'INDI:ADOP:FAMC:ADOP'        => new AdoptedByWhichParent(I18N::translate('Adoption')),
58000c92694SGreg Roach            'INDI:ADOP:PLAC'             => new PlaceName(I18N::translate('Place of adoption')),
58100c92694SGreg Roach            'INDI:AFN'                   => new AncestralFileNumber(I18N::translate('Ancestral file number')),
58200c92694SGreg Roach            'INDI:ALIA'                  => new XrefIndividual(I18N::translate('Alias')),
58300c92694SGreg Roach            'INDI:ANCI'                  => new XrefSubmitter(I18N::translate('Ancestors interest')),
58400c92694SGreg Roach            'INDI:ASSO'                  => new XrefAssociate(I18N::translate('Associate')),
58500c92694SGreg Roach            'INDI:ASSO:RELA'             => new RelationIsDescriptor(I18N::translate('Relationship')),
58600c92694SGreg Roach            'INDI:BAPL'                  => new LdsBaptism(I18N::translate('LDS baptism')),
58700c92694SGreg Roach            'INDI:BAPL:DATE'             => new DateLdsOrd(I18N::translate('Date of LDS baptism')),
58800c92694SGreg Roach            'INDI:BAPL:PLAC'             => new PlaceLivingOrdinance(I18N::translate('Place of LDS baptism')),
58900c92694SGreg Roach            'INDI:BAPL:STAT'             => new LdsBaptismDateStatus(I18N::translate('Status')),
590099c152eSGreg Roach            'INDI:BAPL:STAT:DATE'        => new DateValueExact(I18N::translate('Status change date')),
59100c92694SGreg Roach            'INDI:BAPL:TEMP'             => new TempleCode(I18N::translate('Temple')),
59200c92694SGreg Roach            'INDI:BAPM'                  => new Baptism(I18N::translate('Baptism')),
59300c92694SGreg Roach            'INDI:BAPM:DATE'             => new DateValue(I18N::translate('Date of baptism')),
59400c92694SGreg Roach            'INDI:BAPM:PLAC'             => new PlaceName(I18N::translate('Place of baptism')),
59500c92694SGreg Roach            'INDI:BARM'                  => new BarMitzvah(I18N::translate('Bar mitzvah')),
59600c92694SGreg Roach            'INDI:BARM:DATE'             => new DateValue(I18N::translate('Date of bar mitzvah')),
59700c92694SGreg Roach            'INDI:BARM:PLAC'             => new PlaceName(I18N::translate('Place of bar mitzvah')),
59800c92694SGreg Roach            'INDI:BASM'                  => new BasMitzvah(I18N::translate('Bat mitzvah')),
599a225c3faSGreg Roach            'INDI:BASM:DATE'             => new DateValue(I18N::translate('Date of bat mitzvah')),
600a225c3faSGreg Roach            'INDI:BASM:PLAC'             => new PlaceName(I18N::translate('Place of bat mitzvah')),
60100c92694SGreg Roach            'INDI:BIRT'                  => new Birth(I18N::translate('Birth')),
60200c92694SGreg Roach            'INDI:BIRT:DATE'             => new DateValue(I18N::translate('Date of birth')),
60300c92694SGreg Roach            'INDI:BIRT:FAMC'             => new XrefFamily(I18N::translate('Birth parents')),
60400c92694SGreg Roach            'INDI:BIRT:PLAC'             => new PlaceName(I18N::translate('Place of birth')),
60500c92694SGreg Roach            'INDI:BLES'                  => new Blessing(I18N::translate('Blessing')),
60600c92694SGreg Roach            'INDI:BLES:DATE'             => new DateValue(I18N::translate('Date of blessing')),
60700c92694SGreg Roach            'INDI:BLES:PLAC'             => new PlaceName(I18N::translate('Place of blessing')),
60800c92694SGreg Roach            'INDI:BURI'                  => new Burial(I18N::translate('Burial')),
60900c92694SGreg Roach            'INDI:BURI:DATE'             => new DateValue(I18N::translate('Date of burial')),
61000c92694SGreg Roach            'INDI:BURI:PLAC'             => new PlaceName(I18N::translate('Place of burial')),
61100c92694SGreg Roach            'INDI:CAST'                  => new CasteName(I18N::translate('Caste')),
61200c92694SGreg Roach            'INDI:CENS'                  => new Census(I18N::translate('Census')),
61300c92694SGreg Roach            'INDI:CENS:DATE'             => new DateValue(I18N::translate('Census date')),
61400c92694SGreg Roach            'INDI:CENS:PLAC'             => new PlaceName(I18N::translate('Census place')),
61500c92694SGreg Roach            'INDI:CHAN'                  => new Change(I18N::translate('Last change')),
61600c92694SGreg Roach            'INDI:CHAN:DATE'             => new ChangeDate(I18N::translate('Date of last change')),
617099c152eSGreg Roach            'INDI:CHAN:DATE:TIME'        => new TimeValueNow(I18N::translate('Time of last change')),
618d64c51bcSGreg Roach            'INDI:CHAN:NOTE'             => new NoteStructure(I18N::translate('Note on last change')),
61900c92694SGreg Roach            'INDI:CHR'                   => new Christening(I18N::translate('Christening')),
62000c92694SGreg Roach            'INDI:CHR:DATE'              => new DateValue(I18N::translate('Date of christening')),
62100c92694SGreg Roach            'INDI:CHR:FAMC'              => new XrefFamily(I18N::translate('Godparents')),
62200c92694SGreg Roach            'INDI:CHR:PLAC'              => new PlaceName(I18N::translate('Place of christening')),
62300c92694SGreg Roach            'INDI:CHRA'                  => new AdultChristening(I18N::translate('Adult christening')),
62400c92694SGreg Roach            'INDI:CHRA:PLAC'             => new PlaceName(I18N::translate('Place of christening')),
62500c92694SGreg Roach            'INDI:CONF'                  => new Confirmation(I18N::translate('Confirmation')),
62600c92694SGreg Roach            'INDI:CONF:DATE'             => new DateValue(I18N::translate('Date of confirmation')),
62700c92694SGreg Roach            'INDI:CONF:PLAC'             => new PlaceName(I18N::translate('Place of confirmation')),
62800c92694SGreg Roach            'INDI:CONL'                  => new LdsConfirmation(I18N::translate('LDS confirmation')),
62900c92694SGreg Roach            'INDI:CONL:DATE'             => new DateLdsOrd(I18N::translate('Date of LDS confirmation')),
63000c92694SGreg Roach            'INDI:CONL:PLAC'             => new PlaceLivingOrdinance(I18N::translate('Place of LDS confirmation')),
631701f5d18SGreg Roach            'INDI:CONL:STAT'             => new LdsBaptismDateStatus(I18N::translate('Status')),
632099c152eSGreg Roach            'INDI:CONL:STAT:DATE'        => new DateValueExact(I18N::translate('Status change date')),
63300c92694SGreg Roach            'INDI:CONL:TEMP'             => new TempleCode(I18N::translate('Temple')),
63400c92694SGreg Roach            'INDI:CREM'                  => new Cremation(I18N::translate('Cremation')),
63500c92694SGreg Roach            'INDI:CREM:DATE'             => new DateValue(I18N::translate('Date of cremation')),
63600c92694SGreg Roach            'INDI:CREM:PLAC'             => new PlaceName(I18N::translate('Place of cremation')),
63700c92694SGreg Roach            'INDI:DEAT'                  => new Death(I18N::translate('Death')),
63800c92694SGreg Roach            'INDI:DEAT:CAUS'             => new CauseOfEvent(I18N::translate('Cause of death')),
63900c92694SGreg Roach            'INDI:DEAT:DATE'             => new DateValue(I18N::translate('Date of death')),
64000c92694SGreg Roach            'INDI:DEAT:PLAC'             => new PlaceName(I18N::translate('Place of death')),
64100c92694SGreg Roach            'INDI:DESI'                  => new XrefSubmitter(I18N::translate('Descendants interest')),
64200c92694SGreg Roach            'INDI:DSCR'                  => new PhysicalDescription(I18N::translate('Description')),
64300c92694SGreg Roach            'INDI:EDUC'                  => new ScholasticAchievement(I18N::translate('Education')),
64400c92694SGreg Roach            'INDI:EDUC:AGNC'             => new ResponsibleAgency(I18N::translate('School or college')),
64500c92694SGreg Roach            'INDI:EMIG'                  => new Emigration(I18N::translate('Emigration')),
64600c92694SGreg Roach            'INDI:EMIG:DATE'             => new DateValue(I18N::translate('Date of emigration')),
64700c92694SGreg Roach            'INDI:EMIG:PLAC'             => new PlaceName(I18N::translate('Place of emigration')),
64800c92694SGreg Roach            'INDI:ENDL'                  => new LdsEndowment(I18N::translate('LDS endowment')),
64900c92694SGreg Roach            'INDI:ENDL:DATE'             => new DateLdsOrd(I18N::translate('Date of LDS endowment')),
65000c92694SGreg Roach            'INDI:ENDL:PLAC'             => new PlaceLivingOrdinance(I18N::translate('Place of LDS endowment')),
65100c92694SGreg Roach            'INDI:ENDL:STAT'             => new LdsEndowmentDateStatus(I18N::translate('Status')),
652099c152eSGreg Roach            'INDI:ENDL:STAT:DATE'        => new DateValueExact(I18N::translate('Status change date')),
65300c92694SGreg Roach            'INDI:ENDL:TEMP'             => new TempleCode(I18N::translate('Temple')),
6545d2c6313SGreg Roach            'INDI:EVEN'                  => new IndividualEvent(I18N::translate('Event')),
65500c92694SGreg Roach            'INDI:EVEN:DATE'             => new DateValue(I18N::translate('Date of event')),
65600c92694SGreg Roach            'INDI:EVEN:PLAC'             => new PlaceName(I18N::translate('Place of event')),
6575d2c6313SGreg Roach            'INDI:EVEN:TYPE'             => new EventOrFactClassification(I18N::translate('Type of event')),
6585d2c6313SGreg Roach            'INDI:FACT'                  => new IndividualFact(I18N::translate('Fact')),
6595d2c6313SGreg Roach            'INDI:FACT:TYPE'             => new EventOrFactClassification(I18N::translate('Type of fact')),
66000c92694SGreg Roach            'INDI:FAMC'                  => new XrefFamily(I18N::translate('Family as a child'), ['NOTE' => '0:1', 'PEDI' => '0:1', 'STAT' => '0:1']),
66100c92694SGreg Roach            'INDI:FAMC:PEDI'             => new PedigreeLinkageType(I18N::translate('Relationship to parents')),
66200c92694SGreg Roach            'INDI:FAMC:STAT'             => new ChildLinkageStatus(I18N::translate('Status')),
66300c92694SGreg Roach            'INDI:FAMS'                  => new XrefFamily(I18N::translate('Family as a spouse')),
66400c92694SGreg Roach            'INDI:FCOM'                  => new FirstCommunion(I18N::translate('First communion')),
66500c92694SGreg Roach            'INDI:FCOM:DATE'             => new DateValue(I18N::translate('Date of first communion')),
66600c92694SGreg Roach            'INDI:FCOM:PLAC'             => new PlaceName(I18N::translate('Place of first communion')),
66700c92694SGreg Roach            'INDI:GRAD'                  => new Graduation(I18N::translate('Graduation')),
66800c92694SGreg Roach            'INDI:GRAD:AGNC'             => new ResponsibleAgency(I18N::translate('School or college')),
66900c92694SGreg Roach            'INDI:IDNO'                  => new NationalIdNumber(I18N::translate('Identification number')),
6705d2c6313SGreg Roach            'INDI:IDNO:TYPE'             => new EventOrFactClassification(I18N::translate('Type of identification number')),
67100c92694SGreg Roach            'INDI:IMMI'                  => new Immigration(I18N::translate('Immigration')),
67200c92694SGreg Roach            'INDI:IMMI:DATE'             => new DateValue(I18N::translate('Date of immigration')),
67300c92694SGreg Roach            'INDI:IMMI:PLAC'             => new PlaceName(I18N::translate('Place of immigration')),
67400c92694SGreg Roach            'INDI:NAME'                  => new NamePersonal(I18N::translate('Name')),
67503c55594SGreg Roach            'INDI:NAME:*:SOUR'           => new XrefSource(I18N::translate('Source citation')),
67603c55594SGreg Roach            'INDI:NAME:*:SOUR:DATA'      => new SourceData(I18N::translate('Data')),
67703c55594SGreg Roach            'INDI:NAME:*:SOUR:DATA:DATE' => new DateValue(I18N::translate('Date of entry in original source')),
67803c55594SGreg Roach            'INDI:NAME:*:SOUR:DATA:TEXT' => new TextFromSource(I18N::translate('Text')),
67903c55594SGreg Roach            'INDI:NAME:*:SOUR:EVEN'      => new EventTypeCitedFrom(I18N::translate('Event')),
68003c55594SGreg Roach            'INDI:NAME:*:SOUR:EVEN:ROLE' => new RoleInEvent(I18N::translate('Role')),
681d64c51bcSGreg Roach            'INDI:NAME:*:SOUR:NOTE'      => new NoteStructure(I18N::translate('Note on source citation')),
68203c55594SGreg Roach            'INDI:NAME:*:SOUR:OBJE'      => new XrefMedia(I18N::translate('Media object')),
68303c55594SGreg Roach            'INDI:NAME:*:SOUR:PAGE'      => new WhereWithinSource(I18N::translate('Citation details')),
68403c55594SGreg Roach            'INDI:NAME:*:SOUR:QUAY'      => new CertaintyAssessment(I18N::translate('Quality of data')),
68500c92694SGreg Roach            'INDI:NAME:FONE'             => new NamePhoneticVariation(I18N::translate('Phonetic name')),
68600c92694SGreg Roach            'INDI:NAME:FONE:GIVN'        => new NamePieceGiven(I18N::translate('Given names')),
68700c92694SGreg Roach            'INDI:NAME:FONE:NICK'        => new NamePieceNickname(I18N::translate('Nickname')),
688d64c51bcSGreg Roach            'INDI:NAME:FONE:NOTE'        => new NoteStructure(I18N::translate('Note on phonetic name')),
68900c92694SGreg Roach            'INDI:NAME:FONE:NPFX'        => new NamePiecePrefix(I18N::translate('Name prefix')),
69000c92694SGreg Roach            'INDI:NAME:FONE:NSFX'        => new NamePieceSuffix(I18N::translate('Name suffix')),
69103c55594SGreg Roach            'INDI:NAME:FONE:SOUR'        => new XrefSource(I18N::translate('Source citation')),
69200c92694SGreg Roach            'INDI:NAME:FONE:SPFX'        => new NamePieceSurnamePrefix(I18N::translate('Surname prefix')),
69300c92694SGreg Roach            'INDI:NAME:FONE:SURN'        => new NamePieceSurname(I18N::translate('Surname')),
69400c92694SGreg Roach            'INDI:NAME:FONE:TYPE'        => new PhoneticType(I18N::translate('Phonetic type')),
69500c92694SGreg Roach            'INDI:NAME:GIVN'             => new NamePieceGiven(I18N::translate('Given names')),
69600c92694SGreg Roach            'INDI:NAME:NICK'             => new NamePieceNickname(I18N::translate('Nickname')),
69700c92694SGreg Roach            'INDI:NAME:NPFX'             => new NamePiecePrefix(I18N::translate('Name prefix')),
69800c92694SGreg Roach            'INDI:NAME:NSFX'             => new NamePieceSuffix(I18N::translate('Name suffix')),
69900c92694SGreg Roach            'INDI:NAME:ROMN'             => new NameRomanizedVariation(I18N::translate('Romanized name')),
70000c92694SGreg Roach            'INDI:NAME:ROMN:GIVN'        => new NamePieceGiven(I18N::translate('Given names')),
70100c92694SGreg Roach            'INDI:NAME:ROMN:NICK'        => new NamePieceNickname(I18N::translate('Nickname')),
702d64c51bcSGreg Roach            'INDI:NAME:ROMN:NOTE'        => new NoteStructure(I18N::translate('Note on romanized name')),
70300c92694SGreg Roach            'INDI:NAME:ROMN:NPFX'        => new NamePiecePrefix(I18N::translate('Name prefix')),
70400c92694SGreg Roach            'INDI:NAME:ROMN:NSFX'        => new NamePieceSuffix(I18N::translate('Name suffix')),
70503c55594SGreg Roach            'INDI:NAME:ROMN:SOUR'        => new XrefSource(I18N::translate('Source citation')),
70600c92694SGreg Roach            'INDI:NAME:ROMN:SPFX'        => new NamePieceSurnamePrefix(I18N::translate('Surname prefix')),
70700c92694SGreg Roach            'INDI:NAME:ROMN:SURN'        => new NamePieceSurname(I18N::translate('Surname')),
70800c92694SGreg Roach            'INDI:NAME:ROMN:TYPE'        => new RomanizedType(I18N::translate('Romanized type')),
70900c92694SGreg Roach            'INDI:NAME:SPFX'             => new NamePieceSurnamePrefix(I18N::translate('Surname prefix')),
71000c92694SGreg Roach            'INDI:NAME:SURN'             => new NamePieceSurname(I18N::translate('Surname')),
71100c92694SGreg Roach            'INDI:NAME:TYPE'             => new NameType(I18N::translate('Type of name')),
712f15544dcSGreg Roach            'INDI:NATI'                  => new NationalOrTribalOrigin(I18N::translate('Nationality')),
71300c92694SGreg Roach            'INDI:NATU'                  => new Naturalization(I18N::translate('Naturalization')),
71400c92694SGreg Roach            'INDI:NATU:DATE'             => new DateValue(I18N::translate('Date of naturalization')),
71500c92694SGreg Roach            'INDI:NATU:PLAC'             => new PlaceName(I18N::translate('Place of naturalization')),
71600c92694SGreg Roach            'INDI:NCHI'                  => new CountOfChildren(I18N::translate('Number of children')),
71700c92694SGreg Roach            'INDI:NMR'                   => new CountOfMarriages(I18N::translate('Number of marriages')),
71800c92694SGreg Roach            'INDI:NOTE'                  => new NoteStructure(I18N::translate('Note')),
71900c92694SGreg Roach            'INDI:OBJE'                  => new XrefMedia(I18N::translate('Media object')),
72000c92694SGreg Roach            'INDI:OCCU'                  => new Occupation(I18N::translate('Occupation')),
72100c92694SGreg Roach            'INDI:OCCU:AGNC'             => new ResponsibleAgency(I18N::translate('Employer')),
72200c92694SGreg Roach            'INDI:ORDN'                  => new Ordination(I18N::translate('Ordination')),
7231acded4fSGreg Roach            'INDI:ORDN:AGNC'             => new ResponsibleAgency(I18N::translate('Religious institution')),
7241acded4fSGreg Roach            'INDI:ORDN:DATE'             => new DateValue(I18N::translate('Date of ordination')),
7251acded4fSGreg Roach            'INDI:ORDN:PLAC'             => new PlaceName(I18N::translate('Place of ordination')),
72600c92694SGreg Roach            'INDI:PROB'                  => new Probate(I18N::translate('Probate')),
72700c92694SGreg Roach            'INDI:PROP'                  => new Possessions(I18N::translate('Property')),
72800c92694SGreg Roach            'INDI:REFN'                  => new UserReferenceNumber(I18N::translate('Reference number')),
72900c92694SGreg Roach            'INDI:REFN:TYPE'             => new UserReferenceType(I18N::translate('Type of reference number')),
73000c92694SGreg Roach            'INDI:RELI'                  => new ReligiousAffiliation(I18N::translate('Religion')),
73100c92694SGreg Roach            'INDI:RESI'                  => new Residence(I18N::translate('Residence')),
73200c92694SGreg Roach            'INDI:RESI:DATE'             => new DateValue(I18N::translate('Date of residence')),
73300c92694SGreg Roach            'INDI:RESI:PLAC'             => new PlaceName(I18N::translate('Place of residence')),
73400c92694SGreg Roach            'INDI:RESN'                  => new RestrictionNotice(I18N::translate('Restriction')),
73500c92694SGreg Roach            'INDI:RETI'                  => new Retirement(I18N::translate('Retirement')),
73600c92694SGreg Roach            'INDI:RETI:AGNC'             => new ResponsibleAgency(I18N::translate('Employer')),
73700c92694SGreg Roach            'INDI:RFN'                   => new PermanentRecordFileNumber(I18N::translate('Record file number')),
73800c92694SGreg Roach            'INDI:RIN'                   => new AutomatedRecordId(I18N::translate('Record ID number')),
73900c92694SGreg Roach            'INDI:SEX'                   => new SexValue(I18N::translate('Gender')),
74000c92694SGreg Roach            'INDI:SLGC'                  => new LdsChildSealing(I18N::translate('LDS child sealing')),
74100c92694SGreg Roach            'INDI:SLGC:DATE'             => new DateLdsOrd(I18N::translate('Date of LDS child sealing')),
74200c92694SGreg Roach            'INDI:SLGC:FAMC'             => new XrefFamily(I18N::translate('Parents')),
74300c92694SGreg Roach            'INDI:SLGC:PLAC'             => new PlaceLivingOrdinance(I18N::translate('Place of LDS child sealing')),
74400c92694SGreg Roach            'INDI:SLGC:STAT'             => new LdsChildSealingDateStatus(I18N::translate('Status')),
745099c152eSGreg Roach            'INDI:SLGC:STAT:DATE'        => new DateValueExact(I18N::translate('Status change date')),
74600c92694SGreg Roach            'INDI:SLGC:TEMP'             => new TempleCode(I18N::translate('Temple')),
74700c92694SGreg Roach            'INDI:SOUR'                  => new XrefSource(I18N::translate('Source citation')),
74800c92694SGreg Roach            'INDI:SOUR:DATA'             => new SourceData(I18N::translate('Data')),
749352bd396SGreg Roach            'INDI:SOUR:DATA:DATE'        => new DateValue(I18N::translate('Date of entry in original source')),
75000c92694SGreg Roach            'INDI:SOUR:DATA:TEXT'        => new TextFromSource(I18N::translate('Text')),
75100c92694SGreg Roach            'INDI:SOUR:EVEN'             => new EventTypeCitedFrom(I18N::translate('Event')),
75200c92694SGreg Roach            'INDI:SOUR:EVEN:ROLE'        => new RoleInEvent(I18N::translate('Role')),
753d64c51bcSGreg Roach            'INDI:SOUR:NOTE'             => new NoteStructure(I18N::translate('Note on source citation')),
75400c92694SGreg Roach            'INDI:SOUR:OBJE'             => new XrefMedia(I18N::translate('Media object')),
75500c92694SGreg Roach            'INDI:SOUR:PAGE'             => new WhereWithinSource(I18N::translate('Citation details')),
75600c92694SGreg Roach            'INDI:SOUR:QUAY'             => new CertaintyAssessment(I18N::translate('Quality of data')),
75700c92694SGreg Roach            'INDI:SSN'                   => new SocialSecurityNumber(I18N::translate('Social security number')),
75800c92694SGreg Roach            'INDI:SUBM'                  => new XrefSubmitter(I18N::translate('Submitter')),
75900c92694SGreg Roach            'INDI:TITL'                  => new NobilityTypeTitle(I18N::translate('Title')),
76000c92694SGreg Roach            'INDI:WILL'                  => new Will(I18N::translate('Will')),
76100c92694SGreg Roach            'NOTE'                       => new NoteRecord(I18N::translate('Shared note')),
76200c92694SGreg Roach            'NOTE:CHAN'                  => new Change(I18N::translate('Last change')),
76300c92694SGreg Roach            'NOTE:CHAN:DATE'             => new ChangeDate(I18N::translate('Date of last change')),
764099c152eSGreg Roach            'NOTE:CHAN:DATE:TIME'        => new TimeValueNow(I18N::translate('Time of last change')),
765d64c51bcSGreg Roach            'NOTE:CHAN:NOTE'             => new NoteStructure(I18N::translate('Note on last change')),
76678c3bcf9SGreg Roach            'NOTE:CONC'                  => new SubmitterText(I18N::translate('Note')),
7676e233fa7SGreg Roach            'NOTE:CONT'                  => new SubmitterText(I18N::translate('Continuation')),
76800c92694SGreg Roach            'NOTE:REFN'                  => new UserReferenceNumber(I18N::translate('Reference number')),
76900c92694SGreg Roach            'NOTE:REFN:TYPE'             => new UserReferenceType(I18N::translate('Type of reference number')),
77000c92694SGreg Roach            'NOTE:RIN'                   => new AutomatedRecordId(I18N::translate('Record ID number')),
77100c92694SGreg Roach            'NOTE:SOUR'                  => new XrefSource(I18N::translate('Source citation')),
77200c92694SGreg Roach            'NOTE:SOUR:DATA'             => new SourceData(I18N::translate('Data')),
773352bd396SGreg Roach            'NOTE:SOUR:DATA:DATE'        => new DateValue(I18N::translate('Date of entry in original source')),
77400c92694SGreg Roach            'NOTE:SOUR:DATA:TEXT'        => new TextFromSource(I18N::translate('Text')),
77500c92694SGreg Roach            'NOTE:SOUR:EVEN'             => new EventTypeCitedFrom(I18N::translate('Event')),
77600c92694SGreg Roach            'NOTE:SOUR:EVEN:ROLE'        => new RoleInEvent(I18N::translate('Role')),
777d64c51bcSGreg Roach            'NOTE:SOUR:NOTE'             => new NoteStructure(I18N::translate('Note on source citation')),
77800c92694SGreg Roach            'NOTE:SOUR:OBJE'             => new XrefMedia(I18N::translate('Media object')),
77900c92694SGreg Roach            'NOTE:SOUR:PAGE'             => new WhereWithinSource(I18N::translate('Citation details')),
78000c92694SGreg Roach            'NOTE:SOUR:QUAY'             => new CertaintyAssessment(I18N::translate('Quality of data')),
78100c92694SGreg Roach            'OBJE'                       => new MediaRecord(I18N::translate('Media object')),
78200c92694SGreg Roach            'OBJE:BLOB'                  => new CustomElement(I18N::translate('Binary data object')),
78300c92694SGreg Roach            'OBJE:CHAN'                  => new Change(I18N::translate('Last change')),
78400c92694SGreg Roach            'OBJE:CHAN:DATE'             => new ChangeDate(I18N::translate('Date of last change')),
785099c152eSGreg Roach            'OBJE:CHAN:DATE:TIME'        => new TimeValueNow(I18N::translate('Time of last change')),
786d64c51bcSGreg Roach            'OBJE:CHAN:NOTE'             => new NoteStructure(I18N::translate('Note on last change')),
78700c92694SGreg Roach            'OBJE:FILE'                  => new MultimediaFileReference(I18N::translate('Filename')),
78800c92694SGreg Roach            'OBJE:FILE:FORM'             => new MultimediaFormat(I18N::translate('Format')),
78900c92694SGreg Roach            'OBJE:FILE:FORM:TYPE'        => new SourceMediaType(I18N::translate('Media type')),
79000c92694SGreg Roach            'OBJE:FILE:TITL'             => new DescriptiveTitle(I18N::translate('Title')),
79100c92694SGreg Roach            'OBJE:NOTE'                  => new NoteStructure(I18N::translate('Note')),
79200c92694SGreg Roach            'OBJE:REFN'                  => new UserReferenceNumber(I18N::translate('Reference number')),
79300c92694SGreg Roach            'OBJE:REFN:TYPE'             => new UserReferenceType(I18N::translate('Type of reference number')),
79400c92694SGreg Roach            'OBJE:RIN'                   => new AutomatedRecordId(I18N::translate('Record ID number')),
79500c92694SGreg Roach            'OBJE:SOUR'                  => new XrefSource(I18N::translate('Source citation')),
79600c92694SGreg Roach            'OBJE:SOUR:DATA'             => new SourceData(I18N::translate('Data')),
797352bd396SGreg Roach            'OBJE:SOUR:DATA:DATE'        => new DateValue(I18N::translate('Date of entry in original source')),
79800c92694SGreg Roach            'OBJE:SOUR:DATA:TEXT'        => new TextFromSource(I18N::translate('Text')),
79900c92694SGreg Roach            'OBJE:SOUR:EVEN'             => new EventTypeCitedFrom(I18N::translate('Event')),
80000c92694SGreg Roach            'OBJE:SOUR:EVEN:ROLE'        => new RoleInEvent(I18N::translate('Role')),
801d64c51bcSGreg Roach            'OBJE:SOUR:NOTE'             => new NoteStructure(I18N::translate('Note on source citation')),
80200c92694SGreg Roach            'OBJE:SOUR:OBJE'             => new XrefMedia(I18N::translate('Media object')),
80300c92694SGreg Roach            'OBJE:SOUR:PAGE'             => new WhereWithinSource(I18N::translate('Citation details')),
80400c92694SGreg Roach            'OBJE:SOUR:QUAY'             => new CertaintyAssessment(I18N::translate('Quality of data')),
80500c92694SGreg Roach            'REPO'                       => new RepositoryRecord(I18N::translate('Repository')),
80600c92694SGreg Roach            'REPO:ADDR'                  => new AddressLine(I18N::translate('Address')),
80700c92694SGreg Roach            'REPO:ADDR:ADR1'             => new AddressLine1(I18N::translate('Address line 1')),
80800c92694SGreg Roach            'REPO:ADDR:ADR2'             => new AddressLine2(I18N::translate('Address line 2')),
80900c92694SGreg Roach            'REPO:ADDR:ADR3'             => new AddressLine3(I18N::translate('Address line 3')),
81000c92694SGreg Roach            'REPO:ADDR:CITY'             => new AddressCity(I18N::translate('City')),
81100c92694SGreg Roach            'REPO:ADDR:CTRY'             => new AddressCountry(I18N::translate('Country')),
81200c92694SGreg Roach            'REPO:ADDR:POST'             => new AddressPostalCode(I18N::translate('Postal code')),
81300c92694SGreg Roach            'REPO:ADDR:STAE'             => new AddressState(I18N::translate('State')),
81400c92694SGreg Roach            'REPO:CHAN'                  => new Change(I18N::translate('Last change')),
81500c92694SGreg Roach            'REPO:CHAN:DATE'             => new ChangeDate(I18N::translate('Date of last change')),
816099c152eSGreg Roach            'REPO:CHAN:DATE:TIME'        => new TimeValueNow(I18N::translate('Time of last change')),
817d64c51bcSGreg Roach            'REPO:CHAN:NOTE'             => new NoteStructure(I18N::translate('Note on last change')),
81800c92694SGreg Roach            'REPO:EMAIL'                 => new AddressEmail(I18N::translate('Email address')),
81900c92694SGreg Roach            'REPO:FAX'                   => new AddressFax(I18N::translate('Fax')),
82000c92694SGreg Roach            'REPO:NAME'                  => new NameOfRepository(I18N::translateContext('Repository', 'Name')),
82100c92694SGreg Roach            'REPO:NOTE'                  => new NoteStructure(I18N::translate('Note')),
82200c92694SGreg Roach            'REPO:PHON'                  => new PhoneNumber(I18N::translate('Phone')),
82300c92694SGreg Roach            'REPO:REFN'                  => new UserReferenceNumber(I18N::translate('Reference number')),
82400c92694SGreg Roach            'REPO:REFN:TYPE'             => new UserReferenceType(I18N::translate('Type of reference number')),
82500c92694SGreg Roach            'REPO:RIN'                   => new AutomatedRecordId(I18N::translate('Record ID number')),
82600c92694SGreg Roach            'REPO:WWW'                   => new AddressWebPage(I18N::translate('URL')),
82700c92694SGreg Roach            'SOUR'                       => new SourceRecord(I18N::translate('Source')),
82800c92694SGreg Roach            'SOUR:ABBR'                  => new SourceFiledByEntry(I18N::translate('Abbreviation')),
82900c92694SGreg Roach            'SOUR:AUTH'                  => new SourceOriginator(I18N::translate('Author')),
83000c92694SGreg Roach            'SOUR:CHAN'                  => new Change(I18N::translate('Last change')),
83100c92694SGreg Roach            'SOUR:CHAN:DATE'             => new ChangeDate(I18N::translate('Date of last change')),
832099c152eSGreg Roach            'SOUR:CHAN:DATE:TIME'        => new TimeValueNow(I18N::translate('Time of last change')),
833d64c51bcSGreg Roach            'SOUR:CHAN:NOTE'             => new NoteStructure(I18N::translate('Note on last change')),
83400c92694SGreg Roach            'SOUR:DATA'                  => new EmptyElement(I18N::translate('Data'), ['EVEN' => '0:M', 'AGNC' => '0:1', 'NOTE' => '0:M']),
83500c92694SGreg Roach            'SOUR:DATA:AGNC'             => new ResponsibleAgency(I18N::translate('Agency')),
83600c92694SGreg Roach            'SOUR:DATA:EVEN'             => new EventsRecorded(I18N::translate('Events')),
83700c92694SGreg Roach            'SOUR:DATA:EVEN:DATE'        => new DateValue(I18N::translate('Date range')),
83800c92694SGreg Roach            'SOUR:DATA:EVEN:PLAC'        => new SourceJurisdictionPlace(I18N::translate('Place'), []),
839d64c51bcSGreg Roach            'SOUR:DATA:NOTE'             => new NoteStructure(I18N::translate('Note on source data')),
840d64c51bcSGreg Roach            'SOUR:NOTE'                  => new NoteStructure(I18N::translate('Note on source')),
84100c92694SGreg Roach            'SOUR:OBJE'                  => new XrefMedia(I18N::translate('Media object')),
84200c92694SGreg Roach            'SOUR:PUBL'                  => new SourcePublicationFacts(I18N::translate('Publication')),
84300c92694SGreg Roach            'SOUR:REFN'                  => new UserReferenceNumber(I18N::translate('Reference number')),
84400c92694SGreg Roach            'SOUR:REFN:TYPE'             => new UserReferenceType(I18N::translate('Type of reference number')),
84500c92694SGreg Roach            'SOUR:REPO'                  => new XrefRepository(I18N::translate('Repository')),
84600c92694SGreg Roach            'SOUR:REPO:CALN'             => new SourceCallNumber(I18N::translate('Call number')),
84700c92694SGreg Roach            'SOUR:REPO:CALN:MEDI'        => new SourceMediaType(I18N::translate('Media type')),
848d64c51bcSGreg Roach            'SOUR:REPO:NOTE'             => new NoteStructure(I18N::translate('Note on repository reference')),
84900c92694SGreg Roach            'SOUR:RIN'                   => new AutomatedRecordId(I18N::translate('Record ID number')),
85000c92694SGreg Roach            'SOUR:TEXT'                  => new TextFromSource(I18N::translate('Text')),
85100c92694SGreg Roach            'SOUR:TITL'                  => new DescriptiveTitle(I18N::translate('Title')),
85200c92694SGreg Roach            'SUBM'                       => new SubmitterRecord(I18N::translate('Submitter')),
85300c92694SGreg Roach            'SUBM:ADDR'                  => new AddressLine(I18N::translate('Address')),
85400c92694SGreg Roach            'SUBM:ADDR:ADR1'             => new AddressLine1(I18N::translate('Address line 1')),
85500c92694SGreg Roach            'SUBM:ADDR:ADR2'             => new AddressLine2(I18N::translate('Address line 2')),
85600c92694SGreg Roach            'SUBM:ADDR:ADR3'             => new AddressLine3(I18N::translate('Address line 3')),
85700c92694SGreg Roach            'SUBM:ADDR:CITY'             => new AddressCity(I18N::translate('City')),
85800c92694SGreg Roach            'SUBM:ADDR:CTRY'             => new AddressCountry(I18N::translate('Country')),
85900c92694SGreg Roach            'SUBM:ADDR:POST'             => new AddressPostalCode(I18N::translate('Postal code')),
86000c92694SGreg Roach            'SUBM:ADDR:STAE'             => new AddressState(I18N::translate('State')),
86100c92694SGreg Roach            'SUBM:CHAN'                  => new Change(I18N::translate('Last change')),
86200c92694SGreg Roach            'SUBM:CHAN:DATE'             => new ChangeDate(I18N::translate('Date of last change')),
863099c152eSGreg Roach            'SUBM:CHAN:DATE:TIME'        => new TimeValueNow(I18N::translate('Time of last change')),
864d64c51bcSGreg Roach            'SUBM:CHAN:NOTE'             => new NoteStructure(I18N::translate('Note on last change')),
86500c92694SGreg Roach            'SUBM:EMAIL'                 => new AddressEmail(I18N::translate('Email address')),
86600c92694SGreg Roach            'SUBM:FAX'                   => new AddressFax(I18N::translate('Fax')),
86700c92694SGreg Roach            'SUBM:LANG'                  => new LanguageId(I18N::translate('Language')),
86800c92694SGreg Roach            'SUBM:NAME'                  => new SubmitterName(I18N::translate('Name')),
86900c92694SGreg Roach            'SUBM:NOTE'                  => new NoteStructure(I18N::translate('Note')),
87000c92694SGreg Roach            'SUBM:OBJE'                  => new XrefMedia(I18N::translate('Media object')),
87100c92694SGreg Roach            'SUBM:PHON'                  => new PhoneNumber(I18N::translate('Phone')),
87200c92694SGreg Roach            'SUBM:RFN'                   => new SubmitterRegisteredRfn(I18N::translate('Record file number')),
87300c92694SGreg Roach            'SUBM:RIN'                   => new AutomatedRecordId(I18N::translate('Record ID number')),
87400c92694SGreg Roach            'SUBM:WWW'                   => new AddressWebPage(I18N::translate('URL')),
87500c92694SGreg Roach            'SUBN'                       => new SubmissionRecord(I18N::translate('Submission')),
87600c92694SGreg Roach            'SUBN:ANCE'                  => new GenerationsOfAncestors(I18N::translate('Generations of ancestors')),
87700c92694SGreg Roach            'SUBN:CHAN'                  => new Change(I18N::translate('Last change')),
87800c92694SGreg Roach            'SUBN:CHAN:DATE'             => new ChangeDate(I18N::translate('Date of last change')),
879099c152eSGreg Roach            'SUBN:CHAN:DATE:TIME'        => new TimeValueNow(I18N::translate('Time of last change')),
880d64c51bcSGreg Roach            'SUBN:CHAN:NOTE'             => new NoteStructure(I18N::translate('Note on last change')),
88100c92694SGreg Roach            'SUBN:DESC'                  => new GenerationsOfDescendants(I18N::translate('Generations of descendants')),
88200c92694SGreg Roach            'SUBN:FAMF'                  => new NameOfFamilyFile(I18N::translate('Family file')),
88300c92694SGreg Roach            'SUBN:NOTE'                  => new NoteStructure(I18N::translate('Note')),
88400c92694SGreg Roach            'SUBN:ORDI'                  => new OrdinanceProcessFlag(I18N::translate('Ordinance')),
88500c92694SGreg Roach            'SUBN:RIN'                   => new AutomatedRecordId(I18N::translate('Record ID number')),
88600c92694SGreg Roach            'SUBN:SUBM'                  => new XrefSubmitter(I18N::translate('Submitter')),
88700c92694SGreg Roach            'SUBN:TEMP'                  => new TempleCode(/* I18N: https://en.wikipedia.org/wiki/Temple_(LDS_Church)*/ I18N::translate('Temple')),
88800c92694SGreg Roach            'TRLR'                       => new EmptyElement(I18N::translate('Trailer')),
88900c92694SGreg Roach        ];
89000c92694SGreg Roach    }
89100c92694SGreg Roach
89200c92694SGreg Roach    /**
89300c92694SGreg Roach     * Custom tags for webtrees.
89400c92694SGreg Roach     *
89500c92694SGreg Roach     * @return array<string,ElementInterface>
89600c92694SGreg Roach     */
89700c92694SGreg Roach    private function webtreesTags(): array
89800c92694SGreg Roach    {
89900c92694SGreg Roach        return [
90000c92694SGreg Roach            'FAM:CHAN:_WT_USER'           => new WebtreesUser(I18N::translate('Author of last change')),
90100c92694SGreg Roach            'FAM:*:_ASSO'                 => new XrefAssociate(I18N::translate('Associate')),
902d64c51bcSGreg Roach            'FAM:*:_ASSO:NOTE'            => new NoteStructure(I18N::translate('Note on association')),
90300c92694SGreg Roach            'FAM:*:_ASSO:RELA'            => new RelationIsDescriptor(I18N::translate('Relationship')),
90400c92694SGreg Roach            'FAM:*:_ASSO:SOUR'            => new XrefSource(I18N::translate('Source citation')),
90500c92694SGreg Roach            'FAM:*:_ASSO:SOUR:DATA'       => new SourceData(I18N::translate('Data')),
906352bd396SGreg Roach            'FAM:*:_ASSO:SOUR:DATA:DATE'  => new DateValue(I18N::translate('Date of entry in original source')),
90700c92694SGreg Roach            'FAM:*:_ASSO:SOUR:DATA:TEXT'  => new TextFromSource(I18N::translate('Text')),
90800c92694SGreg Roach            'FAM:*:_ASSO:SOUR:EVEN'       => new EventTypeCitedFrom(I18N::translate('Event')),
90900c92694SGreg Roach            'FAM:*:_ASSO:SOUR:EVEN:ROLE'  => new RoleInEvent(I18N::translate('Role')),
910d64c51bcSGreg Roach            'FAM:*:_ASSO:SOUR:NOTE'       => new NoteStructure(I18N::translate('Note on source citation')),
91100c92694SGreg Roach            'FAM:*:_ASSO:SOUR:OBJE'       => new XrefMedia(I18N::translate('Media object')),
91200c92694SGreg Roach            'FAM:*:_ASSO:SOUR:PAGE'       => new WhereWithinSource(I18N::translate('Citation details')),
91300c92694SGreg Roach            'FAM:*:_ASSO:SOUR:QUAY'       => new CertaintyAssessment(I18N::translate('Quality of data')),
91400c92694SGreg Roach            'INDI:CHAN:_WT_USER'          => new WebtreesUser(I18N::translate('Author of last change')),
91500c92694SGreg Roach            'INDI:*:_ASSO'                => new XrefAssociate(I18N::translate('Associate')),
916d64c51bcSGreg Roach            'INDI:*:_ASSO:NOTE'           => new NoteStructure(I18N::translate('Note on association')),
91700c92694SGreg Roach            'INDI:*:_ASSO:RELA'           => new RelationIsDescriptor(I18N::translate('Relationship')),
91800c92694SGreg Roach            'INDI:*:_ASSO:SOUR'           => new XrefSource(I18N::translate('Source citation')),
91900c92694SGreg Roach            'INDI:*:_ASSO:SOUR:DATA'      => new SourceData(I18N::translate('Data')),
920352bd396SGreg Roach            'INDI:*:_ASSO:SOUR:DATA:DATE' => new DateValue(I18N::translate('Date of entry in original source')),
92100c92694SGreg Roach            'INDI:*:_ASSO:SOUR:DATA:TEXT' => new TextFromSource(I18N::translate('Text')),
92200c92694SGreg Roach            'INDI:*:_ASSO:SOUR:EVEN'      => new EventTypeCitedFrom(I18N::translate('Event')),
92300c92694SGreg Roach            'INDI:*:_ASSO:SOUR:EVEN:ROLE' => new RoleInEvent(I18N::translate('Role')),
924d64c51bcSGreg Roach            'INDI:*:_ASSO:SOUR:NOTE'      => new NoteStructure(I18N::translate('Note on source citation')),
92500c92694SGreg Roach            'INDI:*:_ASSO:SOUR:OBJE'      => new XrefMedia(I18N::translate('Media object')),
92600c92694SGreg Roach            'INDI:*:_ASSO:SOUR:PAGE'      => new WhereWithinSource(I18N::translate('Citation details')),
92700c92694SGreg Roach            'INDI:*:_ASSO:SOUR:QUAY'      => new CertaintyAssessment(I18N::translate('Quality of data')),
92800c92694SGreg Roach            'NOTE:CHAN:_WT_USER'          => new WebtreesUser(I18N::translate('Author of last change')),
92900c92694SGreg Roach            'NOTE:RESN'                   => new RestrictionNotice(I18N::translate('Restriction')),
93000c92694SGreg Roach            'OBJE:CHAN:_WT_USER'          => new WebtreesUser(I18N::translate('Author of last change')),
93100c92694SGreg Roach            'OBJE:RESN'                   => new RestrictionNotice(I18N::translate('Restriction')),
93200c92694SGreg Roach            'REPO:CHAN:_WT_USER'          => new WebtreesUser(I18N::translate('Author of last change')),
93300c92694SGreg Roach            'REPO:RESN'                   => new RestrictionNotice(I18N::translate('Restriction')),
93400c92694SGreg Roach            'SOUR:CHAN:_WT_USER'          => new WebtreesUser(I18N::translate('Author of last change')),
93500c92694SGreg Roach            'SOUR:RESN'                   => new RestrictionNotice(I18N::translate('Restriction')),
93600c92694SGreg Roach            'SUBM:CHAN:_WT_USER'          => new WebtreesUser(I18N::translate('Author of last change')),
93700c92694SGreg Roach            'SUBM:RESN'                   => new RestrictionNotice(I18N::translate('Restriction')),
93800c92694SGreg Roach            '_LOC:CHAN:_WT_USER'          => new WebtreesUser(I18N::translate('Author of last change')),
93900c92694SGreg Roach            '_LOC:RESN'                   => new RestrictionNotice(I18N::translate('Restriction')),
94000c92694SGreg Roach        ];
94100c92694SGreg Roach    }
94200c92694SGreg Roach
94300c92694SGreg Roach    /**
94400c92694SGreg Roach     * @return array<string,array<int,array<int,string>>>
94500c92694SGreg Roach     */
94600c92694SGreg Roach    private function webtreesSubTags(): array
94700c92694SGreg Roach    {
94800c92694SGreg Roach        return [
94900c92694SGreg Roach            'FAM'              => [['_UID', '0:M']],
95000c92694SGreg Roach            'FAM:*:SOUR:DATA'  => [['TEXT', '0:1']],
95100c92694SGreg Roach            'FAM:ANUL'         => [['_ASSO', '0:M', 'NOTE']],
95200c92694SGreg Roach            'FAM:CENS'         => [['_ASSO', '0:M', 'NOTE']],
95300c92694SGreg Roach            'FAM:CHAN'         => [['_WT_USER', '0:1']],
95400c92694SGreg Roach            'FAM:DIV'          => [['_ASSO', '0:M', 'NOTE']],
95500c92694SGreg Roach            'FAM:DIVF'         => [['_ASSO', '0:M', 'NOTE']],
95600c92694SGreg Roach            'FAM:ENGA'         => [['_ASSO', '0:M', 'NOTE']],
95700c92694SGreg Roach            'FAM:EVEN'         => [['_ASSO', '0:M', 'NOTE']],
95800c92694SGreg Roach            'FAM:MARB'         => [['_ASSO', '0:M', 'NOTE']],
95900c92694SGreg Roach            'FAM:MARC'         => [['_ASSO', '0:M', 'NOTE']],
96000c92694SGreg Roach            'FAM:MARL'         => [['_ASSO', '0:M', 'NOTE']],
96100c92694SGreg Roach            'FAM:MARR'         => [['_ASSO', '2:M', 'NOTE']],
96200c92694SGreg Roach            'FAM:MARS'         => [['_ASSO', '0:M', 'NOTE']],
96300c92694SGreg Roach            'FAM:SLGS'         => [['_ASSO', '0:M', 'NOTE']],
96400c92694SGreg Roach            'FAM:SOUR:DATA'    => [['TEXT', '0:1']],
96500c92694SGreg Roach            'INDI'             => [['_UID', '0:M']],
96600c92694SGreg Roach            'INDI:*:SOUR:DATA' => [['TEXT', '0:1']],
96700c92694SGreg Roach            'INDI:ADOP'        => [['_ASSO', '0:M', 'NOTE']],
96800c92694SGreg Roach            'INDI:BAPL'        => [['_ASSO', '0:M', 'NOTE']],
96900c92694SGreg Roach            'INDI:BAPM'        => [['_ASSO', '2:M', 'NOTE']],
97000c92694SGreg Roach            'INDI:BARM'        => [['_ASSO', '0:M', 'NOTE']],
97100c92694SGreg Roach            'INDI:BASM'        => [['_ASSO', '0:M', 'NOTE']],
97200c92694SGreg Roach            'INDI:BIRT'        => [['_ASSO', '0:M', 'NOTE'], ['FAMC', '0:0']],
97300c92694SGreg Roach            'INDI:BURI'        => [['_ASSO', '0:M', 'NOTE']],
97400c92694SGreg Roach            'INDI:CENS'        => [['_ASSO', '0:M', 'NOTE']],
97500c92694SGreg Roach            'INDI:CHAN'        => [['_WT_USER', '0:1']],
97600c92694SGreg Roach            'INDI:CHR'         => [['_ASSO', '2:M', 'NOTE']],
97700c92694SGreg Roach            'INDI:CHRA'        => [['_ASSO', '0:M', 'NOTE']],
97800c92694SGreg Roach            'INDI:CONF'        => [['_ASSO', '0:M', 'NOTE']],
97900c92694SGreg Roach            'INDI:CONL'        => [['_ASSO', '0:M', 'NOTE']],
98000c92694SGreg Roach            'INDI:CREM'        => [['_ASSO', '0:M', 'NOTE']],
98100c92694SGreg Roach            'INDI:DEAT'        => [['_ASSO', '0:M', 'NOTE']],
98200c92694SGreg Roach            'INDI:EDUC'        => [['_ASSO', '0:M', 'NOTE']],
98300c92694SGreg Roach            'INDI:EMIG'        => [['_ASSO', '0:M', 'NOTE']],
98400c92694SGreg Roach            'INDI:ENDL'        => [['_ASSO', '0:M', 'NOTE']],
98500c92694SGreg Roach            'INDI:EVEN'        => [['_ASSO', '0:M', 'NOTE']],
98600c92694SGreg Roach            'INDI:GRAD'        => [['_ASSO', '0:M', 'NOTE']],
98700c92694SGreg Roach            'INDI:IMMI'        => [['_ASSO', '0:M', 'NOTE']],
98800c92694SGreg Roach            'INDI:NATU'        => [['_ASSO', '0:M', 'NOTE']],
98900c92694SGreg Roach            'INDI:OCCU'        => [['_ASSO', '0:M', 'NOTE']],
99000c92694SGreg Roach            'INDI:ORDN'        => [['_ASSO', '0:M', 'NOTE']],
99100c92694SGreg Roach            'INDI:PROB'        => [['_ASSO', '0:M', 'NOTE']],
99200c92694SGreg Roach            'INDI:PROP'        => [['_ASSO', '0:M', 'NOTE']],
99300c92694SGreg Roach            'INDI:RESI'        => [['_ASSO', '0:M', 'NOTE']],
99400c92694SGreg Roach            'INDI:RETI'        => [['_ASSO', '0:M', 'NOTE']],
99500c92694SGreg Roach            'INDI:SLGC'        => [['_ASSO', '0:M', 'NOTE']],
99600c92694SGreg Roach            'INDI:SOUR:DATA'   => [['TEXT', '0:1']],
99700c92694SGreg Roach            'INDI:TITL'        => [['_ASSO', '0:M', 'NOTE']],
99800c92694SGreg Roach            'INDI:WILL'        => [['_ASSO', '0:M', 'NOTE']],
99900c92694SGreg Roach            'NOTE'             => [['RESN', '0:1', 'CHAN']],
100000c92694SGreg Roach            'NOTE:CHAN'        => [['_WT_USER', '0:1']],
100100c92694SGreg Roach            'NOTE:SOUR:DATA'   => [['TEXT', '0:1']],
100200c92694SGreg Roach            'OBJE'             => [['RESN', '0:1', 'CHAN'], ['_UID', '0:M']],
100300c92694SGreg Roach            'OBJE:CHAN'        => [['_WT_USER', '0:1']],
100400c92694SGreg Roach            'OBJE:SOUR:DATA'   => [['TEXT', '0:1']],
100500c92694SGreg Roach            'REPO'             => [['RESN', '0:1', 'CHAN'], ['_UID', '0:M']],
100600c92694SGreg Roach            'REPO:CHAN'        => [['_WT_USER', '0:1']],
100700c92694SGreg Roach            'SOUR'             => [['RESN', '0:1', 'CHAN'], ['_UID', '0:M']],
100800c92694SGreg Roach            'SOUR:CHAN'        => [['_WT_USER', '0:1']],
100900c92694SGreg Roach            'SUBM'             => [['RESN', '0:1', 'CHAN']],
101000c92694SGreg Roach            'SUBM:CHAN'        => [['_WT_USER', '0:1']],
101100c92694SGreg Roach        ];
101200c92694SGreg Roach    }
101300c92694SGreg Roach
101400c92694SGreg Roach    /**
101500c92694SGreg Roach     * @return array<string,array<int,array<int,string>>>
101600c92694SGreg Roach     */
101700c92694SGreg Roach    private function customSubTags(): array
101800c92694SGreg Roach    {
101900c92694SGreg Roach        $custom_family_tags     = array_filter(explode(',', Site::getPreference('CUSTOM_FAMILY_TAGS')));
102000c92694SGreg Roach        $custom_individual_tags = array_filter(explode(',', Site::getPreference('CUSTOM_INDIVIDUAL_TAGS')));
102100c92694SGreg Roach
102200c92694SGreg Roach        $subtags = [
102300c92694SGreg Roach            'FAM'  => array_map(static fn (string $tag): array => [$tag, '0:M'], $custom_family_tags),
102400c92694SGreg Roach            'INDI' => array_map(static fn (string $tag): array => [$tag, '0:M'], $custom_individual_tags),
102500c92694SGreg Roach        ];
102600c92694SGreg Roach
1027f9340759SGreg Roach        // GEDCOM 7 tags
1028f9340759SGreg Roach        if (Site::getPreference('CUSTOM_FAM_FACT') === '1') {
1029f9340759SGreg Roach            $subtags['FAM'][] = ['FACT', '0:M'];
1030f9340759SGreg Roach        }
1031f9340759SGreg Roach        if (Site::getPreference('CUSTOM_FAM_NCHI') === '1') {
1032f9340759SGreg Roach            $subtags['FAM:NCHI'] = [
1033f9340759SGreg Roach                ['TYPE', '0:1:?'],
1034f9340759SGreg Roach                ['DATE', '0:1'],
1035f9340759SGreg Roach                ['PLAC', '0:1:?'],
1036f9340759SGreg Roach                ['ADDR', '0:1:?'],
1037f9340759SGreg Roach                ['EMAIL', '0:1:?'],
1038f9340759SGreg Roach                ['WWW', '0:1:?'],
1039f9340759SGreg Roach                ['PHON', '0:1:?'],
1040f9340759SGreg Roach                ['FAX', '0:1:?'],
1041f9340759SGreg Roach                ['CAUS', '0:1:?'],
1042f9340759SGreg Roach                ['AGNC', '0:1:?'],
1043f9340759SGreg Roach                ['RELI', '0:1:?'],
1044f9340759SGreg Roach                ['NOTE', '0:M'],
1045f9340759SGreg Roach                ['OBJE', '0:M'],
1046f9340759SGreg Roach                ['SOUR', '0:M'],
1047f9340759SGreg Roach                ['RESN', '0:1'],
1048f9340759SGreg Roach            ];
1049f9340759SGreg Roach        }
10503b2b4f4aSGreg Roach
1051d4193d5fSGreg Roach        if (Site::getPreference('CUSTOM_TIME_TAGS') === '1') {
1052d4193d5fSGreg Roach            $subtags['INDI:BIRT:DATE'][] = ['TIME', '0:1'];
1053d4193d5fSGreg Roach            $subtags['INDI:DEAT:DATE'][] = ['TIME', '0:1'];
1054d4193d5fSGreg Roach        }
1055d4193d5fSGreg Roach
105600c92694SGreg Roach        if (Site::getPreference('CUSTOM_GEDCOM_L_TAGS') === '1') {
105700c92694SGreg Roach            $subtags['FAM'][]               = ['_ASSO', '0:M'];
105800c92694SGreg Roach            $subtags['FAM'][]               = ['_STAT', '0:1'];
105900c92694SGreg Roach            $subtags['FAM'][]               = ['_UID', '0:M'];
1060f91876f3SGreg Roach            $subtags['FAM:*:ADDR']          = [['_NAME', '0:1:?', 'ADR1']];
1061f02df124SGreg Roach            $subtags['FAM:*:PLAC']          = [['_POST', '0:1'], ['_MAIDENHEAD', '0:1:?'], ['_LOC', '0:1'], ['_GOV', '0:1']];
1062f02df124SGreg Roach            $subtags['FAM:ENGA:PLAC']       = [['_POST', '0:1'], ['_MAIDENHEAD', '0:1:?'], ['_LOC', '0:1'], ['_GOV', '0:1']];
1063f02df124SGreg Roach            $subtags['FAM:MARB:PLAC']       = [['_POST', '0:1'], ['_MAIDENHEAD', '0:1:?'], ['_LOC', '0:1'], ['_GOV', '0:1']];
10641c2da29dSRichard Cissée            $subtags['FAM:MARR']            = [['_WITN', '0:1']];
1065f02df124SGreg Roach            $subtags['FAM:MARR:PLAC']       = [['_POST', '0:1'], ['_MAIDENHEAD', '0:1:?'], ['_LOC', '0:1'], ['_GOV', '0:1']];
1066f02df124SGreg Roach            $subtags['FAM:SLGS:PLAC']       = [['_POST', '0:1'], ['_MAIDENHEAD', '0:1:?'], ['_LOC', '0:1'], ['_GOV', '0:1']];
106700c92694SGreg Roach            $subtags['INDI'][]              = ['_UID', '0:M'];
1068f91876f3SGreg Roach            $subtags['INDI:*:ADDR']         = [['_NAME', '0:1:?', 'ADR1']];
1069f02df124SGreg Roach            $subtags['INDI:*:PLAC']         = [['_POST', '0:1'], ['_MAIDENHEAD', '0:1:?'], ['_LOC', '0:1'], ['_GOV', '0:1']];
1070f02df124SGreg Roach            $subtags['INDI:ADOP:PLAC']      = [['_POST', '0:1'], ['_MAIDENHEAD', '0:1:?'], ['_LOC', '0:1'], ['_GOV', '0:1']];
1071f02df124SGreg Roach            $subtags['INDI:BAPL:PLAC']      = [['_POST', '0:1'], ['_MAIDENHEAD', '0:1:?'], ['_LOC', '0:1'], ['_GOV', '0:1']];
10721c2da29dSRichard Cissée            $subtags['INDI:BAPM']           = [['_GODP', '0:1'], ['_WITN', '0:1']];
1073f02df124SGreg Roach            $subtags['INDI:BAPM:PLAC']      = [['_POST', '0:1'], ['_MAIDENHEAD', '0:1:?'], ['_LOC', '0:1'], ['_GOV', '0:1']];
1074f02df124SGreg Roach            $subtags['INDI:BARM:PLAC']      = [['_POST', '0:1'], ['_MAIDENHEAD', '0:1:?'], ['_LOC', '0:1'], ['_GOV', '0:1']];
1075f02df124SGreg Roach            $subtags['INDI:BASM:PLAC']      = [['_POST', '0:1'], ['_MAIDENHEAD', '0:1:?'], ['_LOC', '0:1'], ['_GOV', '0:1']];
1076f02df124SGreg Roach            $subtags['INDI:BIRT:PLAC']      = [['_POST', '0:1'], ['_MAIDENHEAD', '0:1:?'], ['_LOC', '0:1'], ['_GOV', '0:1']];
1077f02df124SGreg Roach            $subtags['INDI:BLES:PLAC']      = [['_POST', '0:1'], ['_MAIDENHEAD', '0:1:?'], ['_LOC', '0:1'], ['_GOV', '0:1']];
1078f02df124SGreg Roach            $subtags['INDI:BURI:PLAC']      = [['_POST', '0:1'], ['_MAIDENHEAD', '0:1:?'], ['_LOC', '0:1'], ['_GOV', '0:1']];
1079f02df124SGreg Roach            $subtags['INDI:CENS:PLAC']      = [['_POST', '0:1'], ['_MAIDENHEAD', '0:1:?'], ['_LOC', '0:1'], ['_GOV', '0:1']];
10801c2da29dSRichard Cissée            $subtags['INDI:CHR']            = [['_GODP', '0:1'], ['_WITN', '0:1']];
1081f02df124SGreg Roach            $subtags['INDI:CHR:PLAC']       = [['_POST', '0:1'], ['_MAIDENHEAD', '0:1:?'], ['_LOC', '0:1'], ['_GOV', '0:1']];
1082f02df124SGreg Roach            $subtags['INDI:CHRA:PLAC']      = [['_POST', '0:1'], ['_MAIDENHEAD', '0:1:?'], ['_LOC', '0:1'], ['_GOV', '0:1']];
1083f02df124SGreg Roach            $subtags['INDI:CONF:PLAC']      = [['_POST', '0:1'], ['_MAIDENHEAD', '0:1:?'], ['_LOC', '0:1'], ['_GOV', '0:1']];
1084f02df124SGreg Roach            $subtags['INDI:CONL:PLAC']      = [['_POST', '0:1'], ['_MAIDENHEAD', '0:1:?'], ['_LOC', '0:1'], ['_GOV', '0:1']];
1085f02df124SGreg Roach            $subtags['INDI:CREM:PLAC']      = [['_POST', '0:1'], ['_MAIDENHEAD', '0:1:?'], ['_LOC', '0:1'], ['_GOV', '0:1']];
1086f02df124SGreg Roach            $subtags['INDI:DEAT:PLAC']      = [['_POST', '0:1'], ['_MAIDENHEAD', '0:1:?'], ['_LOC', '0:1'], ['_GOV', '0:1']];
1087f02df124SGreg Roach            $subtags['INDI:EMIG:PLAC']      = [['_POST', '0:1'], ['_MAIDENHEAD', '0:1:?'], ['_LOC', '0:1'], ['_GOV', '0:1']];
1088f02df124SGreg Roach            $subtags['INDI:ENDL:PLAC']      = [['_POST', '0:1'], ['_MAIDENHEAD', '0:1:?'], ['_LOC', '0:1'], ['_GOV', '0:1']];
1089f02df124SGreg Roach            $subtags['INDI:EVEN:PLAC']      = [['_POST', '0:1'], ['_MAIDENHEAD', '0:1:?'], ['_LOC', '0:1'], ['_GOV', '0:1']];
1090f02df124SGreg Roach            $subtags['INDI:FCOM:PLAC']      = [['_POST', '0:1'], ['_MAIDENHEAD', '0:1:?'], ['_LOC', '0:1'], ['_GOV', '0:1']];
1091f02df124SGreg Roach            $subtags['INDI:IMMI:PLAC']      = [['_POST', '0:1'], ['_MAIDENHEAD', '0:1:?'], ['_LOC', '0:1'], ['_GOV', '0:1']];
109278fee3e8SGreg Roach            $subtags['INDI:NAME']           = [['_RUFNAME', '0:1', 'SPFX']];
1093f02df124SGreg Roach            $subtags['INDI:NATU:PLAC']      = [['_POST', '0:1'], ['_MAIDENHEAD', '0:1:?'], ['_LOC', '0:1'], ['_GOV', '0:1']];
1094f02df124SGreg Roach            $subtags['INDI:ORDN:PLAC']      = [['_POST', '0:1'], ['_MAIDENHEAD', '0:1:?'], ['_LOC', '0:1'], ['_GOV', '0:1']];
1095f02df124SGreg Roach            $subtags['INDI:RESI:PLAC']      = [['_POST', '0:1'], ['_MAIDENHEAD', '0:1:?'], ['_LOC', '0:1'], ['_GOV', '0:1']];
1096f02df124SGreg Roach            $subtags['INDI:SLGC:PLAC']      = [['_POST', '0:1'], ['_MAIDENHEAD', '0:1:?'], ['_LOC', '0:1'], ['_GOV', '0:1']];
109700c92694SGreg Roach            $subtags['NOTE']                = [['_UID', '0:M']];
109800c92694SGreg Roach            $subtags['OBJE']                = [['_PRIM', '0:1:?'], ['_UID', '0:M']];
109900c92694SGreg Roach            $subtags['REPO']                = [['_UID', '0:M']];
110000c92694SGreg Roach            $subtags['REPO:ADDR']           = [['_NAME', '0:1', 'ADR1']];
110100c92694SGreg Roach            $subtags['SOUR']                = [['_UID', '0:M']];
1102f02df124SGreg Roach            $subtags['SOUR:DATA:EVEN:PLAC'] = [['_POST', '0:1'], ['_MAIDENHEAD', '0:1:?'], ['_LOC', '0:1'], ['_GOV', '0:1']];
110300c92694SGreg Roach            $subtags['SUBM']                = [['_UID', '0:M']];
110400c92694SGreg Roach            $subtags['SUBM:ADDR']           = [['_NAME', '0:1', 'ADR1']];
110500c92694SGreg Roach        }
110600c92694SGreg Roach
110700c92694SGreg Roach        return $subtags;
110800c92694SGreg Roach    }
110900c92694SGreg Roach
11109e97502fSGreg Roach    /**
11119e97502fSGreg Roach     * @param ElementFactoryInterface $element_factory
11129e97502fSGreg Roach     * @param bool                    $include_custom_tags
11139e97502fSGreg Roach     *
11149e97502fSGreg Roach     * @return void
11159e97502fSGreg Roach     */
1116e669bb4bSGreg Roach    public function registerTags(ElementFactoryInterface $element_factory, bool $include_custom_tags): void
111700c92694SGreg Roach    {
111800c92694SGreg Roach        // Standard GEDCOM.
1119e669bb4bSGreg Roach        $element_factory->registerTags($this->gedcom551Tags());
112000c92694SGreg Roach
112100c92694SGreg Roach        // webtrees extensions.
1122e669bb4bSGreg Roach        $element_factory->registerTags($this->webtreesTags());
1123e669bb4bSGreg Roach
1124e669bb4bSGreg Roach        if ($include_custom_tags) {
1125e669bb4bSGreg Roach            // webtrees extensions.
1126e669bb4bSGreg Roach            $element_factory->registerSubTags($this->webtreesSubTags());
112700c92694SGreg Roach
1128864236f5SGreg Roach            $custom_tags = [
1129864236f5SGreg Roach                new Aldfaer(),
1130864236f5SGreg Roach                new Ancestry(),
1131864236f5SGreg Roach                new BrothersKeeper(),
1132864236f5SGreg Roach                new FamilySearch(),
1133864236f5SGreg Roach                new FamilyTreeBuilder(),
1134864236f5SGreg Roach                new FamilyTreeMaker(),
1135864236f5SGreg Roach                new Gedcom7(),
1136864236f5SGreg Roach                new GedcomL(),
1137864236f5SGreg Roach                new Geneatique(),
1138864236f5SGreg Roach                new GenPlusWin(),
1139864236f5SGreg Roach                new Heredis(),
1140864236f5SGreg Roach                new Legacy(),
1141864236f5SGreg Roach                new MyHeritage(),
1142864236f5SGreg Roach                new PersonalAncestralFile(),
1143864236f5SGreg Roach                new PhpGedView(),
1144864236f5SGreg Roach                new ProGen(),
1145864236f5SGreg Roach                new Reunion(),
1146864236f5SGreg Roach                new RootsMagic(),
1147*1b85c7f5SGreg Roach                new TheMasterGenealogist(),
1148*1b85c7f5SGreg Roach                new TheNextGeneration(),
1149864236f5SGreg Roach            ];
1150864236f5SGreg Roach
1151864236f5SGreg Roach            foreach ($custom_tags as $custom_tag) {
1152864236f5SGreg Roach                $element_factory->registerTags($custom_tag->tags());
1153864236f5SGreg Roach            }
115400c92694SGreg Roach
115500c92694SGreg Roach            // Creating tags from all the above are grouped into one place
1156e669bb4bSGreg Roach            $element_factory->registerSubTags($this->customSubTags());
1157e669bb4bSGreg Roach        }
115800c92694SGreg Roach    }
11590f471f91SGreg Roach}
1160