Skip to content

Commit

Permalink
Merge branch '5.x' into feat/ems_file_from_archive
Browse files Browse the repository at this point in the history
  • Loading branch information
theus77 authored Jul 4, 2024
2 parents 3717a59 + b551348 commit e94548a
Show file tree
Hide file tree
Showing 18 changed files with 268 additions and 161 deletions.
45 changes: 15 additions & 30 deletions EMS/client-helper-bundle/src/Controller/ApiController.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,55 +52,40 @@ public function document(string $apiName, string $contentType, string $ouuid): J
return $this->service->getDocument($apiName, $contentType, $ouuid)->getResponse();
}

public function handleFormPostRequest(Request $request, string $apiName, string $contentType, ?string $ouuid, string $csrfId, string $validationTemplate, int $hashcashLevel, string $hashAlgo, bool $forceCreate = false): JsonResponse
public function handleFormPostRequest(Request $request, string $apiName, string $contentType, ?string $ouuid, string $csrfId, string $validationTemplate, int $hashcashLevel, string $hashAlgo): JsonResponse
{
$this->hashcashHelper->validateHashcash($request, $csrfId, $hashcashLevel, $hashAlgo);
$data = $this->service->treatFormRequest($request, $apiName, $validationTemplate);
$rawData = $this->service->treatFormRequest($request, $apiName, $validationTemplate);

if (null === $data) {
return new JsonResponse([
'success' => false,
'message' => 'Empty data',
]);
if (null === $rawData) {
return new JsonResponse(['success' => false, 'message' => 'Empty data']);
}

try {
if (null === $ouuid || $forceCreate) {
$ouuid = $this->service->createDocument($apiName, $contentType, $ouuid, $data);
} else {
$ouuid = $this->service->updateDocument($apiName, $contentType, $ouuid, $data);
}

return new JsonResponse([
'success' => true,
'ouuid' => $ouuid,
]);
} catch (\Exception $e) {
return new JsonResponse([
'success' => false,
'message' => $e->getMessage(),
]);
$ouuid = $this->service->index($apiName, $contentType, $ouuid, $rawData);

return new JsonResponse(['success' => true, 'ouuid' => $ouuid]);
} catch (\RuntimeException $e) {
return new JsonResponse(['success' => false, 'message' => $e->getMessage()]);
}
}

public function createDocumentFromForm(Request $request, string $apiName, string $contentType, ?string $ouuid, string $redirectUrl, string $validationTemplate = null): RedirectResponse
{
$body = $this->service->treatFormRequest($request, $apiName, $validationTemplate);
$ouuid = $this->service->createDocument($apiName, $contentType, $ouuid, $body);
$rawData = $this->service->treatFormRequest($request, $apiName, $validationTemplate);

$url = \str_replace('%ouuid%', $ouuid, $redirectUrl);
$url = \str_replace('%contenttype%', $contentType, $url);
$ouuid = $this->service->index($apiName, $contentType, $ouuid, $rawData);
$url = \str_replace(['%ouuid%', '%contenttype%'], [$ouuid, $contentType], $redirectUrl);

return new RedirectResponse($url);
}

public function updateDocumentFromForm(Request $request, string $apiName, string $contentType, string $ouuid, string $redirectUrl, string $validationTemplate = null): RedirectResponse
{
$body = $this->service->treatFormRequest($request, $apiName, $validationTemplate);
$ouuid = $this->service->updateDocument($apiName, $contentType, $ouuid, $body);
$rawData = $this->service->treatFormRequest($request, $apiName, $validationTemplate);

$url = \str_replace('%ouuid%', $ouuid, $redirectUrl);
$url = \str_replace('%contenttype%', $contentType, $url);
$ouuid = $this->service->index($apiName, $contentType, $ouuid, $rawData, true);
$url = \str_replace(['%ouuid%', '%contenttype%'], [$ouuid, $contentType], $redirectUrl);

return new RedirectResponse($url);
}
Expand Down
110 changes: 41 additions & 69 deletions EMS/client-helper-bundle/src/Helper/Api/ApiService.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,36 +5,60 @@
namespace EMS\ClientHelperBundle\Helper\Api;

use EMS\ClientHelperBundle\Helper\Elasticsearch\ClientRequest;
use EMS\ClientHelperBundle\Security\CoreApi\User\CoreApiUser;
use EMS\CommonBundle\Common\CoreApi\Exception\NotSuccessfulException;
use EMS\CommonBundle\Helper\EmsFields;
use Psr\Log\LoggerInterface;
use EMS\Helpers\Standard\Json;
use Ramsey\Uuid\Uuid;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\HttpFoundation\FileBag;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Security\Core\Security;
use Twig\Environment;

/**
* @todo use EMS\CommonBundle\Contracts\CoreApi\CoreApiInterface
*/
final class ApiService
{
private const EMS_AJAX_MESSAGE_LEVELS = ['error', 'warning'];

/**
* @param ClientRequest[] $clientRequests
* @param Client[] $apiClients
*/
public function __construct(
private readonly LoggerInterface $logger,
private readonly Environment $twig,
private readonly UrlGeneratorInterface $urlGenerator,
private readonly Security $security,
private readonly iterable $clientRequests = [],
private readonly iterable $apiClients = []
) {
}

/**
* @param array<mixed> $rawData
*/
public function index(string $apiName, string $contentType, ?string $ouuid, array $rawData, bool $merge = false): string
{
$dataEndpoint = $this->getApiClient($apiName)->coreApi->data($contentType);

try {
$ouuid = $ouuid ?? Uuid::uuid4()->toString();

return $dataEndpoint->index($ouuid, $rawData, $merge, true)->getOuuid();
} catch (NotSuccessfulException $e) {
$data = $e->result->getData();
$revisionId = $data['revision_id'] ?? null;

if ($revisionId) {
$dataEndpoint->discard($revisionId);
}

throw new \RuntimeException($e->result->getFirstErrorWarning() ?? 'Finalize failed');
}
}

/**
* @return mixed
*/
Expand All @@ -43,9 +67,7 @@ public function treatFormRequest(Request $request, string $apiName, string $vali
$body = $request->request->all();
$body = $this->treatFiles($body, $apiName, $request->files);
if (null !== $validationTemplate) {
return \json_decode($this->twig->render($validationTemplate, [
'document' => $body,
]), true, 512, JSON_THROW_ON_ERROR);
return Json::decode($this->twig->render($validationTemplate, ['document' => $body]));
}

return $body;
Expand Down Expand Up @@ -163,68 +185,6 @@ public function getContentType(string $apiName, string $contentType, array $filt
return $response;
}

/**
* @param array<mixed> $body
*/
public function updateDocument(string $apiName, string $type, string $ouuid, array $body): string
{
$apiClient = $this->getApiClient($apiName);
$response = $apiClient->updateDocument($type, $ouuid, $body);

return $this->finalizeResponse($apiClient, $response, $type, $ouuid);
}

/**
* @param array<mixed> $body
*/
public function createDocument(string $apiName, string $type, ?string $ouuid, array $body): string
{
$ouuid ??= Uuid::uuid4()->toString();
$apiClient = $this->getApiClient($apiName);
$response = $apiClient->initNewDocument($type, $body, $ouuid);

return $this->finalizeResponse($apiClient, $response, $type, $ouuid);
}

/**
* @param array<mixed> $response
*/
private function finalizeResponse(Client $apiClient, array $response, string $type, ?string $ouuid): string
{
if (!$response['success']) {
foreach (ApiService::EMS_AJAX_MESSAGE_LEVELS as $level) {
if (isset($response[$level][0])) {
throw new \Exception($response[$level][0]);
}
}
throw new \Exception('Initialize draft failed');
}

$revisionId = $response['revision_id'];
$response = $apiClient->finalize($type, $revisionId);

if (!$response['success']) {
try {
$apiClient->discardDraft($type, $revisionId);
} catch (\Exception) {
$this->logger->warning('emsch.api_service.discard_exception', [
'ouuid' => $ouuid,
'type' => $type,
'revision_id' => $revisionId,
]);
}

foreach (ApiService::EMS_AJAX_MESSAGE_LEVELS as $level) {
if (isset($response[$level][0])) {
throw new \Exception($response[$level][0]);
}
}
throw new \Exception('Finalize draft failed');
}

return $response['ouuid'];
}

/**
* @return array<mixed>
*/
Expand Down Expand Up @@ -271,6 +231,18 @@ private function getClientRequest(string $apiName): ClientRequest
}

public function getApiClient(string $clientName): Client
{
$client = $this->getApiClientByName($clientName);

$user = $this->security->getUser();
if ($user instanceof CoreApiUser) {
$client->coreApi->setToken($user->getToken());
}

return $client;
}

private function getApiClientByName(string $clientName): Client
{
foreach ($this->apiClients as $apiClient) {
if ($clientName === $apiClient->getName()) {
Expand Down
2 changes: 1 addition & 1 deletion EMS/client-helper-bundle/src/Resources/config/api.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
<defaults public="false" />

<service id="emsch.api" class="EMS\ClientHelperBundle\Helper\Api\ApiService">
<argument type="service" id="logger" />
<argument type="service" id="twig" />
<argument type="service" id="Symfony\Component\Routing\Generator\UrlGeneratorInterface" />
<argument type="service" id="security.helper" />
<argument type="tagged" tag="emsch.client_request.api" on-invalid="null" />
<argument type="tagged" tag="emsch.api_client" on-invalid="null" />
</service>
Expand Down
2 changes: 1 addition & 1 deletion EMS/common-bundle/src/Common/CoreApi/Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ private function getResult(string $method, string $resource, array $options): Re
$result = new Result($response, $this->logger);

if (!$result->isSuccess()) {
throw new NotSuccessfulException($response);
throw new NotSuccessfulException($result);
}

return $result;
Expand Down
8 changes: 6 additions & 2 deletions EMS/common-bundle/src/Common/CoreApi/Endpoint/Data/Data.php
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,13 @@ public function save(string $ouuid, array $rawData, int $mode = self::MODE_UPDAT
/**
* @param array<string, mixed> $rawData
*/
public function index(?string $ouuid, array $rawData, bool $update = false): Index
public function index(?string $ouuid, array $rawData, bool $merge = false, bool $refresh = false): Index
{
$resource = $this->makeResource($update ? 'update' : 'index', $ouuid);
$resource = $this->makeResource($merge && $ouuid ? 'update' : 'index', $ouuid);

if ($refresh) {
$resource .= '?refresh=true';
}

return new Index($this->client->post($resource, $rawData));
}
Expand Down
27 changes: 26 additions & 1 deletion EMS/common-bundle/src/Common/CoreApi/Endpoint/Data/Index.php
Original file line number Diff line number Diff line change
@@ -1,7 +1,32 @@
<?php

declare(strict_types=1);

namespace EMS\CommonBundle\Common\CoreApi\Endpoint\Data;

class Index extends Draft
use EMS\CommonBundle\Common\CoreApi\Result;
use EMS\CommonBundle\Common\Standard\Type;

class Index
{
private readonly int $id;
private readonly ?string $ouuid;

public function __construct(Result $result)
{
$data = $result->getData();

$this->id = $data['revision_id'];
$this->ouuid = $data['ouuid'] ?? null;
}

public function getRevisionId(): int
{
return $this->id;
}

public function getOuuid(): string
{
return Type::string($this->ouuid);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@

namespace EMS\CommonBundle\Common\CoreApi\Exception;

use EMS\CommonBundle\Common\CoreApi\Result;
use EMS\CommonBundle\Contracts\CoreApi\Exception\NotSuccessfulExceptionInterface;
use Symfony\Contracts\HttpClient\ResponseInterface;

final class NotSuccessfulException extends \RuntimeException implements NotSuccessfulExceptionInterface
{
public function __construct(ResponseInterface $response)
public function __construct(public readonly Result $result)
{
$info = $response->getInfo();
$info = $result->response->getInfo();
$message = \sprintf('[%s] %s was not successful! (Check logs!)', $info['http_method'], $info['url']);

parent::__construct($message, $response->getStatusCode());
parent::__construct($message, $result->response->getStatusCode());
}
}
18 changes: 16 additions & 2 deletions EMS/common-bundle/src/Common/CoreApi/Result.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@ class Result
/** @var array<mixed> */
private readonly array $data;

public function __construct(ResponseInterface $response, LoggerInterface $logger)
{
public function __construct(
public readonly ResponseInterface $response,
LoggerInterface $logger
) {
$data = Json::decode($response->getContent());
$this->data = $data;
$this->acknowledged = isset($data['acknowledged']) ? \boolval($data['acknowledged']) : null;
Expand All @@ -29,6 +31,18 @@ public function __construct(ResponseInterface $response, LoggerInterface $logger
}
}

public function getFirstErrorWarning(): ?string
{
$errors = $this->data['error'] ?? [];
$warnings = $this->data['warning'] ?? [];

return match (true) {
(\count($errors) > 0) => \array_shift($errors),
(\count($warnings) > 0) => \array_shift($warnings),
default => null
};
}

/**
* @return array<mixed>
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public function finalize(int $revisionId): string;
*
* @throws CoreApiExceptionInterface
*/
public function index(?string $ouuid, array $rawData, bool $merge = false): Index;
public function index(?string $ouuid, array $rawData, bool $merge = false, bool $refresh = false): Index;

/**
* @throws CoreApiExceptionInterface
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
namespace EMS\CommonBundle\Tests\Unit\Common\CoreApi\Exception;

use EMS\CommonBundle\Common\CoreApi\Exception\NotSuccessfulException;
use EMS\CommonBundle\Common\CoreApi\Result;
use PHPUnit\Framework\TestCase;
use Psr\Log\LoggerInterface;
use Symfony\Contracts\HttpClient\ResponseInterface;

class NotSuccessfulExceptionAiTest extends TestCase
Expand All @@ -18,11 +20,13 @@ public function testExceptionMessage(): void
'http_method' => 'GET',
'url' => 'https://example.com/api/test',
]);
$response->method('getStatusCode')
->willReturn(404);
$response->method('getStatusCode')->willReturn(404);
$response->method('getContent')->willReturn('{}');

$exception = new NotSuccessfulException($response);
$logger = $this->createMock(LoggerInterface::class);
$result = new Result($response, $logger);

$exception = new NotSuccessfulException($result);
$expectedMessage = '[GET] https://example.com/api/test was not successful! (Check logs!)';
$this->assertEquals($expectedMessage, $exception->getMessage());
$this->assertEquals(404, $exception->getCode());
Expand Down
Loading

0 comments on commit e94548a

Please sign in to comment.