tarlepp/symfony-flex-backend

View on GitHub
src/Command/ApiKey/ApiKeyHelper.php

Summary

Maintainability
A
0 mins
Test Coverage
<?php
declare(strict_types = 1);
/**
 * /src/Command/ApiKey/ApiKeyHelper.php
 *
 * @author TLe, Tarmo Leppänen <tarmo.leppanen@pinja.com>
 */

namespace App\Command\ApiKey;

use App\Entity\ApiKey;
use App\Resource\ApiKeyResource;
use App\Security\RolesService;
use Closure;
use Symfony\Component\Console\Style\SymfonyStyle;
use Throwable;
use function array_map;
use function implode;
use function sprintf;

/**
 * @package App\Command\ApiKey
 * @author TLe, Tarmo Leppänen <tarmo.leppanen@pinja.com>
 */
class ApiKeyHelper
{
    public function __construct(
        private readonly ApiKeyResource $apiKeyResource,
        private readonly RolesService $rolesService,
    ) {
    }

    /**
     * Method to get API key entity. Also note that this may return a null in
     * cases that user do not want to make any changes to API keys.
     *
     * @throws Throwable
     */
    public function getApiKey(SymfonyStyle $io, string $question): ?ApiKey
    {
        $found = false;
        $apiKey = null;

        while ($found !== true) {
            $apiKey = $this->getApiKeyEntity($io, $question);

            if (!$apiKey instanceof ApiKey) {
                break;
            }

            $message = sprintf(
                'Is this the correct API key \'[%s] [%s] %s\'?',
                $apiKey->getId(),
                $apiKey->getToken(),
                $apiKey->getDescription(),
            );

            $found = $io->confirm($message, false);
        }

        return $apiKey ?? null;
    }

    /**
     * Helper method to get "normalized" message for API key. This is used on
     * following cases:
     *  - User changes API key token
     *  - User creates new API key
     *  - User modifies API key
     *  - User removes API key
     *
     * @return array<int, string>
     */
    public function getApiKeyMessage(string $message, ApiKey $apiKey): array
    {
        return [
            $message,
            sprintf(
                "GUID:  %s\nToken: %s",
                $apiKey->getId(),
                $apiKey->getToken(),
            ),
        ];
    }

    /**
     * Method to list ApiKeys where user can select desired one.
     *
     * @throws Throwable
     */
    private function getApiKeyEntity(SymfonyStyle $io, string $question): ?ApiKey
    {
        $choices = [];

        array_map(
            $this->getApiKeyIterator($choices),
            $this->apiKeyResource->find(orderBy: [
                'token' => 'ASC',
            ])
        );

        $choices['Exit'] = 'Exit command';

        return $this->apiKeyResource->findOne((string)$io->choice($question, $choices));
    }

    /**
     * Method to return ApiKeyIterator closure. This will format ApiKey
     * entities for choice list.
     *
     * @param array<string, string> $choices
     */
    private function getApiKeyIterator(array &$choices): Closure
    {
        return function (ApiKey $apiKey) use (&$choices): void {
            $choices[$apiKey->getId()] = sprintf(
                '[Token: %s] %s - Roles: %s',
                $apiKey->getToken(),
                $apiKey->getDescription(),
                implode(', ', $this->rolesService->getInheritedRoles($apiKey->getRoles())),
            );
        };
    }
}