10c0910bfSGreg Roach<?php 20c0910bfSGreg Roach 30c0910bfSGreg Roach/** 40c0910bfSGreg Roach * webtrees: online genealogy 5*5bfc6897SGreg Roach * Copyright (C) 2022 webtrees development team 60c0910bfSGreg Roach * This program is free software: you can redistribute it and/or modify 70c0910bfSGreg Roach * it under the terms of the GNU General Public License as published by 80c0910bfSGreg Roach * the Free Software Foundation, either version 3 of the License, or 90c0910bfSGreg Roach * (at your option) any later version. 100c0910bfSGreg Roach * This program is distributed in the hope that it will be useful, 110c0910bfSGreg Roach * but WITHOUT ANY WARRANTY; without even the implied warranty of 120c0910bfSGreg Roach * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 130c0910bfSGreg Roach * GNU General Public License for more details. 140c0910bfSGreg Roach * You should have received a copy of the GNU General Public License 1589f7189bSGreg Roach * along with this program. If not, see <https://www.gnu.org/licenses/>. 160c0910bfSGreg Roach */ 17fcfa147eSGreg Roach 180c0910bfSGreg Roachdeclare(strict_types=1); 190c0910bfSGreg Roach 200c0910bfSGreg Roachnamespace Fisharebest\Webtrees\Http\RequestHandlers; 210c0910bfSGreg Roach 220c0910bfSGreg Roachuse Fisharebest\Webtrees\Http\ViewResponseTrait; 230c0910bfSGreg Roachuse Fisharebest\Webtrees\I18N; 240c0910bfSGreg Roachuse Fisharebest\Webtrees\Module\FamilyListModule; 250c0910bfSGreg Roachuse Fisharebest\Webtrees\Module\IndividualListModule; 260c0910bfSGreg Roachuse Fisharebest\Webtrees\Module\MediaListModule; 270c0910bfSGreg Roachuse Fisharebest\Webtrees\Module\ModuleAnalyticsInterface; 280c0910bfSGreg Roachuse Fisharebest\Webtrees\Module\ModuleBlockInterface; 290c0910bfSGreg Roachuse Fisharebest\Webtrees\Module\ModuleChartInterface; 3064d12f7bSGreg Roachuse Fisharebest\Webtrees\Module\ModuleCustomInterface; 314da96842SGreg Roachuse Fisharebest\Webtrees\Module\ModuleCustomTagsInterface; 32ce42304aSGreg Roachuse Fisharebest\Webtrees\Module\ModuleDataFixInterface; 330c0910bfSGreg Roachuse Fisharebest\Webtrees\Module\ModuleFooterInterface; 340c0910bfSGreg Roachuse Fisharebest\Webtrees\Module\ModuleHistoricEventsInterface; 350c0910bfSGreg Roachuse Fisharebest\Webtrees\Module\ModuleLanguageInterface; 360c0910bfSGreg Roachuse Fisharebest\Webtrees\Module\ModuleListInterface; 37c9c6f2ecSGreg Roachuse Fisharebest\Webtrees\Module\ModuleMapAutocompleteInterface; 38c9c6f2ecSGreg Roachuse Fisharebest\Webtrees\Module\ModuleMapGeoLocationInterface; 39e3544cb2SGreg Roachuse Fisharebest\Webtrees\Module\ModuleMapLinkInterface; 40c9c6f2ecSGreg Roachuse Fisharebest\Webtrees\Module\ModuleMapProviderInterface; 410c0910bfSGreg Roachuse Fisharebest\Webtrees\Module\ModuleMenuInterface; 420c0910bfSGreg Roachuse Fisharebest\Webtrees\Module\ModuleReportInterface; 438a1a28d7SGreg Roachuse Fisharebest\Webtrees\Module\ModuleShareInterface; 440c0910bfSGreg Roachuse Fisharebest\Webtrees\Module\ModuleSidebarInterface; 450c0910bfSGreg Roachuse Fisharebest\Webtrees\Module\ModuleTabInterface; 460c0910bfSGreg Roachuse Fisharebest\Webtrees\Module\ModuleThemeInterface; 470c0910bfSGreg Roachuse Fisharebest\Webtrees\Module\NoteListModule; 480c0910bfSGreg Roachuse Fisharebest\Webtrees\Module\RepositoryListModule; 490c0910bfSGreg Roachuse Fisharebest\Webtrees\Module\SourceListModule; 50e72c24d6SGreg Roachuse Fisharebest\Webtrees\Module\SubmitterListModule; 51e72c24d6SGreg Roachuse Fisharebest\Webtrees\Note; 526b9cb339SGreg Roachuse Fisharebest\Webtrees\Registry; 53e72c24d6SGreg Roachuse Fisharebest\Webtrees\Repository; 546fd01894SGreg Roachuse Fisharebest\Webtrees\Services\AdminService; 550c0910bfSGreg Roachuse Fisharebest\Webtrees\Services\HousekeepingService; 56a46dd5a6SGreg Roachuse Fisharebest\Webtrees\Services\MessageService; 570c0910bfSGreg Roachuse Fisharebest\Webtrees\Services\ModuleService; 580c0910bfSGreg Roachuse Fisharebest\Webtrees\Services\ServerCheckService; 590c0910bfSGreg Roachuse Fisharebest\Webtrees\Services\TreeService; 600c0910bfSGreg Roachuse Fisharebest\Webtrees\Services\UpgradeService; 610c0910bfSGreg Roachuse Fisharebest\Webtrees\Services\UserService; 62e72c24d6SGreg Roachuse Fisharebest\Webtrees\Submitter; 630c0910bfSGreg Roachuse Fisharebest\Webtrees\Webtrees; 640c0910bfSGreg Roachuse Illuminate\Database\Capsule\Manager as DB; 650c0910bfSGreg Roachuse Illuminate\Database\Query\Expression; 660c0910bfSGreg Roachuse Illuminate\Database\Query\JoinClause; 670c0910bfSGreg Roachuse Illuminate\Support\Collection; 680c0910bfSGreg Roachuse League\Flysystem\Filesystem; 69f7cf8a15SGreg Roachuse League\Flysystem\Local\LocalFilesystemAdapter; 700c0910bfSGreg Roachuse Psr\Http\Message\ResponseInterface; 710c0910bfSGreg Roachuse Psr\Http\Message\ServerRequestInterface; 720c0910bfSGreg Roachuse Psr\Http\Server\RequestHandlerInterface; 730c0910bfSGreg Roach 740c0910bfSGreg Roach/** 750c0910bfSGreg Roach * The control panel shows a summary of the site and links to admin functions. 760c0910bfSGreg Roach */ 770c0910bfSGreg Roachclass ControlPanel implements RequestHandlerInterface 780c0910bfSGreg Roach{ 790c0910bfSGreg Roach use ViewResponseTrait; 800c0910bfSGreg Roach 81c9c6f2ecSGreg Roach private AdminService $admin_service; 826fd01894SGreg Roach 83c9c6f2ecSGreg Roach private HousekeepingService $housekeeping_service; 840c0910bfSGreg Roach 85a46dd5a6SGreg Roach private MessageService $message_service; 86a46dd5a6SGreg Roach 87a46dd5a6SGreg Roach private ModuleService $module_service; 88a46dd5a6SGreg Roach 89c9c6f2ecSGreg Roach private ServerCheckService $server_check_service; 900c0910bfSGreg Roach 91c9c6f2ecSGreg Roach private TreeService $tree_service; 920c0910bfSGreg Roach 93c9c6f2ecSGreg Roach private UpgradeService $upgrade_service; 940c0910bfSGreg Roach 95c9c6f2ecSGreg Roach private UserService $user_service; 960c0910bfSGreg Roach 970c0910bfSGreg Roach /** 980c0910bfSGreg Roach * ControlPanel constructor. 990c0910bfSGreg Roach * 1006fd01894SGreg Roach * @param AdminService $admin_service 1010c0910bfSGreg Roach * @param HousekeepingService $housekeeping_service 102a46dd5a6SGreg Roach * @param MessageService $message_service 1030c0910bfSGreg Roach * @param ModuleService $module_service 1040c0910bfSGreg Roach * @param ServerCheckService $server_check_service 1050c0910bfSGreg Roach * @param TreeService $tree_service 1060c0910bfSGreg Roach * @param UpgradeService $upgrade_service 1070c0910bfSGreg Roach * @param UserService $user_service 1080c0910bfSGreg Roach */ 1090c0910bfSGreg Roach public function __construct( 1106fd01894SGreg Roach AdminService $admin_service, 1110c0910bfSGreg Roach HousekeepingService $housekeeping_service, 112a46dd5a6SGreg Roach MessageService $message_service, 1130c0910bfSGreg Roach ModuleService $module_service, 1140c0910bfSGreg Roach ServerCheckService $server_check_service, 1150c0910bfSGreg Roach TreeService $tree_service, 1160c0910bfSGreg Roach UpgradeService $upgrade_service, 1170c0910bfSGreg Roach UserService $user_service 118928b8592SGreg Roach ) { 1196fd01894SGreg Roach $this->admin_service = $admin_service; 1200c0910bfSGreg Roach $this->housekeeping_service = $housekeeping_service; 121a46dd5a6SGreg Roach $this->message_service = $message_service; 1226fd01894SGreg Roach $this->module_service = $module_service; 1230c0910bfSGreg Roach $this->server_check_service = $server_check_service; 1240c0910bfSGreg Roach $this->tree_service = $tree_service; 1250c0910bfSGreg Roach $this->upgrade_service = $upgrade_service; 1260c0910bfSGreg Roach $this->user_service = $user_service; 1270c0910bfSGreg Roach } 1280c0910bfSGreg Roach 1290c0910bfSGreg Roach /** 1300c0910bfSGreg Roach * @param ServerRequestInterface $request 1310c0910bfSGreg Roach * 1320c0910bfSGreg Roach * @return ResponseInterface 1330c0910bfSGreg Roach */ 1340c0910bfSGreg Roach public function handle(ServerRequestInterface $request): ResponseInterface 1350c0910bfSGreg Roach { 1360c0910bfSGreg Roach $this->layout = 'layouts/administration'; 1370c0910bfSGreg Roach 138f7cf8a15SGreg Roach $filesystem = new Filesystem(new LocalFilesystemAdapter(Webtrees::ROOT_DIR)); 1390c0910bfSGreg Roach $files_to_delete = $this->housekeeping_service->deleteOldWebtreesFiles($filesystem); 1400c0910bfSGreg Roach 14164d12f7bSGreg Roach $custom_updates = $this->module_service 14264d12f7bSGreg Roach ->findByInterface(ModuleCustomInterface::class) 14364d12f7bSGreg Roach ->filter(static function (ModuleCustomInterface $module): bool { 14464d12f7bSGreg Roach return version_compare($module->customModuleLatestVersion(), $module->customModuleVersion()) > 0; 14564d12f7bSGreg Roach }); 14664d12f7bSGreg Roach 1476fd01894SGreg Roach $multiple_tree_threshold = $this->admin_service->multipleTreeThreshold(); 1486b9cb339SGreg Roach $gedcom_file_count = $this->admin_service->gedcomFiles(Registry::filesystem()->data())->count(); 1496fd01894SGreg Roach 1500c0910bfSGreg Roach return $this->viewResponse('admin/control-panel', [ 1510c0910bfSGreg Roach 'title' => I18N::translate('Control panel'), 1520c0910bfSGreg Roach 'server_errors' => $this->server_check_service->serverErrors(), 1530c0910bfSGreg Roach 'server_warnings' => $this->server_check_service->serverWarnings(), 1540c0910bfSGreg Roach 'latest_version' => $this->upgrade_service->latestVersion(), 1550c0910bfSGreg Roach 'all_users' => $this->user_service->all(), 1560c0910bfSGreg Roach 'administrators' => $this->user_service->administrators(), 1570c0910bfSGreg Roach 'managers' => $this->user_service->managers(), 1580c0910bfSGreg Roach 'moderators' => $this->user_service->moderators(), 1590c0910bfSGreg Roach 'unapproved' => $this->user_service->unapproved(), 1600c0910bfSGreg Roach 'unverified' => $this->user_service->unverified(), 161a46dd5a6SGreg Roach 'recipients' => $this->message_service->recipientTypes(), 1620c0910bfSGreg Roach 'all_trees' => $this->tree_service->all(), 1630c0910bfSGreg Roach 'changes' => $this->totalChanges(), 1640c0910bfSGreg Roach 'individuals' => $this->totalIndividuals(), 1650c0910bfSGreg Roach 'families' => $this->totalFamilies(), 1660c0910bfSGreg Roach 'sources' => $this->totalSources(), 1670c0910bfSGreg Roach 'media' => $this->totalMediaObjects(), 1680c0910bfSGreg Roach 'repositories' => $this->totalRepositories(), 1690c0910bfSGreg Roach 'notes' => $this->totalNotes(), 170e72c24d6SGreg Roach 'submitters' => $this->totalSubmitters(), 17160ef53afSGreg Roach 'individual_list_module' => $this->module_service->findByInterface(IndividualListModule::class)->last(), 1720c0910bfSGreg Roach 'family_list_module' => $this->module_service->findByInterface(FamilyListModule::class)->first(), 1730c0910bfSGreg Roach 'media_list_module' => $this->module_service->findByInterface(MediaListModule::class)->first(), 1740c0910bfSGreg Roach 'note_list_module' => $this->module_service->findByInterface(NoteListModule::class)->first(), 1750c0910bfSGreg Roach 'repository_list_module' => $this->module_service->findByInterface(RepositoryListModule::class)->first(), 1760c0910bfSGreg Roach 'source_list_module' => $this->module_service->findByInterface(SourceListModule::class)->first(), 177e72c24d6SGreg Roach 'submitter_list_module' => $this->module_service->findByInterface(SubmitterListModule::class)->first(), 1780c0910bfSGreg Roach 'files_to_delete' => $files_to_delete, 1790c0910bfSGreg Roach 'all_modules_disabled' => $this->module_service->all(true), 1800c0910bfSGreg Roach 'all_modules_enabled' => $this->module_service->all(), 1810c0910bfSGreg Roach 'deleted_modules' => $this->module_service->deletedModules(), 1820c0910bfSGreg Roach 'analytics_modules_disabled' => $this->module_service->findByInterface(ModuleAnalyticsInterface::class, true), 1830c0910bfSGreg Roach 'analytics_modules_enabled' => $this->module_service->findByInterface(ModuleAnalyticsInterface::class), 1840c0910bfSGreg Roach 'block_modules_disabled' => $this->module_service->findByInterface(ModuleBlockInterface::class, true), 1850c0910bfSGreg Roach 'block_modules_enabled' => $this->module_service->findByInterface(ModuleBlockInterface::class), 1860c0910bfSGreg Roach 'chart_modules_disabled' => $this->module_service->findByInterface(ModuleChartInterface::class, true), 1870c0910bfSGreg Roach 'chart_modules_enabled' => $this->module_service->findByInterface(ModuleChartInterface::class), 18864d12f7bSGreg Roach 'custom_updates' => $custom_updates, 1894da96842SGreg Roach 'custom_tags_modules_disabled' => $this->module_service->findByInterface(ModuleCustomTagsInterface::class, true), 1904da96842SGreg Roach 'custom_tags_modules_enabled' => $this->module_service->findByInterface(ModuleCustomTagsInterface::class), 191ce42304aSGreg Roach 'data_fix_modules_disabled' => $this->module_service->findByInterface(ModuleDataFixInterface::class, true), 192ce42304aSGreg Roach 'data_fix_modules_enabled' => $this->module_service->findByInterface(ModuleDataFixInterface::class), 1930c0910bfSGreg Roach 'other_modules' => $this->module_service->otherModules(true), 1940c0910bfSGreg Roach 'footer_modules_disabled' => $this->module_service->findByInterface(ModuleFooterInterface::class, true), 1950c0910bfSGreg Roach 'footer_modules_enabled' => $this->module_service->findByInterface(ModuleFooterInterface::class), 1960c0910bfSGreg Roach 'history_modules_disabled' => $this->module_service->findByInterface(ModuleHistoricEventsInterface::class, true), 1970c0910bfSGreg Roach 'history_modules_enabled' => $this->module_service->findByInterface(ModuleHistoricEventsInterface::class), 1980c0910bfSGreg Roach 'language_modules_disabled' => $this->module_service->findByInterface(ModuleLanguageInterface::class, true), 1990c0910bfSGreg Roach 'language_modules_enabled' => $this->module_service->findByInterface(ModuleLanguageInterface::class), 2000c0910bfSGreg Roach 'list_modules_disabled' => $this->module_service->findByInterface(ModuleListInterface::class, true), 2010c0910bfSGreg Roach 'list_modules_enabled' => $this->module_service->findByInterface(ModuleListInterface::class), 202c9c6f2ecSGreg Roach 'map_autocomplete_modules_disabled' => $this->module_service->findByInterface(ModuleMapAutocompleteInterface::class, true), 203c9c6f2ecSGreg Roach 'map_autocomplete_modules_enabled' => $this->module_service->findByInterface(ModuleMapAutocompleteInterface::class), 204e3544cb2SGreg Roach 'map_link_modules_disabled' => $this->module_service->findByInterface(ModuleMapLinkInterface::class, true), 205e3544cb2SGreg Roach 'map_link_modules_enabled' => $this->module_service->findByInterface(ModuleMapLinkInterface::class), 206c9c6f2ecSGreg Roach 'map_provider_modules_disabled' => $this->module_service->findByInterface(ModuleMapProviderInterface::class, true), 207c9c6f2ecSGreg Roach 'map_provider_modules_enabled' => $this->module_service->findByInterface(ModuleMapProviderInterface::class), 208c9c6f2ecSGreg Roach 'map_search_modules_disabled' => $this->module_service->findByInterface(ModuleMapGeoLocationInterface::class, true), 209c9c6f2ecSGreg Roach 'map_search_modules_enabled' => $this->module_service->findByInterface(ModuleMapGeoLocationInterface::class), 2100c0910bfSGreg Roach 'menu_modules_disabled' => $this->module_service->findByInterface(ModuleMenuInterface::class, true), 2110c0910bfSGreg Roach 'menu_modules_enabled' => $this->module_service->findByInterface(ModuleMenuInterface::class), 2120c0910bfSGreg Roach 'report_modules_disabled' => $this->module_service->findByInterface(ModuleReportInterface::class, true), 2130c0910bfSGreg Roach 'report_modules_enabled' => $this->module_service->findByInterface(ModuleReportInterface::class), 2148a1a28d7SGreg Roach 'share_modules_disabled' => $this->module_service->findByInterface(ModuleShareInterface::class, true), 2158a1a28d7SGreg Roach 'share_modules_enabled' => $this->module_service->findByInterface(ModuleShareInterface::class), 2160c0910bfSGreg Roach 'sidebar_modules_disabled' => $this->module_service->findByInterface(ModuleSidebarInterface::class, true), 2170c0910bfSGreg Roach 'sidebar_modules_enabled' => $this->module_service->findByInterface(ModuleSidebarInterface::class), 2180c0910bfSGreg Roach 'tab_modules_disabled' => $this->module_service->findByInterface(ModuleTabInterface::class, true), 2190c0910bfSGreg Roach 'tab_modules_enabled' => $this->module_service->findByInterface(ModuleTabInterface::class), 2200c0910bfSGreg Roach 'theme_modules_disabled' => $this->module_service->findByInterface(ModuleThemeInterface::class, true), 2210c0910bfSGreg Roach 'theme_modules_enabled' => $this->module_service->findByInterface(ModuleThemeInterface::class), 2226fd01894SGreg Roach 'show_synchronize' => $gedcom_file_count >= $multiple_tree_threshold, 2230c0910bfSGreg Roach ]); 2240c0910bfSGreg Roach } 2250c0910bfSGreg Roach 2260c0910bfSGreg Roach /** 2270c0910bfSGreg Roach * Count the number of pending changes in each tree. 2280c0910bfSGreg Roach * 22924f2a3afSGreg Roach * @return array<string> 2300c0910bfSGreg Roach */ 2310c0910bfSGreg Roach private function totalChanges(): array 2320c0910bfSGreg Roach { 2330c0910bfSGreg Roach return DB::table('gedcom') 2340c0910bfSGreg Roach ->leftJoin('change', static function (JoinClause $join): void { 2350c0910bfSGreg Roach $join 2360c0910bfSGreg Roach ->on('change.gedcom_id', '=', 'gedcom.gedcom_id') 2370c0910bfSGreg Roach ->where('change.status', '=', 'pending'); 2380c0910bfSGreg Roach }) 2390c0910bfSGreg Roach ->groupBy(['gedcom.gedcom_id']) 240eb8ab1e1SGreg Roach ->pluck(new Expression('COUNT(change_id) AS aggregate'), 'gedcom.gedcom_id') 2410c0910bfSGreg Roach ->all(); 2420c0910bfSGreg Roach } 2430c0910bfSGreg Roach 2440c0910bfSGreg Roach /** 2450c0910bfSGreg Roach * Count the number of individuals in each tree. 2460c0910bfSGreg Roach * 24736779af1SGreg Roach * @return Collection<int,int> 2480c0910bfSGreg Roach */ 2490c0910bfSGreg Roach private function totalIndividuals(): Collection 2500c0910bfSGreg Roach { 2510c0910bfSGreg Roach return DB::table('gedcom') 2520c0910bfSGreg Roach ->leftJoin('individuals', 'i_file', '=', 'gedcom_id') 2530c0910bfSGreg Roach ->groupBy(['gedcom_id']) 254eb8ab1e1SGreg Roach ->pluck(new Expression('COUNT(i_id) AS aggregate'), 'gedcom_id') 2550c0910bfSGreg Roach ->map(static function (string $count) { 2560c0910bfSGreg Roach return (int) $count; 2570c0910bfSGreg Roach }); 2580c0910bfSGreg Roach } 2590c0910bfSGreg Roach 2600c0910bfSGreg Roach /** 2610c0910bfSGreg Roach * Count the number of families in each tree. 2620c0910bfSGreg Roach * 26336779af1SGreg Roach * @return Collection<int,int> 2640c0910bfSGreg Roach */ 2650c0910bfSGreg Roach private function totalFamilies(): Collection 2660c0910bfSGreg Roach { 2670c0910bfSGreg Roach return DB::table('gedcom') 2680c0910bfSGreg Roach ->leftJoin('families', 'f_file', '=', 'gedcom_id') 2690c0910bfSGreg Roach ->groupBy(['gedcom_id']) 270eb8ab1e1SGreg Roach ->pluck(new Expression('COUNT(f_id) AS aggregate'), 'gedcom_id') 2710c0910bfSGreg Roach ->map(static function (string $count) { 2720c0910bfSGreg Roach return (int) $count; 2730c0910bfSGreg Roach }); 2740c0910bfSGreg Roach } 2750c0910bfSGreg Roach 2760c0910bfSGreg Roach /** 2770c0910bfSGreg Roach * Count the number of sources in each tree. 2780c0910bfSGreg Roach * 27936779af1SGreg Roach * @return Collection<int,int> 2800c0910bfSGreg Roach */ 2810c0910bfSGreg Roach private function totalSources(): Collection 2820c0910bfSGreg Roach { 2830c0910bfSGreg Roach return DB::table('gedcom') 2840c0910bfSGreg Roach ->leftJoin('sources', 's_file', '=', 'gedcom_id') 2850c0910bfSGreg Roach ->groupBy(['gedcom_id']) 286eb8ab1e1SGreg Roach ->pluck(new Expression('COUNT(s_id) AS aggregate'), 'gedcom_id') 2870c0910bfSGreg Roach ->map(static function (string $count) { 2880c0910bfSGreg Roach return (int) $count; 2890c0910bfSGreg Roach }); 2900c0910bfSGreg Roach } 2910c0910bfSGreg Roach 2920c0910bfSGreg Roach /** 2930c0910bfSGreg Roach * Count the number of media objects in each tree. 2940c0910bfSGreg Roach * 29536779af1SGreg Roach * @return Collection<int,int> 2960c0910bfSGreg Roach */ 2970c0910bfSGreg Roach private function totalMediaObjects(): Collection 2980c0910bfSGreg Roach { 2990c0910bfSGreg Roach return DB::table('gedcom') 3000c0910bfSGreg Roach ->leftJoin('media', 'm_file', '=', 'gedcom_id') 3010c0910bfSGreg Roach ->groupBy(['gedcom_id']) 302eb8ab1e1SGreg Roach ->pluck(new Expression('COUNT(m_id) AS aggregate'), 'gedcom_id') 3030c0910bfSGreg Roach ->map(static function (string $count) { 3040c0910bfSGreg Roach return (int) $count; 3050c0910bfSGreg Roach }); 3060c0910bfSGreg Roach } 3070c0910bfSGreg Roach 3080c0910bfSGreg Roach /** 30936779af1SGreg Roach * Count the number of repositories in each tree. 3100c0910bfSGreg Roach * 31136779af1SGreg Roach * @return Collection<int,int> 3120c0910bfSGreg Roach */ 3130c0910bfSGreg Roach private function totalRepositories(): Collection 3140c0910bfSGreg Roach { 3150c0910bfSGreg Roach return DB::table('gedcom') 3160c0910bfSGreg Roach ->leftJoin('other', static function (JoinClause $join): void { 3170c0910bfSGreg Roach $join 3180c0910bfSGreg Roach ->on('o_file', '=', 'gedcom_id') 319e72c24d6SGreg Roach ->where('o_type', '=', Repository::RECORD_TYPE); 3200c0910bfSGreg Roach }) 3210c0910bfSGreg Roach ->groupBy(['gedcom_id']) 322eb8ab1e1SGreg Roach ->pluck(new Expression('COUNT(o_id) AS aggregate'), 'gedcom_id') 3230c0910bfSGreg Roach ->map(static function (string $count) { 3240c0910bfSGreg Roach return (int) $count; 3250c0910bfSGreg Roach }); 3260c0910bfSGreg Roach } 3270c0910bfSGreg Roach 3280c0910bfSGreg Roach /** 3290c0910bfSGreg Roach * Count the number of notes in each tree. 3300c0910bfSGreg Roach * 33136779af1SGreg Roach * @return Collection<int,int> 3320c0910bfSGreg Roach */ 3330c0910bfSGreg Roach private function totalNotes(): Collection 3340c0910bfSGreg Roach { 3350c0910bfSGreg Roach return DB::table('gedcom') 3360c0910bfSGreg Roach ->leftJoin('other', static function (JoinClause $join): void { 3370c0910bfSGreg Roach $join 3380c0910bfSGreg Roach ->on('o_file', '=', 'gedcom_id') 339e72c24d6SGreg Roach ->where('o_type', '=', Note::RECORD_TYPE); 340e72c24d6SGreg Roach }) 341e72c24d6SGreg Roach ->groupBy(['gedcom_id']) 342eb8ab1e1SGreg Roach ->pluck(new Expression('COUNT(o_id) AS aggregate'), 'gedcom_id') 343e72c24d6SGreg Roach ->map(static function (string $count) { 344e72c24d6SGreg Roach return (int) $count; 345e72c24d6SGreg Roach }); 346e72c24d6SGreg Roach } 347e72c24d6SGreg Roach 348e72c24d6SGreg Roach /** 349e72c24d6SGreg Roach * Count the number of submitters in each tree. 350e72c24d6SGreg Roach * 35136779af1SGreg Roach * @return Collection<int,int> 352e72c24d6SGreg Roach */ 353e72c24d6SGreg Roach private function totalSubmitters(): Collection 354e72c24d6SGreg Roach { 355e72c24d6SGreg Roach return DB::table('gedcom') 356e72c24d6SGreg Roach ->leftJoin('other', static function (JoinClause $join): void { 357e72c24d6SGreg Roach $join 358e72c24d6SGreg Roach ->on('o_file', '=', 'gedcom_id') 359e72c24d6SGreg Roach ->where('o_type', '=', Submitter::RECORD_TYPE); 3600c0910bfSGreg Roach }) 3610c0910bfSGreg Roach ->groupBy(['gedcom_id']) 362eb8ab1e1SGreg Roach ->pluck(new Expression('COUNT(o_id) AS aggregate'), 'gedcom_id') 3630c0910bfSGreg Roach ->map(static function (string $count) { 3640c0910bfSGreg Roach return (int) $count; 3650c0910bfSGreg Roach }); 3660c0910bfSGreg Roach } 3670c0910bfSGreg Roach} 368