18c2e8227SGreg Roach<?php 23976b470SGreg Roach 38c2e8227SGreg Roach/** 48c2e8227SGreg Roach * webtrees: online genealogy 589f7189bSGreg Roach * Copyright (C) 2021 webtrees development team 68c2e8227SGreg Roach * This program is free software: you can redistribute it and/or modify 78c2e8227SGreg Roach * it under the terms of the GNU General Public License as published by 88c2e8227SGreg Roach * the Free Software Foundation, either version 3 of the License, or 98c2e8227SGreg Roach * (at your option) any later version. 108c2e8227SGreg Roach * This program is distributed in the hope that it will be useful, 118c2e8227SGreg Roach * but WITHOUT ANY WARRANTY; without even the implied warranty of 128c2e8227SGreg Roach * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 138c2e8227SGreg Roach * GNU General Public License for more details. 148c2e8227SGreg 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/>. 168c2e8227SGreg Roach */ 17fcfa147eSGreg Roach 18e7f56f2aSGreg Roachdeclare(strict_types=1); 19e7f56f2aSGreg Roach 2076692c8bSGreg Roachnamespace Fisharebest\Webtrees\Module; 2176692c8bSGreg Roach 22de2aa325SGreg Roachuse Aura\Router\Route; 230e62c4b8SGreg Roachuse Fisharebest\Webtrees\Auth; 240e62c4b8SGreg Roachuse Fisharebest\Webtrees\Family; 255a78cd34SGreg Roachuse Fisharebest\Webtrees\Gedcom; 260e62c4b8SGreg Roachuse Fisharebest\Webtrees\GedcomRecord; 27f95e0480SGreg Roachuse Fisharebest\Webtrees\Http\RequestHandlers\FamilyPage; 28f95e0480SGreg Roachuse Fisharebest\Webtrees\Http\RequestHandlers\IndividualPage; 29e8ded2caSGreg Roachuse Fisharebest\Webtrees\Http\RequestHandlers\LocationPage; 30f95e0480SGreg Roachuse Fisharebest\Webtrees\Http\RequestHandlers\MediaPage; 31f95e0480SGreg Roachuse Fisharebest\Webtrees\Http\RequestHandlers\NotePage; 32f95e0480SGreg Roachuse Fisharebest\Webtrees\Http\RequestHandlers\RepositoryPage; 33f95e0480SGreg Roachuse Fisharebest\Webtrees\Http\RequestHandlers\SourcePage; 34d45701ccSGreg Roachuse Fisharebest\Webtrees\Http\RequestHandlers\SubmitterPage; 350e62c4b8SGreg Roachuse Fisharebest\Webtrees\I18N; 360e62c4b8SGreg Roachuse Fisharebest\Webtrees\Individual; 37e8ded2caSGreg Roachuse Fisharebest\Webtrees\Location; 385a78cd34SGreg Roachuse Fisharebest\Webtrees\Media; 390e62c4b8SGreg Roachuse Fisharebest\Webtrees\Menu; 405a78cd34SGreg Roachuse Fisharebest\Webtrees\Note; 41d45701ccSGreg Roachuse Fisharebest\Webtrees\Registry; 425a78cd34SGreg Roachuse Fisharebest\Webtrees\Repository; 4369c05a6eSGreg Roachuse Fisharebest\Webtrees\Services\GedcomExportService; 44e5a6b4d4SGreg Roachuse Fisharebest\Webtrees\Services\UserService; 450e62c4b8SGreg Roachuse Fisharebest\Webtrees\Session; 465a78cd34SGreg Roachuse Fisharebest\Webtrees\Source; 47d45701ccSGreg Roachuse Fisharebest\Webtrees\Submitter; 48aee13b6dSGreg Roachuse Fisharebest\Webtrees\Tree; 4969c05a6eSGreg Roachuse Illuminate\Support\Collection; 505a78cd34SGreg Roachuse League\Flysystem\Filesystem; 51f0448b68SGreg Roachuse League\Flysystem\FilesystemException; 52f32d77e6SGreg Roachuse League\Flysystem\ZipArchive\FilesystemZipArchiveProvider; 535a78cd34SGreg Roachuse League\Flysystem\ZipArchive\ZipArchiveAdapter; 5400c45d23SGreg Roachuse Psr\Http\Message\ResponseFactoryInterface; 556ccdf4f0SGreg Roachuse Psr\Http\Message\ResponseInterface; 566ccdf4f0SGreg Roachuse Psr\Http\Message\ServerRequestInterface; 5700c45d23SGreg Roachuse Psr\Http\Message\StreamFactoryInterface; 5869c05a6eSGreg Roachuse RuntimeException; 593976b470SGreg Roach 60eb235819SGreg Roachuse function app; 61bf80ec58SGreg Roachuse function array_filter; 62bf80ec58SGreg Roachuse function array_keys; 63bf80ec58SGreg Roachuse function array_map; 64fa695506SGreg Roachuse function array_search; 655229eadeSGreg Roachuse function assert; 6669c05a6eSGreg Roachuse function fopen; 67bf80ec58SGreg Roachuse function in_array; 68ddeb3354SGreg Roachuse function is_string; 69bf80ec58SGreg Roachuse function preg_match_all; 70bf80ec58SGreg Roachuse function redirect; 7169c05a6eSGreg Roachuse function rewind; 72bf80ec58SGreg Roachuse function route; 73e5a6b4d4SGreg Roachuse function str_replace; 74fa695506SGreg Roachuse function stream_get_meta_data; 75fa695506SGreg Roachuse function tmpfile; 76fa695506SGreg Roachuse function uasort; 77d45701ccSGreg Roachuse function view; 78fa695506SGreg Roach 79fa695506SGreg Roachuse const PREG_SET_ORDER; 808c2e8227SGreg Roach 818c2e8227SGreg Roach/** 828c2e8227SGreg Roach * Class ClippingsCartModule 838c2e8227SGreg Roach */ 8437eb8894SGreg Roachclass ClippingsCartModule extends AbstractModule implements ModuleMenuInterface 85c1010edaSGreg Roach{ 8649a243cbSGreg Roach use ModuleMenuTrait; 8749a243cbSGreg Roach 8803f99a78SGreg Roach // What to add to the cart? 8903f99a78SGreg Roach private const ADD_RECORD_ONLY = 'record'; 9003f99a78SGreg Roach private const ADD_CHILDREN = 'children'; 9103f99a78SGreg Roach private const ADD_DESCENDANTS = 'descendants'; 9203f99a78SGreg Roach private const ADD_PARENT_FAMILIES = 'parents'; 9303f99a78SGreg Roach private const ADD_SPOUSE_FAMILIES = 'spouses'; 9403f99a78SGreg Roach private const ADD_ANCESTORS = 'ancestors'; 9503f99a78SGreg Roach private const ADD_ANCESTOR_FAMILIES = 'families'; 9603f99a78SGreg Roach private const ADD_LINKED_INDIVIDUALS = 'linked'; 9703f99a78SGreg Roach 985a78cd34SGreg Roach // Routes that have a record which can be added to the clipboard 9916d6367aSGreg Roach private const ROUTES_WITH_RECORDS = [ 100f95e0480SGreg Roach 'Family' => FamilyPage::class, 101f95e0480SGreg Roach 'Individual' => IndividualPage::class, 102f95e0480SGreg Roach 'Media' => MediaPage::class, 103e8ded2caSGreg Roach 'Location' => LocationPage::class, 104f95e0480SGreg Roach 'Note' => NotePage::class, 105f95e0480SGreg Roach 'Repository' => RepositoryPage::class, 106f95e0480SGreg Roach 'Source' => SourcePage::class, 107d45701ccSGreg Roach 'Submitter' => SubmitterPage::class, 108c1010edaSGreg Roach ]; 1095a78cd34SGreg Roach 11049a243cbSGreg Roach /** @var int The default access level for this module. It can be changed in the control panel. */ 11149a243cbSGreg Roach protected $access_level = Auth::PRIV_USER; 11249a243cbSGreg Roach 113*ca47b2adSGreg Roach private GedcomExportService $gedcom_export_service; 11469c05a6eSGreg Roach 115*ca47b2adSGreg Roach private UserService $user_service; 116*ca47b2adSGreg Roach 117*ca47b2adSGreg Roach private ResponseFactoryInterface $response_factory; 118*ca47b2adSGreg Roach 119*ca47b2adSGreg Roach private StreamFactoryInterface $stream_factory; 120e5a6b4d4SGreg Roach 121e5a6b4d4SGreg Roach /** 122e5a6b4d4SGreg Roach * ClippingsCartModule constructor. 123e5a6b4d4SGreg Roach * 12469c05a6eSGreg Roach * @param GedcomExportService $gedcom_export_service 125*ca47b2adSGreg Roach * @param ResponseFactoryInterface $response_factory 126*ca47b2adSGreg Roach * @param StreamFactoryInterface $stream_factory 127e5a6b4d4SGreg Roach * @param UserService $user_service 128e5a6b4d4SGreg Roach */ 129*ca47b2adSGreg Roach public function __construct( 130*ca47b2adSGreg Roach GedcomExportService $gedcom_export_service, 131*ca47b2adSGreg Roach ResponseFactoryInterface $response_factory, 132*ca47b2adSGreg Roach StreamFactoryInterface $stream_factory, 133*ca47b2adSGreg Roach UserService $user_service 134*ca47b2adSGreg Roach ) { 13569c05a6eSGreg Roach $this->gedcom_export_service = $gedcom_export_service; 136*ca47b2adSGreg Roach $this->response_factory = $response_factory; 137*ca47b2adSGreg Roach $this->stream_factory = $stream_factory; 138e5a6b4d4SGreg Roach $this->user_service = $user_service; 139e5a6b4d4SGreg Roach } 140e5a6b4d4SGreg Roach 141e5a6b4d4SGreg Roach /** 142961ec755SGreg Roach * A sentence describing what this module does. 143961ec755SGreg Roach * 144961ec755SGreg Roach * @return string 145961ec755SGreg Roach */ 14649a243cbSGreg Roach public function description(): string 147c1010edaSGreg Roach { 148bbb76c12SGreg Roach /* I18N: Description of the “Clippings cart” module */ 149bbb76c12SGreg Roach return I18N::translate('Select records from your family tree and save them as a GEDCOM file.'); 1508c2e8227SGreg Roach } 1518c2e8227SGreg Roach 1520ee13198SGreg Roach /** 15349a243cbSGreg Roach * The default position for this menu. It can be changed in the control panel. 1540ee13198SGreg Roach * 1550ee13198SGreg Roach * @return int 1560ee13198SGreg Roach */ 1578f53f488SRico Sonntag public function defaultMenuOrder(): int 158c1010edaSGreg Roach { 159353b36abSGreg Roach return 6; 1608c2e8227SGreg Roach } 1618c2e8227SGreg Roach 1620ee13198SGreg Roach /** 1630ee13198SGreg Roach * A menu, to be added to the main application menu. 1640ee13198SGreg Roach * 165aee13b6dSGreg Roach * @param Tree $tree 166aee13b6dSGreg Roach * 1670ee13198SGreg Roach * @return Menu|null 1680ee13198SGreg Roach */ 16946295629SGreg Roach public function getMenu(Tree $tree): ?Menu 170c1010edaSGreg Roach { 171eb235819SGreg Roach /** @var ServerRequestInterface $request */ 1726ccdf4f0SGreg Roach $request = app(ServerRequestInterface::class); 1738c2e8227SGreg Roach 174f7ab47b1SGreg Roach $route = $request->getAttribute('route'); 175de2aa325SGreg Roach assert($route instanceof Route); 1765a78cd34SGreg Roach 177d45701ccSGreg Roach $cart = Session::get('cart', []); 178d45701ccSGreg Roach $count = count($cart[$tree->name()] ?? []); 179d45701ccSGreg Roach $badge = view('components/badge', ['count' => $count]); 180d45701ccSGreg Roach 1815a78cd34SGreg Roach $submenus = [ 182d45701ccSGreg Roach new Menu($this->title() . ' ' . $badge, route('module', [ 18326684e68SGreg Roach 'module' => $this->name(), 184c1010edaSGreg Roach 'action' => 'Show', 185d72b284aSGreg Roach 'tree' => $tree->name(), 186c1010edaSGreg Roach ]), 'menu-clippings-cart', ['rel' => 'nofollow']), 1875a78cd34SGreg Roach ]; 1885a78cd34SGreg Roach 1892b0d92b4SGreg Roach $action = array_search($route->name, self::ROUTES_WITH_RECORDS, true); 190f95e0480SGreg Roach if ($action !== false) { 1912b0d92b4SGreg Roach $xref = $route->attributes['xref']; 192ddeb3354SGreg Roach assert(is_string($xref)); 193ddeb3354SGreg Roach 194c1010edaSGreg Roach $add_route = route('module', [ 19526684e68SGreg Roach 'module' => $this->name(), 196f95e0480SGreg Roach 'action' => 'Add' . $action, 197c1010edaSGreg Roach 'xref' => $xref, 198d72b284aSGreg Roach 'tree' => $tree->name(), 199c1010edaSGreg Roach ]); 2005a78cd34SGreg Roach 20125b2dde3SGreg Roach $submenus[] = new Menu(I18N::translate('Add to the clippings cart'), $add_route, 'menu-clippings-add', ['rel' => 'nofollow']); 2028c2e8227SGreg Roach } 203cbc1590aSGreg Roach 2045a78cd34SGreg Roach if (!$this->isCartEmpty($tree)) { 205c1010edaSGreg Roach $submenus[] = new Menu(I18N::translate('Empty the clippings cart'), route('module', [ 20626684e68SGreg Roach 'module' => $this->name(), 207c1010edaSGreg Roach 'action' => 'Empty', 208d72b284aSGreg Roach 'tree' => $tree->name(), 209c1010edaSGreg Roach ]), 'menu-clippings-empty', ['rel' => 'nofollow']); 210f95e0480SGreg Roach 211c1010edaSGreg Roach $submenus[] = new Menu(I18N::translate('Download'), route('module', [ 21226684e68SGreg Roach 'module' => $this->name(), 213c1010edaSGreg Roach 'action' => 'DownloadForm', 214d72b284aSGreg Roach 'tree' => $tree->name(), 215c1010edaSGreg Roach ]), 'menu-clippings-download', ['rel' => 'nofollow']); 2165a78cd34SGreg Roach } 2175a78cd34SGreg Roach 21849a243cbSGreg Roach return new Menu($this->title(), '#', 'menu-clippings', ['rel' => 'nofollow'], $submenus); 2198c2e8227SGreg Roach } 2208c2e8227SGreg Roach 22176692c8bSGreg Roach /** 222d45701ccSGreg Roach * How should this module be identified in the control panel, etc.? 223d45701ccSGreg Roach * 224d45701ccSGreg Roach * @return string 225d45701ccSGreg Roach */ 226d45701ccSGreg Roach public function title(): string 227d45701ccSGreg Roach { 228d45701ccSGreg Roach /* I18N: Name of a module */ 229d45701ccSGreg Roach return I18N::translate('Clippings cart'); 230d45701ccSGreg Roach } 231d45701ccSGreg Roach 232d45701ccSGreg Roach /** 233d45701ccSGreg Roach * @param Tree $tree 234d45701ccSGreg Roach * 235d45701ccSGreg Roach * @return bool 236d45701ccSGreg Roach */ 237d45701ccSGreg Roach private function isCartEmpty(Tree $tree): bool 238d45701ccSGreg Roach { 239d45701ccSGreg Roach $cart = Session::get('cart', []); 240d45701ccSGreg Roach $contents = $cart[$tree->name()] ?? []; 241d45701ccSGreg Roach 242d45701ccSGreg Roach return $contents === []; 243d45701ccSGreg Roach } 244d45701ccSGreg Roach 245d45701ccSGreg Roach /** 246d45701ccSGreg Roach * @param ServerRequestInterface $request 247d45701ccSGreg Roach * 248d45701ccSGreg Roach * @return ResponseInterface 249d45701ccSGreg Roach */ 250d45701ccSGreg Roach public function getDownloadFormAction(ServerRequestInterface $request): ResponseInterface 251d45701ccSGreg Roach { 252d45701ccSGreg Roach $tree = $request->getAttribute('tree'); 253d45701ccSGreg Roach assert($tree instanceof Tree); 254d45701ccSGreg Roach 255d45701ccSGreg Roach $user = $request->getAttribute('user'); 256d45701ccSGreg Roach $title = I18N::translate('Family tree clippings cart') . ' — ' . I18N::translate('Download'); 257d45701ccSGreg Roach 258d45701ccSGreg Roach return $this->viewResponse('modules/clippings/download', [ 259d45701ccSGreg Roach 'is_manager' => Auth::isManager($tree, $user), 260d45701ccSGreg Roach 'is_member' => Auth::isMember($tree, $user), 261d45701ccSGreg Roach 'module' => $this->name(), 262d45701ccSGreg Roach 'title' => $title, 263d45701ccSGreg Roach 'tree' => $tree, 264d45701ccSGreg Roach ]); 265d45701ccSGreg Roach } 266d45701ccSGreg Roach 267d45701ccSGreg Roach /** 2686ccdf4f0SGreg Roach * @param ServerRequestInterface $request 26976692c8bSGreg Roach * 2706ccdf4f0SGreg Roach * @return ResponseInterface 271f0448b68SGreg Roach * @throws FilesystemException 27276692c8bSGreg Roach */ 273f95e0480SGreg Roach public function postDownloadAction(ServerRequestInterface $request): ResponseInterface 274c1010edaSGreg Roach { 27557ab2231SGreg Roach $tree = $request->getAttribute('tree'); 2764ea62551SGreg Roach assert($tree instanceof Tree); 2774ea62551SGreg Roach 2786b9cb339SGreg Roach $data_filesystem = Registry::filesystem()->data(); 279a04bb9a2SGreg Roach 280b46c87bdSGreg Roach $params = (array) $request->getParsedBody(); 281b46c87bdSGreg Roach 282d45701ccSGreg Roach $privatize_export = $params['privatize_export'] ?? 'none'; 283e2ed7c79SGreg Roach 284e2ed7c79SGreg Roach if ($privatize_export === 'none' && !Auth::isManager($tree)) { 285e2ed7c79SGreg Roach $privatize_export = 'member'; 286e2ed7c79SGreg Roach } 287e2ed7c79SGreg Roach 288e2ed7c79SGreg Roach if ($privatize_export === 'gedadmin' && !Auth::isManager($tree)) { 289e2ed7c79SGreg Roach $privatize_export = 'member'; 290e2ed7c79SGreg Roach } 291e2ed7c79SGreg Roach 292e2ed7c79SGreg Roach if ($privatize_export === 'user' && !Auth::isMember($tree)) { 293e2ed7c79SGreg Roach $privatize_export = 'visitor'; 294e2ed7c79SGreg Roach } 295e2ed7c79SGreg Roach 296b46c87bdSGreg Roach $convert = (bool) ($params['convert'] ?? false); 2978c2e8227SGreg Roach 29813abd6f3SGreg Roach $cart = Session::get('cart', []); 2998c2e8227SGreg Roach 300aa6f03bbSGreg Roach $xrefs = array_keys($cart[$tree->name()] ?? []); 301c8846facSGreg Roach $xrefs = array_map('strval', $xrefs); // PHP converts numeric keys to integers. 3025a78cd34SGreg Roach 3035a78cd34SGreg Roach // Create a new/empty .ZIP file 304a00baf47SGreg Roach $temp_zip_file = stream_get_meta_data(tmpfile())['uri']; 305f32d77e6SGreg Roach $zip_provider = new FilesystemZipArchiveProvider($temp_zip_file, 0755); 306f32d77e6SGreg Roach $zip_adapter = new ZipArchiveAdapter($zip_provider); 3077f996f6eSGreg Roach $zip_filesystem = new Filesystem($zip_adapter); 3085a78cd34SGreg Roach 309fa695506SGreg Roach $media_filesystem = $tree->mediaFilesystem($data_filesystem); 31061bf91b2SGreg Roach 3115a78cd34SGreg Roach // Media file prefix 3125a78cd34SGreg Roach $path = $tree->getPreference('MEDIA_DIRECTORY'); 3135a78cd34SGreg Roach 31469c05a6eSGreg Roach $encoding = $convert ? 'ANSI' : 'UTF-8'; 31569c05a6eSGreg Roach 31669c05a6eSGreg Roach $records = new Collection(); 3175a78cd34SGreg Roach 3185a78cd34SGreg Roach switch ($privatize_export) { 3195a78cd34SGreg Roach case 'gedadmin': 3205a78cd34SGreg Roach $access_level = Auth::PRIV_NONE; 3215a78cd34SGreg Roach break; 3225a78cd34SGreg Roach case 'user': 3235a78cd34SGreg Roach $access_level = Auth::PRIV_USER; 3245a78cd34SGreg Roach break; 3255a78cd34SGreg Roach case 'visitor': 3265a78cd34SGreg Roach $access_level = Auth::PRIV_PRIVATE; 3275a78cd34SGreg Roach break; 3285a78cd34SGreg Roach case 'none': 3295a78cd34SGreg Roach default: 3305a78cd34SGreg Roach $access_level = Auth::PRIV_HIDE; 3315a78cd34SGreg Roach break; 3325a78cd34SGreg Roach } 3335a78cd34SGreg Roach 3345a78cd34SGreg Roach foreach ($xrefs as $xref) { 3356b9cb339SGreg Roach $object = Registry::gedcomRecordFactory()->make($xref, $tree); 3365a78cd34SGreg Roach // The object may have been deleted since we added it to the cart.... 337bed27cedSGreg Roach if ($object instanceof GedcomRecord) { 3385a78cd34SGreg Roach $record = $object->privatizeGedcom($access_level); 3395a78cd34SGreg Roach // Remove links to objects that aren't in the cart 3408d0ebef0SGreg Roach preg_match_all('/\n1 ' . Gedcom::REGEX_TAG . ' @(' . Gedcom::REGEX_XREF . ')@(\n[2-9].*)*/', $record, $matches, PREG_SET_ORDER); 3415a78cd34SGreg Roach foreach ($matches as $match) { 342bf80ec58SGreg Roach if (!in_array($match[1], $xrefs, true)) { 3435a78cd34SGreg Roach $record = str_replace($match[0], '', $record); 3445a78cd34SGreg Roach } 3455a78cd34SGreg Roach } 3468d0ebef0SGreg Roach preg_match_all('/\n2 ' . Gedcom::REGEX_TAG . ' @(' . Gedcom::REGEX_XREF . ')@(\n[3-9].*)*/', $record, $matches, PREG_SET_ORDER); 3475a78cd34SGreg Roach foreach ($matches as $match) { 348bf80ec58SGreg Roach if (!in_array($match[1], $xrefs, true)) { 3495a78cd34SGreg Roach $record = str_replace($match[0], '', $record); 3505a78cd34SGreg Roach } 3515a78cd34SGreg Roach } 3528d0ebef0SGreg Roach preg_match_all('/\n3 ' . Gedcom::REGEX_TAG . ' @(' . Gedcom::REGEX_XREF . ')@(\n[4-9].*)*/', $record, $matches, PREG_SET_ORDER); 3535a78cd34SGreg Roach foreach ($matches as $match) { 354bf80ec58SGreg Roach if (!in_array($match[1], $xrefs, true)) { 3555a78cd34SGreg Roach $record = str_replace($match[0], '', $record); 3565a78cd34SGreg Roach } 3575a78cd34SGreg Roach } 3585a78cd34SGreg Roach 35955167344SGreg Roach if ($object instanceof Individual || $object instanceof Family) { 36069c05a6eSGreg Roach $records->add($record . "\n1 SOUR @WEBTREES@\n2 PAGE " . $object->url()); 36155167344SGreg Roach } elseif ($object instanceof Source) { 36269c05a6eSGreg Roach $records->add($record . "\n1 NOTE " . $object->url()); 36355167344SGreg Roach } elseif ($object instanceof Media) { 36455167344SGreg Roach // Add the media files to the archive 3655a78cd34SGreg Roach foreach ($object->mediaFiles() as $media_file) { 366fa695506SGreg Roach $from = $media_file->filename(); 367fa695506SGreg Roach $to = $path . $media_file->filename(); 368f0448b68SGreg Roach if (!$media_file->isExternal() && $media_filesystem->fileExists($from)) { 369fa695506SGreg Roach $zip_filesystem->writeStream($to, $media_filesystem->readStream($from)); 3705a78cd34SGreg Roach } 3715a78cd34SGreg Roach } 37269c05a6eSGreg Roach $records->add($record); 37355167344SGreg Roach } else { 37469c05a6eSGreg Roach $records->add($record); 3758c2e8227SGreg Roach } 3768c2e8227SGreg Roach } 3778c2e8227SGreg Roach } 3788c2e8227SGreg Roach 3799b93b7c3SGreg Roach $base_url = $request->getAttribute('base_url'); 3809b93b7c3SGreg Roach 3815a78cd34SGreg Roach // Create a source, to indicate the source of the data. 38269c05a6eSGreg Roach $record = "0 @WEBTREES@ SOUR\n1 TITL " . $base_url; 383e5a6b4d4SGreg Roach $author = $this->user_service->find((int) $tree->getPreference('CONTACT_USER_ID')); 3845a78cd34SGreg Roach if ($author !== null) { 38569c05a6eSGreg Roach $record .= "\n1 AUTH " . $author->realName(); 3865a78cd34SGreg Roach } 38769c05a6eSGreg Roach $records->add($record); 3885a78cd34SGreg Roach 38969c05a6eSGreg Roach $stream = fopen('php://temp', 'wb+'); 3905a78cd34SGreg Roach 39169c05a6eSGreg Roach if ($stream === false) { 39269c05a6eSGreg Roach throw new RuntimeException('Failed to create temporary stream'); 3938c2e8227SGreg Roach } 394cbc1590aSGreg Roach 39569c05a6eSGreg Roach // We have already applied privacy filtering, so do not do it again. 39669c05a6eSGreg Roach $this->gedcom_export_service->export($tree, $stream, false, $encoding, Auth::PRIV_HIDE, $path, $records); 39769c05a6eSGreg Roach rewind($stream); 39869c05a6eSGreg Roach 3995a78cd34SGreg Roach // Finally add the GEDCOM file to the .ZIP file. 40069c05a6eSGreg Roach $zip_filesystem->writeStream('clippings.ged', $stream); 4015a78cd34SGreg Roach 4026ccdf4f0SGreg Roach // Use a stream, so that we do not have to load the entire file into memory. 403*ca47b2adSGreg Roach $stream = $this->stream_factory->createStreamFromFile($temp_zip_file); 4045a78cd34SGreg Roach 405*ca47b2adSGreg Roach return $this->response_factory->createResponse() 4066ccdf4f0SGreg Roach ->withBody($stream) 4071b3d4731SGreg Roach ->withHeader('Content-Type', 'application/zip') 408bed27cedSGreg Roach ->withHeader('Content-Disposition', 'attachment; filename="clippings.zip'); 4098c2e8227SGreg Roach } 4108c2e8227SGreg Roach 4118c2e8227SGreg Roach /** 41257ab2231SGreg Roach * @param ServerRequestInterface $request 41376692c8bSGreg Roach * 4146ccdf4f0SGreg Roach * @return ResponseInterface 4158c2e8227SGreg Roach */ 41657ab2231SGreg Roach public function getEmptyAction(ServerRequestInterface $request): ResponseInterface 417c1010edaSGreg Roach { 41857ab2231SGreg Roach $tree = $request->getAttribute('tree'); 4194ea62551SGreg Roach assert($tree instanceof Tree); 4204ea62551SGreg Roach 4215a78cd34SGreg Roach $cart = Session::get('cart', []); 422aa6f03bbSGreg Roach $cart[$tree->name()] = []; 4235a78cd34SGreg Roach Session::put('cart', $cart); 4248c2e8227SGreg Roach 425c1010edaSGreg Roach $url = route('module', [ 42626684e68SGreg Roach 'module' => $this->name(), 427c1010edaSGreg Roach 'action' => 'Show', 428d72b284aSGreg Roach 'tree' => $tree->name(), 429c1010edaSGreg Roach ]); 4305a78cd34SGreg Roach 4316ccdf4f0SGreg Roach return redirect($url); 4325a78cd34SGreg Roach } 4335a78cd34SGreg Roach 4345a78cd34SGreg Roach /** 4356ccdf4f0SGreg Roach * @param ServerRequestInterface $request 4365a78cd34SGreg Roach * 4376ccdf4f0SGreg Roach * @return ResponseInterface 4385a78cd34SGreg Roach */ 43957ab2231SGreg Roach public function postRemoveAction(ServerRequestInterface $request): ResponseInterface 440c1010edaSGreg Roach { 44157ab2231SGreg Roach $tree = $request->getAttribute('tree'); 44275964c75SGreg Roach assert($tree instanceof Tree); 4435229eadeSGreg Roach 444d45701ccSGreg Roach $xref = $request->getQueryParams()['xref'] ?? ''; 4455a78cd34SGreg Roach 4465a78cd34SGreg Roach $cart = Session::get('cart', []); 447aa6f03bbSGreg Roach unset($cart[$tree->name()][$xref]); 4485a78cd34SGreg Roach Session::put('cart', $cart); 4495a78cd34SGreg Roach 450c1010edaSGreg Roach $url = route('module', [ 45126684e68SGreg Roach 'module' => $this->name(), 452c1010edaSGreg Roach 'action' => 'Show', 453d72b284aSGreg Roach 'tree' => $tree->name(), 454c1010edaSGreg Roach ]); 4555a78cd34SGreg Roach 4566ccdf4f0SGreg Roach return redirect($url); 4575a78cd34SGreg Roach } 4585a78cd34SGreg Roach 4595a78cd34SGreg Roach /** 46057ab2231SGreg Roach * @param ServerRequestInterface $request 4615a78cd34SGreg Roach * 4626ccdf4f0SGreg Roach * @return ResponseInterface 4635a78cd34SGreg Roach */ 46457ab2231SGreg Roach public function getShowAction(ServerRequestInterface $request): ResponseInterface 465c1010edaSGreg Roach { 46657ab2231SGreg Roach $tree = $request->getAttribute('tree'); 46775964c75SGreg Roach assert($tree instanceof Tree); 46857ab2231SGreg Roach 4695a78cd34SGreg Roach return $this->viewResponse('modules/clippings/show', [ 47077b78a63SRichard Cissée 'module' => $this->name(), 4715a78cd34SGreg Roach 'records' => $this->allRecordsInCart($tree), 4725a78cd34SGreg Roach 'title' => I18N::translate('Family tree clippings cart'), 4735a78cd34SGreg Roach 'tree' => $tree, 4745a78cd34SGreg Roach ]); 4755a78cd34SGreg Roach } 4765a78cd34SGreg Roach 4775a78cd34SGreg Roach /** 478d45701ccSGreg Roach * Get all the records in the cart. 479d45701ccSGreg Roach * 480d45701ccSGreg Roach * @param Tree $tree 481d45701ccSGreg Roach * 482d45701ccSGreg Roach * @return GedcomRecord[] 483d45701ccSGreg Roach */ 484d45701ccSGreg Roach private function allRecordsInCart(Tree $tree): array 485d45701ccSGreg Roach { 486d45701ccSGreg Roach $cart = Session::get('cart', []); 487d45701ccSGreg Roach 488d45701ccSGreg Roach $xrefs = array_keys($cart[$tree->name()] ?? []); 489d45701ccSGreg Roach $xrefs = array_map('strval', $xrefs); // PHP converts numeric keys to integers. 490d45701ccSGreg Roach 491d45701ccSGreg Roach // Fetch all the records in the cart. 492d45701ccSGreg Roach $records = array_map(static function (string $xref) use ($tree): ?GedcomRecord { 493d45701ccSGreg Roach return Registry::gedcomRecordFactory()->make($xref, $tree); 494d45701ccSGreg Roach }, $xrefs); 495d45701ccSGreg Roach 496d45701ccSGreg Roach // Some records may have been deleted after they were added to the cart. 497d45701ccSGreg Roach $records = array_filter($records); 498d45701ccSGreg Roach 499d45701ccSGreg Roach // Group and sort. 500d45701ccSGreg Roach uasort($records, static function (GedcomRecord $x, GedcomRecord $y): int { 501d45701ccSGreg Roach return $x->tag() <=> $y->tag() ?: GedcomRecord::nameComparator()($x, $y); 502d45701ccSGreg Roach }); 503d45701ccSGreg Roach 504d45701ccSGreg Roach return $records; 505d45701ccSGreg Roach } 506d45701ccSGreg Roach 507d45701ccSGreg Roach /** 5086ccdf4f0SGreg Roach * @param ServerRequestInterface $request 5095a78cd34SGreg Roach * 5106ccdf4f0SGreg Roach * @return ResponseInterface 5115a78cd34SGreg Roach */ 51257ab2231SGreg Roach public function getAddFamilyAction(ServerRequestInterface $request): ResponseInterface 513c1010edaSGreg Roach { 51457ab2231SGreg Roach $tree = $request->getAttribute('tree'); 51575964c75SGreg Roach assert($tree instanceof Tree); 5165229eadeSGreg Roach 517d45701ccSGreg Roach $xref = $request->getQueryParams()['xref'] ?? ''; 5185a78cd34SGreg Roach 5196b9cb339SGreg Roach $family = Registry::familyFactory()->make($xref, $tree); 520d45701ccSGreg Roach $family = Auth::checkFamilyAccess($family); 521d45701ccSGreg Roach $name = $family->fullName(); 5225a78cd34SGreg Roach 523d45701ccSGreg Roach $options = [ 52403f99a78SGreg Roach self::ADD_RECORD_ONLY => $name, 525bbb76c12SGreg Roach /* I18N: %s is a family (husband + wife) */ 52603f99a78SGreg Roach self::ADD_CHILDREN => I18N::translate('%s and their children', $name), 527bbb76c12SGreg Roach /* I18N: %s is a family (husband + wife) */ 52803f99a78SGreg Roach self::ADD_DESCENDANTS => I18N::translate('%s and their descendants', $name), 5295a78cd34SGreg Roach ]; 530d45701ccSGreg Roach 531d45701ccSGreg Roach $title = I18N::translate('Add %s to the clippings cart', $name); 532d45701ccSGreg Roach 533d45701ccSGreg Roach return $this->viewResponse('modules/clippings/add-options', [ 534d45701ccSGreg Roach 'options' => $options, 535d45701ccSGreg Roach 'record' => $family, 536d45701ccSGreg Roach 'title' => $title, 537d45701ccSGreg Roach 'tree' => $tree, 538d45701ccSGreg Roach ]); 5395a78cd34SGreg Roach } 5405a78cd34SGreg Roach 5415a78cd34SGreg Roach /** 5426ccdf4f0SGreg Roach * @param ServerRequestInterface $request 5435a78cd34SGreg Roach * 5446ccdf4f0SGreg Roach * @return ResponseInterface 5455a78cd34SGreg Roach */ 54657ab2231SGreg Roach public function postAddFamilyAction(ServerRequestInterface $request): ResponseInterface 547c1010edaSGreg Roach { 54857ab2231SGreg Roach $tree = $request->getAttribute('tree'); 5494ea62551SGreg Roach assert($tree instanceof Tree); 5504ea62551SGreg Roach 551b46c87bdSGreg Roach $params = (array) $request->getParsedBody(); 552b46c87bdSGreg Roach 553d45701ccSGreg Roach $xref = $params['xref'] ?? ''; 554d45701ccSGreg Roach $option = $params['option'] ?? ''; 5555a78cd34SGreg Roach 5566b9cb339SGreg Roach $family = Registry::familyFactory()->make($xref, $tree); 557d45701ccSGreg Roach $family = Auth::checkFamilyAccess($family); 5585a78cd34SGreg Roach 5595a78cd34SGreg Roach switch ($option) { 56003f99a78SGreg Roach case self::ADD_RECORD_ONLY: 5615a78cd34SGreg Roach $this->addFamilyToCart($family); 5625a78cd34SGreg Roach break; 5635a78cd34SGreg Roach 56403f99a78SGreg Roach case self::ADD_CHILDREN: 5655a78cd34SGreg Roach $this->addFamilyAndChildrenToCart($family); 5665a78cd34SGreg Roach break; 5675a78cd34SGreg Roach 56803f99a78SGreg Roach case self::ADD_DESCENDANTS: 5695a78cd34SGreg Roach $this->addFamilyAndDescendantsToCart($family); 5705a78cd34SGreg Roach break; 5715a78cd34SGreg Roach } 5725a78cd34SGreg Roach 5736ccdf4f0SGreg Roach return redirect($family->url()); 5745a78cd34SGreg Roach } 5755a78cd34SGreg Roach 5765a78cd34SGreg Roach 5775a78cd34SGreg Roach /** 5785a78cd34SGreg Roach * @param Family $family 57918d7a90dSGreg Roach * 58018d7a90dSGreg Roach * @return void 5815a78cd34SGreg Roach */ 582d45701ccSGreg Roach protected function addFamilyAndChildrenToCart(Family $family): void 583c1010edaSGreg Roach { 584d45701ccSGreg Roach $this->addFamilyToCart($family); 5855a78cd34SGreg Roach 58639ca88baSGreg Roach foreach ($family->children() as $child) { 587d45701ccSGreg Roach $this->addIndividualToCart($child); 5885a78cd34SGreg Roach } 5895a78cd34SGreg Roach } 5905a78cd34SGreg Roach 5915a78cd34SGreg Roach /** 5925a78cd34SGreg Roach * @param Family $family 59318d7a90dSGreg Roach * 59418d7a90dSGreg Roach * @return void 5955a78cd34SGreg Roach */ 596d45701ccSGreg Roach protected function addFamilyAndDescendantsToCart(Family $family): void 597c1010edaSGreg Roach { 598d45701ccSGreg Roach $this->addFamilyAndChildrenToCart($family); 5995a78cd34SGreg Roach 60039ca88baSGreg Roach foreach ($family->children() as $child) { 60139ca88baSGreg Roach foreach ($child->spouseFamilies() as $child_family) { 6025a78cd34SGreg Roach $this->addFamilyAndDescendantsToCart($child_family); 6035a78cd34SGreg Roach } 6045a78cd34SGreg Roach } 6055a78cd34SGreg Roach } 6065a78cd34SGreg Roach 6075a78cd34SGreg Roach /** 6086ccdf4f0SGreg Roach * @param ServerRequestInterface $request 6095a78cd34SGreg Roach * 6106ccdf4f0SGreg Roach * @return ResponseInterface 6115a78cd34SGreg Roach */ 61257ab2231SGreg Roach public function getAddIndividualAction(ServerRequestInterface $request): ResponseInterface 613c1010edaSGreg Roach { 61457ab2231SGreg Roach $tree = $request->getAttribute('tree'); 61575964c75SGreg Roach assert($tree instanceof Tree); 6165229eadeSGreg Roach 617d45701ccSGreg Roach $xref = $request->getQueryParams()['xref'] ?? ''; 6185a78cd34SGreg Roach 6196b9cb339SGreg Roach $individual = Registry::individualFactory()->make($xref, $tree); 620d45701ccSGreg Roach $individual = Auth::checkIndividualAccess($individual); 621d45701ccSGreg Roach $name = $individual->fullName(); 6225a78cd34SGreg Roach 62339ca88baSGreg Roach if ($individual->sex() === 'F') { 624d45701ccSGreg Roach $options = [ 62503f99a78SGreg Roach self::ADD_RECORD_ONLY => $name, 62603f99a78SGreg Roach self::ADD_PARENT_FAMILIES => I18N::translate('%s, her parents and siblings', $name), 62703f99a78SGreg Roach self::ADD_SPOUSE_FAMILIES => I18N::translate('%s, her spouses and children', $name), 62803f99a78SGreg Roach self::ADD_ANCESTORS => I18N::translate('%s and her ancestors', $name), 62903f99a78SGreg Roach self::ADD_ANCESTOR_FAMILIES => I18N::translate('%s, her ancestors and their families', $name), 63003f99a78SGreg Roach self::ADD_DESCENDANTS => I18N::translate('%s, her spouses and descendants', $name), 6315a78cd34SGreg Roach ]; 632d45701ccSGreg Roach } else { 633d45701ccSGreg Roach $options = [ 63403f99a78SGreg Roach self::ADD_RECORD_ONLY => $name, 63503f99a78SGreg Roach self::ADD_PARENT_FAMILIES => I18N::translate('%s, his parents and siblings', $name), 63603f99a78SGreg Roach self::ADD_SPOUSE_FAMILIES => I18N::translate('%s, his spouses and children', $name), 63703f99a78SGreg Roach self::ADD_ANCESTORS => I18N::translate('%s and his ancestors', $name), 63803f99a78SGreg Roach self::ADD_ANCESTOR_FAMILIES => I18N::translate('%s, his ancestors and their families', $name), 63903f99a78SGreg Roach self::ADD_DESCENDANTS => I18N::translate('%s, his spouses and descendants', $name), 6405a78cd34SGreg Roach ]; 6415a78cd34SGreg Roach } 6425a78cd34SGreg Roach 643d45701ccSGreg Roach $title = I18N::translate('Add %s to the clippings cart', $name); 644d45701ccSGreg Roach 645d45701ccSGreg Roach return $this->viewResponse('modules/clippings/add-options', [ 646d45701ccSGreg Roach 'options' => $options, 647d45701ccSGreg Roach 'record' => $individual, 648d45701ccSGreg Roach 'title' => $title, 649d45701ccSGreg Roach 'tree' => $tree, 650d45701ccSGreg Roach ]); 651d45701ccSGreg Roach } 652d45701ccSGreg Roach 6535a78cd34SGreg Roach /** 6546ccdf4f0SGreg Roach * @param ServerRequestInterface $request 6555a78cd34SGreg Roach * 6566ccdf4f0SGreg Roach * @return ResponseInterface 6575a78cd34SGreg Roach */ 65857ab2231SGreg Roach public function postAddIndividualAction(ServerRequestInterface $request): ResponseInterface 659c1010edaSGreg Roach { 66057ab2231SGreg Roach $tree = $request->getAttribute('tree'); 6614ea62551SGreg Roach assert($tree instanceof Tree); 6624ea62551SGreg Roach 663b46c87bdSGreg Roach $params = (array) $request->getParsedBody(); 664b46c87bdSGreg Roach 665d45701ccSGreg Roach $xref = $params['xref'] ?? ''; 666d45701ccSGreg Roach $option = $params['option'] ?? ''; 6675a78cd34SGreg Roach 6686b9cb339SGreg Roach $individual = Registry::individualFactory()->make($xref, $tree); 669d45701ccSGreg Roach $individual = Auth::checkIndividualAccess($individual); 6705a78cd34SGreg Roach 6715a78cd34SGreg Roach switch ($option) { 67203f99a78SGreg Roach case self::ADD_RECORD_ONLY: 673d45701ccSGreg Roach $this->addIndividualToCart($individual); 6745a78cd34SGreg Roach break; 6755a78cd34SGreg Roach 67603f99a78SGreg Roach case self::ADD_PARENT_FAMILIES: 67739ca88baSGreg Roach foreach ($individual->childFamilies() as $family) { 6785a78cd34SGreg Roach $this->addFamilyAndChildrenToCart($family); 6795a78cd34SGreg Roach } 6805a78cd34SGreg Roach break; 6815a78cd34SGreg Roach 68203f99a78SGreg Roach case self::ADD_SPOUSE_FAMILIES: 68339ca88baSGreg Roach foreach ($individual->spouseFamilies() as $family) { 6845a78cd34SGreg Roach $this->addFamilyAndChildrenToCart($family); 6855a78cd34SGreg Roach } 6865a78cd34SGreg Roach break; 6875a78cd34SGreg Roach 68803f99a78SGreg Roach case self::ADD_ANCESTORS: 6895a78cd34SGreg Roach $this->addAncestorsToCart($individual); 6905a78cd34SGreg Roach break; 6915a78cd34SGreg Roach 69203f99a78SGreg Roach case self::ADD_ANCESTOR_FAMILIES: 6935a78cd34SGreg Roach $this->addAncestorFamiliesToCart($individual); 6945a78cd34SGreg Roach break; 6955a78cd34SGreg Roach 69603f99a78SGreg Roach case self::ADD_DESCENDANTS: 69739ca88baSGreg Roach foreach ($individual->spouseFamilies() as $family) { 6985a78cd34SGreg Roach $this->addFamilyAndDescendantsToCart($family); 6995a78cd34SGreg Roach } 7005a78cd34SGreg Roach break; 7015a78cd34SGreg Roach } 7025a78cd34SGreg Roach 7036ccdf4f0SGreg Roach return redirect($individual->url()); 7045a78cd34SGreg Roach } 7055a78cd34SGreg Roach 7065a78cd34SGreg Roach /** 7075a78cd34SGreg Roach * @param Individual $individual 70818d7a90dSGreg Roach * 70918d7a90dSGreg Roach * @return void 7105a78cd34SGreg Roach */ 711d45701ccSGreg Roach protected function addAncestorsToCart(Individual $individual): void 712c1010edaSGreg Roach { 713d45701ccSGreg Roach $this->addIndividualToCart($individual); 7145a78cd34SGreg Roach 71539ca88baSGreg Roach foreach ($individual->childFamilies() as $family) { 716d45701ccSGreg Roach $this->addFamilyToCart($family); 7178df4c68dSGreg Roach 71839ca88baSGreg Roach foreach ($family->spouses() as $parent) { 7195a78cd34SGreg Roach $this->addAncestorsToCart($parent); 7205a78cd34SGreg Roach } 7215a78cd34SGreg Roach } 7225a78cd34SGreg Roach } 7235a78cd34SGreg Roach 7245a78cd34SGreg Roach /** 7255a78cd34SGreg Roach * @param Individual $individual 72618d7a90dSGreg Roach * 72718d7a90dSGreg Roach * @return void 7285a78cd34SGreg Roach */ 729d45701ccSGreg Roach protected function addAncestorFamiliesToCart(Individual $individual): void 730c1010edaSGreg Roach { 73139ca88baSGreg Roach foreach ($individual->childFamilies() as $family) { 7325a78cd34SGreg Roach $this->addFamilyAndChildrenToCart($family); 7338df4c68dSGreg Roach 73439ca88baSGreg Roach foreach ($family->spouses() as $parent) { 735cad6d3f3SGreg Roach $this->addAncestorFamiliesToCart($parent); 7365a78cd34SGreg Roach } 7375a78cd34SGreg Roach } 7385a78cd34SGreg Roach } 7395a78cd34SGreg Roach 7405a78cd34SGreg Roach /** 7416ccdf4f0SGreg Roach * @param ServerRequestInterface $request 7425a78cd34SGreg Roach * 7436ccdf4f0SGreg Roach * @return ResponseInterface 7445a78cd34SGreg Roach */ 745e8ded2caSGreg Roach public function getAddLocationAction(ServerRequestInterface $request): ResponseInterface 746e8ded2caSGreg Roach { 747e8ded2caSGreg Roach $tree = $request->getAttribute('tree'); 748e8ded2caSGreg Roach assert($tree instanceof Tree); 749e8ded2caSGreg Roach 750e8ded2caSGreg Roach $xref = $request->getQueryParams()['xref'] ?? ''; 751e8ded2caSGreg Roach 752e8ded2caSGreg Roach $location = Registry::locationFactory()->make($xref, $tree); 753e8ded2caSGreg Roach $location = Auth::checkLocationAccess($location); 754e8ded2caSGreg Roach $name = $location->fullName(); 755e8ded2caSGreg Roach 756e8ded2caSGreg Roach $options = [ 75703f99a78SGreg Roach self::ADD_RECORD_ONLY => $name, 758e8ded2caSGreg Roach ]; 759e8ded2caSGreg Roach 760e8ded2caSGreg Roach $title = I18N::translate('Add %s to the clippings cart', $name); 761e8ded2caSGreg Roach 762e8ded2caSGreg Roach return $this->viewResponse('modules/clippings/add-options', [ 763e8ded2caSGreg Roach 'options' => $options, 764e8ded2caSGreg Roach 'record' => $location, 765e8ded2caSGreg Roach 'title' => $title, 766e8ded2caSGreg Roach 'tree' => $tree, 767e8ded2caSGreg Roach ]); 768e8ded2caSGreg Roach } 769e8ded2caSGreg Roach 770e8ded2caSGreg Roach /** 771e8ded2caSGreg Roach * @param ServerRequestInterface $request 772e8ded2caSGreg Roach * 773e8ded2caSGreg Roach * @return ResponseInterface 774e8ded2caSGreg Roach */ 775e8ded2caSGreg Roach public function postAddLocationAction(ServerRequestInterface $request): ResponseInterface 776e8ded2caSGreg Roach { 777e8ded2caSGreg Roach $tree = $request->getAttribute('tree'); 778e8ded2caSGreg Roach assert($tree instanceof Tree); 779e8ded2caSGreg Roach 780e8ded2caSGreg Roach $xref = $request->getQueryParams()['xref'] ?? ''; 781e8ded2caSGreg Roach 782e8ded2caSGreg Roach $location = Registry::locationFactory()->make($xref, $tree); 783e8ded2caSGreg Roach $location = Auth::checkLocationAccess($location); 784e8ded2caSGreg Roach 785e8ded2caSGreg Roach $this->addLocationToCart($location); 786e8ded2caSGreg Roach 787e8ded2caSGreg Roach return redirect($location->url()); 788e8ded2caSGreg Roach } 789e8ded2caSGreg Roach 790e8ded2caSGreg Roach /** 791e8ded2caSGreg Roach * @param ServerRequestInterface $request 792e8ded2caSGreg Roach * 793e8ded2caSGreg Roach * @return ResponseInterface 794e8ded2caSGreg Roach */ 79557ab2231SGreg Roach public function getAddMediaAction(ServerRequestInterface $request): ResponseInterface 796c1010edaSGreg Roach { 79757ab2231SGreg Roach $tree = $request->getAttribute('tree'); 79875964c75SGreg Roach assert($tree instanceof Tree); 7995229eadeSGreg Roach 800d45701ccSGreg Roach $xref = $request->getQueryParams()['xref'] ?? ''; 8015a78cd34SGreg Roach 8026b9cb339SGreg Roach $media = Registry::mediaFactory()->make($xref, $tree); 803d45701ccSGreg Roach $media = Auth::checkMediaAccess($media); 804d45701ccSGreg Roach $name = $media->fullName(); 8055a78cd34SGreg Roach 806d45701ccSGreg Roach $options = [ 80703f99a78SGreg Roach self::ADD_RECORD_ONLY => $name, 808d45701ccSGreg Roach ]; 8095a78cd34SGreg Roach 810d45701ccSGreg Roach $title = I18N::translate('Add %s to the clippings cart', $name); 8115a78cd34SGreg Roach 8125a78cd34SGreg Roach return $this->viewResponse('modules/clippings/add-options', [ 8135a78cd34SGreg Roach 'options' => $options, 8145a78cd34SGreg Roach 'record' => $media, 8155a78cd34SGreg Roach 'title' => $title, 8165a78cd34SGreg Roach 'tree' => $tree, 8175a78cd34SGreg Roach ]); 8185a78cd34SGreg Roach } 8195a78cd34SGreg Roach 8205a78cd34SGreg Roach /** 8216ccdf4f0SGreg Roach * @param ServerRequestInterface $request 8225a78cd34SGreg Roach * 8236ccdf4f0SGreg Roach * @return ResponseInterface 8245a78cd34SGreg Roach */ 82557ab2231SGreg Roach public function postAddMediaAction(ServerRequestInterface $request): ResponseInterface 826c1010edaSGreg Roach { 82757ab2231SGreg Roach $tree = $request->getAttribute('tree'); 82875964c75SGreg Roach assert($tree instanceof Tree); 8295229eadeSGreg Roach 830d45701ccSGreg Roach $xref = $request->getQueryParams()['xref'] ?? ''; 8315a78cd34SGreg Roach 8326b9cb339SGreg Roach $media = Registry::mediaFactory()->make($xref, $tree); 833d45701ccSGreg Roach $media = Auth::checkMediaAccess($media); 8345a78cd34SGreg Roach 835d45701ccSGreg Roach $this->addMediaToCart($media); 8365a78cd34SGreg Roach 8376ccdf4f0SGreg Roach return redirect($media->url()); 8385a78cd34SGreg Roach } 8395a78cd34SGreg Roach 8405a78cd34SGreg Roach /** 8416ccdf4f0SGreg Roach * @param ServerRequestInterface $request 8425a78cd34SGreg Roach * 8436ccdf4f0SGreg Roach * @return ResponseInterface 8445a78cd34SGreg Roach */ 84557ab2231SGreg Roach public function getAddNoteAction(ServerRequestInterface $request): ResponseInterface 846c1010edaSGreg Roach { 84757ab2231SGreg Roach $tree = $request->getAttribute('tree'); 84875964c75SGreg Roach assert($tree instanceof Tree); 8495229eadeSGreg Roach 850d45701ccSGreg Roach $xref = $request->getQueryParams()['xref'] ?? ''; 8515a78cd34SGreg Roach 8526b9cb339SGreg Roach $note = Registry::noteFactory()->make($xref, $tree); 853d45701ccSGreg Roach $note = Auth::checkNoteAccess($note); 854d45701ccSGreg Roach $name = $note->fullName(); 8555a78cd34SGreg Roach 856d45701ccSGreg Roach $options = [ 85703f99a78SGreg Roach self::ADD_RECORD_ONLY => $name, 858d45701ccSGreg Roach ]; 8595a78cd34SGreg Roach 860d45701ccSGreg Roach $title = I18N::translate('Add %s to the clippings cart', $name); 8615a78cd34SGreg Roach 8625a78cd34SGreg Roach return $this->viewResponse('modules/clippings/add-options', [ 8635a78cd34SGreg Roach 'options' => $options, 8645a78cd34SGreg Roach 'record' => $note, 8655a78cd34SGreg Roach 'title' => $title, 8665a78cd34SGreg Roach 'tree' => $tree, 8675a78cd34SGreg Roach ]); 8685a78cd34SGreg Roach } 8695a78cd34SGreg Roach 8705a78cd34SGreg Roach /** 8716ccdf4f0SGreg Roach * @param ServerRequestInterface $request 8725a78cd34SGreg Roach * 8736ccdf4f0SGreg Roach * @return ResponseInterface 8745a78cd34SGreg Roach */ 87557ab2231SGreg Roach public function postAddNoteAction(ServerRequestInterface $request): ResponseInterface 876c1010edaSGreg Roach { 87757ab2231SGreg Roach $tree = $request->getAttribute('tree'); 87875964c75SGreg Roach assert($tree instanceof Tree); 8795229eadeSGreg Roach 880d45701ccSGreg Roach $xref = $request->getQueryParams()['xref'] ?? ''; 8815a78cd34SGreg Roach 8826b9cb339SGreg Roach $note = Registry::noteFactory()->make($xref, $tree); 883d45701ccSGreg Roach $note = Auth::checkNoteAccess($note); 8845a78cd34SGreg Roach 885d45701ccSGreg Roach $this->addNoteToCart($note); 8865a78cd34SGreg Roach 8876ccdf4f0SGreg Roach return redirect($note->url()); 8885a78cd34SGreg Roach } 8895a78cd34SGreg Roach 8905a78cd34SGreg Roach /** 8916ccdf4f0SGreg Roach * @param ServerRequestInterface $request 8925a78cd34SGreg Roach * 8936ccdf4f0SGreg Roach * @return ResponseInterface 8945a78cd34SGreg Roach */ 89557ab2231SGreg Roach public function getAddRepositoryAction(ServerRequestInterface $request): ResponseInterface 896c1010edaSGreg Roach { 89757ab2231SGreg Roach $tree = $request->getAttribute('tree'); 89875964c75SGreg Roach assert($tree instanceof Tree); 8995229eadeSGreg Roach 900d45701ccSGreg Roach $xref = $request->getQueryParams()['xref'] ?? ''; 9015a78cd34SGreg Roach 9026b9cb339SGreg Roach $repository = Registry::repositoryFactory()->make($xref, $tree); 903d45701ccSGreg Roach $repository = Auth::checkRepositoryAccess($repository); 904d45701ccSGreg Roach $name = $repository->fullName(); 9055a78cd34SGreg Roach 906d45701ccSGreg Roach $options = [ 90703f99a78SGreg Roach self::ADD_RECORD_ONLY => $name, 908d45701ccSGreg Roach ]; 9095a78cd34SGreg Roach 910d45701ccSGreg Roach $title = I18N::translate('Add %s to the clippings cart', $name); 9115a78cd34SGreg Roach 9125a78cd34SGreg Roach return $this->viewResponse('modules/clippings/add-options', [ 9135a78cd34SGreg Roach 'options' => $options, 9145a78cd34SGreg Roach 'record' => $repository, 9155a78cd34SGreg Roach 'title' => $title, 9165a78cd34SGreg Roach 'tree' => $tree, 9175a78cd34SGreg Roach ]); 9185a78cd34SGreg Roach } 9195a78cd34SGreg Roach 9205a78cd34SGreg Roach /** 9216ccdf4f0SGreg Roach * @param ServerRequestInterface $request 9225a78cd34SGreg Roach * 9236ccdf4f0SGreg Roach * @return ResponseInterface 9245a78cd34SGreg Roach */ 92557ab2231SGreg Roach public function postAddRepositoryAction(ServerRequestInterface $request): ResponseInterface 926c1010edaSGreg Roach { 92757ab2231SGreg Roach $tree = $request->getAttribute('tree'); 92875964c75SGreg Roach assert($tree instanceof Tree); 9295229eadeSGreg Roach 930d45701ccSGreg Roach $xref = $request->getQueryParams()['xref'] ?? ''; 9315a78cd34SGreg Roach 9326b9cb339SGreg Roach $repository = Registry::repositoryFactory()->make($xref, $tree); 933d45701ccSGreg Roach $repository = Auth::checkRepositoryAccess($repository); 9345a78cd34SGreg Roach 935d45701ccSGreg Roach $this->addRepositoryToCart($repository); 936d45701ccSGreg Roach 937d45701ccSGreg Roach foreach ($repository->linkedSources('REPO') as $source) { 938d45701ccSGreg Roach $this->addSourceToCart($source); 9395a78cd34SGreg Roach } 9405a78cd34SGreg Roach 9416ccdf4f0SGreg Roach return redirect($repository->url()); 9425a78cd34SGreg Roach } 9435a78cd34SGreg Roach 9445a78cd34SGreg Roach /** 9456ccdf4f0SGreg Roach * @param ServerRequestInterface $request 9465a78cd34SGreg Roach * 9476ccdf4f0SGreg Roach * @return ResponseInterface 9485a78cd34SGreg Roach */ 94957ab2231SGreg Roach public function getAddSourceAction(ServerRequestInterface $request): ResponseInterface 950c1010edaSGreg Roach { 95157ab2231SGreg Roach $tree = $request->getAttribute('tree'); 95275964c75SGreg Roach assert($tree instanceof Tree); 9535229eadeSGreg Roach 954d45701ccSGreg Roach $xref = $request->getQueryParams()['xref'] ?? ''; 9555a78cd34SGreg Roach 9566b9cb339SGreg Roach $source = Registry::sourceFactory()->make($xref, $tree); 957d45701ccSGreg Roach $source = Auth::checkSourceAccess($source); 958d45701ccSGreg Roach $name = $source->fullName(); 9595a78cd34SGreg Roach 960d45701ccSGreg Roach $options = [ 96103f99a78SGreg Roach self::ADD_RECORD_ONLY => $name, 96203f99a78SGreg Roach self::ADD_LINKED_INDIVIDUALS => I18N::translate('%s and the individuals that reference it.', $name), 963d45701ccSGreg Roach ]; 9645a78cd34SGreg Roach 965d45701ccSGreg Roach $title = I18N::translate('Add %s to the clippings cart', $name); 9665a78cd34SGreg Roach 9675a78cd34SGreg Roach return $this->viewResponse('modules/clippings/add-options', [ 9685a78cd34SGreg Roach 'options' => $options, 9695a78cd34SGreg Roach 'record' => $source, 9705a78cd34SGreg Roach 'title' => $title, 9715a78cd34SGreg Roach 'tree' => $tree, 9725a78cd34SGreg Roach ]); 9735a78cd34SGreg Roach } 9745a78cd34SGreg Roach 9755a78cd34SGreg Roach /** 9766ccdf4f0SGreg Roach * @param ServerRequestInterface $request 9775a78cd34SGreg Roach * 9786ccdf4f0SGreg Roach * @return ResponseInterface 9795a78cd34SGreg Roach */ 98057ab2231SGreg Roach public function postAddSourceAction(ServerRequestInterface $request): ResponseInterface 981c1010edaSGreg Roach { 98257ab2231SGreg Roach $tree = $request->getAttribute('tree'); 98375964c75SGreg Roach assert($tree instanceof Tree); 9845229eadeSGreg Roach 985b46c87bdSGreg Roach $params = (array) $request->getParsedBody(); 986b46c87bdSGreg Roach 987d45701ccSGreg Roach $xref = $params['xref'] ?? ''; 988d45701ccSGreg Roach $option = $params['option'] ?? ''; 9895a78cd34SGreg Roach 9906b9cb339SGreg Roach $source = Registry::sourceFactory()->make($xref, $tree); 991d45701ccSGreg Roach $source = Auth::checkSourceAccess($source); 9925a78cd34SGreg Roach 993d45701ccSGreg Roach $this->addSourceToCart($source); 9945a78cd34SGreg Roach 99503f99a78SGreg Roach if ($option === self::ADD_LINKED_INDIVIDUALS) { 9965a78cd34SGreg Roach foreach ($source->linkedIndividuals('SOUR') as $individual) { 997d45701ccSGreg Roach $this->addIndividualToCart($individual); 9985a78cd34SGreg Roach } 9995a78cd34SGreg Roach foreach ($source->linkedFamilies('SOUR') as $family) { 1000d45701ccSGreg Roach $this->addFamilyToCart($family); 10015a78cd34SGreg Roach } 10025a78cd34SGreg Roach } 10035a78cd34SGreg Roach 10046ccdf4f0SGreg Roach return redirect($source->url()); 10055a78cd34SGreg Roach } 10065a78cd34SGreg Roach 10075a78cd34SGreg Roach /** 1008d45701ccSGreg Roach * @param ServerRequestInterface $request 10095a78cd34SGreg Roach * 1010d45701ccSGreg Roach * @return ResponseInterface 10115a78cd34SGreg Roach */ 1012d45701ccSGreg Roach public function getAddSubmitterAction(ServerRequestInterface $request): ResponseInterface 1013c1010edaSGreg Roach { 1014d45701ccSGreg Roach $tree = $request->getAttribute('tree'); 1015d45701ccSGreg Roach assert($tree instanceof Tree); 10165a78cd34SGreg Roach 1017d45701ccSGreg Roach $xref = $request->getQueryParams()['xref'] ?? ''; 10185a78cd34SGreg Roach 1019d45701ccSGreg Roach $submitter = Registry::submitterFactory()->make($xref, $tree); 1020d45701ccSGreg Roach $submitter = Auth::checkSubmitterAccess($submitter); 1021d45701ccSGreg Roach $name = $submitter->fullName(); 10225a78cd34SGreg Roach 1023d45701ccSGreg Roach $options = [ 102403f99a78SGreg Roach self::ADD_RECORD_ONLY => $name, 1025d45701ccSGreg Roach ]; 10265a78cd34SGreg Roach 1027d45701ccSGreg Roach $title = I18N::translate('Add %s to the clippings cart', $name); 10285a78cd34SGreg Roach 1029d45701ccSGreg Roach return $this->viewResponse('modules/clippings/add-options', [ 1030d45701ccSGreg Roach 'options' => $options, 1031d45701ccSGreg Roach 'record' => $submitter, 1032d45701ccSGreg Roach 'title' => $title, 1033d45701ccSGreg Roach 'tree' => $tree, 1034d45701ccSGreg Roach ]); 10355a78cd34SGreg Roach } 10365a78cd34SGreg Roach 10375a78cd34SGreg Roach /** 1038d45701ccSGreg Roach * @param ServerRequestInterface $request 10395a78cd34SGreg Roach * 1040d45701ccSGreg Roach * @return ResponseInterface 10415a78cd34SGreg Roach */ 1042d45701ccSGreg Roach public function postAddSubmitterAction(ServerRequestInterface $request): ResponseInterface 1043d45701ccSGreg Roach { 1044d45701ccSGreg Roach $tree = $request->getAttribute('tree'); 1045d45701ccSGreg Roach assert($tree instanceof Tree); 1046d45701ccSGreg Roach 1047d45701ccSGreg Roach $xref = $request->getQueryParams()['xref'] ?? ''; 1048d45701ccSGreg Roach 1049d45701ccSGreg Roach $submitter = Registry::submitterFactory()->make($xref, $tree); 1050d45701ccSGreg Roach $submitter = Auth::checkSubmitterAccess($submitter); 1051d45701ccSGreg Roach 1052d45701ccSGreg Roach $this->addSubmitterToCart($submitter); 1053d45701ccSGreg Roach 1054d45701ccSGreg Roach return redirect($submitter->url()); 1055d45701ccSGreg Roach } 1056d45701ccSGreg Roach 1057d45701ccSGreg Roach /** 1058d45701ccSGreg Roach * @param Family $family 1059d45701ccSGreg Roach */ 1060d45701ccSGreg Roach protected function addFamilyToCart(Family $family): void 1061c1010edaSGreg Roach { 10625a78cd34SGreg Roach $cart = Session::get('cart', []); 1063d45701ccSGreg Roach $tree = $family->tree()->name(); 1064d45701ccSGreg Roach $xref = $family->xref(); 10655a78cd34SGreg Roach 1066d45701ccSGreg Roach if (($cart[$tree][$xref] ?? false) === false) { 1067d45701ccSGreg Roach $cart[$tree][$xref] = true; 10685a78cd34SGreg Roach 1069d45701ccSGreg Roach Session::put('cart', $cart); 10705a78cd34SGreg Roach 1071d45701ccSGreg Roach foreach ($family->spouses() as $spouse) { 1072d45701ccSGreg Roach $this->addIndividualToCart($spouse); 10735a78cd34SGreg Roach } 10745a78cd34SGreg Roach 1075e8ded2caSGreg Roach $this->addLocationLinksToCart($family); 1076d45701ccSGreg Roach $this->addMediaLinksToCart($family); 1077d45701ccSGreg Roach $this->addNoteLinksToCart($family); 1078d45701ccSGreg Roach $this->addSourceLinksToCart($family); 1079d45701ccSGreg Roach $this->addSubmitterLinksToCart($family); 1080d45701ccSGreg Roach } 1081d45701ccSGreg Roach } 1082d45701ccSGreg Roach 1083d45701ccSGreg Roach /** 1084d45701ccSGreg Roach * @param Individual $individual 1085d45701ccSGreg Roach */ 1086d45701ccSGreg Roach protected function addIndividualToCart(Individual $individual): void 1087d45701ccSGreg Roach { 1088d45701ccSGreg Roach $cart = Session::get('cart', []); 1089d45701ccSGreg Roach $tree = $individual->tree()->name(); 1090d45701ccSGreg Roach $xref = $individual->xref(); 1091d45701ccSGreg Roach 1092d45701ccSGreg Roach if (($cart[$tree][$xref] ?? false) === false) { 1093d45701ccSGreg Roach $cart[$tree][$xref] = true; 1094d45701ccSGreg Roach 1095d45701ccSGreg Roach Session::put('cart', $cart); 1096d45701ccSGreg Roach 1097e8ded2caSGreg Roach $this->addLocationLinksToCart($individual); 1098d45701ccSGreg Roach $this->addMediaLinksToCart($individual); 1099d45701ccSGreg Roach $this->addNoteLinksToCart($individual); 1100d45701ccSGreg Roach $this->addSourceLinksToCart($individual); 1101d45701ccSGreg Roach } 1102d45701ccSGreg Roach } 1103d45701ccSGreg Roach 1104d45701ccSGreg Roach /** 1105e8ded2caSGreg Roach * @param Location $location 1106e8ded2caSGreg Roach */ 1107e8ded2caSGreg Roach protected function addLocationToCart(Location $location): void 1108e8ded2caSGreg Roach { 1109e8ded2caSGreg Roach $cart = Session::get('cart', []); 1110e8ded2caSGreg Roach $tree = $location->tree()->name(); 1111e8ded2caSGreg Roach $xref = $location->xref(); 1112e8ded2caSGreg Roach 1113e8ded2caSGreg Roach if (($cart[$tree][$xref] ?? false) === false) { 1114e8ded2caSGreg Roach $cart[$tree][$xref] = true; 1115e8ded2caSGreg Roach 1116e8ded2caSGreg Roach Session::put('cart', $cart); 1117e8ded2caSGreg Roach 1118e8ded2caSGreg Roach $this->addLocationLinksToCart($location); 1119e8ded2caSGreg Roach $this->addMediaLinksToCart($location); 1120e8ded2caSGreg Roach $this->addNoteLinksToCart($location); 1121e8ded2caSGreg Roach $this->addSourceLinksToCart($location); 1122e8ded2caSGreg Roach } 1123e8ded2caSGreg Roach } 1124e8ded2caSGreg Roach 1125e8ded2caSGreg Roach /** 1126e8ded2caSGreg Roach * @param GedcomRecord $record 1127e8ded2caSGreg Roach */ 1128e8ded2caSGreg Roach protected function addLocationLinksToCart(GedcomRecord $record): void 1129e8ded2caSGreg Roach { 1130e8ded2caSGreg Roach preg_match_all('/\n\d _LOC @(' . Gedcom::REGEX_XREF . ')@/', $record->gedcom(), $matches); 1131e8ded2caSGreg Roach 1132e8ded2caSGreg Roach foreach ($matches[1] as $xref) { 1133e8ded2caSGreg Roach $location = Registry::locationFactory()->make($xref, $record->tree()); 1134e8ded2caSGreg Roach 1135e8ded2caSGreg Roach if ($location instanceof Location && $location->canShow()) { 1136e8ded2caSGreg Roach $this->addLocationToCart($location); 1137e8ded2caSGreg Roach } 1138e8ded2caSGreg Roach } 1139e8ded2caSGreg Roach } 1140e8ded2caSGreg Roach 1141e8ded2caSGreg Roach /** 1142d45701ccSGreg Roach * @param Media $media 1143d45701ccSGreg Roach */ 1144d45701ccSGreg Roach protected function addMediaToCart(Media $media): void 1145d45701ccSGreg Roach { 1146d45701ccSGreg Roach $cart = Session::get('cart', []); 1147d45701ccSGreg Roach $tree = $media->tree()->name(); 1148d45701ccSGreg Roach $xref = $media->xref(); 1149d45701ccSGreg Roach 1150d45701ccSGreg Roach if (($cart[$tree][$xref] ?? false) === false) { 1151d45701ccSGreg Roach $cart[$tree][$xref] = true; 1152d45701ccSGreg Roach 1153d45701ccSGreg Roach Session::put('cart', $cart); 1154d45701ccSGreg Roach 1155d45701ccSGreg Roach $this->addNoteLinksToCart($media); 1156d45701ccSGreg Roach } 1157d45701ccSGreg Roach } 1158d45701ccSGreg Roach 1159d45701ccSGreg Roach /** 1160d45701ccSGreg Roach * @param GedcomRecord $record 1161d45701ccSGreg Roach */ 1162d45701ccSGreg Roach protected function addMediaLinksToCart(GedcomRecord $record): void 1163d45701ccSGreg Roach { 1164d45701ccSGreg Roach preg_match_all('/\n\d OBJE @(' . Gedcom::REGEX_XREF . ')@/', $record->gedcom(), $matches); 1165d45701ccSGreg Roach 1166d45701ccSGreg Roach foreach ($matches[1] as $xref) { 1167d45701ccSGreg Roach $media = Registry::mediaFactory()->make($xref, $record->tree()); 1168d45701ccSGreg Roach 1169d45701ccSGreg Roach if ($media instanceof Media && $media->canShow()) { 1170d45701ccSGreg Roach $this->addMediaToCart($media); 1171d45701ccSGreg Roach } 1172d45701ccSGreg Roach } 1173d45701ccSGreg Roach } 1174d45701ccSGreg Roach 1175d45701ccSGreg Roach /** 1176d45701ccSGreg Roach * @param Note $note 1177d45701ccSGreg Roach */ 1178d45701ccSGreg Roach protected function addNoteToCart(Note $note): void 1179d45701ccSGreg Roach { 1180d45701ccSGreg Roach $cart = Session::get('cart', []); 1181d45701ccSGreg Roach $tree = $note->tree()->name(); 1182d45701ccSGreg Roach $xref = $note->xref(); 1183d45701ccSGreg Roach 1184d45701ccSGreg Roach if (($cart[$tree][$xref] ?? false) === false) { 1185d45701ccSGreg Roach $cart[$tree][$xref] = true; 1186d45701ccSGreg Roach 11875a78cd34SGreg Roach Session::put('cart', $cart); 11885a78cd34SGreg Roach } 1189d45701ccSGreg Roach } 11905a78cd34SGreg Roach 11915a78cd34SGreg Roach /** 1192d45701ccSGreg Roach * @param GedcomRecord $record 11935a78cd34SGreg Roach */ 1194d45701ccSGreg Roach protected function addNoteLinksToCart(GedcomRecord $record): void 1195d45701ccSGreg Roach { 1196d45701ccSGreg Roach preg_match_all('/\n\d NOTE @(' . Gedcom::REGEX_XREF . ')@/', $record->gedcom(), $matches); 1197d45701ccSGreg Roach 1198d45701ccSGreg Roach foreach ($matches[1] as $xref) { 1199d45701ccSGreg Roach $note = Registry::noteFactory()->make($xref, $record->tree()); 1200d45701ccSGreg Roach 1201d45701ccSGreg Roach if ($note instanceof Note && $note->canShow()) { 1202d45701ccSGreg Roach $this->addNoteToCart($note); 1203d45701ccSGreg Roach } 1204d45701ccSGreg Roach } 1205d45701ccSGreg Roach } 1206d45701ccSGreg Roach 1207d45701ccSGreg Roach /** 1208d45701ccSGreg Roach * @param Source $source 1209d45701ccSGreg Roach */ 1210d45701ccSGreg Roach protected function addSourceToCart(Source $source): void 1211c1010edaSGreg Roach { 12125a78cd34SGreg Roach $cart = Session::get('cart', []); 1213d45701ccSGreg Roach $tree = $source->tree()->name(); 1214d45701ccSGreg Roach $xref = $source->xref(); 12155a78cd34SGreg Roach 1216d45701ccSGreg Roach if (($cart[$tree][$xref] ?? false) === false) { 1217d45701ccSGreg Roach $cart[$tree][$xref] = true; 1218d45701ccSGreg Roach 1219d45701ccSGreg Roach Session::put('cart', $cart); 1220d45701ccSGreg Roach 1221d45701ccSGreg Roach $this->addNoteLinksToCart($source); 1222d45701ccSGreg Roach $this->addRepositoryLinksToCart($source); 1223d45701ccSGreg Roach } 1224d45701ccSGreg Roach } 1225d45701ccSGreg Roach 1226d45701ccSGreg Roach /** 1227d45701ccSGreg Roach * @param GedcomRecord $record 1228d45701ccSGreg Roach */ 1229d45701ccSGreg Roach protected function addSourceLinksToCart(GedcomRecord $record): void 1230d45701ccSGreg Roach { 1231d45701ccSGreg Roach preg_match_all('/\n\d SOUR @(' . Gedcom::REGEX_XREF . ')@/', $record->gedcom(), $matches); 1232d45701ccSGreg Roach 1233d45701ccSGreg Roach foreach ($matches[1] as $xref) { 1234d45701ccSGreg Roach $source = Registry::sourceFactory()->make($xref, $record->tree()); 1235d45701ccSGreg Roach 1236d45701ccSGreg Roach if ($source instanceof Source && $source->canShow()) { 1237d45701ccSGreg Roach $this->addSourceToCart($source); 1238d45701ccSGreg Roach } 1239d45701ccSGreg Roach } 1240d45701ccSGreg Roach } 1241d45701ccSGreg Roach 1242d45701ccSGreg Roach /** 1243d45701ccSGreg Roach * @param Repository $repository 1244d45701ccSGreg Roach */ 1245d45701ccSGreg Roach protected function addRepositoryToCart(Repository $repository): void 1246d45701ccSGreg Roach { 1247d45701ccSGreg Roach $cart = Session::get('cart', []); 1248d45701ccSGreg Roach $tree = $repository->tree()->name(); 1249d45701ccSGreg Roach $xref = $repository->xref(); 1250d45701ccSGreg Roach 1251d45701ccSGreg Roach if (($cart[$tree][$xref] ?? false) === false) { 1252d45701ccSGreg Roach $cart[$tree][$xref] = true; 1253d45701ccSGreg Roach 1254d45701ccSGreg Roach Session::put('cart', $cart); 1255d45701ccSGreg Roach 1256d45701ccSGreg Roach $this->addNoteLinksToCart($repository); 1257d45701ccSGreg Roach } 1258d45701ccSGreg Roach } 1259d45701ccSGreg Roach 1260d45701ccSGreg Roach /** 1261d45701ccSGreg Roach * @param GedcomRecord $record 1262d45701ccSGreg Roach */ 1263d45701ccSGreg Roach protected function addRepositoryLinksToCart(GedcomRecord $record): void 1264d45701ccSGreg Roach { 1265d45701ccSGreg Roach preg_match_all('/\n\d REPO @(' . Gedcom::REGEX_XREF . '@)/', $record->gedcom(), $matches); 1266d45701ccSGreg Roach 1267d45701ccSGreg Roach foreach ($matches[1] as $xref) { 1268d45701ccSGreg Roach $repository = Registry::repositoryFactory()->make($xref, $record->tree()); 1269d45701ccSGreg Roach 1270d45701ccSGreg Roach if ($repository instanceof Repository && $repository->canShow()) { 1271d45701ccSGreg Roach $this->addRepositoryToCart($repository); 1272d45701ccSGreg Roach } 1273d45701ccSGreg Roach } 1274d45701ccSGreg Roach } 1275d45701ccSGreg Roach 1276d45701ccSGreg Roach /** 1277d45701ccSGreg Roach * @param Submitter $submitter 1278d45701ccSGreg Roach */ 1279d45701ccSGreg Roach protected function addSubmitterToCart(Submitter $submitter): void 1280d45701ccSGreg Roach { 1281d45701ccSGreg Roach $cart = Session::get('cart', []); 1282d45701ccSGreg Roach $tree = $submitter->tree()->name(); 1283d45701ccSGreg Roach $xref = $submitter->xref(); 1284d45701ccSGreg Roach 1285d45701ccSGreg Roach if (($cart[$tree][$xref] ?? false) === false) { 1286d45701ccSGreg Roach $cart[$tree][$xref] = true; 1287d45701ccSGreg Roach 1288d45701ccSGreg Roach Session::put('cart', $cart); 1289d45701ccSGreg Roach 1290d45701ccSGreg Roach $this->addNoteLinksToCart($submitter); 1291d45701ccSGreg Roach } 1292d45701ccSGreg Roach } 1293d45701ccSGreg Roach 1294d45701ccSGreg Roach /** 1295d45701ccSGreg Roach * @param GedcomRecord $record 1296d45701ccSGreg Roach */ 1297d45701ccSGreg Roach protected function addSubmitterLinksToCart(GedcomRecord $record): void 1298d45701ccSGreg Roach { 1299d45701ccSGreg Roach preg_match_all('/\n\d SUBM @(' . Gedcom::REGEX_XREF . ')@/', $record->gedcom(), $matches); 1300d45701ccSGreg Roach 1301d45701ccSGreg Roach foreach ($matches[1] as $xref) { 1302d45701ccSGreg Roach $submitter = Registry::submitterFactory()->make($xref, $record->tree()); 1303d45701ccSGreg Roach 1304d45701ccSGreg Roach if ($submitter instanceof Submitter && $submitter->canShow()) { 1305d45701ccSGreg Roach $this->addSubmitterToCart($submitter); 1306d45701ccSGreg Roach } 1307d45701ccSGreg Roach } 13085a78cd34SGreg Roach } 13098c2e8227SGreg Roach} 1310