From 13d080d50a1916ab49aee6ea8f0d6adc5632d6e0 Mon Sep 17 00:00:00 2001 From: HichemTech Date: Wed, 5 Mar 2025 18:54:53 +0100 Subject: [PATCH] Add support for removing saved templates Introduced a new `template:remove` command to delete saved templates, either individually or all at once. Updated documentation to reflect this feature and extracted common template utility logic for reusability. Bumped version to 1.2.0 to accommodate this enhancement. --- README.md | 22 ++++++ bin/laravelfs | 3 +- src/Concerns/CommonTemplateUtils.php | 21 ++++++ src/RemoveTemplateCommand.php | 107 +++++++++++++++++++++++++++ src/UseTemplateCommand.php | 11 +-- 5 files changed, 154 insertions(+), 10 deletions(-) create mode 100644 src/Concerns/CommonTemplateUtils.php create mode 100644 src/RemoveTemplateCommand.php diff --git a/README.md b/README.md index 25adcc0..fe55598 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,7 @@ LaravelFS functions similarly to the Laravel Installer but with **extra capabili ✅ Support for **Breeze and Jetstream**, even if they are abandoned. ✅ Install **custom starter kits** from Packagist. ✅ Save and reuse project setups with **Templates**. +✅ Easily **remove saved templates** when no longer needed. ✅ Ensure that provided starter kits are **Composer packages of type `project`**. ✅ CLI command to fetch additional details about a starter kit package. @@ -93,6 +94,27 @@ This runs the exact same command as if you typed everything manually! --- +## **🗑️ Removing Templates** +Need to clean up your templates? You can easily remove them. + +### **Remove a Specific Template** +To delete a single template: + +```sh +laravelfs template:remove my-template +``` + +### **Remove All Templates** +To remove **all saved templates** at once: + +```sh +laravelfs template:remove --all +``` + +> ⚠️ **This action is irreversible!** Make sure you want to delete all templates before running this command. + +--- + ## **Installing Custom Starter Kits** LaravelFS allows you to install **custom Laravel starter kits** from Packagist by providing the package name: diff --git a/bin/laravelfs b/bin/laravelfs index 161ef84..a708a23 100644 --- a/bin/laravelfs +++ b/bin/laravelfs @@ -9,7 +9,7 @@ if (file_exists(__DIR__.'/../../../autoload.php')) { } // Define our own version and the Laravel Installer version we aim to match. -$laravelFSVersion = '1.1.0'; +$laravelFSVersion = '1.2.0'; $laravelInstallerVersion = '5.13.0'; // Compose the displayed version string. @@ -20,6 +20,7 @@ $app->add(new HichemTabTech\LaravelFS\Console\NewCommand); $app->add(new HichemTabTech\LaravelFS\Console\NewTemplateCommand); $app->add(new HichemTabTech\LaravelFS\Console\ShowTemplatesCommand); $app->add(new HichemTabTech\LaravelFS\Console\UseTemplateCommand); +$app->add(new HichemTabTech\LaravelFS\Console\RemoveTemplateCommand); /** @noinspection PhpUnhandledExceptionInspection */ $app->run(); diff --git a/src/Concerns/CommonTemplateUtils.php b/src/Concerns/CommonTemplateUtils.php new file mode 100644 index 0000000..4bd1813 --- /dev/null +++ b/src/Concerns/CommonTemplateUtils.php @@ -0,0 +1,21 @@ +getSavedTemplates(true); + $templates = $templatesData['templates']; + $input->setArgument('template-name', text( + label: 'What is the name this template', + placeholder: count($templates) == 0 ? 'E.g. template1, or-any-name-u-want' : ('E.g. '.implode(', ', array_slice(array_keys($templates), 0, 3)).(count($templates) > 3 ? ', ...' : '')), + required: 'The template name is required.', + hint: 'This name is the key of the template you are searching for.', + )); + } +} \ No newline at end of file diff --git a/src/RemoveTemplateCommand.php b/src/RemoveTemplateCommand.php new file mode 100644 index 0000000..24ce8db --- /dev/null +++ b/src/RemoveTemplateCommand.php @@ -0,0 +1,107 @@ +setName('template:remove') + ->setDescription('remove a saved template') + ->setHelp('This command removes a saved template that you no longer need.') + ->addOption('all', 'a', InputOption::VALUE_NONE, 'Remove all saved templates') + ->addArgument('template-name', InputArgument::REQUIRED, 'The name of the template to remove'); + } + + protected function interact(InputInterface $input, OutputInterface $output): void + { + parent::interact($input, $output); + + $this->configurePrompts($input, $output); + + $output->write(PHP_EOL . ' _ _ + | | | | + | | __ _ _ __ __ ___ _____| | + | | / _` | __/ _` \ \ / / _ \ | + | |___| (_| | | | (_| |\ V / __/ | + |______\__,_|_| \__,_| \_/ \___|_|' . PHP_EOL . PHP_EOL); + + if (!$input->getArgument('template-name')) { + if (!$input->getOption('all')) { + $this->ensureTemplateNameArgument($input); + } else { + $input->setArgument('template-name', confirm( + label: 'Are you sure you want to remove all saved templates?', + default: false, + hint: 'This action is irreversible.', + ) ? '/all/' : null); + } + } + } + + + protected function execute(InputInterface $input, OutputInterface $output): int + { + + $templatesData = $this->getSavedTemplates(); + $templates = $templatesData['templates']; + if (empty($templates)) { + $this->info('No saved templates found.'); + return Command::SUCCESS; + } + + if ($input->getArgument('template-name') == '/all/') { + $templateToRemove = null; + } elseif (!$input->getArgument('template-name')) { + intro('Operation cancelled.'); + return Command::SUCCESS; + } else { + $templateName = $input->getArgument('template-name'); + + if (!isset($templates[$templateName])) { + error("Template '$templateName' not found."); + return Command::INVALID; + } + + $templateToRemove = $templateName; + } + intro("Removing a saved template..."); + + if ($templateToRemove) { + $done = $this->removeTemplates($templatesData['path'], $templatesData, $templateToRemove); + } else { + $done = $this->removeTemplates($templatesData['path'], $templatesData); + } + + if ($done) { + $this->info($templateToRemove ? "Template '$templateToRemove' removed successfully." : 'All saved templates removed successfully.'); + return Command::SUCCESS; + } + + error($templateToRemove ? "Failed to remove template '$templateToRemove'." : 'Failed to remove all saved templates.'); + return Command::FAILURE; + } + + private function removeTemplates(string $path, array $templatesData, string|null $templateToRemove = null): bool + { + if (!$templateToRemove) { + $templatesConfig = ['templates' => []]; + } else { + unset($templatesData['templates'][$templateToRemove]); + $templatesConfig = ['templates' => $templatesData['templates']]; + } + return file_put_contents($path, json_encode($templatesConfig, JSON_PRETTY_PRINT)) !== false; + } +} \ No newline at end of file diff --git a/src/UseTemplateCommand.php b/src/UseTemplateCommand.php index 0e598c9..73e3396 100644 --- a/src/UseTemplateCommand.php +++ b/src/UseTemplateCommand.php @@ -14,7 +14,7 @@ class UseTemplateCommand extends Command { - use Concerns\CommandsUtils, Concerns\ConfiguresPrompts; + use Concerns\CommandsUtils, Concerns\ConfiguresPrompts, Concerns\CommonTemplateUtils; protected function configure(): void { $this->setName('use') @@ -39,14 +39,7 @@ protected function interact(InputInterface $input, OutputInterface $output): voi |______\__,_|_| \__,_| \_/ \___|_|'.PHP_EOL.PHP_EOL); if (!$input->getArgument('template-name')) { - $templatesData = $this->getSavedTemplates(true); - $templates = $templatesData['templates']; - $input->setArgument('template-name', text( - label: 'What is the name this template', - placeholder: count($templates) == 0 ? 'E.g. template1, or-any-name-u-want' : ('E.g. '.implode(', ', array_slice(array_keys($templates), 0, 3)).(count($templates) > 3 ? ', ...' : '')), - required: 'The template name is required.', - hint: 'This name is the key of the template you are searching for.', - )); + $this->ensureTemplateNameArgument($input); } if (!$input->getArgument('project-name')) {