init
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
|
||||
|
||||
namespace MailPoet\Entities;
|
||||
|
||||
if (!defined('ABSPATH')) exit;
|
||||
|
||||
|
||||
use MailPoet\Doctrine\EntityTraits\AutoincrementedIdTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\CreatedAtTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\UpdatedAtTrait;
|
||||
use MailPoetVendor\Doctrine\ORM\Mapping as ORM;
|
||||
use MailPoetVendor\Symfony\Component\Validator\Constraints as Assert;
|
||||
|
||||
/**
|
||||
* @ORM\Entity()
|
||||
* @ORM\Table(name="custom_fields")
|
||||
*/
|
||||
class CustomFieldEntity {
|
||||
public const TYPE_DATE = 'date';
|
||||
public const TYPE_TEXT = 'text';
|
||||
public const TYPE_TEXTAREA = 'textarea';
|
||||
public const TYPE_RADIO = 'radio';
|
||||
public const TYPE_CHECKBOX = 'checkbox';
|
||||
public const TYPE_SELECT = 'select';
|
||||
|
||||
use AutoincrementedIdTrait;
|
||||
use CreatedAtTrait;
|
||||
use UpdatedAtTrait;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string", nullable=false, unique=true)
|
||||
* @Assert\NotBlank()
|
||||
* @var string
|
||||
*/
|
||||
private $name;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string", nullable=false)
|
||||
* @Assert\NotBlank()
|
||||
* @var string
|
||||
*/
|
||||
private $type;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="array")
|
||||
* @var array
|
||||
*/
|
||||
private $params;
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getName() {
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getType() {
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array|null
|
||||
*/
|
||||
public function getParams() {
|
||||
return $this->params;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
*/
|
||||
public function setName($name) {
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $type
|
||||
*/
|
||||
public function setType($type) {
|
||||
$this->type = $type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $params
|
||||
*/
|
||||
public function setParams(array $params) {
|
||||
$this->params = $params;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace MailPoet\Entities;
|
||||
|
||||
if (!defined('ABSPATH')) exit;
|
||||
|
||||
|
||||
use MailPoet\InvalidStateException;
|
||||
use MailPoet\Segments\DynamicSegments\Filters\UserRole;
|
||||
use MailPoet\Segments\DynamicSegments\Filters\WooCommerceProduct;
|
||||
use MailPoetVendor\Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
/**
|
||||
* @ORM\Embeddable()
|
||||
*/
|
||||
class DynamicSegmentFilterData {
|
||||
const TYPE_AUTOMATIONS = 'automations';
|
||||
const TYPE_USER_ROLE = 'userRole';
|
||||
const TYPE_EMAIL = 'email';
|
||||
const TYPE_WOOCOMMERCE = 'woocommerce';
|
||||
const TYPE_WOOCOMMERCE_MEMBERSHIP = 'woocommerceMembership';
|
||||
const TYPE_WOOCOMMERCE_SUBSCRIPTION = 'woocommerceSubscription';
|
||||
|
||||
public const CONNECT_TYPE_AND = 'and';
|
||||
public const CONNECT_TYPE_OR = 'or';
|
||||
|
||||
public const OPERATOR_ALL = 'all';
|
||||
public const OPERATOR_ANY = 'any';
|
||||
public const OPERATOR_NONE = 'none';
|
||||
|
||||
public const OPERATOR_STARTS_WITH = 'startsWith';
|
||||
public const OPERATOR_NOT_ENDS_WITH = 'notEndsWith';
|
||||
public const OPERATOR_IS = 'is';
|
||||
public const OPERATOR_CONTAINS = 'contains';
|
||||
public const OPERATOR_NOT_CONTAINS = 'notContains';
|
||||
public const OPERATOR_NOT_STARTS_WITH = 'notStartsWith';
|
||||
public const OPERATOR_IS_NOT = 'isNot';
|
||||
public const OPERATOR_ENDS_WITH = 'endsWith';
|
||||
public const TEXT_FIELD_OPERATORS = [
|
||||
DynamicSegmentFilterData::OPERATOR_IS,
|
||||
DynamicSegmentFilterData::OPERATOR_IS_NOT,
|
||||
DynamicSegmentFilterData::OPERATOR_CONTAINS,
|
||||
DynamicSegmentFilterData::OPERATOR_NOT_CONTAINS,
|
||||
DynamicSegmentFilterData::OPERATOR_STARTS_WITH,
|
||||
DynamicSegmentFilterData::OPERATOR_NOT_STARTS_WITH,
|
||||
DynamicSegmentFilterData::OPERATOR_ENDS_WITH,
|
||||
DynamicSegmentFilterData::OPERATOR_NOT_ENDS_WITH,
|
||||
];
|
||||
public const IS_NOT_BLANK = 'is_not_blank';
|
||||
public const IS_BLANK = 'is_blank';
|
||||
|
||||
public const TIMEFRAME_ALL_TIME = 'allTime';
|
||||
public const TIMEFRAME_IN_THE_LAST = 'inTheLast';
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="serialized_array")
|
||||
* @var array|null
|
||||
*/
|
||||
private $filterData;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string", nullable=true)
|
||||
* @var string|null
|
||||
*/
|
||||
private $filterType;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string", nullable=true)
|
||||
* @var string|null
|
||||
*/
|
||||
private $action;
|
||||
|
||||
public function __construct(
|
||||
string $filterType,
|
||||
string $action,
|
||||
array $filterData = []
|
||||
) {
|
||||
$this->filterType = $filterType;
|
||||
$this->action = $action;
|
||||
$this->filterData = $filterData;
|
||||
}
|
||||
|
||||
public function getData(): ?array {
|
||||
return $this->filterData;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed|null
|
||||
*/
|
||||
public function getParam(string $name) {
|
||||
return $this->filterData[$name] ?? null;
|
||||
}
|
||||
|
||||
public function getStringParam(string $name): string {
|
||||
$value = $this->filterData[$name] ?? null;
|
||||
if (!is_string($value)) {
|
||||
throw new InvalidStateException("No string value found in filter data for param $name.");
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function getIntParam(string $name): int {
|
||||
$value = $this->filterData[$name] ?? null;
|
||||
if (is_int($value)) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
if (is_string($value)) {
|
||||
return (int)($value);
|
||||
}
|
||||
|
||||
throw new InvalidStateException("No compatible integer value found in filter data for param $name.");
|
||||
}
|
||||
|
||||
public function getArrayParam(string $name): array {
|
||||
$value = $this->getParam($name);
|
||||
if (!is_array($value)) {
|
||||
throw new InvalidStateException("No array value found in filter data for param $name.");
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function getFilterType(): ?string {
|
||||
if ($this->filterType) {
|
||||
return $this->filterType;
|
||||
}
|
||||
// When a new column is empty, we try to get the value from serialized data
|
||||
return $this->filterData['segmentType'] ?? null;
|
||||
}
|
||||
|
||||
public function getAction(): ?string {
|
||||
if ($this->action) {
|
||||
return $this->action;
|
||||
}
|
||||
// When a new column is empty, we try to get the value from serialized data
|
||||
// BC compatibility, the wordpress user role segment didn't have action
|
||||
if ($this->getFilterType() === self::TYPE_USER_ROLE && !isset($this->filterData['action'])) {
|
||||
return UserRole::TYPE;
|
||||
}
|
||||
return $this->filterData['action'] ?? null;
|
||||
}
|
||||
|
||||
public function getOperator(): ?string {
|
||||
$operator = $this->filterData['operator'] ?? null;
|
||||
if (!$operator) {
|
||||
return $this->getDefaultOperator();
|
||||
}
|
||||
|
||||
return $operator;
|
||||
}
|
||||
|
||||
private function getDefaultOperator(): ?string {
|
||||
if ($this->getFilterType() === self::TYPE_WOOCOMMERCE && $this->getAction() === WooCommerceProduct::ACTION_PRODUCT) {
|
||||
return self::OPERATOR_ANY;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
|
||||
|
||||
namespace MailPoet\Entities;
|
||||
|
||||
if (!defined('ABSPATH')) exit;
|
||||
|
||||
|
||||
use MailPoet\Doctrine\EntityTraits\AutoincrementedIdTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\CreatedAtTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\SafeToOneAssociationLoadTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\UpdatedAtTrait;
|
||||
use MailPoetVendor\Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
/**
|
||||
* @ORM\Entity()
|
||||
* @ORM\Table(name="dynamic_segment_filters")
|
||||
*/
|
||||
class DynamicSegmentFilterEntity {
|
||||
use AutoincrementedIdTrait;
|
||||
use CreatedAtTrait;
|
||||
use UpdatedAtTrait;
|
||||
use SafeToOneAssociationLoadTrait;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="MailPoet\Entities\SegmentEntity", inversedBy="filters")
|
||||
* @var SegmentEntity|null
|
||||
*/
|
||||
private $segment;
|
||||
|
||||
/**
|
||||
* @ORM\Embedded(class="MailPoet\Entities\DynamicSegmentFilterData", columnPrefix=false)
|
||||
* @var DynamicSegmentFilterData
|
||||
*/
|
||||
private $filterData;
|
||||
|
||||
public function __construct(
|
||||
SegmentEntity $segment,
|
||||
DynamicSegmentFilterData $filterData
|
||||
) {
|
||||
$this->segment = $segment;
|
||||
$this->filterData = $filterData;
|
||||
}
|
||||
|
||||
public function __clone() {
|
||||
$this->id = null;
|
||||
$this->segment = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return SegmentEntity|null
|
||||
*/
|
||||
public function getSegment() {
|
||||
$this->safelyLoadToOneAssociation('segment');
|
||||
return $this->segment;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return DynamicSegmentFilterData
|
||||
*/
|
||||
public function getFilterData() {
|
||||
return $this->filterData;
|
||||
}
|
||||
|
||||
public function setSegment(SegmentEntity $segment) {
|
||||
$this->segment = $segment;
|
||||
}
|
||||
|
||||
public function setFilterData(DynamicSegmentFilterData $filterData) {
|
||||
$this->filterData = $filterData;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
|
||||
|
||||
namespace MailPoet\Entities;
|
||||
|
||||
if (!defined('ABSPATH')) exit;
|
||||
|
||||
|
||||
use MailPoet\Doctrine\EntityTraits\AutoincrementedIdTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\CreatedAtTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\UpdatedAtTrait;
|
||||
use MailPoetVendor\Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
/**
|
||||
* @ORM\Entity()
|
||||
* @ORM\Table(name="feature_flags", uniqueConstraints={@ORM\UniqueConstraint(name="name",columns={"name"})})
|
||||
*/
|
||||
class FeatureFlagEntity {
|
||||
use AutoincrementedIdTrait;
|
||||
use CreatedAtTrait;
|
||||
use UpdatedAtTrait;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string", nullable=false, unique=true)
|
||||
* @var string
|
||||
*/
|
||||
private $name;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="boolean", nullable=true)
|
||||
* @var bool|null
|
||||
*/
|
||||
private $value;
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @param bool|null $value
|
||||
*/
|
||||
public function __construct(
|
||||
$name,
|
||||
$value = null
|
||||
) {
|
||||
$this->name = $name;
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
/** @return string */
|
||||
public function getName() {
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/** @param string $name */
|
||||
public function setName($name) {
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
/** @return bool|null */
|
||||
public function getValue() {
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
/** @param bool|null $value */
|
||||
public function setValue($value) {
|
||||
$this->value = $value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,213 @@
|
||||
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
|
||||
|
||||
namespace MailPoet\Entities;
|
||||
|
||||
if (!defined('ABSPATH')) exit;
|
||||
|
||||
|
||||
use MailPoet\Doctrine\EntityTraits\AutoincrementedIdTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\CreatedAtTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\DeletedAtTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\UpdatedAtTrait;
|
||||
use MailPoetVendor\Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
/**
|
||||
* @ORM\Entity()
|
||||
* @ORM\Table(name="forms")
|
||||
*/
|
||||
class FormEntity {
|
||||
use AutoincrementedIdTrait;
|
||||
use CreatedAtTrait;
|
||||
use UpdatedAtTrait;
|
||||
use DeletedAtTrait;
|
||||
|
||||
const DISPLAY_TYPE_BELOW_POST = 'below_posts';
|
||||
const DISPLAY_TYPE_FIXED_BAR = 'fixed_bar';
|
||||
const DISPLAY_TYPE_POPUP = 'popup';
|
||||
const DISPLAY_TYPE_SLIDE_IN = 'slide_in';
|
||||
const DISPLAY_TYPE_OTHERS = 'others';
|
||||
|
||||
const STATUS_ENABLED = 'enabled';
|
||||
const STATUS_DISABLED = 'disabled';
|
||||
|
||||
const HTML_BLOCK_TYPE = 'html';
|
||||
const HEADING_BLOCK_TYPE = 'heading';
|
||||
const IMAGE_BLOCK_TYPE = 'image';
|
||||
const PARAGRAPH_BLOCK_TYPE = 'paragraph';
|
||||
const DIVIDER_BLOCK_TYPE = 'divider';
|
||||
const CHECKBOX_BLOCK_TYPE = 'checkbox';
|
||||
const RADIO_BLOCK_TYPE = 'radio';
|
||||
const SEGMENT_SELECTION_BLOCK_TYPE = 'segment';
|
||||
const DATE_BLOCK_TYPE = 'date';
|
||||
const SELECT_BLOCK_TYPE = 'select';
|
||||
const TEXT_BLOCK_TYPE = 'text';
|
||||
const TEXTAREA_BLOCK_TYPE = 'textarea';
|
||||
const SUBMIT_BLOCK_TYPE = 'submit';
|
||||
const COLUMNS_BLOCK_TYPE = 'columns';
|
||||
const COLUMN_BLOCK_TYPE = 'column';
|
||||
|
||||
public const FORM_FIELD_TYPES = [
|
||||
self::CHECKBOX_BLOCK_TYPE,
|
||||
self::RADIO_BLOCK_TYPE,
|
||||
self::SEGMENT_SELECTION_BLOCK_TYPE,
|
||||
self::DATE_BLOCK_TYPE,
|
||||
self::SELECT_BLOCK_TYPE,
|
||||
self::TEXT_BLOCK_TYPE,
|
||||
self::TEXTAREA_BLOCK_TYPE,
|
||||
];
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string")
|
||||
* @var string
|
||||
*/
|
||||
private $name;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="serialized_array")
|
||||
* @var array|null
|
||||
*/
|
||||
private $body;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string")
|
||||
* @var string
|
||||
*/
|
||||
private $status;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="serialized_array")
|
||||
* @var array|null
|
||||
*/
|
||||
private $settings;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string", nullable=true)
|
||||
* @var string|null
|
||||
*/
|
||||
private $styles;
|
||||
|
||||
public function __construct(
|
||||
$name
|
||||
) {
|
||||
$this->name = $name;
|
||||
$this->status = self::STATUS_ENABLED;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getName() {
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array|null
|
||||
*/
|
||||
public function getBody() {
|
||||
return $this->body;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array|null
|
||||
*/
|
||||
public function getSettings() {
|
||||
return $this->settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
public function getStyles() {
|
||||
return $this->styles;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
*/
|
||||
public function setName($name) {
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array|null $body
|
||||
*/
|
||||
public function setBody($body) {
|
||||
$this->body = $body;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array|null $settings
|
||||
*/
|
||||
public function setSettings($settings) {
|
||||
$this->settings = $settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|null $styles
|
||||
*/
|
||||
public function setStyles($styles) {
|
||||
$this->styles = $styles;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $status
|
||||
*/
|
||||
public function setStatus(string $status) {
|
||||
$this->status = $status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getStatus(): string {
|
||||
return $this->status;
|
||||
}
|
||||
|
||||
public function toArray(): array {
|
||||
return [
|
||||
'id' => $this->getId(),
|
||||
'name' => $this->getName(),
|
||||
'body' => $this->getBody(),
|
||||
'settings' => $this->getSettings(),
|
||||
'styles' => $this->getStyles(),
|
||||
'status' => $this->getStatus(),
|
||||
'created_at' => $this->getCreatedAt(),
|
||||
'updated_at' => $this->getUpdatedAt(),
|
||||
'deleted_at' => $this->getDeletedAt(),
|
||||
];
|
||||
}
|
||||
|
||||
public function getBlocksByTypes(array $types, array $blocks = null): array {
|
||||
$found = [];
|
||||
if ($blocks === null) {
|
||||
$blocks = $this->getBody() ?? [];
|
||||
}
|
||||
foreach ($blocks as $block) {
|
||||
if (isset($block['type']) && in_array($block['type'], $types, true)) {
|
||||
$found[] = $block;
|
||||
}
|
||||
if (isset($block['body']) && is_array($block['body']) && !empty($block['body'])) {
|
||||
$found = array_merge($found, $this->getBlocksByTypes($types, $block['body']));
|
||||
}
|
||||
}
|
||||
return $found;
|
||||
}
|
||||
|
||||
public function getSegmentBlocksSegmentIds(): array {
|
||||
$listSelectionBlocks = $this->getBlocksByTypes([FormEntity::SEGMENT_SELECTION_BLOCK_TYPE]);
|
||||
$listSelection = [];
|
||||
foreach ($listSelectionBlocks as $listSelectionBlock) {
|
||||
$listSelection = array_unique(
|
||||
array_merge(
|
||||
$listSelection,
|
||||
array_column($listSelectionBlock['params']['values'] ?? [], 'id')
|
||||
)
|
||||
);
|
||||
}
|
||||
return $listSelection;
|
||||
}
|
||||
|
||||
public function getSettingsSegmentIds(): array {
|
||||
return $this->settings['segments'] ?? [];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
<?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 MailPoetVendor\Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
/**
|
||||
* @ORM\Entity()
|
||||
* @ORM\Table(name="log")
|
||||
*/
|
||||
class LogEntity {
|
||||
use AutoincrementedIdTrait;
|
||||
use CreatedAtTrait;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string", nullable=true)
|
||||
* @var string|null
|
||||
*/
|
||||
private $name;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="integer", nullable=true)
|
||||
* @var int|null
|
||||
*/
|
||||
private $level;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string", nullable=true)
|
||||
* @var string|null
|
||||
*/
|
||||
private $message;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string", nullable=true)
|
||||
* @var string|null
|
||||
*/
|
||||
private $rawMessage;
|
||||
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string", nullable=true)
|
||||
* @var string|null
|
||||
*/
|
||||
private $context;
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
public function getName(): ?string {
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int|null
|
||||
*/
|
||||
public function getLevel(): ?int {
|
||||
return $this->level;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
public function getMessage(): ?string {
|
||||
return $this->message;
|
||||
}
|
||||
|
||||
public function getRawMessage(): ?string {
|
||||
return $this->rawMessage;
|
||||
}
|
||||
|
||||
public function getContext(): ?array {
|
||||
return (array)json_decode($this->context ?? '{}', true);
|
||||
}
|
||||
|
||||
public function setName(?string $name): void {
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
public function setLevel(?int $level): void {
|
||||
$this->level = $level;
|
||||
}
|
||||
|
||||
public function setMessage(?string $message): void {
|
||||
$this->message = $message;
|
||||
}
|
||||
|
||||
public function setCreatedAt(DateTimeInterface $createdAt): void {
|
||||
$this->createdAt = $createdAt;
|
||||
}
|
||||
|
||||
public function setRawMessage(string $message): void {
|
||||
$this->rawMessage = $message;
|
||||
}
|
||||
|
||||
public function setContext(array $context): void {
|
||||
$str = json_encode($context);
|
||||
if ($str) {
|
||||
$this->context = $str;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,658 @@
|
||||
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
|
||||
|
||||
namespace MailPoet\Entities;
|
||||
|
||||
if (!defined('ABSPATH')) exit;
|
||||
|
||||
|
||||
use DateTimeInterface;
|
||||
use MailPoet\AutomaticEmails\WooCommerce\Events\AbandonedCart;
|
||||
use MailPoet\Doctrine\EntityTraits\AutoincrementedIdTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\CreatedAtTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\DeletedAtTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\SafeToOneAssociationLoadTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\UpdatedAtTrait;
|
||||
use MailPoet\Util\Helpers;
|
||||
use MailPoetVendor\Carbon\Carbon;
|
||||
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="newsletters")
|
||||
*/
|
||||
class NewsletterEntity {
|
||||
// types
|
||||
const TYPE_AUTOMATION = 'automation';
|
||||
const TYPE_AUTOMATION_NOTIFICATION = 'automation_notification';
|
||||
const TYPE_AUTOMATION_TRANSACTIONAL = 'automation_transactional';
|
||||
const TYPE_STANDARD = 'standard';
|
||||
const TYPE_NOTIFICATION = 'notification';
|
||||
const TYPE_NOTIFICATION_HISTORY = 'notification_history';
|
||||
const TYPE_RE_ENGAGEMENT = 're_engagement';
|
||||
const TYPE_WC_TRANSACTIONAL_EMAIL = 'wc_transactional';
|
||||
const TYPE_CONFIRMATION_EMAIL_CUSTOMIZER = 'confirmation_email';
|
||||
|
||||
// legacy types, replaced by automations
|
||||
const TYPE_AUTOMATIC = 'automatic';
|
||||
const TYPE_WELCOME = 'welcome';
|
||||
|
||||
// standard newsletters
|
||||
const STATUS_DRAFT = 'draft';
|
||||
const STATUS_SCHEDULED = 'scheduled';
|
||||
const STATUS_SENDING = 'sending';
|
||||
const STATUS_SENT = 'sent';
|
||||
const STATUS_CORRUPT = 'corrupt';
|
||||
|
||||
/**
|
||||
* Newsletters that their body HTML can get re-generated
|
||||
* @see NewsletterSaveController::updateQueue
|
||||
*/
|
||||
const TYPES_WITH_RESETTABLE_BODY = [
|
||||
NewsletterEntity::TYPE_STANDARD,
|
||||
];
|
||||
|
||||
/**
|
||||
* Newsletters that have additional restrictions for activation and sending
|
||||
*/
|
||||
const CAMPAIGN_TYPES = [
|
||||
NewsletterEntity::TYPE_STANDARD,
|
||||
NewsletterEntity::TYPE_NOTIFICATION,
|
||||
NewsletterEntity::TYPE_NOTIFICATION_HISTORY,
|
||||
NewsletterEntity::TYPE_RE_ENGAGEMENT,
|
||||
];
|
||||
|
||||
// automatic newsletters status
|
||||
const STATUS_ACTIVE = 'active';
|
||||
|
||||
/**
|
||||
* Newsletters that use status "active"
|
||||
*/
|
||||
const ACTIVABLE_EMAILS = [
|
||||
NewsletterEntity::TYPE_NOTIFICATION,
|
||||
NewsletterEntity::TYPE_WELCOME,
|
||||
NewsletterEntity::TYPE_AUTOMATIC,
|
||||
NewsletterEntity::TYPE_AUTOMATION,
|
||||
NewsletterEntity::TYPE_RE_ENGAGEMENT,
|
||||
];
|
||||
|
||||
use AutoincrementedIdTrait;
|
||||
use CreatedAtTrait;
|
||||
use UpdatedAtTrait;
|
||||
use DeletedAtTrait;
|
||||
use SafeToOneAssociationLoadTrait;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string", nullable=true)
|
||||
* @var string|null
|
||||
*/
|
||||
private $hash;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string")
|
||||
* @var string
|
||||
*/
|
||||
private $subject;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string")
|
||||
* @Assert\NotBlank()
|
||||
* @var string
|
||||
*/
|
||||
private $type;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string")
|
||||
* @var string
|
||||
*/
|
||||
private $senderAddress = '';
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string")
|
||||
* @var string
|
||||
*/
|
||||
private $senderName = '';
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string")
|
||||
* @var string
|
||||
*/
|
||||
private $status = self::STATUS_DRAFT;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string")
|
||||
* @var string
|
||||
*/
|
||||
private $replyToAddress = '';
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string")
|
||||
* @var string
|
||||
*/
|
||||
private $replyToName = '';
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string")
|
||||
* @var string
|
||||
*/
|
||||
private $preheader = '';
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="json", nullable=true)
|
||||
* @var array|null
|
||||
*/
|
||||
private $body;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="datetimetz", nullable=true)
|
||||
* @var DateTimeInterface|null
|
||||
*/
|
||||
private $sentAt;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string", nullable=true)
|
||||
* @var string|null
|
||||
*/
|
||||
private $unsubscribeToken;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string")
|
||||
* @var string
|
||||
*/
|
||||
private $gaCampaign = '';
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="MailPoet\Entities\NewsletterEntity")
|
||||
* @var NewsletterEntity|null
|
||||
*/
|
||||
private $parent;
|
||||
|
||||
/**
|
||||
* @ORM\OneToMany(targetEntity="MailPoet\Entities\NewsletterEntity", mappedBy="parent", fetch="EXTRA_LAZY")
|
||||
* @var ArrayCollection<int, NewsletterEntity>
|
||||
*/
|
||||
private $children;
|
||||
|
||||
/**
|
||||
* @ORM\OneToMany(targetEntity="MailPoet\Entities\NewsletterSegmentEntity", mappedBy="newsletter", orphanRemoval=true)
|
||||
* @var ArrayCollection<int, NewsletterSegmentEntity>
|
||||
*/
|
||||
private $newsletterSegments;
|
||||
|
||||
/**
|
||||
* @ORM\OneToMany(targetEntity="MailPoet\Entities\NewsletterOptionEntity", mappedBy="newsletter", orphanRemoval=true)
|
||||
* @var ArrayCollection<int, NewsletterOptionEntity>
|
||||
*/
|
||||
private $options;
|
||||
|
||||
/**
|
||||
* @ORM\OneToMany(targetEntity="MailPoet\Entities\SendingQueueEntity", mappedBy="newsletter")
|
||||
* @var ArrayCollection<int, SendingQueueEntity>
|
||||
*/
|
||||
private $queues;
|
||||
|
||||
/**
|
||||
* @ORM\OneToOne(targetEntity="MailPoet\Entities\WpPostEntity")
|
||||
* @ORM\JoinColumn(name="wp_post_id", referencedColumnName="ID", nullable=true)
|
||||
* @var WpPostEntity|null
|
||||
*/
|
||||
private $wpPost;
|
||||
|
||||
public function __construct() {
|
||||
$this->children = new ArrayCollection();
|
||||
$this->newsletterSegments = new ArrayCollection();
|
||||
$this->options = new ArrayCollection();
|
||||
$this->queues = 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 2026-01-01
|
||||
*/
|
||||
public function __get($key) {
|
||||
$getterName = 'get' . Helpers::underscoreToCamelCase($key, $capitaliseFirstChar = true);
|
||||
$callable = [$this, $getterName];
|
||||
if (is_callable($callable)) {
|
||||
// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_trigger_error -- Intended for deprecation warnings
|
||||
trigger_error(
|
||||
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- if the function is callable, it's safe to output
|
||||
"Direct access to \$newsletter->{$key} is deprecated and will be removed after 2026-01-01. Use \$newsletter->{$getterName}() instead.",
|
||||
E_USER_DEPRECATED
|
||||
);
|
||||
return call_user_func($callable);
|
||||
}
|
||||
}
|
||||
|
||||
public function __clone() {
|
||||
// reset ID
|
||||
$this->id = null;
|
||||
$this->newsletterSegments = new ArrayCollection();
|
||||
$this->children = new ArrayCollection();
|
||||
$this->options = new ArrayCollection();
|
||||
$this->queues = new ArrayCollection();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
public function getHash() {
|
||||
return $this->hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|null $hash
|
||||
*/
|
||||
public function setHash($hash) {
|
||||
$this->hash = $hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getSubject() {
|
||||
return $this->subject;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $subject
|
||||
*/
|
||||
public function setSubject($subject) {
|
||||
$this->subject = $subject;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getType() {
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $type
|
||||
*/
|
||||
public function setType($type) {
|
||||
$this->type = $type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getSenderAddress() {
|
||||
return $this->senderAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $senderAddress
|
||||
*/
|
||||
public function setSenderAddress($senderAddress) {
|
||||
$this->senderAddress = $senderAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getSenderName() {
|
||||
return $this->senderName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $senderName
|
||||
*/
|
||||
public function setSenderName($senderName) {
|
||||
$this->senderName = $senderName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getStatus() {
|
||||
return $this->status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $status
|
||||
*/
|
||||
public function setStatus($status) {
|
||||
$this->status = $status;
|
||||
|
||||
// activate/deactivate unfinished tasks
|
||||
$newTaskStatus = null;
|
||||
if (($status === self::STATUS_DRAFT) && $this->canBeSetActive()) {
|
||||
$newTaskStatus = ScheduledTaskEntity::STATUS_PAUSED;
|
||||
}
|
||||
if (($status === self::STATUS_ACTIVE) && $this->canBeSetActive()) {
|
||||
$newTaskStatus = ScheduledTaskEntity::STATUS_SCHEDULED;
|
||||
}
|
||||
|
||||
if (!$newTaskStatus) return;
|
||||
|
||||
$queues = $this->getUnfinishedQueues();
|
||||
|
||||
foreach ($queues as $queue) {
|
||||
/** @var SendingQueueEntity $queue */
|
||||
$task = $queue->getTask();
|
||||
if ($task === null) continue;
|
||||
|
||||
$scheduled = new Carbon($task->getScheduledAt());
|
||||
if ($scheduled < (new Carbon())->subDays(30)) continue;
|
||||
|
||||
if (($status === self::STATUS_DRAFT) && ($task->getStatus() !== ScheduledTaskEntity::STATUS_SCHEDULED)) continue;
|
||||
if (($status === self::STATUS_ACTIVE) && ($task->getStatus() !== ScheduledTaskEntity::STATUS_PAUSED)) continue;
|
||||
|
||||
$task->setStatus($newTaskStatus);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getReplyToAddress() {
|
||||
return $this->replyToAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $replyToAddress
|
||||
*/
|
||||
public function setReplyToAddress($replyToAddress) {
|
||||
$this->replyToAddress = $replyToAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getReplyToName() {
|
||||
return $this->replyToName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $replyToName
|
||||
*/
|
||||
public function setReplyToName($replyToName) {
|
||||
$this->replyToName = $replyToName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getPreheader() {
|
||||
return $this->preheader;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $preheader
|
||||
*/
|
||||
public function setPreheader($preheader) {
|
||||
$this->preheader = $preheader;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array|null
|
||||
*/
|
||||
public function getBody() {
|
||||
return $this->body;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array|null $body
|
||||
*/
|
||||
public function setBody($body) {
|
||||
$this->body = $body;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return DateTimeInterface|null
|
||||
*/
|
||||
public function getSentAt() {
|
||||
return $this->sentAt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param DateTimeInterface|null $sentAt
|
||||
*/
|
||||
public function setSentAt($sentAt) {
|
||||
$this->sentAt = $sentAt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
public function getUnsubscribeToken() {
|
||||
return $this->unsubscribeToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getGaCampaign() {
|
||||
return $this->gaCampaign;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $gaCampaign
|
||||
*/
|
||||
public function setGaCampaign($gaCampaign) {
|
||||
$this->gaCampaign = $gaCampaign;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|null $unsubscribeToken
|
||||
*/
|
||||
public function setUnsubscribeToken($unsubscribeToken) {
|
||||
$this->unsubscribeToken = $unsubscribeToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return NewsletterEntity|null
|
||||
*/
|
||||
public function getParent() {
|
||||
$this->safelyLoadToOneAssociation('parent');
|
||||
return $this->parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param NewsletterEntity|null $parent
|
||||
*/
|
||||
public function setParent($parent) {
|
||||
$this->parent = $parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ArrayCollection<int, NewsletterEntity>
|
||||
*/
|
||||
public function getChildren() {
|
||||
return $this->children;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ArrayCollection<int, NewsletterSegmentEntity>
|
||||
*/
|
||||
public function getNewsletterSegments() {
|
||||
return $this->newsletterSegments;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int[]
|
||||
*/
|
||||
public function getSegmentIds() {
|
||||
return array_filter($this->newsletterSegments->map(function(NewsletterSegmentEntity $newsletterSegment = null) {
|
||||
if (!$newsletterSegment) return null;
|
||||
$segment = $newsletterSegment->getSegment();
|
||||
return $segment ? (int)$segment->getId() : null;
|
||||
})->toArray());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ArrayCollection<int, NewsletterOptionEntity>
|
||||
*/
|
||||
public function getOptions() {
|
||||
return $this->options;
|
||||
}
|
||||
|
||||
public function getOption(string $name): ?NewsletterOptionEntity {
|
||||
$option = $this->options->filter(function (NewsletterOptionEntity $option = null) use ($name): bool {
|
||||
if (!$option) return false;
|
||||
return ($field = $option->getOptionField()) ? $field->getName() === $name : false;
|
||||
})->first();
|
||||
return $option ?: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, mixed> Associative array of newsletter option values with option names as keys
|
||||
*/
|
||||
public function getOptionsAsArray(): array {
|
||||
$optionsArray = [];
|
||||
foreach ($this->options as $option) {
|
||||
$name = $option->getName();
|
||||
if (!$name) {
|
||||
continue;
|
||||
}
|
||||
$optionsArray[$name] = $option->getValue();
|
||||
}
|
||||
return $optionsArray;
|
||||
}
|
||||
|
||||
public function getOptionValue(string $name) {
|
||||
$option = $this->getOption($name);
|
||||
return $option ? $option->getValue() : null;
|
||||
}
|
||||
|
||||
public function getFilterSegmentId(): ?int {
|
||||
$optionValue = $this->getOptionValue(NewsletterOptionFieldEntity::NAME_FILTER_SEGMENT_ID);
|
||||
if ($optionValue) {
|
||||
return (int)$optionValue;
|
||||
}
|
||||
$parentNewsletter = $this->getParent();
|
||||
if ($parentNewsletter instanceof NewsletterEntity && $this->getId() !== $parentNewsletter->getId()) {
|
||||
return $parentNewsletter->getFilterSegmentId();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ArrayCollection<int, SendingQueueEntity>
|
||||
*/
|
||||
public function getQueues() {
|
||||
return $this->queues;
|
||||
}
|
||||
|
||||
public function getLatestQueue(): ?SendingQueueEntity {
|
||||
$criteria = new Criteria();
|
||||
$criteria->orderBy(['id' => Criteria::DESC]);
|
||||
$criteria->setMaxResults(1);
|
||||
return $this->queues->matching($criteria)->first() ?: null;
|
||||
}
|
||||
|
||||
public function getLastUpdatedQueue(): ?SendingQueueEntity {
|
||||
$criteria = new Criteria();
|
||||
$criteria->orderBy(['updatedAt' => Criteria::DESC]);
|
||||
$criteria->setMaxResults(1);
|
||||
return $this->queues->matching($criteria)->first() ?: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection<int, SendingQueueEntity>
|
||||
*/
|
||||
public function getUnfinishedQueues(): Collection {
|
||||
$criteria = new Criteria();
|
||||
$expr = Criteria::expr();
|
||||
$criteria->where($expr->neq('countToProcess', 0));
|
||||
return $this->queues->matching($criteria);
|
||||
}
|
||||
|
||||
public function getGlobalStyle(string $category, string $style): ?string {
|
||||
$body = $this->getBody();
|
||||
if ($body === null) {
|
||||
return null;
|
||||
}
|
||||
return $body['globalStyles'][$category][$style] ?? null;
|
||||
}
|
||||
|
||||
public function setGlobalStyle(string $category, string $style, $value): void {
|
||||
$body = $this->getBody();
|
||||
if ($body === null) {
|
||||
return;
|
||||
}
|
||||
$this->body['globalStyles'][$category][$style] = $value;
|
||||
}
|
||||
|
||||
public function getProcessedAt(): ?DateTimeInterface {
|
||||
$processedAt = null;
|
||||
$queue = $this->getLatestQueue();
|
||||
|
||||
if ($queue instanceof SendingQueueEntity) {
|
||||
$task = $queue->getTask();
|
||||
|
||||
if ($task instanceof ScheduledTaskEntity) {
|
||||
$processedAt = $task->getProcessedAt();
|
||||
}
|
||||
}
|
||||
|
||||
return $processedAt;
|
||||
}
|
||||
|
||||
public function getContent(): string {
|
||||
$content = $this->getBody()['content'] ?? '';
|
||||
return json_encode($content) ?: '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Only some types of newsletters can be set as sent. Some others are just active or draft.
|
||||
*/
|
||||
public function canBeSetSent(): bool {
|
||||
return in_array($this->getType(), [self::TYPE_NOTIFICATION_HISTORY, self::TYPE_STANDARD], true);
|
||||
}
|
||||
|
||||
public function canBeSetActive(): bool {
|
||||
return in_array($this->getType(), self::ACTIVABLE_EMAILS, true);
|
||||
}
|
||||
|
||||
public function getWpPost(): ?WpPostEntity {
|
||||
$this->safelyLoadToOneAssociation('wpPost');
|
||||
return $this->wpPost;
|
||||
}
|
||||
|
||||
public function setWpPost(?WpPostEntity $wpPostEntity): void {
|
||||
$this->wpPost = $wpPostEntity;
|
||||
}
|
||||
|
||||
public function getWpPostId(): ?int {
|
||||
$wpPost = $this->wpPost;
|
||||
return $wpPost ? $wpPost->getId() : null;
|
||||
}
|
||||
|
||||
public function getCampaignName(): ?string {
|
||||
$wpPost = $this->getWpPost();
|
||||
if (!$wpPost) {
|
||||
return null;
|
||||
}
|
||||
return $wpPost->getPostTitle();
|
||||
}
|
||||
|
||||
/**
|
||||
* Used for cases when we present newsletter by name.
|
||||
* Newsletters created via legacy editor have only subjects.
|
||||
*/
|
||||
public function getCampaignNameOrSubject(): string {
|
||||
$campaignName = $this->getCampaignName();
|
||||
return $campaignName ?: $this->getSubject();
|
||||
}
|
||||
|
||||
public function isTransactional(): bool {
|
||||
|
||||
// Legacy Abandoned Cart emails are transactional
|
||||
if (
|
||||
$this->getType() === NewsletterEntity::TYPE_AUTOMATIC
|
||||
&& $this->getOptionValue(NewsletterOptionFieldEntity::NAME_EVENT) === AbandonedCart::SLUG
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return in_array($this->getType(), [
|
||||
NewsletterEntity::TYPE_AUTOMATION_TRANSACTIONAL,
|
||||
NewsletterEntity::TYPE_WC_TRANSACTIONAL_EMAIL,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
|
||||
|
||||
namespace MailPoet\Entities;
|
||||
|
||||
if (!defined('ABSPATH')) exit;
|
||||
|
||||
|
||||
use MailPoet\Doctrine\EntityTraits\AutoincrementedIdTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\CreatedAtTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\SafeToOneAssociationLoadTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\UpdatedAtTrait;
|
||||
use MailPoetVendor\Doctrine\Common\Collections\ArrayCollection;
|
||||
use MailPoetVendor\Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
/**
|
||||
* @ORM\Entity()
|
||||
* @ORM\Table(name="newsletter_links")
|
||||
*/
|
||||
class NewsletterLinkEntity {
|
||||
use AutoincrementedIdTrait;
|
||||
use CreatedAtTrait;
|
||||
use UpdatedAtTrait;
|
||||
use SafeToOneAssociationLoadTrait;
|
||||
|
||||
public const UNSUBSCRIBE_LINK_SHORT_CODE = '[link:subscription_unsubscribe_url]';
|
||||
public const INSTANT_UNSUBSCRIBE_LINK_SHORT_CODE = '[link:subscription_instant_unsubscribe_url]';
|
||||
public const UNSUBSCRIBE_LINK_SHORTCODES = [self::UNSUBSCRIBE_LINK_SHORT_CODE, self::INSTANT_UNSUBSCRIBE_LINK_SHORT_CODE];
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="MailPoet\Entities\NewsletterEntity")
|
||||
* @ORM\JoinColumn(name="newsletter_id", referencedColumnName="id")
|
||||
* @var NewsletterEntity|null
|
||||
*/
|
||||
private $newsletter;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="MailPoet\Entities\SendingQueueEntity")
|
||||
* @ORM\JoinColumn(name="queue_id", referencedColumnName="id")
|
||||
* @var SendingQueueEntity|null
|
||||
*/
|
||||
private $queue;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string")
|
||||
* @var string
|
||||
*/
|
||||
private $url;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string")
|
||||
* @var string
|
||||
*/
|
||||
private $hash;
|
||||
|
||||
/**
|
||||
* Extra lazy is here for `getTotalClicksCount`.
|
||||
* If we didn't specify extra lazy the function would load all clicks and count them. This way it uses a single count query.
|
||||
* @ORM\OneToMany(targetEntity="MailPoet\Entities\StatisticsClickEntity", mappedBy="link", fetch="EXTRA_LAZY")
|
||||
*
|
||||
* @var ArrayCollection<int, StatisticsClickEntity>
|
||||
*/
|
||||
private $clicks;
|
||||
|
||||
public function __construct(
|
||||
NewsletterEntity $newsletter,
|
||||
SendingQueueEntity $queue,
|
||||
string $url,
|
||||
string $hash
|
||||
) {
|
||||
$this->newsletter = $newsletter;
|
||||
$this->queue = $queue;
|
||||
$this->url = $url;
|
||||
$this->hash = $hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return NewsletterEntity|null
|
||||
*/
|
||||
public function getNewsletter() {
|
||||
$this->safelyLoadToOneAssociation('newsletter');
|
||||
return $this->newsletter;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return SendingQueueEntity|null
|
||||
*/
|
||||
public function getQueue() {
|
||||
$this->safelyLoadToOneAssociation('queue');
|
||||
return $this->queue;
|
||||
}
|
||||
|
||||
public function getUrl(): string {
|
||||
return $this->url;
|
||||
}
|
||||
|
||||
public function getHash(): string {
|
||||
return $this->hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getTotalClicksCount() {
|
||||
return $this->clicks->count();
|
||||
}
|
||||
|
||||
public function toArray(): array {
|
||||
return [
|
||||
'id' => $this->getId(),
|
||||
'newsletter_id' => ($this->getNewsletter() instanceof NewsletterEntity) ? $this->getNewsletter()->getId() : null,
|
||||
'queue_id' => ($this->getQueue() instanceof SendingQueueEntity) ? $this->getQueue()->getId() : null,
|
||||
'url' => $this->getUrl(),
|
||||
'hash' => $this->getHash(),
|
||||
'created_at' => $this->getCreatedAt(),
|
||||
'updated_at' => $this->getUpdatedAt(),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
|
||||
|
||||
namespace MailPoet\Entities;
|
||||
|
||||
if (!defined('ABSPATH')) exit;
|
||||
|
||||
|
||||
use MailPoet\Doctrine\EntityTraits\AutoincrementedIdTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\CreatedAtTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\SafeToOneAssociationLoadTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\UpdatedAtTrait;
|
||||
use MailPoetVendor\Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
/**
|
||||
* @ORM\Entity()
|
||||
* @ORM\Table(name="newsletter_option")
|
||||
*/
|
||||
class NewsletterOptionEntity {
|
||||
use AutoincrementedIdTrait;
|
||||
use CreatedAtTrait;
|
||||
use UpdatedAtTrait;
|
||||
use SafeToOneAssociationLoadTrait;
|
||||
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="text", nullable=true)
|
||||
* @var string|null
|
||||
*/
|
||||
private $value;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="MailPoet\Entities\NewsletterEntity", inversedBy="options")
|
||||
* @var NewsletterEntity|null
|
||||
*/
|
||||
private $newsletter;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="MailPoet\Entities\NewsletterOptionFieldEntity")
|
||||
* @var NewsletterOptionFieldEntity|null
|
||||
*/
|
||||
private $optionField;
|
||||
|
||||
public function __construct(
|
||||
NewsletterEntity $newsletter,
|
||||
NewsletterOptionFieldEntity $optionField
|
||||
) {
|
||||
$this->newsletter = $newsletter;
|
||||
$this->optionField = $optionField;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
public function getValue() {
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
public function getName() {
|
||||
$optionField = $this->getOptionField();
|
||||
if ($optionField === null) {
|
||||
return null;
|
||||
}
|
||||
return $optionField->getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|null $value
|
||||
*/
|
||||
public function setValue($value) {
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return NewsletterEntity|null
|
||||
*/
|
||||
public function getNewsletter() {
|
||||
$this->safelyLoadToOneAssociation('newsletter');
|
||||
return $this->newsletter;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return NewsletterOptionFieldEntity|null
|
||||
*/
|
||||
public function getOptionField() {
|
||||
$this->safelyLoadToOneAssociation('optionField');
|
||||
return $this->optionField;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
|
||||
|
||||
namespace MailPoet\Entities;
|
||||
|
||||
if (!defined('ABSPATH')) exit;
|
||||
|
||||
|
||||
use MailPoet\Doctrine\EntityTraits\AutoincrementedIdTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\CreatedAtTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\UpdatedAtTrait;
|
||||
use MailPoetVendor\Doctrine\ORM\Mapping as ORM;
|
||||
use MailPoetVendor\Symfony\Component\Validator\Constraints as Assert;
|
||||
|
||||
/**
|
||||
* @ORM\Entity()
|
||||
* @ORM\Table(name="newsletter_option_fields")
|
||||
*/
|
||||
class NewsletterOptionFieldEntity {
|
||||
// names
|
||||
public const NAME_AFTER_TIME_NUMBER = 'afterTimeNumber';
|
||||
public const NAME_AFTER_TIME_TYPE = 'afterTimeType';
|
||||
public const NAME_EVENT = 'event';
|
||||
public const NAME_GROUP = 'group';
|
||||
public const NAME_INTERVAL_TYPE = 'intervalType';
|
||||
public const NAME_IS_SCHEDULED = 'isScheduled';
|
||||
public const NAME_META = 'meta';
|
||||
public const NAME_MONTH_DAY = 'monthDay';
|
||||
public const NAME_NTH_WEEK_DAY = 'nthWeekDay';
|
||||
public const NAME_ROLE = 'role';
|
||||
public const NAME_SCHEDULE = 'schedule';
|
||||
public const NAME_SCHEDULED_AT = 'scheduledAt';
|
||||
public const NAME_SEGMENT = 'segment';
|
||||
public const NAME_SEND_TO = 'sendTo';
|
||||
public const NAME_TIME_OF_DAY = 'timeOfDay';
|
||||
public const NAME_WEEK_DAY = 'weekDay';
|
||||
public const NAME_AUTOMATION_ID = 'automationId';
|
||||
public const NAME_AUTOMATION_STEP_ID = 'automationStepId';
|
||||
public const NAME_FILTER_SEGMENT_ID = 'filterSegmentId';
|
||||
|
||||
use AutoincrementedIdTrait;
|
||||
use CreatedAtTrait;
|
||||
use UpdatedAtTrait;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string")
|
||||
* @Assert\NotBlank()
|
||||
* @var string
|
||||
*/
|
||||
private $name;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string")
|
||||
* @Assert\NotBlank()
|
||||
* @var string
|
||||
*/
|
||||
private $newsletterType;
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getName() {
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
*/
|
||||
public function setName($name) {
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getNewsletterType() {
|
||||
return $this->newsletterType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $newsletterType
|
||||
*/
|
||||
public function setNewsletterType($newsletterType) {
|
||||
$this->newsletterType = $newsletterType;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
|
||||
|
||||
namespace MailPoet\Entities;
|
||||
|
||||
if (!defined('ABSPATH')) exit;
|
||||
|
||||
|
||||
use MailPoet\Doctrine\EntityTraits\AutoincrementedIdTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\CreatedAtTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\SafeToOneAssociationLoadTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\UpdatedAtTrait;
|
||||
use MailPoetVendor\Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
/**
|
||||
* @ORM\Entity()
|
||||
* @ORM\Table(name="newsletter_posts")
|
||||
*/
|
||||
class NewsletterPostEntity {
|
||||
use AutoincrementedIdTrait;
|
||||
use CreatedAtTrait;
|
||||
use UpdatedAtTrait;
|
||||
use SafeToOneAssociationLoadTrait;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="MailPoet\Entities\NewsletterEntity")
|
||||
* @var NewsletterEntity|null
|
||||
*/
|
||||
private $newsletter;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="integer")
|
||||
* @var int
|
||||
*/
|
||||
private $postId;
|
||||
|
||||
public function __construct(
|
||||
NewsletterEntity $newsletter,
|
||||
int $postId
|
||||
) {
|
||||
$this->newsletter = $newsletter;
|
||||
$this->postId = $postId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return NewsletterEntity|null
|
||||
*/
|
||||
public function getNewsletter() {
|
||||
$this->safelyLoadToOneAssociation('newsletter');
|
||||
return $this->newsletter;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getPostId(): int {
|
||||
return $this->postId;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
|
||||
|
||||
namespace MailPoet\Entities;
|
||||
|
||||
if (!defined('ABSPATH')) exit;
|
||||
|
||||
|
||||
use MailPoet\Doctrine\EntityTraits\AutoincrementedIdTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\CreatedAtTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\SafeToOneAssociationLoadTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\UpdatedAtTrait;
|
||||
use MailPoetVendor\Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
/**
|
||||
* @ORM\Entity()
|
||||
* @ORM\Table(name="newsletter_segment")
|
||||
*/
|
||||
class NewsletterSegmentEntity {
|
||||
use AutoincrementedIdTrait;
|
||||
use CreatedAtTrait;
|
||||
use UpdatedAtTrait;
|
||||
use SafeToOneAssociationLoadTrait;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="MailPoet\Entities\NewsletterEntity", inversedBy="newsletterSegments")
|
||||
* @var NewsletterEntity|null
|
||||
*/
|
||||
private $newsletter;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="MailPoet\Entities\SegmentEntity")
|
||||
* @var SegmentEntity|null
|
||||
*/
|
||||
private $segment;
|
||||
|
||||
public function __construct(
|
||||
NewsletterEntity $newsletter,
|
||||
SegmentEntity $segment
|
||||
) {
|
||||
$this->newsletter = $newsletter;
|
||||
$this->segment = $segment;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return NewsletterEntity|null
|
||||
*/
|
||||
public function getNewsletter() {
|
||||
$this->safelyLoadToOneAssociation('newsletter');
|
||||
return $this->newsletter;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return SegmentEntity|null
|
||||
*/
|
||||
public function getSegment() {
|
||||
$this->safelyLoadToOneAssociation('segment');
|
||||
return $this->segment;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
|
||||
|
||||
namespace MailPoet\Entities;
|
||||
|
||||
if (!defined('ABSPATH')) exit;
|
||||
|
||||
|
||||
use MailPoet\Doctrine\EntityTraits\AutoincrementedIdTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\CreatedAtTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\SafeToOneAssociationLoadTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\UpdatedAtTrait;
|
||||
use MailPoetVendor\Doctrine\ORM\Mapping as ORM;
|
||||
use MailPoetVendor\Symfony\Component\Validator\Constraints as Assert;
|
||||
|
||||
/**
|
||||
* @ORM\Entity()
|
||||
* @ORM\Table(name="newsletter_templates")
|
||||
*/
|
||||
class NewsletterTemplateEntity {
|
||||
use AutoincrementedIdTrait;
|
||||
use CreatedAtTrait;
|
||||
use UpdatedAtTrait;
|
||||
use SafeToOneAssociationLoadTrait;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="MailPoet\Entities\NewsletterEntity")
|
||||
* @var NewsletterEntity|null
|
||||
*/
|
||||
private $newsletter;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string")
|
||||
* @Assert\NotBlank()
|
||||
* @var string
|
||||
*/
|
||||
private $name;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string")
|
||||
* @var string
|
||||
*/
|
||||
private $categories = '[]';
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="json", nullable=true)
|
||||
* @Assert\NotBlank()
|
||||
* @var array|null
|
||||
*/
|
||||
private $body;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string", nullable=true)
|
||||
* @var string|null
|
||||
*/
|
||||
private $thumbnail;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string", nullable=true)
|
||||
* @var string|null
|
||||
*/
|
||||
private $thumbnailData;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="boolean")
|
||||
* @var bool
|
||||
*/
|
||||
private $readonly = false;
|
||||
|
||||
public function __construct(
|
||||
string $name
|
||||
) {
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return NewsletterEntity|null
|
||||
*/
|
||||
public function getNewsletter() {
|
||||
$this->safelyLoadToOneAssociation('newsletter');
|
||||
return $this->newsletter;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param NewsletterEntity|null $newsletter
|
||||
*/
|
||||
public function setNewsletter($newsletter) {
|
||||
$this->newsletter = $newsletter;
|
||||
}
|
||||
|
||||
public function getName(): string {
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function setName(string $name) {
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
public function getCategories(): string {
|
||||
return $this->categories;
|
||||
}
|
||||
|
||||
public function setCategories(string $categories) {
|
||||
$this->categories = $categories;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array|null
|
||||
*/
|
||||
public function getBody() {
|
||||
return $this->body;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array|null $body
|
||||
*/
|
||||
public function setBody($body) {
|
||||
$this->body = $body;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
public function getThumbnail() {
|
||||
return $this->thumbnail;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|null $thumbnail
|
||||
*/
|
||||
public function setThumbnail($thumbnail) {
|
||||
$this->thumbnail = $thumbnail;
|
||||
}
|
||||
|
||||
public function getThumbnailData(): ?string {
|
||||
return $this->thumbnailData;
|
||||
}
|
||||
|
||||
public function setThumbnailData(string $thumbnailData): void {
|
||||
$this->thumbnailData = $thumbnailData;
|
||||
}
|
||||
|
||||
public function getReadonly(): bool {
|
||||
return $this->readonly;
|
||||
}
|
||||
|
||||
public function setReadonly(bool $readonly) {
|
||||
$this->readonly = $readonly;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,264 @@
|
||||
<?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\SafeToOneAssociationLoadTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\UpdatedAtTrait;
|
||||
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;
|
||||
|
||||
/**
|
||||
* @ORM\Entity()
|
||||
* @ORM\Table(name="scheduled_tasks")
|
||||
*/
|
||||
class ScheduledTaskEntity {
|
||||
const STATUS_COMPLETED = 'completed';
|
||||
const STATUS_SCHEDULED = 'scheduled';
|
||||
const STATUS_CANCELLED = 'cancelled';
|
||||
const STATUS_PAUSED = 'paused';
|
||||
const STATUS_INVALID = 'invalid';
|
||||
const VIRTUAL_STATUS_RUNNING = 'running'; // For historical reasons this is stored as null in DB
|
||||
const PRIORITY_HIGH = 1;
|
||||
const PRIORITY_MEDIUM = 5;
|
||||
const PRIORITY_LOW = 10;
|
||||
const BASIC_RESCHEDULE_TIMEOUT = 5; // minutes
|
||||
const MAX_RESCHEDULE_TIMEOUT = 1440; // minutes
|
||||
|
||||
use AutoincrementedIdTrait;
|
||||
use CreatedAtTrait;
|
||||
use UpdatedAtTrait;
|
||||
use DeletedAtTrait;
|
||||
use SafeToOneAssociationLoadTrait;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string", nullable=true)
|
||||
* @var string|null
|
||||
*/
|
||||
private $type;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string", nullable=true)
|
||||
* @var string|null
|
||||
*/
|
||||
private $status;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="integer")
|
||||
* @var int
|
||||
*/
|
||||
private $priority = 0;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="datetimetz", nullable=true)
|
||||
* @var DateTimeInterface|null
|
||||
*/
|
||||
private $scheduledAt;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="datetimetz", nullable=true)
|
||||
* @var DateTimeInterface|null
|
||||
*/
|
||||
private $cancelledAt;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="datetimetz", nullable=true)
|
||||
* @var DateTimeInterface|null
|
||||
*/
|
||||
private $processedAt;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="json", nullable=true)
|
||||
* @var array|null
|
||||
*/
|
||||
private $meta;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="boolean", nullable=true)
|
||||
* @var bool|null
|
||||
*/
|
||||
private $inProgress;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="integer", options={"default" : 0})
|
||||
* @var int
|
||||
*/
|
||||
private $rescheduleCount = 0;
|
||||
|
||||
/**
|
||||
* @ORM\OneToMany(targetEntity="MailPoet\Entities\ScheduledTaskSubscriberEntity", mappedBy="task", fetch="EXTRA_LAZY")
|
||||
* @var Collection<int, ScheduledTaskSubscriberEntity>
|
||||
*/
|
||||
private $subscribers;
|
||||
|
||||
/**
|
||||
* @ORM\OneToOne(targetEntity="MailPoet\Entities\SendingQueueEntity", mappedBy="task", fetch="EAGER")
|
||||
* @var SendingQueueEntity|null
|
||||
*/
|
||||
private $sendingQueue;
|
||||
|
||||
public function __construct() {
|
||||
$this->subscribers = new ArrayCollection();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
public function getType() {
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|null $type
|
||||
*/
|
||||
public function setType($type) {
|
||||
$this->type = $type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
public function getStatus() {
|
||||
return $this->status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|null $status
|
||||
*/
|
||||
public function setStatus($status) {
|
||||
if ($status === self::VIRTUAL_STATUS_RUNNING) {
|
||||
$status = null;
|
||||
}
|
||||
$this->status = $status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getPriority() {
|
||||
return $this->priority;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $priority
|
||||
*/
|
||||
public function setPriority($priority) {
|
||||
$this->priority = $priority;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return DateTimeInterface|null
|
||||
*/
|
||||
public function getScheduledAt() {
|
||||
return $this->scheduledAt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param DateTimeInterface|null $scheduledAt
|
||||
*/
|
||||
public function setScheduledAt($scheduledAt) {
|
||||
$this->scheduledAt = $scheduledAt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return DateTimeInterface|null
|
||||
*/
|
||||
public function getCancelledAt() {
|
||||
return $this->cancelledAt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param DateTimeInterface|null $cancelledAt
|
||||
*/
|
||||
public function setCancelledAt($cancelledAt) {
|
||||
$this->cancelledAt = $cancelledAt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return DateTimeInterface|null
|
||||
*/
|
||||
public function getProcessedAt() {
|
||||
return $this->processedAt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param DateTimeInterface|null $processedAt
|
||||
*/
|
||||
public function setProcessedAt($processedAt) {
|
||||
$this->processedAt = $processedAt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array|null
|
||||
*/
|
||||
public function getMeta() {
|
||||
return $this->meta;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array|null $meta
|
||||
*/
|
||||
public function setMeta($meta) {
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool|null
|
||||
*/
|
||||
public function getInProgress() {
|
||||
return $this->inProgress;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool|null $inProgress
|
||||
*/
|
||||
public function setInProgress($inProgress) {
|
||||
$this->inProgress = $inProgress;
|
||||
}
|
||||
|
||||
public function getRescheduleCount(): int {
|
||||
return $this->rescheduleCount;
|
||||
}
|
||||
|
||||
public function setRescheduleCount(int $rescheduleCount) {
|
||||
$this->rescheduleCount = $rescheduleCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection<int, ScheduledTaskSubscriberEntity>
|
||||
*/
|
||||
public function getSubscribers(): Collection {
|
||||
return $this->subscribers;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $processed ScheduledTaskSubscriberEntity::PROCESSED_* constant
|
||||
* @return SubscriberEntity[]
|
||||
*/
|
||||
public function getSubscribersByProcessed(int $processed): array {
|
||||
$criteria = Criteria::create()
|
||||
->where(Criteria::expr()->eq('processed', $processed));
|
||||
$subscribers = $this->subscribers->matching($criteria)->map(function (ScheduledTaskSubscriberEntity $taskSubscriber = null): ?SubscriberEntity {
|
||||
if (!$taskSubscriber) return null;
|
||||
return $taskSubscriber->getSubscriber();
|
||||
});
|
||||
return array_filter($subscribers->toArray());
|
||||
}
|
||||
|
||||
public function getSendingQueue(): ?SendingQueueEntity {
|
||||
$this->safelyLoadToOneAssociation('sendingQueue');
|
||||
return $this->sendingQueue;
|
||||
}
|
||||
|
||||
public function setSendingQueue(SendingQueueEntity $sendingQueue): void {
|
||||
$this->sendingQueue = $sendingQueue;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
|
||||
|
||||
namespace MailPoet\Entities;
|
||||
|
||||
if (!defined('ABSPATH')) exit;
|
||||
|
||||
|
||||
use MailPoet\Doctrine\EntityTraits\CreatedAtTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\SafeToOneAssociationLoadTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\UpdatedAtTrait;
|
||||
use MailPoetVendor\Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
/**
|
||||
* @ORM\Entity()
|
||||
* @ORM\Table(name="scheduled_task_subscribers")
|
||||
*/
|
||||
class ScheduledTaskSubscriberEntity {
|
||||
const STATUS_UNPROCESSED = 0;
|
||||
const STATUS_PROCESSED = 1;
|
||||
|
||||
const FAIL_STATUS_OK = 0;
|
||||
const FAIL_STATUS_FAILED = 1;
|
||||
|
||||
const SENDING_STATUS_SENT = 'sent';
|
||||
const SENDING_STATUS_FAILED = 'failed';
|
||||
const SENDING_STATUS_UNPROCESSED = 'unprocessed';
|
||||
|
||||
use CreatedAtTrait;
|
||||
use UpdatedAtTrait;
|
||||
use SafeToOneAssociationLoadTrait;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="integer")
|
||||
* @var int
|
||||
*/
|
||||
private $processed;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="integer")
|
||||
* @var int
|
||||
*/
|
||||
private $failed;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="text", nullable=true)
|
||||
* @var string|null
|
||||
*/
|
||||
private $error;
|
||||
|
||||
/**
|
||||
* @ORM\Id @ORM\ManyToOne(targetEntity="MailPoet\Entities\ScheduledTaskEntity", inversedBy="subscribers")
|
||||
* @var ScheduledTaskEntity|null
|
||||
*/
|
||||
private $task;
|
||||
|
||||
/**
|
||||
* @ORM\Id @ORM\ManyToOne(targetEntity="MailPoet\Entities\SubscriberEntity", inversedBy="scheduledTaskSubscribers")
|
||||
* @var SubscriberEntity|null
|
||||
*/
|
||||
private $subscriber;
|
||||
|
||||
public function __construct(
|
||||
ScheduledTaskEntity $task,
|
||||
SubscriberEntity $subscriber,
|
||||
int $processed = 0,
|
||||
int $failed = 0,
|
||||
string $error = null
|
||||
) {
|
||||
$this->task = $task;
|
||||
$this->subscriber = $subscriber;
|
||||
$this->processed = $processed;
|
||||
$this->failed = $failed;
|
||||
$this->error = $error;
|
||||
}
|
||||
|
||||
public function getProcessed(): int {
|
||||
return $this->processed;
|
||||
}
|
||||
|
||||
public function setProcessed(int $processed) {
|
||||
$this->processed = $processed;
|
||||
}
|
||||
|
||||
public function getFailed(): int {
|
||||
return $this->failed;
|
||||
}
|
||||
|
||||
public function setFailed(int $failed) {
|
||||
$this->failed = $failed;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
public function getError() {
|
||||
return $this->error;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|null $error
|
||||
*/
|
||||
public function setError($error) {
|
||||
$this->error = $error;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ScheduledTaskEntity|null
|
||||
*/
|
||||
public function getTask() {
|
||||
$this->safelyLoadToOneAssociation('task');
|
||||
return $this->task;
|
||||
}
|
||||
|
||||
public function setTask(ScheduledTaskEntity $task) {
|
||||
$this->task = $task;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return SubscriberEntity|null
|
||||
*/
|
||||
public function getSubscriber() {
|
||||
$this->safelyLoadToOneAssociation('subscriber');
|
||||
return $this->subscriber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the ID of the subscriber without querying wp_mailpoet_subscribers.
|
||||
* $this->getSubscriber->getId() queries wp_mailpoet_subscribers because of
|
||||
* the way the SafeToOneAssociationLoadTrait works.
|
||||
*
|
||||
* @return int|null
|
||||
*/
|
||||
public function getSubscriberId() {
|
||||
if ($this->subscriber instanceof SubscriberEntity) {
|
||||
return $this->subscriber->getId();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function setSubscriber(SubscriberEntity $subscriber) {
|
||||
$this->subscriber = $subscriber;
|
||||
}
|
||||
|
||||
public function resetToUnprocessed() {
|
||||
$this->setError(null);
|
||||
$this->setProcessed(0);
|
||||
$this->setFailed(0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,196 @@
|
||||
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
|
||||
|
||||
namespace MailPoet\Entities;
|
||||
|
||||
if (!defined('ABSPATH')) exit;
|
||||
|
||||
|
||||
use MailPoet\Doctrine\EntityTraits\AutoincrementedIdTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\CreatedAtTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\DeletedAtTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\UpdatedAtTrait;
|
||||
use MailPoetVendor\Doctrine\Common\Collections\ArrayCollection;
|
||||
use MailPoetVendor\Doctrine\ORM\Mapping as ORM;
|
||||
use MailPoetVendor\Symfony\Component\Validator\Constraints as Assert;
|
||||
|
||||
/**
|
||||
* @ORM\Entity()
|
||||
* @ORM\Table(name="segments")
|
||||
*/
|
||||
class SegmentEntity {
|
||||
use AutoincrementedIdTrait;
|
||||
use CreatedAtTrait;
|
||||
use UpdatedAtTrait;
|
||||
use DeletedAtTrait;
|
||||
|
||||
const TYPE_WP_USERS = 'wp_users';
|
||||
const TYPE_WC_USERS = 'woocommerce_users';
|
||||
const TYPE_WC_MEMBERSHIPS = 'woocommerce_memberships';
|
||||
const TYPE_DEFAULT = 'default';
|
||||
const TYPE_DYNAMIC = 'dynamic';
|
||||
const TYPE_WITHOUT_LIST = 'without-list';
|
||||
|
||||
const NON_WOO_RELATED_TYPES = [
|
||||
self::TYPE_WP_USERS,
|
||||
self::TYPE_DEFAULT,
|
||||
self::TYPE_DYNAMIC,
|
||||
self::TYPE_WITHOUT_LIST,
|
||||
];
|
||||
|
||||
const SEGMENT_ENABLED = 'active';
|
||||
const SEGMENT_DISABLED = 'disabled';
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string")
|
||||
* @Assert\NotBlank()
|
||||
* @var string
|
||||
*/
|
||||
private $name;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string")
|
||||
* @var string
|
||||
*/
|
||||
private $type;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string")
|
||||
* @var string
|
||||
*/
|
||||
private $description;
|
||||
|
||||
/**
|
||||
* @ORM\OneToMany(targetEntity="MailPoet\Entities\DynamicSegmentFilterEntity", mappedBy="segment")
|
||||
* @var ArrayCollection<int, DynamicSegmentFilterEntity>
|
||||
*/
|
||||
private $dynamicFilters;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="float", nullable=true)
|
||||
* @var float|null
|
||||
*/
|
||||
private $averageEngagementScore;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="datetimetz", nullable=true)
|
||||
* @var \DateTimeInterface|null
|
||||
*/
|
||||
private $averageEngagementScoreUpdatedAt;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="boolean")
|
||||
* @var bool
|
||||
*/
|
||||
private $displayInManageSubscriptionPage = false;
|
||||
|
||||
public function __construct(
|
||||
string $name,
|
||||
string $type,
|
||||
string $description
|
||||
) {
|
||||
$this->name = $name;
|
||||
$this->type = $type;
|
||||
$this->description = $description;
|
||||
$this->dynamicFilters = new ArrayCollection();
|
||||
}
|
||||
|
||||
public function __clone() {
|
||||
// reset ID
|
||||
$this->id = null;
|
||||
$this->dynamicFilters = new ArrayCollection();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getName() {
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
*/
|
||||
public function setName($name) {
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getType() {
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $type
|
||||
*/
|
||||
public function setType($type) {
|
||||
$this->type = $type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getDescription() {
|
||||
return $this->description;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $description
|
||||
*/
|
||||
public function setDescription($description) {
|
||||
$this->description = $description;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ArrayCollection<int, DynamicSegmentFilterEntity>
|
||||
*/
|
||||
public function getDynamicFilters() {
|
||||
return $this->dynamicFilters;
|
||||
}
|
||||
|
||||
public function addDynamicFilter(DynamicSegmentFilterEntity $dynamicSegmentFilterEntity) {
|
||||
$this->dynamicFilters->add($dynamicSegmentFilterEntity);
|
||||
}
|
||||
|
||||
public function isStatic(): bool {
|
||||
return in_array($this->getType(), [self::TYPE_DEFAULT, self::TYPE_WP_USERS, self::TYPE_WC_USERS, self::TYPE_WC_MEMBERSHIPS], true);
|
||||
}
|
||||
|
||||
public function getAverageEngagementScore(): ?float {
|
||||
return $this->averageEngagementScore;
|
||||
}
|
||||
|
||||
public function setAverageEngagementScore(?float $averageEngagementScore): void {
|
||||
$this->averageEngagementScore = $averageEngagementScore;
|
||||
}
|
||||
|
||||
public function getAverageEngagementScoreUpdatedAt(): ?\DateTimeInterface {
|
||||
return $this->averageEngagementScoreUpdatedAt;
|
||||
}
|
||||
|
||||
public function setAverageEngagementScoreUpdatedAt(?\DateTimeInterface $averageEngagementScoreUpdatedAt): void {
|
||||
$this->averageEngagementScoreUpdatedAt = $averageEngagementScoreUpdatedAt;
|
||||
}
|
||||
|
||||
public function getDisplayInManageSubscriptionPage(): bool {
|
||||
return $this->displayInManageSubscriptionPage;
|
||||
}
|
||||
|
||||
public function setDisplayInManageSubscriptionPage(bool $state): void {
|
||||
$this->displayInManageSubscriptionPage = $state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns connect operand from the first filter, when doesn't exist, then returns a default value.
|
||||
* @return string
|
||||
*/
|
||||
public function getFiltersConnectOperator(): string {
|
||||
$firstFilter = $this->getDynamicFilters()->first();
|
||||
$filterData = $firstFilter ? $firstFilter->getFilterData() : null;
|
||||
if (!$firstFilter || !$filterData) {
|
||||
return DynamicSegmentFilterData::CONNECT_TYPE_AND;
|
||||
}
|
||||
return $filterData->getParam('connect') ?: DynamicSegmentFilterData::CONNECT_TYPE_AND;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,215 @@
|
||||
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
|
||||
|
||||
namespace MailPoet\Entities;
|
||||
|
||||
if (!defined('ABSPATH')) exit;
|
||||
|
||||
|
||||
use MailPoet\Doctrine\EntityTraits\AutoincrementedIdTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\CreatedAtTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\DeletedAtTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\SafeToOneAssociationLoadTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\UpdatedAtTrait;
|
||||
use MailPoet\Util\Helpers;
|
||||
use MailPoetVendor\Doctrine\ORM\Mapping as ORM;
|
||||
use MailPoetVendor\Symfony\Component\Validator\Constraints as Assert;
|
||||
|
||||
/**
|
||||
* @ORM\Entity()
|
||||
* @ORM\Table(name="sending_queues")
|
||||
*/
|
||||
class SendingQueueEntity {
|
||||
const STATUS_COMPLETED = 'completed';
|
||||
const STATUS_SCHEDULED = 'scheduled';
|
||||
const STATUS_PAUSED = 'paused';
|
||||
const PRIORITY_HIGH = 1;
|
||||
const PRIORITY_MEDIUM = 5;
|
||||
const PRIORITY_LOW = 10;
|
||||
|
||||
use AutoincrementedIdTrait;
|
||||
use CreatedAtTrait;
|
||||
use UpdatedAtTrait;
|
||||
use DeletedAtTrait;
|
||||
use SafeToOneAssociationLoadTrait;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="json_or_serialized")
|
||||
* @Assert\Type("array")
|
||||
* @Assert\Collection(
|
||||
* fields = {
|
||||
* "html" = @Assert\NotBlank(),
|
||||
* "text" = @Assert\NotBlank(),
|
||||
* }
|
||||
* )
|
||||
* @var array|null
|
||||
*/
|
||||
private $newsletterRenderedBody;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string", nullable=true)
|
||||
* @var string|null
|
||||
*/
|
||||
private $newsletterRenderedSubject;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="integer")
|
||||
* @var int
|
||||
*/
|
||||
private $countTotal = 0;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="integer")
|
||||
* @var int
|
||||
*/
|
||||
private $countProcessed = 0;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="integer")
|
||||
* @var int
|
||||
*/
|
||||
private $countToProcess = 0;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="json", nullable=true)
|
||||
* @var array|null
|
||||
*/
|
||||
private $meta;
|
||||
|
||||
/**
|
||||
* @ORM\OneToOne(targetEntity="MailPoet\Entities\ScheduledTaskEntity", fetch="EAGER")
|
||||
* @var ScheduledTaskEntity|null
|
||||
*/
|
||||
private $task;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="MailPoet\Entities\NewsletterEntity", inversedBy="queues")
|
||||
* @var NewsletterEntity|null
|
||||
*/
|
||||
private $newsletter;
|
||||
|
||||
/**
|
||||
* @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 2026-01-01
|
||||
*/
|
||||
public function __get($key) {
|
||||
$getterName = 'get' . Helpers::underscoreToCamelCase($key, $capitaliseFirstChar = true);
|
||||
$callable = [$this, $getterName];
|
||||
if (is_callable($callable)) {
|
||||
// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_trigger_error -- Intended for deprecation warnings
|
||||
trigger_error(
|
||||
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- if the function is callable, it's safe to output
|
||||
"Direct access to \$sendingQueue->{$key} is deprecated and will be removed after 2026-01-01. Use \$sendingQueue->{$getterName}() instead.",
|
||||
E_USER_DEPRECATED
|
||||
);
|
||||
return call_user_func($callable);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array|null
|
||||
*/
|
||||
public function getNewsletterRenderedBody() {
|
||||
return $this->newsletterRenderedBody;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array|null $newsletterRenderedBody
|
||||
*/
|
||||
public function setNewsletterRenderedBody($newsletterRenderedBody) {
|
||||
$this->newsletterRenderedBody = $newsletterRenderedBody;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
public function getNewsletterRenderedSubject() {
|
||||
return $this->newsletterRenderedSubject;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|null $newsletterRenderedSubject
|
||||
*/
|
||||
public function setNewsletterRenderedSubject($newsletterRenderedSubject) {
|
||||
$this->newsletterRenderedSubject = $newsletterRenderedSubject;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getCountTotal() {
|
||||
return $this->countTotal;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $countTotal
|
||||
*/
|
||||
public function setCountTotal($countTotal) {
|
||||
$this->countTotal = $countTotal;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getCountProcessed() {
|
||||
return $this->countProcessed;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $countProcessed
|
||||
*/
|
||||
public function setCountProcessed($countProcessed) {
|
||||
$this->countProcessed = $countProcessed;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getCountToProcess() {
|
||||
return $this->countToProcess;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $countToProcess
|
||||
*/
|
||||
public function setCountToProcess($countToProcess) {
|
||||
$this->countToProcess = $countToProcess;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array|null
|
||||
*/
|
||||
public function getMeta() {
|
||||
return $this->meta;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array|null $meta
|
||||
*/
|
||||
public function setMeta($meta) {
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ScheduledTaskEntity|null
|
||||
*/
|
||||
public function getTask() {
|
||||
$this->safelyLoadToOneAssociation('task');
|
||||
return $this->task;
|
||||
}
|
||||
|
||||
public function setTask(ScheduledTaskEntity $task) {
|
||||
$this->task = $task;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return NewsletterEntity|null
|
||||
*/
|
||||
public function getNewsletter() {
|
||||
$this->safelyLoadToOneAssociation('newsletter');
|
||||
return $this->newsletter;
|
||||
}
|
||||
|
||||
public function setNewsletter(NewsletterEntity $newsletter) {
|
||||
$this->newsletter = $newsletter;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
|
||||
|
||||
namespace MailPoet\Entities;
|
||||
|
||||
if (!defined('ABSPATH')) exit;
|
||||
|
||||
|
||||
use MailPoet\Doctrine\EntityTraits\AutoincrementedIdTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\CreatedAtTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\UpdatedAtTrait;
|
||||
use MailPoet\Util\Helpers;
|
||||
use MailPoetVendor\Doctrine\ORM\Mapping as ORM;
|
||||
use MailPoetVendor\Symfony\Component\Validator\Constraints as Assert;
|
||||
|
||||
/**
|
||||
* @ORM\Entity()
|
||||
* @ORM\Table(name="settings")
|
||||
*/
|
||||
class SettingEntity {
|
||||
use AutoincrementedIdTrait;
|
||||
use CreatedAtTrait;
|
||||
use UpdatedAtTrait;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string")
|
||||
* @Assert\NotBlank()
|
||||
* @var string
|
||||
*/
|
||||
private $name;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="text", nullable=true)
|
||||
* @var string|null
|
||||
*/
|
||||
private $value;
|
||||
|
||||
/** @return string */
|
||||
public function getName() {
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/** @param string $name */
|
||||
public function setName($name) {
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
/** @return mixed */
|
||||
public function getValue() {
|
||||
return $this->value !== null && is_serialized($this->value) ? unserialize($this->value) : $this->value;
|
||||
}
|
||||
|
||||
/** @param mixed $value */
|
||||
public function setValue($value) {
|
||||
$value = Helpers::recursiveTrim($value);
|
||||
if (is_array($value)) {
|
||||
$value = serialize($value);
|
||||
}
|
||||
$this->value = $value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace MailPoet\Entities;
|
||||
|
||||
if (!defined('ABSPATH')) exit;
|
||||
|
||||
|
||||
use MailPoet\Doctrine\EntityTraits\AutoincrementedIdTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\CreatedAtTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\SafeToOneAssociationLoadTrait;
|
||||
use MailPoetVendor\Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
/**
|
||||
* @ORM\Entity()
|
||||
* @ORM\Table(name="statistics_bounces")
|
||||
*/
|
||||
class StatisticsBounceEntity {
|
||||
|
||||
use AutoincrementedIdTrait;
|
||||
use CreatedAtTrait;
|
||||
use SafeToOneAssociationLoadTrait;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="MailPoet\Entities\NewsletterEntity")
|
||||
* @ORM\JoinColumn(name="newsletter_id", referencedColumnName="id")
|
||||
* @var NewsletterEntity|null
|
||||
*/
|
||||
private $newsletter;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="MailPoet\Entities\SendingQueueEntity")
|
||||
* @ORM\JoinColumn(name="queue_id", referencedColumnName="id")
|
||||
* @var SendingQueueEntity|null
|
||||
*/
|
||||
private $queue;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="MailPoet\Entities\SubscriberEntity")
|
||||
* @ORM\JoinColumn(name="subscriber_id", referencedColumnName="id")
|
||||
* @var SubscriberEntity|null
|
||||
*/
|
||||
private $subscriber;
|
||||
|
||||
public function __construct(
|
||||
NewsletterEntity $newsletter,
|
||||
SendingQueueEntity $queue,
|
||||
SubscriberEntity $subscriber
|
||||
) {
|
||||
$this->newsletter = $newsletter;
|
||||
$this->queue = $queue;
|
||||
$this->subscriber = $subscriber;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
|
||||
|
||||
namespace MailPoet\Entities;
|
||||
|
||||
if (!defined('ABSPATH')) exit;
|
||||
|
||||
|
||||
use MailPoet\Doctrine\EntityTraits\AutoincrementedIdTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\CreatedAtTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\SafeToOneAssociationLoadTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\UpdatedAtTrait;
|
||||
use MailPoetVendor\Doctrine\Common\Collections\ArrayCollection;
|
||||
use MailPoetVendor\Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
/**
|
||||
* @ORM\Entity()
|
||||
* @ORM\Table(name="statistics_clicks")
|
||||
*/
|
||||
class StatisticsClickEntity {
|
||||
use AutoincrementedIdTrait;
|
||||
use CreatedAtTrait;
|
||||
use UpdatedAtTrait;
|
||||
use SafeToOneAssociationLoadTrait;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="MailPoet\Entities\NewsletterEntity")
|
||||
* @ORM\JoinColumn(name="newsletter_id", referencedColumnName="id")
|
||||
* @var NewsletterEntity|null
|
||||
*/
|
||||
private $newsletter;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="MailPoet\Entities\SendingQueueEntity")
|
||||
* @ORM\JoinColumn(name="queue_id", referencedColumnName="id")
|
||||
* @var SendingQueueEntity|null
|
||||
*/
|
||||
private $queue;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="MailPoet\Entities\SubscriberEntity")
|
||||
* @ORM\JoinColumn(name="subscriber_id", referencedColumnName="id")
|
||||
* @var SubscriberEntity|null
|
||||
*/
|
||||
private $subscriber;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="MailPoet\Entities\NewsletterLinkEntity", inversedBy="clicks")
|
||||
* @var NewsletterLinkEntity|null
|
||||
*/
|
||||
private $link;
|
||||
|
||||
/**
|
||||
* @ORM\OneToMany(targetEntity="MailPoet\Entities\StatisticsWooCommercePurchaseEntity", mappedBy="click", fetch="EXTRA_LAZY")*
|
||||
* @var ArrayCollection<int, StatisticsWooCommercePurchaseEntity>
|
||||
*/
|
||||
private $wooCommercePurchases;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="MailPoet\Entities\UserAgentEntity")
|
||||
* @var UserAgentEntity|null
|
||||
*/
|
||||
private $userAgent;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="smallint")
|
||||
* @var int
|
||||
*/
|
||||
private $userAgentType = 0;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="integer")
|
||||
* @var int
|
||||
*/
|
||||
private $count;
|
||||
|
||||
public function __construct(
|
||||
NewsletterEntity $newsletter,
|
||||
SendingQueueEntity $queue,
|
||||
SubscriberEntity $subscriber,
|
||||
NewsletterLinkEntity $link,
|
||||
int $count
|
||||
) {
|
||||
$this->newsletter = $newsletter;
|
||||
$this->queue = $queue;
|
||||
$this->subscriber = $subscriber;
|
||||
$this->link = $link;
|
||||
$this->count = $count;
|
||||
$this->wooCommercePurchases = new ArrayCollection();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return NewsletterEntity|null
|
||||
*/
|
||||
public function getNewsletter() {
|
||||
$this->safelyLoadToOneAssociation('newsletter');
|
||||
return $this->newsletter;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return SendingQueueEntity|null
|
||||
*/
|
||||
public function getQueue() {
|
||||
$this->safelyLoadToOneAssociation('queue');
|
||||
return $this->queue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return NewsletterLinkEntity|null
|
||||
*/
|
||||
public function getLink() {
|
||||
$this->safelyLoadToOneAssociation('link');
|
||||
return $this->link;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param NewsletterEntity|null $newsletter
|
||||
*/
|
||||
public function setNewsletter($newsletter) {
|
||||
$this->newsletter = $newsletter;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param SendingQueueEntity|null $queue
|
||||
*/
|
||||
public function setQueue($queue) {
|
||||
$this->queue = $queue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param SubscriberEntity|null $subscriber
|
||||
*/
|
||||
public function setSubscriber($subscriber) {
|
||||
$this->subscriber = $subscriber;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return SubscriberEntity|null
|
||||
*/
|
||||
public function getSubscriber(): ?SubscriberEntity {
|
||||
return $this->subscriber;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param NewsletterLinkEntity|null $link
|
||||
*/
|
||||
public function setLink($link) {
|
||||
$this->link = $link;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $count
|
||||
*/
|
||||
public function setCount(int $count) {
|
||||
$this->count = $count;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ArrayCollection<int, StatisticsWooCommercePurchaseEntity>
|
||||
*/
|
||||
public function getWooCommercePurchases() {
|
||||
return $this->wooCommercePurchases;
|
||||
}
|
||||
|
||||
public function getCount(): int {
|
||||
return $this->count;
|
||||
}
|
||||
|
||||
public function getUserAgent(): ?UserAgentEntity {
|
||||
return $this->userAgent;
|
||||
}
|
||||
|
||||
public function setUserAgent(?UserAgentEntity $userAgent): void {
|
||||
$this->userAgent = $userAgent;
|
||||
}
|
||||
|
||||
public function getUserAgentType(): int {
|
||||
return $this->userAgentType;
|
||||
}
|
||||
|
||||
public function setUserAgentType(int $userAgentType): void {
|
||||
$this->userAgentType = $userAgentType;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
|
||||
|
||||
namespace MailPoet\Entities;
|
||||
|
||||
if (!defined('ABSPATH')) exit;
|
||||
|
||||
|
||||
use MailPoet\Doctrine\EntityTraits\AutoincrementedIdTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\CreatedAtTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\SafeToOneAssociationLoadTrait;
|
||||
use MailPoetVendor\Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
/**
|
||||
* @ORM\Entity()
|
||||
* @ORM\Table(name="statistics_forms")
|
||||
*/
|
||||
class StatisticsFormEntity {
|
||||
use AutoincrementedIdTrait;
|
||||
use CreatedAtTrait;
|
||||
use SafeToOneAssociationLoadTrait;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="MailPoet\Entities\FormEntity")
|
||||
* @ORM\JoinColumn(name="form_id", referencedColumnName="id")
|
||||
* @var FormEntity|null
|
||||
*/
|
||||
private $form;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="MailPoet\Entities\SubscriberEntity")
|
||||
* @ORM\JoinColumn(name="subscriber_id", referencedColumnName="id")
|
||||
* @var SubscriberEntity|null
|
||||
*/
|
||||
private $subscriber;
|
||||
|
||||
public function __construct(
|
||||
FormEntity $form,
|
||||
SubscriberEntity $subscriber
|
||||
) {
|
||||
$this->form = $form;
|
||||
$this->subscriber = $subscriber;
|
||||
}
|
||||
|
||||
public function getForm(): ?FormEntity {
|
||||
$this->safelyLoadToOneAssociation('form');
|
||||
return $this->form;
|
||||
}
|
||||
|
||||
public function getSubscriber(): ?SubscriberEntity {
|
||||
$this->safelyLoadToOneAssociation('form');
|
||||
return $this->subscriber;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
|
||||
|
||||
namespace MailPoet\Entities;
|
||||
|
||||
if (!defined('ABSPATH')) exit;
|
||||
|
||||
|
||||
use MailPoet\Doctrine\EntityTraits\AutoincrementedIdTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\SafeToOneAssociationLoadTrait;
|
||||
use MailPoetVendor\Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
/**
|
||||
* @ORM\Entity()
|
||||
* @ORM\Table(name="statistics_newsletters")
|
||||
*/
|
||||
class StatisticsNewsletterEntity {
|
||||
use AutoincrementedIdTrait;
|
||||
use SafeToOneAssociationLoadTrait;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="MailPoet\Entities\NewsletterEntity")
|
||||
* @ORM\JoinColumn(name="newsletter_id", referencedColumnName="id")
|
||||
* @var NewsletterEntity|null
|
||||
*/
|
||||
private $newsletter;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="MailPoet\Entities\SendingQueueEntity")
|
||||
* @ORM\JoinColumn(name="queue_id", referencedColumnName="id")
|
||||
* @var SendingQueueEntity|null
|
||||
*/
|
||||
private $queue;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="MailPoet\Entities\SubscriberEntity")
|
||||
* @ORM\JoinColumn(name="subscriber_id", referencedColumnName="id")
|
||||
* @var SubscriberEntity|null
|
||||
*/
|
||||
private $subscriber;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="datetimetz", nullable=false)
|
||||
* @var \DateTimeInterface
|
||||
*/
|
||||
private $sentAt;
|
||||
|
||||
public function __construct(
|
||||
NewsletterEntity $newsletter,
|
||||
SendingQueueEntity $queue,
|
||||
SubscriberEntity $subscriber,
|
||||
\DateTimeInterface $sentAt = null
|
||||
) {
|
||||
$this->newsletter = $newsletter;
|
||||
$this->queue = $queue;
|
||||
$this->subscriber = $subscriber;
|
||||
$this->sentAt = $sentAt ?: new \DateTimeImmutable();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return NewsletterEntity|null
|
||||
*/
|
||||
public function getNewsletter() {
|
||||
$this->safelyLoadToOneAssociation('newsletter');
|
||||
return $this->newsletter;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return SendingQueueEntity|null
|
||||
*/
|
||||
public function getQueue() {
|
||||
$this->safelyLoadToOneAssociation('queue');
|
||||
return $this->queue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return SubscriberEntity|null
|
||||
*/
|
||||
public function getSubscriber() {
|
||||
$this->safelyLoadToOneAssociation('subscriber');
|
||||
return $this->subscriber;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \DateTimeInterface|null
|
||||
*/
|
||||
public function getSentAt() {
|
||||
return $this->sentAt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \DateTimeInterface $sentAt
|
||||
*/
|
||||
public function setSentAt(\DateTimeInterface $sentAt) {
|
||||
$this->sentAt = $sentAt;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
|
||||
|
||||
namespace MailPoet\Entities;
|
||||
|
||||
if (!defined('ABSPATH')) exit;
|
||||
|
||||
|
||||
use MailPoet\Doctrine\EntityTraits\AutoincrementedIdTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\CreatedAtTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\SafeToOneAssociationLoadTrait;
|
||||
use MailPoetVendor\Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
/**
|
||||
* @ORM\Entity()
|
||||
* @ORM\Table(name="statistics_opens")
|
||||
*/
|
||||
class StatisticsOpenEntity {
|
||||
use AutoincrementedIdTrait;
|
||||
use CreatedAtTrait;
|
||||
use SafeToOneAssociationLoadTrait;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="MailPoet\Entities\NewsletterEntity")
|
||||
* @ORM\JoinColumn(name="newsletter_id", referencedColumnName="id")
|
||||
* @var NewsletterEntity|null
|
||||
*/
|
||||
private $newsletter;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="MailPoet\Entities\SendingQueueEntity")
|
||||
* @ORM\JoinColumn(name="queue_id", referencedColumnName="id")
|
||||
* @var SendingQueueEntity|null
|
||||
*/
|
||||
private $queue;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="MailPoet\Entities\SubscriberEntity")
|
||||
* @ORM\JoinColumn(name="subscriber_id", referencedColumnName="id")
|
||||
* @var SubscriberEntity|null
|
||||
*/
|
||||
private $subscriber;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="MailPoet\Entities\UserAgentEntity")
|
||||
* @var UserAgentEntity|null
|
||||
*/
|
||||
private $userAgent;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="smallint")
|
||||
* @var int
|
||||
*/
|
||||
private $userAgentType = 0;
|
||||
|
||||
public function __construct(
|
||||
NewsletterEntity $newsletter,
|
||||
SendingQueueEntity $queue,
|
||||
SubscriberEntity $subscriber
|
||||
) {
|
||||
$this->newsletter = $newsletter;
|
||||
$this->queue = $queue;
|
||||
$this->subscriber = $subscriber;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return NewsletterEntity|null
|
||||
*/
|
||||
public function getNewsletter() {
|
||||
$this->safelyLoadToOneAssociation('newsletter');
|
||||
return $this->newsletter;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return SendingQueueEntity|null
|
||||
*/
|
||||
public function getQueue() {
|
||||
$this->safelyLoadToOneAssociation('queue');
|
||||
return $this->queue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param NewsletterEntity|null $newsletter
|
||||
*/
|
||||
public function setNewsletter($newsletter) {
|
||||
$this->newsletter = $newsletter;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param SendingQueueEntity|null $queue
|
||||
*/
|
||||
public function setQueue($queue) {
|
||||
$this->queue = $queue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param SubscriberEntity|null $subscriber
|
||||
*/
|
||||
public function setSubscriber($subscriber) {
|
||||
$this->subscriber = $subscriber;
|
||||
}
|
||||
|
||||
public function getUserAgent(): ?UserAgentEntity {
|
||||
return $this->userAgent;
|
||||
}
|
||||
|
||||
public function setUserAgent(?UserAgentEntity $userAgent): void {
|
||||
$this->userAgent = $userAgent;
|
||||
}
|
||||
|
||||
public function getUserAgentType(): int {
|
||||
return $this->userAgentType;
|
||||
}
|
||||
|
||||
public function setUserAgentType(int $userAgentType): void {
|
||||
$this->userAgentType = $userAgentType;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
|
||||
|
||||
namespace MailPoet\Entities;
|
||||
|
||||
if (!defined('ABSPATH')) exit;
|
||||
|
||||
|
||||
use MailPoet\Doctrine\EntityTraits\AutoincrementedIdTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\CreatedAtTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\SafeToOneAssociationLoadTrait;
|
||||
use MailPoetVendor\Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
/**
|
||||
* @ORM\Entity()
|
||||
* @ORM\Table(name="statistics_unsubscribes")
|
||||
*/
|
||||
class StatisticsUnsubscribeEntity {
|
||||
use AutoincrementedIdTrait;
|
||||
use CreatedAtTrait;
|
||||
use SafeToOneAssociationLoadTrait;
|
||||
|
||||
const SOURCE_NEWSLETTER = 'newsletter';
|
||||
const SOURCE_MANAGE = 'manage';
|
||||
const SOURCE_ADMINISTRATOR = 'admin';
|
||||
const SOURCE_ORDER_CHECKOUT = 'order_checkout';
|
||||
const SOURCE_AUTOMATION = 'automation';
|
||||
const SOURCE_MP_API = 'mp_api';
|
||||
|
||||
const METHOD_LINK = 'link';
|
||||
const METHOD_ONE_CLICK = 'one_click';
|
||||
const METHOD_UNKNOWN = 'unknown';
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="MailPoet\Entities\NewsletterEntity")
|
||||
* @ORM\JoinColumn(name="newsletter_id", referencedColumnName="id")
|
||||
* @var NewsletterEntity|null
|
||||
*/
|
||||
private $newsletter;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="MailPoet\Entities\SendingQueueEntity")
|
||||
* @ORM\JoinColumn(name="queue_id", referencedColumnName="id")
|
||||
* @var SendingQueueEntity|null
|
||||
*/
|
||||
private $queue;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="MailPoet\Entities\SubscriberEntity")
|
||||
* @ORM\JoinColumn(name="subscriber_id", referencedColumnName="id")
|
||||
* @var SubscriberEntity|null
|
||||
*/
|
||||
private $subscriber;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string")
|
||||
* @var string
|
||||
*/
|
||||
private $source = 'unknown';
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string", nullable=true)
|
||||
* @var string|null
|
||||
*/
|
||||
private $meta;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string", nullable=false)
|
||||
* @var string
|
||||
*/
|
||||
private $method = self::METHOD_UNKNOWN;
|
||||
|
||||
public function __construct(
|
||||
NewsletterEntity $newsletter = null,
|
||||
SendingQueueEntity $queue = null,
|
||||
SubscriberEntity $subscriber
|
||||
) {
|
||||
$this->newsletter = $newsletter;
|
||||
$this->queue = $queue;
|
||||
$this->subscriber = $subscriber;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return NewsletterEntity|null
|
||||
*/
|
||||
public function getNewsletter() {
|
||||
$this->safelyLoadToOneAssociation('newsletter');
|
||||
return $this->newsletter;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return SendingQueueEntity|null
|
||||
*/
|
||||
public function getQueue() {
|
||||
$this->safelyLoadToOneAssociation('queue');
|
||||
return $this->queue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getSource(): string {
|
||||
return $this->source;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $source
|
||||
*/
|
||||
public function setSource(string $source) {
|
||||
$this->source = $source;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $meta
|
||||
*/
|
||||
public function setMeta(string $meta) {
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
public function getMeta() {
|
||||
return $this->meta;
|
||||
}
|
||||
|
||||
public function setMethod(string $method) {
|
||||
$this->method = $method;
|
||||
}
|
||||
|
||||
public function getMethod(): string {
|
||||
return $this->method;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
|
||||
|
||||
namespace MailPoet\Entities;
|
||||
|
||||
if (!defined('ABSPATH')) exit;
|
||||
|
||||
|
||||
use MailPoet\Doctrine\EntityTraits\AutoincrementedIdTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\CreatedAtTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\SafeToOneAssociationLoadTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\UpdatedAtTrait;
|
||||
use MailPoetVendor\Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
/**
|
||||
* @ORM\Entity()
|
||||
* @ORM\Table(name="statistics_woocommerce_purchases")
|
||||
*/
|
||||
class StatisticsWooCommercePurchaseEntity {
|
||||
use AutoincrementedIdTrait;
|
||||
use CreatedAtTrait;
|
||||
use UpdatedAtTrait;
|
||||
use SafeToOneAssociationLoadTrait;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="MailPoet\Entities\NewsletterEntity")
|
||||
* @ORM\JoinColumn(name="newsletter_id", referencedColumnName="id", nullable=true)
|
||||
* @var NewsletterEntity|null
|
||||
*/
|
||||
private $newsletter;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="MailPoet\Entities\SendingQueueEntity")
|
||||
* @ORM\JoinColumn(name="queue_id", referencedColumnName="id")
|
||||
* @var SendingQueueEntity|null
|
||||
*/
|
||||
private $queue;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="MailPoet\Entities\SubscriberEntity")
|
||||
* @ORM\JoinColumn(name="subscriber_id", referencedColumnName="id")
|
||||
* @var SubscriberEntity|null
|
||||
*/
|
||||
private $subscriber;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="MailPoet\Entities\StatisticsClickEntity", inversedBy="wooCommercePurchases")
|
||||
* @ORM\JoinColumn(name="click_id", referencedColumnName="id")
|
||||
* @var StatisticsClickEntity|null
|
||||
*/
|
||||
private $click;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="integer")
|
||||
* @var int
|
||||
*/
|
||||
private $orderId;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string")
|
||||
* @var string
|
||||
*/
|
||||
private $orderCurrency;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="float")
|
||||
* @var float
|
||||
*/
|
||||
private $orderPriceTotal;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string")
|
||||
* @var string
|
||||
*/
|
||||
private $status;
|
||||
|
||||
public function __construct(
|
||||
NewsletterEntity $newsletter,
|
||||
SendingQueueEntity $queue,
|
||||
StatisticsClickEntity $click,
|
||||
int $orderId,
|
||||
string $orderCurrency,
|
||||
float $orderPriceTotal,
|
||||
string $status
|
||||
) {
|
||||
$this->newsletter = $newsletter;
|
||||
$this->queue = $queue;
|
||||
$this->click = $click;
|
||||
$this->orderId = $orderId;
|
||||
$this->orderCurrency = $orderCurrency;
|
||||
$this->orderPriceTotal = $orderPriceTotal;
|
||||
$this->status = $status;
|
||||
}
|
||||
|
||||
public function getNewsletter(): ?NewsletterEntity {
|
||||
$this->safelyLoadToOneAssociation('newsletter');
|
||||
return $this->newsletter;
|
||||
}
|
||||
|
||||
public function getQueue(): ?SendingQueueEntity {
|
||||
$this->safelyLoadToOneAssociation('queue');
|
||||
return $this->queue;
|
||||
}
|
||||
|
||||
public function getSubscriber(): ?SubscriberEntity {
|
||||
$this->safelyLoadToOneAssociation('subscriber');
|
||||
return $this->subscriber;
|
||||
}
|
||||
|
||||
public function getClick(): ?StatisticsClickEntity {
|
||||
$this->safelyLoadToOneAssociation('click');
|
||||
return $this->click;
|
||||
}
|
||||
|
||||
public function getOrderId(): int {
|
||||
return $this->orderId;
|
||||
}
|
||||
|
||||
public function setSubscriber(?SubscriberEntity $subscriber) {
|
||||
$this->subscriber = $subscriber;
|
||||
}
|
||||
|
||||
public function getOrderCurrency(): string {
|
||||
return $this->orderCurrency;
|
||||
}
|
||||
|
||||
public function getOrderPriceTotal(): float {
|
||||
return $this->orderPriceTotal;
|
||||
}
|
||||
|
||||
public function setOrderCurrency(string $orderCurrency): void {
|
||||
$this->orderCurrency = $orderCurrency;
|
||||
}
|
||||
|
||||
public function setOrderPriceTotal(float $orderPriceTotal): void {
|
||||
$this->orderPriceTotal = $orderPriceTotal;
|
||||
}
|
||||
|
||||
public function getStatus(): string {
|
||||
return $this->status;
|
||||
}
|
||||
|
||||
public function setStatus(string $status): void {
|
||||
$this->status = $status;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
|
||||
|
||||
namespace MailPoet\Entities;
|
||||
|
||||
if (!defined('ABSPATH')) exit;
|
||||
|
||||
|
||||
use MailPoet\Doctrine\EntityTraits\AutoincrementedIdTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\CreatedAtTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\SafeToOneAssociationLoadTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\UpdatedAtTrait;
|
||||
use MailPoetVendor\Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
/**
|
||||
* @ORM\Entity()
|
||||
* @ORM\Table(name="stats_notifications")
|
||||
*/
|
||||
class StatsNotificationEntity {
|
||||
use AutoincrementedIdTrait;
|
||||
use CreatedAtTrait;
|
||||
use UpdatedAtTrait;
|
||||
use SafeToOneAssociationLoadTrait;
|
||||
|
||||
/**
|
||||
* @ORM\OneToOne(targetEntity="MailPoet\Entities\NewsletterEntity")
|
||||
* @var NewsletterEntity|null
|
||||
*/
|
||||
private $newsletter;
|
||||
|
||||
/**
|
||||
* @ORM\OneToOne(targetEntity="MailPoet\Entities\ScheduledTaskEntity")
|
||||
* @var ScheduledTaskEntity|null
|
||||
*/
|
||||
private $task;
|
||||
|
||||
public function __construct(
|
||||
NewsletterEntity $newsletter,
|
||||
ScheduledTaskEntity $task
|
||||
) {
|
||||
$this->newsletter = $newsletter;
|
||||
$this->task = $task;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return NewsletterEntity|null
|
||||
*/
|
||||
public function getNewsletter() {
|
||||
$this->safelyLoadToOneAssociation('newsletter');
|
||||
return $this->newsletter;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ScheduledTaskEntity|null
|
||||
*/
|
||||
public function getTask() {
|
||||
$this->safelyLoadToOneAssociation('task');
|
||||
return $this->task;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
|
||||
|
||||
namespace MailPoet\Entities;
|
||||
|
||||
if (!defined('ABSPATH')) exit;
|
||||
|
||||
|
||||
use MailPoet\Doctrine\EntityTraits\AutoincrementedIdTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\CreatedAtTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\SafeToOneAssociationLoadTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\UpdatedAtTrait;
|
||||
use MailPoet\InvalidStateException;
|
||||
use MailPoet\Util\DateConverter;
|
||||
use MailPoetVendor\Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
/**
|
||||
* @ORM\Entity()
|
||||
* @ORM\Table(name="subscriber_custom_field")
|
||||
*/
|
||||
class SubscriberCustomFieldEntity {
|
||||
use AutoincrementedIdTrait;
|
||||
use CreatedAtTrait;
|
||||
use UpdatedAtTrait;
|
||||
use SafeToOneAssociationLoadTrait;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="MailPoet\Entities\SubscriberEntity")
|
||||
* @var SubscriberEntity|null
|
||||
*/
|
||||
private $subscriber;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="MailPoet\Entities\CustomFieldEntity")
|
||||
* @var CustomFieldEntity|null
|
||||
*/
|
||||
private $customField;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string")
|
||||
* @var string
|
||||
*/
|
||||
private $value;
|
||||
|
||||
/**
|
||||
* @param string|array|null $value
|
||||
*/
|
||||
public function __construct(
|
||||
SubscriberEntity $subscriber,
|
||||
CustomFieldEntity $customField,
|
||||
$value
|
||||
) {
|
||||
$this->subscriber = $subscriber;
|
||||
$this->customField = $customField;
|
||||
$this->setValue($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return SubscriberEntity|null
|
||||
*/
|
||||
public function getSubscriber() {
|
||||
$this->safelyLoadToOneAssociation('subscriber');
|
||||
return $this->subscriber;
|
||||
}
|
||||
|
||||
public function getValue(): string {
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return CustomFieldEntity|null
|
||||
*/
|
||||
public function getCustomField() {
|
||||
return $this->customField;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|array|null $value
|
||||
*/
|
||||
public function setValue($value): void {
|
||||
$customField = $this->getCustomField();
|
||||
if (!$customField instanceof CustomFieldEntity) {
|
||||
throw new InvalidStateException('CustomField has to be set');
|
||||
}
|
||||
|
||||
// format custom field data depending on type
|
||||
if (is_array($value) && $customField->getType() === CustomFieldEntity::TYPE_DATE) {
|
||||
$customFieldParams = $customField->getParams();
|
||||
$dateFormat = $customFieldParams['date_format'] ?? null;
|
||||
$dateType = isset($customFieldParams['date_type']) ? $customFieldParams['date_type'] : 'year_month_day';
|
||||
switch ($dateType) {
|
||||
case 'year_month_day':
|
||||
$value = str_replace(['DD', 'MM', 'YYYY'], [$value['day'], $value['month'], $value['year']], $dateFormat);
|
||||
break;
|
||||
|
||||
case 'year_month':
|
||||
$value = str_replace(['MM', 'YYYY'], [$value['month'], $value['year']], $dateFormat);
|
||||
break;
|
||||
|
||||
case 'month':
|
||||
$value = (int)$value['month'] === 0 ? '' : sprintf('%s', $value['month']);
|
||||
break;
|
||||
|
||||
case 'day':
|
||||
$value = (int)$value['day'] === 0 ? '' : sprintf('%s', $value['day']);
|
||||
break;
|
||||
|
||||
case 'year':
|
||||
$value = (int)$value['year'] === 0 ? '' : sprintf('%04d', $value['year']);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!empty($value) && is_string($value)) {
|
||||
$value = (new DateConverter())->convertDateToDatetime($value, $dateFormat);
|
||||
}
|
||||
}
|
||||
|
||||
if (is_array($value)) {
|
||||
throw new InvalidStateException('Final value has to be string');
|
||||
}
|
||||
$this->value = (string)$value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,648 @@
|
||||
<?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\Doctrine\EntityTraits\ValidationGroupsTrait;
|
||||
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;
|
||||
use ValidationGroupsTrait;
|
||||
|
||||
/**
|
||||
* @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(groups={"Saving"})
|
||||
* @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 2026-01-01
|
||||
*/
|
||||
public function __get($key) {
|
||||
$getterName = 'get' . Helpers::underscoreToCamelCase($key, $capitaliseFirstChar = true);
|
||||
$callable = [$this, $getterName];
|
||||
if (is_callable($callable)) {
|
||||
// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_trigger_error -- Intended for deprecation warnings
|
||||
trigger_error(
|
||||
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- if the function is callable, it's safe to output
|
||||
"Direct access to \$subscriber->{$key} is deprecated and will be removed after 2026-01-01. Use \$subscriber->{$getterName}() instead.",
|
||||
E_USER_DEPRECATED
|
||||
);
|
||||
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 = null) {
|
||||
if (!$subscriberSegment) return null;
|
||||
return $subscriberSegment->getSegment();
|
||||
})->filter(function (?SegmentEntity $segment = null) {
|
||||
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 = null) {
|
||||
if (!$subscriberSegment) return null;
|
||||
if ($subscriberSegment->getSegment() === null) {
|
||||
$this->subscriberSegments->removeElement($subscriberSegment);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
|
||||
|
||||
namespace MailPoet\Entities;
|
||||
|
||||
if (!defined('ABSPATH')) exit;
|
||||
|
||||
|
||||
use DateTimeInterface;
|
||||
use MailPoetVendor\Carbon\Carbon;
|
||||
use MailPoetVendor\Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
/**
|
||||
* @ORM\Entity()
|
||||
* @ORM\Table(name="subscriber_ips")
|
||||
*/
|
||||
class SubscriberIPEntity {
|
||||
/**
|
||||
* @ORM\Id
|
||||
* @ORM\Column(type="string")
|
||||
* @var string
|
||||
*/
|
||||
private $ip;
|
||||
|
||||
/**
|
||||
* We have to use own type because createdAt is part of the primary key and basic datetimetz isn't supported in primary key
|
||||
* @ORM\Id
|
||||
* @ORM\Column(type="datetimetz_to_string")
|
||||
* @var DateTimeInterface
|
||||
*/
|
||||
private $createdAt;
|
||||
|
||||
public function __construct(
|
||||
string $ip
|
||||
) {
|
||||
$this->ip = $ip;
|
||||
$this->createdAt = new Carbon();
|
||||
}
|
||||
|
||||
public function getIP(): string {
|
||||
return $this->ip;
|
||||
}
|
||||
|
||||
public function getCreatedAt(): DateTimeInterface {
|
||||
return $this->createdAt;
|
||||
}
|
||||
|
||||
public function setCreatedAt(DateTimeInterface $createdAt): void {
|
||||
$this->createdAt = $createdAt;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
|
||||
|
||||
namespace MailPoet\Entities;
|
||||
|
||||
if (!defined('ABSPATH')) exit;
|
||||
|
||||
|
||||
use MailPoet\Doctrine\EntityTraits\AutoincrementedIdTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\CreatedAtTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\SafeToOneAssociationLoadTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\UpdatedAtTrait;
|
||||
use MailPoetVendor\Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
/**
|
||||
* @ORM\Entity()
|
||||
* @ORM\Table(name="subscriber_segment")
|
||||
*/
|
||||
class SubscriberSegmentEntity {
|
||||
use AutoincrementedIdTrait;
|
||||
use CreatedAtTrait;
|
||||
use UpdatedAtTrait;
|
||||
use SafeToOneAssociationLoadTrait;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="MailPoet\Entities\SegmentEntity")
|
||||
* @var SegmentEntity|null
|
||||
*/
|
||||
private $segment;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="MailPoet\Entities\SubscriberEntity", inversedBy="subscriberSegments")
|
||||
* @var SubscriberEntity|null
|
||||
*/
|
||||
private $subscriber;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string")
|
||||
* @var string
|
||||
*/
|
||||
private $status;
|
||||
|
||||
public function __construct(
|
||||
SegmentEntity $segment,
|
||||
SubscriberEntity $subscriber,
|
||||
string $status
|
||||
) {
|
||||
$this->segment = $segment;
|
||||
$this->subscriber = $subscriber;
|
||||
$this->status = $status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return SegmentEntity|null
|
||||
*/
|
||||
public function getSegment() {
|
||||
$this->safelyLoadToOneAssociation('segment');
|
||||
return $this->segment;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return SubscriberEntity|null
|
||||
*/
|
||||
public function getSubscriber() {
|
||||
$this->safelyLoadToOneAssociation('subscriber');
|
||||
return $this->subscriber;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getStatus(): string {
|
||||
return $this->status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $status
|
||||
*/
|
||||
public function setStatus(string $status) {
|
||||
$this->status = $status;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace MailPoet\Entities;
|
||||
|
||||
if (!defined('ABSPATH')) exit;
|
||||
|
||||
|
||||
use MailPoet\Doctrine\EntityTraits\AutoincrementedIdTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\CreatedAtTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\SafeToOneAssociationLoadTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\UpdatedAtTrait;
|
||||
use MailPoetVendor\Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
/**
|
||||
* @ORM\Entity()
|
||||
* @ORM\Table(name="subscriber_tag")
|
||||
*/
|
||||
class SubscriberTagEntity {
|
||||
use AutoincrementedIdTrait;
|
||||
use CreatedAtTrait;
|
||||
use UpdatedAtTrait;
|
||||
use SafeToOneAssociationLoadTrait;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="MailPoet\Entities\TagEntity")
|
||||
* @var TagEntity|null
|
||||
*/
|
||||
private $tag;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="MailPoet\Entities\SubscriberEntity", inversedBy="subscriberTags")
|
||||
* @var SubscriberEntity|null
|
||||
*/
|
||||
private $subscriber;
|
||||
|
||||
public function __construct(
|
||||
TagEntity $tag,
|
||||
SubscriberEntity $subscriber
|
||||
) {
|
||||
$this->tag = $tag;
|
||||
$this->subscriber = $subscriber;
|
||||
}
|
||||
|
||||
public function getTag(): ?TagEntity {
|
||||
$this->safelyLoadToOneAssociation('tag');
|
||||
return $this->tag;
|
||||
}
|
||||
|
||||
public function getSubscriber(): ?SubscriberEntity {
|
||||
$this->safelyLoadToOneAssociation('subscriber');
|
||||
return $this->subscriber;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace MailPoet\Entities;
|
||||
|
||||
if (!defined('ABSPATH')) exit;
|
||||
|
||||
|
||||
use MailPoet\Doctrine\EntityTraits\AutoincrementedIdTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\CreatedAtTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\UpdatedAtTrait;
|
||||
use MailPoetVendor\Doctrine\Common\Collections\ArrayCollection;
|
||||
use MailPoetVendor\Doctrine\ORM\Mapping as ORM;
|
||||
use MailPoetVendor\Symfony\Component\Validator\Constraints as Assert;
|
||||
|
||||
/**
|
||||
* @ORM\Entity()
|
||||
* @ORM\Table(name="tags")
|
||||
*/
|
||||
class TagEntity {
|
||||
use AutoincrementedIdTrait;
|
||||
use CreatedAtTrait;
|
||||
use UpdatedAtTrait;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string")
|
||||
* @Assert\NotBlank()
|
||||
* @var string
|
||||
*/
|
||||
private $name;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string")
|
||||
* @var string
|
||||
*/
|
||||
private $description;
|
||||
|
||||
/**
|
||||
* @ORM\OneToMany(targetEntity="MailPoet\Entities\SubscriberTagEntity", mappedBy="tag", fetch="EXTRA_LAZY")
|
||||
* @var ArrayCollection<int, SubscriberTagEntity>
|
||||
*/
|
||||
private $subscriberTags;
|
||||
|
||||
public function __construct(
|
||||
string $name,
|
||||
string $description = ''
|
||||
) {
|
||||
$this->name = $name;
|
||||
$this->description = $description;
|
||||
$this->subscriberTags = new ArrayCollection();
|
||||
}
|
||||
|
||||
public function getName(): string {
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function setName(string $name): void {
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
public function getDescription(): string {
|
||||
return $this->description;
|
||||
}
|
||||
|
||||
public function setDescription(string $description): void {
|
||||
$this->description = $description;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
|
||||
|
||||
namespace MailPoet\Entities;
|
||||
|
||||
if (!defined('ABSPATH')) exit;
|
||||
|
||||
|
||||
use MailPoet\Doctrine\EntityTraits\AutoincrementedIdTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\CreatedAtTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\UpdatedAtTrait;
|
||||
use MailPoetVendor\Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
/**
|
||||
* @ORM\Entity()
|
||||
* @ORM\Table(name="user_agents")
|
||||
*/
|
||||
class UserAgentEntity {
|
||||
use AutoincrementedIdTrait;
|
||||
use CreatedAtTrait;
|
||||
use UpdatedAtTrait;
|
||||
|
||||
public const USER_AGENT_TYPE_HUMAN = 0;
|
||||
public const USER_AGENT_TYPE_MACHINE = 1;
|
||||
|
||||
public const MACHINE_USER_AGENTS = [
|
||||
'Mozilla/5.0',
|
||||
];
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string")
|
||||
* @var string
|
||||
*/
|
||||
private $hash;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string")
|
||||
* @var string
|
||||
*/
|
||||
private $userAgent;
|
||||
|
||||
public function __construct(
|
||||
string $userAgent
|
||||
) {
|
||||
$this->setUserAgent($userAgent);
|
||||
}
|
||||
|
||||
public function getUserAgent(): string {
|
||||
return $this->userAgent;
|
||||
}
|
||||
|
||||
public function setUserAgent(string $userAgent): void {
|
||||
$this->userAgent = $userAgent;
|
||||
$this->hash = (string)crc32($userAgent);
|
||||
}
|
||||
|
||||
public function getHash(): string {
|
||||
return $this->hash;
|
||||
}
|
||||
|
||||
public function getUserAgentType(): int {
|
||||
if (in_array($this->getUserAgent(), self::MACHINE_USER_AGENTS, true)) {
|
||||
return self::USER_AGENT_TYPE_MACHINE;
|
||||
}
|
||||
return self::USER_AGENT_TYPE_HUMAN;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
|
||||
|
||||
namespace MailPoet\Entities;
|
||||
|
||||
if (!defined('ABSPATH')) exit;
|
||||
|
||||
|
||||
use MailPoet\Doctrine\EntityTraits\AutoincrementedIdTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\CreatedAtTrait;
|
||||
use MailPoet\Doctrine\EntityTraits\UpdatedAtTrait;
|
||||
use MailPoetVendor\Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
/**
|
||||
* @ORM\Entity()
|
||||
* @ORM\Table(name="user_flags")
|
||||
*/
|
||||
class UserFlagEntity {
|
||||
use AutoincrementedIdTrait;
|
||||
use CreatedAtTrait;
|
||||
use UpdatedAtTrait;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="integer")
|
||||
* @var int
|
||||
*/
|
||||
private $userId;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string")
|
||||
* @var string
|
||||
*/
|
||||
private $name;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string", nullable=true)
|
||||
* @var string|null
|
||||
*/
|
||||
private $value;
|
||||
|
||||
/** @return int */
|
||||
public function getUserId() {
|
||||
return $this->userId;
|
||||
}
|
||||
|
||||
/** @param int $userId */
|
||||
public function setUserId($userId) {
|
||||
$this->userId = $userId;
|
||||
}
|
||||
|
||||
/** @return string */
|
||||
public function getName() {
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/** @param string $name */
|
||||
public function setName($name) {
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
/** @return string|null */
|
||||
public function getValue() {
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
/** @param string|null $value */
|
||||
public function setValue($value) {
|
||||
$this->value = $value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace MailPoet\Entities;
|
||||
|
||||
if (!defined('ABSPATH')) exit;
|
||||
|
||||
|
||||
use MailPoet\RuntimeException;
|
||||
use MailPoetVendor\Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
/**
|
||||
* @ORM\Entity(readOnly=true)
|
||||
* @ORM\Table(name="posts")
|
||||
*/
|
||||
class WpPostEntity {
|
||||
/**
|
||||
* @ORM\Column(type="integer", name="ID")
|
||||
* @ORM\Id
|
||||
* @ORM\GeneratedValue
|
||||
* @var int
|
||||
*/
|
||||
private $id;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string", name="post_title")
|
||||
* @var string
|
||||
*/
|
||||
private $postTitle;
|
||||
|
||||
public function __construct() {
|
||||
throw new RuntimeException('WpPostEntity is read only and cannot be instantiated.');
|
||||
}
|
||||
|
||||
public function getId(): int {
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function getPostTitle(): string {
|
||||
return $this->postTitle;
|
||||
}
|
||||
|
||||
/**
|
||||
* We don't use typehint for now because doctrine cache generator would fail as it doesn't know the class.
|
||||
* @return \WP_Post|null
|
||||
*/
|
||||
public function getWpPostInstance() {
|
||||
$post = \WP_Post::get_instance($this->id);
|
||||
return $post ?: null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
<?php
|
||||
Reference in New Issue
Block a user