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|null $father, Individual|null $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|null $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