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