app/Entity/Schema/ORM/QueueSchedule.php line 17

Open in your IDE?
  1. <?php
  2. namespace Sq\Entity\Schema\ORM;
  3. use Carbon\Carbon;
  4. use Doctrine\Common\Collections\ArrayCollection;
  5. use Doctrine\Common\Collections\Collection;
  6. use Doctrine\ORM\Mapping as ORM;
  7. use Sq\Entity\Enum\DayOfWeek;
  8. /**
  9.  * QueueSchedule.
  10.  */
  11. #[ORM\Entity(repositoryClass\Sq\Service\Repository\ORM\TimeslotRepository::class)]
  12. #[ORM\Table(name'queue_schedule')]
  13. #[ORM\Index(name'qs_qpc_id'columns: ['qs_qpc_id'])]
  14. class QueueSchedule implements BelongsToWorkspaceInterfaceOnboardingContentInterface
  15. {
  16.     use WorkspaceValidationTrait;
  17.     /**
  18.      * @var int
  19.      */
  20.     #[ORM\Column(name'qs_id'type'integer'nullablefalseoptions: ['unsigned' => true])]
  21.     #[ORM\Id]
  22.     #[ORM\GeneratedValue(strategy'IDENTITY')]
  23.     private $id;
  24.     /**
  25.      * @var PostCategory
  26.      */
  27.     #[ORM\ManyToOne(targetEntityPostCategory::class, fetch'EAGER'inversedBy'timeslots')]
  28.     #[ORM\JoinColumn(name'qs_qpc_id'referencedColumnName'qpc_id'nullablefalse)]
  29.     private $category;
  30.     /**
  31.      * @var string|null
  32.      */
  33.     #[ORM\Column(name'qs_local_days'type'string'length13nullabletrue)]
  34.     private $localDay;
  35.     /**
  36.      * @deprecated
  37.      *
  38.      * @var string
  39.      */
  40.     #[ORM\Column(name'qs_timezone'type'string'length42nullablefalseoptions: ['default' => 'Europe/London'])]
  41.     private $deprecatedTimezone 'Europe/London';
  42.     #[ORM\OneToOne(targetEntityQueueScheduleTime::class, mappedBy'queueSchedule'fetch'EAGER'cascade: ['persist''remove'])]
  43.     private $localTime;
  44.     #[ORM\ManyToMany(targetEntitySocialProfile::class)]
  45.     #[ORM\JoinTable(name'queue_schedule_account'joinColumns: [new ORM\JoinColumn(name'qsa_qs_id'referencedColumnName'qs_id')], inverseJoinColumns: [new ORM\JoinColumn(name'qsa_sn_id'referencedColumnName'sn_id')])]
  46.     private $profiles;
  47.     /**
  48.      *
  49.      * @var Workspace|null
  50.      */
  51.     #[ORM\ManyToOne(targetEntityWorkspace::class, inversedBy'timeslots')]
  52.     #[ORM\JoinColumn(name'qs_ws_id'referencedColumnName'ws_id'nullabletrue)]
  53.     private $workspace;
  54.     /**
  55.      * @var bool
  56.      */
  57.     #[ORM\Column(name'qs_onboarding_content'type'boolean'nullablefalse)]
  58.     protected $onboardingContent false;
  59.     public function __construct(
  60.         ?Workspace $workspace,
  61.         PostCategory $category,
  62.         int $localDay,
  63.         \DateTimeInterface $localTime,
  64.         array $socialProfiles,
  65.         bool $isOnboardingContent false,
  66.     ) {
  67.         if ($workspace !== null)
  68.         {
  69.             $this->validateSameWorkspace($workspace, [$category, ...$socialProfiles]);
  70.         }
  71.         $this->category $category;
  72.         $this->localDay $localDay;
  73.         $this->localTime = new QueueScheduleTime($this$localTime);
  74.         $this->profiles = new ArrayCollection($socialProfiles);
  75.         $this->workspace $workspace;
  76.         $this->onboardingContent $isOnboardingContent;
  77.     }
  78.     public function getId(): ?int
  79.     {
  80.         return $this->id;
  81.     }
  82.     public function getCategory(): PostCategory
  83.     {
  84.         return $this->category;
  85.     }
  86.     public function setCategory(PostCategory $category): self
  87.     {
  88.         if ($this->workspace !== null)
  89.         {
  90.             $this->validateSameWorkspace($this->workspace, [$category]);
  91.         }
  92.         $this->category $category;
  93.         return $this;
  94.     }
  95.     public function getLocalDayOfWeek(): DayOfWeek
  96.     {
  97.         $day = (int) $this->localDay;
  98.         $day === && $day 1;
  99.         return DayOfWeek::from($day);
  100.     }
  101.     public function setLocalDayOfWeek(DayOfWeek $dayOfWeek): self
  102.     {
  103.         $this->localDay $dayOfWeek->getValue();
  104.         return $this;
  105.     }
  106.     public function getLocalTime(): \DateTimeInterface
  107.     {
  108.         return $this->localTime->getLocalTime();
  109.     }
  110.     public function setLocalTime(\DateTimeInterface $time): self
  111.     {
  112.         $this->localTime->setLocalTime($time);
  113.         return $this;
  114.     }
  115.     /**
  116.      * @return Collection|SocialProfile[]
  117.      */
  118.     public function getSocialProfiles(): Collection
  119.     {
  120.         return $this->profiles->filter(function (SocialProfile $profile): bool
  121.         {
  122.             return !$profile->isDeleted();
  123.         });
  124.     }
  125.     public function addProfile(SocialProfile $profile): self
  126.     {
  127.         if (!$this->profiles->contains($profile))
  128.         {
  129.             if ($this->workspace !== null)
  130.             {
  131.                 $this->validateSameWorkspace($this->workspace, [$profile]);
  132.             }
  133.             $this->profiles->add($profile);
  134.         }
  135.         return $this;
  136.     }
  137.     public function removeProfile(SocialProfile $profile): self
  138.     {
  139.         if ($this->profiles->contains($profile))
  140.         {
  141.             $this->profiles->removeElement($profile);
  142.         }
  143.         return $this;
  144.     }
  145.     public function getWorkspace(): Workspace
  146.     {
  147.         return $this->workspace;
  148.     }
  149.     public function isLegacyWithoutWorkspace(): bool
  150.     {
  151.         return $this->workspace === null;
  152.     }
  153.     /**
  154.      * @param \DateTimeZone|string $timezone
  155.      * The Member or Workspace timezone.
  156.      *
  157.      * Can return null if a next posting date cannot be calculated.
  158.      * (e.g. a Timeslot exists on a day that a seasonal category doesn't include.)
  159.      * Note: This does not check if an entire queue or subqueue is paused, it only checks for seasonal category ranges.
  160.      */
  161.     public function calculateNextPublishingDateTime(\DateTimeZone|string $timezoneint $addWeeks 0): ?\DateTimeInterface
  162.     {
  163.         $localDayName $this->getLocalDayOfWeek()->getDayName();
  164.         $time $this->getLocalTime()->format("H:i:s");
  165.         $oneMinuteFromNow Carbon::now('UTC')->addMinute();
  166.         $nextPostingDay Carbon::createFromFormat("D H:i:s"$localDayName " " $time$timezone);
  167.         while ($nextPostingDay $oneMinuteFromNow)
  168.         {
  169.             $nextPostingDay->addWeek();
  170.         }
  171.         $nextPostingDay->addWeeks($addWeeks);
  172.         if ($this->category->isSeasonal())
  173.         {
  174.             $startDate $this->category->getStartDate();
  175.             $endDate $this->category->getEndDate();
  176.             $seasonalStart Carbon::createFromFormat("Y-m-d H:i:s"$startDate->format("Y-m-d") . "00:00:00"$timezone);
  177.             $seasonalEnd Carbon::createFromFormat("Y-m-d H:i:s"$endDate->format("Y-m-d") . "23:59:59"$timezone);
  178.             $years 0;
  179.             while (true)
  180.             {
  181.                 while ($nextPostingDay $seasonalStart)
  182.                 {
  183.                     // Keep adding weeks until the next posting day is after or equals the seasonal start.
  184.                     $nextPostingDay->addWeek();
  185.                 }
  186.                 if ($nextPostingDay <= $seasonalEnd)
  187.                 {
  188.                     // We know the next posting day is after the seasonal start, so if it's also less than the seasonal end,
  189.                     // we have a valid posting time.
  190.                     return $nextPostingDay;
  191.                 }
  192.                 // Since we couldn't find a valid posting time for this year, we add a year to the seasonal start/end and
  193.                 // try again. If we go past 11 years, return null as it's not possible to calculate a time.
  194.                 $seasonalStart->addYear();
  195.                 $seasonalEnd->addYear();
  196.                 $years++;
  197.                 if ($years 11)
  198.                 {
  199.                     // For some reason we couldn't find a calculated time, so this sub-queue will be un-queued.
  200.                     return null;
  201.                 }
  202.             }
  203.         }
  204.         return $nextPostingDay;
  205.     }
  206.     public function isOnboardingContent(): bool
  207.     {
  208.         return $this->onboardingContent;
  209.     }
  210. }