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 113ca47b2adSGreg Roach private GedcomExportService $gedcom_export_service; 11469c05a6eSGreg Roach 115ca47b2adSGreg Roach private UserService $user_service; 116ca47b2adSGreg Roach 117ca47b2adSGreg Roach private ResponseFactoryInterface $response_factory; 118ca47b2adSGreg Roach 119ca47b2adSGreg Roach private StreamFactoryInterface $stream_factory; 120e5a6b4d4SGreg Roach 121e5a6b4d4SGreg Roach /** 122e5a6b4d4SGreg Roach * ClippingsCartModule constructor. 123e5a6b4d4SGreg Roach * 12469c05a6eSGreg Roach * @param GedcomExportService $gedcom_export_service 125ca47b2adSGreg Roach * @param ResponseFactoryInterface $response_factory 126ca47b2adSGreg Roach * @param StreamFactoryInterface $stream_factory 127e5a6b4d4SGreg Roach * @param UserService $user_service 128e5a6b4d4SGreg Roach */ 129ca47b2adSGreg Roach public function __construct( 130ca47b2adSGreg Roach GedcomExportService $gedcom_export_service, 131ca47b2adSGreg Roach ResponseFactoryInterface $response_factory, 132ca47b2adSGreg Roach StreamFactoryInterface $stream_factory, 133ca47b2adSGreg Roach UserService $user_service 134ca47b2adSGreg Roach ) { 13569c05a6eSGreg Roach $this->gedcom_export_service = $gedcom_export_service; 136ca47b2adSGreg Roach $this->response_factory = $response_factory; 137ca47b2adSGreg 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 359*f566cb16SGreg Roach $records->add($record); 360*f566cb16SGreg Roach 361*f566cb16SGreg Roach if ($object instanceof Media) { 36255167344SGreg Roach // Add the media files to the archive 3635a78cd34SGreg Roach foreach ($object->mediaFiles() as $media_file) { 364fa695506SGreg Roach $from = $media_file->filename(); 365fa695506SGreg Roach $to = $path . $media_file->filename(); 366f0448b68SGreg Roach if (!$media_file->isExternal() && $media_filesystem->fileExists($from)) { 367fa695506SGreg Roach $zip_filesystem->writeStream($to, $media_filesystem->readStream($from)); 3685a78cd34SGreg Roach } 3695a78cd34SGreg Roach } 3708c2e8227SGreg Roach } 3718c2e8227SGreg Roach } 3728c2e8227SGreg Roach } 3738c2e8227SGreg Roach 37469c05a6eSGreg Roach $stream = fopen('php://temp', 'wb+'); 3755a78cd34SGreg Roach 37669c05a6eSGreg Roach if ($stream === false) { 37769c05a6eSGreg Roach throw new RuntimeException('Failed to create temporary stream'); 3788c2e8227SGreg Roach } 379cbc1590aSGreg Roach 38069c05a6eSGreg Roach // We have already applied privacy filtering, so do not do it again. 38169c05a6eSGreg Roach $this->gedcom_export_service->export($tree, $stream, false, $encoding, Auth::PRIV_HIDE, $path, $records); 38269c05a6eSGreg Roach rewind($stream); 38369c05a6eSGreg Roach 3845a78cd34SGreg Roach // Finally add the GEDCOM file to the .ZIP file. 38569c05a6eSGreg Roach $zip_filesystem->writeStream('clippings.ged', $stream); 3865a78cd34SGreg Roach 3876ccdf4f0SGreg Roach // Use a stream, so that we do not have to load the entire file into memory. 388ca47b2adSGreg Roach $stream = $this->stream_factory->createStreamFromFile($temp_zip_file); 3895a78cd34SGreg Roach 390ca47b2adSGreg Roach return $this->response_factory->createResponse() 3916ccdf4f0SGreg Roach ->withBody($stream) 3921b3d4731SGreg Roach ->withHeader('Content-Type', 'application/zip') 393bed27cedSGreg Roach ->withHeader('Content-Disposition', 'attachment; filename="clippings.zip'); 3948c2e8227SGreg Roach } 3958c2e8227SGreg Roach 3968c2e8227SGreg Roach /** 39757ab2231SGreg Roach * @param ServerRequestInterface $request 39876692c8bSGreg Roach * 3996ccdf4f0SGreg Roach * @return ResponseInterface 4008c2e8227SGreg Roach */ 40157ab2231SGreg Roach public function getEmptyAction(ServerRequestInterface $request): ResponseInterface 402c1010edaSGreg Roach { 40357ab2231SGreg Roach $tree = $request->getAttribute('tree'); 4044ea62551SGreg Roach assert($tree instanceof Tree); 4054ea62551SGreg Roach 4065a78cd34SGreg Roach $cart = Session::get('cart', []); 407aa6f03bbSGreg Roach $cart[$tree->name()] = []; 4085a78cd34SGreg Roach Session::put('cart', $cart); 4098c2e8227SGreg Roach 410c1010edaSGreg Roach $url = route('module', [ 41126684e68SGreg Roach 'module' => $this->name(), 412c1010edaSGreg Roach 'action' => 'Show', 413d72b284aSGreg Roach 'tree' => $tree->name(), 414c1010edaSGreg Roach ]); 4155a78cd34SGreg Roach 4166ccdf4f0SGreg Roach return redirect($url); 4175a78cd34SGreg Roach } 4185a78cd34SGreg Roach 4195a78cd34SGreg Roach /** 4206ccdf4f0SGreg Roach * @param ServerRequestInterface $request 4215a78cd34SGreg Roach * 4226ccdf4f0SGreg Roach * @return ResponseInterface 4235a78cd34SGreg Roach */ 42457ab2231SGreg Roach public function postRemoveAction(ServerRequestInterface $request): ResponseInterface 425c1010edaSGreg Roach { 42657ab2231SGreg Roach $tree = $request->getAttribute('tree'); 42775964c75SGreg Roach assert($tree instanceof Tree); 4285229eadeSGreg Roach 429d45701ccSGreg Roach $xref = $request->getQueryParams()['xref'] ?? ''; 4305a78cd34SGreg Roach 4315a78cd34SGreg Roach $cart = Session::get('cart', []); 432aa6f03bbSGreg Roach unset($cart[$tree->name()][$xref]); 4335a78cd34SGreg Roach Session::put('cart', $cart); 4345a78cd34SGreg Roach 435c1010edaSGreg Roach $url = route('module', [ 43626684e68SGreg Roach 'module' => $this->name(), 437c1010edaSGreg Roach 'action' => 'Show', 438d72b284aSGreg Roach 'tree' => $tree->name(), 439c1010edaSGreg Roach ]); 4405a78cd34SGreg Roach 4416ccdf4f0SGreg Roach return redirect($url); 4425a78cd34SGreg Roach } 4435a78cd34SGreg Roach 4445a78cd34SGreg Roach /** 44557ab2231SGreg Roach * @param ServerRequestInterface $request 4465a78cd34SGreg Roach * 4476ccdf4f0SGreg Roach * @return ResponseInterface 4485a78cd34SGreg Roach */ 44957ab2231SGreg Roach public function getShowAction(ServerRequestInterface $request): ResponseInterface 450c1010edaSGreg Roach { 45157ab2231SGreg Roach $tree = $request->getAttribute('tree'); 45275964c75SGreg Roach assert($tree instanceof Tree); 45357ab2231SGreg Roach 4545a78cd34SGreg Roach return $this->viewResponse('modules/clippings/show', [ 45577b78a63SRichard Cissée 'module' => $this->name(), 4565a78cd34SGreg Roach 'records' => $this->allRecordsInCart($tree), 4575a78cd34SGreg Roach 'title' => I18N::translate('Family tree clippings cart'), 4585a78cd34SGreg Roach 'tree' => $tree, 4595a78cd34SGreg Roach ]); 4605a78cd34SGreg Roach } 4615a78cd34SGreg Roach 4625a78cd34SGreg Roach /** 463d45701ccSGreg Roach * Get all the records in the cart. 464d45701ccSGreg Roach * 465d45701ccSGreg Roach * @param Tree $tree 466d45701ccSGreg Roach * 467d45701ccSGreg Roach * @return GedcomRecord[] 468d45701ccSGreg Roach */ 469d45701ccSGreg Roach private function allRecordsInCart(Tree $tree): array 470d45701ccSGreg Roach { 471d45701ccSGreg Roach $cart = Session::get('cart', []); 472d45701ccSGreg Roach 473d45701ccSGreg Roach $xrefs = array_keys($cart[$tree->name()] ?? []); 474d45701ccSGreg Roach $xrefs = array_map('strval', $xrefs); // PHP converts numeric keys to integers. 475d45701ccSGreg Roach 476d45701ccSGreg Roach // Fetch all the records in the cart. 477d45701ccSGreg Roach $records = array_map(static function (string $xref) use ($tree): ?GedcomRecord { 478d45701ccSGreg Roach return Registry::gedcomRecordFactory()->make($xref, $tree); 479d45701ccSGreg Roach }, $xrefs); 480d45701ccSGreg Roach 481d45701ccSGreg Roach // Some records may have been deleted after they were added to the cart. 482d45701ccSGreg Roach $records = array_filter($records); 483d45701ccSGreg Roach 484d45701ccSGreg Roach // Group and sort. 485d45701ccSGreg Roach uasort($records, static function (GedcomRecord $x, GedcomRecord $y): int { 486d45701ccSGreg Roach return $x->tag() <=> $y->tag() ?: GedcomRecord::nameComparator()($x, $y); 487d45701ccSGreg Roach }); 488d45701ccSGreg Roach 489d45701ccSGreg Roach return $records; 490d45701ccSGreg Roach } 491d45701ccSGreg Roach 492d45701ccSGreg Roach /** 4936ccdf4f0SGreg Roach * @param ServerRequestInterface $request 4945a78cd34SGreg Roach * 4956ccdf4f0SGreg Roach * @return ResponseInterface 4965a78cd34SGreg Roach */ 49757ab2231SGreg Roach public function getAddFamilyAction(ServerRequestInterface $request): ResponseInterface 498c1010edaSGreg Roach { 49957ab2231SGreg Roach $tree = $request->getAttribute('tree'); 50075964c75SGreg Roach assert($tree instanceof Tree); 5015229eadeSGreg Roach 502d45701ccSGreg Roach $xref = $request->getQueryParams()['xref'] ?? ''; 5035a78cd34SGreg Roach 5046b9cb339SGreg Roach $family = Registry::familyFactory()->make($xref, $tree); 505d45701ccSGreg Roach $family = Auth::checkFamilyAccess($family); 506d45701ccSGreg Roach $name = $family->fullName(); 5075a78cd34SGreg Roach 508d45701ccSGreg Roach $options = [ 50903f99a78SGreg Roach self::ADD_RECORD_ONLY => $name, 510bbb76c12SGreg Roach /* I18N: %s is a family (husband + wife) */ 51103f99a78SGreg Roach self::ADD_CHILDREN => I18N::translate('%s and their children', $name), 512bbb76c12SGreg Roach /* I18N: %s is a family (husband + wife) */ 51303f99a78SGreg Roach self::ADD_DESCENDANTS => I18N::translate('%s and their descendants', $name), 5145a78cd34SGreg Roach ]; 515d45701ccSGreg Roach 516d45701ccSGreg Roach $title = I18N::translate('Add %s to the clippings cart', $name); 517d45701ccSGreg Roach 518d45701ccSGreg Roach return $this->viewResponse('modules/clippings/add-options', [ 519d45701ccSGreg Roach 'options' => $options, 520d45701ccSGreg Roach 'record' => $family, 521d45701ccSGreg Roach 'title' => $title, 522d45701ccSGreg Roach 'tree' => $tree, 523d45701ccSGreg Roach ]); 5245a78cd34SGreg Roach } 5255a78cd34SGreg Roach 5265a78cd34SGreg Roach /** 5276ccdf4f0SGreg Roach * @param ServerRequestInterface $request 5285a78cd34SGreg Roach * 5296ccdf4f0SGreg Roach * @return ResponseInterface 5305a78cd34SGreg Roach */ 53157ab2231SGreg Roach public function postAddFamilyAction(ServerRequestInterface $request): ResponseInterface 532c1010edaSGreg Roach { 53357ab2231SGreg Roach $tree = $request->getAttribute('tree'); 5344ea62551SGreg Roach assert($tree instanceof Tree); 5354ea62551SGreg Roach 536b46c87bdSGreg Roach $params = (array) $request->getParsedBody(); 537b46c87bdSGreg Roach 538d45701ccSGreg Roach $xref = $params['xref'] ?? ''; 539d45701ccSGreg Roach $option = $params['option'] ?? ''; 5405a78cd34SGreg Roach 5416b9cb339SGreg Roach $family = Registry::familyFactory()->make($xref, $tree); 542d45701ccSGreg Roach $family = Auth::checkFamilyAccess($family); 5435a78cd34SGreg Roach 5445a78cd34SGreg Roach switch ($option) { 54503f99a78SGreg Roach case self::ADD_RECORD_ONLY: 5465a78cd34SGreg Roach $this->addFamilyToCart($family); 5475a78cd34SGreg Roach break; 5485a78cd34SGreg Roach 54903f99a78SGreg Roach case self::ADD_CHILDREN: 5505a78cd34SGreg Roach $this->addFamilyAndChildrenToCart($family); 5515a78cd34SGreg Roach break; 5525a78cd34SGreg Roach 55303f99a78SGreg Roach case self::ADD_DESCENDANTS: 5545a78cd34SGreg Roach $this->addFamilyAndDescendantsToCart($family); 5555a78cd34SGreg Roach break; 5565a78cd34SGreg Roach } 5575a78cd34SGreg Roach 5586ccdf4f0SGreg Roach return redirect($family->url()); 5595a78cd34SGreg Roach } 5605a78cd34SGreg Roach 5615a78cd34SGreg Roach 5625a78cd34SGreg Roach /** 5635a78cd34SGreg Roach * @param Family $family 56418d7a90dSGreg Roach * 56518d7a90dSGreg Roach * @return void 5665a78cd34SGreg Roach */ 567d45701ccSGreg Roach protected function addFamilyAndChildrenToCart(Family $family): void 568c1010edaSGreg Roach { 569d45701ccSGreg Roach $this->addFamilyToCart($family); 5705a78cd34SGreg Roach 57139ca88baSGreg Roach foreach ($family->children() as $child) { 572d45701ccSGreg Roach $this->addIndividualToCart($child); 5735a78cd34SGreg Roach } 5745a78cd34SGreg Roach } 5755a78cd34SGreg Roach 5765a78cd34SGreg Roach /** 5775a78cd34SGreg Roach * @param Family $family 57818d7a90dSGreg Roach * 57918d7a90dSGreg Roach * @return void 5805a78cd34SGreg Roach */ 581d45701ccSGreg Roach protected function addFamilyAndDescendantsToCart(Family $family): void 582c1010edaSGreg Roach { 583d45701ccSGreg Roach $this->addFamilyAndChildrenToCart($family); 5845a78cd34SGreg Roach 58539ca88baSGreg Roach foreach ($family->children() as $child) { 58639ca88baSGreg Roach foreach ($child->spouseFamilies() as $child_family) { 5875a78cd34SGreg Roach $this->addFamilyAndDescendantsToCart($child_family); 5885a78cd34SGreg Roach } 5895a78cd34SGreg Roach } 5905a78cd34SGreg Roach } 5915a78cd34SGreg Roach 5925a78cd34SGreg Roach /** 5936ccdf4f0SGreg Roach * @param ServerRequestInterface $request 5945a78cd34SGreg Roach * 5956ccdf4f0SGreg Roach * @return ResponseInterface 5965a78cd34SGreg Roach */ 59757ab2231SGreg Roach public function getAddIndividualAction(ServerRequestInterface $request): ResponseInterface 598c1010edaSGreg Roach { 59957ab2231SGreg Roach $tree = $request->getAttribute('tree'); 60075964c75SGreg Roach assert($tree instanceof Tree); 6015229eadeSGreg Roach 602d45701ccSGreg Roach $xref = $request->getQueryParams()['xref'] ?? ''; 6035a78cd34SGreg Roach 6046b9cb339SGreg Roach $individual = Registry::individualFactory()->make($xref, $tree); 605d45701ccSGreg Roach $individual = Auth::checkIndividualAccess($individual); 606d45701ccSGreg Roach $name = $individual->fullName(); 6075a78cd34SGreg Roach 60839ca88baSGreg Roach if ($individual->sex() === 'F') { 609d45701ccSGreg Roach $options = [ 61003f99a78SGreg Roach self::ADD_RECORD_ONLY => $name, 61103f99a78SGreg Roach self::ADD_PARENT_FAMILIES => I18N::translate('%s, her parents and siblings', $name), 61203f99a78SGreg Roach self::ADD_SPOUSE_FAMILIES => I18N::translate('%s, her spouses and children', $name), 61303f99a78SGreg Roach self::ADD_ANCESTORS => I18N::translate('%s and her ancestors', $name), 61403f99a78SGreg Roach self::ADD_ANCESTOR_FAMILIES => I18N::translate('%s, her ancestors and their families', $name), 61503f99a78SGreg Roach self::ADD_DESCENDANTS => I18N::translate('%s, her spouses and descendants', $name), 6165a78cd34SGreg Roach ]; 617d45701ccSGreg Roach } else { 618d45701ccSGreg Roach $options = [ 61903f99a78SGreg Roach self::ADD_RECORD_ONLY => $name, 62003f99a78SGreg Roach self::ADD_PARENT_FAMILIES => I18N::translate('%s, his parents and siblings', $name), 62103f99a78SGreg Roach self::ADD_SPOUSE_FAMILIES => I18N::translate('%s, his spouses and children', $name), 62203f99a78SGreg Roach self::ADD_ANCESTORS => I18N::translate('%s and his ancestors', $name), 62303f99a78SGreg Roach self::ADD_ANCESTOR_FAMILIES => I18N::translate('%s, his ancestors and their families', $name), 62403f99a78SGreg Roach self::ADD_DESCENDANTS => I18N::translate('%s, his spouses and descendants', $name), 6255a78cd34SGreg Roach ]; 6265a78cd34SGreg Roach } 6275a78cd34SGreg Roach 628d45701ccSGreg Roach $title = I18N::translate('Add %s to the clippings cart', $name); 629d45701ccSGreg Roach 630d45701ccSGreg Roach return $this->viewResponse('modules/clippings/add-options', [ 631d45701ccSGreg Roach 'options' => $options, 632d45701ccSGreg Roach 'record' => $individual, 633d45701ccSGreg Roach 'title' => $title, 634d45701ccSGreg Roach 'tree' => $tree, 635d45701ccSGreg Roach ]); 636d45701ccSGreg Roach } 637d45701ccSGreg Roach 6385a78cd34SGreg Roach /** 6396ccdf4f0SGreg Roach * @param ServerRequestInterface $request 6405a78cd34SGreg Roach * 6416ccdf4f0SGreg Roach * @return ResponseInterface 6425a78cd34SGreg Roach */ 64357ab2231SGreg Roach public function postAddIndividualAction(ServerRequestInterface $request): ResponseInterface 644c1010edaSGreg Roach { 64557ab2231SGreg Roach $tree = $request->getAttribute('tree'); 6464ea62551SGreg Roach assert($tree instanceof Tree); 6474ea62551SGreg Roach 648b46c87bdSGreg Roach $params = (array) $request->getParsedBody(); 649b46c87bdSGreg Roach 650d45701ccSGreg Roach $xref = $params['xref'] ?? ''; 651d45701ccSGreg Roach $option = $params['option'] ?? ''; 6525a78cd34SGreg Roach 6536b9cb339SGreg Roach $individual = Registry::individualFactory()->make($xref, $tree); 654d45701ccSGreg Roach $individual = Auth::checkIndividualAccess($individual); 6555a78cd34SGreg Roach 6565a78cd34SGreg Roach switch ($option) { 65703f99a78SGreg Roach case self::ADD_RECORD_ONLY: 658d45701ccSGreg Roach $this->addIndividualToCart($individual); 6595a78cd34SGreg Roach break; 6605a78cd34SGreg Roach 66103f99a78SGreg Roach case self::ADD_PARENT_FAMILIES: 66239ca88baSGreg Roach foreach ($individual->childFamilies() as $family) { 6635a78cd34SGreg Roach $this->addFamilyAndChildrenToCart($family); 6645a78cd34SGreg Roach } 6655a78cd34SGreg Roach break; 6665a78cd34SGreg Roach 66703f99a78SGreg Roach case self::ADD_SPOUSE_FAMILIES: 66839ca88baSGreg Roach foreach ($individual->spouseFamilies() as $family) { 6695a78cd34SGreg Roach $this->addFamilyAndChildrenToCart($family); 6705a78cd34SGreg Roach } 6715a78cd34SGreg Roach break; 6725a78cd34SGreg Roach 67303f99a78SGreg Roach case self::ADD_ANCESTORS: 6745a78cd34SGreg Roach $this->addAncestorsToCart($individual); 6755a78cd34SGreg Roach break; 6765a78cd34SGreg Roach 67703f99a78SGreg Roach case self::ADD_ANCESTOR_FAMILIES: 6785a78cd34SGreg Roach $this->addAncestorFamiliesToCart($individual); 6795a78cd34SGreg Roach break; 6805a78cd34SGreg Roach 68103f99a78SGreg Roach case self::ADD_DESCENDANTS: 68239ca88baSGreg Roach foreach ($individual->spouseFamilies() as $family) { 6835a78cd34SGreg Roach $this->addFamilyAndDescendantsToCart($family); 6845a78cd34SGreg Roach } 6855a78cd34SGreg Roach break; 6865a78cd34SGreg Roach } 6875a78cd34SGreg Roach 6886ccdf4f0SGreg Roach return redirect($individual->url()); 6895a78cd34SGreg Roach } 6905a78cd34SGreg Roach 6915a78cd34SGreg Roach /** 6925a78cd34SGreg Roach * @param Individual $individual 69318d7a90dSGreg Roach * 69418d7a90dSGreg Roach * @return void 6955a78cd34SGreg Roach */ 696d45701ccSGreg Roach protected function addAncestorsToCart(Individual $individual): void 697c1010edaSGreg Roach { 698d45701ccSGreg Roach $this->addIndividualToCart($individual); 6995a78cd34SGreg Roach 70039ca88baSGreg Roach foreach ($individual->childFamilies() as $family) { 701d45701ccSGreg Roach $this->addFamilyToCart($family); 7028df4c68dSGreg Roach 70339ca88baSGreg Roach foreach ($family->spouses() as $parent) { 7045a78cd34SGreg Roach $this->addAncestorsToCart($parent); 7055a78cd34SGreg Roach } 7065a78cd34SGreg Roach } 7075a78cd34SGreg Roach } 7085a78cd34SGreg Roach 7095a78cd34SGreg Roach /** 7105a78cd34SGreg Roach * @param Individual $individual 71118d7a90dSGreg Roach * 71218d7a90dSGreg Roach * @return void 7135a78cd34SGreg Roach */ 714d45701ccSGreg Roach protected function addAncestorFamiliesToCart(Individual $individual): void 715c1010edaSGreg Roach { 71639ca88baSGreg Roach foreach ($individual->childFamilies() as $family) { 7175a78cd34SGreg Roach $this->addFamilyAndChildrenToCart($family); 7188df4c68dSGreg Roach 71939ca88baSGreg Roach foreach ($family->spouses() as $parent) { 720cad6d3f3SGreg Roach $this->addAncestorFamiliesToCart($parent); 7215a78cd34SGreg Roach } 7225a78cd34SGreg Roach } 7235a78cd34SGreg Roach } 7245a78cd34SGreg Roach 7255a78cd34SGreg Roach /** 7266ccdf4f0SGreg Roach * @param ServerRequestInterface $request 7275a78cd34SGreg Roach * 7286ccdf4f0SGreg Roach * @return ResponseInterface 7295a78cd34SGreg Roach */ 730e8ded2caSGreg Roach public function getAddLocationAction(ServerRequestInterface $request): ResponseInterface 731e8ded2caSGreg Roach { 732e8ded2caSGreg Roach $tree = $request->getAttribute('tree'); 733e8ded2caSGreg Roach assert($tree instanceof Tree); 734e8ded2caSGreg Roach 735e8ded2caSGreg Roach $xref = $request->getQueryParams()['xref'] ?? ''; 736e8ded2caSGreg Roach 737e8ded2caSGreg Roach $location = Registry::locationFactory()->make($xref, $tree); 738e8ded2caSGreg Roach $location = Auth::checkLocationAccess($location); 739e8ded2caSGreg Roach $name = $location->fullName(); 740e8ded2caSGreg Roach 741e8ded2caSGreg Roach $options = [ 74203f99a78SGreg Roach self::ADD_RECORD_ONLY => $name, 743e8ded2caSGreg Roach ]; 744e8ded2caSGreg Roach 745e8ded2caSGreg Roach $title = I18N::translate('Add %s to the clippings cart', $name); 746e8ded2caSGreg Roach 747e8ded2caSGreg Roach return $this->viewResponse('modules/clippings/add-options', [ 748e8ded2caSGreg Roach 'options' => $options, 749e8ded2caSGreg Roach 'record' => $location, 750e8ded2caSGreg Roach 'title' => $title, 751e8ded2caSGreg Roach 'tree' => $tree, 752e8ded2caSGreg Roach ]); 753e8ded2caSGreg Roach } 754e8ded2caSGreg Roach 755e8ded2caSGreg Roach /** 756e8ded2caSGreg Roach * @param ServerRequestInterface $request 757e8ded2caSGreg Roach * 758e8ded2caSGreg Roach * @return ResponseInterface 759e8ded2caSGreg Roach */ 760e8ded2caSGreg Roach public function postAddLocationAction(ServerRequestInterface $request): ResponseInterface 761e8ded2caSGreg Roach { 762e8ded2caSGreg Roach $tree = $request->getAttribute('tree'); 763e8ded2caSGreg Roach assert($tree instanceof Tree); 764e8ded2caSGreg Roach 765e8ded2caSGreg Roach $xref = $request->getQueryParams()['xref'] ?? ''; 766e8ded2caSGreg Roach 767e8ded2caSGreg Roach $location = Registry::locationFactory()->make($xref, $tree); 768e8ded2caSGreg Roach $location = Auth::checkLocationAccess($location); 769e8ded2caSGreg Roach 770e8ded2caSGreg Roach $this->addLocationToCart($location); 771e8ded2caSGreg Roach 772e8ded2caSGreg Roach return redirect($location->url()); 773e8ded2caSGreg Roach } 774e8ded2caSGreg Roach 775e8ded2caSGreg Roach /** 776e8ded2caSGreg Roach * @param ServerRequestInterface $request 777e8ded2caSGreg Roach * 778e8ded2caSGreg Roach * @return ResponseInterface 779e8ded2caSGreg Roach */ 78057ab2231SGreg Roach public function getAddMediaAction(ServerRequestInterface $request): ResponseInterface 781c1010edaSGreg Roach { 78257ab2231SGreg Roach $tree = $request->getAttribute('tree'); 78375964c75SGreg Roach assert($tree instanceof Tree); 7845229eadeSGreg Roach 785d45701ccSGreg Roach $xref = $request->getQueryParams()['xref'] ?? ''; 7865a78cd34SGreg Roach 7876b9cb339SGreg Roach $media = Registry::mediaFactory()->make($xref, $tree); 788d45701ccSGreg Roach $media = Auth::checkMediaAccess($media); 789d45701ccSGreg Roach $name = $media->fullName(); 7905a78cd34SGreg Roach 791d45701ccSGreg Roach $options = [ 79203f99a78SGreg Roach self::ADD_RECORD_ONLY => $name, 793d45701ccSGreg Roach ]; 7945a78cd34SGreg Roach 795d45701ccSGreg Roach $title = I18N::translate('Add %s to the clippings cart', $name); 7965a78cd34SGreg Roach 7975a78cd34SGreg Roach return $this->viewResponse('modules/clippings/add-options', [ 7985a78cd34SGreg Roach 'options' => $options, 7995a78cd34SGreg Roach 'record' => $media, 8005a78cd34SGreg Roach 'title' => $title, 8015a78cd34SGreg Roach 'tree' => $tree, 8025a78cd34SGreg Roach ]); 8035a78cd34SGreg Roach } 8045a78cd34SGreg Roach 8055a78cd34SGreg Roach /** 8066ccdf4f0SGreg Roach * @param ServerRequestInterface $request 8075a78cd34SGreg Roach * 8086ccdf4f0SGreg Roach * @return ResponseInterface 8095a78cd34SGreg Roach */ 81057ab2231SGreg Roach public function postAddMediaAction(ServerRequestInterface $request): ResponseInterface 811c1010edaSGreg Roach { 81257ab2231SGreg Roach $tree = $request->getAttribute('tree'); 81375964c75SGreg Roach assert($tree instanceof Tree); 8145229eadeSGreg Roach 815d45701ccSGreg Roach $xref = $request->getQueryParams()['xref'] ?? ''; 8165a78cd34SGreg Roach 8176b9cb339SGreg Roach $media = Registry::mediaFactory()->make($xref, $tree); 818d45701ccSGreg Roach $media = Auth::checkMediaAccess($media); 8195a78cd34SGreg Roach 820d45701ccSGreg Roach $this->addMediaToCart($media); 8215a78cd34SGreg Roach 8226ccdf4f0SGreg Roach return redirect($media->url()); 8235a78cd34SGreg Roach } 8245a78cd34SGreg Roach 8255a78cd34SGreg Roach /** 8266ccdf4f0SGreg Roach * @param ServerRequestInterface $request 8275a78cd34SGreg Roach * 8286ccdf4f0SGreg Roach * @return ResponseInterface 8295a78cd34SGreg Roach */ 83057ab2231SGreg Roach public function getAddNoteAction(ServerRequestInterface $request): ResponseInterface 831c1010edaSGreg Roach { 83257ab2231SGreg Roach $tree = $request->getAttribute('tree'); 83375964c75SGreg Roach assert($tree instanceof Tree); 8345229eadeSGreg Roach 835d45701ccSGreg Roach $xref = $request->getQueryParams()['xref'] ?? ''; 8365a78cd34SGreg Roach 8376b9cb339SGreg Roach $note = Registry::noteFactory()->make($xref, $tree); 838d45701ccSGreg Roach $note = Auth::checkNoteAccess($note); 839d45701ccSGreg Roach $name = $note->fullName(); 8405a78cd34SGreg Roach 841d45701ccSGreg Roach $options = [ 84203f99a78SGreg Roach self::ADD_RECORD_ONLY => $name, 843d45701ccSGreg Roach ]; 8445a78cd34SGreg Roach 845d45701ccSGreg Roach $title = I18N::translate('Add %s to the clippings cart', $name); 8465a78cd34SGreg Roach 8475a78cd34SGreg Roach return $this->viewResponse('modules/clippings/add-options', [ 8485a78cd34SGreg Roach 'options' => $options, 8495a78cd34SGreg Roach 'record' => $note, 8505a78cd34SGreg Roach 'title' => $title, 8515a78cd34SGreg Roach 'tree' => $tree, 8525a78cd34SGreg Roach ]); 8535a78cd34SGreg Roach } 8545a78cd34SGreg Roach 8555a78cd34SGreg Roach /** 8566ccdf4f0SGreg Roach * @param ServerRequestInterface $request 8575a78cd34SGreg Roach * 8586ccdf4f0SGreg Roach * @return ResponseInterface 8595a78cd34SGreg Roach */ 86057ab2231SGreg Roach public function postAddNoteAction(ServerRequestInterface $request): ResponseInterface 861c1010edaSGreg Roach { 86257ab2231SGreg Roach $tree = $request->getAttribute('tree'); 86375964c75SGreg Roach assert($tree instanceof Tree); 8645229eadeSGreg Roach 865d45701ccSGreg Roach $xref = $request->getQueryParams()['xref'] ?? ''; 8665a78cd34SGreg Roach 8676b9cb339SGreg Roach $note = Registry::noteFactory()->make($xref, $tree); 868d45701ccSGreg Roach $note = Auth::checkNoteAccess($note); 8695a78cd34SGreg Roach 870d45701ccSGreg Roach $this->addNoteToCart($note); 8715a78cd34SGreg Roach 8726ccdf4f0SGreg Roach return redirect($note->url()); 8735a78cd34SGreg Roach } 8745a78cd34SGreg Roach 8755a78cd34SGreg Roach /** 8766ccdf4f0SGreg Roach * @param ServerRequestInterface $request 8775a78cd34SGreg Roach * 8786ccdf4f0SGreg Roach * @return ResponseInterface 8795a78cd34SGreg Roach */ 88057ab2231SGreg Roach public function getAddRepositoryAction(ServerRequestInterface $request): ResponseInterface 881c1010edaSGreg Roach { 88257ab2231SGreg Roach $tree = $request->getAttribute('tree'); 88375964c75SGreg Roach assert($tree instanceof Tree); 8845229eadeSGreg Roach 885d45701ccSGreg Roach $xref = $request->getQueryParams()['xref'] ?? ''; 8865a78cd34SGreg Roach 8876b9cb339SGreg Roach $repository = Registry::repositoryFactory()->make($xref, $tree); 888d45701ccSGreg Roach $repository = Auth::checkRepositoryAccess($repository); 889d45701ccSGreg Roach $name = $repository->fullName(); 8905a78cd34SGreg Roach 891d45701ccSGreg Roach $options = [ 89203f99a78SGreg Roach self::ADD_RECORD_ONLY => $name, 893d45701ccSGreg Roach ]; 8945a78cd34SGreg Roach 895d45701ccSGreg Roach $title = I18N::translate('Add %s to the clippings cart', $name); 8965a78cd34SGreg Roach 8975a78cd34SGreg Roach return $this->viewResponse('modules/clippings/add-options', [ 8985a78cd34SGreg Roach 'options' => $options, 8995a78cd34SGreg Roach 'record' => $repository, 9005a78cd34SGreg Roach 'title' => $title, 9015a78cd34SGreg Roach 'tree' => $tree, 9025a78cd34SGreg Roach ]); 9035a78cd34SGreg Roach } 9045a78cd34SGreg Roach 9055a78cd34SGreg Roach /** 9066ccdf4f0SGreg Roach * @param ServerRequestInterface $request 9075a78cd34SGreg Roach * 9086ccdf4f0SGreg Roach * @return ResponseInterface 9095a78cd34SGreg Roach */ 91057ab2231SGreg Roach public function postAddRepositoryAction(ServerRequestInterface $request): ResponseInterface 911c1010edaSGreg Roach { 91257ab2231SGreg Roach $tree = $request->getAttribute('tree'); 91375964c75SGreg Roach assert($tree instanceof Tree); 9145229eadeSGreg Roach 915d45701ccSGreg Roach $xref = $request->getQueryParams()['xref'] ?? ''; 9165a78cd34SGreg Roach 9176b9cb339SGreg Roach $repository = Registry::repositoryFactory()->make($xref, $tree); 918d45701ccSGreg Roach $repository = Auth::checkRepositoryAccess($repository); 9195a78cd34SGreg Roach 920d45701ccSGreg Roach $this->addRepositoryToCart($repository); 921d45701ccSGreg Roach 922d45701ccSGreg Roach foreach ($repository->linkedSources('REPO') as $source) { 923d45701ccSGreg Roach $this->addSourceToCart($source); 9245a78cd34SGreg Roach } 9255a78cd34SGreg Roach 9266ccdf4f0SGreg Roach return redirect($repository->url()); 9275a78cd34SGreg Roach } 9285a78cd34SGreg Roach 9295a78cd34SGreg Roach /** 9306ccdf4f0SGreg Roach * @param ServerRequestInterface $request 9315a78cd34SGreg Roach * 9326ccdf4f0SGreg Roach * @return ResponseInterface 9335a78cd34SGreg Roach */ 93457ab2231SGreg Roach public function getAddSourceAction(ServerRequestInterface $request): ResponseInterface 935c1010edaSGreg Roach { 93657ab2231SGreg Roach $tree = $request->getAttribute('tree'); 93775964c75SGreg Roach assert($tree instanceof Tree); 9385229eadeSGreg Roach 939d45701ccSGreg Roach $xref = $request->getQueryParams()['xref'] ?? ''; 9405a78cd34SGreg Roach 9416b9cb339SGreg Roach $source = Registry::sourceFactory()->make($xref, $tree); 942d45701ccSGreg Roach $source = Auth::checkSourceAccess($source); 943d45701ccSGreg Roach $name = $source->fullName(); 9445a78cd34SGreg Roach 945d45701ccSGreg Roach $options = [ 94603f99a78SGreg Roach self::ADD_RECORD_ONLY => $name, 94703f99a78SGreg Roach self::ADD_LINKED_INDIVIDUALS => I18N::translate('%s and the individuals that reference it.', $name), 948d45701ccSGreg Roach ]; 9495a78cd34SGreg Roach 950d45701ccSGreg Roach $title = I18N::translate('Add %s to the clippings cart', $name); 9515a78cd34SGreg Roach 9525a78cd34SGreg Roach return $this->viewResponse('modules/clippings/add-options', [ 9535a78cd34SGreg Roach 'options' => $options, 9545a78cd34SGreg Roach 'record' => $source, 9555a78cd34SGreg Roach 'title' => $title, 9565a78cd34SGreg Roach 'tree' => $tree, 9575a78cd34SGreg Roach ]); 9585a78cd34SGreg Roach } 9595a78cd34SGreg Roach 9605a78cd34SGreg Roach /** 9616ccdf4f0SGreg Roach * @param ServerRequestInterface $request 9625a78cd34SGreg Roach * 9636ccdf4f0SGreg Roach * @return ResponseInterface 9645a78cd34SGreg Roach */ 96557ab2231SGreg Roach public function postAddSourceAction(ServerRequestInterface $request): ResponseInterface 966c1010edaSGreg Roach { 96757ab2231SGreg Roach $tree = $request->getAttribute('tree'); 96875964c75SGreg Roach assert($tree instanceof Tree); 9695229eadeSGreg Roach 970b46c87bdSGreg Roach $params = (array) $request->getParsedBody(); 971b46c87bdSGreg Roach 972d45701ccSGreg Roach $xref = $params['xref'] ?? ''; 973d45701ccSGreg Roach $option = $params['option'] ?? ''; 9745a78cd34SGreg Roach 9756b9cb339SGreg Roach $source = Registry::sourceFactory()->make($xref, $tree); 976d45701ccSGreg Roach $source = Auth::checkSourceAccess($source); 9775a78cd34SGreg Roach 978d45701ccSGreg Roach $this->addSourceToCart($source); 9795a78cd34SGreg Roach 98003f99a78SGreg Roach if ($option === self::ADD_LINKED_INDIVIDUALS) { 9815a78cd34SGreg Roach foreach ($source->linkedIndividuals('SOUR') as $individual) { 982d45701ccSGreg Roach $this->addIndividualToCart($individual); 9835a78cd34SGreg Roach } 9845a78cd34SGreg Roach foreach ($source->linkedFamilies('SOUR') as $family) { 985d45701ccSGreg Roach $this->addFamilyToCart($family); 9865a78cd34SGreg Roach } 9875a78cd34SGreg Roach } 9885a78cd34SGreg Roach 9896ccdf4f0SGreg Roach return redirect($source->url()); 9905a78cd34SGreg Roach } 9915a78cd34SGreg Roach 9925a78cd34SGreg Roach /** 993d45701ccSGreg Roach * @param ServerRequestInterface $request 9945a78cd34SGreg Roach * 995d45701ccSGreg Roach * @return ResponseInterface 9965a78cd34SGreg Roach */ 997d45701ccSGreg Roach public function getAddSubmitterAction(ServerRequestInterface $request): ResponseInterface 998c1010edaSGreg Roach { 999d45701ccSGreg Roach $tree = $request->getAttribute('tree'); 1000d45701ccSGreg Roach assert($tree instanceof Tree); 10015a78cd34SGreg Roach 1002d45701ccSGreg Roach $xref = $request->getQueryParams()['xref'] ?? ''; 10035a78cd34SGreg Roach 1004d45701ccSGreg Roach $submitter = Registry::submitterFactory()->make($xref, $tree); 1005d45701ccSGreg Roach $submitter = Auth::checkSubmitterAccess($submitter); 1006d45701ccSGreg Roach $name = $submitter->fullName(); 10075a78cd34SGreg Roach 1008d45701ccSGreg Roach $options = [ 100903f99a78SGreg Roach self::ADD_RECORD_ONLY => $name, 1010d45701ccSGreg Roach ]; 10115a78cd34SGreg Roach 1012d45701ccSGreg Roach $title = I18N::translate('Add %s to the clippings cart', $name); 10135a78cd34SGreg Roach 1014d45701ccSGreg Roach return $this->viewResponse('modules/clippings/add-options', [ 1015d45701ccSGreg Roach 'options' => $options, 1016d45701ccSGreg Roach 'record' => $submitter, 1017d45701ccSGreg Roach 'title' => $title, 1018d45701ccSGreg Roach 'tree' => $tree, 1019d45701ccSGreg Roach ]); 10205a78cd34SGreg Roach } 10215a78cd34SGreg Roach 10225a78cd34SGreg Roach /** 1023d45701ccSGreg Roach * @param ServerRequestInterface $request 10245a78cd34SGreg Roach * 1025d45701ccSGreg Roach * @return ResponseInterface 10265a78cd34SGreg Roach */ 1027d45701ccSGreg Roach public function postAddSubmitterAction(ServerRequestInterface $request): ResponseInterface 1028d45701ccSGreg Roach { 1029d45701ccSGreg Roach $tree = $request->getAttribute('tree'); 1030d45701ccSGreg Roach assert($tree instanceof Tree); 1031d45701ccSGreg Roach 1032d45701ccSGreg Roach $xref = $request->getQueryParams()['xref'] ?? ''; 1033d45701ccSGreg Roach 1034d45701ccSGreg Roach $submitter = Registry::submitterFactory()->make($xref, $tree); 1035d45701ccSGreg Roach $submitter = Auth::checkSubmitterAccess($submitter); 1036d45701ccSGreg Roach 1037d45701ccSGreg Roach $this->addSubmitterToCart($submitter); 1038d45701ccSGreg Roach 1039d45701ccSGreg Roach return redirect($submitter->url()); 1040d45701ccSGreg Roach } 1041d45701ccSGreg Roach 1042d45701ccSGreg Roach /** 1043d45701ccSGreg Roach * @param Family $family 1044d45701ccSGreg Roach */ 1045d45701ccSGreg Roach protected function addFamilyToCart(Family $family): void 1046c1010edaSGreg Roach { 10475a78cd34SGreg Roach $cart = Session::get('cart', []); 1048d45701ccSGreg Roach $tree = $family->tree()->name(); 1049d45701ccSGreg Roach $xref = $family->xref(); 10505a78cd34SGreg Roach 1051d45701ccSGreg Roach if (($cart[$tree][$xref] ?? false) === false) { 1052d45701ccSGreg Roach $cart[$tree][$xref] = true; 10535a78cd34SGreg Roach 1054d45701ccSGreg Roach Session::put('cart', $cart); 10555a78cd34SGreg Roach 1056d45701ccSGreg Roach foreach ($family->spouses() as $spouse) { 1057d45701ccSGreg Roach $this->addIndividualToCart($spouse); 10585a78cd34SGreg Roach } 10595a78cd34SGreg Roach 1060e8ded2caSGreg Roach $this->addLocationLinksToCart($family); 1061d45701ccSGreg Roach $this->addMediaLinksToCart($family); 1062d45701ccSGreg Roach $this->addNoteLinksToCart($family); 1063d45701ccSGreg Roach $this->addSourceLinksToCart($family); 1064d45701ccSGreg Roach $this->addSubmitterLinksToCart($family); 1065d45701ccSGreg Roach } 1066d45701ccSGreg Roach } 1067d45701ccSGreg Roach 1068d45701ccSGreg Roach /** 1069d45701ccSGreg Roach * @param Individual $individual 1070d45701ccSGreg Roach */ 1071d45701ccSGreg Roach protected function addIndividualToCart(Individual $individual): void 1072d45701ccSGreg Roach { 1073d45701ccSGreg Roach $cart = Session::get('cart', []); 1074d45701ccSGreg Roach $tree = $individual->tree()->name(); 1075d45701ccSGreg Roach $xref = $individual->xref(); 1076d45701ccSGreg Roach 1077d45701ccSGreg Roach if (($cart[$tree][$xref] ?? false) === false) { 1078d45701ccSGreg Roach $cart[$tree][$xref] = true; 1079d45701ccSGreg Roach 1080d45701ccSGreg Roach Session::put('cart', $cart); 1081d45701ccSGreg Roach 1082e8ded2caSGreg Roach $this->addLocationLinksToCart($individual); 1083d45701ccSGreg Roach $this->addMediaLinksToCart($individual); 1084d45701ccSGreg Roach $this->addNoteLinksToCart($individual); 1085d45701ccSGreg Roach $this->addSourceLinksToCart($individual); 1086d45701ccSGreg Roach } 1087d45701ccSGreg Roach } 1088d45701ccSGreg Roach 1089d45701ccSGreg Roach /** 1090e8ded2caSGreg Roach * @param Location $location 1091e8ded2caSGreg Roach */ 1092e8ded2caSGreg Roach protected function addLocationToCart(Location $location): void 1093e8ded2caSGreg Roach { 1094e8ded2caSGreg Roach $cart = Session::get('cart', []); 1095e8ded2caSGreg Roach $tree = $location->tree()->name(); 1096e8ded2caSGreg Roach $xref = $location->xref(); 1097e8ded2caSGreg Roach 1098e8ded2caSGreg Roach if (($cart[$tree][$xref] ?? false) === false) { 1099e8ded2caSGreg Roach $cart[$tree][$xref] = true; 1100e8ded2caSGreg Roach 1101e8ded2caSGreg Roach Session::put('cart', $cart); 1102e8ded2caSGreg Roach 1103e8ded2caSGreg Roach $this->addLocationLinksToCart($location); 1104e8ded2caSGreg Roach $this->addMediaLinksToCart($location); 1105e8ded2caSGreg Roach $this->addNoteLinksToCart($location); 1106e8ded2caSGreg Roach $this->addSourceLinksToCart($location); 1107e8ded2caSGreg Roach } 1108e8ded2caSGreg Roach } 1109e8ded2caSGreg Roach 1110e8ded2caSGreg Roach /** 1111e8ded2caSGreg Roach * @param GedcomRecord $record 1112e8ded2caSGreg Roach */ 1113e8ded2caSGreg Roach protected function addLocationLinksToCart(GedcomRecord $record): void 1114e8ded2caSGreg Roach { 1115e8ded2caSGreg Roach preg_match_all('/\n\d _LOC @(' . Gedcom::REGEX_XREF . ')@/', $record->gedcom(), $matches); 1116e8ded2caSGreg Roach 1117e8ded2caSGreg Roach foreach ($matches[1] as $xref) { 1118e8ded2caSGreg Roach $location = Registry::locationFactory()->make($xref, $record->tree()); 1119e8ded2caSGreg Roach 1120e8ded2caSGreg Roach if ($location instanceof Location && $location->canShow()) { 1121e8ded2caSGreg Roach $this->addLocationToCart($location); 1122e8ded2caSGreg Roach } 1123e8ded2caSGreg Roach } 1124e8ded2caSGreg Roach } 1125e8ded2caSGreg Roach 1126e8ded2caSGreg Roach /** 1127d45701ccSGreg Roach * @param Media $media 1128d45701ccSGreg Roach */ 1129d45701ccSGreg Roach protected function addMediaToCart(Media $media): void 1130d45701ccSGreg Roach { 1131d45701ccSGreg Roach $cart = Session::get('cart', []); 1132d45701ccSGreg Roach $tree = $media->tree()->name(); 1133d45701ccSGreg Roach $xref = $media->xref(); 1134d45701ccSGreg Roach 1135d45701ccSGreg Roach if (($cart[$tree][$xref] ?? false) === false) { 1136d45701ccSGreg Roach $cart[$tree][$xref] = true; 1137d45701ccSGreg Roach 1138d45701ccSGreg Roach Session::put('cart', $cart); 1139d45701ccSGreg Roach 1140d45701ccSGreg Roach $this->addNoteLinksToCart($media); 1141d45701ccSGreg Roach } 1142d45701ccSGreg Roach } 1143d45701ccSGreg Roach 1144d45701ccSGreg Roach /** 1145d45701ccSGreg Roach * @param GedcomRecord $record 1146d45701ccSGreg Roach */ 1147d45701ccSGreg Roach protected function addMediaLinksToCart(GedcomRecord $record): void 1148d45701ccSGreg Roach { 1149d45701ccSGreg Roach preg_match_all('/\n\d OBJE @(' . Gedcom::REGEX_XREF . ')@/', $record->gedcom(), $matches); 1150d45701ccSGreg Roach 1151d45701ccSGreg Roach foreach ($matches[1] as $xref) { 1152d45701ccSGreg Roach $media = Registry::mediaFactory()->make($xref, $record->tree()); 1153d45701ccSGreg Roach 1154d45701ccSGreg Roach if ($media instanceof Media && $media->canShow()) { 1155d45701ccSGreg Roach $this->addMediaToCart($media); 1156d45701ccSGreg Roach } 1157d45701ccSGreg Roach } 1158d45701ccSGreg Roach } 1159d45701ccSGreg Roach 1160d45701ccSGreg Roach /** 1161d45701ccSGreg Roach * @param Note $note 1162d45701ccSGreg Roach */ 1163d45701ccSGreg Roach protected function addNoteToCart(Note $note): void 1164d45701ccSGreg Roach { 1165d45701ccSGreg Roach $cart = Session::get('cart', []); 1166d45701ccSGreg Roach $tree = $note->tree()->name(); 1167d45701ccSGreg Roach $xref = $note->xref(); 1168d45701ccSGreg Roach 1169d45701ccSGreg Roach if (($cart[$tree][$xref] ?? false) === false) { 1170d45701ccSGreg Roach $cart[$tree][$xref] = true; 1171d45701ccSGreg Roach 11725a78cd34SGreg Roach Session::put('cart', $cart); 11735a78cd34SGreg Roach } 1174d45701ccSGreg Roach } 11755a78cd34SGreg Roach 11765a78cd34SGreg Roach /** 1177d45701ccSGreg Roach * @param GedcomRecord $record 11785a78cd34SGreg Roach */ 1179d45701ccSGreg Roach protected function addNoteLinksToCart(GedcomRecord $record): void 1180d45701ccSGreg Roach { 1181d45701ccSGreg Roach preg_match_all('/\n\d NOTE @(' . Gedcom::REGEX_XREF . ')@/', $record->gedcom(), $matches); 1182d45701ccSGreg Roach 1183d45701ccSGreg Roach foreach ($matches[1] as $xref) { 1184d45701ccSGreg Roach $note = Registry::noteFactory()->make($xref, $record->tree()); 1185d45701ccSGreg Roach 1186d45701ccSGreg Roach if ($note instanceof Note && $note->canShow()) { 1187d45701ccSGreg Roach $this->addNoteToCart($note); 1188d45701ccSGreg Roach } 1189d45701ccSGreg Roach } 1190d45701ccSGreg Roach } 1191d45701ccSGreg Roach 1192d45701ccSGreg Roach /** 1193d45701ccSGreg Roach * @param Source $source 1194d45701ccSGreg Roach */ 1195d45701ccSGreg Roach protected function addSourceToCart(Source $source): void 1196c1010edaSGreg Roach { 11975a78cd34SGreg Roach $cart = Session::get('cart', []); 1198d45701ccSGreg Roach $tree = $source->tree()->name(); 1199d45701ccSGreg Roach $xref = $source->xref(); 12005a78cd34SGreg Roach 1201d45701ccSGreg Roach if (($cart[$tree][$xref] ?? false) === false) { 1202d45701ccSGreg Roach $cart[$tree][$xref] = true; 1203d45701ccSGreg Roach 1204d45701ccSGreg Roach Session::put('cart', $cart); 1205d45701ccSGreg Roach 1206d45701ccSGreg Roach $this->addNoteLinksToCart($source); 1207d45701ccSGreg Roach $this->addRepositoryLinksToCart($source); 1208d45701ccSGreg Roach } 1209d45701ccSGreg Roach } 1210d45701ccSGreg Roach 1211d45701ccSGreg Roach /** 1212d45701ccSGreg Roach * @param GedcomRecord $record 1213d45701ccSGreg Roach */ 1214d45701ccSGreg Roach protected function addSourceLinksToCart(GedcomRecord $record): void 1215d45701ccSGreg Roach { 1216d45701ccSGreg Roach preg_match_all('/\n\d SOUR @(' . Gedcom::REGEX_XREF . ')@/', $record->gedcom(), $matches); 1217d45701ccSGreg Roach 1218d45701ccSGreg Roach foreach ($matches[1] as $xref) { 1219d45701ccSGreg Roach $source = Registry::sourceFactory()->make($xref, $record->tree()); 1220d45701ccSGreg Roach 1221d45701ccSGreg Roach if ($source instanceof Source && $source->canShow()) { 1222d45701ccSGreg Roach $this->addSourceToCart($source); 1223d45701ccSGreg Roach } 1224d45701ccSGreg Roach } 1225d45701ccSGreg Roach } 1226d45701ccSGreg Roach 1227d45701ccSGreg Roach /** 1228d45701ccSGreg Roach * @param Repository $repository 1229d45701ccSGreg Roach */ 1230d45701ccSGreg Roach protected function addRepositoryToCart(Repository $repository): void 1231d45701ccSGreg Roach { 1232d45701ccSGreg Roach $cart = Session::get('cart', []); 1233d45701ccSGreg Roach $tree = $repository->tree()->name(); 1234d45701ccSGreg Roach $xref = $repository->xref(); 1235d45701ccSGreg Roach 1236d45701ccSGreg Roach if (($cart[$tree][$xref] ?? false) === false) { 1237d45701ccSGreg Roach $cart[$tree][$xref] = true; 1238d45701ccSGreg Roach 1239d45701ccSGreg Roach Session::put('cart', $cart); 1240d45701ccSGreg Roach 1241d45701ccSGreg Roach $this->addNoteLinksToCart($repository); 1242d45701ccSGreg Roach } 1243d45701ccSGreg Roach } 1244d45701ccSGreg Roach 1245d45701ccSGreg Roach /** 1246d45701ccSGreg Roach * @param GedcomRecord $record 1247d45701ccSGreg Roach */ 1248d45701ccSGreg Roach protected function addRepositoryLinksToCart(GedcomRecord $record): void 1249d45701ccSGreg Roach { 1250d45701ccSGreg Roach preg_match_all('/\n\d REPO @(' . Gedcom::REGEX_XREF . '@)/', $record->gedcom(), $matches); 1251d45701ccSGreg Roach 1252d45701ccSGreg Roach foreach ($matches[1] as $xref) { 1253d45701ccSGreg Roach $repository = Registry::repositoryFactory()->make($xref, $record->tree()); 1254d45701ccSGreg Roach 1255d45701ccSGreg Roach if ($repository instanceof Repository && $repository->canShow()) { 1256d45701ccSGreg Roach $this->addRepositoryToCart($repository); 1257d45701ccSGreg Roach } 1258d45701ccSGreg Roach } 1259d45701ccSGreg Roach } 1260d45701ccSGreg Roach 1261d45701ccSGreg Roach /** 1262d45701ccSGreg Roach * @param Submitter $submitter 1263d45701ccSGreg Roach */ 1264d45701ccSGreg Roach protected function addSubmitterToCart(Submitter $submitter): void 1265d45701ccSGreg Roach { 1266d45701ccSGreg Roach $cart = Session::get('cart', []); 1267d45701ccSGreg Roach $tree = $submitter->tree()->name(); 1268d45701ccSGreg Roach $xref = $submitter->xref(); 1269d45701ccSGreg Roach 1270d45701ccSGreg Roach if (($cart[$tree][$xref] ?? false) === false) { 1271d45701ccSGreg Roach $cart[$tree][$xref] = true; 1272d45701ccSGreg Roach 1273d45701ccSGreg Roach Session::put('cart', $cart); 1274d45701ccSGreg Roach 1275d45701ccSGreg Roach $this->addNoteLinksToCart($submitter); 1276d45701ccSGreg Roach } 1277d45701ccSGreg Roach } 1278d45701ccSGreg Roach 1279d45701ccSGreg Roach /** 1280d45701ccSGreg Roach * @param GedcomRecord $record 1281d45701ccSGreg Roach */ 1282d45701ccSGreg Roach protected function addSubmitterLinksToCart(GedcomRecord $record): void 1283d45701ccSGreg Roach { 1284d45701ccSGreg Roach preg_match_all('/\n\d SUBM @(' . Gedcom::REGEX_XREF . ')@/', $record->gedcom(), $matches); 1285d45701ccSGreg Roach 1286d45701ccSGreg Roach foreach ($matches[1] as $xref) { 1287d45701ccSGreg Roach $submitter = Registry::submitterFactory()->make($xref, $record->tree()); 1288d45701ccSGreg Roach 1289d45701ccSGreg Roach if ($submitter instanceof Submitter && $submitter->canShow()) { 1290d45701ccSGreg Roach $this->addSubmitterToCart($submitter); 1291d45701ccSGreg Roach } 1292d45701ccSGreg Roach } 12935a78cd34SGreg Roach } 12948c2e8227SGreg Roach} 1295