<?php
namespace App\Atd\Supplier\Bokun\Domain\EventListeners;
use App\Atd\Domain\Config\ConfigDto;
use App\Atd\Domain\RequestDto;
use App\Atd\Supplier\Bokun\Auth\Domain\AuthCommand;
use App\Atd\Supplier\Bokun\Domain\CommandRunnerContext;
use App\Atd\Supplier\Bokun\Domain\Events\EventTypes;
use App\Atd\Supplier\Bokun\Domain\Events\PickupPlacesRequestEvent;
use App\Atd\Supplier\Bokun\Domain\Location;
use App\Atd\Supplier\Bokun\KeyGenerator\Service\KeyGeneratorService;
use App\Atd\Supplier\Bokun\PickupPlaces\Domain\PickupPlacesCommand;
use App\Atd\Supplier\Bokun\PickupPlaces\Domain\PickupPlacesCommandFactory;
use App\EventListener\SupplierEventSubscriber;
use App\Service\AuxDataStorageService;
use App\Service\ConfigDtoService;
use App\Service\Connections\RedisConnection;
use Psr\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
class PickupPlacesRequestListener extends SupplierEventSubscriber
{
/** Odd that even though this is domain logic we still need to identify the domain */
public const PROVIDER_CODE = 'bkn';
public function __construct(
private readonly CommandRunnerContext $context,
private readonly AuthCommand $authCommand,
private readonly PickupPlacesCommandFactory $pickupPlacesCommandFactory,
private readonly ConfigDtoService $configDtoService,
private readonly AuxDataStorageService $auxDataStorageService,
private readonly ParameterBagInterface $parameterBag,
private readonly KeyGeneratorService $keyGeneratorService,
protected EventDispatcherInterface $dispatcher
) {
parent::__construct($dispatcher);
}
/**
* @return string[]
*/
public static function getSubscribedEvents(): array
{
return [
EventTypes::PICKUP_PLACES_REQUEST => 'handleEvent',
];
}
/**
* @throws \Exception
*/
public function handleEvent(PickupPlacesRequestEvent $event): void
{
try {
$payload = [
'activityId' => $event->getActivityId(),
];
$this->setEndpointRequestDto($payload);
$this->authCommand->execute($this->context, PickupPlacesCommand::CMD_NAME, $payload);
$pickupPlacesCommand = $this->pickupPlacesCommandFactory->create();
$pickupPlacesCommand->execute($this->context);
$placesResponse = $this->context->getPickupPlacesResponseDao();
$this->cacheLocations($event->getActivityId(), $placesResponse->getLocations());
$this->sendInterruptResponse($placesResponse->toArray());
} catch (\Throwable $exception) {
throw new \Exception($exception->getMessage());
}
}
private function getConfigDto(): ConfigDto
{
return $this->configDtoService->configDtoFactory(self::PROVIDER_CODE);
}
/**
* @throws \Exception
*/
private function setEndpointRequestDto(array $requestData = []): void
{
$this->context->setRequestDto(
RequestDto::factory([
'method' => 'PUT',
'query' => null,
'data' => $requestData,
'provider' => self::PROVIDER_CODE,
'nocache' => true,
'configDto' => $this->getConfigDto(),
'updateDatastore' => false,
])
);
}
private function getConnectedAuxCacheStoreService(): AuxDataStorageService
{
$conn = new RedisConnection(
$this->parameterBag->get('app.aux.redis.ip'),
$this->parameterBag->get('app.aux.redis.port')
);
return $this->auxDataStorageService->connect($conn);
}
/**
* @param array|Location[] $locations
*
* @throws \Exception
*/
private function cacheLocations(string $activityId, array $locations): void
{
$key = $this->keyGeneratorService->generatePickupLocationsKey(
self::PROVIDER_CODE,
$activityId
);
$this->getConnectedAuxCacheStoreService()
->store(
$key,
$locations
);
}
}