xref: /webtrees/app/Factories/ElementFactory.php (revision 1ff45046fabc22237b5d0d8e489c96f031fc598d)
1c2ed51d1SGreg Roach<?php
2c2ed51d1SGreg Roach
3c2ed51d1SGreg Roach/**
4c2ed51d1SGreg Roach * webtrees: online genealogy
5d11be702SGreg Roach * Copyright (C) 2023 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\UnknownElement;
25472ace44SGreg Roach
26c2ed51d1SGreg Roachuse function preg_match;
27c2ed51d1SGreg Roach
28c2ed51d1SGreg Roach/**
29c2ed51d1SGreg Roach * Make a GEDCOM element.
30c2ed51d1SGreg Roach */
31c2ed51d1SGreg Roachclass ElementFactory implements ElementFactoryInterface
32c2ed51d1SGreg Roach{
333d2c98d1SGreg Roach    /** @var array<string,ElementInterface> */
344dbb2a39SGreg Roach    private array $elements = [];
35c2ed51d1SGreg Roach
36c2ed51d1SGreg Roach    /**
37c2ed51d1SGreg Roach     * Create a GEDCOM element that corresponds to a GEDCOM tag.
38c2ed51d1SGreg Roach     * Finds the correct element for all valid tags.
39c2ed51d1SGreg Roach     * Finds a likely element for custom tags.
40c2ed51d1SGreg Roach     *
41e5766395SGreg Roach     * @param string $tag Colon delimited hierarchy, e.g. 'INDI:BIRT:PLAC'
42c2ed51d1SGreg Roach     *
43c2ed51d1SGreg Roach     * @return ElementInterface
44c2ed51d1SGreg Roach     */
45c2ed51d1SGreg Roach    public function make(string $tag): ElementInterface
46c2ed51d1SGreg Roach    {
4700c92694SGreg Roach        return $this->elements[$tag] ?? $this->findElementByWildcard($tag) ?? new UnknownElement($tag);
48c2ed51d1SGreg Roach    }
49c2ed51d1SGreg Roach
50c2ed51d1SGreg Roach    /**
5100c92694SGreg Roach     * Register GEDCOM tags.
524ab8e344SGreg Roach     *
534ab8e344SGreg Roach     * @param array<string,ElementInterface> $elements
544ab8e344SGreg Roach     */
5500c92694SGreg Roach    public function registerTags(array $elements): void
564ab8e344SGreg Roach    {
5700c92694SGreg Roach        $this->elements = $elements + $this->elements;
5800c92694SGreg Roach    }
5900c92694SGreg Roach
6000c92694SGreg Roach    /**
6100c92694SGreg Roach     * Register more subtags.
6200c92694SGreg Roach     *
6300c92694SGreg Roach     * @param array<string,array<int,array<int,string>>> $subtags
6400c92694SGreg Roach     */
6500c92694SGreg Roach    public function registerSubTags(array $subtags): void
6600c92694SGreg Roach    {
6700c92694SGreg Roach        foreach ($subtags as $tag => $children) {
6800c92694SGreg Roach            foreach ($children as $child) {
6900c92694SGreg Roach                $this->make($tag)->subtag(...$child);
7000c92694SGreg Roach            }
7100c92694SGreg Roach        }
724ab8e344SGreg Roach    }
734ab8e344SGreg Roach
74*1ff45046SGreg Roach    private function findElementByWildcard(string $tag): ElementInterface|null
754ab8e344SGreg Roach    {
7600c92694SGreg Roach        foreach ($this->elements as $tags => $element) {
77c5b48766SGreg Roach            if (str_contains($tags, '*')) {
784ab8e344SGreg Roach                $regex = '/^' . strtr($tags, ['*' => '[^:]+']) . '$/';
794ab8e344SGreg Roach
804ab8e344SGreg Roach                if (preg_match($regex, $tag)) {
814ab8e344SGreg Roach                    return $element;
824ab8e344SGreg Roach                }
834ab8e344SGreg Roach            }
844ab8e344SGreg Roach        }
854ab8e344SGreg Roach
864ab8e344SGreg Roach        return null;
874ab8e344SGreg Roach    }
88c2ed51d1SGreg Roach}
89