<?php declare(strict_types=1);
namespace App\Subscriber;
use App\Entity\User;
use App\Event\Recurring\MembershipAdd;
use App\Event\Recurring\MembershipAttempt;
use App\Event\Recurring\MembershipCancel;
use App\Event\Recurring\MembershipRebill;
use App\RabbitMq\Handler\MembershipStatsHandler;
use App\RabbitMq\TasksPool;
use RuntimeException;
use Symfony\Component\Console\ConsoleEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
class MembershipTrackSubscriber implements EventSubscriberInterface
{
private TasksPool $tasksPool;
private bool $dirty = false;
public function __construct(TasksPool $tasksPool)
{
$this->tasksPool = $tasksPool;
}
public function onMembershipAttempt(MembershipAttempt $event): void
{
$user = $event->getUser();
if (!$user instanceof User) {
throw new UnexpectedTypeException($user, User::class);
}
$this->handle($user, MembershipStatsHandler::ATTEMPT);
}
public function onMembershipAdd(MembershipAdd $event): void
{
$user = $event->getUser();
if (!$user instanceof User) {
throw new UnexpectedTypeException($user, User::class);
}
$this->handle($user, MembershipStatsHandler::ADD);
}
public function onMembershipRebill(MembershipRebill $event): void
{
$user = $event->getUser();
if (!$user instanceof User) {
throw new UnexpectedTypeException($user, User::class);
}
$this->handle($user, MembershipStatsHandler::REBILL);
}
public function onMembershipCancel(MembershipCancel $event): void
{
$user = $event->getUser();
if (!$user instanceof User) {
throw new UnexpectedTypeException($user, User::class);
}
$this->handle($user, MembershipStatsHandler::CANCEL);
}
public function sendPool(): void
{
if (!$this->dirty) {
return;
}
$this->tasksPool->send();
}
private function handle(User $user, string $operation): void
{
if (!in_array($operation, [MembershipStatsHandler::ATTEMPT, MembershipStatsHandler::ADD, MembershipStatsHandler::REBILL, MembershipStatsHandler::CANCEL], true)) {
throw new RuntimeException('Unknown operation given. ' . $operation);
}
if (null === $user->getId()) {
throw new UnexpectedTypeException($user->getId(), 'int');
}
$this->dirty = true;
$this->tasksPool->addTask(
MembershipStatsHandler::class,
'handle',
User::class,
$user->getId(),
[$operation]
);
}
/**
* @return array<string, array<int|string, array<int|string, int|string>|int|string>|string>
*/
public static function getSubscribedEvents(): array
{
$events = [
MembershipAttempt::class => 'onMembershipAttempt',
MembershipAdd::class => 'onMembershipAdd',
MembershipRebill::class => 'onMembershipRebill',
MembershipCancel::class => 'onMembershipCancel',
];
if (class_exists(KernelEvents::class)) {
$events[KernelEvents::TERMINATE] = 'sendPool';
}
if (class_exists(ConsoleEvents::class)) {
$events[ConsoleEvents::TERMINATE] = 'sendPool';
}
return $events;
}
}