generated from Nodarx/template
178 lines
6.6 KiB
PHP
178 lines
6.6 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
/**
|
|
* SPDX-FileCopyrightText: Sebastian Krupinski <krupinski01@gmail.com>
|
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
|
*/
|
|
|
|
namespace KTXM\ProviderImap\Console;
|
|
|
|
use KTXM\ProviderImap\Providers\Provider;
|
|
use KTXM\ProviderImap\Providers\Service;
|
|
use KTXC\SessionTenant;
|
|
use Symfony\Component\Console\Attribute\AsCommand;
|
|
use Symfony\Component\Console\Command\Command;
|
|
use Symfony\Component\Console\Input\InputArgument;
|
|
use Symfony\Component\Console\Input\InputInterface;
|
|
use Symfony\Component\Console\Input\InputOption;
|
|
use Symfony\Component\Console\Output\OutputInterface;
|
|
use Symfony\Component\Console\Style\SymfonyStyle;
|
|
|
|
/**
|
|
* Remove a stored IMAP service connection.
|
|
*
|
|
* Looks up the service by its ID (or prompts for one), confirms with the
|
|
* operator, then permanently deletes the service document from the store.
|
|
*
|
|
* Usage:
|
|
* bin/console provider_imap_mail:service:disconnect --tenant=t1 --user=u1 <service-id>
|
|
*/
|
|
#[AsCommand(
|
|
name: 'provider_imap_mail:service:disconnect',
|
|
description: 'Remove a stored IMAP service connection',
|
|
)]
|
|
class DisconnectCommand extends Command
|
|
{
|
|
public function __construct(
|
|
private readonly Provider $provider,
|
|
private readonly SessionTenant $sessionTenant,
|
|
) {
|
|
parent::__construct();
|
|
}
|
|
|
|
protected function configure(): void
|
|
{
|
|
$this
|
|
->addArgument('service-id', InputArgument::OPTIONAL, 'Service ID to remove')
|
|
->addOption('tenant', 't', InputOption::VALUE_REQUIRED, 'Tenant ID')
|
|
->addOption('user', 'u', InputOption::VALUE_REQUIRED, 'User ID')
|
|
->addOption('force', 'f', InputOption::VALUE_NONE, 'Skip confirmation prompt')
|
|
->setHelp(<<<'HELP'
|
|
The <info>provider_imap_mail:service:disconnect</info> command permanently removes
|
|
a stored IMAP service configuration from the store.
|
|
|
|
Examples:
|
|
|
|
Interactive (lists services and prompts for ID):
|
|
<info>bin/console provider_imap_mail:service:disconnect --tenant=t1 --user=u1</info>
|
|
|
|
Direct, with confirmation:
|
|
<info>bin/console provider_imap_mail:service:disconnect abc123 --tenant=t1 --user=u1</info>
|
|
|
|
Skip confirmation:
|
|
<info>bin/console provider_imap_mail:service:disconnect abc123 --tenant=t1 --user=u1 --force</info>
|
|
HELP);
|
|
}
|
|
|
|
protected function interact(InputInterface $input, OutputInterface $output): void
|
|
{
|
|
$io = new SymfonyStyle($input, $output);
|
|
|
|
if (!$input->getOption('tenant')) {
|
|
$tenant = $io->ask('Tenant ID');
|
|
if ($tenant) $input->setOption('tenant', $tenant);
|
|
}
|
|
|
|
if (!$input->getOption('user')) {
|
|
$user = $io->ask('User ID');
|
|
if ($user) $input->setOption('user', $user);
|
|
}
|
|
|
|
// If no service ID given, list available services and let the operator pick
|
|
if (!$input->getArgument('service-id')) {
|
|
$tenantId = (string) ($input->getOption('tenant') ?? '');
|
|
$userId = (string) ($input->getOption('user') ?? '');
|
|
|
|
if ($tenantId !== '' && $userId !== '') {
|
|
$this->sessionTenant->configureById($tenantId);
|
|
$services = $this->provider->serviceList($tenantId, $userId);
|
|
|
|
if (empty($services)) {
|
|
// nothing to select — let execute() handle the error
|
|
return;
|
|
}
|
|
|
|
$choices = [];
|
|
foreach ($services as $id => $service) {
|
|
$label = $service instanceof Service ? ($service->getLabel() ?? $id) : $id;
|
|
$choices[$id] = "{$label} [{$id}]";
|
|
}
|
|
|
|
$chosen = $io->choice('Select service to disconnect', array_values($choices));
|
|
// resolve the chosen label back to its key
|
|
$serviceId = (string) array_search($chosen, $choices, true);
|
|
if ($serviceId !== '') {
|
|
$input->setArgument('service-id', $serviceId);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
protected function execute(InputInterface $input, OutputInterface $output): int
|
|
{
|
|
$io = new SymfonyStyle($input, $output);
|
|
|
|
$tenantId = (string) ($input->getOption('tenant') ?? '');
|
|
$userId = (string) ($input->getOption('user') ?? '');
|
|
$serviceId = (string) ($input->getArgument('service-id') ?? '');
|
|
$force = (bool) $input->getOption('force');
|
|
|
|
$errors = [];
|
|
if ($tenantId === '') $errors[] = 'Tenant ID is required (--tenant).';
|
|
if ($userId === '') $errors[] = 'User ID is required (--user).';
|
|
if ($serviceId === '') $errors[] = 'Service ID is required.';
|
|
|
|
if (!empty($errors)) {
|
|
$io->error($errors);
|
|
return Command::FAILURE;
|
|
}
|
|
|
|
// ── Fetch service for display ────────────────────────────────────────
|
|
$this->sessionTenant->configureById($tenantId);
|
|
$service = $this->provider->serviceFetch($tenantId, $userId, $serviceId);
|
|
|
|
if ($service === null) {
|
|
$io->error("Service '{$serviceId}' not found.");
|
|
return Command::FAILURE;
|
|
}
|
|
|
|
$label = $service->getLabel() ?? $serviceId;
|
|
$host = $service->getLocation()?->getHost() ?? 'unknown';
|
|
|
|
$io->title('Disconnect IMAP Service');
|
|
$io->definitionList(
|
|
['ID' => $serviceId],
|
|
['Label' => $label],
|
|
['Host' => $host],
|
|
);
|
|
|
|
// ── Confirmation ─────────────────────────────────────────────────────
|
|
|
|
if (!$force) {
|
|
$confirm = $io->confirm(
|
|
"Permanently remove service <comment>{$label}</comment> ({$serviceId})?",
|
|
false
|
|
);
|
|
if (!$confirm) {
|
|
$io->note('Aborted.');
|
|
return Command::SUCCESS;
|
|
}
|
|
}
|
|
|
|
// ── Destroy ──────────────────────────────────────────────────────────
|
|
|
|
$deleted = $this->provider->serviceDestroy($tenantId, $userId, $service);
|
|
|
|
if (!$deleted) {
|
|
$io->error("Failed to remove service '{$serviceId}'.");
|
|
return Command::FAILURE;
|
|
}
|
|
|
|
$io->success("Service '{$label}' ({$serviceId}) has been removed.");
|
|
|
|
return Command::SUCCESS;
|
|
}
|
|
}
|