src/Products/NotificationsBundle/Entity/AbstractRecipient.php line 60

Open in your IDE?
  1. <?php
  2. namespace Products\NotificationsBundle\Entity;
  3. use Cms\TenantBundle\Entity\TenantedEntity;
  4. use Doctrine\Common\Collections\ArrayCollection;
  5. use Doctrine\Common\Collections\Collection;
  6. use Doctrine\Common\Collections\Criteria;
  7. use Doctrine\ORM\Mapping as ORM;
  8. use Products\NotificationsBundle\Entity\Recipients;
  9. use Products\NotificationsBundle\Model\Contacts\ContactInterface;
  10. use Products\NotificationsBundle\Util\ReachabilityTrait;
  11. use Symfony\Component\Validator\Constraints;
  12. /**
  13.  * Class AbstractRecipient
  14.  *
  15.  * @package Products\NotificationsBundle\Entity
  16.  *
  17.  * @ORM\Entity(
  18.  *     repositoryClass = "Products\NotificationsBundle\Doctrine\Repository\RecipientRepository",
  19.  * )
  20.  * @ORM\InheritanceType("SINGLE_TABLE")
  21.  * @ORM\DiscriminatorColumn(
  22.  *     name = "discr",
  23.  *     type = "string",
  24.  * )
  25.  * @ORM\DiscriminatorMap({
  26.  *     Recipients\EmailRecipient::DISCR = "Products\NotificationsBundle\Entity\Recipients\EmailRecipient",
  27.  *     Recipients\PhoneRecipient::DISCR = "Products\NotificationsBundle\Entity\Recipients\PhoneRecipient",
  28.  *     Recipients\AppRecipient::DISCR = "Products\NotificationsBundle\Entity\Recipients\AppRecipient",
  29.  * })
  30.  * @ORM\Table(
  31.  *     name = "notis__recipient",
  32.  *     indexes = {
  33.  *         @ORM\Index(
  34.  *             name = "idx__contact",
  35.  *             columns = {
  36.  *                 "contact",
  37.  *             },
  38.  *         ),
  39.  *         @ORM\Index(
  40.  *             name = "idx__installation",
  41.  *             columns = {
  42.  *                 "installation",
  43.  *             },
  44.  *         ),
  45.  *     },
  46.  *     uniqueConstraints = {
  47.  *         @ORM\UniqueConstraint(
  48.  *             name = "uidx__tenant__profile__contact",
  49.  *             columns = {
  50.  *                 "tenant",
  51.  *                 "contact",
  52.  *             },
  53.  *         ),
  54.  *     },
  55.  * )
  56.  */
  57. abstract class AbstractRecipient extends TenantedEntity implements ContactInterface
  58. {
  59.     use ReachabilityTrait;
  60.     const DISCRS = [
  61.         Recipients\EmailRecipient::DISCR => Recipients\EmailRecipient::class,
  62.         Recipients\PhoneRecipient::DISCR => Recipients\PhoneRecipient::class,
  63.         Recipients\AppRecipient::DISCR => Recipients\AppRecipient::class,
  64.     ];
  65.     const DISCR null;
  66.     const KINDS = [
  67.         self::KINDS__EMAIL,
  68.         self::KINDS__HYBRID,
  69.         self::KINDS__SMS,
  70.         self::KINDS__VOICE,
  71.         self::KINDS__APP,
  72.     ];
  73.     const KINDS__EMAIL 'email.email';
  74.     const KINDS__HYBRID 'phone.hybrid';
  75.     const KINDS__SMS 'phone.sms';
  76.     const KINDS__VOICE 'phone.voice';
  77.     const KINDS__APP 'app.app';
  78.     /**
  79.      * @var Collection|ProfileContact[]
  80.      *
  81.      * @ORM\OneToMany(
  82.      *     targetEntity = "Products\NotificationsBundle\Entity\ProfileContact",
  83.      *     mappedBy = "recipient",
  84.      * )
  85.      */
  86.     protected Collection $contacts;
  87.     /**
  88.      * This is an overloaded field in order to keep the recipient stuff simple and querying consistent.
  89.      * For emails, this expects a string formatted as a valid email address; likely no issues here.
  90.      * For phones, this expects a consistently formatted phone string; probably need to accept and use an RFC kind of formatting.
  91.      * When displaying and working with phones, we can use other formats, but storage should always be normalized.
  92.      *
  93.      * @var string|null
  94.      *
  95.      * @ORM\Column(
  96.      *     type = "string",
  97.      *     nullable = false,
  98.      * )
  99.      *
  100.      * @Constraints\NotBlank()
  101.      */
  102.     protected ?string $contact null;
  103.     /**
  104.      * @var bool
  105.      *
  106.      * @ORM\Column(
  107.      *     type = "boolean",
  108.      *     nullable = false,
  109.      *     options = {
  110.      *         "default" = true,
  111.      *     },
  112.      * )
  113.      */
  114.     protected bool $active true;
  115.     /**
  116.      *
  117.      */
  118.     public function __construct()
  119.     {
  120.         $this->contacts = new ArrayCollection();
  121.     }
  122.     /**
  123.      * @param Criteria|bool|null $criteria
  124.      * @return iterable|Collection|array|ProfileContact[]
  125.      */
  126.     public function getContacts($criteria null): iterable
  127.     {
  128.         if ( ! $this->contacts instanceof Collection) {
  129.             $this->contacts = new ArrayCollection();
  130.         }
  131.         $criteria = ($criteria === true) ? new Criteria() : ($criteria ?: null);
  132.         if ( ! empty($criteria)) {
  133.             return $this->contacts->matching($criteria);
  134.         }
  135.         return $this->contacts;
  136.     }
  137.     /**
  138.      * @param Criteria|bool|null $criteria
  139.      * @return iterable|Collection|array|Profile[]
  140.      */
  141.     public function getProfiles($criteria null): iterable
  142.     {
  143.         return $this->getContacts($criteria)->map(function (ProfileContact $contact) {
  144.             return $contact->getProfile();
  145.         });
  146.     }
  147.     /**
  148.      * @param Criteria|bool|null $criteria
  149.      * @return array|Profile[]
  150.      */
  151.     public function getProfilesAsArray($criteria null): array
  152.     {
  153.         return $this->getProfiles($criteria)->toArray();
  154.     }
  155.     /**
  156.      * @return string
  157.      */
  158.     abstract public function getKind(): string;
  159.     /**
  160.      * @return string
  161.      */
  162.     public function getKindSimple(): string
  163.     {
  164.         switch ($kind $this->getKind()) {
  165.             case self::KINDS__HYBRID:
  166.                 $kind self::KINDS__SMS;
  167.                 break;
  168.         }
  169.         return explode('.'$kind)[1];
  170.     }
  171.     /**
  172.      * @return string
  173.      */
  174.     public function discr(): string
  175.     {
  176.         return static::DISCR;
  177.     }
  178.     /**
  179.      * @return string|null
  180.      */
  181.     public function getContact(): ?string
  182.     {
  183.         return $this->contact;
  184.     }
  185.     /**
  186.      * @param string $contact
  187.      * @return $this
  188.      */
  189.     public function setContact(string $contact): self
  190.     {
  191.         $this->contact $contact;
  192.         return $this;
  193.     }
  194.     /**
  195.      * @return bool
  196.      */
  197.     public function isPhone(): bool
  198.     {
  199.         return str_starts_with($this->getKind(), 'phone.');
  200.     }
  201.     /**
  202.      * @return bool
  203.      */
  204.     public function isEmail(): bool
  205.     {
  206.         return str_starts_with($this->getKind(), 'email.');
  207.     }
  208.     /**
  209.      * @return bool
  210.      */
  211.     public function isApp(): bool
  212.     {
  213.         return str_starts_with($this->getKind(), 'app.');
  214.     }
  215.     /**
  216.      * @return bool
  217.      */
  218.     public function isActive(): bool
  219.     {
  220.         return $this->active;
  221.     }
  222.     /**
  223.      * @param bool $active
  224.      * @return $this
  225.      */
  226.     public function setActive(bool $active): self
  227.     {
  228.         $this->active $active;
  229.         return $this;
  230.     }
  231.     /**
  232.      * @return string
  233.      */
  234.     public function ui(): string
  235.     {
  236.         return $this->getContact() ?: '';
  237.     }
  238.     /**
  239.      * @return string
  240.      */
  241.     abstract public function getDisplayName(): string;
  242. }