<?php declare(strict_types=1);
namespace App\Subscriber;
use App\Email\EmailStrategy;
use App\Email\ProposalCanceled;
use App\Email\ProposalDealDownloadable;
use App\Email\ProposalFunded;
use App\Email\ProposalFundedInternalNotification;
use App\Entity\Deal;
use App\Entity\Project;
use App\Entity\Proposal;
use App\Entity\User;
use App\Event\ProposalCanceledEvent;
use App\Event\ProposalFundedEvent;
use App\RabbitMq\Processing\PopProcessingEvent;
use Sindrive\EmailSenderBundle\Service\EmailSender;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
use UploadsBundle\RabbitMq\Handler\FileHandlerFactoryHandler;
class ProposalEmailSubscriber implements EventSubscriberInterface
{
private EmailSender $emailSender;
private EmailStrategy $emailStrategy;
public function __construct(EmailSender $emailSender, EmailStrategy $emailStrategy)
{
$this->emailSender = $emailSender;
$this->emailStrategy = $emailStrategy;
}
public function onFunded(ProposalFundedEvent $event): void
{
$proposal = $event->getProposal();
$this->sendEmailToBidders(
$proposal,
function (Proposal $proposal, User $bidUser): void {
if (!$proposal instanceof Deal && !$proposal instanceof Project) {
throw new UnexpectedTypeException($proposal, Deal::class . '|' . Project::class);
}
$this->emailSender->sendType(new ProposalFunded($proposal, $bidUser, $this->emailStrategy));
}
);
$this->emailSender->sendType(new ProposalFundedInternalNotification($proposal, $this->emailStrategy));
}
public function onCanceled(ProposalCanceledEvent $event): void
{
$this->sendEmailToBidders(
$event->getProposal(),
function (Proposal $proposal, User $bidUser): void {
if (!$proposal instanceof Deal && !$proposal instanceof Project) {
throw new UnexpectedTypeException($proposal, Deal::class . '|' . Project::class);
}
$this->emailSender->sendType(new ProposalCanceled($proposal, $bidUser, $this->emailStrategy));
}
);
}
public function onPop(PopProcessingEvent $event): void
{
if ($event->getService() !== FileHandlerFactoryHandler::HANDLER) {
return;
}
/** @var string[] $arguments */
$arguments = $event->getArguments();
if (!isset($arguments[0]) || $arguments[0] !== 'project_video') {
return;
}
if ($event->getMethod() !== 'move' && $event->getMethod() !== 'create') {
return;
}
/** @var Project $proposal */
$proposal = $event->getEntity();
if (!$proposal->isFunded() || !$proposal->isFinished() || $proposal->isDownloadableEmailSent()) {
return;
}
$proposal->setDownloadableEmailSent();
$this->sendEmailToBidders(
$proposal,
function (Project $proposal, User $bidUser): void {
$this->emailSender->sendType(new ProposalDealDownloadable($proposal, $bidUser, $this->emailStrategy));
}
);
}
/**
* @param Project|Deal $proposal
*/
private function sendEmailToBidders(Proposal $proposal, callable $sendEmailCallable): void
{
$bidders = [];
foreach ($proposal->getBids() as $proposalBid) {
$bidUser = $proposalBid->getUser();
if (isset($bidders[$bidUser->getId()])) {
continue;
}
if (!$proposalBid->isJustRefunded() && ($proposalBid->isRefunded() || $proposalBid->isCanceled())) {
continue;
}
$bidders[$bidUser->getId()] = true;
if (!$bidUser->shouldNotifyProposal($proposal)) {
continue;
}
$sendEmailCallable($proposal, $bidUser);
}
}
/**
* @return array<string, array<int|string, array<int|string, int|string>|int|string>|string>
*/
public static function getSubscribedEvents(): array
{
return [
ProposalFundedEvent::class => 'onFunded',
ProposalCanceledEvent::class => 'onCanceled',
PopProcessingEvent::class => 'onPop',
];
}
}