Total Complexity | 106 |
Total Lines | 928 |
Duplicated Lines | 0 % |
Changes | 0 |
Complex classes like IndividualFactsTabModule often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use IndividualFactsTabModule, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
37 | class IndividualFactsTabModule extends AbstractModule implements ModuleTabInterface |
||
38 | { |
||
39 | use ModuleTabTrait; |
||
40 | |||
41 | /** @var ModuleService */ |
||
42 | private $module_service; |
||
43 | |||
44 | /** @var ClipboardService */ |
||
45 | private $clipboard_service; |
||
46 | |||
47 | /** |
||
48 | * IndividualFactsTabModule constructor. |
||
49 | * |
||
50 | * @param ModuleService $module_service |
||
51 | * @param ClipboardService $clipboard_service |
||
52 | */ |
||
53 | public function __construct(ModuleService $module_service, ClipboardService $clipboard_service) |
||
54 | { |
||
55 | $this->module_service = $module_service; |
||
56 | $this->clipboard_service = $clipboard_service; |
||
57 | } |
||
58 | |||
59 | /** |
||
60 | * How should this module be identified in the control panel, etc.? |
||
61 | * |
||
62 | * @return string |
||
63 | */ |
||
64 | public function title(): string |
||
65 | { |
||
66 | /* I18N: Name of a module/tab on the individual page. */ |
||
67 | return I18N::translate('Facts and events'); |
||
68 | } |
||
69 | |||
70 | /** |
||
71 | * A sentence describing what this module does. |
||
72 | * |
||
73 | * @return string |
||
74 | */ |
||
75 | public function description(): string |
||
76 | { |
||
77 | /* I18N: Description of the “Facts and events” module */ |
||
78 | return I18N::translate('A tab showing the facts and events of an individual.'); |
||
79 | } |
||
80 | |||
81 | /** |
||
82 | * The default position for this tab. It can be changed in the control panel. |
||
83 | * |
||
84 | * @return int |
||
85 | */ |
||
86 | public function defaultTabOrder(): int |
||
87 | { |
||
88 | return 1; |
||
89 | } |
||
90 | |||
91 | /** |
||
92 | * A greyed out tab has no actual content, but may perhaps have |
||
93 | * options to create content. |
||
94 | * |
||
95 | * @param Individual $individual |
||
96 | * |
||
97 | * @return bool |
||
98 | */ |
||
99 | public function isGrayedOut(Individual $individual): bool |
||
100 | { |
||
101 | return false; |
||
102 | } |
||
103 | |||
104 | /** |
||
105 | * Generate the HTML content of this tab. |
||
106 | * |
||
107 | * @param Individual $individual |
||
108 | * |
||
109 | * @return string |
||
110 | */ |
||
111 | public function getTabContent(Individual $individual): string |
||
112 | { |
||
113 | // Only include events of close relatives that are between birth and death |
||
114 | $min_date = $individual->getEstimatedBirthDate(); |
||
115 | $max_date = $individual->getEstimatedDeathDate(); |
||
116 | |||
117 | // Which facts and events are handled by other modules? |
||
118 | $sidebar_facts = $this->module_service |
||
119 | ->findByComponent(ModuleSidebarInterface::class, $individual->tree(), Auth::user()) |
||
120 | ->map(static function (ModuleSidebarInterface $sidebar): Collection { |
||
121 | return $sidebar->supportedFacts(); |
||
122 | }); |
||
123 | |||
124 | $tab_facts = $this->module_service |
||
125 | ->findByComponent(ModuleTabInterface::class, $individual->tree(), Auth::user()) |
||
126 | ->map(static function (ModuleTabInterface $sidebar): Collection { |
||
127 | return $sidebar->supportedFacts(); |
||
128 | }); |
||
129 | |||
130 | $exclude_facts = $sidebar_facts->merge($tab_facts)->flatten(); |
||
131 | |||
132 | // The individual’s own facts |
||
133 | $indifacts = $individual->facts() |
||
134 | ->filter(static function (Fact $fact) use ($exclude_facts): bool { |
||
135 | return !$exclude_facts->contains($fact->getTag()); |
||
|
|||
136 | }); |
||
137 | |||
138 | // Add spouse-family facts |
||
139 | foreach ($individual->spouseFamilies() as $family) { |
||
140 | foreach ($family->facts() as $fact) { |
||
141 | if (!$exclude_facts->contains($fact->getTag()) && $fact->getTag() !== 'CHAN') { |
||
142 | $indifacts->push($fact); |
||
143 | } |
||
144 | } |
||
145 | |||
146 | $spouse = $family->spouse($individual); |
||
147 | |||
148 | if ($spouse instanceof Individual) { |
||
149 | $spouse_facts = $this->spouseFacts($individual, $spouse, $min_date, $max_date); |
||
150 | $indifacts = $indifacts->merge($spouse_facts); |
||
151 | } |
||
152 | |||
153 | $child_facts = $this->childFacts($individual, $family, '_CHIL', '', $min_date, $max_date); |
||
154 | $indifacts = $indifacts->merge($child_facts); |
||
155 | } |
||
156 | |||
157 | $parent_facts = $this->parentFacts($individual, 1, $min_date, $max_date); |
||
158 | $associate_facts = $this->associateFacts($individual); |
||
159 | $historical_facts = $this->historicalFacts($individual); |
||
160 | |||
161 | $indifacts = $indifacts |
||
162 | ->merge($parent_facts) |
||
163 | ->merge($associate_facts) |
||
164 | ->merge($historical_facts); |
||
165 | |||
166 | $indifacts = Fact::sortFacts($indifacts); |
||
167 | |||
168 | return view('modules/personal_facts/tab', [ |
||
169 | 'can_edit' => $individual->canEdit(), |
||
170 | 'clipboard_facts' => $this->clipboard_service->pastableFacts($individual, new Collection()), |
||
171 | 'has_historical_facts' => $historical_facts !== [], |
||
172 | 'individual' => $individual, |
||
173 | 'facts' => $indifacts, |
||
174 | ]); |
||
175 | } |
||
176 | |||
177 | /** |
||
178 | * Does a relative event occur within a date range (i.e. the individual's lifetime)? |
||
179 | * |
||
180 | * @param Fact $fact |
||
181 | * @param Date $min_date |
||
182 | * @param Date $max_date |
||
183 | * |
||
184 | * @return bool |
||
185 | */ |
||
186 | private function includeFact(Fact $fact, Date $min_date, Date $max_date): bool |
||
191 | } |
||
192 | |||
193 | /** |
||
194 | * Is this tab empty? If so, we don't always need to display it. |
||
195 | * |
||
196 | * @param Individual $individual |
||
197 | * |
||
198 | * @return bool |
||
199 | */ |
||
200 | public function hasTabContent(Individual $individual): bool |
||
203 | } |
||
204 | |||
205 | /** |
||
206 | * Can this tab load asynchronously? |
||
207 | * |
||
208 | * @return bool |
||
209 | */ |
||
210 | public function canLoadAjax(): bool |
||
213 | } |
||
214 | |||
215 | /** |
||
216 | * Convert an event into a special "event of a close relative". |
||
217 | * |
||
218 | * @param Fact $fact |
||
219 | * @param string $type |
||
220 | * |
||
221 | * @return Fact |
||
222 | */ |
||
223 | private function convertEvent(Fact $fact, string $type): Fact |
||
224 | { |
||
225 | $gedcom = $fact->gedcom(); |
||
226 | $gedcom = preg_replace('/\n2 TYPE .*/', '', $gedcom); |
||
227 | $gedcom = preg_replace('/^1 .*/', "1 EVEN CLOSE_RELATIVE\n2 TYPE " . $type, $gedcom); |
||
228 | |||
229 | $converted = new Fact($gedcom, $fact->record(), $fact->id()); |
||
230 | |||
231 | if ($fact->isPendingAddition()) { |
||
232 | $converted->setPendingAddition(); |
||
233 | } |
||
234 | |||
235 | if ($fact->isPendingDeletion()) { |
||
236 | $converted->setPendingDeletion(); |
||
237 | } |
||
238 | |||
239 | return $converted; |
||
240 | } |
||
241 | |||
242 | /** |
||
243 | * Spouse facts that are shown on an individual’s page. |
||
244 | * |
||
245 | * @param Individual $individual Show events that occured during the lifetime of this individual |
||
246 | * @param Individual $spouse Show events of this individual |
||
247 | * @param Date $min_date |
||
248 | * @param Date $max_date |
||
249 | * |
||
250 | * @return Fact[] |
||
251 | */ |
||
252 | private function spouseFacts(Individual $individual, Individual $spouse, Date $min_date, Date $max_date): array |
||
253 | { |
||
254 | $SHOW_RELATIVES_EVENTS = $individual->tree()->getPreference('SHOW_RELATIVES_EVENTS'); |
||
255 | |||
256 | $death_of_a_spouse = [ |
||
257 | 'DEAT' => [ |
||
258 | 'M' => I18N::translate('Death of a husband'), |
||
259 | 'F' => I18N::translate('Death of a wife'), |
||
260 | 'U' => I18N::translate('Death of a spouse'), |
||
261 | ], |
||
262 | 'BURI' => [ |
||
263 | 'M' => I18N::translate('Burial of a husband'), |
||
264 | 'F' => I18N::translate('Burial of a wife'), |
||
265 | 'U' => I18N::translate('Burial of a spouse'), |
||
266 | ], |
||
267 | 'CREM' => [ |
||
268 | 'M' => I18N::translate('Cremation of a husband'), |
||
269 | 'F' => I18N::translate('Cremation of a wife'), |
||
270 | 'U' => I18N::translate('Cremation of a spouse'), |
||
271 | ], |
||
272 | ]; |
||
273 | |||
274 | $facts = []; |
||
275 | |||
276 | if (str_contains($SHOW_RELATIVES_EVENTS, '_DEAT_SPOU')) { |
||
277 | foreach ($spouse->facts(['DEAT', 'BURI', 'CREM']) as $fact) { |
||
278 | if ($this->includeFact($fact, $min_date, $max_date)) { |
||
279 | $facts[] = $this->convertEvent($fact, $death_of_a_spouse[$fact->getTag()][$fact->record()->sex()]); |
||
280 | } |
||
281 | } |
||
282 | } |
||
283 | |||
284 | return $facts; |
||
285 | } |
||
286 | |||
287 | /** |
||
288 | * Get the events of children and grandchildren. |
||
289 | * |
||
290 | * @param Individual $person |
||
291 | * @param Family $family |
||
292 | * @param string $option |
||
293 | * @param string $relation |
||
294 | * @param Date $min_date |
||
295 | * @param Date $max_date |
||
296 | * |
||
297 | * @return Fact[] |
||
298 | */ |
||
299 | private function childFacts(Individual $person, Family $family, string $option, string $relation, Date $min_date, Date $max_date): array |
||
300 | { |
||
301 | $SHOW_RELATIVES_EVENTS = $person->tree()->getPreference('SHOW_RELATIVES_EVENTS'); |
||
302 | |||
303 | $birth_of_a_child = [ |
||
304 | 'BIRT' => [ |
||
305 | 'M' => I18N::translate('Birth of a son'), |
||
306 | 'F' => I18N::translate('Birth of a daughter'), |
||
307 | 'U' => I18N::translate('Birth of a child'), |
||
308 | ], |
||
309 | 'CHR' => [ |
||
310 | 'M' => I18N::translate('Christening of a son'), |
||
311 | 'F' => I18N::translate('Christening of a daughter'), |
||
312 | 'U' => I18N::translate('Christening of a child'), |
||
313 | ], |
||
314 | 'BAPM' => [ |
||
315 | 'M' => I18N::translate('Baptism of a son'), |
||
316 | 'F' => I18N::translate('Baptism of a daughter'), |
||
317 | 'U' => I18N::translate('Baptism of a child'), |
||
318 | ], |
||
319 | 'ADOP' => [ |
||
320 | 'M' => I18N::translate('Adoption of a son'), |
||
321 | 'F' => I18N::translate('Adoption of a daughter'), |
||
322 | 'U' => I18N::translate('Adoption of a child'), |
||
323 | ], |
||
324 | ]; |
||
325 | |||
326 | $birth_of_a_sibling = [ |
||
327 | 'BIRT' => [ |
||
328 | 'M' => I18N::translate('Birth of a brother'), |
||
329 | 'F' => I18N::translate('Birth of a sister'), |
||
330 | 'U' => I18N::translate('Birth of a sibling'), |
||
331 | ], |
||
332 | 'CHR' => [ |
||
333 | 'M' => I18N::translate('Christening of a brother'), |
||
334 | 'F' => I18N::translate('Christening of a sister'), |
||
335 | 'U' => I18N::translate('Christening of a sibling'), |
||
336 | ], |
||
337 | 'BAPM' => [ |
||
338 | 'M' => I18N::translate('Baptism of a brother'), |
||
339 | 'F' => I18N::translate('Baptism of a sister'), |
||
340 | 'U' => I18N::translate('Baptism of a sibling'), |
||
341 | ], |
||
342 | 'ADOP' => [ |
||
343 | 'M' => I18N::translate('Adoption of a brother'), |
||
344 | 'F' => I18N::translate('Adoption of a sister'), |
||
345 | 'U' => I18N::translate('Adoption of a sibling'), |
||
346 | ], |
||
347 | ]; |
||
348 | |||
349 | $birth_of_a_half_sibling = [ |
||
350 | 'BIRT' => [ |
||
351 | 'M' => I18N::translate('Birth of a half-brother'), |
||
352 | 'F' => I18N::translate('Birth of a half-sister'), |
||
353 | 'U' => I18N::translate('Birth of a half-sibling'), |
||
354 | ], |
||
355 | 'CHR' => [ |
||
356 | 'M' => I18N::translate('Christening of a half-brother'), |
||
357 | 'F' => I18N::translate('Christening of a half-sister'), |
||
358 | 'U' => I18N::translate('Christening of a half-sibling'), |
||
359 | ], |
||
360 | 'BAPM' => [ |
||
361 | 'M' => I18N::translate('Baptism of a half-brother'), |
||
362 | 'F' => I18N::translate('Baptism of a half-sister'), |
||
363 | 'U' => I18N::translate('Baptism of a half-sibling'), |
||
364 | ], |
||
365 | 'ADOP' => [ |
||
366 | 'M' => I18N::translate('Adoption of a half-brother'), |
||
367 | 'F' => I18N::translate('Adoption of a half-sister'), |
||
368 | 'U' => I18N::translate('Adoption of a half-sibling'), |
||
369 | ], |
||
370 | ]; |
||
371 | |||
372 | $birth_of_a_grandchild = [ |
||
373 | 'BIRT' => [ |
||
374 | 'M' => I18N::translate('Birth of a grandson'), |
||
375 | 'F' => I18N::translate('Birth of a granddaughter'), |
||
376 | 'U' => I18N::translate('Birth of a grandchild'), |
||
377 | ], |
||
378 | 'CHR' => [ |
||
379 | 'M' => I18N::translate('Christening of a grandson'), |
||
380 | 'F' => I18N::translate('Christening of a granddaughter'), |
||
381 | 'U' => I18N::translate('Christening of a grandchild'), |
||
382 | ], |
||
383 | 'BAPM' => [ |
||
384 | 'M' => I18N::translate('Baptism of a grandson'), |
||
385 | 'F' => I18N::translate('Baptism of a granddaughter'), |
||
386 | 'U' => I18N::translate('Baptism of a grandchild'), |
||
387 | ], |
||
388 | 'ADOP' => [ |
||
389 | 'M' => I18N::translate('Adoption of a grandson'), |
||
390 | 'F' => I18N::translate('Adoption of a granddaughter'), |
||
391 | 'U' => I18N::translate('Adoption of a grandchild'), |
||
392 | ], |
||
393 | ]; |
||
394 | |||
395 | $birth_of_a_grandchild1 = [ |
||
396 | 'BIRT' => [ |
||
397 | 'M' => I18N::translateContext('daughter’s son', 'Birth of a grandson'), |
||
398 | 'F' => I18N::translateContext('daughter’s daughter', 'Birth of a granddaughter'), |
||
399 | 'U' => I18N::translate('Birth of a grandchild'), |
||
400 | ], |
||
401 | 'CHR' => [ |
||
402 | 'M' => I18N::translateContext('daughter’s son', 'Christening of a grandson'), |
||
403 | 'F' => I18N::translateContext('daughter’s daughter', 'Christening of a granddaughter'), |
||
404 | 'U' => I18N::translate('Christening of a grandchild'), |
||
405 | ], |
||
406 | 'BAPM' => [ |
||
407 | 'M' => I18N::translateContext('daughter’s son', 'Baptism of a grandson'), |
||
408 | 'F' => I18N::translateContext('daughter’s daughter', 'Baptism of a granddaughter'), |
||
409 | 'U' => I18N::translate('Baptism of a grandchild'), |
||
410 | ], |
||
411 | 'ADOP' => [ |
||
412 | 'M' => I18N::translateContext('daughter’s son', 'Adoption of a grandson'), |
||
413 | 'F' => I18N::translateContext('daughter’s daughter', 'Adoption of a granddaughter'), |
||
414 | 'U' => I18N::translate('Adoption of a grandchild'), |
||
415 | ], |
||
416 | ]; |
||
417 | |||
418 | $birth_of_a_grandchild2 = [ |
||
419 | 'BIRT' => [ |
||
420 | 'M' => I18N::translateContext('son’s son', 'Birth of a grandson'), |
||
421 | 'F' => I18N::translateContext('son’s daughter', 'Birth of a granddaughter'), |
||
422 | 'U' => I18N::translate('Birth of a grandchild'), |
||
423 | ], |
||
424 | 'CHR' => [ |
||
425 | 'M' => I18N::translateContext('son’s son', 'Christening of a grandson'), |
||
426 | 'F' => I18N::translateContext('son’s daughter', 'Christening of a granddaughter'), |
||
427 | 'U' => I18N::translate('Christening of a grandchild'), |
||
428 | ], |
||
429 | 'BAPM' => [ |
||
430 | 'M' => I18N::translateContext('son’s son', 'Baptism of a grandson'), |
||
431 | 'F' => I18N::translateContext('son’s daughter', 'Baptism of a granddaughter'), |
||
432 | 'U' => I18N::translate('Baptism of a grandchild'), |
||
433 | ], |
||
434 | 'ADOP' => [ |
||
435 | 'M' => I18N::translateContext('son’s son', 'Adoption of a grandson'), |
||
436 | 'F' => I18N::translateContext('son’s daughter', 'Adoption of a granddaughter'), |
||
437 | 'U' => I18N::translate('Adoption of a grandchild'), |
||
438 | ], |
||
439 | ]; |
||
440 | |||
441 | $death_of_a_child = [ |
||
442 | 'DEAT' => [ |
||
443 | 'M' => I18N::translate('Death of a son'), |
||
444 | 'F' => I18N::translate('Death of a daughter'), |
||
445 | 'U' => I18N::translate('Death of a child'), |
||
446 | ], |
||
447 | 'BURI' => [ |
||
448 | 'M' => I18N::translate('Burial of a son'), |
||
449 | 'F' => I18N::translate('Burial of a daughter'), |
||
450 | 'U' => I18N::translate('Burial of a child'), |
||
451 | ], |
||
452 | 'CREM' => [ |
||
453 | 'M' => I18N::translate('Cremation of a son'), |
||
454 | 'F' => I18N::translate('Cremation of a daughter'), |
||
455 | 'U' => I18N::translate('Cremation of a child'), |
||
456 | ], |
||
457 | ]; |
||
458 | |||
459 | $death_of_a_sibling = [ |
||
460 | 'DEAT' => [ |
||
461 | 'M' => I18N::translate('Death of a brother'), |
||
462 | 'F' => I18N::translate('Death of a sister'), |
||
463 | 'U' => I18N::translate('Death of a sibling'), |
||
464 | ], |
||
465 | 'BURI' => [ |
||
466 | 'M' => I18N::translate('Burial of a brother'), |
||
467 | 'F' => I18N::translate('Burial of a sister'), |
||
468 | 'U' => I18N::translate('Burial of a sibling'), |
||
469 | ], |
||
470 | 'CREM' => [ |
||
471 | 'M' => I18N::translate('Cremation of a brother'), |
||
472 | 'F' => I18N::translate('Cremation of a sister'), |
||
473 | 'U' => I18N::translate('Cremation of a sibling'), |
||
474 | ], |
||
475 | ]; |
||
476 | |||
477 | $death_of_a_half_sibling = [ |
||
478 | 'DEAT' => [ |
||
479 | 'M' => I18N::translate('Death of a half-brother'), |
||
480 | 'F' => I18N::translate('Death of a half-sister'), |
||
481 | 'U' => I18N::translate('Death of a half-sibling'), |
||
482 | ], |
||
483 | 'BURI' => [ |
||
484 | 'M' => I18N::translate('Burial of a half-brother'), |
||
485 | 'F' => I18N::translate('Burial of a half-sister'), |
||
486 | 'U' => I18N::translate('Burial of a half-sibling'), |
||
487 | ], |
||
488 | 'CREM' => [ |
||
489 | 'M' => I18N::translate('Cremation of a half-brother'), |
||
490 | 'F' => I18N::translate('Cremation of a half-sister'), |
||
491 | 'U' => I18N::translate('Cremation of a half-sibling'), |
||
492 | ], |
||
493 | ]; |
||
494 | |||
495 | $death_of_a_grandchild = [ |
||
496 | 'DEAT' => [ |
||
497 | 'M' => I18N::translate('Death of a grandson'), |
||
498 | 'F' => I18N::translate('Death of a granddaughter'), |
||
499 | 'U' => I18N::translate('Death of a grandchild'), |
||
500 | ], |
||
501 | 'BURI' => [ |
||
502 | 'M' => I18N::translate('Burial of a grandson'), |
||
503 | 'F' => I18N::translate('Burial of a granddaughter'), |
||
504 | 'U' => I18N::translate('Burial of a grandchild'), |
||
505 | ], |
||
506 | 'CREM' => [ |
||
507 | 'M' => I18N::translate('Cremation of a grandson'), |
||
508 | 'F' => I18N::translate('Cremation of a granddaughter'), |
||
509 | 'U' => I18N::translate('Baptism of a grandchild'), |
||
510 | ], |
||
511 | ]; |
||
512 | |||
513 | $death_of_a_grandchild1 = [ |
||
514 | 'DEAT' => [ |
||
515 | 'M' => I18N::translateContext('daughter’s son', 'Death of a grandson'), |
||
516 | 'F' => I18N::translateContext('daughter’s daughter', 'Death of a granddaughter'), |
||
517 | 'U' => I18N::translate('Death of a grandchild'), |
||
518 | ], |
||
519 | 'BURI' => [ |
||
520 | 'M' => I18N::translateContext('daughter’s son', 'Burial of a grandson'), |
||
521 | 'F' => I18N::translateContext('daughter’s daughter', 'Burial of a granddaughter'), |
||
522 | 'U' => I18N::translate('Burial of a grandchild'), |
||
523 | ], |
||
524 | 'CREM' => [ |
||
525 | 'M' => I18N::translateContext('daughter’s son', 'Cremation of a grandson'), |
||
526 | 'F' => I18N::translateContext('daughter’s daughter', 'Cremation of a granddaughter'), |
||
527 | 'U' => I18N::translate('Baptism of a grandchild'), |
||
528 | ], |
||
529 | ]; |
||
530 | |||
531 | $death_of_a_grandchild2 = [ |
||
532 | 'DEAT' => [ |
||
533 | 'M' => I18N::translateContext('son’s son', 'Death of a grandson'), |
||
534 | 'F' => I18N::translateContext('son’s daughter', 'Death of a granddaughter'), |
||
535 | 'U' => I18N::translate('Death of a grandchild'), |
||
536 | ], |
||
537 | 'BURI' => [ |
||
538 | 'M' => I18N::translateContext('son’s son', 'Burial of a grandson'), |
||
539 | 'F' => I18N::translateContext('son’s daughter', 'Burial of a granddaughter'), |
||
540 | 'U' => I18N::translate('Burial of a grandchild'), |
||
541 | ], |
||
542 | 'CREM' => [ |
||
543 | 'M' => I18N::translateContext('son’s son', 'Cremation of a grandson'), |
||
544 | 'F' => I18N::translateContext('son’s daughter', 'Cremation of a granddaughter'), |
||
545 | 'U' => I18N::translate('Cremation of a grandchild'), |
||
546 | ], |
||
547 | ]; |
||
548 | |||
549 | $marriage_of_a_child = [ |
||
550 | 'M' => I18N::translate('Marriage of a son'), |
||
551 | 'F' => I18N::translate('Marriage of a daughter'), |
||
552 | 'U' => I18N::translate('Marriage of a child'), |
||
553 | ]; |
||
554 | |||
555 | $marriage_of_a_grandchild = [ |
||
556 | 'M' => I18N::translate('Marriage of a grandson'), |
||
557 | 'F' => I18N::translate('Marriage of a granddaughter'), |
||
558 | 'U' => I18N::translate('Marriage of a grandchild'), |
||
559 | ]; |
||
560 | |||
561 | $marriage_of_a_grandchild1 = [ |
||
562 | 'M' => I18N::translateContext('daughter’s son', 'Marriage of a grandson'), |
||
563 | 'F' => I18N::translateContext('daughter’s daughter', 'Marriage of a granddaughter'), |
||
564 | 'U' => I18N::translate('Marriage of a grandchild'), |
||
565 | ]; |
||
566 | |||
567 | $marriage_of_a_grandchild2 = [ |
||
568 | 'M' => I18N::translateContext('son’s son', 'Marriage of a grandson'), |
||
569 | 'F' => I18N::translateContext('son’s daughter', 'Marriage of a granddaughter'), |
||
570 | 'U' => I18N::translate('Marriage of a grandchild'), |
||
571 | ]; |
||
572 | |||
573 | $marriage_of_a_sibling = [ |
||
574 | 'M' => I18N::translate('Marriage of a brother'), |
||
575 | 'F' => I18N::translate('Marriage of a sister'), |
||
576 | 'U' => I18N::translate('Marriage of a sibling'), |
||
577 | ]; |
||
578 | |||
579 | $marriage_of_a_half_sibling = [ |
||
580 | 'M' => I18N::translate('Marriage of a half-brother'), |
||
581 | 'F' => I18N::translate('Marriage of a half-sister'), |
||
582 | 'U' => I18N::translate('Marriage of a half-sibling'), |
||
583 | ]; |
||
584 | |||
585 | $facts = []; |
||
586 | |||
587 | // Deal with recursion. |
||
588 | switch ($option) { |
||
589 | case '_CHIL': |
||
590 | // Add grandchildren |
||
591 | foreach ($family->children() as $child) { |
||
592 | foreach ($child->spouseFamilies() as $cfamily) { |
||
593 | switch ($child->sex()) { |
||
594 | case 'M': |
||
595 | foreach ($this->childFacts($person, $cfamily, '_GCHI', 'son', $min_date, $max_date) as $fact) { |
||
596 | $facts[] = $fact; |
||
597 | } |
||
598 | break; |
||
599 | case 'F': |
||
600 | foreach ($this->childFacts($person, $cfamily, '_GCHI', 'dau', $min_date, $max_date) as $fact) { |
||
601 | $facts[] = $fact; |
||
602 | } |
||
603 | break; |
||
604 | default: |
||
605 | foreach ($this->childFacts($person, $cfamily, '_GCHI', 'chi', $min_date, $max_date) as $fact) { |
||
606 | $facts[] = $fact; |
||
607 | } |
||
608 | break; |
||
609 | } |
||
610 | } |
||
611 | } |
||
612 | break; |
||
613 | } |
||
614 | |||
615 | // For each child in the family |
||
616 | foreach ($family->children() as $child) { |
||
617 | if ($child->xref() === $person->xref()) { |
||
618 | // We are not our own sibling! |
||
619 | continue; |
||
620 | } |
||
621 | // add child’s birth |
||
622 | if (str_contains($SHOW_RELATIVES_EVENTS, '_BIRT' . str_replace('_HSIB', '_SIBL', $option))) { |
||
623 | foreach ($child->facts(['BIRT', 'CHR', 'BAPM', 'ADOP']) as $fact) { |
||
624 | // Always show _BIRT_CHIL, even if the dates are not known |
||
625 | if ($option === '_CHIL' || $this->includeFact($fact, $min_date, $max_date)) { |
||
626 | switch ($option) { |
||
627 | case '_GCHI': |
||
628 | switch ($relation) { |
||
629 | case 'dau': |
||
630 | $facts[] = $this->convertEvent($fact, $birth_of_a_grandchild1[$fact->getTag()][$fact->record()->sex()]); |
||
631 | break; |
||
632 | case 'son': |
||
633 | $facts[] = $this->convertEvent($fact, $birth_of_a_grandchild2[$fact->getTag()][$fact->record()->sex()]); |
||
634 | break; |
||
635 | case 'chil': |
||
636 | $facts[] = $this->convertEvent($fact, $birth_of_a_grandchild[$fact->getTag()][$fact->record()->sex()]); |
||
637 | break; |
||
638 | } |
||
639 | break; |
||
640 | case '_SIBL': |
||
641 | $facts[] = $this->convertEvent($fact, $birth_of_a_sibling[$fact->getTag()][$fact->record()->sex()]); |
||
642 | break; |
||
643 | case '_HSIB': |
||
644 | $facts[] = $this->convertEvent($fact, $birth_of_a_half_sibling[$fact->getTag()][$fact->record()->sex()]); |
||
645 | break; |
||
646 | case '_CHIL': |
||
647 | $facts[] = $this->convertEvent($fact, $birth_of_a_child[$fact->getTag()][$fact->record()->sex()]); |
||
648 | break; |
||
649 | } |
||
650 | } |
||
651 | } |
||
652 | } |
||
653 | // add child’s death |
||
654 | if (str_contains($SHOW_RELATIVES_EVENTS, '_DEAT' . str_replace('_HSIB', '_SIBL', $option))) { |
||
655 | foreach ($child->facts(['DEAT', 'BURI', 'CREM']) as $fact) { |
||
656 | if ($this->includeFact($fact, $min_date, $max_date)) { |
||
657 | switch ($option) { |
||
658 | case '_GCHI': |
||
659 | switch ($relation) { |
||
660 | case 'dau': |
||
661 | $facts[] = $this->convertEvent($fact, $death_of_a_grandchild1[$fact->getTag()][$fact->record()->sex()]); |
||
662 | break; |
||
663 | case 'son': |
||
664 | $facts[] = $this->convertEvent($fact, $death_of_a_grandchild2[$fact->getTag()][$fact->record()->sex()]); |
||
665 | break; |
||
666 | case 'chi': |
||
667 | $facts[] = $this->convertEvent($fact, $death_of_a_grandchild[$fact->getTag()][$fact->record()->sex()]); |
||
668 | break; |
||
669 | } |
||
670 | break; |
||
671 | case '_SIBL': |
||
672 | $facts[] = $this->convertEvent($fact, $death_of_a_sibling[$fact->getTag()][$fact->record()->sex()]); |
||
673 | break; |
||
674 | case '_HSIB': |
||
675 | $facts[] = $this->convertEvent($fact, $death_of_a_half_sibling[$fact->getTag()][$fact->record()->sex()]); |
||
676 | break; |
||
677 | case '_CHIL': |
||
678 | $facts[] = $this->convertEvent($fact, $death_of_a_child[$fact->getTag()][$fact->record()->sex()]); |
||
679 | break; |
||
680 | } |
||
681 | } |
||
682 | } |
||
683 | } |
||
684 | |||
685 | // add child’s marriage |
||
686 | if (str_contains($SHOW_RELATIVES_EVENTS, '_MARR' . str_replace('_HSIB', '_SIBL', $option))) { |
||
687 | foreach ($child->spouseFamilies() as $sfamily) { |
||
688 | foreach ($sfamily->facts(['MARR']) as $fact) { |
||
689 | if ($this->includeFact($fact, $min_date, $max_date)) { |
||
690 | switch ($option) { |
||
691 | case '_GCHI': |
||
692 | switch ($relation) { |
||
693 | case 'dau': |
||
694 | $facts[] = $this->convertEvent($fact, $marriage_of_a_grandchild1['F']); |
||
695 | break; |
||
696 | case 'son': |
||
697 | $facts[] = $this->convertEvent($fact, $marriage_of_a_grandchild2['M']); |
||
698 | break; |
||
699 | case 'chi': |
||
700 | $facts[] = $this->convertEvent($fact, $marriage_of_a_grandchild['U']); |
||
701 | break; |
||
702 | } |
||
703 | break; |
||
704 | case '_SIBL': |
||
705 | $facts[] = $this->convertEvent($fact, $marriage_of_a_sibling['U']); |
||
706 | break; |
||
707 | case '_HSIB': |
||
708 | $facts[] = $this->convertEvent($fact, $marriage_of_a_half_sibling['U']); |
||
709 | break; |
||
710 | case '_CHIL': |
||
711 | $facts[] = $this->convertEvent($fact, $marriage_of_a_child['U']); |
||
712 | break; |
||
713 | } |
||
714 | } |
||
715 | } |
||
716 | } |
||
717 | } |
||
718 | } |
||
719 | |||
720 | return $facts; |
||
721 | } |
||
722 | |||
723 | /** |
||
724 | * Get the events of parents and grandparents. |
||
725 | * |
||
726 | * @param Individual $person |
||
727 | * @param int $sosa |
||
728 | * @param Date $min_date |
||
729 | * @param Date $max_date |
||
730 | * |
||
731 | * @return Fact[] |
||
732 | */ |
||
733 | private function parentFacts(Individual $person, int $sosa, Date $min_date, Date $max_date): array |
||
734 | { |
||
735 | $SHOW_RELATIVES_EVENTS = $person->tree()->getPreference('SHOW_RELATIVES_EVENTS'); |
||
736 | |||
737 | $death_of_a_parent = [ |
||
738 | 'DEAT' => [ |
||
739 | 'M' => I18N::translate('Death of a father'), |
||
740 | 'F' => I18N::translate('Death of a mother'), |
||
741 | 'U' => I18N::translate('Death of a parent'), |
||
742 | ], |
||
743 | 'BURI' => [ |
||
744 | 'M' => I18N::translate('Burial of a father'), |
||
745 | 'F' => I18N::translate('Burial of a mother'), |
||
746 | 'U' => I18N::translate('Burial of a parent'), |
||
747 | ], |
||
748 | 'CREM' => [ |
||
749 | 'M' => I18N::translate('Cremation of a father'), |
||
750 | 'F' => I18N::translate('Cremation of a mother'), |
||
751 | 'U' => I18N::translate('Cremation of a parent'), |
||
752 | ], |
||
753 | ]; |
||
754 | |||
755 | $death_of_a_grandparent = [ |
||
756 | 'DEAT' => [ |
||
757 | 'M' => I18N::translate('Death of a grandfather'), |
||
758 | 'F' => I18N::translate('Death of a grandmother'), |
||
759 | 'U' => I18N::translate('Death of a grandparent'), |
||
760 | ], |
||
761 | 'BURI' => [ |
||
762 | 'M' => I18N::translate('Burial of a grandfather'), |
||
763 | 'F' => I18N::translate('Burial of a grandmother'), |
||
764 | 'U' => I18N::translate('Burial of a grandparent'), |
||
765 | ], |
||
766 | 'CREM' => [ |
||
767 | 'M' => I18N::translate('Cremation of a grandfather'), |
||
768 | 'F' => I18N::translate('Cremation of a grandmother'), |
||
769 | 'U' => I18N::translate('Cremation of a grandparent'), |
||
770 | ], |
||
771 | ]; |
||
772 | |||
773 | $death_of_a_maternal_grandparent = [ |
||
774 | 'DEAT' => [ |
||
775 | 'M' => I18N::translate('Death of a maternal grandfather'), |
||
776 | 'F' => I18N::translate('Death of a maternal grandmother'), |
||
777 | 'U' => I18N::translate('Death of a grandparent'), |
||
778 | ], |
||
779 | 'BURI' => [ |
||
780 | 'M' => I18N::translate('Burial of a maternal grandfather'), |
||
781 | 'F' => I18N::translate('Burial of a maternal grandmother'), |
||
782 | 'U' => I18N::translate('Burial of a grandparent'), |
||
783 | ], |
||
784 | 'CREM' => [ |
||
785 | 'M' => I18N::translate('Cremation of a maternal grandfather'), |
||
786 | 'F' => I18N::translate('Cremation of a maternal grandmother'), |
||
787 | 'U' => I18N::translate('Cremation of a grandparent'), |
||
788 | ], |
||
789 | ]; |
||
790 | |||
791 | $death_of_a_paternal_grandparent = [ |
||
792 | 'DEAT' => [ |
||
793 | 'M' => I18N::translate('Death of a paternal grandfather'), |
||
794 | 'F' => I18N::translate('Death of a paternal grandmother'), |
||
795 | 'U' => I18N::translate('Death of a grandparent'), |
||
796 | ], |
||
797 | 'BURI' => [ |
||
798 | 'M' => I18N::translate('Burial of a paternal grandfather'), |
||
799 | 'F' => I18N::translate('Burial of a paternal grandmother'), |
||
800 | 'U' => I18N::translate('Burial of a grandparent'), |
||
801 | ], |
||
802 | 'CREM' => [ |
||
803 | 'M' => I18N::translate('Cremation of a paternal grandfather'), |
||
804 | 'F' => I18N::translate('Cremation of a paternal grandmother'), |
||
805 | 'U' => I18N::translate('Cremation of a grandparent'), |
||
806 | ], |
||
807 | ]; |
||
808 | |||
809 | $marriage_of_a_parent = [ |
||
810 | 'M' => I18N::translate('Marriage of a father'), |
||
811 | 'F' => I18N::translate('Marriage of a mother'), |
||
812 | 'U' => I18N::translate('Marriage of a parent'), |
||
813 | ]; |
||
814 | |||
815 | $facts = []; |
||
816 | |||
817 | if ($sosa === 1) { |
||
818 | foreach ($person->childFamilies() as $family) { |
||
819 | // Add siblings |
||
820 | foreach ($this->childFacts($person, $family, '_SIBL', '', $min_date, $max_date) as $fact) { |
||
821 | $facts[] = $fact; |
||
822 | } |
||
823 | foreach ($family->spouses() as $spouse) { |
||
824 | foreach ($spouse->spouseFamilies() as $sfamily) { |
||
825 | if ($family !== $sfamily) { |
||
826 | // Add half-siblings |
||
827 | foreach ($this->childFacts($person, $sfamily, '_HSIB', '', $min_date, $max_date) as $fact) { |
||
828 | $facts[] = $fact; |
||
829 | } |
||
830 | } |
||
831 | } |
||
832 | // Add grandparents |
||
833 | foreach ($this->parentFacts($spouse, $spouse->sex() === 'F' ? 3 : 2, $min_date, $max_date) as $fact) { |
||
834 | $facts[] = $fact; |
||
835 | } |
||
836 | } |
||
837 | } |
||
838 | |||
839 | if (str_contains($SHOW_RELATIVES_EVENTS, '_MARR_PARE')) { |
||
840 | // add father/mother marriages |
||
841 | foreach ($person->childFamilies() as $sfamily) { |
||
842 | foreach ($sfamily->facts(['MARR']) as $fact) { |
||
843 | if ($this->includeFact($fact, $min_date, $max_date)) { |
||
844 | // marriage of parents (to each other) |
||
845 | $facts[] = $this->convertEvent($fact, I18N::translate('Marriage of parents')); |
||
846 | } |
||
847 | } |
||
848 | } |
||
849 | foreach ($person->childStepFamilies() as $sfamily) { |
||
850 | foreach ($sfamily->facts(['MARR']) as $fact) { |
||
851 | if ($this->includeFact($fact, $min_date, $max_date)) { |
||
852 | // marriage of a parent (to another spouse) |
||
853 | $facts[] = $this->convertEvent($fact, $marriage_of_a_parent['U']); |
||
854 | } |
||
855 | } |
||
856 | } |
||
857 | } |
||
858 | } |
||
859 | |||
860 | foreach ($person->childFamilies() as $family) { |
||
861 | foreach ($family->spouses() as $parent) { |
||
862 | if (str_contains($SHOW_RELATIVES_EVENTS, '_DEAT' . ($sosa === 1 ? '_PARE' : '_GPAR'))) { |
||
863 | foreach ($parent->facts(['DEAT', 'BURI', 'CREM']) as $fact) { |
||
864 | // Show death of parent when it happened prior to birth |
||
865 | if ($sosa === 1 && Date::compare($fact->date(), $min_date) < 0 || $this->includeFact($fact, $min_date, $max_date)) { |
||
866 | switch ($sosa) { |
||
867 | case 1: |
||
868 | $facts[] = $this->convertEvent($fact, $death_of_a_parent[$fact->getTag()][$fact->record()->sex()]); |
||
869 | break; |
||
870 | case 2: |
||
871 | case 3: |
||
872 | switch ($person->sex()) { |
||
873 | case 'M': |
||
874 | $facts[] = $this->convertEvent($fact, $death_of_a_paternal_grandparent[$fact->getTag()][$fact->record()->sex()]); |
||
875 | break; |
||
876 | case 'F': |
||
877 | $facts[] = $this->convertEvent($fact, $death_of_a_maternal_grandparent[$fact->getTag()][$fact->record()->sex()]); |
||
878 | break; |
||
879 | default: |
||
880 | $facts[] = $this->convertEvent($fact, $death_of_a_grandparent[$fact->getTag()][$fact->record()->sex()]); |
||
881 | break; |
||
882 | } |
||
883 | } |
||
884 | } |
||
885 | } |
||
886 | } |
||
887 | } |
||
888 | } |
||
889 | |||
890 | return $facts; |
||
891 | } |
||
892 | |||
893 | /** |
||
894 | * Get any historical events. |
||
895 | * |
||
896 | * @param Individual $individual |
||
897 | * |
||
898 | * @return Fact[] |
||
899 | */ |
||
900 | private function historicalFacts(Individual $individual): array |
||
908 | } |
||
909 | |||
910 | /** |
||
911 | * Get the events of associates. |
||
912 | * |
||
913 | * @param Individual $person |
||
914 | * |
||
915 | * @return Fact[] |
||
916 | */ |
||
917 | private function associateFacts(Individual $person): array |
||
918 | { |
||
919 | $facts = []; |
||
920 | |||
921 | /** @var Individual[] $associates */ |
||
922 | $asso1 = $person->linkedIndividuals('ASSO'); |
||
923 | $asso2 = $person->linkedIndividuals('_ASSO'); |
||
924 | $asso3 = $person->linkedFamilies('ASSO'); |
||
925 | $asso4 = $person->linkedFamilies('_ASSO'); |
||
926 | |||
927 | $associates = $asso1->merge($asso2)->merge($asso3)->merge($asso4); |
||
928 | |||
929 | foreach ($associates as $associate) { |
||
930 | foreach ($associate->facts() as $fact) { |
||
931 | if (preg_match('/\n\d _?ASSO @' . $person->xref() . '@/', $fact->gedcom())) { |
||
932 | // Extract the important details from the fact |
||
933 | $factrec = '1 ' . $fact->getTag(); |
||
934 | if (preg_match('/\n2 DATE .*/', $fact->gedcom(), $match)) { |
||
935 | $factrec .= $match[0]; |
||
936 | } |
||
937 | if (preg_match('/\n2 PLAC .*/', $fact->gedcom(), $match)) { |
||
938 | $factrec .= $match[0]; |
||
939 | } |
||
940 | if ($associate instanceof Family) { |
||
941 | foreach ($associate->spouses() as $spouse) { |
||
942 | $factrec .= "\n2 _ASSO @" . $spouse->xref() . '@'; |
||
943 | } |
||
944 | } else { |
||
945 | $factrec .= "\n2 _ASSO @" . $associate->xref() . '@'; |
||
946 | } |
||
947 | $facts[] = new Fact($factrec, $associate, 'asso'); |
||
948 | } |
||
949 | } |
||
950 | } |
||
951 | |||
952 | return $facts; |
||
953 | } |
||
954 | |||
955 | /** |
||
956 | * This module handles the following facts - so don't show them on the "Facts and events" tab. |
||
957 | * |
||
958 | * @return Collection<string> |
||
959 | */ |
||
960 | public function supportedFacts(): Collection |
||
965 | } |
||
966 | } |
||
967 |
This function has been deprecated. The supplier of the function has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.