src/Products/NotificationsBundle/Entity/AbstractNotification.php line 45

Open in your IDE?
  1. <?php
  2. namespace Products\NotificationsBundle\Entity;
  3. use App\Entity\Shared\FlagsTrait;
  4. use App\Entity\System\School;
  5. use App\Entity\System\SocialAccounts\FacebookSocialAccount;
  6. use App\Entity\System\SocialAccounts\InstagramSocialAccount;
  7. use App\Entity\System\SocialAccounts\TwitterSocialAccount;
  8. use App\Model\Async\StringSemaphoreInterface;
  9. use App\Model\Async\StringSemaphoreTrait;
  10. use App\Util\Locales;
  11. use Cms\ContainerBundle\Entity\Containers\GenericContainer;
  12. use Cms\CoreBundle\Model\Interfaces\Loggable\LoggableInterface;
  13. use Cms\TenantBundle\Entity\TenantedEntity;
  14. use DateTimeInterface;
  15. use Doctrine\Common\Collections\ArrayCollection;
  16. use Doctrine\Common\Collections\Collection;
  17. use Doctrine\Common\Collections\Criteria;
  18. use Doctrine\ORM\Mapping as ORM;
  19. use Products\NotificationsBundle\Entity\Notifications;
  20. use Reinder83\BinaryFlags\Bits;
  21. use Symfony\Component\Serializer\Annotation\Groups;
  22. /**
  23.  * Class AbstractNotification
  24.  * @package Products\NotificationsBundle\Entity
  25.  *
  26.  * @ORM\Entity(
  27.  *     repositoryClass = "Products\NotificationsBundle\Doctrine\Repository\AbstractNotificationRepository",
  28.  * )
  29.  * @ORM\InheritanceType("SINGLE_TABLE")
  30.  * @ORM\DiscriminatorColumn(
  31.  *     name = "discr",
  32.  *     type = "string",
  33.  * )
  34.  * @ORM\DiscriminatorMap({
  35.  *     Notifications\Message::DISCR = Notifications\Message::class,
  36.  *     Notifications\Invocation::DISCR = Notifications\Invocation::class,
  37.  * })
  38.  * @ORM\Table(
  39.  *     name = "notis__notification",
  40.  * )
  41.  */
  42. abstract class AbstractNotification extends TenantedEntity
  43.     implements
  44.         Notifications\NotificationInterface,
  45.         Notifications\Channels\TransactionalChannelsInterface,
  46.         Notifications\Channels\ServiceChannelsInterface,
  47.         Notifications\Translations\TranslatableInterface,
  48.         LoggableInterface,
  49.         StringSemaphoreInterface
  50. {
  51.     public const DISCRS = [
  52.         Notifications\Message::DISCR => Notifications\Message::class,
  53.         Notifications\Invocation::DISCR => Notifications\Invocation::class,
  54.     ];
  55.     public const DISCR null;
  56.     public const STATUSES = [
  57.         'draft' => self::STATUSES__DRAFT,
  58.         'ready' => self::STATUSES__READY,
  59.         'sending' => self::STATUSES__SENDING,
  60.         'complete' => self::STATUSES__COMPLETE,
  61.     ];
  62.     public const STATUSES__DRAFT 0;
  63.     public const STATUSES__READY Bits::BIT_1;
  64.     public const STATUSES__SENDING Bits::BIT_2;
  65.     public const STATUSES__COMPLETE Bits::BIT_3;
  66.     public const FLAGS = [
  67.         'modified_since_translation' => self::FLAGS__MODIFIED_SINCE_TRANSLATION,
  68.     ];
  69.     public const FLAGS__MODIFIED_SINCE_TRANSLATION Bits::BIT_1;
  70.     use Notifications\NotificationTrait;
  71.     use Notifications\Translations\TranslatableTrait;
  72.     use Notifications\Channels\TransactionalChannelsTrait;
  73.     use Notifications\Channels\ServiceChannelsTrait;
  74.     use FlagsTrait;
  75.     use StringSemaphoreTrait;
  76.     /**
  77.      * @var Collection|AbstractList[]|null
  78.      *
  79.      * @ORM\ManyToMany(
  80.      *     targetEntity = "Products\NotificationsBundle\Entity\AbstractList",
  81.      * )
  82.      * @ORM\JoinTable(
  83.      *     name = "notis__notification_x_list",
  84.      *     joinColumns = {
  85.      *         @ORM\JoinColumn(
  86.      *             name = "notification",
  87.      *             referencedColumnName = "id",
  88.      *             onDelete = "CASCADE",
  89.      *         ),
  90.      *     },
  91.      *     inverseJoinColumns = {
  92.      *         @ORM\JoinColumn(
  93.      *             name = "list",
  94.      *             referencedColumnName = "id",
  95.      *             onDelete = "CASCADE",
  96.      *         ),
  97.      *     },
  98.      * )
  99.      *
  100.      * @Groups("message_details")
  101.      */
  102.     protected ?Collection $lists null;
  103.     /**
  104.      * @var Collection|GenericContainer[]|null
  105.      *
  106.      * @ORM\ManyToMany(
  107.      *     targetEntity = "Cms\ContainerBundle\Entity\Containers\GenericContainer",
  108.      * )
  109.      * @ORM\JoinTable(
  110.      *     name = "notis__notification_x_department",
  111.      *     joinColumns = {
  112.      *         @ORM\JoinColumn(
  113.      *             name = "notification",
  114.      *             referencedColumnName = "id",
  115.      *             onDelete = "CASCADE",
  116.      *         ),
  117.      *     },
  118.      *     inverseJoinColumns = {
  119.      *         @ORM\JoinColumn(
  120.      *             name = "department",
  121.      *             referencedColumnName = "id",
  122.      *             onDelete = "CASCADE",
  123.      *         ),
  124.      *     },
  125.      * )
  126.      *
  127.      * @Groups({"message_details", "template_details"})
  128.      */
  129.     protected ?Collection $websiteDepartments null;
  130.     /**
  131.      * @var Collection|FacebookSocialAccount[]|null
  132.      *
  133.      * @ORM\ManyToMany(
  134.      *     targetEntity = "App\Entity\System\SocialAccounts\FacebookSocialAccount",
  135.      * )
  136.      * @ORM\JoinTable(
  137.      *     name = "notis__notification_x_facebook_social_account",
  138.      *     joinColumns = {
  139.      *         @ORM\JoinColumn(
  140.      *             name = "notification",
  141.      *             referencedColumnName = "id",
  142.      *             onDelete = "CASCADE",
  143.      *         ),
  144.      *     },
  145.      *     inverseJoinColumns = {
  146.      *         @ORM\JoinColumn(
  147.      *             name = "facebookSocialAccount",
  148.      *             referencedColumnName = "id",
  149.      *             onDelete = "CASCADE",
  150.      *         ),
  151.      *     },
  152.      * )
  153.      *
  154.      * @Groups({"message_details", "template_details"})
  155.      */
  156.     protected ?Collection $facebookSocialAccounts null;
  157.     /**
  158.      * @var Collection|InstagramSocialAccount[]|null
  159.      *
  160.      * @ORM\ManyToMany(
  161.      *     targetEntity = "App\Entity\System\SocialAccounts\InstagramSocialAccount",
  162.      * )
  163.      * @ORM\JoinTable(
  164.      *     name = "notis__notification_x_instagram_social_account",
  165.      *     joinColumns = {
  166.      *         @ORM\JoinColumn(
  167.      *             name = "notification",
  168.      *             referencedColumnName = "id",
  169.      *             onDelete = "CASCADE",
  170.      *         ),
  171.      *     },
  172.      *     inverseJoinColumns = {
  173.      *         @ORM\JoinColumn(
  174.      *             name = "instagramSocialAccount",
  175.      *             referencedColumnName = "id",
  176.      *             onDelete = "CASCADE",
  177.      *         ),
  178.      *     },
  179.      * )
  180.      *
  181.      * @Groups({"message_details", "template_details"})
  182.      */
  183.     protected ?Collection $instagramSocialAccounts null;
  184.     /**
  185.      * @var Collection|TwitterSocialAccount[]|null
  186.      *
  187.      * @ORM\ManyToMany(
  188.      *     targetEntity = "App\Entity\System\SocialAccounts\TwitterSocialAccount",
  189.      * )
  190.      * @ORM\JoinTable(
  191.      *     name = "notis__notification_x_twitter_social_account",
  192.      *     joinColumns = {
  193.      *         @ORM\JoinColumn(
  194.      *             name = "notification",
  195.      *             referencedColumnName = "id",
  196.      *             onDelete = "CASCADE",
  197.      *         ),
  198.      *     },
  199.      *     inverseJoinColumns = {
  200.      *         @ORM\JoinColumn(
  201.      *             name = "twitterSocialAccount",
  202.      *             referencedColumnName = "id",
  203.      *             onDelete = "CASCADE",
  204.      *         ),
  205.      *     },
  206.      * )
  207.      *
  208.      * @Groups({"message_details", "template_details"})
  209.      */
  210.     protected ?Collection $twitterSocialAccounts null;
  211.     /**
  212.      * @var bool
  213.      *
  214.      * @ORM\Column(
  215.      *     type = "boolean",
  216.      *     nullable = false,
  217.      *     options = {
  218.      *         "default" = false,
  219.      *     },
  220.      * )
  221.      */
  222.     protected bool $urgent false;
  223.     /**
  224.      * @var int|null
  225.      *
  226.      * @ORM\Column(
  227.      *     type = "bigint",
  228.      *     nullable = true,
  229.      *     options = {
  230.      *         "unsigned" = true,
  231.      *     },
  232.      * )
  233.      */
  234.     protected ?int $templateChannels;
  235.     /**
  236.      * @var int
  237.      *
  238.      * @ORM\Column(
  239.      *     type = "bigint",
  240.      *     nullable = false,
  241.      *     options = {
  242.      *         "default" = 0,
  243.      *     },
  244.      * )
  245.      *
  246.      * @Groups("message_details")
  247.      */
  248.     protected int $status 0;
  249.     /**
  250.      * @var array|string[]
  251.      *
  252.      * @ORM\Column(
  253.      *     type = "simple_array",
  254.      *     nullable = true,
  255.      * )
  256.      */
  257.     protected ?array $facades = [];
  258.     /**
  259.      * @var ArrayCollection|Job[]
  260.      *
  261.      * @ORM\OneToMany(
  262.      *     targetEntity = "Products\NotificationsBundle\Entity\Job",
  263.      *     mappedBy = "notification",
  264.      * )
  265.      * @ORM\OrderBy({
  266.      *     "createdAt" = "DESC",
  267.      * })
  268.      */
  269.     protected $jobs;
  270.     /**
  271.      * @var DateTimeInterface|null
  272.      *
  273.      * @ORM\Column(
  274.      *     type = "datetime",
  275.      *     nullable = true,
  276.      * )
  277.      *
  278.      * @Groups("message_details")
  279.      */
  280.     protected ?DateTimeInterface $scheduledAt null;
  281.     /**
  282.      * @var School|null
  283.      *
  284.      * @ORM\ManyToOne(
  285.      *     targetEntity = School::class,
  286.      * )
  287.      * @ORM\JoinColumn(
  288.      *     name = "branding",
  289.      *     referencedColumnName = "id",
  290.      *     nullable = true,
  291.      *     onDelete = "SET NULL",
  292.      * )
  293.      */
  294.     protected ?School $branding null;
  295.     /**
  296.      *
  297.      */
  298.     public function __construct()
  299.     {
  300.         $this->lists = new ArrayCollection();
  301.         $this->facebookSocialAccounts = new ArrayCollection();
  302.         $this->instagramSocialAccounts = new ArrayCollection();
  303.         $this->twitterSocialAccounts = new ArrayCollection();
  304.         $this->websiteDepartments = new ArrayCollection();
  305.         $this->jobs = new ArrayCollection();
  306.     }
  307.     /**
  308.      * @return DateTimeInterface|null
  309.      */
  310.     public function getScheduledAt(): ?DateTimeInterface
  311.     {
  312.         return $this->scheduledAt;
  313.     }
  314.     /**
  315.      * @param DateTimeInterface|null $scheduledAt
  316.      * @return $this
  317.      */
  318.     public function setScheduledAt(?DateTimeInterface $scheduledAt): self
  319.     {
  320.         $this->scheduledAt $scheduledAt;
  321.         return $this;
  322.     }
  323.     /**
  324.      * @return bool
  325.      */
  326.     public function isScheduled(): bool
  327.     {
  328.         return $this->isReady() && $this->getScheduledAt();
  329.     }
  330.     /**
  331.      * @return bool
  332.      */
  333.     public function isUrgent(): bool
  334.     {
  335.         return $this->urgent;
  336.     }
  337.     /**
  338.      * @param bool $urgent
  339.      * @return $this
  340.      */
  341.     public function setUrgent(bool $urgent): self
  342.     {
  343.         $this->urgent $urgent;
  344.         return $this;
  345.     }
  346.     /**
  347.      * @param int $starterChannels
  348.      * @return $this
  349.      */
  350.     public function setStarterChannels(int $starterChannels): self
  351.     {
  352.         $this->templateChannels $starterChannels;
  353.         return $this;
  354.     }
  355.     /**
  356.      * @return int
  357.      */
  358.     public function getStarterChannels(): int
  359.     {
  360.         return $this->templateChannels;
  361.     }
  362.     /**
  363.      * @param int $starterChannel
  364.      * @return bool
  365.      */
  366.     public function hasStarterChannel(int $starterChannel): bool
  367.     {
  368.         if (empty($this->getStarterChannels())) {
  369.             return true;
  370.         }
  371.         return (($this->getStarterChannels() & $starterChannel) === $starterChannel);
  372.     }
  373.     /**
  374.      * @return int
  375.      */
  376.     public function getStatus(): int
  377.     {
  378.         return $this->status;
  379.     }
  380.     /**
  381.      * @param int $status
  382.      * @return bool
  383.      */
  384.     public function isStatus(int $status): bool
  385.     {
  386.         if ($status === 0) {
  387.             return ($this->getStatus() === $status);
  388.         } else if ($status 0) {
  389.             if ($this->getStatus() < 0) {
  390.                 return false;
  391.             }
  392.             return (($this->getStatus() & $status) === $status);
  393.         } else {
  394.             if ($this->getStatus() > 0) {
  395.                 return false;
  396.             }
  397.             return ((~$this->getStatus() & ~$status) === ~$status);
  398.         }
  399.     }
  400.     /**
  401.      * @param int $status
  402.      * @return $this
  403.      */
  404.     public function setStatus(int $status): self
  405.     {
  406.         $this->status $status;
  407.         return $this;
  408.     }
  409.     /**
  410.      * @param string $locale
  411.      * @return Notifications\NotificationInterface
  412.      */
  413.     public function getNotification(string $locale Locales::RFC4646_DEFAULT): Notifications\NotificationInterface
  414.     {
  415.         return $this->getTranslation($locale) ?: $this;
  416.     }
  417.     /**
  418.      * @param Criteria|null $criteria
  419.      * @return Collection|Job[]
  420.      */
  421.     public function getJobs(?Criteria $criteria null): Collection
  422.     {
  423.         if ( ! $this->jobs instanceof Collection) {
  424.             $this->jobs = new ArrayCollection();
  425.         }
  426.         if ( ! empty($criteria)) {
  427.             return $this->jobs->matching($criteria);
  428.         }
  429.         return $this->jobs;
  430.     }
  431.     /**
  432.      * @return Job|null
  433.      */
  434.     public function getFirstJob(): ?Job
  435.     {
  436.         if ($this->jobs->count() > 0) {
  437.             return $this->jobs[0];
  438.         }
  439.         return null;
  440.     }
  441.     /**
  442.      * @return Job|null
  443.      */
  444.     public function getLastJob(): ?Job
  445.     {
  446.         if ($this->jobs->count() > 0) {
  447.             return $this->jobs[$this->jobs->count() - 1];
  448.         }
  449.         return null;
  450.     }
  451.     /**
  452.      * @return bool
  453.      */
  454.     public function isDraft(): bool
  455.     {
  456.         return $this->isStatus(self::STATUSES__DRAFT);
  457.     }
  458.     /**
  459.      * @return bool
  460.      */
  461.     public function isReady(): bool
  462.     {
  463.         return $this->isStatus(self::STATUSES__READY);
  464.     }
  465.     /**
  466.      * @return bool
  467.      */
  468.     public function isSending(): bool
  469.     {
  470.         return $this->isStatus(self::STATUSES__SENDING);
  471.     }
  472.     /**
  473.      * @return bool
  474.      */
  475.     public function isComplete(): bool
  476.     {
  477.         return $this->isStatus(self::STATUSES__COMPLETE);
  478.     }
  479.     /**
  480.      * @return bool
  481.      */
  482.     public function isError(): bool
  483.     {
  484.         if ( ! $this->isComplete()) {
  485.             return false;
  486.         }
  487.         if ( ! $this->getFirstJob()) {
  488.             return false;
  489.         }
  490.         return ($this->getFirstJob()->getErrorCount() > 0);
  491.     }
  492.     /**
  493.      * @return bool
  494.      */
  495.     public function isViewable(): bool
  496.     {
  497.         return $this->isSending() || $this->isComplete();
  498.     }
  499.     /**
  500.      * @return bool
  501.      */
  502.     public function supportsVoice(): bool
  503.     {
  504.         return $this->isUrgent();
  505.     }
  506.     /**
  507.      * @return bool
  508.      */
  509.     public function isPublic(): bool
  510.     {
  511.         return true;
  512.     }
  513.     /**
  514.      * {@inheritDoc}
  515.      */
  516.     public function getLoggableDetails(): array
  517.     {
  518.         return [
  519.             'id' => (string) $this->getId(),
  520.             'title' => $this->getTitle(),
  521.         ];
  522.     }
  523.     /**
  524.      * @return School|null
  525.      */
  526.     public function getBranding(): ?School
  527.     {
  528.         return $this->branding;
  529.     }
  530.     /**
  531.      * @param School|null $branding
  532.      * @return self
  533.      */
  534.     public function setBranding(?School $branding): self
  535.     {
  536.         $this->branding $branding;
  537.         return $this;
  538.     }
  539. }