14991f205SGreg Roach<?php 24991f205SGreg Roach 34991f205SGreg Roach/** 44991f205SGreg Roach * webtrees: online genealogy 5*5bfc6897SGreg Roach * Copyright (C) 2022 webtrees development team 64991f205SGreg Roach * This program is free software: you can redistribute it and/or modify 74991f205SGreg Roach * it under the terms of the GNU General Public License as published by 84991f205SGreg Roach * the Free Software Foundation, either version 3 of the License, or 94991f205SGreg Roach * (at your option) any later version. 104991f205SGreg Roach * This program is distributed in the hope that it will be useful, 114991f205SGreg Roach * but WITHOUT ANY WARRANTY; without even the implied warranty of 124991f205SGreg Roach * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 134991f205SGreg Roach * GNU General Public License for more details. 144991f205SGreg Roach * You should have received a copy of the GNU General Public License 154991f205SGreg Roach * along with this program. If not, see <https://www.gnu.org/licenses/>. 164991f205SGreg Roach */ 174991f205SGreg Roach 184991f205SGreg Roachdeclare(strict_types=1); 194991f205SGreg Roach 204991f205SGreg Roachnamespace Fisharebest\Webtrees\Services; 214991f205SGreg Roach 224991f205SGreg Roachuse Fisharebest\Webtrees\Family; 234991f205SGreg Roachuse Fisharebest\Webtrees\GedcomRecord; 244991f205SGreg Roachuse Fisharebest\Webtrees\Individual; 254991f205SGreg Roachuse Fisharebest\Webtrees\Location; 264991f205SGreg Roachuse Fisharebest\Webtrees\Media; 274991f205SGreg Roachuse Fisharebest\Webtrees\Note; 284991f205SGreg Roachuse Fisharebest\Webtrees\Registry; 294991f205SGreg Roachuse Fisharebest\Webtrees\Repository; 304991f205SGreg Roachuse Fisharebest\Webtrees\Source; 314991f205SGreg Roachuse Fisharebest\Webtrees\Submitter; 324991f205SGreg Roachuse Illuminate\Database\Capsule\Manager as DB; 334991f205SGreg Roachuse Illuminate\Database\Query\Builder; 344991f205SGreg Roachuse Illuminate\Database\Query\Expression; 354991f205SGreg Roachuse Illuminate\Database\Query\JoinClause; 364991f205SGreg Roachuse Illuminate\Support\Collection; 374991f205SGreg Roach 384991f205SGreg Roachuse function addcslashes; 394991f205SGreg Roachuse function assert; 404991f205SGreg Roach 414991f205SGreg Roach/** 424991f205SGreg Roach * Find records linked to other records 434991f205SGreg Roach */ 444991f205SGreg Roachclass LinkedRecordService 454991f205SGreg Roach{ 464991f205SGreg Roach /** 474991f205SGreg Roach * Find all records linked to a record. 484991f205SGreg Roach * 494991f205SGreg Roach * @param GedcomRecord $record 504991f205SGreg Roach * 514991f205SGreg Roach * @return Collection<int,Family> 524991f205SGreg Roach */ 534991f205SGreg Roach public function allLinkedRecords(GedcomRecord $record): Collection 544991f205SGreg Roach { 554991f205SGreg Roach $like = addcslashes($record->xref(), '\\%_'); 564991f205SGreg Roach 574991f205SGreg Roach $union = DB::table('change') 584991f205SGreg Roach ->where('gedcom_id', '=', $record->tree()->id()) 594991f205SGreg Roach ->where('new_gedcom', 'LIKE', '%@' . $like . '@%') 604991f205SGreg Roach ->where('new_gedcom', 'NOT LIKE', '0 @' . $like . '@%') 614991f205SGreg Roach ->whereIn('change_id', function (Builder $query) use ($record): void { 624991f205SGreg Roach $query 634991f205SGreg Roach ->select(new Expression('MAX(change_id)')) 644991f205SGreg Roach ->from('change') 654991f205SGreg Roach ->where('gedcom_id', '=', $record->tree()->id()) 664991f205SGreg Roach ->where('status', '=', 'pending') 674991f205SGreg Roach ->groupBy(['xref']); 684991f205SGreg Roach }) 694991f205SGreg Roach ->select(['xref']); 704991f205SGreg Roach 714991f205SGreg Roach $xrefs = DB::table('link') 724991f205SGreg Roach ->where('l_file', '=', $record->tree()->id()) 734991f205SGreg Roach ->where('l_to', '=', $record->xref()) 744991f205SGreg Roach ->select(['l_from']) 754991f205SGreg Roach ->union($union) 764991f205SGreg Roach ->pluck('l_from'); 774991f205SGreg Roach 784991f205SGreg Roach return $xrefs->map(static fn (string $xref) => Registry::gedcomRecordFactory()->make($xref, $record->tree())); 794991f205SGreg Roach } 804991f205SGreg Roach 814991f205SGreg Roach /** 824991f205SGreg Roach * Find families linked to a record. 834991f205SGreg Roach * 844991f205SGreg Roach * @param GedcomRecord $record 854991f205SGreg Roach * @param string|null $link_type 864991f205SGreg Roach * 874991f205SGreg Roach * @return Collection<int,Family> 884991f205SGreg Roach */ 894991f205SGreg Roach public function linkedFamilies(GedcomRecord $record, string $link_type = null): Collection 904991f205SGreg Roach { 914991f205SGreg Roach $query = DB::table('families') 924991f205SGreg Roach ->join('link', static function (JoinClause $join): void { 934991f205SGreg Roach $join 944991f205SGreg Roach ->on('l_file', '=', 'f_file') 954991f205SGreg Roach ->on('l_from', '=', 'f_id'); 964991f205SGreg Roach }) 974991f205SGreg Roach ->where('f_file', '=', $record->tree()->id()) 984991f205SGreg Roach ->where('l_to', '=', $record->xref()); 994991f205SGreg Roach 1004991f205SGreg Roach if ($link_type !== null) { 1014991f205SGreg Roach $query->where('l_type', '=', $link_type); 1024991f205SGreg Roach } 1034991f205SGreg Roach 1044991f205SGreg Roach return $query 1054991f205SGreg Roach ->select(['families.*']) 1064991f205SGreg Roach ->get() 1074991f205SGreg Roach ->map(Registry::familyFactory()->mapper($record->tree())) 1084991f205SGreg Roach ->filter(GedcomRecord::accessFilter()); 1094991f205SGreg Roach } 1104991f205SGreg Roach 1114991f205SGreg Roach /** 1124991f205SGreg Roach * Find individuals linked to a record. 1134991f205SGreg Roach * 1144991f205SGreg Roach * @param GedcomRecord $record 1154991f205SGreg Roach * 1164991f205SGreg Roach * @return Collection<int,Individual> 1174991f205SGreg Roach */ 1184991f205SGreg Roach public function linkedIndividuals(GedcomRecord $record, string $link_type = null): Collection 1194991f205SGreg Roach { 1204991f205SGreg Roach $query = DB::table('individuals') 1214991f205SGreg Roach ->join('link', static function (JoinClause $join): void { 1224991f205SGreg Roach $join 1234991f205SGreg Roach ->on('l_file', '=', 'i_file') 1244991f205SGreg Roach ->on('l_from', '=', 'i_id'); 1254991f205SGreg Roach }) 1264991f205SGreg Roach ->where('i_file', '=', $record->tree()->id()) 1274991f205SGreg Roach ->where('l_to', '=', $record->xref()); 1284991f205SGreg Roach 1294991f205SGreg Roach if ($link_type !== null) { 1304991f205SGreg Roach $query->where('l_type', '=', $link_type); 1314991f205SGreg Roach } 1324991f205SGreg Roach 1334991f205SGreg Roach return $query 1344991f205SGreg Roach ->select(['individuals.*']) 1354991f205SGreg Roach ->get() 1364991f205SGreg Roach ->map(Registry::individualFactory()->mapper($record->tree())) 1374991f205SGreg Roach ->filter(GedcomRecord::accessFilter()); 1384991f205SGreg Roach } 1394991f205SGreg Roach 1404991f205SGreg Roach /** 1414991f205SGreg Roach * Find locations linked to a record. 1424991f205SGreg Roach * 1434991f205SGreg Roach * @param GedcomRecord $record 1444991f205SGreg Roach * 1454991f205SGreg Roach * @return Collection<int,Location> 1464991f205SGreg Roach */ 1474991f205SGreg Roach public function linkedLocations(GedcomRecord $record): Collection 1484991f205SGreg Roach { 1494991f205SGreg Roach return DB::table('other') 1504991f205SGreg Roach ->join('link', static function (JoinClause $join): void { 1514991f205SGreg Roach $join 1524991f205SGreg Roach ->on('l_file', '=', 'o_file') 1534991f205SGreg Roach ->on('l_from', '=', 'o_id'); 1544991f205SGreg Roach }) 1554991f205SGreg Roach ->where('o_file', '=', $record->tree()->id()) 1564991f205SGreg Roach ->where('o_type', '=', Location::RECORD_TYPE) 1574991f205SGreg Roach ->where('l_to', '=', $record->xref()) 1584991f205SGreg Roach ->select(['other.*']) 1594991f205SGreg Roach ->get() 1604991f205SGreg Roach ->map(Registry::locationFactory()->mapper($record->tree())) 1614991f205SGreg Roach ->filter(GedcomRecord::accessFilter()); 1624991f205SGreg Roach } 1634991f205SGreg Roach 1644991f205SGreg Roach /** 1654991f205SGreg Roach * Find media objects linked to a record. 1664991f205SGreg Roach * 1674991f205SGreg Roach * @param GedcomRecord $record 1684991f205SGreg Roach * 1694991f205SGreg Roach * @return Collection<int,Media> 1704991f205SGreg Roach */ 1714991f205SGreg Roach public function linkedMedia(GedcomRecord $record): Collection 1724991f205SGreg Roach { 1734991f205SGreg Roach return DB::table('media') 1744991f205SGreg Roach ->join('link', static function (JoinClause $join): void { 1754991f205SGreg Roach $join 1764991f205SGreg Roach ->on('l_file', '=', 'm_file') 1774991f205SGreg Roach ->on('l_from', '=', 'm_id'); 1784991f205SGreg Roach }) 1794991f205SGreg Roach ->where('m_file', '=', $record->tree()->id()) 1804991f205SGreg Roach ->where('l_to', '=', $record->xref()) 1814991f205SGreg Roach ->select(['media.*']) 1824991f205SGreg Roach ->get() 1834991f205SGreg Roach ->map(Registry::mediaFactory()->mapper($record->tree())) 1844991f205SGreg Roach ->filter(GedcomRecord::accessFilter()); 1854991f205SGreg Roach } 1864991f205SGreg Roach 1874991f205SGreg Roach /** 1884991f205SGreg Roach * Find notes linked to a record. 1894991f205SGreg Roach * 1904991f205SGreg Roach * @param GedcomRecord $record 1914991f205SGreg Roach * 1924991f205SGreg Roach * @return Collection<int,Note> 1934991f205SGreg Roach */ 1944991f205SGreg Roach public function linkedNotes(GedcomRecord $record): Collection 1954991f205SGreg Roach { 1964991f205SGreg Roach return DB::table('other') 1974991f205SGreg Roach ->join('link', static function (JoinClause $join): void { 1984991f205SGreg Roach $join 1994991f205SGreg Roach ->on('l_file', '=', 'o_file') 2004991f205SGreg Roach ->on('l_from', '=', 'o_id'); 2014991f205SGreg Roach }) 2024991f205SGreg Roach ->where('o_file', '=', $record->tree()->id()) 2034991f205SGreg Roach ->where('o_type', '=', Note::RECORD_TYPE) 2044991f205SGreg Roach ->where('l_to', '=', $record->xref()) 2054991f205SGreg Roach ->select(['other.*']) 2064991f205SGreg Roach ->get() 2074991f205SGreg Roach ->map(Registry::noteFactory()->mapper($record->tree())) 2084991f205SGreg Roach ->filter(GedcomRecord::accessFilter()); 2094991f205SGreg Roach } 2104991f205SGreg Roach 2114991f205SGreg Roach /** 2124991f205SGreg Roach * Find repositories linked to a record. 2134991f205SGreg Roach * 2144991f205SGreg Roach * @param GedcomRecord $record 2154991f205SGreg Roach * 2164991f205SGreg Roach * @return Collection<int,Repository> 2174991f205SGreg Roach */ 2184991f205SGreg Roach public function linkedRepositories(GedcomRecord $record): Collection 2194991f205SGreg Roach { 2204991f205SGreg Roach return DB::table('other') 2214991f205SGreg Roach ->join('link', static function (JoinClause $join): void { 2224991f205SGreg Roach $join 2234991f205SGreg Roach ->on('l_file', '=', 'o_file') 2244991f205SGreg Roach ->on('l_from', '=', 'o_id'); 2254991f205SGreg Roach }) 2264991f205SGreg Roach ->where('o_file', '=', $record->tree()->id()) 2274991f205SGreg Roach ->where('o_type', '=', Repository::RECORD_TYPE) 2284991f205SGreg Roach ->where('l_to', '=', $record->xref()) 2294991f205SGreg Roach ->select(['other.*']) 2304991f205SGreg Roach ->get() 2314991f205SGreg Roach ->map(Registry::repositoryFactory()->mapper($record->tree())) 2324991f205SGreg Roach ->filter(GedcomRecord::accessFilter()); 2334991f205SGreg Roach } 2344991f205SGreg Roach 2354991f205SGreg Roach /** 2364991f205SGreg Roach * Find sources linked to a record. 2374991f205SGreg Roach * 2384991f205SGreg Roach * @param GedcomRecord $record 2394991f205SGreg Roach * 2404991f205SGreg Roach * @return Collection<int,Source> 2414991f205SGreg Roach */ 2424991f205SGreg Roach public function linkedSources(GedcomRecord $record): Collection 2434991f205SGreg Roach { 2444991f205SGreg Roach return DB::table('sources') 2454991f205SGreg Roach ->join('link', static function (JoinClause $join): void { 2464991f205SGreg Roach $join 2474991f205SGreg Roach ->on('l_file', '=', 's_file') 2484991f205SGreg Roach ->on('l_from', '=', 's_id'); 2494991f205SGreg Roach }) 2504991f205SGreg Roach ->where('s_file', '=', $record->tree()->id()) 2514991f205SGreg Roach ->where('l_to', '=', $record->xref()) 2524991f205SGreg Roach ->select(['sources.*']) 2534991f205SGreg Roach ->get() 2544991f205SGreg Roach ->map(Registry::sourceFactory()->mapper($record->tree())) 2554991f205SGreg Roach ->filter(GedcomRecord::accessFilter()); 2564991f205SGreg Roach } 2574991f205SGreg Roach 2584991f205SGreg Roach /** 2594991f205SGreg Roach * Find submitters linked to a record. 2604991f205SGreg Roach * 2614991f205SGreg Roach * @param GedcomRecord $record 2624991f205SGreg Roach * 2634991f205SGreg Roach * @return Collection<int,Repository> 2644991f205SGreg Roach */ 2654991f205SGreg Roach public function linkedSubmitters(GedcomRecord $record): Collection 2664991f205SGreg Roach { 2674991f205SGreg Roach return DB::table('other') 2684991f205SGreg Roach ->join('link', static function (JoinClause $join): void { 2694991f205SGreg Roach $join 2704991f205SGreg Roach ->on('l_file', '=', 'o_file') 2714991f205SGreg Roach ->on('l_from', '=', 'o_id'); 2724991f205SGreg Roach }) 2734991f205SGreg Roach ->where('o_file', '=', $record->tree()->id()) 2744991f205SGreg Roach ->where('o_type', '=', Submitter::RECORD_TYPE) 2754991f205SGreg Roach ->where('l_to', '=', $record->xref()) 2764991f205SGreg Roach ->select(['other.*']) 2774991f205SGreg Roach ->get() 2784991f205SGreg Roach ->map(Registry::repositoryFactory()->mapper($record->tree())) 2794991f205SGreg Roach ->filter(GedcomRecord::accessFilter()); 2804991f205SGreg Roach } 2814991f205SGreg Roach} 282