diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f17df61..351ac54 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,7 +3,7 @@ on: [push, pull_request] jobs: main: name: phpList on PHP ${{ matrix.php-versions }} [Build, Test] - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 env: DB_DATABASE: phplist DB_USERNAME: root diff --git a/.github/workflows/core-docs.yml b/.github/workflows/core-docs.yml index a88fa4f..dc3a5bd 100644 --- a/.github/workflows/core-docs.yml +++ b/.github/workflows/core-docs.yml @@ -3,7 +3,7 @@ on: [push, pull_request] jobs: make-restapi-docs: name: Checkout phpList core and generate docs using `phpDocumentor` - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 steps: - name: Checkout uses: actions/checkout@v3 @@ -41,7 +41,7 @@ jobs: path: phpdocumentor.zip deploy-docs: name: Deploy Core Docs - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 needs: make-restapi-docs steps: - name: Checkout phplist/core-docs diff --git a/config/repositories.yml b/config/repositories.yml index 47cdbd0..2373b0d 100644 --- a/config/repositories.yml +++ b/config/repositories.yml @@ -11,10 +11,10 @@ services: arguments: - PhpList\Core\Domain\Model\Identity\AdministratorToken - PhpList\Core\Domain\Repository\Messaging\SubscriberListRepository: + PhpList\Core\Domain\Repository\Subscription\SubscriberListRepository: parent: PhpList\Core\Domain\Repository arguments: - - PhpList\Core\Domain\Model\Messaging\SubscriberList + - PhpList\Core\Domain\Model\Subscription\SubscriberList PhpList\Core\Domain\Repository\Subscription\SubscriberRepository: parent: PhpList\Core\Domain\Repository @@ -25,3 +25,18 @@ services: parent: PhpList\Core\Domain\Repository arguments: - PhpList\Core\Domain\Model\Subscription\Subscription + + PhpList\Core\Domain\Repository\Messaging\MessageRepository: + parent: PhpList\Core\Domain\Repository + arguments: + - PhpList\Core\Domain\Model\Messaging\Message + + PhpList\Core\Domain\Repository\Messaging\TemplateRepository: + parent: PhpList\Core\Domain\Repository + arguments: + - PhpList\Core\Domain\Model\Messaging\Template + + PhpList\Core\Domain\Repository\Messaging\TemplateImageRepository: + parent: PhpList\Core\Domain\Repository + arguments: + - PhpList\Core\Domain\Model\Messaging\TemplateImage diff --git a/src/Domain/Model/Analytics/LinkTrackForward.php b/src/Domain/Model/Analytics/LinkTrackForward.php index 2b42bc9..a06d66f 100644 --- a/src/Domain/Model/Analytics/LinkTrackForward.php +++ b/src/Domain/Model/Analytics/LinkTrackForward.php @@ -7,8 +7,8 @@ use Doctrine\ORM\Mapping as ORM; use PhpList\Core\Domain\Model\Interfaces\DomainModel; use PhpList\Core\Domain\Model\Interfaces\Identity; -use PhpList\Core\Domain\Model\Traits\IdentityTrait; use PhpList\Core\Domain\Repository\Analytics\LinkTrackForwardRepository; +use Symfony\Component\Serializer\Attribute\Groups; #[ORM\Entity(repositoryClass: LinkTrackForwardRepository::class)] #[ORM\Table(name: 'phplist_linktrack_forward')] @@ -17,7 +17,11 @@ #[ORM\Index(name: 'uuididx', columns: ['uuid'])] class LinkTrackForward implements DomainModel, Identity { - use IdentityTrait; + #[ORM\Id] + #[ORM\Column(type: 'integer')] + #[ORM\GeneratedValue] + #[Groups(['SubscriberList', 'SubscriberListMembers'])] + private ?int $id = null; #[ORM\Column(type: 'string', length: 2083, nullable: true)] private ?string $url = null; @@ -31,6 +35,11 @@ class LinkTrackForward implements DomainModel, Identity #[ORM\Column(type: 'boolean', nullable: true, options: ['default' => 0])] private bool $personalise = false; + public function getId(): ?int + { + return $this->id; + } + public function getUrl(): ?string { return $this->url; diff --git a/src/Domain/Model/Analytics/LinkTrackUmlClick.php b/src/Domain/Model/Analytics/LinkTrackUmlClick.php index 964a8c9..e72f024 100644 --- a/src/Domain/Model/Analytics/LinkTrackUmlClick.php +++ b/src/Domain/Model/Analytics/LinkTrackUmlClick.php @@ -8,8 +8,8 @@ use Doctrine\ORM\Mapping as ORM; use PhpList\Core\Domain\Model\Interfaces\DomainModel; use PhpList\Core\Domain\Model\Interfaces\Identity; -use PhpList\Core\Domain\Model\Traits\IdentityTrait; use PhpList\Core\Domain\Repository\Analytics\LinkTrackUmlClickRepository; +use Symfony\Component\Serializer\Attribute\Groups; #[ORM\Entity(repositoryClass: LinkTrackUmlClickRepository::class)] #[ORM\Table(name: 'phplist_linktrack_uml_click')] @@ -19,7 +19,11 @@ #[ORM\Index(name: 'uidindex', columns: ['userid'])] class LinkTrackUmlClick implements DomainModel, Identity { - use IdentityTrait; + #[ORM\Id] + #[ORM\Column(type: 'integer')] + #[ORM\GeneratedValue] + #[Groups(['SubscriberList', 'SubscriberListMembers'])] + private ?int $id = null; #[ORM\Column(name: 'messageid', type: 'integer')] private int $messageId; @@ -45,6 +49,11 @@ class LinkTrackUmlClick implements DomainModel, Identity #[ORM\Column(name: 'textclicked', type: 'integer', nullable: true, options: ['default' => 0])] private ?int $textClicked = 0; + public function getId(): ?int + { + return $this->id; + } + public function getMessageId(): int { return $this->messageId; diff --git a/src/Domain/Model/Analytics/UserMessageView.php b/src/Domain/Model/Analytics/UserMessageView.php index 19a6bbc..673216d 100644 --- a/src/Domain/Model/Analytics/UserMessageView.php +++ b/src/Domain/Model/Analytics/UserMessageView.php @@ -8,7 +8,7 @@ use Doctrine\ORM\Mapping as ORM; use PhpList\Core\Domain\Model\Interfaces\DomainModel; use PhpList\Core\Domain\Model\Interfaces\Identity; -use PhpList\Core\Domain\Model\Traits\IdentityTrait; +use Symfony\Component\Serializer\Attribute\Groups; #[ORM\Entity] #[ORM\Table(name: 'phplist_user_message_view')] @@ -17,7 +17,11 @@ #[ORM\Index(name: 'usermsgidx', columns: ['userid', 'messageid'])] class UserMessageView implements DomainModel, Identity { - use IdentityTrait; + #[ORM\Id] + #[ORM\Column(type: 'integer')] + #[ORM\GeneratedValue] + #[Groups(['SubscriberList', 'SubscriberListMembers'])] + private ?int $id = null; #[ORM\Column(name: 'messageid', type: 'integer')] private int $messageId; @@ -34,6 +38,11 @@ class UserMessageView implements DomainModel, Identity #[ORM\Column(name: 'data', type: 'text', nullable: true)] private ?string $data = null; + public function getId(): ?int + { + return $this->id; + } + public function getMessageId(): int { return $this->messageId; diff --git a/src/Domain/Model/Analytics/UserStats.php b/src/Domain/Model/Analytics/UserStats.php index 838b942..07d7d5c 100644 --- a/src/Domain/Model/Analytics/UserStats.php +++ b/src/Domain/Model/Analytics/UserStats.php @@ -7,7 +7,7 @@ use Doctrine\ORM\Mapping as ORM; use PhpList\Core\Domain\Model\Interfaces\DomainModel; use PhpList\Core\Domain\Model\Interfaces\Identity; -use PhpList\Core\Domain\Model\Traits\IdentityTrait; +use Symfony\Component\Serializer\Attribute\Groups; #[ORM\Entity] #[ORM\Table(name: 'phplist_userstats')] @@ -18,7 +18,11 @@ #[ORM\Index(name: 'listindex', columns: ['listid'])] class UserStats implements DomainModel, Identity { - use IdentityTrait; + #[ORM\Id] + #[ORM\Column(type: 'integer')] + #[ORM\GeneratedValue] + #[Groups(['SubscriberList', 'SubscriberListMembers'])] + private ?int $id = null; #[ORM\Column(name: 'unixdate', type: 'integer', nullable: true)] private ?int $unixDate = null; @@ -32,6 +36,11 @@ class UserStats implements DomainModel, Identity #[ORM\Column(name: 'value', type: 'integer', options: ['default' => 0])] private int $value = 0; + public function getId(): ?int + { + return $this->id; + } + public function getUnixDate(): ?int { return $this->unixDate; diff --git a/src/Domain/Model/Configuration/EventLog.php b/src/Domain/Model/Configuration/EventLog.php index d26ae73..40c5f32 100644 --- a/src/Domain/Model/Configuration/EventLog.php +++ b/src/Domain/Model/Configuration/EventLog.php @@ -8,8 +8,8 @@ use Doctrine\ORM\Mapping as ORM; use PhpList\Core\Domain\Model\Interfaces\DomainModel; use PhpList\Core\Domain\Model\Interfaces\Identity; -use PhpList\Core\Domain\Model\Traits\IdentityTrait; use PhpList\Core\Domain\Repository\Configuration\EventLogRepository; +use Symfony\Component\Serializer\Attribute\Groups; #[ORM\Entity(repositoryClass: EventLogRepository::class)] #[ORM\Table(name: 'phplist_eventlog')] @@ -17,7 +17,11 @@ #[ORM\Index(name: 'pageidx', columns: ['page'])] class EventLog implements DomainModel, Identity { - use IdentityTrait; + #[ORM\Id] + #[ORM\Column(type: 'integer')] + #[ORM\GeneratedValue] + #[Groups(['SubscriberList', 'SubscriberListMembers'])] + private ?int $id = null; #[ORM\Column(type: 'datetime', nullable: true)] private ?DateTimeInterface $entered = null; @@ -28,7 +32,7 @@ class EventLog implements DomainModel, Identity #[ORM\Column(type: 'text', nullable: true)] private ?string $entry = null; - public function getId(): int + public function getId(): ?int { return $this->id; } diff --git a/src/Domain/Model/Configuration/UrlCache.php b/src/Domain/Model/Configuration/UrlCache.php index 5ea2f9e..621878e 100644 --- a/src/Domain/Model/Configuration/UrlCache.php +++ b/src/Domain/Model/Configuration/UrlCache.php @@ -8,14 +8,18 @@ use Doctrine\ORM\Mapping as ORM; use PhpList\Core\Domain\Model\Interfaces\DomainModel; use PhpList\Core\Domain\Model\Interfaces\Identity; -use PhpList\Core\Domain\Model\Traits\IdentityTrait; +use Symfony\Component\Serializer\Attribute\Groups; #[ORM\Entity] #[ORM\Table(name: 'phplist_urlcache')] #[ORM\Index(name: 'urlindex', columns: ['url'])] class UrlCache implements DomainModel, Identity { - use IdentityTrait; + #[ORM\Id] + #[ORM\Column(type: 'integer')] + #[ORM\GeneratedValue] + #[Groups(['SubscriberList', 'SubscriberListMembers'])] + private ?int $id = null; #[ORM\Column(name: 'url', type: 'string', length: 2083)] private string $url; @@ -29,6 +33,11 @@ class UrlCache implements DomainModel, Identity #[ORM\Column(name: 'content', type: 'blob', nullable: true)] private ?string $content = null; + public function getId(): ?int + { + return $this->id; + } + public function getUrl(): string { return $this->url; diff --git a/src/Domain/Model/Identity/AdminAttribute.php b/src/Domain/Model/Identity/AdminAttribute.php index a3696bd..2e6a007 100644 --- a/src/Domain/Model/Identity/AdminAttribute.php +++ b/src/Domain/Model/Identity/AdminAttribute.php @@ -7,15 +7,19 @@ use Doctrine\ORM\Mapping as ORM; use PhpList\Core\Domain\Model\Interfaces\DomainModel; use PhpList\Core\Domain\Model\Interfaces\Identity; -use PhpList\Core\Domain\Model\Traits\IdentityTrait; use PhpList\Core\Domain\Repository\Identity\AdminAttributeRepository; +use Symfony\Component\Serializer\Attribute\Groups; #[ORM\Entity(repositoryClass: AdminAttributeRepository::class)] #[ORM\Table(name: 'phplist_admin_attribute')] #[ORM\HasLifecycleCallbacks] class AdminAttribute implements DomainModel, Identity { - use IdentityTrait; + #[ORM\Id] + #[ORM\Column(type: 'integer')] + #[ORM\GeneratedValue] + #[Groups(['SubscriberList', 'SubscriberListMembers'])] + private ?int $id = null; #[ORM\Column(name: 'name', type: 'string', length: 255)] private string $name; @@ -51,7 +55,7 @@ public function __construct( $this->tableName = $tableName; } - public function getId(): int + public function getId(): ?int { return $this->id; } @@ -86,33 +90,45 @@ public function getTableName(): ?string return $this->tableName; } - public function setName(string $name): void + public function setName(string $name): self { $this->name = $name; + + return $this; } - public function setType(?string $type): void + public function setType(?string $type): self { $this->type = $type; + + return $this; } - public function setListOrder(?int $listOrder): void + public function setListOrder(?int $listOrder): self { $this->listOrder = $listOrder; + + return $this; } - public function setDefaultValue(?string $defaultValue): void + public function setDefaultValue(?string $defaultValue): self { $this->defaultValue = $defaultValue; + + return $this; } - public function setRequired(?bool $required): void + public function setRequired(?bool $required): self { $this->required = $required; + + return $this; } - public function setTableName(?string $tableName): void + public function setTableName(?string $tableName): self { $this->tableName = $tableName; + + return $this; } } diff --git a/src/Domain/Model/Identity/AdminAttributeRelation.php b/src/Domain/Model/Identity/AdminAttributeRelation.php index 526156f..454e880 100644 --- a/src/Domain/Model/Identity/AdminAttributeRelation.php +++ b/src/Domain/Model/Identity/AdminAttributeRelation.php @@ -46,8 +46,10 @@ public function getValue(): ?string return $this->value; } - public function setValue(?string $value): void + public function setValue(?string $value): self { $this->value = $value; + + return $this; } } diff --git a/src/Domain/Model/Identity/AdminLogin.php b/src/Domain/Model/Identity/AdminLogin.php index d16bff1..653e5dc 100644 --- a/src/Domain/Model/Identity/AdminLogin.php +++ b/src/Domain/Model/Identity/AdminLogin.php @@ -7,15 +7,19 @@ use Doctrine\ORM\Mapping as ORM; use PhpList\Core\Domain\Model\Interfaces\DomainModel; use PhpList\Core\Domain\Model\Interfaces\Identity; -use PhpList\Core\Domain\Model\Traits\IdentityTrait; use PhpList\Core\Domain\Repository\Identity\AdminLoginRepository; +use Symfony\Component\Serializer\Attribute\Groups; #[ORM\Entity(repositoryClass: AdminLoginRepository::class)] #[ORM\Table(name: 'phplist_admin_login')] #[ORM\HasLifecycleCallbacks] class AdminLogin implements DomainModel, Identity { - use IdentityTrait; + #[ORM\Id] + #[ORM\Column(type: 'integer')] + #[ORM\GeneratedValue] + #[Groups(['SubscriberList', 'SubscriberListMembers'])] + private ?int $id = null; #[ORM\Column(name: 'adminid', type: 'integer', options: ['unsigned' => true])] private int $adminId; @@ -49,6 +53,11 @@ public function __construct( $this->sessionId = $sessionId; } + public function getId(): ?int + { + return $this->id; + } + public function setActive(bool $active): self { $this->active = $active; diff --git a/src/Domain/Model/Identity/Administrator.php b/src/Domain/Model/Identity/Administrator.php index 8c56c36..815b09f 100644 --- a/src/Domain/Model/Identity/Administrator.php +++ b/src/Domain/Model/Identity/Administrator.php @@ -10,25 +10,32 @@ use PhpList\Core\Domain\Model\Interfaces\DomainModel; use PhpList\Core\Domain\Model\Interfaces\Identity; use PhpList\Core\Domain\Model\Interfaces\ModificationDate; -use PhpList\Core\Domain\Model\Traits\CreationDateTrait; -use PhpList\Core\Domain\Model\Traits\IdentityTrait; -use PhpList\Core\Domain\Model\Traits\ModificationDateTrait; use PhpList\Core\Domain\Repository\Identity\AdministratorRepository; +use Symfony\Component\Serializer\Attribute\Groups; /** * This class represents an administrator who can log to the system, is allowed to administer * selected lists (as the owner), send campaigns to these lists and edit subscribers. * * @author Oliver Klee + * @author Tatevik Grigoryan */ #[ORM\Entity(repositoryClass: AdministratorRepository::class)] #[ORM\Table(name: 'phplist_admin')] #[ORM\HasLifecycleCallbacks] class Administrator implements DomainModel, Identity, CreationDate, ModificationDate { - use IdentityTrait; - use CreationDateTrait; - use ModificationDateTrait; + #[ORM\Id] + #[ORM\Column(type: 'integer')] + #[ORM\GeneratedValue] + #[Groups(['SubscriberList', 'SubscriberListMembers'])] + private ?int $id = null; + + #[ORM\Column(name: 'created', type: 'datetime')] + protected DateTime $createdAt; + + #[ORM\Column(name: 'modified', type: 'datetime')] + private ?DateTime $updatedAt; #[ORM\Column(name: 'loginname')] private string $loginName; @@ -37,10 +44,7 @@ class Administrator implements DomainModel, Identity, CreationDate, Modification private string $namelc; #[ORM\Column(name: 'email')] - private string $emailAddress; - - #[ORM\Column(name: 'created', type: 'datetime')] - protected ?DateTime $creationDate = null; + private string $email; #[ORM\Column(name: 'modifiedby', type: 'string', length: 66, nullable: true)] protected ?string $modifiedBy; @@ -67,8 +71,9 @@ public function __construct() $this->passwordChangeDate = null; $this->loginName = ''; $this->passwordHash = ''; - $this->modificationDate = null; - $this->emailAddress = ''; + $this->createdAt = new DateTime(); + $this->updatedAt = null; + $this->email = ''; } public function getLoginName(): string @@ -76,19 +81,23 @@ public function getLoginName(): string return $this->loginName; } - public function setLoginName(string $loginName): void + public function setLoginName(string $loginName): self { $this->loginName = $loginName; + + return $this; } - public function getEmailAddress(): string + public function getEmail(): string { - return $this->emailAddress; + return $this->email; } - public function setEmailAddress(string $emailAddress): void + public function setEmail(string $email): self { - $this->emailAddress = $emailAddress; + $this->email = $email; + + return $this; } public function getPasswordHash(): string @@ -96,10 +105,12 @@ public function getPasswordHash(): string return $this->passwordHash; } - public function setPasswordHash(string $passwordHash): void + public function setPasswordHash(string $passwordHash): self { $this->passwordHash = $passwordHash; - $this->setPasswordChangeDate(new DateTime()); + $this->passwordChangeDate = new DateTime(); + + return $this; } public function getPasswordChangeDate(): ?DateTime @@ -107,19 +118,16 @@ public function getPasswordChangeDate(): ?DateTime return $this->passwordChangeDate; } - private function setPasswordChangeDate(DateTime $changeDate): void - { - $this->passwordChangeDate = $changeDate; - } - public function isDisabled(): bool { return $this->disabled; } - public function setDisabled(bool $disabled): void + public function setDisabled(bool $disabled): self { $this->disabled = $disabled; + + return $this; } public function isSuperUser(): bool @@ -127,14 +135,18 @@ public function isSuperUser(): bool return $this->superUser; } - public function setSuperUser(bool $superUser): void + public function setSuperUser(bool $superUser): self { $this->superUser = $superUser; + + return $this; } - public function setNameLc(string $nameLc): void + public function setNameLc(string $nameLc): self { $this->namelc = $nameLc; + + return $this; } public function getNameLc(): string @@ -142,13 +154,39 @@ public function getNameLc(): string return $this->namelc; } - public function setPrivileges(string $privileges): void + public function setPrivileges(string $privileges): self { $this->privileges = $privileges; + + return $this; } public function getPrivileges(): string { return $this->privileges; } + + public function getCreatedAt(): ?DateTime + { + return $this->createdAt; + } + + public function getId(): ?int + { + return $this->id; + } + + public function getUpdatedAt(): ?DateTime + { + return $this->updatedAt; + } + + #[ORM\PrePersist] + #[ORM\PreUpdate] + public function updateUpdatedAt(): DomainModel + { + $this->updatedAt = new DateTime(); + + return $this; + } } diff --git a/src/Domain/Model/Identity/AdministratorToken.php b/src/Domain/Model/Identity/AdministratorToken.php index 43c57bb..e4f8039 100644 --- a/src/Domain/Model/Identity/AdministratorToken.php +++ b/src/Domain/Model/Identity/AdministratorToken.php @@ -14,7 +14,7 @@ use PhpList\Core\Domain\Model\Interfaces\CreationDate; use PhpList\Core\Domain\Model\Interfaces\DomainModel; use PhpList\Core\Domain\Model\Interfaces\Identity; -use PhpList\Core\Domain\Model\Traits\IdentityTrait; +use Symfony\Component\Serializer\Attribute\Groups; /** * This class represents an API authentication token for an administrator. @@ -25,13 +25,17 @@ #[ORM\HasLifecycleCallbacks] class AdministratorToken implements DomainModel, Identity, CreationDate { - use IdentityTrait; + #[ORM\Id] + #[ORM\Column(type: 'integer')] + #[ORM\GeneratedValue] + #[Groups(['SubscriberList', 'SubscriberListMembers'])] + private ?int $id = null; public const DEFAULT_EXPIRY = '+1 hour'; #[ORM\Column(name: 'entered', type: 'integer')] #[Ignore] - protected int $creationDate = 0; + protected int $createdAt = 0; #[ORM\Column(name: 'expires', type: 'datetime')] #[SerializedName('expiry_date')] @@ -51,27 +55,35 @@ public function __construct() $this->setExpiry(new DateTime()); } - public function getCreationDate(): ?DateTime + public function getId(): ?int { - if ($this->creationDate === 0) { + return $this->id; + } + + public function getCreatedAt(): ?DateTime + { + if ($this->createdAt === 0) { return null; } $date = new DateTime(); - $date->setTimestamp($this->creationDate); + $date->setTimestamp($this->createdAt); $date->setTimezone(new DateTimeZone('UTC')); return $date; } - private function setCreationDate(DateTime $creationDate): void + private function setCreatedAt(DateTime $createdAt): self { - $this->creationDate = $creationDate->getTimestamp(); + $this->createdAt = $createdAt->getTimestamp(); + + return $this; } #[ORM\PrePersist] - public function updateCreationDate(): void + public function updateCreatedAt(): DomainModel { - $this->setCreationDate(new DateTime()); + $this->setCreatedAt(new DateTime()); + return $this; } public function getExpiry(): DateTime @@ -79,14 +91,18 @@ public function getExpiry(): DateTime return $this->expiry; } - private function setExpiry(DateTime $expiry): void + private function setExpiry(DateTime $expiry): self { $this->expiry = $expiry; + + return $this; } - public function generateExpiry(): void + public function generateExpiry(): self { $this->setExpiry(new DateTime(static::DEFAULT_EXPIRY)); + + return $this; } public function getKey(): string @@ -94,15 +110,19 @@ public function getKey(): string return $this->key; } - public function setKey(string $key): void + public function setKey(string $key): self { $this->key = $key; + + return $this; } - public function generateKey(): void + public function generateKey(): self { $key = md5(random_bytes(256)); $this->setKey($key); + + return $this; } public function getAdministrator(): Administrator|Proxy|null @@ -110,8 +130,9 @@ public function getAdministrator(): Administrator|Proxy|null return $this->administrator; } - public function setAdministrator(Administrator $administrator): void + public function setAdministrator(Administrator $administrator): self { $this->administrator = $administrator; + return $this; } } diff --git a/src/Domain/Model/Interfaces/CreationDate.php b/src/Domain/Model/Interfaces/CreationDate.php index 41a6f9a..813970f 100644 --- a/src/Domain/Model/Interfaces/CreationDate.php +++ b/src/Domain/Model/Interfaces/CreationDate.php @@ -13,20 +13,12 @@ * The CreationDateTrait is the default implementation. * * @author Oliver Klee + * @author Tatevik Grigoryan */ interface CreationDate { /** * @return DateTime|null */ - public function getCreationDate(): ?DateTime; - - /** - * Updates the creation date to now. - * - * @PrePersist - * - * @return void - */ - public function updateCreationDate(): void; + public function getCreatedAt(): ?DateTime; } diff --git a/src/Domain/Model/Interfaces/EmbeddableInterface.php b/src/Domain/Model/Interfaces/EmbeddableInterface.php new file mode 100644 index 0000000..92524b7 --- /dev/null +++ b/src/Domain/Model/Interfaces/EmbeddableInterface.php @@ -0,0 +1,10 @@ +size = $size; } + public function getId(): ?int + { + return $this->id; + } + public function getFilename(): ?string { return $this->filename; } - public function setFilename(?string $filename): void + public function setFilename(?string $filename): self { $this->filename = $filename; + return $this; } public function getRemoteFile(): ?string @@ -60,9 +70,10 @@ public function getRemoteFile(): ?string return $this->remoteFile; } - public function setRemoteFile(?string $remoteFile): void + public function setRemoteFile(?string $remoteFile): self { $this->remoteFile = $remoteFile; + return $this; } public function getMimeType(): ?string @@ -70,9 +81,10 @@ public function getMimeType(): ?string return $this->mimeType; } - public function setMimeType(?string $mimeType): void + public function setMimeType(?string $mimeType): self { $this->mimeType = $mimeType; + return $this; } public function getDescription(): ?string @@ -80,9 +92,10 @@ public function getDescription(): ?string return $this->description; } - public function setDescription(?string $description): void + public function setDescription(?string $description): self { $this->description = $description; + return $this; } public function getSize(): ?int @@ -90,8 +103,9 @@ public function getSize(): ?int return $this->size; } - public function setSize(?int $size): void + public function setSize(?int $size): self { $this->size = $size; + return $this; } } diff --git a/src/Domain/Model/Messaging/Bounce.php b/src/Domain/Model/Messaging/Bounce.php index 3a4c066..a6a594d 100644 --- a/src/Domain/Model/Messaging/Bounce.php +++ b/src/Domain/Model/Messaging/Bounce.php @@ -8,8 +8,8 @@ use DateTime; use PhpList\Core\Domain\Model\Interfaces\DomainModel; use PhpList\Core\Domain\Model\Interfaces\Identity; -use PhpList\Core\Domain\Model\Traits\IdentityTrait; use PhpList\Core\Domain\Repository\Messaging\BounceRepository; +use Symfony\Component\Serializer\Attribute\Groups; #[ORM\Entity(repositoryClass: BounceRepository::class)] #[ORM\Table(name: 'phplist_bounce')] @@ -17,7 +17,11 @@ #[ORM\Index(name: 'statusidx', columns: ['status'])] class Bounce implements DomainModel, Identity { - use IdentityTrait; + #[ORM\Id] + #[ORM\Column(type: 'integer')] + #[ORM\GeneratedValue] + #[Groups(['SubscriberList', 'SubscriberListMembers'])] + private ?int $id = null; #[ORM\Column(type: 'datetime', nullable: true)] private ?DateTime $date; @@ -48,7 +52,7 @@ public function __construct( $this->comment = $comment; } - public function getId(): int + public function getId(): ?int { return $this->id; } @@ -58,9 +62,10 @@ public function getDate(): ?DateTime return $this->date; } - public function setDate(?DateTime $date): void + public function setDate(?DateTime $date): self { $this->date = $date; + return $this; } public function getHeader(): ?string @@ -68,9 +73,10 @@ public function getHeader(): ?string return $this->header; } - public function setHeader(?string $header): void + public function setHeader(?string $header): self { $this->header = $header; + return $this; } public function getData(): ?string @@ -78,9 +84,10 @@ public function getData(): ?string return $this->data; } - public function setData(?string $data): void + public function setData(?string $data): self { $this->data = $data; + return $this; } public function getStatus(): ?string @@ -88,9 +95,10 @@ public function getStatus(): ?string return $this->status; } - public function setStatus(?string $status): void + public function setStatus(?string $status): self { $this->status = $status; + return $this; } public function getComment(): ?string @@ -98,8 +106,9 @@ public function getComment(): ?string return $this->comment; } - public function setComment(?string $comment): void + public function setComment(?string $comment): self { $this->comment = $comment; + return $this; } } diff --git a/src/Domain/Model/Messaging/BounceRegex.php b/src/Domain/Model/Messaging/BounceRegex.php index d5179b9..67a5bba 100644 --- a/src/Domain/Model/Messaging/BounceRegex.php +++ b/src/Domain/Model/Messaging/BounceRegex.php @@ -7,15 +7,19 @@ use Doctrine\ORM\Mapping as ORM; use PhpList\Core\Domain\Model\Interfaces\DomainModel; use PhpList\Core\Domain\Model\Interfaces\Identity; -use PhpList\Core\Domain\Model\Traits\IdentityTrait; use PhpList\Core\Domain\Repository\Messaging\BounceRegexRepository; +use Symfony\Component\Serializer\Attribute\Groups; #[ORM\Entity(repositoryClass: BounceRegexRepository::class)] #[ORM\Table(name: 'phplist_bounceregex')] #[ORM\UniqueConstraint(name: 'regex', columns: ['regexhash'])] class BounceRegex implements DomainModel, Identity { - use IdentityTrait; + #[ORM\Id] + #[ORM\Column(type: 'integer')] + #[ORM\GeneratedValue] + #[Groups(['SubscriberList', 'SubscriberListMembers'])] + private ?int $id = null; #[ORM\Column(type: 'string', length: 2083, nullable: true)] private ?string $regex; @@ -61,7 +65,7 @@ public function __construct( $this->count = $count; } - public function getId(): int + public function getId(): ?int { return $this->id; } @@ -71,9 +75,10 @@ public function getRegex(): ?string return $this->regex; } - public function setRegex(?string $regex): void + public function setRegex(?string $regex): self { $this->regex = $regex; + return $this; } public function getRegexHash(): ?string @@ -81,9 +86,10 @@ public function getRegexHash(): ?string return $this->regexHash; } - public function setRegexHash(?string $regexHash): void + public function setRegexHash(?string $regexHash): self { $this->regexHash = $regexHash; + return $this; } public function getAction(): ?string @@ -91,9 +97,10 @@ public function getAction(): ?string return $this->action; } - public function setAction(?string $action): void + public function setAction(?string $action): self { $this->action = $action; + return $this; } public function getListOrder(): ?int @@ -101,9 +108,10 @@ public function getListOrder(): ?int return $this->listOrder; } - public function setListOrder(?int $listOrder): void + public function setListOrder(?int $listOrder): self { $this->listOrder = $listOrder; + return $this; } public function getAdmin(): ?int @@ -111,9 +119,10 @@ public function getAdmin(): ?int return $this->admin; } - public function setAdmin(?int $admin): void + public function setAdmin(?int $admin): self { $this->admin = $admin; + return $this; } public function getComment(): ?string @@ -121,9 +130,10 @@ public function getComment(): ?string return $this->comment; } - public function setComment(?string $comment): void + public function setComment(?string $comment): self { $this->comment = $comment; + return $this; } public function getStatus(): ?string @@ -131,9 +141,10 @@ public function getStatus(): ?string return $this->status; } - public function setStatus(?string $status): void + public function setStatus(?string $status): self { $this->status = $status; + return $this; } public function getCount(): ?int @@ -141,8 +152,9 @@ public function getCount(): ?int return $this->count; } - public function setCount(?int $count): void + public function setCount(?int $count): self { $this->count = $count; + return $this; } } diff --git a/src/Domain/Model/Messaging/BounceRegexBounce.php b/src/Domain/Model/Messaging/BounceRegexBounce.php index 7696770..de245fc 100644 --- a/src/Domain/Model/Messaging/BounceRegexBounce.php +++ b/src/Domain/Model/Messaging/BounceRegexBounce.php @@ -31,9 +31,10 @@ public function getRegex(): int return $this->regex; } - public function setRegex(int $regex): void + public function setRegex(int $regex): self { $this->regex = $regex; + return $this; } public function getBounce(): int @@ -41,8 +42,9 @@ public function getBounce(): int return $this->bounce; } - public function setBounce(int $bounce): void + public function setBounce(int $bounce): self { $this->bounce = $bounce; + return $this; } } diff --git a/src/Domain/Model/Messaging/ListMessage.php b/src/Domain/Model/Messaging/ListMessage.php index b587d8b..e3b48fb 100644 --- a/src/Domain/Model/Messaging/ListMessage.php +++ b/src/Domain/Model/Messaging/ListMessage.php @@ -10,9 +10,8 @@ use PhpList\Core\Domain\Model\Interfaces\DomainModel; use PhpList\Core\Domain\Model\Interfaces\Identity; use PhpList\Core\Domain\Model\Interfaces\ModificationDate; -use PhpList\Core\Domain\Model\Traits\IdentityTrait; -use PhpList\Core\Domain\Model\Traits\ModificationDateTrait; use PhpList\Core\Domain\Repository\Messaging\ListMessageRepository; +use Symfony\Component\Serializer\Attribute\Groups; #[ORM\Entity(repositoryClass: ListMessageRepository::class)] #[ORM\Table(name: 'phplist_listmessage')] @@ -21,8 +20,11 @@ #[ORM\HasLifecycleCallbacks] class ListMessage implements DomainModel, Identity, ModificationDate { - use IdentityTrait; - use ModificationDateTrait; + #[ORM\Id] + #[ORM\Column(type: 'integer')] + #[ORM\GeneratedValue] + #[Groups(['SubscriberList', 'SubscriberListMembers'])] + private ?int $id = null; #[ORM\Column(name: 'messageid', type: 'integer')] private int $messageId; @@ -30,9 +32,17 @@ class ListMessage implements DomainModel, Identity, ModificationDate #[ORM\Column(name: 'listid', type: 'integer')] private int $listId; - #[ORM\Column(type: 'datetime', nullable: true)] + #[ORM\Column(name: 'entered', type: 'datetime', nullable: true)] private ?DateTimeInterface $entered = null; + #[ORM\Column(name: 'modified', type: 'datetime')] + private ?DateTime $updatedAt = null; + + public function getId(): ?int + { + return $this->id; + } + public function getMessageId(): int { return $this->messageId; @@ -65,4 +75,18 @@ public function setEntered(?DateTimeInterface $entered): self $this->entered = $entered; return $this; } + + public function getUpdatedAt(): ?DateTime + { + return $this->updatedAt; + } + + #[ORM\PrePersist] + #[ORM\PreUpdate] + public function updateUpdatedAt(): DomainModel + { + $this->updatedAt = new DateTime(); + + return $this; + } } diff --git a/src/Domain/Model/Messaging/Message.php b/src/Domain/Model/Messaging/Message.php new file mode 100644 index 0000000..8ea9f88 --- /dev/null +++ b/src/Domain/Model/Messaging/Message.php @@ -0,0 +1,181 @@ + ''])] + private ?string $uuid = ''; + + #[ORM\ManyToOne(targetEntity: Administrator::class)] + #[ORM\JoinColumn(name: 'owner', referencedColumnName: 'id', nullable: true)] + private ?Administrator $owner; + + #[ORM\ManyToOne(targetEntity: Template::class)] + #[ORM\JoinColumn(name: 'template', referencedColumnName: 'id', nullable: true, onDelete: 'SET NULL')] + private ?Template $template = null; + + public function __construct( + MessageFormat $format, + MessageSchedule $schedule, + MessageMetadata $metadata, + MessageContent $content, + MessageOptions $options, + ?Administrator $owner, + ?Template $template = null, + ) { + $this->format = $format; + $this->schedule = $schedule; + $this->metadata = $metadata; + $this->content = $content; + $this->options = $options; + $this->uuid = bin2hex(random_bytes(18)); + $this->owner = $owner; + $this->template = $template; + } + + public function getId(): ?int + { + return $this->id; + } + + public function getUpdatedAt(): ?DateTime + { + return $this->updatedAt; + } + + #[ORM\PrePersist] + #[ORM\PreUpdate] + public function updateUpdatedAt(): DomainModel + { + $this->updatedAt = new DateTime(); + + return $this; + } + + public function getFormat(): MessageFormat + { + return $this->format; + } + + public function getSchedule(): MessageSchedule + { + return $this->schedule; + } + + public function getMetadata(): MessageMetadata + { + return $this->metadata; + } + + public function getContent(): MessageContent + { + return $this->content; + } + + public function getOptions(): MessageOptions + { + return $this->options; + } + + public function getUuid(): ?string + { + return $this->uuid; + } + + public function getOwner(): ?Administrator + { + return $this->owner; + } + + public function setOwner(?Administrator $owner): self + { + $this->owner = $owner; + return $this; + } + + public function getTemplate(): ?Template + { + return $this->template; + } + + public function setTemplate(?Template $template): self + { + $this->template = $template; + return $this; + } + + public function setFormat(MessageFormat $format): self + { + $this->format = $format; + return $this; + } + + public function setSchedule(MessageSchedule $schedule): self + { + $this->schedule = $schedule; + return $this; + } + + public function setMetadata(MessageMetadata $metadata): self + { + $this->metadata = $metadata; + return $this; + } + + public function setContent(MessageContent $content): self + { + $this->content = $content; + return $this; + } + + public function setOptions(MessageOptions $options): self + { + $this->options = $options; + return $this; + } +} diff --git a/src/Domain/Model/Messaging/Message/Message.php b/src/Domain/Model/Messaging/Message/Message.php deleted file mode 100644 index a2285da..0000000 --- a/src/Domain/Model/Messaging/Message/Message.php +++ /dev/null @@ -1,87 +0,0 @@ - ''])] - private ?string $uuid = ''; - - public function __construct( - MessageFormat $format, - MessageSchedule $schedule, - MessageMetadata $metadata, - MessageContent $content, - MessageOptions $options - ) { - $this->format = $format; - $this->schedule = $schedule; - $this->metadata = $metadata; - $this->content = $content; - $this->options = $options; - $this->uuid = bin2hex(random_bytes(18)); - } - - public function getFormat(): MessageFormat - { - return $this->format; - } - - public function getSchedule(): MessageSchedule - { - return $this->schedule; - } - - public function getMetadata(): MessageMetadata - { - return $this->metadata; - } - - public function getContent(): MessageContent - { - return $this->content; - } - - public function getOptions(): MessageOptions - { - return $this->options; - } - - public function getUuid(): ?string - { - return $this->uuid; - } -} diff --git a/src/Domain/Model/Messaging/Message/MessageContent.php b/src/Domain/Model/Messaging/Message/MessageContent.php index 6474c4e..b80580a 100644 --- a/src/Domain/Model/Messaging/Message/MessageContent.php +++ b/src/Domain/Model/Messaging/Message/MessageContent.php @@ -5,14 +5,15 @@ namespace PhpList\Core\Domain\Model\Messaging\Message; use Doctrine\ORM\Mapping as ORM; +use PhpList\Core\Domain\Model\Interfaces\EmbeddableInterface; #[ORM\Embeddable] -class MessageContent +class MessageContent implements EmbeddableInterface { #[ORM\Column(type: 'string', length: 255, nullable: false, options: ['default' => '(no subject)'])] private string $subject; - #[ORM\Column(type: 'text', nullable: true)] + #[ORM\Column(name:'message', type: 'text', nullable: true)] private ?string $text = null; #[ORM\Column(name: 'textmessage', type: 'text', nullable: true)] @@ -60,8 +61,20 @@ public function getTextMessage(): ?string return $this->textMessage; } + public function setTextMessage(?string $textMessage): self + { + $this->textMessage = $textMessage; + return $this; + } + public function getFooter(): ?string { return $this->footer; } + + public function setFooter(?string $footer): self + { + $this->footer = $footer; + return $this; + } } diff --git a/src/Domain/Model/Messaging/Message/MessageFormat.php b/src/Domain/Model/Messaging/Message/MessageFormat.php index e4de42c..90fc56f 100644 --- a/src/Domain/Model/Messaging/Message/MessageFormat.php +++ b/src/Domain/Model/Messaging/Message/MessageFormat.php @@ -5,35 +5,46 @@ namespace PhpList\Core\Domain\Model\Messaging\Message; use Doctrine\ORM\Mapping as ORM; +use InvalidArgumentException; +use PhpList\Core\Domain\Model\Interfaces\EmbeddableInterface; #[ORM\Embeddable] -class MessageFormat +class MessageFormat implements EmbeddableInterface { - #[ORM\Column(type: 'boolean', options: ['default' => false])] + #[ORM\Column(name: 'htmlformatted', type: 'boolean', options: ['default' => false])] private bool $htmlFormatted = false; #[ORM\Column(name: 'sendformat', type: 'string', length: 20, nullable: true)] private ?string $sendFormat = null; #[ORM\Column(name: 'astext', type: 'integer', options: ['default' => 0])] - private int $asText = 0; + private bool $asText = false; #[ORM\Column(name: 'ashtml', type: 'integer', options: ['default' => 0])] - private int $asHtml = 0; - - #[ORM\Column(name: 'astextandhtml', type: 'integer', options: ['default' => 0])] - private int $asTextAndHtml = 0; + private bool $asHtml = false; #[ORM\Column(name: 'aspdf', type: 'integer', options: ['default' => 0])] - private int $asPdf = 0; + private bool $asPdf = false; + + #[ORM\Column(name: 'astextandhtml', type: 'integer', options: ['default' => 0])] + private bool $asTextAndHtml = false; #[ORM\Column(name: 'astextandpdf', type: 'integer', options: ['default' => 0])] - private int $asTextAndPdf = 0; + private bool $asTextAndPdf = false; - public function __construct(bool $htmlFormatted, ?string $sendFormat) - { + public const FORMAT_TEXT = 'text'; + public const FORMAT_HTML = 'html'; + public const FORMAT_PDF = 'pdf'; + + public function __construct( + bool $htmlFormatted, + ?string $sendFormat, + array $formatOptions = [] + ) { $this->htmlFormatted = $htmlFormatted; $this->sendFormat = $sendFormat; + + $this->setFormatOptions($formatOptions); } public function isHtmlFormatted(): bool @@ -41,39 +52,71 @@ public function isHtmlFormatted(): bool return $this->htmlFormatted; } + public function setHtmlFormatted(bool $htmlFormatted): self + { + $this->htmlFormatted = $htmlFormatted; + return $this; + } + public function getSendFormat(): ?string { return $this->sendFormat; } - public function getAsText(): int + public function setSendFormat(?string $sendFormat): self + { + $this->sendFormat = $sendFormat; + return $this; + } + + public function isAsText(): bool { return $this->asText; } - public function getAsHtml(): int + public function isAsHtml(): bool { return $this->asHtml; } - public function getAsTextAndHtml(): int + public function isAsTextAndHtml(): bool { return $this->asTextAndHtml; } - public function getAsPdf(): int + public function isAsPdf(): bool { return $this->asPdf; } - public function getAsTextAndPdf(): int + public function isAsTextAndPdf(): bool { return $this->asTextAndPdf; } - public function setSendFormat(?string $sendFormat): self + public function getFormatOptions(): array { - $this->sendFormat = $sendFormat; + return array_values(array_filter([ + $this->asText ? self::FORMAT_TEXT : null, + $this->asHtml ? self::FORMAT_HTML : null, + $this->asPdf ? self::FORMAT_PDF : null, + ])); + } + + public function setFormatOptions(array $formatOptions): self + { + foreach ($formatOptions as $option) { + match ($option) { + self::FORMAT_TEXT => $this->asText = true, + self::FORMAT_HTML => $this->asHtml = true, + self::FORMAT_PDF => $this->asPdf = true, + default => throw new InvalidArgumentException('Invalid format option: ' . $option) + }; + } + + $this->asTextAndHtml = $this->asText && $this->asHtml; + $this->asTextAndPdf = $this->asText && $this->asPdf; + return $this; } } diff --git a/src/Domain/Model/Messaging/Message/MessageMetadata.php b/src/Domain/Model/Messaging/Message/MessageMetadata.php index 6e2a52e..3e4452a 100644 --- a/src/Domain/Model/Messaging/Message/MessageMetadata.php +++ b/src/Domain/Model/Messaging/Message/MessageMetadata.php @@ -6,18 +6,19 @@ use DateTime; use Doctrine\ORM\Mapping as ORM; +use PhpList\Core\Domain\Model\Interfaces\EmbeddableInterface; #[ORM\Embeddable] -class MessageMetadata +class MessageMetadata implements EmbeddableInterface { #[ORM\Column(type: 'string', length: 255, nullable: true)] private ?string $status = null; - #[ORM\Column(type: 'integer', options: ['unsigned' => true, 'default' => 0])] - private int $processed; + #[ORM\Column(type: 'boolean', options: ['unsigned' => true, 'default' => false])] + private bool $processed; #[ORM\Column(type: 'integer', options: ['default' => 0])] - private int $viewed; + private int $viewed = 0; #[ORM\Column(name: 'bouncecount', type: 'integer', options: ['default' => 0])] private int $bounceCount; @@ -28,20 +29,23 @@ class MessageMetadata #[ORM\Column(type: 'datetime', nullable: true)] private ?DateTime $sent; + #[ORM\Column(name: 'sendstart', type: 'datetime', nullable: true)] + private ?DateTime $sendStart; + public function __construct( ?string $status = null, - int $processed = 0, - int $viewed = 0, int $bounceCount = 0, ?DateTime $entered = null, ?DateTime $sent = null, + ?DateTime $sendStart = null, ) { $this->status = $status; - $this->processed = $processed; - $this->viewed = $viewed; + $this->processed = false; + $this->viewed = 0; $this->bounceCount = $bounceCount; $this->entered = $entered ?? new DateTime(); $this->sent = $sent; + $this->sendStart = $sendStart; } public function getStatus(): ?string @@ -49,18 +53,30 @@ public function getStatus(): ?string return $this->status; } - public function getProcessed(): int + public function setStatus(string $status): self + { + $this->status = $status; + return $this; + } + + public function isProcessed(): bool { return $this->processed; } - public function setProcessed(int $processed): self + public function setProcessed(bool $processed): self { $this->processed = $processed; return $this; } - public function getViewed(): int + public function setViews(int $viewed): self + { + $this->viewed = $viewed; + return $this; + } + + public function getViews(): int { return $this->viewed; } @@ -79,4 +95,33 @@ public function getSent(): ?DateTime { return $this->sent; } + + public function setBounceCount(int $bounceCount): self + { + $this->bounceCount = $bounceCount; + return $this; + } + + public function setEntered(?DateTime $entered): self + { + $this->entered = $entered; + return $this; + } + + public function setSent(?DateTime $sent): self + { + $this->sent = $sent; + return $this; + } + + public function getSendStart(): ?DateTime + { + return $this->sendStart; + } + + public function setSendStart(?DateTime $sendStart): self + { + $this->sendStart = $sendStart; + return $this; + } } diff --git a/src/Domain/Model/Messaging/Message/MessageOptions.php b/src/Domain/Model/Messaging/Message/MessageOptions.php index 0c88552..002d3c9 100644 --- a/src/Domain/Model/Messaging/Message/MessageOptions.php +++ b/src/Domain/Model/Messaging/Message/MessageOptions.php @@ -5,10 +5,10 @@ namespace PhpList\Core\Domain\Model\Messaging\Message; use Doctrine\ORM\Mapping as ORM; -use DateTime; +use PhpList\Core\Domain\Model\Interfaces\EmbeddableInterface; #[ORM\Embeddable] -class MessageOptions +class MessageOptions implements EmbeddableInterface { #[ORM\Column(name: 'fromfield', type: 'string', length: 255, nullable: false, options: ['default' => ''])] private string $fromField; @@ -19,44 +19,24 @@ class MessageOptions #[ORM\Column(name: 'replyto', type: 'string', length: 255, nullable: false, options: ['default' => ''])] private string $replyTo; - #[ORM\Column(type: 'datetime', nullable: true)] - private ?DateTime $embargo; - #[ORM\Column(name: 'userselection', type: 'text', nullable: true)] private ?string $userSelection; - #[ORM\Column(type: 'integer', nullable: true)] - private ?int $template; - - #[ORM\Column(name: 'sendstart', type: 'datetime', nullable: true)] - private ?DateTime $sendStart; - #[ORM\Column(name: 'rsstemplate', type: 'string', length: 100, nullable: true)] private ?string $rssTemplate; - #[ORM\Column(type: 'integer', nullable: true)] - private ?int $owner; - public function __construct( string $fromField = '', string $toField = '', string $replyTo = '', - ?DateTime $embargo = null, ?string $userSelection = null, - ?int $template = null, - ?DateTime $sendStart = null, - ?string $rssTemplate = null, - ?int $owner = null + ?string $rssTemplate = null ) { $this->fromField = $fromField; $this->toField = $toField; $this->replyTo = $replyTo; - $this->embargo = $embargo; $this->userSelection = $userSelection; - $this->template = $template; - $this->sendStart = $sendStart; $this->rssTemplate = $rssTemplate; - $this->owner = $owner; } public function getFromField(): string @@ -69,38 +49,48 @@ public function getToField(): string return $this->toField; } - public function getReplyToO(): string + public function getReplyTo(): string { return $this->replyTo; } - public function getEmbargo(): ?DateTime + public function getUserSelection(): ?string { - return $this->embargo; + return $this->userSelection; } - public function getUserSelection(): ?string + public function getRssTemplate(): ?string { - return $this->userSelection; + return $this->rssTemplate; } - public function getTemplate(): ?int + public function setFromField(string $fromField): self { - return $this->template; + $this->fromField = $fromField; + return $this; } - public function getSendStart(): ?DateTime + public function setToField(string $toField): self { - return $this->sendStart; + $this->toField = $toField; + return $this; } - public function getRssTemplate(): ?string + public function setReplyTo(string $replyTo): self { - return $this->rssTemplate; + $this->replyTo = $replyTo; + return $this; } - public function getOwner(): ?int + public function setUserSelection(?string $userSelection): self { - return $this->owner; + $this->userSelection = $userSelection; + return $this; + } + + public function setRssTemplate(?string $rssTemplate): self + { + $this->rssTemplate = $rssTemplate; + return $this; } } diff --git a/src/Domain/Model/Messaging/Message/MessageSchedule.php b/src/Domain/Model/Messaging/Message/MessageSchedule.php index 28b82c4..3448f8d 100644 --- a/src/Domain/Model/Messaging/Message/MessageSchedule.php +++ b/src/Domain/Model/Messaging/Message/MessageSchedule.php @@ -6,9 +6,10 @@ use DateTime; use Doctrine\ORM\Mapping as ORM; +use PhpList\Core\Domain\Model\Interfaces\EmbeddableInterface; #[ORM\Embeddable] -class MessageSchedule +class MessageSchedule implements EmbeddableInterface { #[ORM\Column(name: 'repeatinterval', type: 'integer', nullable: true, options: ['default' => 0])] private ?int $repeatInterval; @@ -22,16 +23,21 @@ class MessageSchedule #[ORM\Column(name: 'requeueuntil', type: 'datetime', nullable: true)] private ?DateTime $requeueUntil; + #[ORM\Column(type: 'datetime', nullable: true)] + private ?DateTime $embargo; + public function __construct( ?int $repeatInterval, ?DateTime $repeatUntil, ?int $requeueInterval, - ?DateTime $requeueUntil + ?DateTime $requeueUntil, + ?DateTime $embargo ) { $this->repeatInterval = $repeatInterval; $this->repeatUntil = $repeatUntil; $this->requeueInterval = $requeueInterval; $this->requeueUntil = $requeueUntil; + $this->embargo = $embargo; } public function getRepeatInterval(): ?int @@ -53,4 +59,39 @@ public function getRequeueUntil(): ?DateTime { return $this->requeueUntil; } + + public function getEmbargo(): ?DateTime + { + return $this->embargo; + } + + public function setRepeatInterval(?int $repeatInterval): self + { + $this->repeatInterval = $repeatInterval; + return $this; + } + + public function setRepeatUntil(?DateTime $repeatUntil): self + { + $this->repeatUntil = $repeatUntil; + return $this; + } + + public function setRequeueInterval(?int $requeueInterval): self + { + $this->requeueInterval = $requeueInterval; + return $this; + } + + public function setRequeueUntil(?DateTime $requeueUntil): self + { + $this->requeueUntil = $requeueUntil; + return $this; + } + + public function setEmbargo(?DateTime $embargo): self + { + $this->embargo = $embargo; + return $this; + } } diff --git a/src/Domain/Model/Messaging/MessageAttachment.php b/src/Domain/Model/Messaging/MessageAttachment.php index a4baaf8..6f6ae72 100644 --- a/src/Domain/Model/Messaging/MessageAttachment.php +++ b/src/Domain/Model/Messaging/MessageAttachment.php @@ -6,7 +6,7 @@ use Doctrine\ORM\Mapping as ORM; use PhpList\Core\Domain\Model\Interfaces\Identity; -use PhpList\Core\Domain\Model\Traits\IdentityTrait; +use Symfony\Component\Serializer\Attribute\Groups; #[ORM\Entity] #[ORM\Table(name: 'phplist_message_attachment')] @@ -14,7 +14,11 @@ #[ORM\Index(name: 'messageidx', columns: ['messageid'])] class MessageAttachment implements Identity { - use IdentityTrait; + #[ORM\Id] + #[ORM\Column(type: 'integer')] + #[ORM\GeneratedValue] + #[Groups(['SubscriberList', 'SubscriberListMembers'])] + private ?int $id = null; #[ORM\Column(name: 'messageid', type: 'integer')] private int $messageId; @@ -22,6 +26,11 @@ class MessageAttachment implements Identity #[ORM\Column(name: 'attachmentid', type: 'integer')] private int $attachmentId; + public function getId(): ?int + { + return $this->id; + } + public function getMessageId(): int { return $this->messageId; diff --git a/src/Domain/Model/Messaging/SendProcess.php b/src/Domain/Model/Messaging/SendProcess.php index 1db3623..9c32a55 100644 --- a/src/Domain/Model/Messaging/SendProcess.php +++ b/src/Domain/Model/Messaging/SendProcess.php @@ -9,16 +9,21 @@ use PhpList\Core\Domain\Model\Interfaces\DomainModel; use PhpList\Core\Domain\Model\Interfaces\Identity; use PhpList\Core\Domain\Model\Interfaces\ModificationDate; -use PhpList\Core\Domain\Model\Traits\IdentityTrait; -use PhpList\Core\Domain\Model\Traits\ModificationDateTrait; +use Symfony\Component\Serializer\Attribute\Groups; #[ORM\Entity] #[ORM\Table(name: 'phplist_sendprocess')] #[ORM\HasLifecycleCallbacks] class SendProcess implements DomainModel, Identity, ModificationDate { - use IdentityTrait; - use ModificationDateTrait; + #[ORM\Id] + #[ORM\Column(type: 'integer')] + #[ORM\GeneratedValue] + #[Groups(['SubscriberList', 'SubscriberListMembers'])] + private ?int $id = null; + + #[ORM\Column(name: 'modified', type: 'datetime')] + private ?DateTime $updatedAt = null; #[ORM\Column(name: 'started', type: 'datetime', nullable: true)] private ?DateTime $started = null; @@ -32,6 +37,25 @@ class SendProcess implements DomainModel, Identity, ModificationDate #[ORM\Column(name: 'page', type: 'string', length: 100, nullable: true)] private ?string $page = null; + public function getId(): ?int + { + return $this->id; + } + + public function getUpdatedAt(): ?DateTime + { + return $this->updatedAt; + } + + #[ORM\PrePersist] + #[ORM\PreUpdate] + public function updateUpdatedAt(): DomainModel + { + $this->updatedAt = new DateTime(); + + return $this; + } + public function getStartedDate(): ?DateTime { return $this->started; diff --git a/src/Domain/Model/Messaging/Template.php b/src/Domain/Model/Messaging/Template.php index 3236f64..420ba9b 100644 --- a/src/Domain/Model/Messaging/Template.php +++ b/src/Domain/Model/Messaging/Template.php @@ -9,23 +9,26 @@ use Doctrine\ORM\Mapping as ORM; use PhpList\Core\Domain\Model\Interfaces\DomainModel; use PhpList\Core\Domain\Model\Interfaces\Identity; -use PhpList\Core\Domain\Model\Traits\IdentityTrait; +use PhpList\Core\Domain\Repository\Messaging\TemplateRepository; -#[ORM\Entity] +#[ORM\Entity(repositoryClass: TemplateRepository::class)] #[ORM\Table(name: 'phplist_template')] #[ORM\UniqueConstraint(name: 'title', columns: ['title'])] class Template implements DomainModel, Identity { - use IdentityTrait; + #[ORM\Id] + #[ORM\Column(type: 'integer')] + #[ORM\GeneratedValue] + private ?int $id = null; #[ORM\Column(name: 'title', type: 'string', length: 255, unique: true)] private string $title; #[ORM\Column(name: 'template', type: 'blob', nullable: true)] - private ?string $template = null; + private mixed $content; #[ORM\Column(name: 'template_text', type: 'blob', nullable: true)] - private ?string $templateText = null; + private mixed $text; #[ORM\Column(name: 'listorder', type: 'integer', nullable: true)] private ?int $listOrder = null; @@ -38,24 +41,40 @@ class Template implements DomainModel, Identity )] private Collection $images; - public function __construct() + public function __construct(string $title) { + $this->title = $title; $this->images = new ArrayCollection(); } + public function getId(): ?int + { + return $this->id; + } + public function getTitle(): string { return $this->title; } - public function getTemplate(): ?string + public function getContent(): ?string { - return $this->template; + if (is_resource($this->content)) { + rewind($this->content); + return stream_get_contents($this->content); + } + + return $this->content; } - public function getTemplateText(): ?string + public function getText(): ?string { - return $this->templateText; + if (is_resource($this->text)) { + rewind($this->text); + return stream_get_contents($this->text); + } + + return $this->text; } public function getListOrder(): ?int @@ -74,15 +93,16 @@ public function setTitle(string $title): self return $this; } - public function setTemplate(?string $template): self + public function setContent(?string $content): self { - $this->template = $template; + $this->content = $content !== null ? fopen('data://text/plain,' . $content, 'r') : null; return $this; } - public function setTemplateText(?string $templateText): self + + public function setText(?string $text): self { - $this->templateText = $templateText; + $this->text = $text !== null ? fopen('data://text/plain,' . $text, 'r') : null; return $this; } diff --git a/src/Domain/Model/Messaging/TemplateImage.php b/src/Domain/Model/Messaging/TemplateImage.php index dd95f89..09ff6b2 100644 --- a/src/Domain/Model/Messaging/TemplateImage.php +++ b/src/Domain/Model/Messaging/TemplateImage.php @@ -7,14 +7,18 @@ use Doctrine\ORM\Mapping as ORM; use PhpList\Core\Domain\Model\Interfaces\DomainModel; use PhpList\Core\Domain\Model\Interfaces\Identity; -use PhpList\Core\Domain\Model\Traits\IdentityTrait; +use PhpList\Core\Domain\Repository\Messaging\TemplateImageRepository; -#[ORM\Entity] +#[ORM\Entity(repositoryClass: TemplateImageRepository::class)] #[ORM\Table(name: 'phplist_templateimage')] #[ORM\Index(name: 'templateidx', columns: ['template'])] class TemplateImage implements DomainModel, Identity { - use IdentityTrait; + #[ORM\Id] + #[ORM\Column(type: 'integer')] + #[ORM\GeneratedValue] + private ?int $id = null; + #[ORM\ManyToOne(targetEntity: Template::class)] #[ORM\JoinColumn(name: 'template', referencedColumnName: 'id', nullable: false, onDelete: 'CASCADE')] private Template $template; @@ -26,7 +30,7 @@ class TemplateImage implements DomainModel, Identity private ?string $filename = null; #[ORM\Column(name: 'data', type: 'blob', nullable: true)] - private ?string $data = null; + private mixed $data = null; #[ORM\Column(name: 'width', type: 'integer', nullable: true)] private ?int $width = null; @@ -34,6 +38,11 @@ class TemplateImage implements DomainModel, Identity #[ORM\Column(name: 'height', type: 'integer', nullable: true)] private ?int $height = null; + public function getId(): ?int + { + return $this->id; + } + public function getTemplate(): ?Template { return $this->template; @@ -51,6 +60,11 @@ public function getFilename(): ?string public function getData(): ?string { + if (is_resource($this->data)) { + rewind($this->data); + return stream_get_contents($this->data); + } + return $this->data; } @@ -84,7 +98,7 @@ public function setFilename(?string $filename): self public function setData(?string $data): self { - $this->data = $data; + $this->data = $data !== null ? fopen('data://text/plain,' . $data, 'r') : null; return $this; } diff --git a/src/Domain/Model/Messaging/UserMessage.php b/src/Domain/Model/Messaging/UserMessage.php index f62dca2..2fc3eeb 100644 --- a/src/Domain/Model/Messaging/UserMessage.php +++ b/src/Domain/Model/Messaging/UserMessage.php @@ -7,7 +7,6 @@ use DateTime; use Doctrine\ORM\Mapping as ORM; use PhpList\Core\Domain\Model\Interfaces\DomainModel; -use PhpList\Core\Domain\Model\Messaging\Message\Message; use PhpList\Core\Domain\Model\Subscription\Subscriber; #[ORM\Entity] diff --git a/src/Domain/Model/Messaging/UserMessageBounce.php b/src/Domain/Model/Messaging/UserMessageBounce.php index 280c2d8..c03ff8c 100644 --- a/src/Domain/Model/Messaging/UserMessageBounce.php +++ b/src/Domain/Model/Messaging/UserMessageBounce.php @@ -8,7 +8,6 @@ use Doctrine\ORM\Mapping as ORM; use PhpList\Core\Domain\Model\Interfaces\DomainModel; use PhpList\Core\Domain\Model\Interfaces\Identity; -use PhpList\Core\Domain\Model\Traits\IdentityTrait; #[ORM\Entity] #[ORM\Table(name: 'phplist_user_message_bounce')] @@ -19,7 +18,10 @@ #[ORM\HasLifecycleCallbacks] class UserMessageBounce implements DomainModel, Identity { - use IdentityTrait; + #[ORM\Id] + #[ORM\Column(type: 'integer')] + #[ORM\GeneratedValue] + private ?int $id = null; #[ORM\Column(name: 'user', type: 'integer')] private int $user; @@ -38,6 +40,11 @@ public function __construct() $this->time = new DateTime(); } + public function getId(): ?int + { + return $this->id; + } + public function getUser(): int { return $this->user; diff --git a/src/Domain/Model/Messaging/UserMessageForward.php b/src/Domain/Model/Messaging/UserMessageForward.php index ac79f4d..153d307 100644 --- a/src/Domain/Model/Messaging/UserMessageForward.php +++ b/src/Domain/Model/Messaging/UserMessageForward.php @@ -8,7 +8,6 @@ use Doctrine\ORM\Mapping as ORM; use PhpList\Core\Domain\Model\Interfaces\DomainModel; use PhpList\Core\Domain\Model\Interfaces\Identity; -use PhpList\Core\Domain\Model\Traits\IdentityTrait; #[ORM\Entity] #[ORM\Table(name: 'phplist_user_message_forward')] @@ -17,7 +16,10 @@ #[ORM\Index(name: 'usermessageidx', columns: ['user', 'message'])] class UserMessageForward implements DomainModel, Identity { - use IdentityTrait; + #[ORM\Id] + #[ORM\Column(type: 'integer')] + #[ORM\GeneratedValue] + private ?int $id = null; #[ORM\Column(name: 'user', type: 'integer')] private int $user; @@ -34,6 +36,11 @@ class UserMessageForward implements DomainModel, Identity #[ORM\Column(name: 'time', type: 'datetime', options: ['default' => 'CURRENT_TIMESTAMP'])] private DateTime $time; + public function getId(): ?int + { + return $this->id; + } + public function getUser(): int { return $this->user; diff --git a/src/Domain/Model/Subscription/SubscribePage.php b/src/Domain/Model/Subscription/SubscribePage.php index 75f2b15..e58e199 100644 --- a/src/Domain/Model/Subscription/SubscribePage.php +++ b/src/Domain/Model/Subscription/SubscribePage.php @@ -7,13 +7,17 @@ use Doctrine\ORM\Mapping as ORM; use PhpList\Core\Domain\Model\Interfaces\DomainModel; use PhpList\Core\Domain\Model\Interfaces\Identity; -use PhpList\Core\Domain\Model\Traits\IdentityTrait; +use Symfony\Component\Serializer\Attribute\Groups; #[ORM\Entity] #[ORM\Table(name: 'phplist_subscribepage')] class SubscribePage implements DomainModel, Identity { - use IdentityTrait; + #[ORM\Id] + #[ORM\Column(type: 'integer')] + #[ORM\GeneratedValue] + #[Groups(['SubscriberList', 'SubscriberListMembers'])] + private ?int $id = null; #[ORM\Column(name: 'title', type: 'string', length: 255)] private string $title; @@ -24,6 +28,11 @@ class SubscribePage implements DomainModel, Identity #[ORM\Column(name: 'owner', type: 'integer', nullable: true)] private ?int $owner = null; + public function getId(): ?int + { + return $this->id; + } + public function getTitle(): string { return $this->title; diff --git a/src/Domain/Model/Subscription/Subscriber.php b/src/Domain/Model/Subscription/Subscriber.php index ce1fec5..0e693c2 100644 --- a/src/Domain/Model/Subscription/Subscriber.php +++ b/src/Domain/Model/Subscription/Subscriber.php @@ -9,21 +9,18 @@ use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; use PhpList\Core\Domain\Repository\Subscription\SubscriberRepository; -use Symfony\Component\Serializer\Annotation\Ignore; use Symfony\Component\Serializer\Annotation\SerializedName; use PhpList\Core\Domain\Model\Interfaces\CreationDate; use PhpList\Core\Domain\Model\Interfaces\DomainModel; use PhpList\Core\Domain\Model\Interfaces\Identity; use PhpList\Core\Domain\Model\Interfaces\ModificationDate; -use PhpList\Core\Domain\Model\Traits\CreationDateTrait; -use PhpList\Core\Domain\Model\Traits\IdentityTrait; -use PhpList\Core\Domain\Model\Traits\ModificationDateTrait; use Symfony\Component\Serializer\Attribute\Groups; /** * This class represents subscriber who can subscribe to multiple subscriber lists and can receive email messages from * campaigns for those subscriber lists. * @author Oliver Klee + * @author Tatevik Grigoryan */ #[ORM\Entity(repositoryClass: SubscriberRepository::class)] #[ORM\Table(name: 'phplist_user_user')] @@ -34,14 +31,19 @@ #[ORM\HasLifecycleCallbacks] class Subscriber implements DomainModel, Identity, CreationDate, ModificationDate { - use IdentityTrait; - use CreationDateTrait; - use ModificationDateTrait; + #[ORM\Id] + #[ORM\Column(type: 'integer')] + #[ORM\GeneratedValue] + #[Groups(['SubscriberList', 'SubscriberListMembers'])] + private ?int $id = null; #[ORM\Column(name: 'entered', type: 'datetime', nullable: true)] #[SerializedName('creation_date')] #[Groups(['SubscriberListMembers'])] - protected ?DateTime $creationDate = null; + protected ?DateTime $createdAt = null; + + #[ORM\Column(name: 'modified', type: 'datetime')] + private ?DateTime $updatedAt = null; #[ORM\Column(unique: true)] #[SerializedName('email')] @@ -83,17 +85,54 @@ class Subscriber implements DomainModel, Identity, CreationDate, ModificationDat private ?string $extraData; #[ORM\OneToMany( - targetEntity: 'PhpList\Core\Domain\Model\Subscription\Subscription', + targetEntity: Subscription::class, mappedBy: 'subscriber', cascade: ['remove'], orphanRemoval: true, )] private Collection $subscriptions; + /** + * @var Collection + */ + #[ORM\OneToMany( + targetEntity: SubscriberAttribute::class, + mappedBy: 'subscriber', + cascade: ['persist', 'remove'], + orphanRemoval: true + )] + private Collection $attributes; + public function __construct() { $this->subscriptions = new ArrayCollection(); + $this->attributes = new ArrayCollection(); $this->extraData = ''; + $this->createdAt = new DateTime(); + } + + public function getId(): ?int + { + return $this->id; + } + + public function getCreatedAt(): ?DateTime + { + return $this->createdAt; + } + + public function getUpdatedAt(): ?DateTime + { + return $this->updatedAt; + } + + #[ORM\PrePersist] + #[ORM\PreUpdate] + public function updateUpdatedAt(): DomainModel + { + $this->updatedAt = new DateTime(); + + return $this; } public function isConfirmed(): bool @@ -101,9 +140,11 @@ public function isConfirmed(): bool return $this->confirmed; } - public function setConfirmed(bool $confirmed): void + public function setConfirmed(bool $confirmed): self { $this->confirmed = $confirmed; + + return $this; } public function isBlacklisted(): bool @@ -111,9 +152,11 @@ public function isBlacklisted(): bool return $this->blacklisted; } - public function setBlacklisted(bool $blacklisted): void + public function setBlacklisted(bool $blacklisted): self { $this->blacklisted = $blacklisted; + + return $this; } public function getBounceCount(): int @@ -121,14 +164,18 @@ public function getBounceCount(): int return $this->bounceCount; } - public function setBounceCount(int $bounceCount): void + public function setBounceCount(int $bounceCount): self { $this->bounceCount = $bounceCount; + + return $this; } - public function addToBounceCount(int $delta): void + public function addToBounceCount(int $delta): self { $this->setBounceCount($this->getBounceCount() + $delta); + + return $this; } public function getUniqueId(): string @@ -136,15 +183,18 @@ public function getUniqueId(): string return $this->uniqueId; } - public function setUniqueId(string $uniqueId): void + public function setUniqueId(string $uniqueId): self { $this->uniqueId = $uniqueId; + + return $this; } #[ORM\PrePersist] - public function generateUniqueId(): void + public function generateUniqueId(): self { $this->setUniqueId(bin2hex(random_bytes(16))); + return $this; } public function getEmail(): string @@ -152,9 +202,11 @@ public function getEmail(): string return $this->email; } - public function setEmail(string $email): void + public function setEmail(string $email): self { $this->email = $email; + + return $this; } public function hasHtmlEmail(): bool @@ -162,9 +214,11 @@ public function hasHtmlEmail(): bool return $this->htmlEmail; } - public function setHtmlEmail(bool $htmlEmail): void + public function setHtmlEmail(bool $htmlEmail): self { $this->htmlEmail = $htmlEmail; + + return $this; } public function isDisabled(): bool @@ -172,9 +226,11 @@ public function isDisabled(): bool return $this->disabled; } - public function setDisabled(bool $disabled): void + public function setDisabled(bool $disabled): self { $this->disabled = $disabled; + + return $this; } public function getExtraData(): string @@ -182,9 +238,11 @@ public function getExtraData(): string return $this->extraData; } - public function setExtraData(string $extraData): void + public function setExtraData(string $extraData): self { $this->extraData = $extraData; + + return $this; } /** @@ -223,4 +281,24 @@ public function getSubscribedLists(): Collection return $result; } + + public function getAttributes(): Collection + { + return $this->attributes; + } + + public function addAttribute(SubscriberAttribute $attribute): self + { + if (!$this->attributes->contains($attribute)) { + $this->attributes[] = $attribute; + } + + return $this; + } + + public function removeAttribute(SubscriberAttribute $attribute): self + { + $this->attributes->removeElement($attribute); + return $this; + } } diff --git a/src/Domain/Model/Subscription/SubscriberAttribute.php b/src/Domain/Model/Subscription/SubscriberAttribute.php index 4bdc44f..47844e3 100644 --- a/src/Domain/Model/Subscription/SubscriberAttribute.php +++ b/src/Domain/Model/Subscription/SubscriberAttribute.php @@ -15,8 +15,9 @@ class SubscriberAttribute implements DomainModel { #[ORM\Id] - #[ORM\Column(name: 'attributeid', type: 'integer', nullable: false)] - private int $id; + #[ORM\ManyToOne(targetEntity: SubscriberAttributeDefinition::class)] + #[ORM\JoinColumn(name: 'attributeid', referencedColumnName: 'id', nullable: false, onDelete: 'CASCADE')] + private SubscriberAttributeDefinition $attributeDefinition; #[ORM\Id] #[ORM\ManyToOne(targetEntity: Subscriber::class)] @@ -26,15 +27,15 @@ class SubscriberAttribute implements DomainModel #[ORM\Column(name: 'value', type: 'text', nullable: true)] private ?string $value = null; - public function __construct(int $id, Subscriber $subscriber) + public function __construct(SubscriberAttributeDefinition $attributeDefinition, Subscriber $subscriber) { - $this->id = $id; + $this->attributeDefinition = $attributeDefinition; $this->subscriber = $subscriber; } - public function getId(): int + public function getAttributeDefinition(): SubscriberAttributeDefinition { - return $this->id; + return $this->attributeDefinition; } public function getSubscriber(): Subscriber diff --git a/src/Domain/Model/Identity/UserAttribute.php b/src/Domain/Model/Subscription/SubscriberAttributeDefinition.php similarity index 85% rename from src/Domain/Model/Identity/UserAttribute.php rename to src/Domain/Model/Subscription/SubscriberAttributeDefinition.php index 81e4c8c..0210c0d 100644 --- a/src/Domain/Model/Identity/UserAttribute.php +++ b/src/Domain/Model/Subscription/SubscriberAttributeDefinition.php @@ -2,20 +2,24 @@ declare(strict_types=1); -namespace PhpList\Core\Domain\Model\Identity; +namespace PhpList\Core\Domain\Model\Subscription; use Doctrine\ORM\Mapping as ORM; use PhpList\Core\Domain\Model\Interfaces\DomainModel; use PhpList\Core\Domain\Model\Interfaces\Identity; -use PhpList\Core\Domain\Model\Traits\IdentityTrait; +use Symfony\Component\Serializer\Attribute\Groups; #[ORM\Entity] #[ORM\Table(name: 'phplist_user_attribute')] #[ORM\Index(name: 'idnameindex', columns: ['id', 'name'])] #[ORM\Index(name: 'nameindex', columns: ['name'])] -class UserAttribute implements DomainModel, Identity +class SubscriberAttributeDefinition implements DomainModel, Identity { - use IdentityTrait; + #[ORM\Id] + #[ORM\Column(type: 'integer')] + #[ORM\GeneratedValue] + #[Groups(['SubscriberList', 'SubscriberListMembers'])] + private ?int $id = null; #[ORM\Column(name: 'name', type: 'string', length: 255)] private string $name; @@ -35,6 +39,11 @@ class UserAttribute implements DomainModel, Identity #[ORM\Column(name: 'tablename', type: 'string', length: 255, nullable: true)] private ?string $tableName = null; + public function getId(): ?int + { + return $this->id; + } + public function getName(): string { return $this->name; diff --git a/src/Domain/Model/Subscription/SubscriberHistory.php b/src/Domain/Model/Subscription/SubscriberHistory.php index ace918c..47847a5 100644 --- a/src/Domain/Model/Subscription/SubscriberHistory.php +++ b/src/Domain/Model/Subscription/SubscriberHistory.php @@ -8,7 +8,7 @@ use Doctrine\ORM\Mapping as ORM; use PhpList\Core\Domain\Model\Interfaces\DomainModel; use PhpList\Core\Domain\Model\Interfaces\Identity; -use PhpList\Core\Domain\Model\Traits\IdentityTrait; +use Symfony\Component\Serializer\Attribute\Groups; #[ORM\Entity] #[ORM\Table(name: 'phplist_user_user_history')] @@ -16,7 +16,11 @@ #[ORM\Index(name: 'userididx', columns: ['userid'])] class SubscriberHistory implements DomainModel, Identity { - use IdentityTrait; + #[ORM\Id] + #[ORM\Column(type: 'integer')] + #[ORM\GeneratedValue] + #[Groups(['SubscriberList', 'SubscriberListMembers'])] + private ?int $id = null; #[ORM\ManyToOne(targetEntity: Subscriber::class)] #[ORM\JoinColumn(name: 'userid', referencedColumnName: 'id', nullable: false, onDelete: 'CASCADE')] @@ -37,6 +41,11 @@ class SubscriberHistory implements DomainModel, Identity #[ORM\Column(name: 'systeminfo', type: 'text', nullable: true)] private ?string $systemInfo = null; + public function getId(): ?int + { + return $this->id; + } + public function getSubscriber(): Subscriber { return $this->subscriber; diff --git a/src/Domain/Model/Messaging/SubscriberList.php b/src/Domain/Model/Subscription/SubscriberList.php similarity index 73% rename from src/Domain/Model/Messaging/SubscriberList.php rename to src/Domain/Model/Subscription/SubscriberList.php index 4340ef1..2a6d016 100644 --- a/src/Domain/Model/Messaging/SubscriberList.php +++ b/src/Domain/Model/Subscription/SubscriberList.php @@ -2,24 +2,20 @@ declare(strict_types=1); -namespace PhpList\Core\Domain\Model\Messaging; +namespace PhpList\Core\Domain\Model\Subscription; use DateTime; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; -use PhpList\Core\Domain\Model\Subscription\Subscription; -use PhpList\Core\Domain\Repository\Messaging\SubscriberListRepository; -use Symfony\Component\Serializer\Annotation\Ignore; -use Symfony\Component\Serializer\Annotation\SerializedName; use PhpList\Core\Domain\Model\Identity\Administrator; use PhpList\Core\Domain\Model\Interfaces\CreationDate; use PhpList\Core\Domain\Model\Interfaces\DomainModel; use PhpList\Core\Domain\Model\Interfaces\Identity; use PhpList\Core\Domain\Model\Interfaces\ModificationDate; -use PhpList\Core\Domain\Model\Traits\CreationDateTrait; -use PhpList\Core\Domain\Model\Traits\IdentityTrait; -use PhpList\Core\Domain\Model\Traits\ModificationDateTrait; +use PhpList\Core\Domain\Repository\Subscription\SubscriberListRepository; +use Symfony\Component\Serializer\Annotation\Ignore; +use Symfony\Component\Serializer\Annotation\SerializedName; use Symfony\Component\Serializer\Attribute\Groups; use Symfony\Component\Serializer\Attribute\MaxDepth; @@ -27,6 +23,7 @@ * This class represents an administrator who can log to the system, is allowed to administer * selected lists (as the owner), send campaigns to these lists and edit subscribers. * @author Oliver Klee + * @author Tatevik Grigoryan */ #[ORM\Entity(repositoryClass: SubscriberListRepository::class)] #[ORM\Table(name: 'phplist_list')] @@ -35,9 +32,11 @@ #[ORM\HasLifecycleCallbacks] class SubscriberList implements DomainModel, Identity, CreationDate, ModificationDate { - use IdentityTrait; - use CreationDateTrait; - use ModificationDateTrait; + #[ORM\Id] + #[ORM\Column(type: 'integer')] + #[ORM\GeneratedValue] + #[Groups(['SubscriberList', 'SubscriberListMembers'])] + private ?int $id = null; #[ORM\Column] #[SerializedName('name')] @@ -52,7 +51,10 @@ class SubscriberList implements DomainModel, Identity, CreationDate, Modificatio #[ORM\Column(name: 'entered', type: 'datetime', nullable: true)] #[SerializedName('creation_date')] #[Groups(['SubscriberList'])] - protected ?DateTime $creationDate = null; + protected ?DateTime $createdAt = null; + + #[ORM\Column(name: 'modified', type: 'datetime')] + private ?DateTime $updatedAt = null; #[ORM\Column(name: 'listorder', type: 'integer', nullable: true)] #[SerializedName('list_position')] @@ -74,13 +76,13 @@ class SubscriberList implements DomainModel, Identity, CreationDate, Modificatio #[Groups(['SubscriberList'])] private string $category; - #[ORM\ManyToOne(targetEntity: 'PhpList\Core\Domain\Model\Identity\Administrator')] + #[ORM\ManyToOne(targetEntity: Administrator::class)] #[ORM\JoinColumn(name: 'owner')] #[Ignore] private ?Administrator $owner = null; #[ORM\OneToMany( - targetEntity: 'PhpList\Core\Domain\Model\Subscription\Subscription', + targetEntity: Subscription::class, mappedBy: 'subscriberList', cascade: ['remove'], orphanRemoval: true, @@ -91,20 +93,28 @@ class SubscriberList implements DomainModel, Identity, CreationDate, Modificatio public function __construct() { $this->subscriptions = new ArrayCollection(); + $this->createdAt = new DateTime(); $this->listPosition = 0; $this->subjectPrefix = ''; $this->category = ''; $this->public = false; } + public function getId(): ?int + { + return $this->id; + } + public function getName(): string { return $this->name; } - public function setName(string $name): void + public function setName(string $name): self { $this->name = $name; + + return $this; } public function getDescription(): string @@ -112,9 +122,11 @@ public function getDescription(): string return $this->description; } - public function setDescription(string $description): void + public function setDescription(string $description): self { $this->description = $description; + + return $this; } public function getListPosition(): ?int @@ -122,9 +134,10 @@ public function getListPosition(): ?int return $this->listPosition; } - public function setListPosition(int $listPosition): void + public function setListPosition(int $listPosition): self { $this->listPosition = $listPosition; + return $this; } public function getSubjectPrefix(): ?string @@ -132,9 +145,11 @@ public function getSubjectPrefix(): ?string return $this->subjectPrefix; } - public function setSubjectPrefix(string $subjectPrefix): void + public function setSubjectPrefix(string $subjectPrefix): self { $this->subjectPrefix = $subjectPrefix; + + return $this; } public function isPublic(): bool @@ -142,9 +157,11 @@ public function isPublic(): bool return $this->public ?? false; } - public function setPublic(bool $public): void + public function setPublic(bool $public): self { $this->public = $public; + + return $this; } public function getCategory(): string @@ -152,9 +169,11 @@ public function getCategory(): string return $this->category; } - public function setCategory(string $category): void + public function setCategory(string $category): self { $this->category = $category; + + return $this; } public function getOwner(): ?Administrator @@ -162,9 +181,11 @@ public function getOwner(): ?Administrator return $this->owner; } - public function setOwner(Administrator $owner): void + public function setOwner(Administrator $owner): self { $this->owner = $owner; + + return $this; } public function getSubscriptions(): Collection @@ -200,4 +221,23 @@ public function getSubscribers(): Collection return $result; } + + public function getCreatedAt(): ?DateTime + { + return $this->createdAt; + } + + public function getUpdatedAt(): ?DateTime + { + return $this->updatedAt; + } + + #[ORM\PrePersist] + #[ORM\PreUpdate] + public function updateUpdatedAt(): DomainModel + { + $this->updatedAt = new DateTime(); + + return $this; + } } diff --git a/src/Domain/Model/Subscription/Subscription.php b/src/Domain/Model/Subscription/Subscription.php index fa73694..ba1ade7 100644 --- a/src/Domain/Model/Subscription/Subscription.php +++ b/src/Domain/Model/Subscription/Subscription.php @@ -7,22 +7,21 @@ use DateTime; use Doctrine\ORM\Mapping as ORM; use Doctrine\Persistence\Proxy; -use Symfony\Component\Serializer\Annotation\Ignore; -use Symfony\Component\Serializer\Annotation\SerializedName; use PhpList\Core\Domain\Model\Interfaces\CreationDate; use PhpList\Core\Domain\Model\Interfaces\DomainModel; use PhpList\Core\Domain\Model\Interfaces\ModificationDate; -use PhpList\Core\Domain\Model\Messaging\SubscriberList; -use PhpList\Core\Domain\Model\Traits\CreationDateTrait; -use PhpList\Core\Domain\Model\Traits\ModificationDateTrait; +use PhpList\Core\Domain\Repository\Subscription\SubscriptionRepository; +use Symfony\Component\Serializer\Annotation\Ignore; +use Symfony\Component\Serializer\Annotation\SerializedName; use Symfony\Component\Serializer\Attribute\Groups; /** * This class represents subscriber who can subscribe to multiple subscriber lists and can receive email messages from * campaigns for those subscriber lists. * @author Oliver Klee + * @author Tatevik Grigoryan */ -#[ORM\Entity(repositoryClass: 'PhpList\Core\Domain\Repository\Subscription\SubscriptionRepository')] +#[ORM\Entity(repositoryClass: SubscriptionRepository::class)] #[ORM\Table(name: 'phplist_listuser')] #[ORM\Index(name: 'userenteredidx', columns: ['userid', 'entered'])] #[ORM\Index(name: 'userlistenteredidx', columns: ['userid', 'entered', 'listid'])] @@ -31,16 +30,16 @@ #[ORM\HasLifecycleCallbacks] class Subscription implements DomainModel, CreationDate, ModificationDate { - use CreationDateTrait; - use ModificationDateTrait; - #[ORM\Column(name: 'entered', type: 'datetime', nullable: true)] #[SerializedName('creation_date')] - protected ?DateTime $creationDate = null; + protected ?DateTime $createdAt = null; + + #[ORM\Column(name: 'modified', type: 'datetime')] + private ?DateTime $updatedAt = null; #[ORM\Id] #[ORM\ManyToOne( - targetEntity: 'PhpList\Core\Domain\Model\Subscription\Subscriber', + targetEntity: Subscriber::class, inversedBy: 'subscriptions' )] #[ORM\JoinColumn(name: 'userid')] @@ -49,7 +48,7 @@ class Subscription implements DomainModel, CreationDate, ModificationDate #[ORM\Id] #[ORM\ManyToOne( - targetEntity: 'PhpList\Core\Domain\Model\Messaging\SubscriberList', + targetEntity: SubscriberList::class, inversedBy: 'subscriptions' )] #[ORM\JoinColumn(name: 'listid', onDelete: 'CASCADE')] @@ -57,14 +56,20 @@ class Subscription implements DomainModel, CreationDate, ModificationDate #[Groups(['SubscriberListMembers'])] private ?SubscriberList $subscriberList = null; + public function __construct() + { + $this->createdAt = new DateTime(); + } + public function getSubscriber(): Subscriber|Proxy|null { return $this->subscriber; } - public function setSubscriber(?Subscriber $subscriber): void + public function setSubscriber(?Subscriber $subscriber): self { $this->subscriber = $subscriber; + return $this; } public function getSubscriberList(): ?SubscriberList @@ -72,8 +77,28 @@ public function getSubscriberList(): ?SubscriberList return $this->subscriberList; } - public function setSubscriberList(?SubscriberList $subscriberList): void + public function setSubscriberList(?SubscriberList $subscriberList): self { $this->subscriberList = $subscriberList; + return $this; + } + + public function getCreatedAt(): ?DateTime + { + return $this->createdAt; + } + + public function getUpdatedAt(): ?DateTime + { + return $this->updatedAt; + } + + #[ORM\PrePersist] + #[ORM\PreUpdate] + public function updateUpdatedAt(): DomainModel + { + $this->updatedAt = new DateTime(); + + return $this; } } diff --git a/src/Domain/Model/Traits/CreationDateTrait.php b/src/Domain/Model/Traits/CreationDateTrait.php deleted file mode 100644 index 51b6fd2..0000000 --- a/src/Domain/Model/Traits/CreationDateTrait.php +++ /dev/null @@ -1,45 +0,0 @@ - - */ -trait CreationDateTrait -{ - /** - * @return DateTime|null - */ - public function getCreationDate(): ?DateTime - { - return $this->creationDate; - } - - /** - * @param DateTime $creationDate - * - * @return void - */ - private function setCreationDate(DateTime $creationDate): void - { - $this->creationDate = $creationDate; - } - - #[ORM\PrePersist] - public function updateCreationDate(): void - { - $this->setCreationDate(new DateTime()); - } -} diff --git a/src/Domain/Model/Traits/IdentityTrait.php b/src/Domain/Model/Traits/IdentityTrait.php deleted file mode 100644 index 4445ea2..0000000 --- a/src/Domain/Model/Traits/IdentityTrait.php +++ /dev/null @@ -1,31 +0,0 @@ - - */ -trait IdentityTrait -{ - #[ORM\Id] - #[ORM\Column(type: 'integer')] - #[ORM\GeneratedValue] - #[SerializedName('id')] - #[Groups(['SubscriberList', 'SubscriberListMembers'])] - private int $id; - - public function getId(): int - { - return $this->id; - } -} diff --git a/src/Domain/Model/Traits/ModificationDateTrait.php b/src/Domain/Model/Traits/ModificationDateTrait.php deleted file mode 100644 index ab03e76..0000000 --- a/src/Domain/Model/Traits/ModificationDateTrait.php +++ /dev/null @@ -1,41 +0,0 @@ - - */ -trait ModificationDateTrait -{ - #[ORM\Column(name: 'modified', type: 'datetime')] - private ?DateTime $modificationDate = null; - - public function getModificationDate(): ?DateTime - { - return $this->modificationDate; - } - - private function setModificationDate(DateTime $modificationDate): void - { - $this->modificationDate = $modificationDate; - } - - #[ORM\PrePersist] - #[ORM\PreUpdate] - public function updateModificationDate(): void - { - $this->setModificationDate(new DateTime()); - } -} diff --git a/src/Domain/Repository/Messaging/MessageRepository.php b/src/Domain/Repository/Messaging/MessageRepository.php index 0d013be..5fad191 100644 --- a/src/Domain/Repository/Messaging/MessageRepository.php +++ b/src/Domain/Repository/Messaging/MessageRepository.php @@ -4,8 +4,18 @@ namespace PhpList\Core\Domain\Repository\Messaging; +use PhpList\Core\Domain\Model\Messaging\Message; use PhpList\Core\Domain\Repository\AbstractRepository; class MessageRepository extends AbstractRepository { + /** @return Message[] */ + public function getByOwnerId(int $ownerId): array + { + return $this->createQueryBuilder('m') + ->where('IDENTITY(m.owner) = :ownerId') + ->setParameter('ownerId', $ownerId) + ->getQuery() + ->getResult(); + } } diff --git a/src/Domain/Repository/Messaging/TemplateImageRepository.php b/src/Domain/Repository/Messaging/TemplateImageRepository.php new file mode 100644 index 0000000..6106bbd --- /dev/null +++ b/src/Domain/Repository/Messaging/TemplateImageRepository.php @@ -0,0 +1,11 @@ +createQueryBuilder('subscription') + ->join('subscription.subscriber', 'subscriber') + ->join('subscription.subscriberList', 'list') + ->where('subscriber.email = :email') + ->andWhere('list.id = :listId') + ->setParameter('email', $email) + ->setParameter('listId', $listId) + ->getQuery() + ->getOneOrNullResult(); + } } diff --git a/tests/Integration/Domain/Repository/Fixtures/Administrator.csv b/tests/Integration/Domain/Repository/Fixtures/Identity/Administrator.csv similarity index 100% rename from tests/Integration/Domain/Repository/Fixtures/Administrator.csv rename to tests/Integration/Domain/Repository/Fixtures/Identity/Administrator.csv diff --git a/tests/Integration/Domain/Repository/Fixtures/AdministratorFixture.php b/tests/Integration/Domain/Repository/Fixtures/Identity/AdministratorFixture.php similarity index 91% rename from tests/Integration/Domain/Repository/Fixtures/AdministratorFixture.php rename to tests/Integration/Domain/Repository/Fixtures/Identity/AdministratorFixture.php index 30905f2..963d764 100644 --- a/tests/Integration/Domain/Repository/Fixtures/AdministratorFixture.php +++ b/tests/Integration/Domain/Repository/Fixtures/Identity/AdministratorFixture.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace PhpList\Core\Tests\Integration\Domain\Repository\Fixtures; +namespace PhpList\Core\Tests\Integration\Domain\Repository\Fixtures\Identity; use DateTime; use Doctrine\Bundle\FixturesBundle\Fixture; @@ -39,13 +39,13 @@ public function load(ObjectManager $manager): void $admin = new Administrator(); $this->setSubjectId($admin, (int)$row['id']); $admin->setLoginName($row['loginname']); - $admin->setEmailAddress($row['email']); + $admin->setEmail($row['email']); $admin->setPasswordHash($row['password']); $admin->setDisabled((bool) $row['disabled']); $admin->setSuperUser((bool) $row['superuser']); $manager->persist($admin); - $this->setSubjectProperty($admin, 'creationDate', new DateTime($row['created'])); + $this->setSubjectProperty($admin, 'createdAt', new DateTime($row['created'])); $this->setSubjectProperty($admin, 'passwordChangeDate', new DateTime($row['passwordchanged'])); } while (true); diff --git a/tests/Integration/Domain/Repository/Fixtures/AdministratorTokenWithAdministrator.csv b/tests/Integration/Domain/Repository/Fixtures/Identity/AdministratorTokenWithAdministrator.csv similarity index 100% rename from tests/Integration/Domain/Repository/Fixtures/AdministratorTokenWithAdministrator.csv rename to tests/Integration/Domain/Repository/Fixtures/Identity/AdministratorTokenWithAdministrator.csv diff --git a/tests/Integration/Domain/Repository/Fixtures/AdministratorTokenWithAdministratorFixture.php b/tests/Integration/Domain/Repository/Fixtures/Identity/AdministratorTokenWithAdministratorFixture.php similarity index 94% rename from tests/Integration/Domain/Repository/Fixtures/AdministratorTokenWithAdministratorFixture.php rename to tests/Integration/Domain/Repository/Fixtures/Identity/AdministratorTokenWithAdministratorFixture.php index 1d1ac74..9805cae 100644 --- a/tests/Integration/Domain/Repository/Fixtures/AdministratorTokenWithAdministratorFixture.php +++ b/tests/Integration/Domain/Repository/Fixtures/Identity/AdministratorTokenWithAdministratorFixture.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace PhpList\Core\Tests\Integration\Domain\Repository\Fixtures; +namespace PhpList\Core\Tests\Integration\Domain\Repository\Fixtures\Identity; use DateTime; use Doctrine\Bundle\FixturesBundle\Fixture; @@ -49,7 +49,7 @@ public function load(ObjectManager $manager): void $this->setSubjectId($adminToken, (int)$row['id']); $adminToken->setKey($row['value']); $this->setSubjectProperty($adminToken, 'expiry', new DateTime($row['expires'])); - $this->setSubjectProperty($adminToken, 'creationDate', (bool) $row['entered']); + $this->setSubjectProperty($adminToken, 'createdAt', (bool) $row['entered']); $adminToken->setAdministrator($admin); $manager->persist($adminToken); } while (true); diff --git a/tests/Integration/Domain/Repository/Fixtures/DetachedAdministratorTokenFixture.php b/tests/Integration/Domain/Repository/Fixtures/Identity/DetachedAdministratorTokenFixture.php similarity index 93% rename from tests/Integration/Domain/Repository/Fixtures/DetachedAdministratorTokenFixture.php rename to tests/Integration/Domain/Repository/Fixtures/Identity/DetachedAdministratorTokenFixture.php index 15f5d2a..cd4bc68 100644 --- a/tests/Integration/Domain/Repository/Fixtures/DetachedAdministratorTokenFixture.php +++ b/tests/Integration/Domain/Repository/Fixtures/Identity/DetachedAdministratorTokenFixture.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace PhpList\Core\Tests\Integration\Domain\Repository\Fixtures; +namespace PhpList\Core\Tests\Integration\Domain\Repository\Fixtures\Identity; use DateTime; use Doctrine\Bundle\FixturesBundle\Fixture; @@ -43,7 +43,7 @@ public function load(ObjectManager $manager): void $manager->persist($adminToken); $this->setSubjectProperty($adminToken, 'expiry', new DateTime($row['expires'])); - $this->setSubjectProperty($adminToken, 'creationDate', $row['entered']); + $this->setSubjectProperty($adminToken, 'createdAt', $row['entered']); } while (true); fclose($handle); diff --git a/tests/Integration/Domain/Repository/Fixtures/DetachedAdministratorTokens.csv b/tests/Integration/Domain/Repository/Fixtures/Identity/DetachedAdministratorTokens.csv similarity index 100% rename from tests/Integration/Domain/Repository/Fixtures/DetachedAdministratorTokens.csv rename to tests/Integration/Domain/Repository/Fixtures/Identity/DetachedAdministratorTokens.csv diff --git a/tests/Integration/Domain/Repository/Fixtures/Messaging/Message.csv b/tests/Integration/Domain/Repository/Fixtures/Messaging/Message.csv new file mode 100644 index 0000000..c2e52a7 --- /dev/null +++ b/tests/Integration/Domain/Repository/Fixtures/Messaging/Message.csv @@ -0,0 +1,21 @@ +id,uuid,subject,fromfield,tofield,replyto,message,textmessage,footer,entered,modified,embargo,repeatinterval,repeatuntil,requeueinterval,requeueuntil,status,userselection,sent,htmlformatted,sendformat,template,processed,astext,ashtml,astextandhtml,aspdf,astextandpdf,viewed,bouncecount,sendstart,rsstemplate,owner +1,2df6b147-8470-45ed-8e4e-86aa01af400d,Do you want to continue receiving our messages?, My Name ,"","","

