. */ declare(strict_types=1); namespace Fisharebest\Webtrees\Factories; use Fisharebest\Webtrees\Contracts\ElementFactoryInterface; use Fisharebest\Webtrees\Contracts\ElementInterface; use Fisharebest\Webtrees\Elements\UnknownElement; use function preg_match; /** * Make a GEDCOM element. */ class ElementFactory implements ElementFactoryInterface { /** @var array */ private array $elements = []; /** * Create a GEDCOM element that corresponds to a GEDCOM tag. * Finds the correct element for all valid tags. * Finds a likely element for custom tags. * * @param string $tag - Colon delimited hierarchy, e.g. 'INDI:BIRT:PLAC' * * @return ElementInterface */ public function make(string $tag): ElementInterface { return $this->elements[$tag] ?? $this->findElementByWildcard($tag) ?? new UnknownElement($tag); } /** * Register GEDCOM tags. * * @param array $elements */ public function registerTags(array $elements): void { $this->elements = $elements + $this->elements; } /** * Register more subtags. * * @param array>> $subtags */ public function registerSubTags(array $subtags): void { foreach ($subtags as $tag => $children) { foreach ($children as $child) { $this->make($tag)->subtag(...$child); } } } /** * @param string $tag * * @return ElementInterface|null */ private function findElementByWildcard(string $tag): ?ElementInterface { foreach ($this->elements as $tags => $element) { if (str_contains($tags, '*')) { $regex = '/^' . strtr($tags, ['*' => '[^:]+']) . '$/'; if (preg_match($regex, $tag)) { return $element; } } } return null; } }