geno/wp-content/plugins/mailpoet/lib/Entities/SubscriberEntity.php
2024-02-01 11:54:18 +00:00

638 lines
15 KiB
PHP

<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
namespace MailPoet\Entities;
if (!defined('ABSPATH')) exit;
use DateTimeInterface;
use MailPoet\Doctrine\EntityTraits\AutoincrementedIdTrait;
use MailPoet\Doctrine\EntityTraits\CreatedAtTrait;
use MailPoet\Doctrine\EntityTraits\DeletedAtTrait;
use MailPoet\Doctrine\EntityTraits\UpdatedAtTrait;
use MailPoet\Util\Helpers;
use MailPoetVendor\Doctrine\Common\Collections\ArrayCollection;
use MailPoetVendor\Doctrine\Common\Collections\Collection;
use MailPoetVendor\Doctrine\Common\Collections\Criteria;
use MailPoetVendor\Doctrine\ORM\Mapping as ORM;
use MailPoetVendor\Symfony\Component\Validator\Constraints as Assert;
/**
* @ORM\Entity()
* @ORM\Table(name="subscribers")
* @ORM\HasLifecycleCallbacks
* @ORM\EntityListeners({"\MailPoet\Doctrine\EventListeners\SubscriberListener"})
*/
class SubscriberEntity {
// hook names
public const HOOK_SUBSCRIBER_CREATED = 'mailpoet_subscriber_created';
public const HOOK_SUBSCRIBER_DELETED = 'mailpoet_subscriber_deleted';
public const HOOK_SUBSCRIBER_UPDATED = 'mailpoet_subscriber_updated';
public const HOOK_SUBSCRIBER_STATUS_CHANGED = 'mailpoet_subscriber_status_changed';
public const HOOK_MULTIPLE_SUBSCRIBERS_CREATED = 'mailpoet_multiple_subscribers_created';
public const HOOK_MULTIPLE_SUBSCRIBERS_DELETED = 'mailpoet_multiple_subscribers_deleted';
public const HOOK_MULTIPLE_SUBSCRIBERS_UPDATED = 'mailpoet_multiple_subscribers_updated';
// statuses
const STATUS_BOUNCED = 'bounced';
const STATUS_INACTIVE = 'inactive';
const STATUS_SUBSCRIBED = 'subscribed';
const STATUS_UNCONFIRMED = 'unconfirmed';
const STATUS_UNSUBSCRIBED = 'unsubscribed';
public const OBSOLETE_LINK_TOKEN_LENGTH = 6;
public const LINK_TOKEN_LENGTH = 32;
use AutoincrementedIdTrait;
use CreatedAtTrait;
use UpdatedAtTrait;
use DeletedAtTrait;
/**
* @ORM\Column(type="bigint", nullable=true)
* @var string|null
*/
private $wpUserId;
/**
* @ORM\Column(type="boolean")
* @var bool
*/
private $isWoocommerceUser = false;
/**
* @ORM\Column(type="string")
* @var string
*/
private $firstName = '';
/**
* @ORM\Column(type="string")
* @var string
*/
private $lastName = '';
/**
* @ORM\Column(type="string")
* @Assert\Email()
* @Assert\NotBlank()
* @var string
*/
private $email;
/**
* @ORM\Column(type="string")
* @var string
*/
private $status = self::STATUS_UNCONFIRMED;
/**
* @ORM\Column(type="string", nullable=true)
* @var string|null
*/
private $subscribedIp;
/**
* @ORM\Column(type="string", nullable=true)
* @var string|null
*/
private $confirmedIp;
/**
* @ORM\Column(type="datetimetz", nullable=true)
* @var DateTimeInterface|null
*/
private $confirmedAt;
/**
* @ORM\Column(type="datetimetz", nullable=true)
* @var DateTimeInterface|null
*/
private $lastSubscribedAt;
/**
* @ORM\Column(type="text", nullable=true)
* @var string|null
*/
private $unconfirmedData;
/**
* @ORM\Column(type="string")
* @var string
*/
private $source = 'unknown';
/**
* @ORM\Column(type="integer")
* @var int
*/
private $countConfirmations = 0;
/**
* @ORM\Column(type="string", nullable=true)
* @var string|null
*/
private $unsubscribeToken;
/**
* @ORM\Column(type="string", nullable=true)
* @var string|null
*/
private $linkToken;
/**
* @ORM\Column(type="float", nullable=true)
* @var float|null
*/
private $engagementScore;
/**
* @ORM\Column(type="datetimetz", nullable=true)
* @var DateTimeInterface|null
*/
private $engagementScoreUpdatedAt;
/**
* @ORM\Column(type="datetimetz", nullable=true)
* @var DateTimeInterface|null
*/
private $lastEngagementAt;
/**
* @ORM\Column(type="datetimetz", nullable=true)
* @var DateTimeInterface|null
*/
private $lastSendingAt;
/**
* @ORM\Column(type="datetimetz", nullable=true)
* @var DateTimeInterface|null
*/
private $lastOpenAt;
/**
* @ORM\Column(type="datetimetz", nullable=true)
* @var DateTimeInterface|null
*/
private $lastClickAt;
/**
* @ORM\Column(type="datetimetz", nullable=true)
* @var DateTimeInterface|null
*/
private $lastPurchaseAt;
/**
* @ORM\Column(type="datetimetz", nullable=true)
* @var DateTimeInterface|null
*/
private $lastPageViewAt;
/**
* @ORM\Column(type="datetimetz", nullable=true)
* @var DateTimeInterface|null
*/
private $woocommerceSyncedAt;
/**
* @ORM\Column(type="integer")
* @var int
*/
private $emailCount = 0;
/**
* @ORM\OneToMany(targetEntity="MailPoet\Entities\SubscriberSegmentEntity", mappedBy="subscriber", orphanRemoval=true)
* @var Collection<int, SubscriberSegmentEntity>
*/
private $subscriberSegments;
/**
* @ORM\OneToMany(targetEntity="MailPoet\Entities\SubscriberCustomFieldEntity", mappedBy="subscriber", orphanRemoval=true)
* @var Collection<int, SubscriberCustomFieldEntity>
*/
private $subscriberCustomFields;
/**
* @ORM\OneToMany(targetEntity="MailPoet\Entities\SubscriberTagEntity", mappedBy="subscriber", orphanRemoval=true)
* @var Collection<int, SubscriberTagEntity>
*/
private $subscriberTags;
/**
* @ORM\OneToMany(targetEntity="MailPoet\Entities\ScheduledTaskSubscriberEntity", mappedBy="subscriber", orphanRemoval=true)
* @var Collection<int, ScheduledTaskSubscriberEntity>
*/
private $scheduledTaskSubscribers;
public function __construct() {
$this->subscriberSegments = new ArrayCollection();
$this->subscriberCustomFields = new ArrayCollection();
$this->subscriberTags = new ArrayCollection();
$this->scheduledTaskSubscribers = new ArrayCollection();
}
/**
* @deprecated This is here only for backward compatibility with custom shortcodes https://kb.mailpoet.com/article/160-create-a-custom-shortcode
* This can be removed after 2021-08-01
*/
public function __get($key) {
$getterName = 'get' . Helpers::underscoreToCamelCase($key, $capitaliseFirstChar = true);
$callable = [$this, $getterName];
if (is_callable($callable)) {
return call_user_func($callable);
}
}
/**
* @return int|null
*/
public function getWpUserId() {
return $this->wpUserId ? (int)$this->wpUserId : null;
}
/**
* @param int|null $wpUserId
*/
public function setWpUserId($wpUserId) {
$this->wpUserId = $wpUserId ? (string)$wpUserId : null;
}
public function isWPUser(): bool {
return $this->getWpUserId() > 0;
}
/**
* @return bool
*/
public function getIsWoocommerceUser() {
return $this->isWoocommerceUser;
}
/**
* @param bool $isWoocommerceUser
*/
public function setIsWoocommerceUser($isWoocommerceUser) {
$this->isWoocommerceUser = $isWoocommerceUser;
}
/**
* @return string
*/
public function getFirstName() {
return $this->firstName;
}
/**
* @param string $firstName
*/
public function setFirstName($firstName) {
$this->firstName = $firstName;
}
/**
* @return string
*/
public function getLastName() {
return $this->lastName;
}
/**
* @param string $lastName
*/
public function setLastName($lastName) {
$this->lastName = $lastName;
}
/**
* @return string
*/
public function getEmail() {
return $this->email;
}
/**
* @param string $email
*/
public function setEmail($email) {
$this->email = $email;
}
/**
* @return string
*/
public function getStatus() {
return $this->status;
}
/**
* @param string $status
*/
public function setStatus($status) {
if (
!in_array($status, [
self::STATUS_BOUNCED,
self::STATUS_INACTIVE,
self::STATUS_SUBSCRIBED,
self::STATUS_UNCONFIRMED,
self::STATUS_UNSUBSCRIBED,
])
) {
throw new \InvalidArgumentException("Invalid status '{$status}' given to subscriber!");
}
$this->status = $status;
}
/**
* @return string|null
*/
public function getSubscribedIp() {
return $this->subscribedIp;
}
/**
* @param string $subscribedIp
*/
public function setSubscribedIp($subscribedIp) {
$this->subscribedIp = $subscribedIp;
}
/**
* @return string|null
*/
public function getConfirmedIp() {
return $this->confirmedIp;
}
/**
* @param string|null $confirmedIp
*/
public function setConfirmedIp($confirmedIp) {
$this->confirmedIp = $confirmedIp;
}
/**
* @return DateTimeInterface|null
*/
public function getConfirmedAt() {
return $this->confirmedAt;
}
/**
* @param DateTimeInterface|null $confirmedAt
*/
public function setConfirmedAt($confirmedAt) {
$this->confirmedAt = $confirmedAt;
}
/**
* @return DateTimeInterface|null
*/
public function getLastSubscribedAt() {
return $this->lastSubscribedAt;
}
/**
* @param DateTimeInterface|null $lastSubscribedAt
*/
public function setLastSubscribedAt($lastSubscribedAt) {
$this->lastSubscribedAt = $lastSubscribedAt;
}
/**
* @return string|null
*/
public function getUnconfirmedData() {
return $this->unconfirmedData;
}
/**
* @param string|null $unconfirmedData
*/
public function setUnconfirmedData($unconfirmedData) {
$this->unconfirmedData = $unconfirmedData;
}
/**
* @return string
*/
public function getSource() {
return $this->source;
}
/**
* @param string $source
*/
public function setSource($source) {
if (
!in_array($source, [
'api',
'form',
'unknown',
'imported',
'administrator',
'wordpress_user',
'woocommerce_user',
'woocommerce_checkout',
])
) {
throw new \InvalidArgumentException("Invalid source '{$source}' given to subscriber!");
}
$this->source = $source;
}
/**
* @return int
*/
public function getConfirmationsCount() {
return $this->countConfirmations;
}
/**
* @param int $countConfirmations
*/
public function setConfirmationsCount($countConfirmations) {
$this->countConfirmations = $countConfirmations;
}
/**
* @return string|null
*/
public function getUnsubscribeToken() {
return $this->unsubscribeToken;
}
/**
* @param string|null $unsubscribeToken
*/
public function setUnsubscribeToken($unsubscribeToken) {
$this->unsubscribeToken = $unsubscribeToken;
}
/**
* @return string|null
*/
public function getLinkToken() {
return $this->linkToken;
}
/**
* @param string|null $linkToken
*/
public function setLinkToken($linkToken) {
$this->linkToken = $linkToken;
}
/**
* @return Collection<int, SubscriberSegmentEntity>
*/
public function getSubscriberSegments(?string $status = null) {
if (!is_null($status)) {
$criteria = Criteria::create()
->where(Criteria::expr()->eq('status', $status));
$subscriberSegments = $this->subscriberSegments->matching($criteria);
} else {
$subscriberSegments = $this->subscriberSegments;
}
return $subscriberSegments;
}
/** * @return Collection<int, SegmentEntity> */
public function getSegments() {
return $this->subscriberSegments->map(function (SubscriberSegmentEntity $subscriberSegment) {
return $subscriberSegment->getSegment();
})->filter(function ($segment) {
return $segment !== null;
});
}
/**
* @return Collection<int, SubscriberCustomFieldEntity>
*/
public function getSubscriberCustomFields() {
return $this->subscriberCustomFields;
}
public function getSubscriberCustomField(CustomFieldEntity $customField): ?SubscriberCustomFieldEntity {
$criteria = Criteria::create()
->where(Criteria::expr()->eq('customField', $customField))
->setMaxResults(1);
return $this->getSubscriberCustomFields()->matching($criteria)->first() ?: null;
}
/**
* @return Collection<int, SubscriberTagEntity>
*/
public function getSubscriberTags() {
return $this->subscriberTags;
}
public function getSubscriberTag(TagEntity $tag): ?SubscriberTagEntity {
$criteria = Criteria::create()
->where(Criteria::expr()->eq('tag', $tag))
->setMaxResults(1);
return $this->getSubscriberTags()->matching($criteria)->first() ?: null;
}
/**
* @return float|null
*/
public function getEngagementScore(): ?float {
return $this->engagementScore;
}
/**
* @param float|null $engagementScore
*/
public function setEngagementScore(?float $engagementScore): void {
$this->engagementScore = $engagementScore;
}
/**
* @return DateTimeInterface|null
*/
public function getEngagementScoreUpdatedAt(): ?DateTimeInterface {
return $this->engagementScoreUpdatedAt;
}
/**
* @param DateTimeInterface|null $engagementScoreUpdatedAt
*/
public function setEngagementScoreUpdatedAt(?DateTimeInterface $engagementScoreUpdatedAt): void {
$this->engagementScoreUpdatedAt = $engagementScoreUpdatedAt;
}
public function getLastEngagementAt(): ?DateTimeInterface {
return $this->lastEngagementAt;
}
public function setLastEngagementAt(DateTimeInterface $lastEngagementAt): void {
$this->lastEngagementAt = $lastEngagementAt;
}
public function getLastSendingAt(): ?DateTimeInterface {
return $this->lastSendingAt;
}
public function setLastSendingAt(?DateTimeInterface $dateTime): void {
$this->lastSendingAt = $dateTime;
}
public function getLastOpenAt(): ?DateTimeInterface {
return $this->lastOpenAt;
}
public function setLastOpenAt(?DateTimeInterface $dateTime): void {
$this->lastOpenAt = $dateTime;
}
public function getLastClickAt(): ?DateTimeInterface {
return $this->lastClickAt;
}
public function setLastClickAt(?DateTimeInterface $dateTime): void {
$this->lastClickAt = $dateTime;
}
public function getLastPurchaseAt(): ?DateTimeInterface {
return $this->lastPurchaseAt;
}
public function setLastPurchaseAt(?DateTimeInterface $dateTime): void {
$this->lastPurchaseAt = $dateTime;
}
public function getLastPageViewAt(): ?DateTimeInterface {
return $this->lastPageViewAt;
}
public function setLastPageViewAt(?DateTimeInterface $dateTime): void {
$this->lastPageViewAt = $dateTime;
}
public function setWoocommerceSyncedAt(?DateTimeInterface $woocommerceSyncedAt): void {
$this->woocommerceSyncedAt = $woocommerceSyncedAt;
}
public function getWoocommerceSyncedAt(): ?DateTimeInterface {
return $this->woocommerceSyncedAt;
}
public function getEmailCount(): int {
return $this->emailCount;
}
public function setEmailCount(int $emailCount): void {
$this->emailCount = $emailCount;
}
/** @ORM\PreFlush */
public function cleanupSubscriberSegments(): void {
// Delete old orphan SubscriberSegments to avoid errors on update
$this->subscriberSegments->map(function (SubscriberSegmentEntity $subscriberSegment) {
if ($subscriberSegment->getSegment() === null) {
$this->subscriberSegments->removeElement($subscriberSegment);
}
});
}
}