<?php
namespace Products\NotificationsBundle\Entity\Recipients;
use App\Service\Data\PhoneNumberService;
use App\Validator\Constraints\PhoneRecipientCompatibleMethod;
use DateTime;
use Products\NotificationsBundle\Entity\AbstractRecipient;
use Products\NotificationsBundle\Model\Contacts\PhoneContactInterface;
use Reinder83\BinaryFlags\Bits;
use Doctrine\ORM\Mapping as ORM;
/**
* Class PhoneRecipient
* @package Products\NotificationsBundle\Entity\Recipients
*
* @ORM\Entity(
* repositoryClass = "Products\NotificationsBundle\Doctrine\Repository\Recipients\PhoneRecipientRepository",
* )
*
* @PhoneRecipientCompatibleMethod()
*/
class PhoneRecipient extends AbstractRecipient implements PhoneContactInterface
{
const DISCR = 'phone';
const TYPES = [
null => self::TYPES__UNKNOWN,
'landline' => self::TYPES__LANDLINE,
'mobile' => self::TYPES__MOBILE,
'voip' => self::TYPES__VOIP,
];
const TYPES__UNKNOWN = 0;
const TYPES__LANDLINE = Bits::BIT_1;
const TYPES__MOBILE = Bits::BIT_2;
const TYPES__VOIP = Bits::BIT_3;
const METHODS = [
'sms' => self::METHODS__SMS,
'voice' => self::METHODS__VOICE,
'hybrid' => self::METHODS__HYBRID,
];
const METHODS__UNSET = 0;
const METHODS__SMS = Bits::BIT_1;
const METHODS__VOICE = Bits::BIT_2;
const METHODS__HYBRID = Bits::BIT_3;
const SMS_METHODS = [
self::METHODS__SMS,
self::METHODS__HYBRID,
];
const VOICE_METHODS = [
self::METHODS__UNSET,
self::METHODS__VOICE,
self::METHODS__HYBRID,
];
const HYBRID_METHODS = [
self::METHODS__HYBRID,
];
const LOOKUPS__MISSING = null;
const LOOKUPS__SUCCESSFUL = true;
const LOOKUPS__FAILED = false;
/**
* @var array
*
* @ORM\Column(
* type = "json",
* nullable = false,
* )
*/
protected array $lookup = [];
/**
* @var DateTime|null
*
* @ORM\Column(
* type = "datetime",
* nullable = true,
* )
*/
protected ?DateTime $lookupTimestamp = null;
/**
* @var bool|null
*
* @ORM\Column(
* type = "boolean",
* nullable = true,
* )
*/
protected ?bool $lookupStatus = self::LOOKUPS__MISSING;
/**
* @var int
*
* @ORM\Column(
* type = "integer",
* nullable = false,
* options = {
* "default" = PhoneRecipient::TYPES__UNKNOWN,
* "unsigned" = true,
* },
* )
*/
protected int $type = self::TYPES__UNKNOWN;
/**
* @var int
*
* @ORM\Column(
* type = "integer",
* nullable = false,
* options = {
* "default" = PhoneRecipient::METHODS__UNSET,
* "unsigned" = true,
* },
* )
*/
protected int $method = self::METHODS__UNSET;
/**
* @var bool|null
*
* @ORM\Column(
* type = "boolean",
* nullable = false,
* options = {
* "default" = false,
* },
* )
*/
protected bool $blocked = false;
/**
* Whether the phone supports texting and voice.
*
* @return bool
*/
public function isHybrid(): bool
{
return in_array($this->getMethod(), self::HYBRID_METHODS);
}
/**
* Whether the phone supports texting.
*
* @return bool
*/
public function isSms(): bool
{
return in_array($this->getMethod(), self::SMS_METHODS);
}
/**
* Whether the phone prefers voice communication.
* Since any phone type can support voice, but not texting, this is the default type if none is set.
*
* @return bool
*/
public function isVoice(): bool
{
return in_array($this->getMethod(), self::VOICE_METHODS);
}
/**
* @return int
*/
public function getType(): int
{
return $this->type;
}
/**
* @param int $type
* @return $this
*/
public function setType(int $type): self
{
$this->type = $type;
return $this;
}
/**
* @return int
*/
public function getMethod(): int
{
return $this->method;
}
/**
* @param int $method
* @return $this
*/
public function setMethod(int $method): self
{
$this->method = $method;
return $this;
}
/**
* @param int $method
* @param bool $toggle
* @return $this
*/
public function toggleMethod(int $method, bool $toggle): self
{
static $alts = [
self::METHODS__SMS => self::METHODS__VOICE,
self::METHODS__VOICE => self::METHODS__SMS,
];
switch (true) {
// if nothing is set, just set it
case $toggle && $this->getMethod() === self::METHODS__UNSET:
// if something is set, and it is us, can just set us again
case $toggle && $this->getMethod() === $method:
return $this->setMethod($method);
// if something is set, and it is not hybrid, make it hybrid
case $toggle && $this->getMethod() !== self::METHODS__HYBRID:
// or, we are already hybrid
case $toggle && $this->getMethod() === self::METHODS__HYBRID:
return $this->setMethod(self::METHODS__HYBRID);
// toggling off and we are hybid
case ! $toggle && $this->getMethod() === self::METHODS__HYBRID:
return $this->setMethod($alts[$method]);
// toggling off, and we are not what is toggled on, just pass through
case ! $toggle && $this->getMethod() !== $method:
return $this;
// toggling off, and we are what is toggled on, so just unset the method
case ! $toggle && $this->getMethod() === $method:
// toggling off, and nothing is already set
case ! $toggle && $this->getMethod() === self::METHODS__UNSET:
return $this->setMethod(self::METHODS__UNSET);
}
throw new \Exception();
}
/**
* {@inheritDoc}
*/
public function getKind(): string
{
switch (true) {
case $this->isHybrid():
return AbstractRecipient::KINDS__HYBRID;
case $this->isSms():
return AbstractRecipient::KINDS__SMS;
case $this->isVoice():
return AbstractRecipient::KINDS__VOICE;
}
throw new \Exception();
}
/**
* {@inheritDoc}
*/
public function getPhoneNumber(): string
{
return $this->getContact();
}
/**
* @return array|null
*/
public function getLookup(): ?array
{
return $this->lookup ?: null;
}
/**
* @param array|null $lookup
* @return $this
*/
public function setLookup(?array $lookup): self
{
$this->lookup = $lookup ?: [];
return $this;
}
/**
* @return DateTime|null
*/
public function getLookupTimestamp(): ?DateTime
{
return $this->lookupTimestamp;
}
/**
* @param DateTime|null $lookupTimestamp
* @return $this
*/
public function setLookupTimestamp(?DateTime $lookupTimestamp): self
{
$this->lookupTimestamp = $lookupTimestamp;
return $this;
}
/**
* @return bool|null
*/
public function getLookupStatus(): ?bool
{
return $this->lookupStatus;
}
/**
* @param bool|null $lookupStatus
* @return $this
*/
public function setLookupStatus(?bool $lookupStatus): self
{
$this->lookupStatus = $lookupStatus;
return $this;
}
/**
* {@inheritDoc}
*/
public function getDisplayName(): string
{
return PhoneNumberService::getInstance()->national(
$this->getPhoneNumber()
);
}
/**
* @return bool
*/
public function isBlocked(): bool
{
return $this->blocked;
}
/**
* @param bool $blocked
* @return self
*/
public function setBlocked(bool $blocked): self
{
$this->blocked = $blocked;
return $this;
}
}