<?php
namespace Products\NotificationsBundle\Entity;
use App\Entity\Shared\FlagsTrait;
use App\Entity\System\School;
use App\Entity\System\SocialAccounts\FacebookSocialAccount;
use App\Entity\System\SocialAccounts\InstagramSocialAccount;
use App\Entity\System\SocialAccounts\TwitterSocialAccount;
use App\Model\Async\StringSemaphoreInterface;
use App\Model\Async\StringSemaphoreTrait;
use App\Util\Locales;
use Cms\ContainerBundle\Entity\Containers\GenericContainer;
use Cms\CoreBundle\Model\Interfaces\Loggable\LoggableInterface;
use Cms\TenantBundle\Entity\TenantedEntity;
use DateTimeInterface;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\Common\Collections\Criteria;
use Doctrine\ORM\Mapping as ORM;
use Products\NotificationsBundle\Entity\Notifications;
use Reinder83\BinaryFlags\Bits;
use Symfony\Component\Serializer\Annotation\Groups;
/**
* Class AbstractNotification
* @package Products\NotificationsBundle\Entity
*
* @ORM\Entity(
* repositoryClass = "Products\NotificationsBundle\Doctrine\Repository\AbstractNotificationRepository",
* )
* @ORM\InheritanceType("SINGLE_TABLE")
* @ORM\DiscriminatorColumn(
* name = "discr",
* type = "string",
* )
* @ORM\DiscriminatorMap({
* Notifications\Message::DISCR = Notifications\Message::class,
* Notifications\Invocation::DISCR = Notifications\Invocation::class,
* })
* @ORM\Table(
* name = "notis__notification",
* )
*/
abstract class AbstractNotification extends TenantedEntity
implements
Notifications\NotificationInterface,
Notifications\Channels\TransactionalChannelsInterface,
Notifications\Channels\ServiceChannelsInterface,
Notifications\Translations\TranslatableInterface,
LoggableInterface,
StringSemaphoreInterface
{
public const DISCRS = [
Notifications\Message::DISCR => Notifications\Message::class,
Notifications\Invocation::DISCR => Notifications\Invocation::class,
];
public const DISCR = null;
public const STATUSES = [
'draft' => self::STATUSES__DRAFT,
'ready' => self::STATUSES__READY,
'sending' => self::STATUSES__SENDING,
'complete' => self::STATUSES__COMPLETE,
];
public const STATUSES__DRAFT = 0;
public const STATUSES__READY = Bits::BIT_1;
public const STATUSES__SENDING = Bits::BIT_2;
public const STATUSES__COMPLETE = Bits::BIT_3;
public const FLAGS = [
'modified_since_translation' => self::FLAGS__MODIFIED_SINCE_TRANSLATION,
];
public const FLAGS__MODIFIED_SINCE_TRANSLATION = Bits::BIT_1;
use Notifications\NotificationTrait;
use Notifications\Translations\TranslatableTrait;
use Notifications\Channels\TransactionalChannelsTrait;
use Notifications\Channels\ServiceChannelsTrait;
use FlagsTrait;
use StringSemaphoreTrait;
/**
* @var Collection|AbstractList[]|null
*
* @ORM\ManyToMany(
* targetEntity = "Products\NotificationsBundle\Entity\AbstractList",
* )
* @ORM\JoinTable(
* name = "notis__notification_x_list",
* joinColumns = {
* @ORM\JoinColumn(
* name = "notification",
* referencedColumnName = "id",
* onDelete = "CASCADE",
* ),
* },
* inverseJoinColumns = {
* @ORM\JoinColumn(
* name = "list",
* referencedColumnName = "id",
* onDelete = "CASCADE",
* ),
* },
* )
*
* @Groups("message_details")
*/
protected ?Collection $lists = null;
/**
* @var Collection|GenericContainer[]|null
*
* @ORM\ManyToMany(
* targetEntity = "Cms\ContainerBundle\Entity\Containers\GenericContainer",
* )
* @ORM\JoinTable(
* name = "notis__notification_x_department",
* joinColumns = {
* @ORM\JoinColumn(
* name = "notification",
* referencedColumnName = "id",
* onDelete = "CASCADE",
* ),
* },
* inverseJoinColumns = {
* @ORM\JoinColumn(
* name = "department",
* referencedColumnName = "id",
* onDelete = "CASCADE",
* ),
* },
* )
*
* @Groups({"message_details", "template_details"})
*/
protected ?Collection $websiteDepartments = null;
/**
* @var Collection|FacebookSocialAccount[]|null
*
* @ORM\ManyToMany(
* targetEntity = "App\Entity\System\SocialAccounts\FacebookSocialAccount",
* )
* @ORM\JoinTable(
* name = "notis__notification_x_facebook_social_account",
* joinColumns = {
* @ORM\JoinColumn(
* name = "notification",
* referencedColumnName = "id",
* onDelete = "CASCADE",
* ),
* },
* inverseJoinColumns = {
* @ORM\JoinColumn(
* name = "facebookSocialAccount",
* referencedColumnName = "id",
* onDelete = "CASCADE",
* ),
* },
* )
*
* @Groups({"message_details", "template_details"})
*/
protected ?Collection $facebookSocialAccounts = null;
/**
* @var Collection|InstagramSocialAccount[]|null
*
* @ORM\ManyToMany(
* targetEntity = "App\Entity\System\SocialAccounts\InstagramSocialAccount",
* )
* @ORM\JoinTable(
* name = "notis__notification_x_instagram_social_account",
* joinColumns = {
* @ORM\JoinColumn(
* name = "notification",
* referencedColumnName = "id",
* onDelete = "CASCADE",
* ),
* },
* inverseJoinColumns = {
* @ORM\JoinColumn(
* name = "instagramSocialAccount",
* referencedColumnName = "id",
* onDelete = "CASCADE",
* ),
* },
* )
*
* @Groups({"message_details", "template_details"})
*/
protected ?Collection $instagramSocialAccounts = null;
/**
* @var Collection|TwitterSocialAccount[]|null
*
* @ORM\ManyToMany(
* targetEntity = "App\Entity\System\SocialAccounts\TwitterSocialAccount",
* )
* @ORM\JoinTable(
* name = "notis__notification_x_twitter_social_account",
* joinColumns = {
* @ORM\JoinColumn(
* name = "notification",
* referencedColumnName = "id",
* onDelete = "CASCADE",
* ),
* },
* inverseJoinColumns = {
* @ORM\JoinColumn(
* name = "twitterSocialAccount",
* referencedColumnName = "id",
* onDelete = "CASCADE",
* ),
* },
* )
*
* @Groups({"message_details", "template_details"})
*/
protected ?Collection $twitterSocialAccounts = null;
/**
* @var bool
*
* @ORM\Column(
* type = "boolean",
* nullable = false,
* options = {
* "default" = false,
* },
* )
*/
protected bool $urgent = false;
/**
* @var int|null
*
* @ORM\Column(
* type = "bigint",
* nullable = true,
* options = {
* "unsigned" = true,
* },
* )
*/
protected ?int $templateChannels;
/**
* @var int
*
* @ORM\Column(
* type = "bigint",
* nullable = false,
* options = {
* "default" = 0,
* },
* )
*
* @Groups("message_details")
*/
protected int $status = 0;
/**
* @var array|string[]
*
* @ORM\Column(
* type = "simple_array",
* nullable = true,
* )
*/
protected ?array $facades = [];
/**
* @var ArrayCollection|Job[]
*
* @ORM\OneToMany(
* targetEntity = "Products\NotificationsBundle\Entity\Job",
* mappedBy = "notification",
* )
* @ORM\OrderBy({
* "createdAt" = "DESC",
* })
*/
protected $jobs;
/**
* @var DateTimeInterface|null
*
* @ORM\Column(
* type = "datetime",
* nullable = true,
* )
*
* @Groups("message_details")
*/
protected ?DateTimeInterface $scheduledAt = null;
/**
* @var School|null
*
* @ORM\ManyToOne(
* targetEntity = School::class,
* )
* @ORM\JoinColumn(
* name = "branding",
* referencedColumnName = "id",
* nullable = true,
* onDelete = "SET NULL",
* )
*/
protected ?School $branding = null;
/**
*
*/
public function __construct()
{
$this->lists = new ArrayCollection();
$this->facebookSocialAccounts = new ArrayCollection();
$this->instagramSocialAccounts = new ArrayCollection();
$this->twitterSocialAccounts = new ArrayCollection();
$this->websiteDepartments = new ArrayCollection();
$this->jobs = new ArrayCollection();
}
/**
* @return DateTimeInterface|null
*/
public function getScheduledAt(): ?DateTimeInterface
{
return $this->scheduledAt;
}
/**
* @param DateTimeInterface|null $scheduledAt
* @return $this
*/
public function setScheduledAt(?DateTimeInterface $scheduledAt): self
{
$this->scheduledAt = $scheduledAt;
return $this;
}
/**
* @return bool
*/
public function isScheduled(): bool
{
return $this->isReady() && $this->getScheduledAt();
}
/**
* @return bool
*/
public function isUrgent(): bool
{
return $this->urgent;
}
/**
* @param bool $urgent
* @return $this
*/
public function setUrgent(bool $urgent): self
{
$this->urgent = $urgent;
return $this;
}
/**
* @param int $starterChannels
* @return $this
*/
public function setStarterChannels(int $starterChannels): self
{
$this->templateChannels = $starterChannels;
return $this;
}
/**
* @return int
*/
public function getStarterChannels(): int
{
return $this->templateChannels;
}
/**
* @param int $starterChannel
* @return bool
*/
public function hasStarterChannel(int $starterChannel): bool
{
if (empty($this->getStarterChannels())) {
return true;
}
return (($this->getStarterChannels() & $starterChannel) === $starterChannel);
}
/**
* @return int
*/
public function getStatus(): int
{
return $this->status;
}
/**
* @param int $status
* @return bool
*/
public function isStatus(int $status): bool
{
if ($status === 0) {
return ($this->getStatus() === $status);
} else if ($status > 0) {
if ($this->getStatus() < 0) {
return false;
}
return (($this->getStatus() & $status) === $status);
} else {
if ($this->getStatus() > 0) {
return false;
}
return ((~$this->getStatus() & ~$status) === ~$status);
}
}
/**
* @param int $status
* @return $this
*/
public function setStatus(int $status): self
{
$this->status = $status;
return $this;
}
/**
* @param string $locale
* @return Notifications\NotificationInterface
*/
public function getNotification(string $locale = Locales::RFC4646_DEFAULT): Notifications\NotificationInterface
{
return $this->getTranslation($locale) ?: $this;
}
/**
* @param Criteria|null $criteria
* @return Collection|Job[]
*/
public function getJobs(?Criteria $criteria = null): Collection
{
if ( ! $this->jobs instanceof Collection) {
$this->jobs = new ArrayCollection();
}
if ( ! empty($criteria)) {
return $this->jobs->matching($criteria);
}
return $this->jobs;
}
/**
* @return Job|null
*/
public function getFirstJob(): ?Job
{
if ($this->jobs->count() > 0) {
return $this->jobs[0];
}
return null;
}
/**
* @return Job|null
*/
public function getLastJob(): ?Job
{
if ($this->jobs->count() > 0) {
return $this->jobs[$this->jobs->count() - 1];
}
return null;
}
/**
* @return bool
*/
public function isDraft(): bool
{
return $this->isStatus(self::STATUSES__DRAFT);
}
/**
* @return bool
*/
public function isReady(): bool
{
return $this->isStatus(self::STATUSES__READY);
}
/**
* @return bool
*/
public function isSending(): bool
{
return $this->isStatus(self::STATUSES__SENDING);
}
/**
* @return bool
*/
public function isComplete(): bool
{
return $this->isStatus(self::STATUSES__COMPLETE);
}
/**
* @return bool
*/
public function isError(): bool
{
if ( ! $this->isComplete()) {
return false;
}
if ( ! $this->getFirstJob()) {
return false;
}
return ($this->getFirstJob()->getErrorCount() > 0);
}
/**
* @return bool
*/
public function isViewable(): bool
{
return $this->isSending() || $this->isComplete();
}
/**
* @return bool
*/
public function supportsVoice(): bool
{
return $this->isUrgent();
}
/**
* @return bool
*/
public function isPublic(): bool
{
return true;
}
/**
* {@inheritDoc}
*/
public function getLoggableDetails(): array
{
return [
'id' => (string) $this->getId(),
'title' => $this->getTitle(),
];
}
/**
* @return School|null
*/
public function getBranding(): ?School
{
return $this->branding;
}
/**
* @param School|null $branding
* @return self
*/
public function setBranding(?School $branding): self
{
$this->branding = $branding;
return $this;
}
}