diff options
| author | Greg Roach <greg@subaqua.co.uk> | 2025-05-13 11:28:56 +0100 |
|---|---|---|
| committer | Greg Roach <greg@subaqua.co.uk> | 2025-05-13 11:28:56 +0100 |
| commit | 1fe5972b9c911ca4873c4a0fb40a416598b02997 (patch) | |
| tree | 458ee27696873af036b8266f0877ff83bf7eb7df /app/Cli | |
| parent | 036af8696129956af9534bd1e19e74a9d2305337 (diff) | |
| download | webtrees-1fe5972b9c911ca4873c4a0fb40a416598b02997.tar.gz webtrees-1fe5972b9c911ca4873c4a0fb40a416598b02997.tar.bz2 webtrees-1fe5972b9c911ca4873c4a0fb40a416598b02997.zip | |
Add CLI for tree-export
Diffstat (limited to 'app/Cli')
| -rw-r--r-- | app/Cli/Commands/TreeExport.php | 115 | ||||
| -rw-r--r-- | app/Cli/Console.php | 2 |
2 files changed, 101 insertions, 16 deletions
diff --git a/app/Cli/Commands/TreeExport.php b/app/Cli/Commands/TreeExport.php index b058e9adcd..493178c7e7 100644 --- a/app/Cli/Commands/TreeExport.php +++ b/app/Cli/Commands/TreeExport.php @@ -21,7 +21,6 @@ namespace Fisharebest\Webtrees\Cli\Commands; use Fisharebest\Webtrees\Auth; use Fisharebest\Webtrees\DB; -use Fisharebest\Webtrees\Encodings\UTF8; use Fisharebest\Webtrees\Services\GedcomExportService; use Fisharebest\Webtrees\Services\TreeService; use Symfony\Component\Console\Completion\CompletionInput; @@ -30,12 +29,21 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Style\SymfonyStyle; +use ZipArchive; use function addcslashes; +use function filesize; use function stream_get_contents; final class TreeExport extends AbstractCommand { + private const array ACCESS_LEVELS = [ + 'none' => Auth::PRIV_HIDE, + 'manager' => Auth::PRIV_NONE, + 'member' => Auth::PRIV_USER, + 'visitor' => Auth::PRIV_PRIVATE, + ]; + public function __construct( private readonly GedcomExportService $gedcom_export_service, private readonly TreeService $tree_service, @@ -48,8 +56,8 @@ final class TreeExport extends AbstractCommand $this ->setName(name: 'tree-export') ->addArgument(name: 'tree_name', mode: InputArgument::REQUIRED, description: 'The name of the tree', suggestedValues: self::autoCompleteTreeName(...)) - ->addOption(name: 'format', shortcut: null, mode: InputOption::VALUE_REQUIRED, description: 'Export format') - ->addOption(name: 'filename', shortcut: null, mode: InputOption::VALUE_REQUIRED, description: 'Export filename') + ->addOption(name: 'format', mode: InputOption::VALUE_REQUIRED, description: 'Export format: gedcom (default), gedzip, zip or zipmedia') + ->addOption(name: 'privacy', mode: InputOption::VALUE_REQUIRED, description: 'Apply privacy: none (default), manager, member or visitor') ->setDescription(description: 'Export a tree to a GEDCOM file'); } @@ -68,9 +76,25 @@ final class TreeExport extends AbstractCommand { $io = new SymfonyStyle(input: $input, output: $output); - $tree_name = $input->getArgument(name: 'tree_name'); + $tree_name = $this->stringArgument(input: $input, name: 'tree_name'); $format = $this->stringOption(input: $input, name: 'format'); - $filename = $this->stringOption(input: $input, name: 'filename'); + $privacy = $this->stringOption(input: $input, name: 'privacy'); + + if ($format === '') { + $format = 'gedcom'; + } + + if ($privacy === '') { + $privacy = 'none'; + } + + $access_level = self::ACCESS_LEVELS[$privacy] ?? null; + + if ($access_level === null) { + $io->error(message: 'privacy option should be none, manager, member or visitor'); + + return self::FAILURE; + } $tree = $this->tree_service->all()[$tree_name] ?? null; @@ -80,20 +104,81 @@ final class TreeExport extends AbstractCommand return self::FAILURE; } - $stream = $this->gedcom_export_service->export( + $start_time = microtime(true); + + switch ($format) { + case 'gedcom': + $media_path = null; + $filename = $tree_name . '.ged'; + $zip_filesystem = null; + break; + + case 'gedzip': + $media_path = ''; + $filename = $tree_name . '.gdz'; + $zip_filesystem = new ZipArchive(); + $zip_filesystem->open($filename, ZipArchive::CREATE | ZipArchive::OVERWRITE); + break; + + case 'zip': + $media_path = null; + $filename = $tree_name . '.zip'; + $zip_filesystem = new ZipArchive(); + $zip_filesystem->open($filename, ZipArchive::CREATE | ZipArchive::OVERWRITE); + break; + + case 'zipmedia': + $media_path = $tree->getPreference('MEDIA_DIRECTORY'); + $filename = $tree_name . '.zip'; + $zip_filesystem = new ZipArchive(); + $zip_filesystem->open($filename, ZipArchive::CREATE | ZipArchive::OVERWRITE); + break; + + default: + $io->error(message: 'Format option should be gedcom, gedzip, zip or zipmedia'); + + return self::FAILURE; + } + + $resource = $this->gedcom_export_service->export( tree: $tree, - sort_by_xref: false, - encoding: UTF8::NAME, - access_level: Auth::PRIV_HIDE, - line_endings: 'CRLF', - records: null, - zip_filesystem: null, - media_path: null, + sort_by_xref: true, + access_level: $access_level, + zip_filesystem: $zip_filesystem, + media_path: $media_path, ); - echo stream_get_contents($stream); + $gedcom = stream_get_contents($resource); + fclose($resource); + + if ($gedcom === false) { + $io->error(message: 'Failed to read GEDCOM'); + + return self::FAILURE; + } + + switch ($format) { + case 'gedcom': + file_put_contents($filename, $gedcom); + break; + + case 'gedzip': + $zip_filesystem->addFromString('gedcom.ged', $gedcom); + $zip_filesystem->close(); + break; + + case 'zip': + case 'zipmedia': + $zip_filesystem->addFromString($tree_name . '.ged', $gedcom); + $zip_filesystem->close(); + break; + } + + $bytes = filesize($filename); + $seconds = microtime(true) - $start_time; + $message = sprintf('File exported successfully. %d bytes written to %s in %.3f seconds', $bytes, $filename, $seconds); - $io->success('File exported successfully.'); + $io->success($message); return self::SUCCESS; } diff --git a/app/Cli/Console.php b/app/Cli/Console.php index 4ddff02d9a..f3bf5def29 100644 --- a/app/Cli/Console.php +++ b/app/Cli/Console.php @@ -37,7 +37,7 @@ final class Console extends Application Commands\SiteOnline::class, Commands\SiteSetting::class, //Commands\TreeCreate::class, - //Commands\TreeExport::class, + Commands\TreeExport::class, Commands\TreeList::class, Commands\TreeSetting::class, //Commands\UserCreate::class, |
