xref: /webtrees/app/Factories/ElementFactory.php (revision 00c92694dd3637f3b741bcc2df92d58d9df74043)
1c2ed51d1SGreg Roach<?php
2c2ed51d1SGreg Roach
3c2ed51d1SGreg Roach/**
4c2ed51d1SGreg Roach * webtrees: online genealogy
55bfc6897SGreg Roach * Copyright (C) 2022 webtrees development team
6c2ed51d1SGreg Roach * This program is free software: you can redistribute it and/or modify
7c2ed51d1SGreg Roach * it under the terms of the GNU General Public License as published by
8c2ed51d1SGreg Roach * the Free Software Foundation, either version 3 of the License, or
9c2ed51d1SGreg Roach * (at your option) any later version.
10c2ed51d1SGreg Roach * This program is distributed in the hope that it will be useful,
11c2ed51d1SGreg Roach * but WITHOUT ANY WARRANTY; without even the implied warranty of
12c2ed51d1SGreg Roach * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13c2ed51d1SGreg Roach * GNU General Public License for more details.
14c2ed51d1SGreg Roach * You should have received a copy of the GNU General Public License
15c2ed51d1SGreg Roach * along with this program. If not, see <https://www.gnu.org/licenses/>.
16c2ed51d1SGreg Roach */
17c2ed51d1SGreg Roach
18c2ed51d1SGreg Roachdeclare(strict_types=1);
19c2ed51d1SGreg Roach
20c2ed51d1SGreg Roachnamespace Fisharebest\Webtrees\Factories;
21c2ed51d1SGreg Roach
22c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Contracts\ElementFactoryInterface;
23c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Contracts\ElementInterface;
24c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\AddressCity;
25c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\AddressCountry;
26c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\AddressEmail;
27c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\AddressFax;
28c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\AddressLine;
29c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\AddressLine1;
30c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\AddressLine2;
31c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\AddressLine3;
32c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\AddressPostalCode;
33c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\AddressState;
34c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\AddressWebPage;
35c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\AdoptedByWhichParent;
36c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\Adoption;
37c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\AdultChristening;
38c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\AgeAtEvent;
39c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\AncestralFileNumber;
40c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\Annulment;
41c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\ApprovedSystemId;
42c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\AutomatedRecordId;
43c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\Baptism;
443eb619d2SGreg Roachuse Fisharebest\Webtrees\Elements\BarMitzvah;
45c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\BasMitzvah;
46c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\Birth;
47c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\Blessing;
48c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\Burial;
49c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\CasteName;
50c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\CauseOfEvent;
51c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\Census;
52c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\CertaintyAssessment;
53c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\Change;
54c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\ChangeDate;
55c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\CharacterSet;
56c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\ChildLinkageStatus;
57c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\Christening;
58c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\Confirmation;
59c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\ContentDescription;
60241d59e1SGreg Roachuse Fisharebest\Webtrees\Elements\Coordinates;
61c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\CopyrightFile;
62c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\CopyrightSourceData;
63c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\CountOfChildren;
64c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\CountOfMarriages;
65c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\Cremation;
668c21658eSGreg Roachuse Fisharebest\Webtrees\Elements\CustomElement;
67*00c92694SGreg Roachuse Fisharebest\Webtrees\Elements\CustomEvent;
6878fa3281SGreg Roachuse Fisharebest\Webtrees\Elements\CustomFact;
694c93bfa7SGreg Roachuse Fisharebest\Webtrees\Elements\CustomFamilyEvent;
704c93bfa7SGreg Roachuse Fisharebest\Webtrees\Elements\CustomIndividualEvent;
71c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\DateLdsOrd;
72c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\DateValue;
73c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\Death;
74c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\DescriptiveTitle;
75c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\Divorce;
76c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\DivorceFiled;
77c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\Emigration;
78c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\EmptyElement;
79c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\Engagement;
80c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\EntryRecordingDate;
81c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\EventAttributeType;
82c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\EventOrFactClassification;
83c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\EventsRecorded;
84c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\EventTypeCitedFrom;
8582e500efSGreg Roachuse Fisharebest\Webtrees\Elements\FamilyCensus;
86e7e5b015SGreg Roachuse Fisharebest\Webtrees\Elements\FamilyRecord;
87a6081838SGreg Roachuse Fisharebest\Webtrees\Elements\FamilyResidence;
88*00c92694SGreg Roachuse Fisharebest\Webtrees\Elements\FamilySearchFamilyTreeId;
89*00c92694SGreg Roachuse Fisharebest\Webtrees\Elements\FamilyStatusText;
90c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\FileName;
91c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\FirstCommunion;
92c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\Form;
9390288370SGreg Roachuse Fisharebest\Webtrees\Elements\GedcomElement;
94c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\GenerationsOfAncestors;
95c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\GenerationsOfDescendants;
96*00c92694SGreg Roachuse Fisharebest\Webtrees\Elements\GovIdentifier;
97c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\Graduation;
98e7e5b015SGreg Roachuse Fisharebest\Webtrees\Elements\HeaderRecord;
99*00c92694SGreg Roachuse Fisharebest\Webtrees\Elements\HierarchicalRelationship;
100c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\Immigration;
101e7e5b015SGreg Roachuse Fisharebest\Webtrees\Elements\IndividualRecord;
102c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\LanguageId;
103c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\LdsBaptism;
104c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\LdsBaptismDateStatus;
105c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\LdsChildSealing;
106c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\LdsChildSealingDateStatus;
107c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\LdsConfirmation;
108c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\LdsEndowment;
109c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\LdsEndowmentDateStatus;
110c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\LdsSpouseSealing;
111c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\LdsSpouseSealingDateStatus;
112*00c92694SGreg Roachuse Fisharebest\Webtrees\Elements\LocationRecord;
113*00c92694SGreg Roachuse Fisharebest\Webtrees\Elements\MaidenheadLocator;
114c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\Marriage;
115c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\MarriageBanns;
116c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\MarriageContract;
117c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\MarriageLicence;
118c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\MarriageSettlement;
119c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\MarriageType;
120c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\MediaRecord;
121c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\MultimediaFileReference;
122c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\MultimediaFormat;
123c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\NameOfBusiness;
124c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\NameOfFamilyFile;
125c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\NameOfProduct;
126c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\NameOfRepository;
127c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\NameOfSourceData;
128c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\NamePersonal;
129c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\NamePhoneticVariation;
130c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\NamePieceGiven;
131c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\NamePieceNickname;
132c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\NamePiecePrefix;
133c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\NamePieceSuffix;
134c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\NamePieceSurname;
135c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\NamePieceSurnamePrefix;
136c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\NameRomanizedVariation;
137c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\NameType;
138c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\NationalIdNumber;
139c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\NationOrTribalOrigin;
140c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\Naturalization;
141c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\NobilityTypeTitle;
142c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\NoteRecord;
143c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\NoteStructure;
144c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\Occupation;
145c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\OrdinanceProcessFlag;
146c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\Ordination;
147*00c92694SGreg Roachuse Fisharebest\Webtrees\Elements\PafUid;
148c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\PedigreeLinkageType;
149c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\PermanentRecordFileNumber;
150c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\PhoneNumber;
151c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\PhoneticType;
152c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\PhysicalDescription;
153c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\PlaceHierarchy;
154c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\PlaceLatitude;
155c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\PlaceLivingOrdinance;
156c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\PlaceLongtitude;
157c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\PlaceName;
158c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\PlacePhoneticVariation;
159c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\PlaceRomanizedVariation;
160c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\Possessions;
161c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\Probate;
162c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\PublicationDate;
163c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\ReceivingSystemName;
164c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\RelationIsDescriptor;
165c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\ReligiousAffiliation;
166c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\RepositoryRecord;
167*00c92694SGreg Roachuse Fisharebest\Webtrees\Elements\ResearchTask;
168*00c92694SGreg Roachuse Fisharebest\Webtrees\Elements\ResearchTaskPriority;
169*00c92694SGreg Roachuse Fisharebest\Webtrees\Elements\ResearchTaskStatus;
170*00c92694SGreg Roachuse Fisharebest\Webtrees\Elements\ResearchTaskType;
171c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\Residence;
172c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\ResponsibleAgency;
173c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\RestrictionNotice;
174c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\Retirement;
175c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\RoleInEvent;
176c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\RomanizedType;
177c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\ScholasticAchievement;
178c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\SexValue;
179*00c92694SGreg Roachuse Fisharebest\Webtrees\Elements\SexXValue;
180c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\SocialSecurityNumber;
181c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\SourceCallNumber;
182c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\SourceData;
183c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\SourceFiledByEntry;
184c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\SourceJurisdictionPlace;
185c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\SourceMediaType;
186c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\SourceOriginator;
187c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\SourcePublicationFacts;
188c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\SourceRecord;
189c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\SubmissionRecord;
190c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\SubmitterName;
191c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\SubmitterRecord;
192c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\SubmitterRegisteredRfn;
193c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\SubmitterText;
194c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\TempleCode;
195c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\TextFromSource;
196c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\TimeValue;
197c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\TransmissionDate;
198c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\UnknownElement;
199c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\UserReferenceNumber;
200c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\UserReferenceType;
201c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\VersionNumber;
202*00c92694SGreg Roachuse Fisharebest\Webtrees\Elements\WebtreesUser;
203c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\WhereWithinSource;
204c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\Will;
2057b542389SGreg Roachuse Fisharebest\Webtrees\Elements\XrefAssociate;
206c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\XrefFamily;
207c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\XrefIndividual;
208*00c92694SGreg Roachuse Fisharebest\Webtrees\Elements\XrefLocation;
209c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\XrefMedia;
210c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\XrefRepository;
211c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\XrefSource;
212c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\XrefSubmission;
213c2ed51d1SGreg Roachuse Fisharebest\Webtrees\Elements\XrefSubmitter;
214c2ed51d1SGreg Roachuse Fisharebest\Webtrees\I18N;
215472ace44SGreg Roach
216dc6af6c2SGreg Roachuse function array_merge;
217c2ed51d1SGreg Roachuse function preg_match;
218*00c92694SGreg Roachuse function var_dump;
219c2ed51d1SGreg Roach
220c2ed51d1SGreg Roach/**
221c2ed51d1SGreg Roach * Make a GEDCOM element.
222c2ed51d1SGreg Roach */
223c2ed51d1SGreg Roachclass ElementFactory implements ElementFactoryInterface
224c2ed51d1SGreg Roach{
2253d2c98d1SGreg Roach    /** @var array<string,ElementInterface> */
2264dbb2a39SGreg Roach    private array $elements = [];
227c2ed51d1SGreg Roach
228c2ed51d1SGreg Roach    /**
229c2ed51d1SGreg Roach     * Create a GEDCOM element that corresponds to a GEDCOM tag.
230c2ed51d1SGreg Roach     * Finds the correct element for all valid tags.
231c2ed51d1SGreg Roach     * Finds a likely element for custom tags.
232c2ed51d1SGreg Roach     *
233c2ed51d1SGreg Roach     * @param string $tag - Colon delimited hierarchy, e.g. 'INDI:BIRT:PLAC'
234c2ed51d1SGreg Roach     *
235c2ed51d1SGreg Roach     * @return ElementInterface
236c2ed51d1SGreg Roach     */
237c2ed51d1SGreg Roach    public function make(string $tag): ElementInterface
238c2ed51d1SGreg Roach    {
239*00c92694SGreg Roach        return $this->elements[$tag] ?? $this->findElementByWildcard($tag) ?? new UnknownElement($tag);
240c2ed51d1SGreg Roach    }
241c2ed51d1SGreg Roach
242c2ed51d1SGreg Roach    /**
243*00c92694SGreg Roach     * Register GEDCOM tags.
2444ab8e344SGreg Roach     *
2454ab8e344SGreg Roach     * @param array<string,ElementInterface> $elements
2464ab8e344SGreg Roach     */
247*00c92694SGreg Roach    public function registerTags(array $elements): void
2484ab8e344SGreg Roach    {
249*00c92694SGreg Roach        $this->elements = $elements + $this->elements;
250*00c92694SGreg Roach    }
251*00c92694SGreg Roach
252*00c92694SGreg Roach    /**
253*00c92694SGreg Roach     * Register more subtags.
254*00c92694SGreg Roach     *
255*00c92694SGreg Roach     * @param array<string,array<int,array<int,string>>> $subtags
256*00c92694SGreg Roach     */
257*00c92694SGreg Roach    public function registerSubTags(array $subtags): void
258*00c92694SGreg Roach    {
259*00c92694SGreg Roach        foreach ($subtags as $tag => $children) {
260*00c92694SGreg Roach            foreach ($children as $child) {
261*00c92694SGreg Roach                $this->make($tag)->subtag(...$child);
262*00c92694SGreg Roach            }
263*00c92694SGreg Roach        }
2644ab8e344SGreg Roach    }
2654ab8e344SGreg Roach
2664ab8e344SGreg Roach    /**
2674ab8e344SGreg Roach     * @param string $tag
2684ab8e344SGreg Roach     *
2694ab8e344SGreg Roach     * @return ElementInterface|null
2704ab8e344SGreg Roach     */
2714ab8e344SGreg Roach    private function findElementByWildcard(string $tag): ?ElementInterface
2724ab8e344SGreg Roach    {
273*00c92694SGreg Roach        foreach ($this->elements as $tags => $element) {
274c5b48766SGreg Roach            if (str_contains($tags, '*')) {
2754ab8e344SGreg Roach                $regex = '/^' . strtr($tags, ['*' => '[^:]+']) . '$/';
2764ab8e344SGreg Roach
2774ab8e344SGreg Roach                if (preg_match($regex, $tag)) {
2784ab8e344SGreg Roach                    return $element;
2794ab8e344SGreg Roach                }
2804ab8e344SGreg Roach            }
2814ab8e344SGreg Roach        }
2824ab8e344SGreg Roach
2834ab8e344SGreg Roach        return null;
2844ab8e344SGreg Roach    }
285c2ed51d1SGreg Roach}
286