1<?php 2 3declare(strict_types=1); 4 5use Fisharebest\Webtrees\Age; 6use Fisharebest\Webtrees\Auth; 7use Fisharebest\Webtrees\Fact; 8use Fisharebest\Webtrees\Family; 9use Fisharebest\Webtrees\Gedcom; 10use Fisharebest\Webtrees\I18N; 11use Fisharebest\Webtrees\Individual; 12use Fisharebest\Webtrees\Module\ModuleChartInterface; 13use Fisharebest\Webtrees\Module\ModuleInterface; 14use Fisharebest\Webtrees\Module\RelationshipsChartModule; 15use Fisharebest\Webtrees\Registry; 16use Fisharebest\Webtrees\Services\ModuleService; 17use Fisharebest\Webtrees\Services\RelationshipService; 18 19/** 20 * @var Fact $fact 21 */ 22 23$parent = $fact->record(); 24// To whom is this record an associate? 25if ($parent instanceof Individual) { 26 // On an individual page, we just show links to the person 27 $associates = [$parent]; 28} elseif ($parent instanceof Family) { 29 // On a family page, we show links to both spouses 30 $associates = $parent->spouses(); 31} else { 32 // On other pages, it does not make sense to show associates 33 return ''; 34} 35 36preg_match_all('/\n2 (_?ASSO) @(' . Gedcom::REGEX_XREF . ')@((\n[3-9].*)*)/', $fact->gedcom(), $amatches, PREG_SET_ORDER); 37 38$html = ''; 39// For each ASSO record 40foreach ($amatches as $amatch) { 41 $person = Registry::individualFactory()->make($amatch[2], $fact->record()->tree()); 42 if ($person instanceof Individual && $person->canShowName()) { 43 // Is there a "RELA" tag 44 if (preg_match('/\n([23]) RELA (.+)/', $amatch[3], $rmatch) === 1) { 45 if ($rmatch[1] === '2') { 46 $rela_tag = $fact->record()->tag() . ':' . $amatch[1] . ':RELA'; 47 } else { 48 $rela_tag = $fact->tag() . ':' . $amatch[1] . ':RELA'; 49 } 50 // Use the supplied relationship as a label 51 $label = Registry::elementFactory()->make($rela_tag)->value($rmatch[2], $parent->tree()); 52 } elseif (preg_match('/^1 _?ASSO/', $fact->gedcom()) === 1) { 53 // Use a default label 54 $label = Registry::elementFactory()->make($fact->tag())->label(); 55 } else { 56 // Use a default label 57 $label = Registry::elementFactory()->make($fact->tag() . ':_ASSO')->label(); 58 } 59 60 if ($person !== $parent && $person->getBirthDate()->isOK() && $fact->date()->isOK()) { 61 $age = new Age($person->getBirthDate(), $fact->date()); 62 switch ($person->sex()) { 63 case 'M': 64 $age_text = ' ' . I18N::translateContext('Male', '(aged %s)', (string) $age); 65 break; 66 case 'F': 67 $age_text = ' ' . I18N::translateContext('Female', '(aged %s)', (string) $age); 68 break; 69 default: 70 $age_text = ' ' . I18N::translate('(aged %s)', (string) $age); 71 break; 72 } 73 } else { 74 $age_text = ''; 75 } 76 77 $values = ['<a href="' . e($person->url()) . '">' . $person->fullName() . '</a>' . $age_text]; 78 79 $module = Registry::container()->get(ModuleService::class) 80 ->findByComponent(ModuleChartInterface::class, $person->tree(), Auth::user()) 81 ->first(static function (ModuleInterface $module) { 82 return $module instanceof RelationshipsChartModule; 83 }); 84 85 if ($module instanceof RelationshipsChartModule) { 86 foreach ($associates as $associate) { 87 $relationship_name = Registry::container()->get(RelationshipService::class)->getCloseRelationshipName($associate, $person); 88 if ($relationship_name === '') { 89 $relationship_name = I18N::translate('Relationship'); 90 } 91 92 if ($parent instanceof Family) { 93 // For family ASSO records (e.g. MARR), identify the spouse with a sex icon 94 $relationship_name .= '<small>' . view('icons/sex', ['sex' => $associate->sex()]) . '</small>'; 95 } 96 97 $values[] = '<a href="' . $module->chartUrl($associate, ['xref2' => $person->xref()]) . '" rel="nofollow">' . $relationship_name . '</a>'; 98 } 99 } 100 $label = '<span class="label">' . $label . '</span>'; 101 $value = '<span class="field" dir="auto">' . implode(' — ', $values) . '</span>'; 102 103 $asso = I18N::translate('%1$s: %2$s', $label, $value); 104 } elseif ($amatch[2] === 'VOID') { 105 $label = '<span class="label">' . I18N::translate('Associate') . '</span>'; 106 $value = I18N::translate('Not recorded'); 107 $asso = I18N::translate('%1$s: %2$s', $label, $value); 108 } elseif (Auth::isEditor($fact->record()->tree())) { 109 $label = '<span class="label">' . I18N::translate('Associate') . '</span>'; 110 $value = '<span class="error">@' . e($amatch[2]) . '@</span>'; 111 $asso = I18N::translate('%1$s: %2$s', $label, $value); 112 } else { 113 $asso = ''; 114 } 115 $html .= '<div class="fact_ASSO">' . $asso . '</div>'; 116} 117 118echo $html; 119