<?php
namespace App\Entity;
use ApiPlatform\Core\Annotation\ApiResource;
use App\Repository\RestrictionRepository;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Validator\Constraints as Assert;
/**
* Restrictions are limitations in time to connection by users of the tvCompany
* Ex: a restriction with a code to "WEEKLY", a field to "saturday", and a value to "10:00 - 12:00", means that
* the users will not be allowed in between those hours
* Every date will be stored in a timestamp fashion
* @ORM\Entity(repositoryClass=RestrictionRepository::class)
* @ApiResource(
* normalizationContext={"groups"={"restriction:read"}},
* denormalizationContext={"groups"={"restriction:write"}}
* )
* @ORM\HasLifecycleCallbacks()
*/
class Restriction
{
/**
* With this code the will register the start and
* the value will register the end, but we will only take into
* account the day
*/
const WEEKLY = 'weekly';
/**
* With this code the will register the start and
* the value will register the end, but we will ignore the year who will
* be replaced by the current year
*/
const ANNUALLY = 'annually';
/**
* With this code the field will register the start and
* the value will register the end
*/
const PUNCTUAL = 'punctual';
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="string", length=255)
* @Groups({"restriction:read"})
*/
private $code;
/**
* @ORM\Column(type="string", length=255)
* @Groups({"restriction:read"})
*/
private $field;
/**
* @ORM\Column(type="text", nullable=true)
* @Groups({"restriction:read", "restriction:write"})
* @Assert\Regex("/^(\d{2}:\d{2}) - (\d{2}:\d{2})$/")
*/
private $value;
/**
* @ORM\Column(type="datetime", nullable=true)
* @Gedmo\Timestampable(on="create")
*/
private $createdAt;
/**
* @ORM\Column(type="datetime")
* @Gedmo\Timestampable(on="update")
*/
private $updatedAt;
/**
* @ORM\ManyToOne(targetEntity=TvCompany::class, inversedBy="restrictions")
* @ORM\JoinColumn(nullable=true)
* @Groups({"restriction:read", "restriction:write"})
*/
private $tvCompany;
/**
* @ORM\ManyToOne(targetEntity=Company::class, inversedBy="restrictions")
* @ORM\JoinColumn(nullable=true)
* @Assert\NotNull
* @Groups({"restriction:read", "restriction:write"})
*/
private $company;
/**
* Puts the yearly date to the present if necessary
* @param \DateTime $date
* @return \DateTime
*/
private function updateYearlyDate(\DateTime $date): \DateTime
{
return date_create_from_format('d-m H:i', $date->format("d-m H:i"));
}
/**
* Puts the weekly date to the present if necessary
* @param \DateTime $date
* @return \DateTime
*/
private function updateWeeklyDate(\DateTime $date): \DateTime
{
return date_create_from_format('l H:i', $date->format('l H:i'));
}
/**
* Gets the start of a restriction for a weekly value
* no error management is done in here be careful
* @param \DateTime $time
* @return \DateTime|false
*/
private function getWeeklyStart(\DateTime $time)
{
list($hour) = explode(' - ', $this->getValue());
return $this->innerWeeklyDate($time, $hour);
}
/**
* Gets the limit for the given hour
* @param \DateTime $time
* @param string $hour
* @return \DateTime|false
*/
private function innerWeeklyDate(\DateTime $time, string $hour)
{
$weekday = $this->getField();
$_time = clone $time;
if ($weekday === "everyday") {
$weekday = $_time->format('l');
}
$weekday = ucfirst($weekday);
if ($weekday != $_time->format('l')) {
$_time->add(date_interval_create_from_date_string("next $weekday"));
}
$hour = date_create_from_format('H:i', $hour);
return $_time->setTime(intval($hour->format('H')), intval($hour->format('i')), 0, 0);
}
/**
* Gets the start of a restriction for a weekly value
* no error management is done in here be careful
* @param \DateTime $time
* @return \DateTime|false
*/
private function getWeeklyEnd(\DateTime $time)
{
list($hour) = array_reverse(explode(' - ', $this->getValue()));
return $this->innerWeeklyDate($time, $hour);
}
/**
* @param \DateTime $time
* @return \DateTime
*/
public function getStart(\DateTime $time): \DateTime
{
$date = (new \DateTime());
switch ($this->code) {
case self::ANNUALLY:
$date = $time;
break;
case self::WEEKLY:
$date = $this->getWeeklyStart($time);
break;
case self::PUNCTUAL:
default:
break;
}
return $date;
}
/**
* @param \DateTime $time
* @return \DateTime
*/
public function getEnd(\DateTime $time): \DateTime
{
$date = (new \DateTime());
switch ($this->code) {
case self::ANNUALLY:
$date = $this->updateYearlyDate($date);
break;
case self::WEEKLY:
$date = $this->getWeeklyEnd($time);
break;
case self::PUNCTUAL:
default:
break;
}
return $date;
}
public function getId(): ?int
{
return $this->id;
}
public function getCode(): ?string
{
return $this->code;
}
public function setCode(string $code): self
{
$this->code = $code;
return $this;
}
public function getField(): ?string
{
return $this->field;
}
public function setField(string $field): self
{
$this->field = $field;
return $this;
}
public function getValue(): ?string
{
return $this->value;
}
public function setValue(?string $value): self
{
$this->value = $value;
return $this;
}
public function getCreatedAt(): ?\DateTimeInterface
{
return $this->createdAt;
}
public function setCreatedAt(\DateTimeInterface $createdAt): self
{
$this->createdAt = $createdAt;
return $this;
}
public function getUpdatedAt(): ?\DateTimeInterface
{
return $this->updatedAt;
}
public function setUpdatedAt(\DateTimeInterface $updatedAt): self
{
$this->updatedAt = $updatedAt;
return $this;
}
public function getTvCompany(): ?TvCompany
{
return $this->tvCompany;
}
public function setTvCompany(?TvCompany $tvCompany): self
{
$this->tvCompany = $tvCompany;
return $this;
}
public function getCompany(): ?Company
{
return $this->company;
}
public function setCompany(?Company $company): self
{
$this->company = $company;
return $this;
}
/**
* Retrieves if the restriction is applied or not
*
* @param \DateTime $time
* @return bool
*/
public function isRestricted(\DateTime $time): bool
{
return ($time > $this->getStart($time) && $time < $this->getEnd($time));
}
/**
* @Assert\IsTrue(message="The first hour must be inferior to the second one")
*/
public function isValueValid(): bool
{
$result = false;
list($start, $end) = explode(' - ', $this->value);
$start = str_replace(':', '', $start);
$end = str_replace(':', '', $end);
if (intval($start) < intval($end)) {
$result = true;
}
return $result;
}
}