xref: /webtrees/app/SurnameTradition/DefaultSurnameTradition.php (revision 8d018ab2fe3b6881cab8124d97e1a69e0be79d32)
1<?php
2
3/**
4 * webtrees: online genealogy
5 * Copyright (C) 2023 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\I18N;
25use Fisharebest\Webtrees\Individual;
26
27use function array_filter;
28use function array_keys;
29use function array_map;
30use function implode;
31use function in_array;
32
33/**
34 * All family members keep their original surname
35 */
36class DefaultSurnameTradition implements SurnameTraditionInterface
37{
38    /** Extract a GIVN from a NAME */
39    protected const REGEX_GIVN = '~^(?<GIVN>[^/ ]+)~';
40
41    /** Extract a SPFX and SURN from a NAME */
42    protected const REGEX_SPFX_SURN = '~(?<NAME>/(?<SPFX>[a-z’\']{0,4}(?: [a-z’\']{1,4})*) ?(?<SURN>[^/]*)/)~';
43
44    /** Extract a simple SURN from a NAME */
45    protected const REGEX_SURN = '~(?<NAME>/(?<SURN>[^/]+)/)~';
46
47    /** Extract two Spanish/Portuguese SURNs from a NAME */
48    protected const REGEX_SURNS = '~/(?<SURN1>[^ /]+)(?: | y |/ /|/ y /)(?<SURN2>[^ /]+)/~';
49
50    /**
51     * The name of this surname tradition
52     *
53     * @return string
54     */
55    public function name(): string
56    {
57        return I18N::translateContext('Surname tradition', 'none');
58    }
59
60    /**
61     * A short description of this surname tradition
62     *
63     * @return string
64     */
65    public function description(): string
66    {
67        return '';
68    }
69
70    /**
71     * A default/empty name
72     *
73     * @return string
74     */
75    public function defaultName(): string
76    {
77        return '//';
78    }
79
80    /**
81     * What name is given to a new child
82     *
83     * @param Individual|null $father
84     * @param Individual|null $mother
85     * @param string          $sex
86     *
87     * @return array<int,string>
88     */
89    public function newChildNames(?Individual $father, ?Individual $mother, string $sex): array
90    {
91        return [
92            $this->buildName('//', ['TYPE' => NameType::VALUE_BIRTH]),
93        ];
94    }
95
96    /**
97     * What name is given to a new parent
98     *
99     * @param Individual $child
100     * @param string     $sex
101     *
102     * @return array<int,string>
103     */
104    public function newParentNames(Individual $child, string $sex): array
105    {
106        return [
107            $this->buildName('//', ['TYPE' => NameType::VALUE_BIRTH]),
108        ];
109    }
110
111    /**
112     * What names are given to a new spouse
113     *
114     * @param Individual $spouse
115     * @param string     $sex
116     *
117     * @return array<int,string>
118     */
119    public function newSpouseNames(Individual $spouse, string $sex): array
120    {
121        return [
122            $this->buildName('//', ['TYPE' => NameType::VALUE_BIRTH]),
123        ];
124    }
125
126    /**
127     * Build a GEDCOM name record
128     *
129     * @param string               $name
130     * @param array<string,string> $parts
131     *
132     * @return string
133     */
134    protected function buildName(string $name, array $parts): string
135    {
136        $parts = array_filter($parts);
137
138        $parts = array_map(
139            static fn (string $tag, string $value): string => "\n2 " . $tag . ' ' . $value,
140            array_keys($parts),
141            $parts
142        );
143
144        if ($name === '') {
145            return '1 NAME' . implode($parts);
146        }
147
148        return '1 NAME ' . $name . implode($parts);
149    }
150
151    /**
152     * Extract an individual's name.
153     *
154     * @param Individual|null $individual
155     *
156     * @return string
157     */
158    protected function extractName(?Individual $individual): string
159    {
160        if ($individual instanceof Individual) {
161            $fact = $individual
162                ->facts(['NAME'])
163                ->first(fn (Fact $fact): bool => in_array($fact->attribute('TYPE'), ['', NameType::VALUE_BIRTH, NameType::VALUE_CHANGE], true));
164
165            if ($fact instanceof Fact) {
166                return $fact->value();
167            }
168        }
169
170        return '';
171    }
172}
173