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::VALUE_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::VALUE_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::VALUE_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::VALUE_BIRTH, NameType::VALUE_CHANGE], true)); 143 144 if ($fact instanceof Fact) { 145 return $fact->value(); 146 } 147 } 148 149 return ''; 150 } 151} 152