<?php
namespace App\EventSubscribers\Coaching;
use App\Entity\Coaching\CoachingUser;
use App\Entity\Coaching\Transaction;
use App\Events\Coaching\CoachingUser\CoachingAutologinGeneratedEvent;
use App\Events\Coaching\CoachingUser\CoachingUserCreatedOnWebsiteEvent;
use App\Events\Coaching\CoachingUser\CoachingUserReactivatedEvent;
use App\Events\Coaching\CoachingUser\CoachingUserRegisteredEvent;
use App\Events\Coaching\CoachingUser\CoachingUserSoftRegisteredEvent;
use App\Events\Coaching\CoachingUser\CoachingUserSubscribedEvent;
use App\Events\Coaching\CoachingUser\CoachingUserUnregisteredEvent;
use App\Events\Coaching\CoachingUser\CoachingUserUnsubscribedEvent;
use App\Events\Coaching\CoachingUser\CoachingUserUpdatedEvent;
use App\Services\EmailManager;
use App\Tools\Encryption;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\EntityRepository;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
class CoachingUserSubscriber implements EventSubscriberInterface
{
const
COACHING_USER_SOFT_REGISTER = 'coaching.user.soft.register',
COACHING_USER_REGISTER = 'coaching.user.register',
COACHING_USER_SUBSCRIBE = 'coaching.user.subscribe',
COACHING_USER_UNSUBSCRIBE = 'coaching.user.unsubscribe',
COACHING_USER_UNREGISTER = 'coaching.user.unregister',
COACHING_USER_UPDATE = 'coaching.user.update',
COACHING_AUTOLOGIN_GENERATED = 'coaching.autologin.generated',
COACHING_USER_REACTIVATE = 'coaching.user.reactivate',
COACHING_USER_CREATED_ON_WEBSITE = 'coaching.user.created.on.website'
;
private EmailManager $emailManager;
private EntityRepository $transactionRepository;
/**
* CoachingUserSubscriber constructor.
*/
public function __construct(
private EntityManagerInterface $entityManager,
private UserPasswordHasherInterface $encoder,
private Encryption $encryption,
EmailManager $emailManager
) {
$this->emailManager = $emailManager;
$this->transactionRepository = $entityManager->getRepository(Transaction::class);
}
/**
* @return array
*/
public static function getSubscribedEvents()
{
return array(
self::COACHING_USER_REGISTER => "userRegistration",
self::COACHING_USER_SOFT_REGISTER => "userSoftRegistration",
self::COACHING_USER_UNREGISTER => "userUnRegistration",
self::COACHING_USER_SUBSCRIBE => "userSubscription",
self::COACHING_USER_UNSUBSCRIBE => "userUnSubscription",
self::COACHING_USER_UPDATE => "userUpdate",
self::COACHING_AUTOLOGIN_GENERATED => "autologinGenerated",
self::COACHING_USER_REACTIVATE => "userReactivation",
self::COACHING_USER_CREATED_ON_WEBSITE => "userCreatedOnWebsite"
);
}
/**
* @param CoachingUserCreatedOnWebsiteEvent $event
*/
public function userCreatedOnWebsite(CoachingUserCreatedOnWebsiteEvent $event)
{
// here we need to send the email for this user.
$this->emailManager->sendCoachingRegistrationEmail(
$event->getUser()->getUser(),
[
'password' => $event->getPlainPassword()
]
);
}
/**
* @param CoachingUserRegisteredEvent $event
*/
public function userRegistration(CoachingUserRegisteredEvent $event)
{
$this->createCoachingUserPassword($event->getUser());
$transaction = new Transaction();
$transaction->setUser($event->getUser());
$transaction->setType(Transaction::TYPE_REGISTER);
$transaction->setStatus($this->getApiCallStatus($event->getApiResult()));
$dateEnd = new \DateTime('+30 DAYS');
$transaction->setSubscriptionEndDate($this->getNewEndDate($event->getUser(), $dateEnd));
$this->entityManager->persist($transaction);
$this->entityManager->flush();
}
/**
* @param CoachingUserSoftRegisteredEvent $event
*/
public function userSoftRegistration(CoachingUserSoftRegisteredEvent $event)
{
$this->createCoachingUserPassword($event->getUser());
$transaction = new Transaction();
$transaction->setUser($event->getUser());
$transaction->setType(Transaction::TYPE_SOFT_REGISTER);
$transaction->setStatus($this->getApiCallStatus($event->getApiResult()));
$dateEnd = new \DateTime('+30 DAYS');
$transaction->setSubscriptionEndDate($dateEnd);
$this->entityManager->persist($transaction);
$this->entityManager->flush();
}
/**
* @param CoachingUserUnregisteredEvent $event
*/
public function userUnRegistration(CoachingUserUnregisteredEvent $event)
{
$transaction = new Transaction();
$transaction->setUser($event->getUser());
$transaction->setType(Transaction::TYPE_UNREGISTER);
$transaction->setStatus($this->getApiCallStatus($event->getApiResult()));
$transaction->setSubscriptionEndDate($this->getNewEndDate($event->getUser()));
$this->entityManager->persist($transaction);
$this->entityManager->flush();
}
/**
* @param CoachingUserReactivatedEvent $event
*/
public function userReactivation(CoachingUserReactivatedEvent $event)
{
$coachingUser = $event->getCoachingUser();
$coachingUser->setUnregistered(false);
$transaction = new Transaction();
$transaction->setUser($coachingUser);
$transaction->setType(Transaction::TYPE_REACTIVATE);
$transaction->setStatus($this->getApiCallStatus($event->getApiResult()));
$dateEnd = new \DateTime('+30 DAYS');
$transaction->setSubscriptionEndDate($dateEnd);
$this->entityManager->persist($coachingUser);
$this->entityManager->persist($transaction);
$this->entityManager->flush();
}
/**
* @param CoachingUserSubscribedEvent $event
*/
public function userSubscription(CoachingUserSubscribedEvent $event)
{
$transaction = new Transaction();
$transaction->setUser($event->getUser());
$transaction->setType(Transaction::TYPE_SUBSCRIBE);
$transaction->setStatus($this->getApiCallStatus($event->getApiResult()));
$transaction->setSubscriptionEndDate($event->getDateEnd());
$this->entityManager->persist($transaction);
$this->entityManager->flush();
}
/**
* @param CoachingUserUnsubscribedEvent $event
*/
public function userUnSubscription(CoachingUserUnsubscribedEvent $event)
{
$transaction = new Transaction();
$transaction->setUser($event->getUser());
$transaction->setType(Transaction::TYPE_UNSUBSCRIBE);
$transaction->setStatus($this->getApiCallStatus($event->getApiResult()));
$dateEnd = new \DateTime();
$transaction->setSubscriptionEndDate($dateEnd);
$this->entityManager->persist($transaction);
$this->entityManager->flush();
}
/**
* @param CoachingUserUpdatedEvent $event
*/
public function userUpdate(CoachingUserUpdatedEvent $event)
{
$transaction = new Transaction();
$transaction->setUser($event->getUser());
$transaction->setType(Transaction::TYPE_UPDATE);
$transaction->setStatus($this->getApiCallStatus($event->getApiResult()));
$transaction->setSubscriptionEndDate($this->getNewEndDate($event->getUser()));
$this->entityManager->persist($transaction);
$this->entityManager->flush();
}
/**
* @param CoachingAutologinGeneratedEvent $event
*/
public function autologinGenerated(CoachingAutologinGeneratedEvent $event)
{
$transaction = new Transaction();
$transaction->setUser($event->getUser());
$transaction->setType(Transaction::TYPE_AUTOLOGIN);
if ($event->getApiResult()) {
$transaction->setStatus("SUCCESS");
} else {
$transaction->setStatus("ERROR");
}
$transaction->setSubscriptionEndDate($this->getNewEndDate($event->getUser()));
$this->entityManager->persist($transaction);
$this->entityManager->flush();
}
/**
* @param array $result
* @return mixed|string
*/
private function getApiCallStatus(array $result)
{
static $status_list = [
'success' => Transaction::STATUS_OK,
'failed' => Transaction::STATUS_FAILED,
'error' => Transaction::STATUS_ERROR,
];
return $status = $status_list[$result['status']] ?? Transaction::STATUS_PENDING;
}
/**
* @param CoachingUser $user
* @return Transaction|null
*/
private function getLastTransaction(CoachingUser $user)
{
return $lastTransaction = $this->transactionRepository->getLastTransactionForUser($user);
}
/**
* Assign the correct end date for his current coaching.
*
* @param CoachingUser $user
* @return \DateTime
*/
private function getNewEndDate(CoachingUser $user, \DateTimeInterface $fallBackIfNoTransaction = null)
{
$lastTransaction = $this->getLastTransaction($user);
if ($lastTransaction instanceof Transaction) {
return $lastTransaction->getSubscriptionEndDate();
}
if ($fallBackIfNoTransaction instanceof \DateTime) {
return $fallBackIfNoTransaction;
}
if ($fallBackIfNoTransaction instanceof \DateTimeImmutable) {
// The entity accept only datetime, and a datetimeImmutable can be passed, change object type.
return new \DateTime("@" . $fallBackIfNoTransaction->format("U"));
}
return new \DateTime();
}
/**
* @param CoachingUser $user
* @return CoachingUser|void
*/
protected function createCoachingUserPassword(CoachingUser $user)
{
if (!empty($user->getPassword())) {
return;
}
if (empty($user->getPlainPassword())) {
$user->setPlainPassword($this->encryption->decrypt($user->getUser()->getEncryptedPassword()));
}
$user->setPassword($this->encoder->hashPassword($user, $user->getPlainPassword()));
return $user;
}
}