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 static 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