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