<?php
namespace Products\NotificationsBundle\Entity;
use Cms\TenantBundle\Entity\TenantedEntity;
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\Recipients;
use Products\NotificationsBundle\Model\Contacts\ContactInterface;
use Products\NotificationsBundle\Util\ReachabilityTrait;
use Symfony\Component\Validator\Constraints;
/**
* Class AbstractRecipient
*
* @package Products\NotificationsBundle\Entity
*
* @ORM\Entity(
* repositoryClass = "Products\NotificationsBundle\Doctrine\Repository\RecipientRepository",
* )
* @ORM\InheritanceType("SINGLE_TABLE")
* @ORM\DiscriminatorColumn(
* name = "discr",
* type = "string",
* )
* @ORM\DiscriminatorMap({
* Recipients\EmailRecipient::DISCR = "Products\NotificationsBundle\Entity\Recipients\EmailRecipient",
* Recipients\PhoneRecipient::DISCR = "Products\NotificationsBundle\Entity\Recipients\PhoneRecipient",
* Recipients\AppRecipient::DISCR = "Products\NotificationsBundle\Entity\Recipients\AppRecipient",
* })
* @ORM\Table(
* name = "notis__recipient",
* indexes = {
* @ORM\Index(
* name = "idx__contact",
* columns = {
* "contact",
* },
* ),
* @ORM\Index(
* name = "idx__installation",
* columns = {
* "installation",
* },
* ),
* },
* uniqueConstraints = {
* @ORM\UniqueConstraint(
* name = "uidx__tenant__profile__contact",
* columns = {
* "tenant",
* "contact",
* },
* ),
* },
* )
*/
abstract class AbstractRecipient extends TenantedEntity implements ContactInterface
{
use ReachabilityTrait;
const DISCRS = [
Recipients\EmailRecipient::DISCR => Recipients\EmailRecipient::class,
Recipients\PhoneRecipient::DISCR => Recipients\PhoneRecipient::class,
Recipients\AppRecipient::DISCR => Recipients\AppRecipient::class,
];
const DISCR = null;
const KINDS = [
self::KINDS__EMAIL,
self::KINDS__HYBRID,
self::KINDS__SMS,
self::KINDS__VOICE,
self::KINDS__APP,
];
const KINDS__EMAIL = 'email.email';
const KINDS__HYBRID = 'phone.hybrid';
const KINDS__SMS = 'phone.sms';
const KINDS__VOICE = 'phone.voice';
const KINDS__APP = 'app.app';
/**
* @var Collection|ProfileContact[]
*
* @ORM\OneToMany(
* targetEntity = "Products\NotificationsBundle\Entity\ProfileContact",
* mappedBy = "recipient",
* )
*/
protected Collection $contacts;
/**
* This is an overloaded field in order to keep the recipient stuff simple and querying consistent.
* For emails, this expects a string formatted as a valid email address; likely no issues here.
* For phones, this expects a consistently formatted phone string; probably need to accept and use an RFC kind of formatting.
* When displaying and working with phones, we can use other formats, but storage should always be normalized.
*
* @var string|null
*
* @ORM\Column(
* type = "string",
* nullable = false,
* )
*
* @Constraints\NotBlank()
*/
protected ?string $contact = null;
/**
* @var bool
*
* @ORM\Column(
* type = "boolean",
* nullable = false,
* options = {
* "default" = true,
* },
* )
*/
protected bool $active = true;
/**
*
*/
public function __construct()
{
$this->contacts = new ArrayCollection();
}
/**
* @param Criteria|bool|null $criteria
* @return iterable|Collection|array|ProfileContact[]
*/
public function getContacts($criteria = null): iterable
{
if ( ! $this->contacts instanceof Collection) {
$this->contacts = new ArrayCollection();
}
$criteria = ($criteria === true) ? new Criteria() : ($criteria ?: null);
if ( ! empty($criteria)) {
return $this->contacts->matching($criteria);
}
return $this->contacts;
}
/**
* @param Criteria|bool|null $criteria
* @return iterable|Collection|array|Profile[]
*/
public function getProfiles($criteria = null): iterable
{
return $this->getContacts($criteria)->map(function (ProfileContact $contact) {
return $contact->getProfile();
});
}
/**
* @param Criteria|bool|null $criteria
* @return array|Profile[]
*/
public function getProfilesAsArray($criteria = null): array
{
return $this->getProfiles($criteria)->toArray();
}
/**
* @return string
*/
abstract public function getKind(): string;
/**
* @return string
*/
public function getKindSimple(): string
{
switch ($kind = $this->getKind()) {
case self::KINDS__HYBRID:
$kind = self::KINDS__SMS;
break;
}
return explode('.', $kind)[1];
}
/**
* @return string
*/
public function discr(): string
{
return static::DISCR;
}
/**
* @return string|null
*/
public function getContact(): ?string
{
return $this->contact;
}
/**
* @param string $contact
* @return $this
*/
public function setContact(string $contact): self
{
$this->contact = $contact;
return $this;
}
/**
* @return bool
*/
public function isPhone(): bool
{
return str_starts_with($this->getKind(), 'phone.');
}
/**
* @return bool
*/
public function isEmail(): bool
{
return str_starts_with($this->getKind(), 'email.');
}
/**
* @return bool
*/
public function isApp(): bool
{
return str_starts_with($this->getKind(), 'app.');
}
/**
* @return bool
*/
public function isActive(): bool
{
return $this->active;
}
/**
* @param bool $active
* @return $this
*/
public function setActive(bool $active): self
{
$this->active = $active;
return $this;
}
/**
* @return string
*/
public function ui(): string
{
return $this->getContact() ?: '';
}
/**
* @return string
*/
abstract public function getDisplayName(): string;
}