Hi [FIRST NAME%%there], remember us? You first signed up for our email newsletter on [ENTERED] – please click here to confirm you're happy to continue receiving our messages:

+ +

Continue receiving messages  (If you do not confirm using this link, then you won't hear from us again)

+ +

While you're at it, you can also update your preferences, including your email address or other details, by clicking here:

+ +

Update preferences

+ +

By confirming your membership and keeping your details up to date, you're helping us to manage and protect your data in accordance with best practices.

+ +

Thank you!

","","-- + +
+

This message was sent to [EMAIL] by [FROMEMAIL].

+

To forward this message, please do not use the forward button of your email application, because this message was made specifically for you only. Instead use the forward page in our newsletter system.
+ To change your details and to choose which lists to be subscribed to, visit your personal preferences page.
+ Or you can opt-out completely from all future mailings.

+
+ + ",2024-11-10 16:57:46,2024-11-14 08:32:15,2024-11-14 08:32:00,0,2024-11-14 08:32:00,0,2024-11-14 08:32:00,sent,,2024-11-14 08:32:15,1,invite,0,0,0,0,0,0,0,0,0,2024-11-14 08:32:15,,1 diff --git a/tests/Integration/Domain/Repository/Fixtures/Messaging/MessageFixture.php b/tests/Integration/Domain/Repository/Fixtures/Messaging/MessageFixture.php new file mode 100644 index 0000000..b65e66c --- /dev/null +++ b/tests/Integration/Domain/Repository/Fixtures/Messaging/MessageFixture.php @@ -0,0 +1,109 @@ +getRepository(Administrator::class); + $templateRepository = $manager->getRepository(Template::class); + + do { + $data = fgetcsv($handle); + if ($data === false) { + break; + } + $row = array_combine($headers, $data); + $admin = $adminRepository->find($row['owner']); + $template = $templateRepository->find($row['template']); + + $format = new MessageFormat( + (bool)$row['htmlformatted'], + $row['sendformat'], + array_keys(array_filter([ + MessageFormat::FORMAT_TEXT => $row['astext'], + MessageFormat::FORMAT_HTML => $row['ashtml'], + MessageFormat::FORMAT_PDF => $row['aspdf'], + ])) + ); + + $schedule = new MessageSchedule( + (int)$row['repeatinterval'], + new DateTime($row['repeatuntil']), + (int)$row['requeueinterval'], + new DateTime($row['requeueuntil']), + new DateTime($row['embargo']), + ); + $metadata = new MessageMetadata( + $row['status'], + (int)$row['bouncecount'], + new DateTime($row['entered']), + new DateTime($row['sent']), + new DateTime($row['sendstart']), + ); + $metadata->setProcessed((bool) $row['processed']); + $metadata->setViews($row['viewed']); + $content = new MessageContent( + $row['subject'], + $row['message'], + $row['textmessage'], + $row['footer'] + ); + $options = new MessageOptions( + $row['fromfield'], + $row['tofield'], + $row['replyto'], + $row['userselection'], + $row['rsstemplate'], + ); + + $message = new Message( + $format, + $schedule, + $metadata, + $content, + $options, + $admin, + $template, + ); + $this->setSubjectId($message, (int)$row['id']); + $this->setSubjectProperty($message, 'uuid', $row['uuid']); + + $manager->persist($message); + $this->setSubjectProperty($message, 'updatedAt', new DateTime($row['modified'])); + } while (true); + + fclose($handle); + } +} diff --git a/tests/Integration/Domain/Repository/Fixtures/Messaging/Template.csv b/tests/Integration/Domain/Repository/Fixtures/Messaging/Template.csv new file mode 100644 index 0000000..65872d6 --- /dev/null +++ b/tests/Integration/Domain/Repository/Fixtures/Messaging/Template.csv @@ -0,0 +1,2 @@ +id,title,template,template_text,listorder +1,Newsletter Template,

Welcome

,,1 diff --git a/tests/Integration/Domain/Repository/Fixtures/Messaging/TemplateFixture.php b/tests/Integration/Domain/Repository/Fixtures/Messaging/TemplateFixture.php new file mode 100644 index 0000000..e522229 --- /dev/null +++ b/tests/Integration/Domain/Repository/Fixtures/Messaging/TemplateFixture.php @@ -0,0 +1,50 @@ +setContent($row['template']); + $template->setText($row['template_text']); + $template->setListOrder((int)$row['listorder']); + + $this->setSubjectId($template, (int)$row['id']); + $manager->persist($template); + } while (true); + + fclose($handle); + } +} diff --git a/tests/Integration/Domain/Repository/Fixtures/Subscriber.csv b/tests/Integration/Domain/Repository/Fixtures/Subscription/Subscriber.csv similarity index 100% rename from tests/Integration/Domain/Repository/Fixtures/Subscriber.csv rename to tests/Integration/Domain/Repository/Fixtures/Subscription/Subscriber.csv diff --git a/tests/Integration/Domain/Repository/Fixtures/SubscriberFixture.php b/tests/Integration/Domain/Repository/Fixtures/Subscription/SubscriberFixture.php similarity index 89% rename from tests/Integration/Domain/Repository/Fixtures/SubscriberFixture.php rename to tests/Integration/Domain/Repository/Fixtures/Subscription/SubscriberFixture.php index 9a4ce78..a9fc586 100644 --- a/tests/Integration/Domain/Repository/Fixtures/SubscriberFixture.php +++ b/tests/Integration/Domain/Repository/Fixtures/Subscription/SubscriberFixture.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace PhpList\Core\Tests\Integration\Domain\Repository\Fixtures; +namespace PhpList\Core\Tests\Integration\Domain\Repository\Fixtures\Subscription; use DateTime; use Doctrine\Bundle\FixturesBundle\Fixture; @@ -51,8 +51,8 @@ public function load(ObjectManager $manager): void $manager->persist($subscriber); // avoid pre-persist $subscriber->setUniqueId($row['uniqueid']); - $this->setSubjectProperty($subscriber, 'creationDate', new DateTime($row['entered'])); - $this->setSubjectProperty($subscriber, 'modificationDate', new DateTime($row['modified'])); + $this->setSubjectProperty($subscriber, 'createdAt', new DateTime($row['entered'])); + $this->setSubjectProperty($subscriber, 'updatedAt', new DateTime($row['modified'])); } while (true); fclose($handle); diff --git a/tests/Integration/Domain/Repository/Fixtures/SubscriberList.csv b/tests/Integration/Domain/Repository/Fixtures/Subscription/SubscriberList.csv similarity index 100% rename from tests/Integration/Domain/Repository/Fixtures/SubscriberList.csv rename to tests/Integration/Domain/Repository/Fixtures/Subscription/SubscriberList.csv diff --git a/tests/Integration/Domain/Repository/Fixtures/SubscriberListFixture.php b/tests/Integration/Domain/Repository/Fixtures/Subscription/SubscriberListFixture.php similarity index 87% rename from tests/Integration/Domain/Repository/Fixtures/SubscriberListFixture.php rename to tests/Integration/Domain/Repository/Fixtures/Subscription/SubscriberListFixture.php index 0b8aff8..954c3c0 100644 --- a/tests/Integration/Domain/Repository/Fixtures/SubscriberListFixture.php +++ b/tests/Integration/Domain/Repository/Fixtures/Subscription/SubscriberListFixture.php @@ -2,13 +2,13 @@ declare(strict_types=1); -namespace PhpList\Core\Tests\Integration\Domain\Repository\Fixtures; +namespace PhpList\Core\Tests\Integration\Domain\Repository\Fixtures\Subscription; use DateTime; use Doctrine\Bundle\FixturesBundle\Fixture; use Doctrine\Persistence\ObjectManager; use PhpList\Core\Domain\Model\Identity\Administrator; -use PhpList\Core\Domain\Model\Messaging\SubscriberList; +use PhpList\Core\Domain\Model\Subscription\SubscriberList; use PhpList\Core\TestingSupport\Traits\ModelTestTrait; use RuntimeException; @@ -50,8 +50,6 @@ public function load(ObjectManager $manager): void $this->setSubjectId($subscriberList, (int)$row['id']); $subscriberList->setName($row['name']); $subscriberList->setDescription($row['description']); - $this->setSubjectProperty($subscriberList, 'creationDate', new DateTime($row['entered'])); - $this->setSubjectProperty($subscriberList, 'modificationDate', new DateTime($row['modified'])); $subscriberList->setListPosition((int)$row['listorder']); $subscriberList->setSubjectPrefix($row['prefix']); $subscriberList->setPublic((bool) $row['active']); @@ -59,6 +57,9 @@ public function load(ObjectManager $manager): void $subscriberList->setOwner($admin); $manager->persist($subscriberList); + + $this->setSubjectProperty($subscriberList, 'createdAt', new DateTime($row['entered'])); + $this->setSubjectProperty($subscriberList, 'updatedAt', new DateTime($row['modified'])); } while (true); fclose($handle); diff --git a/tests/Integration/Domain/Repository/Fixtures/Subscription.csv b/tests/Integration/Domain/Repository/Fixtures/Subscription/Subscription.csv similarity index 100% rename from tests/Integration/Domain/Repository/Fixtures/Subscription.csv rename to tests/Integration/Domain/Repository/Fixtures/Subscription/Subscription.csv diff --git a/tests/Integration/Domain/Repository/Fixtures/SubscriptionFixture.php b/tests/Integration/Domain/Repository/Fixtures/Subscription/SubscriptionFixture.php similarity index 86% rename from tests/Integration/Domain/Repository/Fixtures/SubscriptionFixture.php rename to tests/Integration/Domain/Repository/Fixtures/Subscription/SubscriptionFixture.php index 35cd792..df1741c 100644 --- a/tests/Integration/Domain/Repository/Fixtures/SubscriptionFixture.php +++ b/tests/Integration/Domain/Repository/Fixtures/Subscription/SubscriptionFixture.php @@ -2,13 +2,13 @@ declare(strict_types=1); -namespace PhpList\Core\Tests\Integration\Domain\Repository\Fixtures; +namespace PhpList\Core\Tests\Integration\Domain\Repository\Fixtures\Subscription; use DateTime; use Doctrine\Bundle\FixturesBundle\Fixture; use Doctrine\Persistence\ObjectManager; -use PhpList\Core\Domain\Model\Messaging\SubscriberList; use PhpList\Core\Domain\Model\Subscription\Subscriber; +use PhpList\Core\Domain\Model\Subscription\SubscriberList; use PhpList\Core\Domain\Model\Subscription\Subscription; use PhpList\Core\TestingSupport\Traits\ModelTestTrait; use RuntimeException; @@ -51,8 +51,8 @@ public function load(ObjectManager $manager): void $manager->persist($subscription); - $this->setSubjectProperty($subscription, 'creationDate', new DateTime($row['entered'])); - $this->setSubjectProperty($subscription, 'modificationDate', new DateTime($row['modified'])); + $this->setSubjectProperty($subscription, 'createdAt', new DateTime($row['entered'])); + $this->setSubjectProperty($subscription, 'updatedAt', new DateTime($row['modified'])); } while (true); fclose($handle); diff --git a/tests/Integration/Domain/Repository/Identity/AdministratorRepositoryTest.php b/tests/Integration/Domain/Repository/Identity/AdministratorRepositoryTest.php index 2f74bcf..05d0b83 100644 --- a/tests/Integration/Domain/Repository/Identity/AdministratorRepositoryTest.php +++ b/tests/Integration/Domain/Repository/Identity/AdministratorRepositoryTest.php @@ -10,7 +10,7 @@ use PhpList\Core\Domain\Repository\Identity\AdministratorRepository; use PhpList\Core\TestingSupport\Traits\DatabaseTestTrait; use PhpList\Core\TestingSupport\Traits\ModelTestTrait; -use PhpList\Core\Tests\Integration\Domain\Repository\Fixtures\AdministratorFixture; +use PhpList\Core\Tests\Integration\Domain\Repository\Fixtures\Identity\AdministratorFixture; use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; /** @@ -51,34 +51,36 @@ public function testFindReadsModelFromDatabase(): void $this->assertSame($actual->getLoginName(), $actual->getLoginName()); $this->assertEqualsWithDelta( (new DateTime())->getTimestamp(), - $actual->getModificationDate()->getTimestamp(), + $actual->getUpdatedAt()->getTimestamp(), 1 ); - $this->assertSame('john@example.com', $actual->getEmailAddress()); + $this->assertSame('john@example.com', $actual->getEmail()); $this->assertSame( '1491a3c7e7b23b9a6393323babbb095dee0d7d81b2199617b487bd0fb5236f3c', $actual->getPasswordHash() ); - $this->assertEquals(new DateTime('2017-06-22 15:01:17'), $actual->getCreationDate()); + $this->assertEquals(new DateTime('2017-06-22 15:01:17'), $actual->getCreatedat()); $this->assertEquals(new DateTime('2017-06-28'), $actual->getPasswordChangeDate()); } public function testCreationDateOfExistingModelStaysUnchangedOnUpdate(): void { $id = 1; + /** @var Administrator $model */ $model = $this->repository->find($id); $this->assertNotNull($model); - $originalCreationDate = $model->getCreationDate(); + $originalCreationDate = $model->getCreatedAt(); $model->setLoginName('mel'); $this->entityManager->flush(); - $this->assertSame($originalCreationDate, $model->getCreationDate()); + $this->assertSame($originalCreationDate, $model->getCreatedAt()); } public function testModificationDateOfExistingModelGetsUpdatedOnUpdate(): void { $id = 1; + /** @var Administrator $model */ $model = $this->repository->find($id); $this->assertNotNull($model); @@ -86,7 +88,7 @@ public function testModificationDateOfExistingModelGetsUpdatedOnUpdate(): void $this->entityManager->flush(); $expectedModificationDate = new DateTime(); - $this->assertEqualsWithDelta($expectedModificationDate, $model->getModificationDate(), 5); + $this->assertEqualsWithDelta($expectedModificationDate, $model->getUpdatedAt(), 5); } public function testCreationDateOfNewModelIsSetToNowOnPersist() @@ -97,7 +99,7 @@ public function testCreationDateOfNewModelIsSetToNowOnPersist() $this->entityManager->flush(); $expectedCreationDate = new DateTime(); - $this->assertEqualsWithDelta($expectedCreationDate, $model->getCreationDate(), 1); + $this->assertEqualsWithDelta($expectedCreationDate, $model->getCreatedAt(), 1); } public function testModificationDateOfNewModelIsSetToNowOnPersist() @@ -108,7 +110,7 @@ public function testModificationDateOfNewModelIsSetToNowOnPersist() $this->entityManager->flush(); $expectedCreationDate = new DateTime(); - $this->assertEqualsWithDelta($expectedCreationDate, $model->getModificationDate(), 1); + $this->assertEqualsWithDelta($expectedCreationDate, $model->getUpdatedAt(), 1); } /** diff --git a/tests/Integration/Domain/Repository/Identity/AdministratorTokenRepositoryTest.php b/tests/Integration/Domain/Repository/Identity/AdministratorTokenRepositoryTest.php index e6b9ba3..b37d4e7 100644 --- a/tests/Integration/Domain/Repository/Identity/AdministratorTokenRepositoryTest.php +++ b/tests/Integration/Domain/Repository/Identity/AdministratorTokenRepositoryTest.php @@ -12,10 +12,8 @@ use PhpList\Core\Domain\Repository\Identity\AdministratorTokenRepository; use PhpList\Core\TestingSupport\Traits\DatabaseTestTrait; use PhpList\Core\TestingSupport\Traits\SimilarDatesAssertionTrait; -use PhpList\Core\Tests\Integration\Domain\Repository\Fixtures\AdministratorFixture; -use PhpList\Core\Tests\Integration\Domain\Repository\Fixtures\AdministratorTokenWithAdministratorFixture; -use PhpList\Core\Tests\Integration\Domain\Repository\Fixtures\DetachedAdministratorTokenFixture; -use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; +use PhpList\Core\Tests\Integration\Domain\Repository\Fixtures\Identity\AdministratorFixture; +use PhpList\Core\Tests\Integration\Domain\Repository\Fixtures\Identity\DetachedAdministratorTokenFixture; use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; /** @@ -58,7 +56,7 @@ public function testFindReadsModelFromDatabase() self::assertInstanceOf(AdministratorToken::class, $model); self::assertSame($id, $model->getId()); - self::assertEqualsWithDelta($creationDate, $model->getCreationDate(), 1); + self::assertEqualsWithDelta($creationDate, $model->getCreatedAt(), 1); self::assertEquals($expiry, $model->getExpiry()); self::assertSame($key, $model->getKey()); } @@ -70,12 +68,12 @@ public function testCreationDateOfExistingModelStaysUnchangedOnUpdate() $id = 1; /** @var AdministratorToken $model */ $model = $this->repository->find($id); - $creationDate = $model->getCreationDate(); + $creationDate = $model->getCreatedAt(); $model->setKey('asdfasd'); $this->entityManager->flush(); - self::assertEquals($creationDate, $model->getCreationDate()); + self::assertEquals($creationDate, $model->getCreatedAt()); } public function testCreationDateOfNewModelIsSetToNowOnPersist() @@ -85,7 +83,7 @@ public function testCreationDateOfNewModelIsSetToNowOnPersist() $this->entityManager->persist($model); - self::assertSimilarDates($expectedCreationDate, $model->getCreationDate()); + self::assertSimilarDates($expectedCreationDate, $model->getCreatedAt()); } public function testFindOneUnexpiredByKeyFindsUnexpiredTokenWithMatchingKey() diff --git a/tests/Integration/Domain/Repository/Messaging/MessageRepositoryTest.php b/tests/Integration/Domain/Repository/Messaging/MessageRepositoryTest.php new file mode 100644 index 0000000..fc16a41 --- /dev/null +++ b/tests/Integration/Domain/Repository/Messaging/MessageRepositoryTest.php @@ -0,0 +1,133 @@ +loadSchema(); + + $this->messageRepository = self::getContainer()->get(MessageRepository::class); + } + + protected function tearDown(): void + { + $schemaTool = new SchemaTool($this->entityManager); + $schemaTool->dropDatabase(); + parent::tearDown(); + } + + public function testMessageIsPersistedAndFetchedCorrectly(): void + { + $admin = new Administrator(); + $this->entityManager->persist($admin); + + $message = new Message( + new MessageFormat(true, 'text'), + new MessageSchedule(1, null, 3, null, null), + new MessageMetadata('done'), + new MessageContent('Hello world!'), + new MessageOptions(), + $admin + ); + + $this->entityManager->persist($message); + $this->entityManager->flush(); + $this->entityManager->clear(); + + $foundMessages = $this->messageRepository->getByOwnerId($admin->getId()); + + self::assertCount(1, $foundMessages); + self::assertInstanceOf(Message::class, $foundMessages[0]); + self::assertSame('done', $foundMessages[0]->getMetadata()->getStatus()); + self::assertSame('Hello world!', $foundMessages[0]->getContent()->getSubject()); + } + + public function testGetByOwnerIdReturnsOnlyOwnedMessages(): void + { + $admin1 = new Administrator(); + $admin2 = new Administrator(); + + $this->entityManager->persist($admin1); + $this->entityManager->persist($admin2); + + $msg1 = new Message( + new MessageFormat(true, MessageFormat::FORMAT_TEXT), + new MessageSchedule(1, null, 3, null, null), + new MessageMetadata('done'), + new MessageContent('Owned by Admin 1!'), + new MessageOptions(), + $admin1 + ); + + $msg2 = new Message( + new MessageFormat(true, MessageFormat::FORMAT_TEXT), + new MessageSchedule(1, null, 3, null, null), + new MessageMetadata(null), + new MessageContent('Owned by Admin 2!'), + new MessageOptions(), + $admin2 + ); + + $msg3 = new Message( + new MessageFormat(true, MessageFormat::FORMAT_TEXT), + new MessageSchedule(1, null, 3, null, null), + new MessageMetadata(null), + new MessageContent('Hello world!'), + new MessageOptions(), + null + ); + + $this->entityManager->persist($msg1); + $this->entityManager->persist($msg2); + $this->entityManager->persist($msg3); + $this->entityManager->flush(); + $this->entityManager->clear(); + + $results = $this->messageRepository->getByOwnerId($admin1->getId()); + + self::assertCount(1, $results); + self::assertSame('Owned by Admin 1!', $results[0]->getContent()->getSubject()); + } + + public function testMessageTimestampsAreSetOnPersist(): void + { + $expectedDate = new DateTime(); + + $message = new Message( + new MessageFormat(true, MessageFormat::FORMAT_TEXT), + new MessageSchedule(1, null, 3, null, null), + new MessageMetadata(null), + new MessageContent('Hello world!'), + new MessageOptions(), + null + ); + + $this->entityManager->persist($message); + + self::assertSimilarDates($expectedDate, $message->getUpdatedAt()); + } +} diff --git a/tests/Integration/Domain/Repository/Messaging/SubscriberListRepositoryTest.php b/tests/Integration/Domain/Repository/Messaging/SubscriberListRepositoryTest.php index e53d725..c721cb5 100644 --- a/tests/Integration/Domain/Repository/Messaging/SubscriberListRepositoryTest.php +++ b/tests/Integration/Domain/Repository/Messaging/SubscriberListRepositoryTest.php @@ -6,20 +6,19 @@ use DateTime; use Doctrine\ORM\Tools\SchemaTool; -use PhpList\Core\Domain\Model\Identity\Administrator; -use PhpList\Core\Domain\Model\Messaging\SubscriberList; use PhpList\Core\Domain\Model\Subscription\Subscriber; +use PhpList\Core\Domain\Model\Subscription\SubscriberList; use PhpList\Core\Domain\Model\Subscription\Subscription; use PhpList\Core\Domain\Repository\Identity\AdministratorRepository; -use PhpList\Core\Domain\Repository\Messaging\SubscriberListRepository; +use PhpList\Core\Domain\Repository\Subscription\SubscriberListRepository; use PhpList\Core\Domain\Repository\Subscription\SubscriberRepository; use PhpList\Core\Domain\Repository\Subscription\SubscriptionRepository; use PhpList\Core\TestingSupport\Traits\DatabaseTestTrait; use PhpList\Core\TestingSupport\Traits\SimilarDatesAssertionTrait; -use PhpList\Core\Tests\Integration\Domain\Repository\Fixtures\AdministratorFixture; -use PhpList\Core\Tests\Integration\Domain\Repository\Fixtures\SubscriberFixture; -use PhpList\Core\Tests\Integration\Domain\Repository\Fixtures\SubscriberListFixture; -use PhpList\Core\Tests\Integration\Domain\Repository\Fixtures\SubscriptionFixture; +use PhpList\Core\Tests\Integration\Domain\Repository\Fixtures\Identity\AdministratorFixture; +use PhpList\Core\Tests\Integration\Domain\Repository\Fixtures\Subscription\SubscriberFixture; +use PhpList\Core\Tests\Integration\Domain\Repository\Fixtures\Subscription\SubscriberListFixture; +use PhpList\Core\Tests\Integration\Domain\Repository\Fixtures\Subscription\SubscriptionFixture; use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; /** @@ -60,8 +59,8 @@ public function testFindReadsModelFromDatabase() $this->loadFixtures([SubscriberListFixture::class]); $id = 1; - $creationDate = new DateTime(); - $modificationDate = new DateTime(); + $creationDate = new DateTime('2016-06-22 15:01:17'); + $modificationDate = new DateTime('2016-06-23 19:50:43'); $name = 'News'; $description = 'News (and some fun stuff)'; $listPosition = 12; @@ -72,8 +71,8 @@ public function testFindReadsModelFromDatabase() $model = $this->subscriberListRepository->find($id); self::assertSame($id, $model->getId()); - self::assertSimilarDates($creationDate, $model->getCreationDate()); - self::assertSimilarDates($modificationDate, $model->getModificationDate()); + self::assertSimilarDates($creationDate, $model->getCreatedAt()); + self::assertSimilarDates($modificationDate, $model->getUpdatedAt()); self::assertSame($name, $model->getName()); self::assertSame($description, $model->getDescription()); self::assertSame($listPosition, $model->getListPosition()); @@ -89,7 +88,7 @@ public function testCreationDateOfNewModelIsSetToNowOnPersist() $this->entityManager->persist($model); - self::assertSimilarDates($expectedCreationDate, $model->getCreationDate()); + self::assertSimilarDates($expectedCreationDate, $model->getCreatedAt()); } public function testModificationDateOfNewModelIsSetToNowOnPersist() @@ -99,7 +98,7 @@ public function testModificationDateOfNewModelIsSetToNowOnPersist() $this->entityManager->persist($model); - self::assertSimilarDates($expectedModificationDate, $model->getModificationDate()); + self::assertSimilarDates($expectedModificationDate, $model->getUpdatedAt()); } public function testSavePersistsAndFlushesModel() diff --git a/tests/Integration/Domain/Repository/Messaging/TemplateRepositoryTest.php b/tests/Integration/Domain/Repository/Messaging/TemplateRepositoryTest.php new file mode 100644 index 0000000..2d49df1 --- /dev/null +++ b/tests/Integration/Domain/Repository/Messaging/TemplateRepositoryTest.php @@ -0,0 +1,73 @@ +loadSchema(); + + $this->templateRepository = self::getContainer()->get(TemplateRepository::class); + } + + protected function tearDown(): void + { + $schemaTool = new SchemaTool($this->entityManager); + $schemaTool->dropDatabase(); + parent::tearDown(); + } + + public function testGetAllTemplatesReturnsCorrectResults(): void + { + $template1 = new Template('Template 1'); + $template2 = new Template('Template 2'); + + $this->entityManager->persist($template1); + $this->entityManager->persist($template2); + $this->entityManager->flush(); + $this->entityManager->clear(); + + $allTemplates = $this->templateRepository->findAll(); + + self::assertCount(2, $allTemplates); + self::assertContainsOnlyInstancesOf(Template::class, $allTemplates); + } + + public function testTemplateIsPersistedAndFetchedCorrectly(): void + { + $this->loadFixtures([TemplateFixture::class]); + + $fetched = $this->templateRepository->findOneBy(['title' => 'Newsletter Template']); + + self::assertInstanceOf(Template::class, $fetched); + self::assertSame('Newsletter Template', $fetched->getTitle()); + self::assertSame('

