mustSuggestArgumentValuesFor('identifier')) { $clients = $this->clientRepository->findAll(Pagination::ofOffsetAndLimit(0, 100)); /** @var list $items */ $items = array_map( static fn (Client $client): Suggestion => new Suggestion( value: $client->identifier->value, description: sprintf('%s (%s)', $client->name->value, $client->isActive ? 'Active' : 'Inactive'), ), $clients->getItems(), ); $suggestions->suggestValues($items); } } public function handle( RegenerateClientSecret $usecase, FindClient $findClient, UsecaseExecutor $executor, ): int { $identifierString = $this->resolveIdentifier($findClient, $executor); if ($identifierString === null) { return self::FAILURE; } try { $clientIdentifier = $this->parseClientIdentifier($identifierString, $findClient, $executor); $client = $this->clientRepository->findByIdentifier($clientIdentifier); if ($client === null) { $this->error(sprintf("Client '%s' not found.", $clientIdentifier->value)); return self::FAILURE; } if (! $this->confirmRegeneration($client)) { $this->warn('Secret regeneration cancelled.'); return self::SUCCESS; } $input = new Input($client->id); /** @var RegenerateClientSecretView $view */ $view = UsecaseBuilder::using($executor) ->do($usecase) ->from($input) ->with(new RegenerateClientSecretPresenter()) ->run(); $this->displayResult($client, $view); return self::SUCCESS; } catch (ClientNotFoundException | \InvalidArgumentException $e) { $this->error($e->getMessage()); return self::FAILURE; } } private function resolveIdentifier(FindClient $findClient, UsecaseExecutor $executor): ?string { $raw = $this->argument('identifier'); if ($raw !== null) { return (string) $raw; } /** @var string|null $answer */ $answer = $this->anticipate( 'Search client (by name, ID, identifier, or slug):', function (string $input) use ($findClient, $executor): array { $trimmed = trim($input); if ($trimmed === '') { return []; } try { /** @var FindClientView $view */ $view = UsecaseBuilder::using($executor) ->do($findClient) ->from(new FindClientInput($trimmed)) ->with(new FindClientPresenter()) ->run(); return array_map( static fn (FoundClientItem $item): string => $item->identifier, $view->clients, ); } catch (\Throwable) { return []; } } ); if ($answer === null || trim($answer) === '') { $this->error('No client specified.'); return null; } return trim($answer); } /** * @throws \InvalidArgumentException */ private function parseClientIdentifier( string $value, FindClient $findClient, UsecaseExecutor $executor, ): ClientIdentifier { try { return new ClientIdentifier($value); } catch (\InvalidArgumentException) { try { /** @var FindClientView $view */ $view = UsecaseBuilder::using($executor) ->do($findClient) ->from(new FindClientInput($value)) ->with(new FindClientPresenter()) ->run(); if (count($view->clients) === 1) { return new ClientIdentifier($view->clients[0]->identifier); } if (count($view->clients) > 1) { foreach ($view->clients as $found) { if ( strcasecmp($found->name, $value) === 0 || strcasecmp($found->id, $value) === 0 ) { return new ClientIdentifier($found->identifier); } } } } catch (\Throwable) { } throw new \InvalidArgumentException("Invalid client identifier '{$value}'. Expected a valid client identifier."); } } private function confirmRegeneration(Client $client): bool { $this->newLine(); $this->warn(sprintf("Regenerating the secret will immediately invalidate the existing secret for client '%s'.", $client->name->value)); return $this->confirm('Do you want to proceed?', false); } private function displayResult(Client $client, RegenerateClientSecretView $view): void { $this->newLine(); $this->info($view->message); $this->newLine(); $this->table( ['Field', 'Value'], [ ['ID', $client->id->value], ['Name', $client->name->value], ['Identifier', $view->identifier], ['New Secret', $view->secret], ], ); $this->newLine(); $this->warn('WARNING: Store the new secret securely, it cannot be retrieved later.'); } }