]> Raphaël G. Git Repositories - airbundle/blobdiff - Entity/Session.php
Rename rapsysair:calendar2 command to rapsysair:calendar
[airbundle] / Entity / Session.php
index e2ffc7afd72584d5cfdac4a6534dbd796bd7a72d..f74963cdb338dd2914d7c9fc189e2733abb12761 100644 (file)
-<?php
+<?php declare(strict_types=1);
+
+/*
+ * This file is part of the Rapsys AirBundle package.
+ *
+ * (c) Raphaël Gertz <symfony@rapsys.eu>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
 
 namespace Rapsys\AirBundle\Entity;
 
+use Doctrine\Common\Collections\Collection;
+use Doctrine\Common\Collections\ArrayCollection;
+use Doctrine\ORM\Event\PreUpdateEventArgs;
+
+use Rapsys\PackBundle\Util\IntlUtil;
+
 /**
  * Session
  */
 class Session {
        /**
-        * @var integer
-        */
-       private $id;
-
-       /**
-        * @var \DateTime
-        */
-       private $date;
-
-       /**
-        * @var \DateTime
+        * Primary key
         */
-       private $begin;
+       private ?int $id = null;
 
        /**
-        * @var \DateTime
+        * Begin time
         */
-       private $start = null;
+       private ?\DateTime $begin = null;
 
        /**
-        * @var \DateTime
+        * Computed start datetime
         */
-       private $length;
+       private ?\DateTime $start = null;
 
        /**
-        * @var \DateTime
+        * Length time
         */
-       private $stop = null;
+       private ?\DateTime $length = null;
 
        /**
-        * @var boolean
+        * Computed stop datetime
         */
-       private $premium;
+       private ?\DateTime $stop = null;
 
        /**
-        * @var float
+        * Premium
         */
-       private $rainfall;
+       private ?bool $premium = null;
 
        /**
-        * @var float
+        * Rain mm
         */
-       private $rainrisk;
+       private ?float $rainfall = null;
 
        /**
-        * @var float
+        * Rain chance
         */
-       private $realfeel;
+       private ?float $rainrisk = null;
 
        /**
-        * @var float
+        * Real feel temperature
         */
-       private $realfeelmin;
+       private ?float $realfeel = null;
 
        /**
-        * @var float
+        * Real feel minimum temperature
         */
-       private $realfeelmax;
+       private ?float $realfeelmin = null;
 
        /**
-        * @var integer
+        * Real feel maximum temperature
         */
-       private $temperature;
+       private ?float $realfeelmax = null;
 
        /**
-        * @var integer
+        * Temperature
         */
-       private $temperaturemin;
+       private ?float $temperature = null;
 
        /**
-        * @var integer
+        * Minimum temperature
         */
-       private $temperaturemax;
+       private ?float $temperaturemin = null;
 
        /**
-        * @var \DateTime
+        * Maximum temperature
         */
-       private $created;
+       private ?float $temperaturemax = null;
 
        /**
-        * @var \DateTime
+        * Lock datetime
         */
-       private $updated;
+       private ?\DateTime $locked = null;
 
        /**
-        * @var \Rapsys\AirBundle\Entity\Application
+        * Create datetime
         */
-       private $application;
+       private \DateTime $created;
 
        /**
-        * @var \Rapsys\AirBundle\Entity\Location
+        * Update datetime
         */
-       private $location;
+       private \DateTime $updated;
 
        /**
-        * @var \Rapsys\AirBundle\Entity\Slot
+        * Application instance
         */
-       private $slot;
+       private ?Application $application = null;
 
        /**
-        * @var \Doctrine\Common\Collections\Collection
+        * Applications collection
         */
-       private $applications;
+       private Collection $applications;
 
        /**
         * Constructor
         */
-       public function __construct() {
-               $this->applications = new \Doctrine\Common\Collections\ArrayCollection();
+       public function __construct(private \DateTime $date, private Location $location, private Slot $slot) {
+               //Set defaults
+               $this->created = new \DateTime('now');
+               $this->updated = new \DateTime('now');
+
+               //Set collections
+               $this->applications = new ArrayCollection();
        }
 
        /**
@@ -123,7 +133,7 @@ class Session {
         *
         * @return integer
         */
-       public function getId() {
+       public function getId(): ?int {
                return $this->id;
        }
 
@@ -134,7 +144,7 @@ class Session {
         *
         * @return Session
         */
-       public function setDate($date) {
+       public function setDate(\DateTime $date): Session {
                $this->date = $date;
 
                return $this;
@@ -145,7 +155,7 @@ class Session {
         *
         * @return \DateTime
         */
-       public function getDate() {
+       public function getDate(): \DateTime {
                return $this->date;
        }
 
@@ -156,7 +166,7 @@ class Session {
         *
         * @return Session
         */
-       public function setBegin($begin) {
+       public function setBegin(?\DateTime $begin): Session {
                $this->begin = $begin;
 
                return $this;
@@ -167,7 +177,7 @@ class Session {
         *
         * @return \DateTime
         */
-       public function getBegin() {
+       public function getBegin(): ?\DateTime {
                return $this->begin;
        }
 
@@ -176,8 +186,8 @@ class Session {
         *
         * @return \DateTime
         */
-       public function getStart() {
-               //Check start
+       public function getStart(): \DateTime {
+               //With start
                if ($this->start !== null) {
                        return $this->start;
                }
@@ -186,13 +196,20 @@ class Session {
                $this->start = clone $this->date;
 
                //Check if after slot
-               if ($this->slot->getTitle() == 'After') {
+               //XXX: id=4 <=> title=After
+               if ($this->slot->getId() == 4) {
                        //Add one day
                        $this->start->add(new \DateInterval('P1D'));
                }
 
-               //Return date
-               return $this->start->setTime($this->begin->format('H'), $this->begin->format('i'), $this->begin->format('s'));
+               //With begin
+               if ($this->begin !== null) {
+                       //Set start time
+                       $this->start->setTime(intval($this->begin->format('H')), intval($this->begin->format('i')), intval($this->begin->format('s')));
+               }
+
+               //Return start
+               return $this->start;
        }
 
        /**
@@ -202,7 +219,7 @@ class Session {
         *
         * @return Session
         */
-       public function setLength($length) {
+       public function setLength(?\DateTime $length): Session {
                $this->length = $length;
 
                return $this;
@@ -213,7 +230,7 @@ class Session {
         *
         * @return \DateTime
         */
-       public function getLength() {
+       public function getLength(): ?\DateTime {
                return $this->length;
        }
 
@@ -222,7 +239,7 @@ class Session {
         *
         * @return \DateTime
         */
-       public function getStop() {
+       public function getStop(): \DateTime {
                //Check start
                if ($this->stop !== null) {
                        return $this->stop;
@@ -231,18 +248,24 @@ class Session {
                //Get start clone
                $this->stop = clone $this->getStart();
 
+               //With length
+               if ($this->length !== null) {
+                       //Set stop time
+                       $this->stop->add(new \DateInterval('PT'.$this->length->format('H').'H'.$this->length->format('i').'M'.$this->length->format('s').'S'));
+               }
+
                //Return date
-               return $this->stop->add(new \DateInterval('PT'.$this->length->format('H').'H'.$this->length->format('i').'M'.$this->length->format('s').'S'));
+               return $this->stop;
        }
 
        /**
         * Set premium
         *
-        * @param boolean $premium
+        * @param bool $premium
         *
         * @return Session
         */
-       public function setPremium($premium) {
+       public function setPremium(?bool $premium): Session {
                $this->premium = $premium;
 
                return $this;
@@ -251,20 +274,20 @@ class Session {
        /**
         * Get premium
         *
-        * @return boolean
+        * @return bool
         */
-       public function getPremium() {
+       public function getPremium(): ?bool {
                return $this->premium;
        }
 
        /**
         * Set rainfall
         *
-        * @param boolean $rainfall
+        * @param float $rainfall
         *
         * @return Session
         */
-       public function setRainfall($rainfall) {
+       public function setRainfall(?float $rainfall): Session {
                $this->rainfall = $rainfall;
 
                return $this;
@@ -273,20 +296,20 @@ class Session {
        /**
         * Get rainfall
         *
-        * @return boolean
+        * @return float
         */
-       public function getRainfall() {
+       public function getRainfall(): ?float {
                return $this->rainfall;
        }
 
        /**
         * Set rainrisk
         *
-        * @param boolean $rainrisk
+        * @param float $rainrisk
         *
         * @return Session
         */
-       public function setRainrisk($rainrisk) {
+       public function setRainrisk(?float $rainrisk): Session {
                $this->rainrisk = $rainrisk;
 
                return $this;
@@ -295,20 +318,20 @@ class Session {
        /**
         * Get rainrisk
         *
-        * @return boolean
+        * @return float
         */
-       public function getRainrisk() {
+       public function getRainrisk(): ?float {
                return $this->rainrisk;
        }
 
        /**
         * Set realfeel
         *
-        * @param integer $realfeel
+        * @param float $realfeel
         *
         * @return Session
         */
-       public function setRealfeel($realfeel) {
+       public function setRealfeel(?float $realfeel): Session {
                $this->realfeel = $realfeel;
 
                return $this;
@@ -317,20 +340,20 @@ class Session {
        /**
         * Get realfeel
         *
-        * @return integer
+        * @return float
         */
-       public function getRealfeel() {
+       public function getRealfeel(): ?float {
                return $this->realfeel;
        }
 
        /**
         * Set realfeelmin
         *
-        * @param integer $realfeelmin
+        * @param float $realfeelmin
         *
         * @return Session
         */
-       public function setRealfeelmin($realfeelmin) {
+       public function setRealfeelmin(?float $realfeelmin): Session {
                $this->realfeelmin = $realfeelmin;
 
                return $this;
@@ -339,20 +362,20 @@ class Session {
        /**
         * Get realfeelmin
         *
-        * @return integer
+        * @return float
         */
-       public function getRealfeelmin() {
+       public function getRealfeelmin(): ?float {
                return $this->realfeelmin;
        }
 
        /**
         * Set realfeelmax
         *
-        * @param integer $realfeelmax
+        * @param float $realfeelmax
         *
         * @return Session
         */
-       public function setRealfeelmax($realfeelmax) {
+       public function setRealfeelmax(?float $realfeelmax): Session {
                $this->realfeelmax = $realfeelmax;
 
                return $this;
@@ -361,20 +384,20 @@ class Session {
        /**
         * Get realfeelmax
         *
-        * @return integer
+        * @return float
         */
-       public function getRealfeelmax() {
+       public function getRealfeelmax(): ?float {
                return $this->realfeelmax;
        }
 
        /**
         * Set temperature
         *
-        * @param integer $temperature
+        * @param float $temperature
         *
         * @return Session
         */
-       public function setTemperature($temperature) {
+       public function setTemperature(?float $temperature): Session {
                $this->temperature = $temperature;
 
                return $this;
@@ -383,20 +406,20 @@ class Session {
        /**
         * Get temperature
         *
-        * @return integer
+        * @return float
         */
-       public function getTemperature() {
+       public function getTemperature(): ?float {
                return $this->temperature;
        }
 
        /**
         * Set temperaturemin
         *
-        * @param integer $temperaturemin
+        * @param float $temperaturemin
         *
         * @return Session
         */
-       public function setTemperaturemin($temperaturemin) {
+       public function setTemperaturemin(?float $temperaturemin): Session {
                $this->temperaturemin = $temperaturemin;
 
                return $this;
@@ -405,20 +428,20 @@ class Session {
        /**
         * Get temperaturemin
         *
-        * @return integer
+        * @return float
         */
-       public function getTemperaturemin() {
+       public function getTemperaturemin(): ?float {
                return $this->temperaturemin;
        }
 
        /**
         * Set temperaturemax
         *
-        * @param integer $temperaturemax
+        * @param float $temperaturemax
         *
         * @return Session
         */
-       public function setTemperaturemax($temperaturemax) {
+       public function setTemperaturemax(?float $temperaturemax): Session {
                $this->temperaturemax = $temperaturemax;
 
                return $this;
@@ -427,12 +450,34 @@ class Session {
        /**
         * Get temperaturemax
         *
-        * @return integer
+        * @return float
         */
-       public function getTemperaturemax() {
+       public function getTemperaturemax(): ?float {
                return $this->temperaturemax;
        }
 
+       /**
+        * Set locked
+        *
+        * @param \DateTime $locked
+        *
+        * @return Session
+        */
+       public function setLocked(?\DateTime $locked): Session {
+               $this->locked = $locked;
+
+               return $this;
+       }
+
+       /**
+        * Get locked
+        *
+        * @return \DateTime
+        */
+       public function getLocked(): ?\DateTime {
+               return $this->locked;
+       }
+
        /**
         * Set created
         *
@@ -440,7 +485,7 @@ class Session {
         *
         * @return Session
         */
-       public function setCreated($created) {
+       public function setCreated(\DateTime $created): Session {
                $this->created = $created;
 
                return $this;
@@ -451,7 +496,7 @@ class Session {
         *
         * @return \DateTime
         */
-       public function getCreated() {
+       public function getCreated(): \DateTime {
                return $this->created;
        }
 
@@ -462,7 +507,7 @@ class Session {
         *
         * @return Session
         */
-       public function setUpdated($updated) {
+       public function setUpdated(\DateTime $updated): Session {
                $this->updated = $updated;
 
                return $this;
@@ -473,18 +518,18 @@ class Session {
         *
         * @return \DateTime
         */
-       public function getUpdated() {
+       public function getUpdated(): \DateTime {
                return $this->updated;
        }
 
        /**
         * Add application
         *
-        * @param \Rapsys\AirBundle\Entity\Application $application
+        * @param Application $application
         *
         * @return Session
         */
-       public function addApplication(\Rapsys\AirBundle\Entity\Application $application) {
+       public function addApplication(Application $application): Session {
                $this->applications[] = $application;
 
                return $this;
@@ -493,29 +538,29 @@ class Session {
        /**
         * Remove application
         *
-        * @param \Rapsys\AirBundle\Entity\Application $application
+        * @param Application $application
         */
-       public function removeApplication(\Rapsys\AirBundle\Entity\Application $application) {
-               $this->applications->removeElement($application);
+       public function removeApplication(Application $application): bool {
+               return $this->applications->removeElement($application);
        }
 
        /**
         * Get applications
         *
-        * @return \Doctrine\Common\Collections\Collection
+        * @return ArrayCollection
         */
-       public function getApplications() {
+       public function getApplications(): ArrayCollection {
                return $this->applications;
        }
 
        /**
         * Set location
         *
-        * @param \Rapsys\AirBundle\Entity\Location $location
+        * @param Location $location
         *
         * @return Session
         */
-       public function setLocation(\Rapsys\AirBundle\Entity\Location $location = null) {
+       public function setLocation(Location $location): Session {
                $this->location = $location;
 
                return $this;
@@ -524,20 +569,20 @@ class Session {
        /**
         * Get location
         *
-        * @return \Rapsys\AirBundle\Entity\Location
+        * @return Location
         */
-       public function getLocation() {
+       public function getLocation(): Location {
                return $this->location;
        }
 
        /**
         * Set slot
         *
-        * @param \Rapsys\AirBundle\Entity\Slot $slot
+        * @param Slot $slot
         *
         * @return Session
         */
-       public function setSlot(\Rapsys\AirBundle\Entity\Slot $slot = null) {
+       public function setSlot(Slot $slot): Session {
                $this->slot = $slot;
 
                return $this;
@@ -546,20 +591,20 @@ class Session {
        /**
         * Get slot
         *
-        * @return \Rapsys\AirBundle\Entity\Slot
+        * @return Slot
         */
-       public function getSlot() {
+       public function getSlot(): Slot {
                return $this->slot;
        }
 
        /**
         * Set application
         *
-        * @param \Rapsys\AirBundle\Entity\Application $application
+        * @param Application $application
         *
         * @return Session
         */
-       public function setApplication(\Rapsys\AirBundle\Entity\Application $application = null) {
+       public function setApplication(?Application $application): Session {
                $this->application = $application;
 
                return $this;
@@ -568,9 +613,126 @@ class Session {
        /**
         * Get application
         *
-        * @return \Rapsys\AirBundle\Entity\Application
+        * @return Application
         */
-       public function getApplication() {
+       public function getApplication(): ?Application {
                return $this->application;
        }
+
+       /**
+        * {@inheritdoc}
+        */
+       public function preUpdate(PreUpdateEventArgs $eventArgs) {
+               //Check that we have a session instance
+               if (($session = $eventArgs->getObject()) instanceof Session) {
+                       //Set updated value
+                       $session->setUpdated(new \DateTime('now'));
+               }
+       }
+
+       /**
+        * Wether if session is a premium day
+        *
+        * Consider as premium a day off for afternoon, the eve for evening and after
+        * Store computed result in premium member for afternoon and evening
+        *
+        * @TODO improve by moving day off computation in IntlUtil or HolidayUtil class ?
+        *
+        * @return bool Whether the date is day off or not
+        */
+       public function isPremium(): bool {
+               //Without date
+               if (empty($date = $this->date)) {
+                       throw new \LogicException('Property date is empty');
+               }
+
+               //Without slot
+               if (empty($slot = $this->slot) || empty($slotTitle = $slot->getTitle())) {
+                       throw new \LogicException('Property slot is empty');
+               }
+
+               //With evening and after slot
+               if ($slotTitle == 'Evening' || $slotTitle == 'After') {
+                       //Evening and after session is considered premium when the eve is a day off
+                       $date = (clone $date)->add(new \DateInterval('P1D'));
+               }
+
+               //Get day number
+               $w = $date->format('w');
+
+               //Check if weekend day
+               if ($w == 0 || $w == 6) {
+                       //With afternoon and evening slot
+                       if ($slotTitle == 'Afternoon' || $slotTitle == 'Evening') {
+                               //Save premium
+                               $this->premium = true;
+                       }
+
+                       //Date is weekend day
+                       return true;
+               }
+
+               //Get date day
+               $d = $date->format('d');
+
+               //Get date month
+               $m = $date->format('m');
+
+               //Check if fixed holiday
+               if (
+                       //Check if 1st january
+                       ($d == 1 && $m == 1) ||
+                       //Check if 1st may
+                       ($d == 1 && $m == 5) ||
+                       //Check if 8st may
+                       ($d == 8 && $m == 5) ||
+                       //Check if 14st july
+                       ($d == 14 && $m == 7) ||
+                       //Check if 15st august
+                       ($d == 15 && $m == 8) ||
+                       //Check if 1st november
+                       ($d == 1 && $m == 11) ||
+                       //Check if 11st november
+                       ($d == 11 && $m == 11) ||
+                       //Check if 25st december
+                       ($d == 25 && $m == 12)
+               ) {
+                       //With afternoon and evening slot
+                       if ($slotTitle == 'Afternoon' || $slotTitle == 'Evening') {
+                               //Save premium
+                               $this->premium = true;
+                       }
+
+                       //Date is a fixed holiday
+                       return true;
+               }
+
+               //Get eastern
+               $eastern = (new IntlUtil())->getEastern($date->format('Y'));
+
+               //Check dynamic holidays
+               if (
+                       (clone $eastern)->add(new \DateInterval('P1D')) == $date ||
+                       (clone $eastern)->add(new \DateInterval('P39D')) == $date ||
+                       (clone $eastern)->add(new \DateInterval('P50D')) == $date
+               ) {
+                       //With afternoon and evening slot
+                       if ($slotTitle == 'Afternoon' || $slotTitle == 'Evening') {
+                               //Save premium
+                               $this->premium = true;
+                       }
+
+                       //Date is a dynamic holiday
+                       return true;
+               }
+
+               //With afternoon and evening slot
+               if ($slotTitle == 'Afternoon' || $slotTitle == 'Evening') {
+                       //Save premium
+                       $this->premium = false;
+               }
+
+               //Date is not a holiday and week day
+               return false;
+       }
 }