Welcome

', $fetched->getContent()); + self::assertSame('', $fetched->getText()); + self::assertSame(1, $fetched->getListOrder()); + } + + public function testGetAllTemplatesReturnsCorrectType(): void + { + $this->loadFixtures([TemplateFixture::class]); + + $allTemplates = $this->templateRepository->findAll(); + + self::assertNotEmpty($allTemplates); + self::assertContainsOnlyInstancesOf(Template::class, $allTemplates); + } +} diff --git a/tests/Integration/Domain/Repository/Subscription/SubscriberRepositoryTest.php b/tests/Integration/Domain/Repository/Subscription/SubscriberRepositoryTest.php index fc7b50f..7c779bf 100644 --- a/tests/Integration/Domain/Repository/Subscription/SubscriberRepositoryTest.php +++ b/tests/Integration/Domain/Repository/Subscription/SubscriberRepositoryTest.php @@ -6,21 +6,19 @@ use DateTime; use Doctrine\Common\Collections\ArrayCollection; -use Doctrine\Common\Collections\Collection; use Doctrine\DBAL\Exception\UniqueConstraintViolationException; use Doctrine\ORM\Tools\SchemaTool; -use PhpList\Core\Domain\Model\Identity\Administrator; use PhpList\Core\Domain\Model\Subscription\Subscriber; use PhpList\Core\Domain\Model\Subscription\Subscription; -use PhpList\Core\Domain\Repository\Messaging\SubscriberListRepository; +use PhpList\Core\Domain\Repository\Subscription\SubscriberListRepository; use PhpList\Core\Domain\Repository\Subscription\SubscriberRepository; use PhpList\Core\Domain\Repository\Subscription\SubscriptionRepository; use PhpList\Core\TestingSupport\Traits\DatabaseTestTrait; use PhpList\Core\TestingSupport\Traits\SimilarDatesAssertionTrait; -use PhpList\Core\Tests\Integration\Domain\Repository\Fixtures\AdministratorFixture; -use PhpList\Core\Tests\Integration\Domain\Repository\Fixtures\SubscriberFixture; -use PhpList\Core\Tests\Integration\Domain\Repository\Fixtures\SubscriberListFixture; -use PhpList\Core\Tests\Integration\Domain\Repository\Fixtures\SubscriptionFixture; +use PhpList\Core\Tests\Integration\Domain\Repository\Fixtures\Identity\AdministratorFixture; +use PhpList\Core\Tests\Integration\Domain\Repository\Fixtures\Subscription\SubscriberFixture; +use PhpList\Core\Tests\Integration\Domain\Repository\Fixtures\Subscription\SubscriberListFixture; +use PhpList\Core\Tests\Integration\Domain\Repository\Fixtures\Subscription\SubscriptionFixture; use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; /** @@ -67,8 +65,8 @@ public function testFindReadsModelFromDatabase() $model = $this->subscriberRepository->find($id); self::assertSame($id, $model->getId()); - self::assertSimilarDates($creationDate, $model->getCreationDate()); - self::assertSimilarDates($modificationDate, $model->getModificationDate()); + self::assertSimilarDates($creationDate, $model->getCreatedAt()); + self::assertSimilarDates($modificationDate, $model->getUpdatedAt()); self::assertEquals('oliver@example.com', $model->getEmail()); self::assertTrue($model->isConfirmed()); self::assertTrue($model->isBlacklisted()); @@ -87,7 +85,7 @@ public function testCreationDateOfNewModelIsSetToNowOnPersist() $this->entityManager->persist($model); - self::assertSimilarDates($expectedCreationDate, $model->getCreationDate()); + self::assertSimilarDates($expectedCreationDate, $model->getCreatedAt()); } public function testModificationDateOfNewModelIsSetToNowOnPersist() @@ -98,7 +96,7 @@ public function testModificationDateOfNewModelIsSetToNowOnPersist() $this->entityManager->persist($model); - self::assertSimilarDates($expectedModificationDate, $model->getModificationDate()); + self::assertSimilarDates($expectedModificationDate, $model->getUpdatedAt()); } public function testSavePersistsAndFlushesModel() diff --git a/tests/Integration/Domain/Repository/Subscription/SubscriptionRepositoryTest.php b/tests/Integration/Domain/Repository/Subscription/SubscriptionRepositoryTest.php index 280c7dc..e394a3f 100644 --- a/tests/Integration/Domain/Repository/Subscription/SubscriptionRepositoryTest.php +++ b/tests/Integration/Domain/Repository/Subscription/SubscriptionRepositoryTest.php @@ -6,17 +6,17 @@ use DateTime; use Doctrine\ORM\Tools\SchemaTool; -use PhpList\Core\Domain\Model\Messaging\SubscriberList; use PhpList\Core\Domain\Model\Subscription\Subscriber; +use PhpList\Core\Domain\Model\Subscription\SubscriberList; use PhpList\Core\Domain\Model\Subscription\Subscription; -use PhpList\Core\Domain\Repository\Messaging\SubscriberListRepository; +use PhpList\Core\Domain\Repository\Subscription\SubscriberListRepository; use PhpList\Core\Domain\Repository\Subscription\SubscriberRepository; use PhpList\Core\Domain\Repository\Subscription\SubscriptionRepository; use PhpList\Core\TestingSupport\Traits\DatabaseTestTrait; use PhpList\Core\TestingSupport\Traits\SimilarDatesAssertionTrait; -use PhpList\Core\Tests\Integration\Domain\Repository\Fixtures\SubscriberFixture; -use PhpList\Core\Tests\Integration\Domain\Repository\Fixtures\SubscriberListFixture; -use PhpList\Core\Tests\Integration\Domain\Repository\Fixtures\SubscriptionFixture; +use PhpList\Core\Tests\Integration\Domain\Repository\Fixtures\Subscription\SubscriberFixture; +use PhpList\Core\Tests\Integration\Domain\Repository\Fixtures\Subscription\SubscriberListFixture; +use PhpList\Core\Tests\Integration\Domain\Repository\Fixtures\Subscription\SubscriptionFixture; use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; /** @@ -64,8 +64,8 @@ public function testFindAllReadsModelsFromDatabase() $model = $result[0]; self::assertInstanceOf(Subscription::class, $model); - self::assertEquals($creationDate, $model->getCreationDate()); - self::assertEquals($modificationDate, $model->getModificationDate()); + self::assertEquals($creationDate, $model->getCreatedAt()); + self::assertEquals($modificationDate, $model->getUpdatedAt()); } public function testCreationDateOfNewModelIsSetToNowOnPersist() @@ -83,7 +83,7 @@ public function testCreationDateOfNewModelIsSetToNowOnPersist() $this->entityManager->persist($model); - self::assertSimilarDates($expectedCreationDate, $model->getCreationDate()); + self::assertSimilarDates($expectedCreationDate, $model->getCreatedAt()); } public function testModificationDateOfNewModelIsSetToNowOnPersist() @@ -101,7 +101,7 @@ public function testModificationDateOfNewModelIsSetToNowOnPersist() $this->entityManager->persist($model); - self::assertSimilarDates($expectedModificationDate, $model->getModificationDate()); + self::assertSimilarDates($expectedModificationDate, $model->getUpdatedAt()); } public function testFindBySubscriberFindsSubscriptionOnlyWithTheGivenSubscriber() @@ -212,4 +212,26 @@ public function testFindOneBySubscriberListAndSubscriberForBothMatchingReturnsMa self::assertSame($subscriberList, $result->getSubscriberList()); self::assertSame($subscriber, $result->getSubscriber()); } + + public function testFindOneByListIdAndSubscriberEmailForNeitherMatchingReturnsNull() + { + $this->loadFixtures([SubscriberFixture::class, SubscriberListFixture::class, SubscriptionFixture::class]); + + $result = $this->subscriptionRepository->findOneBySubscriberEmailAndListId(3, 'some@random.mail'); + + self::assertNull($result); + } + + public function testFindOneByListIdAndSubscriberEmailForBothMatchingReturnsMatch() + { + $this->loadFixtures([SubscriberFixture::class, SubscriberListFixture::class, SubscriptionFixture::class]); + + $subscriberList = $this->subscriberListRepository->find(2); + $subscriber = $this->subscriberRepository->find(1); + $result = $this->subscriptionRepository->findOneBySubscriberEmailAndListId(2, $subscriber->getEmail()); + + self::assertInstanceOf(Subscription::class, $result); + self::assertSame($subscriberList, $result->getSubscriberList()); + self::assertSame($subscriber, $result->getSubscriber()); + } } diff --git a/tests/Integration/Security/AuthenticationTest.php b/tests/Integration/Security/AuthenticationTest.php index dfb5508..a46a6d9 100644 --- a/tests/Integration/Security/AuthenticationTest.php +++ b/tests/Integration/Security/AuthenticationTest.php @@ -8,8 +8,8 @@ use PhpList\Core\Domain\Model\Identity\Administrator; use PhpList\Core\Security\Authentication; use PhpList\Core\TestingSupport\Traits\DatabaseTestTrait; -use PhpList\Core\Tests\Integration\Domain\Repository\Fixtures\AdministratorFixture; -use PhpList\Core\Tests\Integration\Domain\Repository\Fixtures\AdministratorTokenWithAdministratorFixture; +use PhpList\Core\Tests\Integration\Domain\Repository\Fixtures\Identity\AdministratorFixture; +use PhpList\Core\Tests\Integration\Domain\Repository\Fixtures\Identity\AdministratorTokenWithAdministratorFixture; use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; use Symfony\Component\HttpFoundation\Request; diff --git a/tests/Unit/Domain/Model/Identity/AdministratorTest.php b/tests/Unit/Domain/Model/Identity/AdministratorTest.php index 4bdca7d..e5565c6 100644 --- a/tests/Unit/Domain/Model/Identity/AdministratorTest.php +++ b/tests/Unit/Domain/Model/Identity/AdministratorTest.php @@ -55,39 +55,27 @@ public function testSetLoginNameSetsLoginName(): void public function testGetEmailAddressInitiallyReturnsEmptyString(): void { - self::assertSame('', $this->subject->getEmailAddress()); + self::assertSame('', $this->subject->getEmail()); } public function testSetEmailAddressSetsEmailAddress(): void { $value = 'oliver@example.com'; - $this->subject->setEmailAddress($value); + $this->subject->setEmail($value); - self::assertSame($value, $this->subject->getEmailAddress()); + self::assertSame($value, $this->subject->getEmail()); } - public function testGetCreationDateInitiallyReturnsNull(): void + public function testGetUpdatedAtInitiallyReturnsNull(): void { - self::assertNull($this->subject->getCreationDate()); - } - - public function testUpdateCreationDateSetsCreationDateToNow(): void - { - $this->subject->updateCreationDate(); - - self::assertSimilarDates(new \DateTime(), $this->subject->getCreationDate()); - } - - public function testGetModificationDateInitiallyReturnsNull(): void - { - self::assertNull($this->subject->getModificationDate()); + self::assertNull($this->subject->getUpdatedAt()); } public function testUpdateModificationDateSetsModificationDateToNow(): void { - $this->subject->updateModificationDate(); + $this->subject->updateUpdatedAt(); - self::assertSimilarDates(new \DateTime(), $this->subject->getModificationDate()); + self::assertSimilarDates(new \DateTime(), $this->subject->getUpdatedAt()); } public function testGetPasswordHashInitiallyReturnsEmptyString(): void diff --git a/tests/Unit/Domain/Model/Identity/AdministratorTokenTest.php b/tests/Unit/Domain/Model/Identity/AdministratorTokenTest.php index f28a2d7..5318782 100644 --- a/tests/Unit/Domain/Model/Identity/AdministratorTokenTest.php +++ b/tests/Unit/Domain/Model/Identity/AdministratorTokenTest.php @@ -42,16 +42,16 @@ public function testGetIdReturnsId(): void self::assertSame($id, $this->subject->getId()); } - public function testGetCreationDateInitiallyReturnsNull(): void + public function testgetCreatedAtInitiallyReturnsNull(): void { - self::assertNull($this->subject->getCreationDate()); + self::assertNull($this->subject->getCreatedAt()); } public function testUpdateCreationDateSetsCreationDateToNow(): void { - $this->subject->updateCreationDate(); + $this->subject->updateCreatedAt(); - self::assertSimilarDates(new DateTime(), $this->subject->getCreationDate()); + self::assertSimilarDates(new DateTime(), $this->subject->getCreatedAt()); } public function testGetKeyInitiallyReturnsEmptyString(): void diff --git a/tests/Unit/Domain/Model/Messaging/MessageTest.php b/tests/Unit/Domain/Model/Messaging/MessageTest.php new file mode 100644 index 0000000..92ec624 --- /dev/null +++ b/tests/Unit/Domain/Model/Messaging/MessageTest.php @@ -0,0 +1,106 @@ +format = new MessageFormat(true, MessageFormat::FORMAT_TEXT); + $this->schedule = new MessageSchedule(1, new DateTime(), 2, new DateTime(), null); + $this->metadata = new MessageMetadata(); + $this->content = new MessageContent('This is the body'); + $this->options = new MessageOptions(); + $this->owner = new Administrator(); + + $this->message = new Message( + $this->format, + $this->schedule, + $this->metadata, + $this->content, + $this->options, + $this->owner + ); + } + + public function testIsDomainModel(): void + { + self::assertInstanceOf(DomainModel::class, $this->message); + self::assertInstanceOf(Identity::class, $this->message); + self::assertInstanceOf(ModificationDate::class, $this->message); + } + + public function testUuidIsGenerated(): void + { + $uuid = $this->message->getUuid(); + self::assertNotEmpty($uuid); + self::assertMatchesRegularExpression('/^[a-f0-9]{36}$/', $uuid); + } + + public function testGetFormat(): void + { + self::assertSame($this->format, $this->message->getFormat()); + } + + public function testGetSchedule(): void + { + self::assertSame($this->schedule, $this->message->getSchedule()); + } + + public function testGetMetadata(): void + { + self::assertSame($this->metadata, $this->message->getMetadata()); + } + + public function testGetContent(): void + { + self::assertSame($this->content, $this->message->getContent()); + } + + public function testGetOptions(): void + { + self::assertSame($this->options, $this->message->getOptions()); + } + + public function testGetOwner(): void + { + self::assertSame($this->owner, $this->message->getOwner()); + } + + public function testGetOwnerInitiallyNull(): void + { + $message = new Message( + $this->format, + $this->schedule, + $this->metadata, + $this->content, + $this->options, + null + ); + + self::assertNull($message->getOwner()); + } +} diff --git a/tests/Unit/Domain/Model/Messaging/SubscriberListTest.php b/tests/Unit/Domain/Model/Messaging/SubscriberListTest.php index eb8209c..8b7afa5 100644 --- a/tests/Unit/Domain/Model/Messaging/SubscriberListTest.php +++ b/tests/Unit/Domain/Model/Messaging/SubscriberListTest.php @@ -5,12 +5,11 @@ namespace PhpList\Core\Tests\Unit\Domain\Model\Messaging; use DateTime; -use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use PhpList\Core\Domain\Model\Identity\Administrator; use PhpList\Core\Domain\Model\Interfaces\DomainModel; -use PhpList\Core\Domain\Model\Messaging\SubscriberList; use PhpList\Core\Domain\Model\Subscription\Subscriber; +use PhpList\Core\Domain\Model\Subscription\SubscriberList; use PhpList\Core\Domain\Model\Subscription\Subscription; use PhpList\Core\TestingSupport\Traits\ModelTestTrait; use PhpList\Core\TestingSupport\Traits\SimilarDatesAssertionTrait; @@ -46,28 +45,23 @@ public function testGetIdReturnsId(): void self::assertSame($id, $this->subscriberList->getId()); } - public function testGetCreationDateInitiallyReturnsNull(): void - { - self::assertNull($this->subscriberList->getCreationDate()); - } - public function testUpdateCreationDateSetsCreationDateToNow(): void { - $this->subscriberList->updateCreationDate(); + $this->subscriberList->setCategory('test'); - self::assertSimilarDates(new DateTime(), $this->subscriberList->getCreationDate()); + self::assertSimilarDates(new DateTime(), $this->subscriberList->getCreatedAt()); } - public function testGetModificationDateInitiallyReturnsNull(): void + public function testgetUpdatedAtInitiallyReturnsNull(): void { - self::assertNull($this->subscriberList->getModificationDate()); + self::assertNull($this->subscriberList->getUpdatedAt()); } public function testUpdateModificationDateSetsModificationDateToNow(): void { - $this->subscriberList->updateModificationDate(); + $this->subscriberList->updateUpdatedAt(); - self::assertSimilarDates(new DateTime(), $this->subscriberList->getModificationDate()); + self::assertSimilarDates(new DateTime(), $this->subscriberList->getUpdatedAt()); } public function testGetNameInitiallyReturnsEmptyString(): void diff --git a/tests/Unit/Domain/Model/Subscription/SubscriberTest.php b/tests/Unit/Domain/Model/Subscription/SubscriberTest.php index edac579..f61c319 100644 --- a/tests/Unit/Domain/Model/Subscription/SubscriberTest.php +++ b/tests/Unit/Domain/Model/Subscription/SubscriberTest.php @@ -7,8 +7,8 @@ use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use PhpList\Core\Domain\Model\Interfaces\DomainModel; -use PhpList\Core\Domain\Model\Messaging\SubscriberList; use PhpList\Core\Domain\Model\Subscription\Subscriber; +use PhpList\Core\Domain\Model\Subscription\SubscriberList; use PhpList\Core\Domain\Model\Subscription\Subscription; use PhpList\Core\TestingSupport\Traits\ModelTestTrait; use PhpList\Core\TestingSupport\Traits\SimilarDatesAssertionTrait; @@ -44,28 +44,28 @@ public function testGetIdReturnsId(): void self::assertSame($id, $this->subscriber->getId()); } - public function testGetCreationDateInitiallyReturnsNull(): void + public function testGetCreatedAtInitiallyReturnsNull(): void { - self::assertNull($this->subscriber->getCreationDate()); + self::assertSimilarDates(new \DateTime(), $this->subscriber->getCreatedAt()); } public function testUpdateCreationDateSetsCreationDateToNow(): void { - $this->subscriber->updateCreationDate(); + $this->subscriber->updateUpdatedAt(); - self::assertSimilarDates(new \DateTime(), $this->subscriber->getCreationDate()); + self::assertSimilarDates(new \DateTime(), $this->subscriber->getCreatedAt()); } - public function testGetModificationDateInitiallyReturnsNull(): void + public function testgetUpdatedAtInitiallyReturnsNull(): void { - self::assertNull($this->subscriber->getModificationDate()); + self::assertNull($this->subscriber->getUpdatedAt()); } public function testUpdateModificationDateSetsModificationDateToNow(): void { - $this->subscriber->updateModificationDate(); + $this->subscriber->updateUpdatedAt(); - self::assertSimilarDates(new \DateTime(), $this->subscriber->getModificationDate()); + self::assertSimilarDates(new \DateTime(), $this->subscriber->getUpdatedAt()); } public function testGetEmailInitiallyReturnsEmptyString(): void diff --git a/tests/Unit/Domain/Model/Subscription/SubscriptionTest.php b/tests/Unit/Domain/Model/Subscription/SubscriptionTest.php index af1aff8..5cdf3c0 100644 --- a/tests/Unit/Domain/Model/Subscription/SubscriptionTest.php +++ b/tests/Unit/Domain/Model/Subscription/SubscriptionTest.php @@ -6,8 +6,8 @@ use DateTime; use PhpList\Core\Domain\Model\Interfaces\DomainModel; -use PhpList\Core\Domain\Model\Messaging\SubscriberList; use PhpList\Core\Domain\Model\Subscription\Subscriber; +use PhpList\Core\Domain\Model\Subscription\SubscriberList; use PhpList\Core\Domain\Model\Subscription\Subscription; use PhpList\Core\TestingSupport\Traits\ModelTestTrait; use PhpList\Core\TestingSupport\Traits\SimilarDatesAssertionTrait; @@ -61,27 +61,20 @@ public function testSetSubscriberListSetsSubscriberList(): void self::assertSame($model, $this->subject->getSubscriberList()); } - public function testGetCreationDateInitiallyReturnsNull(): void + public function testGetCreatedAtInitiallyReturnsCurrentTime(): void { - self::assertNull($this->subject->getCreationDate()); + self::assertSimilarDates(new DateTime(), $this->subject->getCreatedAt()); } - public function testUpdateCreationDateSetsCreationDateToNow(): void + public function testGetUpdatedAtInitiallyReturnsNull(): void { - $this->subject->updateCreationDate(); - - self::assertSimilarDates(new DateTime(), $this->subject->getCreationDate()); - } - - public function testGetModificationDateInitiallyReturnsNull(): void - { - self::assertNull($this->subject->getModificationDate()); + self::assertNull($this->subject->getUpdatedAt()); } public function testUpdateModificationDateSetsModificationDateToNow(): void { - $this->subject->updateModificationDate(); + $this->subject->updateUpdatedAt(); - self::assertSimilarDates(new DateTime(), $this->subject->getModificationDate()); + self::assertSimilarDates(new DateTime(), $this->subject->getUpdatedAt()); } } diff --git a/tests/Unit/Domain/Repository/Messaging/MessageRepositoryTest.php b/tests/Unit/Domain/Repository/Messaging/MessageRepositoryTest.php new file mode 100644 index 0000000..067ecb7 --- /dev/null +++ b/tests/Unit/Domain/Repository/Messaging/MessageRepositoryTest.php @@ -0,0 +1,36 @@ + + */ +class MessageRepositoryTest extends TestCase +{ + private MessageRepository $subject; + + protected function setUp(): void + { + $entityManager = $this->createMock(EntityManager::class); + + $classMetadata = $this->createMock(ClassMetadata::class); + $classMetadata->name = MessageRepository::class; + + $this->subject = new MessageRepository($entityManager, $classMetadata); + } + + public function testClassIsEntityRepository(): void + { + self::assertInstanceOf(EntityRepository::class, $this->subject); + } +} diff --git a/tests/Unit/Domain/Repository/Messaging/SubscriberListRepositoryTest.php b/tests/Unit/Domain/Repository/Messaging/SubscriberListRepositoryTest.php index e4cf7c1..f1f6a56 100644 --- a/tests/Unit/Domain/Repository/Messaging/SubscriberListRepositoryTest.php +++ b/tests/Unit/Domain/Repository/Messaging/SubscriberListRepositoryTest.php @@ -7,7 +7,8 @@ use Doctrine\ORM\EntityManager; use Doctrine\ORM\EntityRepository; use Doctrine\ORM\Mapping\ClassMetadata; -use PhpList\Core\Domain\Repository\Messaging\SubscriberListRepository; +use PhpList\Core\Domain\Model\Subscription\SubscriberList; +use PhpList\Core\Domain\Repository\Subscription\SubscriberListRepository; use PHPUnit\Framework\TestCase; /** @@ -24,7 +25,7 @@ protected function setUp(): void $entityManager = $this->createMock(EntityManager::class); $classMetadata = $this->createMock(ClassMetadata::class); - $classMetadata->name = 'PhpList\Core\Domain\Model\Messaging\SubscriberList'; + $classMetadata->name = SubscriberList::class; $this->subject = new SubscriberListRepository($entityManager, $classMetadata); }