1<?php 2 3declare(strict_types=1); 4 5use Fisharebest\Webtrees\DB; 6use Fisharebest\Webtrees\I18N; 7use Fisharebest\Webtrees\Location; 8use Fisharebest\Webtrees\Tree; 9use Illuminate\Database\Query\Expression; 10use Illuminate\Database\Query\JoinClause; 11use Illuminate\Support\Collection; 12 13/** 14 * @var Collection<int,Location> $locations 15 * @var Tree $tree 16 */ 17 18?> 19 20<?php 21// Count the number of linked records. These numbers include private records. 22// It is not good to bypass privacy, but many servers do not have the resources 23// to process privacy for every record in the tree 24$count_individuals = DB::table('individuals') 25 ->join('link', static function (JoinClause $join): void { 26 $join->on('l_from', '=', 'i_id'); 27 $join->on('l_file', '=', 'i_file'); 28 }) 29 ->where('l_type', '=', '_LOC') 30 ->where('l_file', '=', $tree->id()) 31 ->groupBy(['l_to']) 32 ->pluck(new Expression('COUNT(*) AS total'), 'l_to') 33 ->map(static fn ($n) => (int) $n) 34 ->all(); 35 36$count_families = DB::table('families') 37 ->join('link', static function (JoinClause $join): void { 38 $join->on('l_from', '=', 'f_id'); 39 $join->on('l_file', '=', 'f_file'); 40 }) 41 ->where('l_type', '=', '_LOC') 42 ->where('l_file', '=', $tree->id()) 43 ->groupBy(['l_to']) 44 ->pluck(new Expression('COUNT(*) AS total'), 'l_to') 45 ->map(static fn ($n) => (int) $n) 46 ->all(); 47?> 48 49<table 50 class="table table-bordered table-sm wt-table-location datatables d-none" 51 <?= view('lists/datatables-attributes') ?> 52 data-columns="<?= e(json_encode([ 53 ['type' => 'html'], 54 ['visible' => array_sum($count_individuals) > 0], 55 ['visible' => array_sum($count_families) > 0], 56 ['visible' => (bool) $tree->getPreference('SHOW_LAST_CHANGE'), 'searchable' => false], 57 ], JSON_THROW_ON_ERROR)) ?>" 58> 59 <caption class="visually-hidden"> 60 <?= $caption ?? I18N::translate('Locations') ?> 61 </caption> 62 63 <thead> 64 <tr> 65 <th><?= I18N::translate('Location') ?></th> 66 <th><?= I18N::translate('Individuals') ?></th> 67 <th><?= I18N::translate('Families') ?></th> 68 <th><?= I18N::translate('Last change') ?></th> 69 </tr> 70 </thead> 71 72 <tbody> 73 <?php foreach ($locations as $location) : ?> 74 <tr class="<?= $location->isPendingAddition() ? 'wt-new' : '' ?> <?= $location->isPendingDeletion() ? 'wt-old' : '' ?>"> 75 <!-- Location name --> 76 <td data-sort="<?= e($location->sortName()) ?>"> 77 <a href="<?= e($location->url()) ?>"> 78 <?= $location->fullName() ?> 79 </a> 80 </td> 81 82 <!-- Count of linked individuals --> 83 <td class="text-center" data-sort="<?= $count_individuals[$location->xref()] ?? 0 ?>"> 84 <?= I18N::number($count_individuals[$location->xref()] ?? 0) ?> 85 </td> 86 87 <!-- Count of linked families --> 88 <td class="text-center" data-sort="<?= $count_families[$location->xref()] ?? 0 ?>"> 89 <?= I18N::number($count_families[$location->xref()] ?? 0) ?> 90 </td> 91 92 <!-- Last change --> 93 <td data-sort="<?= $location->lastChangeTimestamp()->timestamp() ?>"> 94 <?= view('components/datetime', ['timestamp' => $location->lastChangeTimestamp()]) ?> 95 </td> 96 </tr> 97 <?php endforeach ?> 98 </tbody> 99</table> 100