<?php
/**
* Created by PhpStorm.
* User: Igor Ratsun
* Date: 27.09.2021
* Time: 12:55
*/
namespace App\Service;
use App\Config\CartConfig;
use App\Entity\PromoCode;
use App\Entity\Speaker;
use App\Entity\SpeakerConsultation;
use App\Entity\SpeakerCourse;
use App\Repository\SpeakerConsultationRepository;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\RequestStack;
class CartService
{
const SESSION_KEY = 'cart_bag';
private SpeakerConsultationRepository $speakerConsultationRepository;
private EntityManagerInterface $entityManager;
private RequestStack $requestStack;
public function __construct(
SpeakerConsultationRepository $speakerConsultationRepository,
EntityManagerInterface $entityManager,
RequestStack $requestStack
)
{
$this->speakerConsultationRepository = $speakerConsultationRepository;
$this->entityManager = $entityManager;
$this->requestStack = $requestStack;
}
public function freezeConsultation($id, $type): bool
{
$consultation = $this->speakerConsultationRepository->findIfNotFrozen($id);
if (!is_null($consultation)) {
$expired = (new \DateTime())->modify('+' . CartConfig::FREEZE_MIN . ' minutes');
$this->addConsultation($consultation, $type, $expired);
// Update user consultation
foreach ($this->speakerConsultationRepository->findBy(['id' => $this->getConsultationsIds()]) as $item) {
$item->setFreezeDate($expired);
$this->entityManager->persist($item);
}
$this->entityManager->flush();
return true;
}
return false;
}
protected function addConsultation(SpeakerConsultation $consultation, $type, \DateTime $expired): CartService
{
$consultations = $this->getConsultations();
$consultations[$consultation->getSpeaker()->getId()][$consultation->getId()] = [
'id' => $consultation->getId(),
'type' => $type,
];
$this->setData([
'consultations' => $consultations,
'expired' => $expired,
]);
return $this;
}
public function addPromoCode(PromoCode $promoCode): CartService
{
$promoCodes = $this->getPromoCodes();
$promoCodes[$promoCode->getSpeaker()->getId()] = $promoCode->getId();
$this->setData(['promoCodes' => $promoCodes]);
return $this;
}
public function removePromoCodeBySpeakerId($speakerId): CartService
{
$promoCodes = $this->getPromoCodes();
if (isset($promoCodes[$speakerId])) {
unset($promoCodes[$speakerId]);
$this->setData(['promoCodes' => $promoCodes]);
}
return $this;
}
public function getConsultations()
{
return $this->getData()['consultations'] ?? [];
}
public function getExpired()
{
return $this->getData()['expired'] ?? null;
}
public function getPromoCodes()
{
return $this->getData()['promoCodes'] ?? [];
}
public function getTimeZone(): string
{
return $this->getData()['timezone'] ?? (new \DateTime())->getTimezone()->getName();
}
public function clearConsultations(): bool
{
foreach ($this->speakerConsultationRepository->findBy(['id' => $this->getConsultationsIds()]) as $item) {
$item->setFreezeDate(null);
$this->entityManager->persist($item);
}
$this->entityManager->flush();
$this->setData(['consultations' => [], 'expired' => null]);
return true;
}
public function setTimeZone(string $timezone): CartService
{
if (strpos($timezone, '/')) {
$this->setData(['timezone' => $timezone]);
}
return $this;
}
public function getConsultationsIds(): array
{
$ids = [];
foreach ($this->getConsultations() as $data) {
foreach (array_keys($data) as $id) {
$ids[] = $id;
}
}
return $ids;
}
public function removeConsultation(SpeakerConsultation $consultation): CartService
{
$consultations = $this->getConsultations();
if (isset($consultations[$consultation->getSpeaker()->getId()][$consultation->getId()])) {
$consultation->setFreezeDate(null);
$this->entityManager->persist($consultation);
$this->entityManager->flush();
unset($consultations[$consultation->getSpeaker()->getId()][$consultation->getId()]);
if (empty($consultations[$consultation->getSpeaker()->getId()])) {
unset($consultations[$consultation->getSpeaker()->getId()]);
}
$this->setData(['consultations' => $consultations]);
}
if (empty($consultations)) {
$this->setData(['expired' => null]);
}
return $this;
}
public function clear(): CartService
{
$this->setData($this->getDefault());
return $this;
}
public function getServices()
{
return $this->getData()['services'] ?? [];
}
public function addService($code, Speaker $speaker): CartService
{
$services = $this->getServices();
if (empty($services[$speaker->getId()]) || !in_array($code, $services[$speaker->getId()])) {
$services[$speaker->getId()][] = $code;
$this->setData(['services' => $services]);
}
return $this;
}
public function removeService($code, Speaker $speaker): CartService
{
$services = $this->getServices();
if (!empty($services[$speaker->getId()]) && in_array($code, $services[$speaker->getId()])) {
unset($services[$speaker->getId()][array_search($code, $services[$speaker->getId()])]);
if (empty($services[$speaker->getId()])) {
unset($services[$speaker->getId()]);
}
$this->setData(['services' => $services]);
}
return $this;
}
public function getPremiumPackages()
{
return $this->getData()['premium_packages'] ?? [];
}
public function addPremiumPackage($code, Speaker $speaker): CartService
{
$package = $this->getPremiumPackages();
if (empty($package[$speaker->getId()]) || !in_array($code, $package[$speaker->getId()][$speaker->getId()])) {
$package[$speaker->getId()][] = $code;
$this->setData(['premium_packages' => $package]);
}
return $this;
}
public function removePremiumPackage($code, Speaker $speaker): CartService
{
$package = $this->getPremiumPackages();
if (!empty($package[$speaker->getId()]) && in_array($code, $package[$speaker->getId()])) {
unset($package[$speaker->getId()][array_search($code, $package[$speaker->getId()])]);
if (empty($package[$speaker->getId()])) {
unset($package[$speaker->getId()]);
}
$this->setData(['premium_packages' => $package]);
}
return $this;
}
public function getCourses()
{
return $this->getData()['courses'] ?? [];
}
public function addCourse(SpeakerCourse $course): CartService
{
$courses = $this->getCourses();
if (empty($courses[$course->getSpeaker()->getId()]) || !in_array($course->getId(), $courses[$course->getSpeaker()->getId()])) {
$courses[$course->getSpeaker()->getId()][] = $course->getId();
$this->setData(['courses' => $courses]);
}
return $this;
}
public function removeCourse(SpeakerCourse $course): CartService
{
$courses = $this->getCourses();
if (!empty($courses[$course->getSpeaker()->getId()]) && in_array($course->getId(), $courses[$course->getSpeaker()->getId()])) {
unset($courses[$course->getSpeaker()->getId()][array_search($course->getId(), $courses[$course->getSpeaker()->getId()])]);
if (empty($courses[$course->getSpeaker()->getId()])) {
unset($courses[$course->getSpeaker()->getId()]);
}
$this->setData(['courses' => $courses]);
}
return $this;
}
public function getCoursesIds(): array
{
$ids = [];
foreach ($this->getCourses() as $data) {
foreach ($data as $id) {
$ids[] = $id;
}
}
return $ids;
}
public function getItemsCount()
{
$count = count($this->getConsultationsIds());
foreach ($this->getCourses() as $items) {
$count += count($items);
}
return $count;
}
protected function getData()
{
return $this->requestStack->getSession()->get(self::SESSION_KEY, $this->getDefault());
}
protected function setData(array $data): CartService
{
$this->requestStack->getSession()->set(self::SESSION_KEY, array_merge($this->getData(), $data));
return $this;
}
protected function getDefault(): array
{
return [
'consultations' => [],
'expired' => null,
'promoCodes' => [],
'services' => [],
'premium_packages' => [],
'courses' => [],
];
}
}