1<?php 2 3/** 4 * webtrees: online genealogy 5 * Copyright (C) 2023 webtrees development team 6 * This program is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation, either version 3 of the License, or 9 * (at your option) any later version. 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * You should have received a copy of the GNU General Public License 15 * along with this program. If not, see <https://www.gnu.org/licenses/>. 16 */ 17 18declare(strict_types=1); 19 20namespace Fisharebest\Webtrees\Cli\Commands; 21 22use Fisharebest\Webtrees\Auth; 23use Fisharebest\Webtrees\DB; 24use Fisharebest\Webtrees\Encodings\UTF8; 25use Fisharebest\Webtrees\Services\GedcomExportService; 26use Fisharebest\Webtrees\Services\TreeService; 27use Symfony\Component\Console\Command\Command; 28use Symfony\Component\Console\Completion\CompletionInput; 29use Symfony\Component\Console\Input\InputArgument; 30use Symfony\Component\Console\Input\InputInterface; 31use Symfony\Component\Console\Input\InputOption; 32use Symfony\Component\Console\Output\OutputInterface; 33use Symfony\Component\Console\Style\SymfonyStyle; 34 35use function addcslashes; 36use function stream_get_contents; 37 38class TreeExport extends Command 39{ 40 public function __construct( 41 private readonly GedcomExportService $gedcom_export_service, 42 private readonly TreeService $tree_service, 43 ) { 44 parent::__construct(); 45 } 46 47 protected function configure(): void 48 { 49 $this 50 ->setName(name: 'tree-export') 51 ->addArgument(name: 'tree_name', mode: InputArgument::REQUIRED, description: 'The name of the tree', suggestedValues: self::autoCompleteTreeName(...)) 52 ->addOption(name: 'format', shortcut: null, mode: InputOption::VALUE_REQUIRED, description: 'Export format') 53 ->addOption(name: 'filename', shortcut: null, mode: InputOption::VALUE_REQUIRED, description: 'Export filename') 54 ->setDescription(description: 'Export a tree to a GEDCOM file'); 55 } 56 57 /** 58 * @return array<string> 59 */ 60 private function autoCompleteTreeName(CompletionInput $input): array 61 { 62 return DB::table('tree') 63 ->where('tree_name', 'LIKE', addcslashes($input->getCompletionValue(), '%_\\') . '%') 64 ->pluck('name') 65 ->all(); 66 } 67 68 protected function execute(InputInterface $input, OutputInterface $output): int 69 { 70 $io = new SymfonyStyle(input: $input, output: $output); 71 72 $tree_name = $input->getArgument(name: 'tree_name'); 73 $format = $input->getOption(name: 'format'); 74 $filename = $input->getOption(name: 'filename'); 75 76 $tree = $this->tree_service->all()[$tree_name] ?? null; 77 78 if ($tree === null) { 79 $io->error(message: 'Tree "' . $tree_name . '" not found.'); 80 81 return Command::FAILURE; 82 } 83 84 $stream = $this->gedcom_export_service->export( 85 tree: $tree, 86 sort_by_xref: false, 87 encoding: UTF8::NAME, 88 access_level: Auth::PRIV_HIDE, 89 line_endings: 'CRLF', 90 records: null, 91 zip_filesystem: null, 92 media_path: null, 93 ); 94 95 echo stream_get_contents($stream); 96 97 $io->success('File exported successfully.'); 98 99 return Command::SUCCESS; 100 } 101} 102