feat(bookstack) : add BookStackSettings API resource with provider and processor

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-15 18:09:20 +01:00
parent df00b27a64
commit 28fbc73248
3 changed files with 124 additions and 0 deletions

View File

@@ -0,0 +1,45 @@
<?php
declare(strict_types=1);
namespace App\ApiResource;
use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\Get;
use ApiPlatform\Metadata\Put;
use App\State\BookStackSettingsProcessor;
use App\State\BookStackSettingsProvider;
use Symfony\Component\Serializer\Attribute\Groups;
#[ApiResource(
operations: [
new Get(
uriTemplate: '/settings/bookstack',
normalizationContext: ['groups' => ['bookstack_settings:read']],
provider: BookStackSettingsProvider::class,
security: "is_granted('ROLE_ADMIN')",
),
new Put(
uriTemplate: '/settings/bookstack',
denormalizationContext: ['groups' => ['bookstack_settings:write']],
normalizationContext: ['groups' => ['bookstack_settings:read']],
provider: BookStackSettingsProvider::class,
processor: BookStackSettingsProcessor::class,
security: "is_granted('ROLE_ADMIN')",
),
],
)]
final class BookStackSettings
{
#[Groups(['bookstack_settings:read', 'bookstack_settings:write'])]
public ?string $url = null;
#[Groups(['bookstack_settings:write'])]
public ?string $tokenId = null;
#[Groups(['bookstack_settings:write'])]
public ?string $tokenSecret = null;
#[Groups(['bookstack_settings:read'])]
public bool $hasToken = false;
}

View File

@@ -0,0 +1,49 @@
<?php
declare(strict_types=1);
namespace App\State;
use ApiPlatform\Metadata\Operation;
use ApiPlatform\State\ProcessorInterface;
use App\ApiResource\BookStackSettings;
use App\Entity\BookStackConfiguration;
use App\Repository\BookStackConfigurationRepository;
use App\Service\TokenEncryptor;
use Doctrine\ORM\EntityManagerInterface;
final readonly class BookStackSettingsProcessor implements ProcessorInterface
{
public function __construct(
private EntityManagerInterface $em,
private BookStackConfigurationRepository $configRepository,
private TokenEncryptor $tokenEncryptor,
) {}
public function process(mixed $data, Operation $operation, array $uriVariables = [], array $context = []): BookStackSettings
{
assert($data instanceof BookStackSettings);
$config = $this->configRepository->findSingleton();
if (null === $config) {
$config = new BookStackConfiguration();
}
$config->setUrl($data->url);
if (null !== $data->tokenId && '' !== $data->tokenId
&& null !== $data->tokenSecret && '' !== $data->tokenSecret) {
$config->setEncryptedTokenId($this->tokenEncryptor->encrypt($data->tokenId));
$config->setEncryptedTokenSecret($this->tokenEncryptor->encrypt($data->tokenSecret));
}
$this->em->persist($config);
$this->em->flush();
$result = new BookStackSettings();
$result->url = $config->getUrl();
$result->hasToken = $config->hasToken();
return $result;
}
}

View File

@@ -0,0 +1,30 @@
<?php
declare(strict_types=1);
namespace App\State;
use ApiPlatform\Metadata\Operation;
use ApiPlatform\State\ProviderInterface;
use App\ApiResource\BookStackSettings;
use App\Repository\BookStackConfigurationRepository;
final readonly class BookStackSettingsProvider implements ProviderInterface
{
public function __construct(
private BookStackConfigurationRepository $configRepository,
) {}
public function provide(Operation $operation, array $uriVariables = [], array $context = []): BookStackSettings
{
$config = $this->configRepository->findSingleton();
$dto = new BookStackSettings();
if (null !== $config) {
$dto->url = $config->getUrl();
$dto->hasToken = $config->hasToken();
}
return $dto;
}
}