xref: /webtrees/app/Census/AbstractCensusColumn.php (revision 49f828d09aa0a49d064593c8626c56c5dc5354ac)
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    public function father(Individual $individual): Individual|null
69    {
70        $family = $individual->childFamilies()->first();
71
72        if ($family instanceof Family) {
73            return $family->husband();
74        }
75
76        return null;
77    }
78
79    /**
80     * Find the mother of an individual
81     */
82    public function mother(Individual $individual): Individual|null
83    {
84        $family = $individual->childFamilies()->first();
85
86        if ($family instanceof Family) {
87            return $family->wife();
88        }
89
90        return null;
91    }
92
93    /**
94     * Find the current spouse family of an individual
95     */
96    public function spouseFamily(Individual $individual): Family|null
97    {
98        return $individual->spouseFamilies()
99                // Exclude families that were created after this census date
100            ->filter(fn (Family $family): bool => Date::compare($family->getMarriageDate(), $this->date()) <= 0)
101            ->sort(Family::marriageDateComparator())
102            ->last();
103    }
104
105    /**
106     * What was an individual's likely name on a given date, allowing
107     * for marriages and married names.
108     *
109     * @return array<string>
110     */
111    protected function nameAtCensusDate(Individual $individual): array
112    {
113        $names  = $individual->getAllNames();
114        $name   = $names[0];
115        $family = $this->spouseFamily($individual);
116
117        if ($family instanceof Family) {
118            $spouse = $family->spouse($individual);
119
120            if ($spouse instanceof Individual) {
121                foreach ($family->facts(['MARR']) as $marriage) {
122                    if ($marriage->date()->isOK()) {
123                        foreach ($names as $individual_name) {
124                            foreach ($spouse->getAllNames() as $spouse_name) {
125                                if ($individual_name['type'] === '_MARNM' && $individual_name['surn'] === $spouse_name['surn']) {
126                                    return $individual_name;
127                                }
128                            }
129                        }
130                    }
131                }
132            }
133        }
134
135        return $name;
136    }
137
138    /**
139     * When did this census occur
140     */
141    public function date(): Date
142    {
143        return new Date($this->census->censusDate());
144    }
145
146    /**
147     * The full version of the column's name.
148     *
149     * @return string
150     */
151    public function title(): string
152    {
153        return $this->title;
154    }
155
156    /**
157     * Extract the country (last part) of a place name.
158     *
159     * @param string $place e.g. "London, England"
160     *
161     * @return string e.g. "England"
162     */
163    protected function lastPartOfPlace(string $place): string
164    {
165        $parts = explode(', ', $place);
166
167        return end($parts);
168    }
169
170    /**
171     * Remove the country of a place name, where it is the same as the census place
172     *
173     * @param string $place e.g. "London, England"
174     *
175     * @return string e.g. "London" (for census of England) and "London, England" elsewhere
176     */
177    protected function notCountry(string $place): string
178    {
179        $parts = explode(', ', $place);
180
181        if (end($parts) === $this->place()) {
182            return implode(', ', array_slice($parts, 0, -1));
183        }
184
185        return $place;
186    }
187
188    /**
189     * Where did this census occur
190     *
191     * @return string
192     */
193    public function place(): string
194    {
195        return $this->census->censusPlace();
196    }
197}
198