xref: /webtrees/app/SurnameTradition/DefaultSurnameTradition.php (revision 93a49342332e33b457b78292c20c2dd1fd4d7303)
1<?php
2
3/**
4 * webtrees: online genealogy
5 * Copyright (C) 2022 webtrees development team
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <https://www.gnu.org/licenses/>.
16 */
17
18declare(strict_types=1);
19
20namespace Fisharebest\Webtrees\SurnameTradition;
21
22use Fisharebest\Webtrees\Elements\NameType;
23use Fisharebest\Webtrees\Fact;
24use Fisharebest\Webtrees\Individual;
25
26use function array_filter;
27use function array_keys;
28use function array_map;
29use function implode;
30use function in_array;
31
32/**
33 * All family members keep their original surname
34 */
35class DefaultSurnameTradition implements SurnameTraditionInterface
36{
37    /** Extract a GIVN from a NAME */
38    protected const REGEX_GIVN = '~^(?<GIVN>[^/ ]+)~';
39
40    /** Extract a SPFX and SURN from a NAME */
41    protected const REGEX_SPFX_SURN = '~(?<NAME>/(?<SPFX>[a-z’\']{0,4}(?: [a-z’\']{1,4})*) ?(?<SURN>[^/]*)/)~';
42
43    /** Extract a simple SURN from a NAME */
44    protected const REGEX_SURN = '~(?<NAME>/(?<SURN>[^/]+)/)~';
45
46    /** Extract two Spanish/Portuguese SURNs from a NAME */
47    protected const REGEX_SURNS = '~/(?<SURN1>[^ /]+)(?: | y |/ /|/ y /)(?<SURN2>[^ /]+)/~';
48
49    /**
50     * A default/empty name
51     *
52     * @return string
53     */
54    public function defaultName(): string
55    {
56        return '//';
57    }
58
59    /**
60     * What name is given to a new child
61     *
62     * @param Individual|null $father
63     * @param Individual|null $mother
64     * @param string          $sex
65     *
66     * @return array<int,string>
67     */
68    public function newChildNames(?Individual $father, ?Individual $mother, string $sex): array
69    {
70        return [
71            $this->buildName('//', ['TYPE' => NameType::TYPE_BIRTH]),
72        ];
73    }
74
75    /**
76     * What name is given to a new parent
77     *
78     * @param Individual $child
79     * @param string     $sex
80     *
81     * @return array<int,string>
82     */
83    public function newParentNames(Individual $child, string $sex): array
84    {
85        return [
86            $this->buildName('//', ['TYPE' => NameType::TYPE_BIRTH]),
87        ];
88    }
89
90    /**
91     * What names are given to a new spouse
92     *
93     * @param Individual $spouse
94     * @param string     $sex
95     *
96     * @return array<int,string>
97     */
98    public function newSpouseNames(Individual $spouse, string $sex): array
99    {
100        return [
101            $this->buildName('//', ['TYPE' => NameType::TYPE_BIRTH]),
102        ];
103    }
104
105    /**
106     * Build a GEDCOM name record
107     *
108     * @param string               $name
109     * @param array<string,string> $parts
110     *
111     * @return string
112     */
113    protected function buildName(string $name, array $parts): string
114    {
115        $parts = array_filter($parts);
116
117        $parts = array_map(
118            static fn (string $tag, string $value): string => "\n2 " . $tag . ' ' . $value,
119            array_keys($parts),
120            $parts
121        );
122
123        if ($name === '') {
124            return '1 NAME' . implode($parts);
125        }
126
127        return '1 NAME ' . $name . implode($parts);
128    }
129
130    /**
131     * Extract an individual's name.
132     *
133     * @param Individual|null $individual
134     *
135     * @return string
136     */
137    protected function extractName(?Individual $individual): string
138    {
139        if ($individual instanceof Individual) {
140            $fact = $individual
141                ->facts(['NAME'])
142                ->first(fn (Fact $fact): bool => in_array($fact->attribute('TYPE'), ['', NameType::TYPE_BIRTH, NameType::TYPE_CHANGE], true));
143
144            if ($fact instanceof Fact) {
145                return $fact->value();
146            }
147        }
148
149        return '';
150    }
151}
152