addArgument('identifier', InputArgument::REQUIRED, 'Tenant identifier to delete') ->addOption('force', 'f', InputOption::VALUE_NONE, 'Skip confirmation prompt') ->setHelp('This command deletes a tenant. Deletion must be confirmed by typing the tenant\'s primary domain. User accounts and module data belonging to the tenant are not removed.') ; } protected function execute(InputInterface $input, OutputInterface $output): int { $io = new SymfonyStyle($input, $output); $identifier = $input->getArgument('identifier'); $force = $input->getOption('force'); $io->title('Delete Tenant'); try { $tenant = $this->tenantService->fetchById($identifier); if (!$tenant) { $io->error("Tenant '{$identifier}' not found."); return Command::FAILURE; } if (!$force) { // Confirm by typing the tenant's primary domain (identifier for // legacy tenants without domains) $domains = $tenant->getDomains()?->getArrayCopy() ?? []; $confirmation = $domains[0] ?? $identifier; $io->definitionList( ['Identifier' => $tenant->getIdentifier()], ['Label' => $tenant->getLabel()], ['Domains' => implode(', ', $domains)], ); $answer = $io->ask("Type '{$confirmation}' to confirm deletion"); if ($answer !== $confirmation) { $io->error('Confirmation did not match. Delete cancelled.'); return Command::FAILURE; } } $this->tenantService->destroy($tenant); $this->logger->info('Tenant deleted via console', [ 'identifier' => $identifier, 'command' => $this->getName(), ]); $io->success("Tenant '{$identifier}' deleted successfully!"); return Command::SUCCESS; } catch (\Throwable $e) { $io->error('Failed to delete tenant: ' . $e->getMessage()); $this->logger->error('Tenant delete failed', [ 'identifier' => $identifier, 'error' => $e->getMessage(), ]); return Command::FAILURE; } } }