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')) {