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\Census; 21 22use Fisharebest\Webtrees\Date; 23use Fisharebest\Webtrees\Family; 24use Fisharebest\Webtrees\Individual; 25 26use function array_slice; 27use function explode; 28use function implode; 29 30/** 31 * Definitions for a census column 32 */ 33class AbstractCensusColumn 34{ 35 private CensusInterface $census; 36 37 private string $abbr; 38 39 private string $title; 40 41 /** 42 * Create a column for a census 43 * 44 * @param CensusInterface $census The census to which this column forms part. 45 * @param string $abbr The abbreviated on-screen name "BiC" 46 * @param string $title The full column heading "Born in the county" 47 */ 48 public function __construct(CensusInterface $census, string $abbr, string $title) 49 { 50 $this->census = $census; 51 $this->abbr = $abbr; 52 $this->title = $title; 53 } 54 55 /** 56 * A short version of the column's name. 57 * 58 * @return string 59 */ 60 public function abbreviation(): string 61 { 62 return $this->abbr; 63 } 64 65 /** 66 * Find the father of an individual 67 * 68 * @param Individual $individual 69 * 70 * @return Individual|null 71 */ 72 public function father(Individual $individual): ?Individual 73 { 74 $family = $individual->childFamilies()->first(); 75 76 if ($family instanceof Family) { 77 return $family->husband(); 78 } 79 80 return null; 81 } 82 83 /** 84 * Find the mother of an individual 85 * 86 * @param Individual $individual 87 * 88 * @return Individual|null 89 */ 90 public function mother(Individual $individual): ?Individual 91 { 92 $family = $individual->childFamilies()->first(); 93 94 if ($family instanceof Family) { 95 return $family->wife(); 96 } 97 98 return null; 99 } 100 101 /** 102 * Find the current spouse family of an individual 103 * 104 * @param Individual $individual 105 * 106 * @return Family|null 107 */ 108 public function spouseFamily(Individual $individual): ?Family 109 { 110 return $individual->spouseFamilies() 111 // Exclude families that were created after this census date 112 ->filter(fn(Family $family): bool => Date::compare($family->getMarriageDate(), $this->date()) <= 0) 113 ->sort(Family::marriageDateComparator()) 114 ->last(); 115 } 116 117 /** 118 * What was an individual's likely name on a given date, allowing 119 * for marriages and married names. 120 * 121 * @param Individual $individual 122 * 123 * @return array<string> 124 */ 125 protected function nameAtCensusDate(Individual $individual): array 126 { 127 $names = $individual->getAllNames(); 128 $name = $names[0]; 129 $family = $this->spouseFamily($individual); 130 131 if ($family instanceof Family) { 132 $spouse = $family->spouse($individual); 133 134 if ($spouse instanceof Individual) { 135 foreach ($family->facts(['MARR']) as $marriage) { 136 if ($marriage->date()->isOK()) { 137 foreach ($names as $individual_name) { 138 foreach ($spouse->getAllNames() as $spouse_name) { 139 if ($individual_name['type'] === '_MARNM' && $individual_name['surn'] === $spouse_name['surn']) { 140 return $individual_name; 141 } 142 } 143 } 144 } 145 } 146 } 147 } 148 149 return $name; 150 } 151 152 /** 153 * When did this census occur 154 * 155 * @return Date 156 */ 157 public function date(): Date 158 { 159 return new Date($this->census->censusDate()); 160 } 161 162 /** 163 * The full version of the column's name. 164 * 165 * @return string 166 */ 167 public function title(): string 168 { 169 return $this->title; 170 } 171 172 /** 173 * Extract the country (last part) of a place name. 174 * 175 * @param string $place e.g. "London, England" 176 * 177 * @return string e.g. "England" 178 */ 179 protected function lastPartOfPlace(string $place): string 180 { 181 $parts = explode(', ', $place); 182 183 return end($parts); 184 } 185 186 /** 187 * Remove the country of a place name, where it is the same as the census place 188 * 189 * @param string $place e.g. "London, England" 190 * 191 * @return string e.g. "London" (for census of England) and "London, England" elsewhere 192 */ 193 protected function notCountry(string $place): string 194 { 195 $parts = explode(', ', $place); 196 197 if (end($parts) === $this->place()) { 198 return implode(', ', array_slice($parts, 0, -1)); 199 } 200 201 return $place; 202 } 203 204 /** 205 * Where did this census occur 206 * 207 * @return string 208 */ 209 public function place(): string 210 { 211 return $this->census->censusPlace(); 212 } 213} 214