<?php
namespace App\Entity\LearningCourses;
use App\Annotation\SiteAware;
use App\Entity\AbstractBase;
use App\Entity\Interfaces\SiteInterface;
use App\Entity\MiniAbstractBase;
use App\Entity\Traits\ActiveTrait;
use App\Entity\Traits\DescriptionTrait;
use App\Entity\Traits\ImageFileNameTrait;
use App\Entity\Traits\ImageFileTrait;
use App\Entity\Traits\NameTrait;
use App\Entity\Traits\SiteTrait;
use App\Entity\User;
use App\Enum\LearningCourseTypeEnum;
use App\Repository\LearningCourses\LearningCourseRepository;
use DateTimeImmutable;
use DateTimeInterface;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;
use Symfony\Component\HttpFoundation\File\File;
use Vich\UploaderBundle\Mapping\Annotation as Vich;
/**
* @ORM\Table(name="vulco_learning_course", indexes={@ORM\Index(name="learning_course_site_idx", columns={"site"})})
* @ORM\Entity(repositoryClass=LearningCourseRepository::class)
* @Gedmo\SoftDeleteable(fieldName="removedAt", timeAware=false)
* @SiteAware(siteFieldName="site")
* @Vich\Uploadable
*/
class LearningCourse extends AbstractBase implements SiteInterface
{
use ActiveTrait;
use DescriptionTrait;
use ImageFileTrait;
use ImageFileNameTrait;
use NameTrait;
use SiteTrait;
/**
* @ORM\ManyToMany(targetEntity="App\Entity\User")
* @ORM\JoinTable(name="vulco_learning_courses_users",
* joinColumns={@ORM\JoinColumn(name="learning_course_id", referencedColumnName="id")},
* inverseJoinColumns={@ORM\JoinColumn(name="user_id", referencedColumnName="id")}
* )
*/
private ?Collection $associatedUsers;
/**
* @ORM\ManyToOne(targetEntity="LearningCourseCategory", inversedBy="courses")
*/
private ?LearningCourseCategory $category = null;
/**
* @ORM\OneToMany(targetEntity="LearningCourseRegistration", mappedBy="course", cascade={"persist", "remove"})
*/
private ?Collection $registrations; // order here is important because cascade remove will remove registrations before sessions
/**
* @ORM\OneToMany(targetEntity="LearningCourseSession", mappedBy="course", cascade={"persist", "remove"})
* @ORM\OrderBy({"date": "ASC"})
*/
private ?Collection $sessions;
/**
* @ORM\Column(type="string", length=255, nullable=false)
*/
private string $name;
/**
* @ORM\Column(type="text", length=10000, nullable=true)
*/
private ?string $description;
/**
* @Vich\UploadableField(mapping="learning_course_image", fileNameProperty="imageFileName")
*/
private ?File $imageFile = null;
/**
* @ORM\Column(type="string", length=255, nullable=true)
*/
private ?string $imageFileName = null;
/**
* @ORM\Column(type="integer", nullable=false, options={"default": 0})
*/
private int $type = 0;
/**
* @ORM\Column(type="integer", nullable=false, options={"default": 0})
*/
private int $status = 0;
/**
* @ORM\Column(type="string", length=255, nullable=true)
*/
private ?string $totalHours = '';
/**
* @ORM\Column(type="integer", nullable=false, options={"default": 0})
*/
private int $maximumCapacity = 0;
/**
* @ORM\Column(type="datetime", nullable=true)
*/
private ?DateTimeInterface $endRegistrationPeriod;
/**
* @ORM\Column(type="boolean", nullable=false, options={"default": 1})
*/
private bool $active = true;
public function __construct()
{
$this->associatedUsers = new ArrayCollection();
$this->sessions = new ArrayCollection();
$this->registrations = new ArrayCollection();
}
public function getAssociatedUsersAmount(): int
{
return $this->getAssociatedUsers()->count();
}
public function getAssociatedUsers(): Collection
{
return $this->associatedUsers;
}
public function setAssociatedUsers(?Collection $associatedUsers): self
{
$this->associatedUsers = $associatedUsers;
return $this;
}
public function addAssociatedUser(User $associatedUser): self
{
if (!$this->associatedUsers->contains($associatedUser)) {
$this->associatedUsers->add($associatedUser);
}
return $this;
}
public function removeAssociatedUser(User $associatedUser): self
{
if ($this->associatedUsers->contains($associatedUser)) {
$this->associatedUsers->removeElement($associatedUser);
}
return $this;
}
public function getSessions(): Collection
{
return $this->sessions;
}
public function addSession(LearningCourseSession $session): self
{
if (!$this->getSessions()->contains($session)) {
$session->setCourse($this);
$this->sessions->add($session);
}
return $this;
}
public function removeSession(LearningCourseSession $session): self
{
if ($this->getSessions()->contains($session)) {
$this->sessions->removeElement($session);
}
return $this;
}
public function getSessionsAmount(): int
{
return $this->getSessions()->count();
}
public function getRegistrations(): Collection
{
return $this->registrations;
}
public function getRegistrationsAmount(): int
{
return $this->getRegistrations()->count();
}
public function addRegistration(LearningCourseRegistration $registration): self
{
if (!$this->getRegistrations()->contains($registration)) {
$registration->setCourse($this);
$this->getRegistrations()->add($registration);
}
return $this;
}
public function removeRegistration(LearningCourseRegistration $registration): self
{
if ($this->getRegistrations()->contains($registration)) {
$this->getRegistrations()->removeElement($registration);
}
return $this;
}
public function getCategory(): ?LearningCourseCategory
{
return $this->category;
}
public function getCategoryName(): string
{
return $this->getCategory() ? $this->getCategory()->getName() : MiniAbstractBase::DEFAULT_EMPTY_STRING;
}
public function setCategory(?LearningCourseCategory $category): self
{
$this->category = $category;
return $this;
}
public function getType(): int
{
return $this->type;
}
public function getTypeAsTranlationKeyString(): string
{
return LearningCourseTypeEnum::getTranslatedEnumArray()[$this->getType()];
}
public function setType(int $type): self
{
$this->type = $type;
return $this;
}
public function getStatus(): int
{
return $this->status;
}
public function setStatus(int $status): self
{
$this->status = $status;
return $this;
}
public function getTotalHours(): ?string
{
return $this->totalHours;
}
public function setTotalHours(?string $totalHours): self
{
$this->totalHours = $totalHours;
return $this;
}
public function getMaximumCapacity(): int
{
return $this->maximumCapacity;
}
public function getCurrentCapacity(): int
{
return $this->getRegistrationsAmount();
}
public function getAvailableRegistersAmount(): int
{
return $this->getMaximumCapacity() - $this->getRegistrationsAmount();
}
public function isFull(): bool
{
return $this->getAvailableRegistersAmount() <= 0;
}
public function setMaximumCapacity(int $maximumCapacity): self
{
$this->maximumCapacity = $maximumCapacity;
return $this;
}
public function getEndRegistrationPeriod(): ?DateTimeInterface
{
return $this->endRegistrationPeriod;
}
public function isEndRegistrationPeriodExpired(): bool
{
return $this->getEndRegistrationPeriod() && (new DateTimeImmutable())->format('Y/m/d') > $this->getEndRegistrationPeriod()->format('Y/m/d');
}
public function getEndRegistrationPeriodAsString(): string
{
return $this->getDateAsString($this->endRegistrationPeriod);
}
public function setEndRegistrationPeriod(?DateTimeInterface $endRegistrationPeriod): self
{
$this->endRegistrationPeriod = $endRegistrationPeriod;
return $this;
}
public function getCourseBeginDate(): ?DateTimeInterface
{
$firstDate = null;
if ($this->getSessionsAmount() > 0) {
/** @var LearningCourseSession $session */
foreach ($this->getSessions() as $session) {
if (is_null($firstDate)) {
$firstDate = $session->getDate();
} elseif ($firstDate->format(MiniAbstractBase::DEFAULT_DATE_DATABASE_FORMAT) > $session->getDate()->format(MiniAbstractBase::DEFAULT_DATE_DATABASE_FORMAT)) {
$firstDate = $session->getDate();
}
}
}
return $firstDate;
}
public function getCourseBeginDateAsString(): string
{
return $this->getDateAsString($this->getCourseBeginDate());
}
public function getCourseEndDate(): ?DateTimeInterface
{
$lastDate = null;
if ($this->getSessionsAmount() > 0) {
/** @var LearningCourseSession $session */
foreach ($this->getSessions() as $session) {
if (is_null($lastDate)) {
$lastDate = $session->getDate();
} elseif ($lastDate->format(MiniAbstractBase::DEFAULT_DATE_DATABASE_FORMAT) <= $session->getDate()->format(MiniAbstractBase::DEFAULT_DATE_DATABASE_FORMAT)) {
$lastDate = $session->getDate();
}
}
}
return $lastDate;
}
public function getCourseEndDateAsString(): string
{
return $this->getDateAsString($this->getCourseEndDate());
}
public function isExpired(): bool
{
return $this->getCourseEndDate() && (new DateTimeImmutable())->format('Y/m/d') > $this->getCourseEndDate()->format('Y/m/d');
}
}