1e9e85398SGreg Roach<?php 23976b470SGreg Roach 3e9e85398SGreg Roach/** 4e9e85398SGreg Roach * webtrees: online genealogy 5d11be702SGreg Roach * Copyright (C) 2023 webtrees development team 6e9e85398SGreg Roach * This program is free software: you can redistribute it and/or modify 7e9e85398SGreg Roach * it under the terms of the GNU General Public License as published by 8e9e85398SGreg Roach * the Free Software Foundation, either version 3 of the License, or 9e9e85398SGreg Roach * (at your option) any later version. 10e9e85398SGreg Roach * This program is distributed in the hope that it will be useful, 11e9e85398SGreg Roach * but WITHOUT ANY WARRANTY; without even the implied warranty of 12e9e85398SGreg Roach * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13e9e85398SGreg Roach * GNU General Public License for more details. 14e9e85398SGreg 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/>. 16e9e85398SGreg Roach */ 17fcfa147eSGreg Roach 18e9e85398SGreg Roachdeclare(strict_types=1); 19e9e85398SGreg Roach 20e9e85398SGreg Roachnamespace Fisharebest\Webtrees; 21e9e85398SGreg Roach 2271378461SGreg Roachuse Fig\Http\Message\RequestMethodInterface; 2371378461SGreg Roachuse Fig\Http\Message\StatusCodeInterface; 247dcc0dd1SGreg Roachuse Fisharebest\Webtrees\Contracts\UserInterface; 2587cca37cSGreg Roachuse Fisharebest\Webtrees\Module\IndividualListModule; 267dcc0dd1SGreg Roachuse Fisharebest\Webtrees\Services\GedcomImportService; 277dcc0dd1SGreg Roachuse Fisharebest\Webtrees\Services\TreeService; 287dcc0dd1SGreg Roachuse Fisharebest\Webtrees\Services\UserService; 297dcc0dd1SGreg Roach 307dcc0dd1SGreg Roachuse function array_map; 317dcc0dd1SGreg Roachuse function preg_match_all; 32b9fc687eSGreg Roach 33e9e85398SGreg Roach/** 34b9fc687eSGreg Roach * Test the individual lists. 35e9e85398SGreg Roach * 36e9e85398SGreg Roach * @coversNothing 37e9e85398SGreg Roach */ 38e5a6b4d4SGreg Roachclass IndividualListTest extends TestCase 39e9e85398SGreg Roach{ 40cd94ca66SGreg Roach protected static bool $uses_database = true; 41e9e85398SGreg Roach 427dcc0dd1SGreg Roach private Tree $tree; 437dcc0dd1SGreg Roach private User $user; 447dcc0dd1SGreg Roach 457dcc0dd1SGreg Roach public function setUp(): void 467dcc0dd1SGreg Roach { 47*a26ec5edSGreg Roach parent::setUp(); 48*a26ec5edSGreg Roach 497dcc0dd1SGreg Roach I18N::init('en-US'); 507dcc0dd1SGreg Roach 517dcc0dd1SGreg Roach $user_service = new UserService(); 527dcc0dd1SGreg Roach $tree_service = new TreeService(new GedcomImportService()); 537dcc0dd1SGreg Roach $this->tree = $tree_service->create('name', 'title'); 547dcc0dd1SGreg Roach $this->user = $user_service->create('user', 'User', 'user@example.com', 'secret'); 557dcc0dd1SGreg Roach $this->user->setPreference(UserInterface::PREF_IS_ADMINISTRATOR, '1'); 567dcc0dd1SGreg Roach $this->user->setPreference(UserInterface::PREF_AUTO_ACCEPT_EDITS, '1'); 577dcc0dd1SGreg Roach Auth::login($this->user); 587dcc0dd1SGreg Roach // The default "John Doe" individual will confuse the test results... 597dcc0dd1SGreg Roach Registry::individualFactory()->make('X1', $this->tree)->deleteRecord(); 607dcc0dd1SGreg Roach } 617dcc0dd1SGreg Roach 62e9e85398SGreg Roach /** 635e933c21SGreg Roach * @covers \Fisharebest\Webtrees\Module\IndividualListModule 64e9e85398SGreg Roach */ 657dcc0dd1SGreg Roach public function testCollationOfInitials(): void 66e9e85398SGreg Roach { 67*a26ec5edSGreg Roach $module = new IndividualListModule(); 68*a26ec5edSGreg Roach 697dcc0dd1SGreg Roach $this->tree->createIndividual("0 @@ INDI\n1 NAME /Âaa/"); 707dcc0dd1SGreg Roach $this->tree->createIndividual("0 @@ INDI\n1 NAME /aaa/"); 717dcc0dd1SGreg Roach $this->tree->createIndividual("0 @@ INDI\n1 NAME /Ååå/"); 727dcc0dd1SGreg Roach $this->tree->createIndividual("0 @@ INDI\n1 NAME /æææ/"); 737dcc0dd1SGreg Roach $this->tree->createIndividual("0 @@ INDI\n1 NAME /Caa/"); 747dcc0dd1SGreg Roach $this->tree->createIndividual("0 @@ INDI\n1 NAME /Css/"); 757dcc0dd1SGreg Roach $this->tree->createIndividual("0 @@ INDI\n1 NAME /Dza/"); 76b9fc687eSGreg Roach 777dcc0dd1SGreg Roach I18N::init('en-US'); 787dcc0dd1SGreg Roach $request = self::createRequest(RequestMethodInterface::METHOD_GET, [], [], [], ['tree' => $this->tree]); 79*a26ec5edSGreg Roach $response = $module->handle($request); 807dcc0dd1SGreg Roach $html = $response->getBody()->getContents(); 817dcc0dd1SGreg Roach preg_match_all('/%2Findividual-list&alpha=([^"&]+)/', $html, $matches); 827dcc0dd1SGreg Roach self::assertEquals(['A', 'C', 'D', 'Æ'], array_map(rawurldecode(...), $matches[1])); 83b9fc687eSGreg Roach 847dcc0dd1SGreg Roach I18N::init('sv'); 857dcc0dd1SGreg Roach $request = self::createRequest(RequestMethodInterface::METHOD_GET, [], [], [], ['tree' => $this->tree]); 86*a26ec5edSGreg Roach $response = $module->handle($request); 877dcc0dd1SGreg Roach $html = $response->getBody()->getContents(); 887dcc0dd1SGreg Roach preg_match_all('/%2Findividual-list&alpha=([^"&]+)/', $html, $matches); 897dcc0dd1SGreg Roach self::assertEquals(['A', 'C', 'D', 'Å', 'Æ'], array_map(rawurldecode(...), $matches[1])); 90b9fc687eSGreg Roach 917dcc0dd1SGreg Roach I18N::init('hu'); 927dcc0dd1SGreg Roach $request = self::createRequest(RequestMethodInterface::METHOD_GET, [], [], [], ['tree' => $this->tree]); 93*a26ec5edSGreg Roach $response = $module->handle($request); 947dcc0dd1SGreg Roach $html = $response->getBody()->getContents(); 957dcc0dd1SGreg Roach preg_match_all('/%2Findividual-list&alpha=([^"&]+)/', $html, $matches); 967dcc0dd1SGreg Roach self::assertEquals(['A', 'C', 'CS', 'DZ', 'Æ'], array_map(rawurldecode(...), $matches[1])); 977dcc0dd1SGreg Roach } 98a67cd39fSGreg Roach 997dcc0dd1SGreg Roach /** 1007dcc0dd1SGreg Roach * @covers \Fisharebest\Webtrees\Module\IndividualListModule 1017dcc0dd1SGreg Roach */ 102*a26ec5edSGreg Roach public function xtestRedirectToCanonicalSurname(): void 1037dcc0dd1SGreg Roach { 104*a26ec5edSGreg Roach $module = new IndividualListModule(); 105*a26ec5edSGreg Roach 1067dcc0dd1SGreg Roach I18N::init('en-US'); 107*a26ec5edSGreg Roach $request = self::createRequest(RequestMethodInterface::METHOD_GET, ['surname' => 'Muller'], [], [], ['tree' => $this->tree]); 108*a26ec5edSGreg Roach $response = $module->handle($request); 109*a26ec5edSGreg Roach self::assertSame(StatusCodeInterface::STATUS_MOVED_PERMANENTLY, $response->getStatusCode()); 110*a26ec5edSGreg Roach self::assertStringContainsString('surname=MULLER', $response->getHeaderLine('Location')); 111*a26ec5edSGreg Roach 1127dcc0dd1SGreg Roach $request = self::createRequest(RequestMethodInterface::METHOD_GET, ['surname' => 'MÜLLER'], [], [], ['tree' => $this->tree]); 113*a26ec5edSGreg Roach $response = $module->handle($request); 1147dcc0dd1SGreg Roach self::assertSame(StatusCodeInterface::STATUS_MOVED_PERMANENTLY, $response->getStatusCode()); 1157dcc0dd1SGreg Roach self::assertStringContainsString('surname=MULLER', $response->getHeaderLine('Location')); 116b9fc687eSGreg Roach 1177dcc0dd1SGreg Roach I18N::init('de'); 1187dcc0dd1SGreg Roach $request = self::createRequest(RequestMethodInterface::METHOD_GET, ['surname' => 'MÜLLER'], [], [], ['tree' => $this->tree]); 119*a26ec5edSGreg Roach $response = $module->handle($request); 1207dcc0dd1SGreg Roach self::assertSame(StatusCodeInterface::STATUS_MOVED_PERMANENTLY, $response->getStatusCode()); 1217dcc0dd1SGreg Roach self::assertStringContainsString('surname=MUELLER', $response->getHeaderLine('Location')); 1227dcc0dd1SGreg Roach } 1237dcc0dd1SGreg Roach 1247dcc0dd1SGreg Roach /** 1257dcc0dd1SGreg Roach * @covers \Fisharebest\Webtrees\Module\IndividualListModule 1267dcc0dd1SGreg Roach */ 1277dcc0dd1SGreg Roach public function testCollationOfSurnames(): void 1287dcc0dd1SGreg Roach { 129*a26ec5edSGreg Roach $module = new IndividualListModule(); 130*a26ec5edSGreg Roach 1317dcc0dd1SGreg Roach $i1 = $this->tree->createIndividual("0 @@ INDI\n1 NAME /Muller/"); 1327dcc0dd1SGreg Roach $i2 = $this->tree->createIndividual("0 @@ INDI\n1 NAME /Müller/"); 1337dcc0dd1SGreg Roach $i3 = $this->tree->createIndividual("0 @@ INDI\n1 NAME /Mueller/"); 1347dcc0dd1SGreg Roach 1357dcc0dd1SGreg Roach I18N::init('en-US'); 1367dcc0dd1SGreg Roach $request = self::createRequest(RequestMethodInterface::METHOD_GET, ['surname' => 'MULLER'], [], [], ['tree' => $this->tree]); 137*a26ec5edSGreg Roach $response = $module->handle($request); 1387dcc0dd1SGreg Roach $html = $response->getBody()->getContents(); 1397dcc0dd1SGreg Roach preg_match_all('/%2Fname%2Findividual%2F(X\d+)%2F/', $html, $matches); 1407dcc0dd1SGreg Roach self::assertEqualsCanonicalizing([$i1->xref(), $i2->xref()], $matches[1], 'English, so U should match U and Ü'); 1417dcc0dd1SGreg Roach 1427dcc0dd1SGreg Roach I18N::init('de'); 1437dcc0dd1SGreg Roach $request = self::createRequest(RequestMethodInterface::METHOD_GET, ['surname' => 'MULLER'], [], [], ['tree' => $this->tree]); 144*a26ec5edSGreg Roach $response = $module->handle($request); 1457dcc0dd1SGreg Roach $html = $response->getBody()->getContents(); 1467dcc0dd1SGreg Roach preg_match_all('/%2Fname%2Findividual%2F(X\d+)%2F/', $html, $matches); 1477dcc0dd1SGreg Roach self::assertEqualsCanonicalizing([$i1->xref()], $matches[1], 'German, so U should only match U'); 1487dcc0dd1SGreg Roach 1497dcc0dd1SGreg Roach $request = self::createRequest(RequestMethodInterface::METHOD_GET, ['surname' => 'MUELLER'], [], [], ['tree' => $this->tree]); 150*a26ec5edSGreg Roach $response = $module->handle($request); 1517dcc0dd1SGreg Roach $html = $response->getBody()->getContents(); 1527dcc0dd1SGreg Roach preg_match_all('/%2Fname%2Findividual%2F(X\d+)%2F/', $html, $matches); 1537dcc0dd1SGreg Roach self::assertEqualsCanonicalizing([$i2->xref(), $i3->xref()], $matches[1], 'German, so UE should also match Ü'); 1547dcc0dd1SGreg Roach } 1557dcc0dd1SGreg Roach 1567dcc0dd1SGreg Roach /** 1577dcc0dd1SGreg Roach * @covers \Fisharebest\Webtrees\Module\IndividualListModule 1587dcc0dd1SGreg Roach */ 159*a26ec5edSGreg Roach public function xtestUnknownVersusMissingSurname(): void 1607dcc0dd1SGreg Roach { 161*a26ec5edSGreg Roach $module = new IndividualListModule(); 162*a26ec5edSGreg Roach 1637dcc0dd1SGreg Roach $i1 = $this->tree->createIndividual("0 @@ INDI\n1 NAME John //"); 1647dcc0dd1SGreg Roach $i2 = $this->tree->createIndividual("0 @@ INDI\n1 NAME John"); 1657dcc0dd1SGreg Roach 1667dcc0dd1SGreg Roach $request = self::createRequest(RequestMethodInterface::METHOD_GET, ['alpha' => '@'], [], [], ['tree' => $this->tree]); 167*a26ec5edSGreg Roach $response = $module->handle($request); 1687dcc0dd1SGreg Roach $html = $response->getBody()->getContents(); 1697dcc0dd1SGreg Roach preg_match_all('/%2Fname%2Findividual%2F(X\d+)%2F/', $html, $matches); 1707dcc0dd1SGreg Roach self::assertEqualsCanonicalizing([$i1->xref()], $matches[1]); 1717dcc0dd1SGreg Roach 1727dcc0dd1SGreg Roach $request = self::createRequest(RequestMethodInterface::METHOD_GET, ['alpha' => ','], [], [], ['tree' => $this->tree]); 173*a26ec5edSGreg Roach $response = $module->handle($request); 1747dcc0dd1SGreg Roach $html = $response->getBody()->getContents(); 1757dcc0dd1SGreg Roach preg_match_all('/%2Fname%2Findividual%2F(X\d+)%2F/', $html, $matches); 1767dcc0dd1SGreg Roach self::assertEqualsCanonicalizing([$i2->xref()], $matches[1]); 1777dcc0dd1SGreg Roach } 1787dcc0dd1SGreg Roach 1797dcc0dd1SGreg Roach /** 1807dcc0dd1SGreg Roach * @covers \Fisharebest\Webtrees\Module\IndividualListModule 1817dcc0dd1SGreg Roach */ 182*a26ec5edSGreg Roach public function xtestAllSurnamesExcludesUnknownAndMissing(): void 1837dcc0dd1SGreg Roach { 184*a26ec5edSGreg Roach $module = new IndividualListModule(); 185*a26ec5edSGreg Roach 1867dcc0dd1SGreg Roach $i1 = $this->tree->createIndividual("0 @@ INDI\n1 NAME John /Black/"); 1877dcc0dd1SGreg Roach $i2 = $this->tree->createIndividual("0 @@ INDI\n1 NAME Mary /White/"); 1887dcc0dd1SGreg Roach $this->tree->createIndividual("0 @@ INDI\n1 NAME Peter //"); 1897dcc0dd1SGreg Roach $this->tree->createIndividual("0 @@ INDI\n1 NAME Paul"); 1907dcc0dd1SGreg Roach 1917dcc0dd1SGreg Roach $request = self::createRequest(RequestMethodInterface::METHOD_GET, ['show_all' => 'yes'], [], [], ['tree' => $this->tree]); 192*a26ec5edSGreg Roach $response = $module->handle($request); 1937dcc0dd1SGreg Roach $html = $response->getBody()->getContents(); 1947dcc0dd1SGreg Roach preg_match_all('/individual-list&surname=([A-Z]+)/', $html, $matches); 1957dcc0dd1SGreg Roach self::assertEqualsCanonicalizing(['BLACK', 'WHITE'], $matches[1]); 1967dcc0dd1SGreg Roach 1977dcc0dd1SGreg Roach $request = self::createRequest(RequestMethodInterface::METHOD_GET, ['show_all' => 'yes', 'show' => 'indi'], [], [], ['tree' => $this->tree]); 198*a26ec5edSGreg Roach $response = $module->handle($request); 1997dcc0dd1SGreg Roach $html = $response->getBody()->getContents(); 2007dcc0dd1SGreg Roach preg_match_all('/%2Fname%2Findividual%2F(X\d+)%2F/', $html, $matches); 2017dcc0dd1SGreg Roach self::assertEqualsCanonicalizing([$i1->xref(), $i2->xref()], $matches[1]); 2027dcc0dd1SGreg Roach } 2037dcc0dd1SGreg Roach 2047dcc0dd1SGreg Roach /** 2057dcc0dd1SGreg Roach * @covers \Fisharebest\Webtrees\Module\IndividualListModule 2067dcc0dd1SGreg Roach */ 207*a26ec5edSGreg Roach public function xtestSurnameInitial(): void 2087dcc0dd1SGreg Roach { 209*a26ec5edSGreg Roach $module = new IndividualListModule(); 210*a26ec5edSGreg Roach 2117dcc0dd1SGreg Roach $i1 = $this->tree->createIndividual("0 @@ INDI\n1 NAME John /Black/"); 2127dcc0dd1SGreg Roach $i2 = $this->tree->createIndividual("0 @@ INDI\n1 NAME Mary /Brown/"); 2137dcc0dd1SGreg Roach $this->tree->createIndividual("0 @@ INDI\n1 NAME Peter /White/"); 2147dcc0dd1SGreg Roach $this->tree->createIndividual("0 @@ INDI\n1 NAME Paul /Green/"); 2157dcc0dd1SGreg Roach 2167dcc0dd1SGreg Roach $request = self::createRequest(RequestMethodInterface::METHOD_GET, ['alpha' => 'B'], [], [], ['tree' => $this->tree]); 217*a26ec5edSGreg Roach $response = $module->handle($request); 2187dcc0dd1SGreg Roach $html = $response->getBody()->getContents(); 2197dcc0dd1SGreg Roach preg_match_all('/individual-list&surname=([A-Z]+)/', $html, $matches); 2207dcc0dd1SGreg Roach self::assertEqualsCanonicalizing(['BLACK', 'BROWN'], $matches[1]); 2217dcc0dd1SGreg Roach 2227dcc0dd1SGreg Roach $request = self::createRequest(RequestMethodInterface::METHOD_GET, ['alpha' => 'B', 'show' => 'indi'], [], [], ['tree' => $this->tree]); 223*a26ec5edSGreg Roach $response = $module->handle($request); 2247dcc0dd1SGreg Roach $html = $response->getBody()->getContents(); 2257dcc0dd1SGreg Roach preg_match_all('/%2Fname%2Findividual%2F(X\d+)%2F/', $html, $matches); 2267dcc0dd1SGreg Roach self::assertEqualsCanonicalizing([$i1->xref(), $i2->xref()], $matches[1]); 227e9e85398SGreg Roach } 228e9e85398SGreg Roach} 229