From e7485704c16e0638a18aeec52d06b0d24c18e94e Mon Sep 17 00:00:00 2001 From: Tatevik Date: Tue, 8 Apr 2025 19:44:03 +0400 Subject: [PATCH 01/30] ISSUE-345: add relation to subscriber attributes --- src/Domain/Model/Subscription/Subscriber.php | 36 +++++++++++++++++-- .../Subscription/SubscriberAttribute.php | 13 +++---- .../SubscriberAttributeDefinition.php} | 4 +-- 3 files changed, 43 insertions(+), 10 deletions(-) rename src/Domain/Model/{Identity/UserAttribute.php => Subscription/SubscriberAttributeDefinition.php} (95%) diff --git a/src/Domain/Model/Subscription/Subscriber.php b/src/Domain/Model/Subscription/Subscriber.php index ce1fec51..f60ce84f 100644 --- a/src/Domain/Model/Subscription/Subscriber.php +++ b/src/Domain/Model/Subscription/Subscriber.php @@ -9,7 +9,6 @@ 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; @@ -24,6 +23,7 @@ * 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')] @@ -83,16 +83,28 @@ 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 = ''; } @@ -223,4 +235,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 4bdc44fc..47844e39 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 95% rename from src/Domain/Model/Identity/UserAttribute.php rename to src/Domain/Model/Subscription/SubscriberAttributeDefinition.php index 81e4c8c2..f3678c5e 100644 --- a/src/Domain/Model/Identity/UserAttribute.php +++ b/src/Domain/Model/Subscription/SubscriberAttributeDefinition.php @@ -2,7 +2,7 @@ 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; @@ -13,7 +13,7 @@ #[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; From 29657c91438355f03615d8637b540b7179f8757c Mon Sep 17 00:00:00 2001 From: Tatevik Date: Wed, 9 Apr 2025 22:03:35 +0400 Subject: [PATCH 02/30] ISSUE-345: return self after set --- config/repositories.yml | 4 +- src/Domain/Model/Identity/AdminAttribute.php | 24 +++++++++--- .../Model/Identity/AdminAttributeRelation.php | 4 +- src/Domain/Model/Identity/Administrator.php | 33 ++++++++++++---- .../Model/Identity/AdministratorToken.php | 23 ++++++++--- src/Domain/Model/Messaging/Attachment.php | 15 +++++--- src/Domain/Model/Messaging/Bounce.php | 15 +++++--- src/Domain/Model/Messaging/BounceRegex.php | 24 ++++++++---- .../Model/Messaging/BounceRegexBounce.php | 6 ++- src/Domain/Model/Subscription/Subscriber.php | 36 +++++++++++++----- .../SubscriberList.php | 38 ++++++++++++------- .../Model/Subscription/Subscription.php | 19 ++++++---- .../SubscriberListRepository.php | 4 +- .../Subscription/SubscriptionRepository.php | 2 +- .../Fixtures/SubscriberListFixture.php | 2 +- .../Fixtures/SubscriptionFixture.php | 2 +- .../SubscriberListRepositoryTest.php | 5 +-- .../Subscription/SubscriberRepositoryTest.php | 4 +- .../SubscriptionRepositoryTest.php | 4 +- .../Model/Messaging/SubscriberListTest.php | 3 +- .../Model/Subscription/SubscriberTest.php | 2 +- .../Model/Subscription/SubscriptionTest.php | 2 +- .../SubscriberListRepositoryTest.php | 4 +- 23 files changed, 183 insertions(+), 92 deletions(-) rename src/Domain/Model/{Messaging => Subscription}/SubscriberList.php (86%) rename src/Domain/Repository/{Messaging => Subscription}/SubscriberListRepository.php (85%) diff --git a/config/repositories.yml b/config/repositories.yml index 47cdbd07..980b0487 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 diff --git a/src/Domain/Model/Identity/AdminAttribute.php b/src/Domain/Model/Identity/AdminAttribute.php index a3696bdb..39d23851 100644 --- a/src/Domain/Model/Identity/AdminAttribute.php +++ b/src/Domain/Model/Identity/AdminAttribute.php @@ -86,33 +86,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 526156fe..454e8800 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/Administrator.php b/src/Domain/Model/Identity/Administrator.php index 8c56c367..b02f2a1f 100644 --- a/src/Domain/Model/Identity/Administrator.php +++ b/src/Domain/Model/Identity/Administrator.php @@ -20,6 +20,7 @@ * 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')] @@ -76,9 +77,11 @@ 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 @@ -86,9 +89,11 @@ public function getEmailAddress(): string return $this->emailAddress; } - public function setEmailAddress(string $emailAddress): void + public function setEmailAddress(string $emailAddress): self { $this->emailAddress = $emailAddress; + + return $this; } public function getPasswordHash(): string @@ -96,10 +101,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()); + + return $this; } public function getPasswordChangeDate(): ?DateTime @@ -107,9 +114,11 @@ public function getPasswordChangeDate(): ?DateTime return $this->passwordChangeDate; } - private function setPasswordChangeDate(DateTime $changeDate): void + private function setPasswordChangeDate(DateTime $changeDate): self { $this->passwordChangeDate = $changeDate; + + return $this; } public function isDisabled(): bool @@ -117,9 +126,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 isSuperUser(): bool @@ -127,14 +138,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,9 +157,11 @@ 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 diff --git a/src/Domain/Model/Identity/AdministratorToken.php b/src/Domain/Model/Identity/AdministratorToken.php index 43c57bbd..35614a04 100644 --- a/src/Domain/Model/Identity/AdministratorToken.php +++ b/src/Domain/Model/Identity/AdministratorToken.php @@ -63,9 +63,11 @@ public function getCreationDate(): ?DateTime return $date; } - private function setCreationDate(DateTime $creationDate): void + private function setCreationDate(DateTime $creationDate): self { $this->creationDate = $creationDate->getTimestamp(); + + return $this; } #[ORM\PrePersist] @@ -79,14 +81,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 +100,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 +120,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/Messaging/Attachment.php b/src/Domain/Model/Messaging/Attachment.php index 7df3b9b9..c5c4410b 100644 --- a/src/Domain/Model/Messaging/Attachment.php +++ b/src/Domain/Model/Messaging/Attachment.php @@ -50,9 +50,10 @@ 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 +61,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 +72,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 +83,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 +94,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 3a4c0668..79cbd2d6 100644 --- a/src/Domain/Model/Messaging/Bounce.php +++ b/src/Domain/Model/Messaging/Bounce.php @@ -58,9 +58,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 +69,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 +80,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 +91,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 +102,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 d5179b99..505cbe73 100644 --- a/src/Domain/Model/Messaging/BounceRegex.php +++ b/src/Domain/Model/Messaging/BounceRegex.php @@ -71,9 +71,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 +82,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 +93,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 +104,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 +115,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 +126,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 +137,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 +148,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 76967704..de245fcb 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/Subscription/Subscriber.php b/src/Domain/Model/Subscription/Subscriber.php index f60ce84f..900ea42b 100644 --- a/src/Domain/Model/Subscription/Subscriber.php +++ b/src/Domain/Model/Subscription/Subscriber.php @@ -113,9 +113,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 @@ -123,9 +125,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 @@ -133,14 +137,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 @@ -148,9 +156,11 @@ 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] @@ -164,9 +174,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 @@ -174,9 +186,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 @@ -184,9 +198,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 @@ -194,9 +210,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; } /** diff --git a/src/Domain/Model/Messaging/SubscriberList.php b/src/Domain/Model/Subscription/SubscriberList.php similarity index 86% rename from src/Domain/Model/Messaging/SubscriberList.php rename to src/Domain/Model/Subscription/SubscriberList.php index 4340ef17..f29d2924 100644 --- a/src/Domain/Model/Messaging/SubscriberList.php +++ b/src/Domain/Model/Subscription/SubscriberList.php @@ -2,16 +2,12 @@ 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; @@ -20,6 +16,9 @@ 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 +26,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')] @@ -74,13 +74,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, @@ -102,9 +102,11 @@ 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 +114,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 @@ -132,9 +136,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 +148,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 +160,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 +172,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 diff --git a/src/Domain/Model/Subscription/Subscription.php b/src/Domain/Model/Subscription/Subscription.php index fa736940..aaee8f66 100644 --- a/src/Domain/Model/Subscription/Subscription.php +++ b/src/Domain/Model/Subscription/Subscription.php @@ -7,22 +7,23 @@ 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'])] @@ -40,7 +41,7 @@ class Subscription implements DomainModel, CreationDate, ModificationDate #[ORM\Id] #[ORM\ManyToOne( - targetEntity: 'PhpList\Core\Domain\Model\Subscription\Subscriber', + targetEntity: Subscriber::class, inversedBy: 'subscriptions' )] #[ORM\JoinColumn(name: 'userid')] @@ -49,7 +50,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')] @@ -62,9 +63,10 @@ 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 +74,9 @@ public function getSubscriberList(): ?SubscriberList return $this->subscriberList; } - public function setSubscriberList(?SubscriberList $subscriberList): void + public function setSubscriberList(?SubscriberList $subscriberList): self { $this->subscriberList = $subscriberList; + return $this; } } diff --git a/src/Domain/Repository/Messaging/SubscriberListRepository.php b/src/Domain/Repository/Subscription/SubscriberListRepository.php similarity index 85% rename from src/Domain/Repository/Messaging/SubscriberListRepository.php rename to src/Domain/Repository/Subscription/SubscriberListRepository.php index 04d45b5a..4430f08b 100644 --- a/src/Domain/Repository/Messaging/SubscriberListRepository.php +++ b/src/Domain/Repository/Subscription/SubscriberListRepository.php @@ -2,10 +2,10 @@ declare(strict_types=1); -namespace PhpList\Core\Domain\Repository\Messaging; +namespace PhpList\Core\Domain\Repository\Subscription; use PhpList\Core\Domain\Model\Identity\Administrator; -use PhpList\Core\Domain\Model\Messaging\SubscriberList; +use PhpList\Core\Domain\Model\Subscription\SubscriberList; use PhpList\Core\Domain\Repository\AbstractRepository; /** diff --git a/src/Domain/Repository/Subscription/SubscriptionRepository.php b/src/Domain/Repository/Subscription/SubscriptionRepository.php index eb79f023..bebd0200 100644 --- a/src/Domain/Repository/Subscription/SubscriptionRepository.php +++ b/src/Domain/Repository/Subscription/SubscriptionRepository.php @@ -4,8 +4,8 @@ namespace PhpList\Core\Domain\Repository\Subscription; -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\AbstractRepository; diff --git a/tests/Integration/Domain/Repository/Fixtures/SubscriberListFixture.php b/tests/Integration/Domain/Repository/Fixtures/SubscriberListFixture.php index 0b8aff88..d95f759d 100644 --- a/tests/Integration/Domain/Repository/Fixtures/SubscriberListFixture.php +++ b/tests/Integration/Domain/Repository/Fixtures/SubscriberListFixture.php @@ -8,7 +8,7 @@ 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; diff --git a/tests/Integration/Domain/Repository/Fixtures/SubscriptionFixture.php b/tests/Integration/Domain/Repository/Fixtures/SubscriptionFixture.php index 35cd792b..9fc192d7 100644 --- a/tests/Integration/Domain/Repository/Fixtures/SubscriptionFixture.php +++ b/tests/Integration/Domain/Repository/Fixtures/SubscriptionFixture.php @@ -7,8 +7,8 @@ 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; diff --git a/tests/Integration/Domain/Repository/Messaging/SubscriberListRepositoryTest.php b/tests/Integration/Domain/Repository/Messaging/SubscriberListRepositoryTest.php index e53d725b..06f74183 100644 --- a/tests/Integration/Domain/Repository/Messaging/SubscriberListRepositoryTest.php +++ b/tests/Integration/Domain/Repository/Messaging/SubscriberListRepositoryTest.php @@ -6,12 +6,11 @@ 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; diff --git a/tests/Integration/Domain/Repository/Subscription/SubscriberRepositoryTest.php b/tests/Integration/Domain/Repository/Subscription/SubscriberRepositoryTest.php index fc7b50f4..ef162e16 100644 --- a/tests/Integration/Domain/Repository/Subscription/SubscriberRepositoryTest.php +++ b/tests/Integration/Domain/Repository/Subscription/SubscriberRepositoryTest.php @@ -6,13 +6,11 @@ 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; diff --git a/tests/Integration/Domain/Repository/Subscription/SubscriptionRepositoryTest.php b/tests/Integration/Domain/Repository/Subscription/SubscriptionRepositoryTest.php index 280c7dcc..408179ab 100644 --- a/tests/Integration/Domain/Repository/Subscription/SubscriptionRepositoryTest.php +++ b/tests/Integration/Domain/Repository/Subscription/SubscriptionRepositoryTest.php @@ -6,10 +6,10 @@ 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; diff --git a/tests/Unit/Domain/Model/Messaging/SubscriberListTest.php b/tests/Unit/Domain/Model/Messaging/SubscriberListTest.php index eb8209c5..2620966b 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; diff --git a/tests/Unit/Domain/Model/Subscription/SubscriberTest.php b/tests/Unit/Domain/Model/Subscription/SubscriberTest.php index edac5790..408d78b3 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; diff --git a/tests/Unit/Domain/Model/Subscription/SubscriptionTest.php b/tests/Unit/Domain/Model/Subscription/SubscriptionTest.php index af1aff86..e83197b3 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; diff --git a/tests/Unit/Domain/Repository/Messaging/SubscriberListRepositoryTest.php b/tests/Unit/Domain/Repository/Messaging/SubscriberListRepositoryTest.php index e4cf7c19..134f633f 100644 --- a/tests/Unit/Domain/Repository/Messaging/SubscriberListRepositoryTest.php +++ b/tests/Unit/Domain/Repository/Messaging/SubscriberListRepositoryTest.php @@ -7,7 +7,7 @@ use Doctrine\ORM\EntityManager; use Doctrine\ORM\EntityRepository; use Doctrine\ORM\Mapping\ClassMetadata; -use PhpList\Core\Domain\Repository\Messaging\SubscriberListRepository; +use PhpList\Core\Domain\Repository\Subscription\SubscriberListRepository; use PHPUnit\Framework\TestCase; /** @@ -24,7 +24,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 = 'PhpList\Core\Domain\Model\Subscription\SubscriberList'; $this->subject = new SubscriberListRepository($entityManager, $classMetadata); } From b4d1e8a6225125debc4527769ab56c3f2d591826 Mon Sep 17 00:00:00 2001 From: Tatevik Date: Wed, 9 Apr 2025 22:45:36 +0400 Subject: [PATCH 03/30] ISSUE-345: fix traits --- src/Domain/Model/Identity/AdministratorToken.php | 3 ++- src/Domain/Model/Interfaces/CreationDate.php | 5 +++-- src/Domain/Model/Interfaces/ModificationDate.php | 4 ++-- src/Domain/Model/Subscription/Subscriber.php | 3 ++- src/Domain/Model/Subscription/SubscriberList.php | 3 ++- src/Domain/Model/Traits/CreationDateTrait.php | 11 ++++++++--- src/Domain/Model/Traits/ModificationDateTrait.php | 8 ++++++-- 7 files changed, 25 insertions(+), 12 deletions(-) diff --git a/src/Domain/Model/Identity/AdministratorToken.php b/src/Domain/Model/Identity/AdministratorToken.php index 35614a04..3178333a 100644 --- a/src/Domain/Model/Identity/AdministratorToken.php +++ b/src/Domain/Model/Identity/AdministratorToken.php @@ -71,9 +71,10 @@ private function setCreationDate(DateTime $creationDate): self } #[ORM\PrePersist] - public function updateCreationDate(): void + public function updateCreationDate(): DomainModel { $this->setCreationDate(new DateTime()); + return $this; } public function getExpiry(): DateTime diff --git a/src/Domain/Model/Interfaces/CreationDate.php b/src/Domain/Model/Interfaces/CreationDate.php index 41a6f9ad..5ff35925 100644 --- a/src/Domain/Model/Interfaces/CreationDate.php +++ b/src/Domain/Model/Interfaces/CreationDate.php @@ -13,6 +13,7 @@ * The CreationDateTrait is the default implementation. * * @author Oliver Klee + * @author Tatevik Grigoryan */ interface CreationDate { @@ -26,7 +27,7 @@ public function getCreationDate(): ?DateTime; * * @PrePersist * - * @return void + * @return DomainModel */ - public function updateCreationDate(): void; + public function updateCreationDate(): DomainModel; } diff --git a/src/Domain/Model/Interfaces/ModificationDate.php b/src/Domain/Model/Interfaces/ModificationDate.php index 68a0dfc1..1c40208d 100644 --- a/src/Domain/Model/Interfaces/ModificationDate.php +++ b/src/Domain/Model/Interfaces/ModificationDate.php @@ -27,7 +27,7 @@ public function getModificationDate(): ?DateTime; * @Mapping\PrePersist * @Mapping\PreUpdate * - * @return void + * @return DomainModel */ - public function updateModificationDate(): void; + public function updateModificationDate(): DomainModel; } diff --git a/src/Domain/Model/Subscription/Subscriber.php b/src/Domain/Model/Subscription/Subscriber.php index 900ea42b..7897f571 100644 --- a/src/Domain/Model/Subscription/Subscriber.php +++ b/src/Domain/Model/Subscription/Subscriber.php @@ -164,9 +164,10 @@ public function setUniqueId(string $uniqueId): self } #[ORM\PrePersist] - public function generateUniqueId(): void + public function generateUniqueId(): self { $this->setUniqueId(bin2hex(random_bytes(16))); + return $this; } public function getEmail(): string diff --git a/src/Domain/Model/Subscription/SubscriberList.php b/src/Domain/Model/Subscription/SubscriberList.php index f29d2924..2f0f7724 100644 --- a/src/Domain/Model/Subscription/SubscriberList.php +++ b/src/Domain/Model/Subscription/SubscriberList.php @@ -126,9 +126,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 diff --git a/src/Domain/Model/Traits/CreationDateTrait.php b/src/Domain/Model/Traits/CreationDateTrait.php index 51b6fd25..885ef06c 100644 --- a/src/Domain/Model/Traits/CreationDateTrait.php +++ b/src/Domain/Model/Traits/CreationDateTrait.php @@ -6,6 +6,7 @@ use DateTime; use Doctrine\ORM\Mapping as ORM; +use PhpList\Core\Domain\Model\Interfaces\DomainModel; /** * This trait provides an automatic creation date for models. @@ -16,6 +17,7 @@ * and also to have a $creationDate property with the correct column name mapping. * * @author Oliver Klee + * @author Tatevik Grigoryan */ trait CreationDateTrait { @@ -30,16 +32,19 @@ public function getCreationDate(): ?DateTime /** * @param DateTime $creationDate * - * @return void + * @return DomainModel */ - private function setCreationDate(DateTime $creationDate): void + private function setCreationDate(DateTime $creationDate): DomainModel { $this->creationDate = $creationDate; + return $this; } #[ORM\PrePersist] - public function updateCreationDate(): void + public function updateCreationDate(): DomainModel { $this->setCreationDate(new DateTime()); + + return $this; } } diff --git a/src/Domain/Model/Traits/ModificationDateTrait.php b/src/Domain/Model/Traits/ModificationDateTrait.php index ab03e769..57c8260b 100644 --- a/src/Domain/Model/Traits/ModificationDateTrait.php +++ b/src/Domain/Model/Traits/ModificationDateTrait.php @@ -6,6 +6,7 @@ use DateTime; use Doctrine\ORM\Mapping as ORM; +use PhpList\Core\Domain\Model\Interfaces\DomainModel; /** * This trait provides an automatic modification date for models. @@ -27,15 +28,18 @@ public function getModificationDate(): ?DateTime return $this->modificationDate; } - private function setModificationDate(DateTime $modificationDate): void + private function setModificationDate(DateTime $modificationDate): DomainModel { $this->modificationDate = $modificationDate; + return $this; } #[ORM\PrePersist] #[ORM\PreUpdate] - public function updateModificationDate(): void + public function updateModificationDate(): DomainModel { $this->setModificationDate(new DateTime()); + + return $this; } } From 58b548e020629e0a9b72c47f9ca45ddcde685b6b Mon Sep 17 00:00:00 2001 From: Tatevik Date: Sun, 13 Apr 2025 20:00:41 +0400 Subject: [PATCH 04/30] ISSUE-345: add method in SubscriptionRepository --- .../Subscription/SubscriptionRepository.php | 19 ++++++++++++++++ .../SubscriptionRepositoryTest.php | 22 +++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/src/Domain/Repository/Subscription/SubscriptionRepository.php b/src/Domain/Repository/Subscription/SubscriptionRepository.php index bebd0200..ad6fa4b0 100644 --- a/src/Domain/Repository/Subscription/SubscriptionRepository.php +++ b/src/Domain/Repository/Subscription/SubscriptionRepository.php @@ -34,4 +34,23 @@ public function findOneBySubscriberListAndSubscriber(SubscriberList $list, Subsc ] ); } + + /** + * @param int $listId + * @param string $email + * + * @return Subscription|null + */ + public function findOneBySubscriberEmailAndListId(int $listId, string $email): ?Subscription + { + return $this->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/Subscription/SubscriptionRepositoryTest.php b/tests/Integration/Domain/Repository/Subscription/SubscriptionRepositoryTest.php index 408179ab..4b50eedc 100644 --- a/tests/Integration/Domain/Repository/Subscription/SubscriptionRepositoryTest.php +++ b/tests/Integration/Domain/Repository/Subscription/SubscriptionRepositoryTest.php @@ -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()); + } } From 915df7ecded62b9c88222058b3aa9f3a79ed8c34 Mon Sep 17 00:00:00 2001 From: Tatevik Date: Tue, 15 Apr 2025 21:08:56 +0400 Subject: [PATCH 05/30] ISSUE-345: message repository --- config/repositories.yml | 5 + .../Model/Messaging/{Message => }/Message.php | 32 ++++-- .../Model/Messaging/Message/MessageFormat.php | 2 +- .../Messaging/Message/MessageOptions.php | 12 +- src/Domain/Model/Messaging/UserMessage.php | 1 - .../Messaging/MessageRepository.php | 10 ++ .../Domain/Model/Messaging/MessageTest.php | 106 ++++++++++++++++++ .../Messaging/MessageRepositoryTest.php | 36 ++++++ .../SubscriberListRepositoryTest.php | 3 +- 9 files changed, 185 insertions(+), 22 deletions(-) rename src/Domain/Model/Messaging/{Message => }/Message.php (65%) create mode 100644 tests/Unit/Domain/Model/Messaging/MessageTest.php create mode 100644 tests/Unit/Domain/Repository/Messaging/MessageRepositoryTest.php diff --git a/config/repositories.yml b/config/repositories.yml index 980b0487..ad356367 100644 --- a/config/repositories.yml +++ b/config/repositories.yml @@ -25,3 +25,8 @@ 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: + - PPhpList\Core\Domain\Model\Messaging\Message diff --git a/src/Domain/Model/Messaging/Message/Message.php b/src/Domain/Model/Messaging/Message.php similarity index 65% rename from src/Domain/Model/Messaging/Message/Message.php rename to src/Domain/Model/Messaging/Message.php index a2285dab..55ae68a5 100644 --- a/src/Domain/Model/Messaging/Message/Message.php +++ b/src/Domain/Model/Messaging/Message.php @@ -2,13 +2,18 @@ declare(strict_types=1); -namespace PhpList\Core\Domain\Model\Messaging\Message; +namespace PhpList\Core\Domain\Model\Messaging; -use DateTime; use Doctrine\ORM\Mapping as ORM; +use PhpList\Core\Domain\Model\Identity\Administrator; 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\Messaging\Message\MessageContent; +use PhpList\Core\Domain\Model\Messaging\Message\MessageFormat; +use PhpList\Core\Domain\Model\Messaging\Message\MessageMetadata; +use PhpList\Core\Domain\Model\Messaging\Message\MessageOptions; +use PhpList\Core\Domain\Model\Messaging\Message\MessageSchedule; use PhpList\Core\Domain\Model\Traits\IdentityTrait; use PhpList\Core\Domain\Model\Traits\ModificationDateTrait; use PhpList\Core\Domain\Repository\Messaging\MessageRepository; @@ -22,30 +27,35 @@ class Message implements DomainModel, Identity, ModificationDate use IdentityTrait; use ModificationDateTrait; - #[ORM\Embedded(class: 'MessageFormat')] + #[ORM\Embedded(class: MessageFormat::class)] private MessageFormat $format; - #[ORM\Embedded(class: 'MessageSchedule')] + #[ORM\Embedded(class: MessageSchedule::class)] private MessageSchedule $schedule; - #[ORM\Embedded(class: 'MessageMetadata')] + #[ORM\Embedded(class: MessageMetadata::class)] private MessageMetadata $metadata; - #[ORM\Embedded(class: 'MessageContent')] + #[ORM\Embedded(class: MessageContent::class)] private MessageContent $content; - #[ORM\Embedded(class: 'MessageOptions')] + #[ORM\Embedded(class: MessageOptions::class)] private MessageOptions $options; #[ORM\Column(type: 'string', length: 36, nullable: true, options: ['default' => ''])] private ?string $uuid = ''; + #[ORM\ManyToOne(targetEntity: Administrator::class)] + #[ORM\JoinColumn(name: 'owner', referencedColumnName: 'id', nullable: true)] + private ?Administrator $owner; + public function __construct( MessageFormat $format, MessageSchedule $schedule, MessageMetadata $metadata, MessageContent $content, - MessageOptions $options + MessageOptions $options, + ?Administrator $owner = null ) { $this->format = $format; $this->schedule = $schedule; @@ -53,6 +63,7 @@ public function __construct( $this->content = $content; $this->options = $options; $this->uuid = bin2hex(random_bytes(18)); + $this->owner = $owner; } public function getFormat(): MessageFormat @@ -84,4 +95,9 @@ public function getUuid(): ?string { return $this->uuid; } + + public function getOwner(): ?Administrator + { + return $this->owner; + } } diff --git a/src/Domain/Model/Messaging/Message/MessageFormat.php b/src/Domain/Model/Messaging/Message/MessageFormat.php index e4de42c4..e3bc9612 100644 --- a/src/Domain/Model/Messaging/Message/MessageFormat.php +++ b/src/Domain/Model/Messaging/Message/MessageFormat.php @@ -30,7 +30,7 @@ class MessageFormat #[ORM\Column(name: 'astextandpdf', type: 'integer', options: ['default' => 0])] private int $asTextAndPdf = 0; - public function __construct(bool $htmlFormatted, ?string $sendFormat) + public function __construct(bool $htmlFormatted, ?string $sendFormat = null) { $this->htmlFormatted = $htmlFormatted; $this->sendFormat = $sendFormat; diff --git a/src/Domain/Model/Messaging/Message/MessageOptions.php b/src/Domain/Model/Messaging/Message/MessageOptions.php index 0c885528..4742d786 100644 --- a/src/Domain/Model/Messaging/Message/MessageOptions.php +++ b/src/Domain/Model/Messaging/Message/MessageOptions.php @@ -34,9 +34,6 @@ class MessageOptions #[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 = '', @@ -45,8 +42,7 @@ public function __construct( ?string $userSelection = null, ?int $template = null, ?DateTime $sendStart = null, - ?string $rssTemplate = null, - ?int $owner = null + ?string $rssTemplate = null ) { $this->fromField = $fromField; $this->toField = $toField; @@ -56,7 +52,6 @@ public function __construct( $this->template = $template; $this->sendStart = $sendStart; $this->rssTemplate = $rssTemplate; - $this->owner = $owner; } public function getFromField(): string @@ -98,9 +93,4 @@ public function getRssTemplate(): ?string { return $this->rssTemplate; } - - public function getOwner(): ?int - { - return $this->owner; - } } diff --git a/src/Domain/Model/Messaging/UserMessage.php b/src/Domain/Model/Messaging/UserMessage.php index f62dca24..2fc3eeb2 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/Repository/Messaging/MessageRepository.php b/src/Domain/Repository/Messaging/MessageRepository.php index 0d013bef..5fad191c 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/tests/Unit/Domain/Model/Messaging/MessageTest.php b/tests/Unit/Domain/Model/Messaging/MessageTest.php new file mode 100644 index 00000000..4b7378f5 --- /dev/null +++ b/tests/Unit/Domain/Model/Messaging/MessageTest.php @@ -0,0 +1,106 @@ +format = new MessageFormat(true); + $this->schedule = new MessageSchedule(1, new DateTime(), 2, new DateTime()); + $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/Repository/Messaging/MessageRepositoryTest.php b/tests/Unit/Domain/Repository/Messaging/MessageRepositoryTest.php new file mode 100644 index 00000000..067ecb73 --- /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 134f633f..f1f6a56b 100644 --- a/tests/Unit/Domain/Repository/Messaging/SubscriberListRepositoryTest.php +++ b/tests/Unit/Domain/Repository/Messaging/SubscriberListRepositoryTest.php @@ -7,6 +7,7 @@ use Doctrine\ORM\EntityManager; use Doctrine\ORM\EntityRepository; use Doctrine\ORM\Mapping\ClassMetadata; +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\Subscription\SubscriberList'; + $classMetadata->name = SubscriberList::class; $this->subject = new SubscriberListRepository($entityManager, $classMetadata); } From bbbfb090c24c35fa8480f7f909e47ce0eb8764d9 Mon Sep 17 00:00:00 2001 From: Tatevik Date: Wed, 16 Apr 2025 12:04:06 +0400 Subject: [PATCH 06/30] ISSUE-345: message fixture --- config/repositories.yml | 2 +- .../Model/Messaging/Message/MessageFormat.php | 32 ++++-- .../Domain/Repository/Fixtures/Message.csv | 21 ++++ .../Repository/Fixtures/MessageFixture.php | 106 ++++++++++++++++++ 4 files changed, 150 insertions(+), 11 deletions(-) create mode 100644 tests/Integration/Domain/Repository/Fixtures/Message.csv create mode 100644 tests/Integration/Domain/Repository/Fixtures/MessageFixture.php diff --git a/config/repositories.yml b/config/repositories.yml index ad356367..198a6cd2 100644 --- a/config/repositories.yml +++ b/config/repositories.yml @@ -29,4 +29,4 @@ services: PhpList\Core\Domain\Repository\Messaging\MessageRepository: parent: PhpList\Core\Domain\Repository arguments: - - PPhpList\Core\Domain\Model\Messaging\Message + - PhpList\Core\Domain\Model\Messaging\Message diff --git a/src/Domain/Model/Messaging/Message/MessageFormat.php b/src/Domain/Model/Messaging/Message/MessageFormat.php index e3bc9612..c6b5622b 100644 --- a/src/Domain/Model/Messaging/Message/MessageFormat.php +++ b/src/Domain/Model/Messaging/Message/MessageFormat.php @@ -16,24 +16,36 @@ class MessageFormat private ?string $sendFormat = null; #[ORM\Column(name: 'astext', type: 'integer', options: ['default' => 0])] - private int $asText = 0; + private int $asText; #[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 int $asHtml; #[ORM\Column(name: 'aspdf', type: 'integer', options: ['default' => 0])] - private int $asPdf = 0; + private int $asPdf; - #[ORM\Column(name: 'astextandpdf', type: 'integer', options: ['default' => 0])] - private int $asTextAndPdf = 0; + #[ORM\Column(name: 'astextandhtml', type: 'integer', options: ['default' => 0])] + private int $asTextAndHtml; - public function __construct(bool $htmlFormatted, ?string $sendFormat = null) - { + #[ORM\Column(name: 'astextandpdf', type: 'integer', options: ['default' => 0])] + private int $asTextAndPdf; + + public function __construct( + bool $htmlFormatted, + string $sendFormat = null, + int $asText = 0, + int $asHtml = 0, + int $asPdf = 0, + int $asTextAndHtml = 0, + int $asTextAndPdf = 0, + ) { $this->htmlFormatted = $htmlFormatted; $this->sendFormat = $sendFormat; + $this->asText = $asText; + $this->asHtml = $asHtml; + $this->asPdf = $asPdf; + $this->asTextAndHtml = $asTextAndHtml; + $this->asTextAndPdf = $asTextAndPdf; } public function isHtmlFormatted(): bool diff --git a/tests/Integration/Domain/Repository/Fixtures/Message.csv b/tests/Integration/Domain/Repository/Fixtures/Message.csv new file mode 100644 index 00000000..c2e52a79 --- /dev/null +++ b/tests/Integration/Domain/Repository/Fixtures/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/MessageFixture.php b/tests/Integration/Domain/Repository/Fixtures/MessageFixture.php new file mode 100644 index 00000000..59f4b25f --- /dev/null +++ b/tests/Integration/Domain/Repository/Fixtures/MessageFixture.php @@ -0,0 +1,106 @@ +getRepository(Administrator::class); + + do { + $data = fgetcsv($handle); + if ($data === false) { + break; + } + $row = array_combine($headers, $data); + $admin = $adminRepository->find($row['owner']); + + $format = new MessageFormat( + $row['htmlformatted'], + $row['sendformat'], + $row['astext'], + $row['ashtml'], + $row['aspdf'], + $row['astextandhtml'], + $row['astextandpdf'] + ); + + $schedule = new MessageSchedule( + $row['repeatinterval'], + $row['repeatuntil'], + $row['requeueinterval'], + $row['requeueuntil'] + ); + $metadata = new MessageMetadata( + $row['status'], + $row['processed'], + $row['viewed'], + $row['bouncecount'], + $row['entered'], + $row['sent'] + ); + $content = new MessageContent( + $row['subject'], + $row['message'], + $row['textmessage'], + $row['footer'] + ); + $options = new MessageOptions( + $row['fromfield'], + $row['tofield'], + $row['replyto'], + $row['embargo'], + $row['userselection'], + $row['template'], + $row['sendstart'], + $row['rsstemplate'], + ); + + $message = new Message( + $format, + $schedule, + $metadata, + $content, + $options, + $admin, + ); + $this->setSubjectId($message, (int)$row['id']); + $this->setSubjectProperty($message, 'uuid', $row['uuid']); + + $manager->persist($message); + $this->setSubjectProperty($message, 'modificationDate', new DateTime($row['modified'])); + } while (true); + + fclose($handle); + } +} From 8b81d3addd3e16171469fc7686e45b3f7f4a661e Mon Sep 17 00:00:00 2001 From: Tatevik Date: Wed, 16 Apr 2025 12:16:41 +0400 Subject: [PATCH 07/30] ISSUE-345: message fixture + test --- .../Messaging/MessageRepositoryTest.php | 133 ++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 tests/Integration/Domain/Repository/Messaging/MessageRepositoryTest.php diff --git a/tests/Integration/Domain/Repository/Messaging/MessageRepositoryTest.php b/tests/Integration/Domain/Repository/Messaging/MessageRepositoryTest.php new file mode 100644 index 00000000..e5f6187f --- /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), + new MessageSchedule(1, null, 3, 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), + new MessageSchedule(1, null, 3, null), + new MessageMetadata('done'), + new MessageContent('Owned by Admin 1!'), + new MessageOptions(), + $admin1 + ); + + $msg2 = new Message( + new MessageFormat(true), + new MessageSchedule(1, null, 3, null), + new MessageMetadata(null), + new MessageContent('Owned by Admin 2!'), + new MessageOptions(), + $admin2 + ); + + $msg3 = new Message( + new MessageFormat(true), + new MessageSchedule(1, null, 3, 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), + new MessageSchedule(1, null, 3, null), + new MessageMetadata(null), + new MessageContent('Hello world!'), + new MessageOptions(), + null + ); + + $this->entityManager->persist($message); + + self::assertSimilarDates($expectedDate, $message->getModificationDate()); + } +} From 2047f7732d6c3a315d0d053d3813d9992880e51b Mon Sep 17 00:00:00 2001 From: Tatevik Date: Wed, 16 Apr 2025 12:47:40 +0400 Subject: [PATCH 08/30] ISSUE-345: column name fix --- src/Domain/Model/Messaging/Message/MessageFormat.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Domain/Model/Messaging/Message/MessageFormat.php b/src/Domain/Model/Messaging/Message/MessageFormat.php index c6b5622b..77b2f857 100644 --- a/src/Domain/Model/Messaging/Message/MessageFormat.php +++ b/src/Domain/Model/Messaging/Message/MessageFormat.php @@ -9,7 +9,7 @@ #[ORM\Embeddable] class MessageFormat { - #[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)] From c5d1429611178f319bc657568cb0cce262ec65ee Mon Sep 17 00:00:00 2001 From: Tatevik Date: Wed, 16 Apr 2025 12:51:31 +0400 Subject: [PATCH 09/30] ISSUE-345: remove prefix --- src/Domain/Model/Messaging/Message.php | 10 +++++----- src/Domain/Model/Messaging/Message/MessageContent.php | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Domain/Model/Messaging/Message.php b/src/Domain/Model/Messaging/Message.php index 55ae68a5..53e33356 100644 --- a/src/Domain/Model/Messaging/Message.php +++ b/src/Domain/Model/Messaging/Message.php @@ -27,19 +27,19 @@ class Message implements DomainModel, Identity, ModificationDate use IdentityTrait; use ModificationDateTrait; - #[ORM\Embedded(class: MessageFormat::class)] + #[ORM\Embedded(class: MessageFormat::class, columnPrefix: false)] private MessageFormat $format; - #[ORM\Embedded(class: MessageSchedule::class)] + #[ORM\Embedded(class: MessageSchedule::class, columnPrefix: false)] private MessageSchedule $schedule; - #[ORM\Embedded(class: MessageMetadata::class)] + #[ORM\Embedded(class: MessageMetadata::class, columnPrefix: false)] private MessageMetadata $metadata; - #[ORM\Embedded(class: MessageContent::class)] + #[ORM\Embedded(class: MessageContent::class, columnPrefix: false)] private MessageContent $content; - #[ORM\Embedded(class: MessageOptions::class)] + #[ORM\Embedded(class: MessageOptions::class, columnPrefix: false)] private MessageOptions $options; #[ORM\Column(type: 'string', length: 36, nullable: true, options: ['default' => ''])] diff --git a/src/Domain/Model/Messaging/Message/MessageContent.php b/src/Domain/Model/Messaging/Message/MessageContent.php index 6474c4ec..7bf80b52 100644 --- a/src/Domain/Model/Messaging/Message/MessageContent.php +++ b/src/Domain/Model/Messaging/Message/MessageContent.php @@ -12,7 +12,7 @@ class MessageContent #[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)] From 743fc18598596de7c1a5a477fe7cab426f91fead Mon Sep 17 00:00:00 2001 From: Tatevik Date: Wed, 16 Apr 2025 13:30:05 +0400 Subject: [PATCH 10/30] ISSUE-345: make format props bool --- .../Model/Messaging/Message/MessageFormat.php | 60 ++++++++++++++----- .../Messaging/Message/MessageOptions.php | 2 +- .../Repository/Fixtures/MessageFixture.php | 10 ++-- 3 files changed, 51 insertions(+), 21 deletions(-) diff --git a/src/Domain/Model/Messaging/Message/MessageFormat.php b/src/Domain/Model/Messaging/Message/MessageFormat.php index 77b2f857..d344642a 100644 --- a/src/Domain/Model/Messaging/Message/MessageFormat.php +++ b/src/Domain/Model/Messaging/Message/MessageFormat.php @@ -16,28 +16,28 @@ class MessageFormat private ?string $sendFormat = null; #[ORM\Column(name: 'astext', type: 'integer', options: ['default' => 0])] - private int $asText; + private bool $asText; #[ORM\Column(name: 'ashtml', type: 'integer', options: ['default' => 0])] - private int $asHtml; + private bool $asHtml; #[ORM\Column(name: 'aspdf', type: 'integer', options: ['default' => 0])] - private int $asPdf; + private bool $asPdf; #[ORM\Column(name: 'astextandhtml', type: 'integer', options: ['default' => 0])] - private int $asTextAndHtml; + private bool $asTextAndHtml; #[ORM\Column(name: 'astextandpdf', type: 'integer', options: ['default' => 0])] - private int $asTextAndPdf; + private bool $asTextAndPdf; public function __construct( bool $htmlFormatted, string $sendFormat = null, - int $asText = 0, - int $asHtml = 0, - int $asPdf = 0, - int $asTextAndHtml = 0, - int $asTextAndPdf = 0, + bool $asText = false, + bool $asHtml = false, + bool $asPdf = false, + bool $asTextAndHtml = false, + bool $asTextAndPdf = false, ) { $this->htmlFormatted = $htmlFormatted; $this->sendFormat = $sendFormat; @@ -58,27 +58,27 @@ public function getSendFormat(): ?string return $this->sendFormat; } - public function getAsText(): int + 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; } @@ -88,4 +88,34 @@ public function setSendFormat(?string $sendFormat): self $this->sendFormat = $sendFormat; return $this; } + + public function setAsText(bool $asText): self + { + $this->asText = $asText; + return $this; + } + + public function setAsHtml(bool $asHtml): self + { + $this->asHtml = $asHtml; + return $this; + } + + public function setAsPdf(bool $asPdf): self + { + $this->asPdf = $asPdf; + return $this; + } + + public function setAsTextAndHtml(bool $asTextAndHtml): self + { + $this->asTextAndHtml = $asTextAndHtml; + return $this; + } + + public function setAsTextAndPdf(bool $asTextAndPdf): self + { + $this->asTextAndPdf = $asTextAndPdf; + return $this; + } } diff --git a/src/Domain/Model/Messaging/Message/MessageOptions.php b/src/Domain/Model/Messaging/Message/MessageOptions.php index 4742d786..febb04d8 100644 --- a/src/Domain/Model/Messaging/Message/MessageOptions.php +++ b/src/Domain/Model/Messaging/Message/MessageOptions.php @@ -64,7 +64,7 @@ public function getToField(): string return $this->toField; } - public function getReplyToO(): string + public function getReplyTo(): string { return $this->replyTo; } diff --git a/tests/Integration/Domain/Repository/Fixtures/MessageFixture.php b/tests/Integration/Domain/Repository/Fixtures/MessageFixture.php index 59f4b25f..63e1d6ec 100644 --- a/tests/Integration/Domain/Repository/Fixtures/MessageFixture.php +++ b/tests/Integration/Domain/Repository/Fixtures/MessageFixture.php @@ -48,11 +48,11 @@ public function load(ObjectManager $manager): void $format = new MessageFormat( $row['htmlformatted'], $row['sendformat'], - $row['astext'], - $row['ashtml'], - $row['aspdf'], - $row['astextandhtml'], - $row['astextandpdf'] + (bool)$row['astext'], + (bool)$row['ashtml'], + (bool)$row['aspdf'], + (bool)$row['astextandhtml'], + (bool)$row['astextandpdf'] ); $schedule = new MessageSchedule( From ef70b5fcbdc81c3bcfabd75be0006cf3d5ae82aa Mon Sep 17 00:00:00 2001 From: Tatevik Date: Thu, 17 Apr 2025 10:55:10 +0400 Subject: [PATCH 11/30] ISSUE-345: relation to template in message --- src/Domain/Model/Messaging/Message.php | 13 +++++- .../Model/Messaging/Message/MessageFormat.php | 40 +++++++++++-------- .../Messaging/Message/MessageMetadata.php | 24 ++++++----- .../Messaging/Message/MessageOptions.php | 10 ----- src/Domain/Model/Messaging/Template.php | 13 +++--- .../Repository/Fixtures/MessageFixture.php | 19 +++++---- .../Messaging/MessageRepositoryTest.php | 10 ++--- .../Domain/Model/Messaging/MessageTest.php | 2 +- 8 files changed, 74 insertions(+), 57 deletions(-) diff --git a/src/Domain/Model/Messaging/Message.php b/src/Domain/Model/Messaging/Message.php index 53e33356..7bb324dc 100644 --- a/src/Domain/Model/Messaging/Message.php +++ b/src/Domain/Model/Messaging/Message.php @@ -49,13 +49,18 @@ class Message implements DomainModel, Identity, ModificationDate #[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 = null + ?Administrator $owner, + ?Template $template = null, ) { $this->format = $format; $this->schedule = $schedule; @@ -64,6 +69,7 @@ public function __construct( $this->options = $options; $this->uuid = bin2hex(random_bytes(18)); $this->owner = $owner; + $this->template = $template; } public function getFormat(): MessageFormat @@ -100,4 +106,9 @@ public function getOwner(): ?Administrator { return $this->owner; } + + public function getTemplate(): ?Template + { + return $this->template; + } } diff --git a/src/Domain/Model/Messaging/Message/MessageFormat.php b/src/Domain/Model/Messaging/Message/MessageFormat.php index d344642a..b0ce77c6 100644 --- a/src/Domain/Model/Messaging/Message/MessageFormat.php +++ b/src/Domain/Model/Messaging/Message/MessageFormat.php @@ -5,6 +5,7 @@ namespace PhpList\Core\Domain\Model\Messaging\Message; use Doctrine\ORM\Mapping as ORM; +use InvalidArgumentException; #[ORM\Embeddable] class MessageFormat @@ -16,36 +17,43 @@ class MessageFormat private ?string $sendFormat = null; #[ORM\Column(name: 'astext', type: 'integer', options: ['default' => 0])] - private bool $asText; + private bool $asText = false; #[ORM\Column(name: 'ashtml', type: 'integer', options: ['default' => 0])] - private bool $asHtml; + private bool $asHtml = false; #[ORM\Column(name: 'aspdf', type: 'integer', options: ['default' => 0])] - private bool $asPdf; + private bool $asPdf = false; #[ORM\Column(name: 'astextandhtml', type: 'integer', options: ['default' => 0])] - private bool $asTextAndHtml; + private bool $asTextAndHtml = false; #[ORM\Column(name: 'astextandpdf', type: 'integer', options: ['default' => 0])] - private bool $asTextAndPdf; + private bool $asTextAndPdf = false; + + public const FORMAT_TEXT = 'text'; + public const FORMAT_HTML = 'html'; + public const FORMAT_PDF = 'pdf'; public function __construct( bool $htmlFormatted, - string $sendFormat = null, - bool $asText = false, - bool $asHtml = false, - bool $asPdf = false, - bool $asTextAndHtml = false, - bool $asTextAndPdf = false, + ?string $sendFormat, + array $formatOptions = [] ) { $this->htmlFormatted = $htmlFormatted; $this->sendFormat = $sendFormat; - $this->asText = $asText; - $this->asHtml = $asHtml; - $this->asPdf = $asPdf; - $this->asTextAndHtml = $asTextAndHtml; - $this->asTextAndPdf = $asTextAndPdf; + + 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; } public function isHtmlFormatted(): bool diff --git a/src/Domain/Model/Messaging/Message/MessageMetadata.php b/src/Domain/Model/Messaging/Message/MessageMetadata.php index 6e2a52e0..8e125a2c 100644 --- a/src/Domain/Model/Messaging/Message/MessageMetadata.php +++ b/src/Domain/Model/Messaging/Message/MessageMetadata.php @@ -13,11 +13,11 @@ class MessageMetadata #[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; @@ -30,15 +30,13 @@ class MessageMetadata public function __construct( ?string $status = null, - int $processed = 0, - int $viewed = 0, int $bounceCount = 0, ?DateTime $entered = null, ?DateTime $sent = 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; @@ -49,18 +47,24 @@ public function getStatus(): ?string return $this->status; } - public function getProcessed(): int + 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; } diff --git a/src/Domain/Model/Messaging/Message/MessageOptions.php b/src/Domain/Model/Messaging/Message/MessageOptions.php index febb04d8..806c4419 100644 --- a/src/Domain/Model/Messaging/Message/MessageOptions.php +++ b/src/Domain/Model/Messaging/Message/MessageOptions.php @@ -25,9 +25,6 @@ class MessageOptions #[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; @@ -40,7 +37,6 @@ public function __construct( string $replyTo = '', ?DateTime $embargo = null, ?string $userSelection = null, - ?int $template = null, ?DateTime $sendStart = null, ?string $rssTemplate = null ) { @@ -49,7 +45,6 @@ public function __construct( $this->replyTo = $replyTo; $this->embargo = $embargo; $this->userSelection = $userSelection; - $this->template = $template; $this->sendStart = $sendStart; $this->rssTemplate = $rssTemplate; } @@ -79,11 +74,6 @@ public function getUserSelection(): ?string return $this->userSelection; } - public function getTemplate(): ?int - { - return $this->template; - } - public function getSendStart(): ?DateTime { return $this->sendStart; diff --git a/src/Domain/Model/Messaging/Template.php b/src/Domain/Model/Messaging/Template.php index 3236f64c..10f0395c 100644 --- a/src/Domain/Model/Messaging/Template.php +++ b/src/Domain/Model/Messaging/Template.php @@ -22,10 +22,10 @@ class Template implements DomainModel, Identity private string $title; #[ORM\Column(name: 'template', type: 'blob', nullable: true)] - private ?string $template = null; + private mixed $template; #[ORM\Column(name: 'template_text', type: 'blob', nullable: true)] - private ?string $templateText = null; + private mixed $templateText; #[ORM\Column(name: 'listorder', type: 'integer', nullable: true)] private ?int $listOrder = null; @@ -50,12 +50,12 @@ public function getTitle(): string public function getTemplate(): ?string { - return $this->template; + return is_resource($this->template) ? stream_get_contents($this->template) : $this->template; } public function getTemplateText(): ?string { - return $this->templateText; + return is_resource($this->templateText) ? stream_get_contents($this->templateText) : $this->templateText; } public function getListOrder(): ?int @@ -76,13 +76,14 @@ public function setTitle(string $title): self public function setTemplate(?string $template): self { - $this->template = $template; + $this->template = $template !== null ? fopen('data://text/plain,' . $template, 'r') : null; return $this; } + public function setTemplateText(?string $templateText): self { - $this->templateText = $templateText; + $this->templateText = $templateText !== null ? fopen('data://text/plain,' . $templateText, 'r') : null; return $this; } diff --git a/tests/Integration/Domain/Repository/Fixtures/MessageFixture.php b/tests/Integration/Domain/Repository/Fixtures/MessageFixture.php index 63e1d6ec..6ce2317f 100644 --- a/tests/Integration/Domain/Repository/Fixtures/MessageFixture.php +++ b/tests/Integration/Domain/Repository/Fixtures/MessageFixture.php @@ -14,6 +14,7 @@ use PhpList\Core\Domain\Model\Messaging\Message\MessageMetadata; use PhpList\Core\Domain\Model\Messaging\Message\MessageOptions; use PhpList\Core\Domain\Model\Messaging\Message\MessageSchedule; +use PhpList\Core\Domain\Model\Messaging\Template; use PhpList\Core\TestingSupport\Traits\ModelTestTrait; use RuntimeException; @@ -36,6 +37,7 @@ public function load(ObjectManager $manager): void $headers = fgetcsv($handle); $adminRepository = $manager->getRepository(Administrator::class); + $templateRepository = $manager->getRepository(Template::class); do { $data = fgetcsv($handle); @@ -44,15 +46,16 @@ public function load(ObjectManager $manager): void } $row = array_combine($headers, $data); $admin = $adminRepository->find($row['owner']); + $template = $templateRepository->find($row['template']); $format = new MessageFormat( $row['htmlformatted'], $row['sendformat'], - (bool)$row['astext'], - (bool)$row['ashtml'], - (bool)$row['aspdf'], - (bool)$row['astextandhtml'], - (bool)$row['astextandpdf'] + array_keys(array_filter([ + MessageFormat::FORMAT_TEXT => $row['astext'], + MessageFormat::FORMAT_HTML => $row['ashtml'], + MessageFormat::FORMAT_PDF => $row['aspdf'], + ])) ); $schedule = new MessageSchedule( @@ -63,12 +66,12 @@ public function load(ObjectManager $manager): void ); $metadata = new MessageMetadata( $row['status'], - $row['processed'], - $row['viewed'], $row['bouncecount'], $row['entered'], $row['sent'] ); + $metadata->setProcessed((bool) $row['processed']); + $metadata->setViews($row['viewed']); $content = new MessageContent( $row['subject'], $row['message'], @@ -81,7 +84,6 @@ public function load(ObjectManager $manager): void $row['replyto'], $row['embargo'], $row['userselection'], - $row['template'], $row['sendstart'], $row['rsstemplate'], ); @@ -93,6 +95,7 @@ public function load(ObjectManager $manager): void $content, $options, $admin, + $template, ); $this->setSubjectId($message, (int)$row['id']); $this->setSubjectProperty($message, 'uuid', $row['uuid']); diff --git a/tests/Integration/Domain/Repository/Messaging/MessageRepositoryTest.php b/tests/Integration/Domain/Repository/Messaging/MessageRepositoryTest.php index e5f6187f..45c4cf8a 100644 --- a/tests/Integration/Domain/Repository/Messaging/MessageRepositoryTest.php +++ b/tests/Integration/Domain/Repository/Messaging/MessageRepositoryTest.php @@ -46,7 +46,7 @@ public function testMessageIsPersistedAndFetchedCorrectly(): void $this->entityManager->persist($admin); $message = new Message( - new MessageFormat(true), + new MessageFormat(true, 'text'), new MessageSchedule(1, null, 3, null), new MessageMetadata('done'), new MessageContent('Hello world!'), @@ -75,7 +75,7 @@ public function testGetByOwnerIdReturnsOnlyOwnedMessages(): void $this->entityManager->persist($admin2); $msg1 = new Message( - new MessageFormat(true), + new MessageFormat(true, MessageFormat::FORMAT_TEXT), new MessageSchedule(1, null, 3, null), new MessageMetadata('done'), new MessageContent('Owned by Admin 1!'), @@ -84,7 +84,7 @@ public function testGetByOwnerIdReturnsOnlyOwnedMessages(): void ); $msg2 = new Message( - new MessageFormat(true), + new MessageFormat(true, MessageFormat::FORMAT_TEXT), new MessageSchedule(1, null, 3, null), new MessageMetadata(null), new MessageContent('Owned by Admin 2!'), @@ -93,7 +93,7 @@ public function testGetByOwnerIdReturnsOnlyOwnedMessages(): void ); $msg3 = new Message( - new MessageFormat(true), + new MessageFormat(true, MessageFormat::FORMAT_TEXT), new MessageSchedule(1, null, 3, null), new MessageMetadata(null), new MessageContent('Hello world!'), @@ -118,7 +118,7 @@ public function testMessageTimestampsAreSetOnPersist(): void $expectedDate = new DateTime(); $message = new Message( - new MessageFormat(true), + new MessageFormat(true, MessageFormat::FORMAT_TEXT), new MessageSchedule(1, null, 3, null), new MessageMetadata(null), new MessageContent('Hello world!'), diff --git a/tests/Unit/Domain/Model/Messaging/MessageTest.php b/tests/Unit/Domain/Model/Messaging/MessageTest.php index 4b7378f5..70c89162 100644 --- a/tests/Unit/Domain/Model/Messaging/MessageTest.php +++ b/tests/Unit/Domain/Model/Messaging/MessageTest.php @@ -29,7 +29,7 @@ class MessageTest extends TestCase protected function setUp(): void { - $this->format = new MessageFormat(true); + $this->format = new MessageFormat(true, MessageFormat::FORMAT_TEXT); $this->schedule = new MessageSchedule(1, new DateTime(), 2, new DateTime()); $this->metadata = new MessageMetadata(); $this->content = new MessageContent('This is the body'); From 89044e3127b6f5f657d5ae8104312d09e154a63c Mon Sep 17 00:00:00 2001 From: Tatevik Date: Thu, 17 Apr 2025 13:15:22 +0400 Subject: [PATCH 12/30] ISSUE-345: update runner --- .github/workflows/ci.yml | 2 +- .github/workflows/core-docs.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f17df61b..351ac54e 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 a88fa4fe..dc3a5bdf 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 From eb6c91b6b5ecfa01ce8079414a2dd9385b213dd0 Mon Sep 17 00:00:00 2001 From: Tatevik Date: Sat, 19 Apr 2025 16:41:25 +0400 Subject: [PATCH 13/30] ISSUE-345: template repo --- src/Domain/Model/Messaging/Template.php | 3 ++- .../Repository/Messaging/TemplateRepository.php | 11 +++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 src/Domain/Repository/Messaging/TemplateRepository.php diff --git a/src/Domain/Model/Messaging/Template.php b/src/Domain/Model/Messaging/Template.php index 10f0395c..ddf2282d 100644 --- a/src/Domain/Model/Messaging/Template.php +++ b/src/Domain/Model/Messaging/Template.php @@ -10,8 +10,9 @@ 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 diff --git a/src/Domain/Repository/Messaging/TemplateRepository.php b/src/Domain/Repository/Messaging/TemplateRepository.php new file mode 100644 index 00000000..b169f129 --- /dev/null +++ b/src/Domain/Repository/Messaging/TemplateRepository.php @@ -0,0 +1,11 @@ + Date: Sat, 19 Apr 2025 16:54:26 +0400 Subject: [PATCH 14/30] ISSUE-345: move to dirs --- src/Domain/Model/Messaging/Template.php | 3 ++- .../Repository/Fixtures/{ => Identity}/Administrator.csv | 0 .../Fixtures/{ => Identity}/AdministratorFixture.php | 2 +- .../AdministratorTokenWithAdministrator.csv | 0 .../AdministratorTokenWithAdministratorFixture.php | 2 +- .../{ => Identity}/DetachedAdministratorTokenFixture.php | 2 +- .../{ => Identity}/DetachedAdministratorTokens.csv | 0 .../Repository/Fixtures/{ => Messaging}/Message.csv | 0 .../Fixtures/{ => Messaging}/MessageFixture.php | 2 +- .../Repository/Fixtures/{ => Subscription}/Subscriber.csv | 0 .../Fixtures/{ => Subscription}/SubscriberFixture.php | 2 +- .../Fixtures/{ => Subscription}/SubscriberList.csv | 0 .../Fixtures/{ => Subscription}/SubscriberListFixture.php | 2 +- .../Fixtures/{ => Subscription}/Subscription.csv | 0 .../Fixtures/{ => Subscription}/SubscriptionFixture.php | 2 +- .../Repository/Identity/AdministratorRepositoryTest.php | 2 +- .../Identity/AdministratorTokenRepositoryTest.php | 6 ++---- .../Repository/Messaging/SubscriberListRepositoryTest.php | 8 ++++---- .../Repository/Subscription/SubscriberRepositoryTest.php | 8 ++++---- .../Subscription/SubscriptionRepositoryTest.php | 6 +++--- tests/Integration/Security/AuthenticationTest.php | 4 ++-- 21 files changed, 25 insertions(+), 26 deletions(-) rename tests/Integration/Domain/Repository/Fixtures/{ => Identity}/Administrator.csv (100%) rename tests/Integration/Domain/Repository/Fixtures/{ => Identity}/AdministratorFixture.php (99%) rename tests/Integration/Domain/Repository/Fixtures/{ => Identity}/AdministratorTokenWithAdministrator.csv (100%) rename tests/Integration/Domain/Repository/Fixtures/{ => Identity}/AdministratorTokenWithAdministratorFixture.php (99%) rename tests/Integration/Domain/Repository/Fixtures/{ => Identity}/DetachedAdministratorTokenFixture.php (99%) rename tests/Integration/Domain/Repository/Fixtures/{ => Identity}/DetachedAdministratorTokens.csv (100%) rename tests/Integration/Domain/Repository/Fixtures/{ => Messaging}/Message.csv (100%) rename tests/Integration/Domain/Repository/Fixtures/{ => Messaging}/MessageFixture.php (99%) rename tests/Integration/Domain/Repository/Fixtures/{ => Subscription}/Subscriber.csv (100%) rename tests/Integration/Domain/Repository/Fixtures/{ => Subscription}/SubscriberFixture.php (99%) rename tests/Integration/Domain/Repository/Fixtures/{ => Subscription}/SubscriberList.csv (100%) rename tests/Integration/Domain/Repository/Fixtures/{ => Subscription}/SubscriberListFixture.php (99%) rename tests/Integration/Domain/Repository/Fixtures/{ => Subscription}/Subscription.csv (100%) rename tests/Integration/Domain/Repository/Fixtures/{ => Subscription}/SubscriptionFixture.php (99%) diff --git a/src/Domain/Model/Messaging/Template.php b/src/Domain/Model/Messaging/Template.php index ddf2282d..6b276fa4 100644 --- a/src/Domain/Model/Messaging/Template.php +++ b/src/Domain/Model/Messaging/Template.php @@ -39,8 +39,9 @@ class Template implements DomainModel, Identity )] private Collection $images; - public function __construct() + public function __construct(string $title) { + $this->title = $title; $this->images = new ArrayCollection(); } 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 99% rename from tests/Integration/Domain/Repository/Fixtures/AdministratorFixture.php rename to tests/Integration/Domain/Repository/Fixtures/Identity/AdministratorFixture.php index 30905f29..c94bba86 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; 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 99% rename from tests/Integration/Domain/Repository/Fixtures/AdministratorTokenWithAdministratorFixture.php rename to tests/Integration/Domain/Repository/Fixtures/Identity/AdministratorTokenWithAdministratorFixture.php index 1d1ac74c..73a1bb5a 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; diff --git a/tests/Integration/Domain/Repository/Fixtures/DetachedAdministratorTokenFixture.php b/tests/Integration/Domain/Repository/Fixtures/Identity/DetachedAdministratorTokenFixture.php similarity index 99% rename from tests/Integration/Domain/Repository/Fixtures/DetachedAdministratorTokenFixture.php rename to tests/Integration/Domain/Repository/Fixtures/Identity/DetachedAdministratorTokenFixture.php index 15f5d2a7..0935dfea 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; 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/Message.csv b/tests/Integration/Domain/Repository/Fixtures/Messaging/Message.csv similarity index 100% rename from tests/Integration/Domain/Repository/Fixtures/Message.csv rename to tests/Integration/Domain/Repository/Fixtures/Messaging/Message.csv diff --git a/tests/Integration/Domain/Repository/Fixtures/MessageFixture.php b/tests/Integration/Domain/Repository/Fixtures/Messaging/MessageFixture.php similarity index 99% rename from tests/Integration/Domain/Repository/Fixtures/MessageFixture.php rename to tests/Integration/Domain/Repository/Fixtures/Messaging/MessageFixture.php index 6ce2317f..539e6eb4 100644 --- a/tests/Integration/Domain/Repository/Fixtures/MessageFixture.php +++ b/tests/Integration/Domain/Repository/Fixtures/Messaging/MessageFixture.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\Messaging; use DateTime; use Doctrine\Bundle\FixturesBundle\Fixture; 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 99% rename from tests/Integration/Domain/Repository/Fixtures/SubscriberFixture.php rename to tests/Integration/Domain/Repository/Fixtures/Subscription/SubscriberFixture.php index 9a4ce782..36b69516 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; 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 99% rename from tests/Integration/Domain/Repository/Fixtures/SubscriberListFixture.php rename to tests/Integration/Domain/Repository/Fixtures/Subscription/SubscriberListFixture.php index d95f759d..5b9ff102 100644 --- a/tests/Integration/Domain/Repository/Fixtures/SubscriberListFixture.php +++ b/tests/Integration/Domain/Repository/Fixtures/Subscription/SubscriberListFixture.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; 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 99% rename from tests/Integration/Domain/Repository/Fixtures/SubscriptionFixture.php rename to tests/Integration/Domain/Repository/Fixtures/Subscription/SubscriptionFixture.php index 9fc192d7..e75b4e30 100644 --- a/tests/Integration/Domain/Repository/Fixtures/SubscriptionFixture.php +++ b/tests/Integration/Domain/Repository/Fixtures/Subscription/SubscriptionFixture.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; diff --git a/tests/Integration/Domain/Repository/Identity/AdministratorRepositoryTest.php b/tests/Integration/Domain/Repository/Identity/AdministratorRepositoryTest.php index 2f74bcf3..f69a63e3 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; /** diff --git a/tests/Integration/Domain/Repository/Identity/AdministratorTokenRepositoryTest.php b/tests/Integration/Domain/Repository/Identity/AdministratorTokenRepositoryTest.php index e6b9ba35..23c9e8d5 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; /** diff --git a/tests/Integration/Domain/Repository/Messaging/SubscriberListRepositoryTest.php b/tests/Integration/Domain/Repository/Messaging/SubscriberListRepositoryTest.php index 06f74183..97c948a7 100644 --- a/tests/Integration/Domain/Repository/Messaging/SubscriberListRepositoryTest.php +++ b/tests/Integration/Domain/Repository/Messaging/SubscriberListRepositoryTest.php @@ -15,10 +15,10 @@ 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; /** diff --git a/tests/Integration/Domain/Repository/Subscription/SubscriberRepositoryTest.php b/tests/Integration/Domain/Repository/Subscription/SubscriberRepositoryTest.php index ef162e16..f8098e88 100644 --- a/tests/Integration/Domain/Repository/Subscription/SubscriberRepositoryTest.php +++ b/tests/Integration/Domain/Repository/Subscription/SubscriberRepositoryTest.php @@ -15,10 +15,10 @@ 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; /** diff --git a/tests/Integration/Domain/Repository/Subscription/SubscriptionRepositoryTest.php b/tests/Integration/Domain/Repository/Subscription/SubscriptionRepositoryTest.php index 4b50eedc..c36399e9 100644 --- a/tests/Integration/Domain/Repository/Subscription/SubscriptionRepositoryTest.php +++ b/tests/Integration/Domain/Repository/Subscription/SubscriptionRepositoryTest.php @@ -14,9 +14,9 @@ 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; /** diff --git a/tests/Integration/Security/AuthenticationTest.php b/tests/Integration/Security/AuthenticationTest.php index dfb55089..a46a6d93 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; From fba5aa99fd4b659d3fde3e26f54e61cf957b7a58 Mon Sep 17 00:00:00 2001 From: Tatevik Date: Sat, 19 Apr 2025 17:14:01 +0400 Subject: [PATCH 15/30] ISSUE-345: add test + fix template --- config/repositories.yml | 5 ++ src/Domain/Model/Messaging/Template.php | 14 +++- .../Fixtures/Messaging/Template.csv | 2 + .../Fixtures/Messaging/TemplateFixture.php | 50 +++++++++++++ .../Messaging/TemplateRepositoryTest.php | 73 +++++++++++++++++++ 5 files changed, 142 insertions(+), 2 deletions(-) create mode 100644 tests/Integration/Domain/Repository/Fixtures/Messaging/Template.csv create mode 100644 tests/Integration/Domain/Repository/Fixtures/Messaging/TemplateFixture.php create mode 100644 tests/Integration/Domain/Repository/Messaging/TemplateRepositoryTest.php diff --git a/config/repositories.yml b/config/repositories.yml index 198a6cd2..e273225b 100644 --- a/config/repositories.yml +++ b/config/repositories.yml @@ -30,3 +30,8 @@ services: 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 diff --git a/src/Domain/Model/Messaging/Template.php b/src/Domain/Model/Messaging/Template.php index 6b276fa4..48a8010b 100644 --- a/src/Domain/Model/Messaging/Template.php +++ b/src/Domain/Model/Messaging/Template.php @@ -52,12 +52,22 @@ public function getTitle(): string public function getTemplate(): ?string { - return is_resource($this->template) ? stream_get_contents($this->template) : $this->template; + if (is_resource($this->template)) { + rewind($this->template); + return stream_get_contents($this->template); + } + + return $this->template; } public function getTemplateText(): ?string { - return is_resource($this->templateText) ? stream_get_contents($this->templateText) : $this->templateText; + if (is_resource($this->templateText)) { + rewind($this->templateText); + return stream_get_contents($this->templateText); + } + + return $this->templateText; } public function getListOrder(): ?int 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 00000000..65872d62 --- /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 00000000..b707a7db --- /dev/null +++ b/tests/Integration/Domain/Repository/Fixtures/Messaging/TemplateFixture.php @@ -0,0 +1,50 @@ +setTemplate($row['template']); + $template->setTemplateText($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/Messaging/TemplateRepositoryTest.php b/tests/Integration/Domain/Repository/Messaging/TemplateRepositoryTest.php new file mode 100644 index 00000000..b729c359 --- /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->getTemplate()); + self::assertSame('', $fetched->getTemplateText()); + 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); + } +} From be0c5d92edc638a0120749f406772581a43c5e4d Mon Sep 17 00:00:00 2001 From: Tatevik Date: Sat, 19 Apr 2025 19:17:15 +0400 Subject: [PATCH 16/30] ISSUE-345: message setters --- src/Domain/Model/Messaging/Message.php | 6 ++ .../Messaging/Message/MessageContent.php | 12 ++++ .../Model/Messaging/Message/MessageFormat.php | 68 ++++++++----------- .../Messaging/Message/MessageMetadata.php | 24 +++++++ .../Messaging/Message/MessageOptions.php | 46 ++++++++++--- .../Messaging/Message/MessageSchedule.php | 42 +++++++++++- .../Fixtures/Messaging/MessageFixture.php | 4 +- .../Messaging/MessageRepositoryTest.php | 10 +-- .../Domain/Model/Messaging/MessageTest.php | 2 +- 9 files changed, 157 insertions(+), 57 deletions(-) diff --git a/src/Domain/Model/Messaging/Message.php b/src/Domain/Model/Messaging/Message.php index 7bb324dc..08d8c1fc 100644 --- a/src/Domain/Model/Messaging/Message.php +++ b/src/Domain/Model/Messaging/Message.php @@ -107,6 +107,12 @@ 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; diff --git a/src/Domain/Model/Messaging/Message/MessageContent.php b/src/Domain/Model/Messaging/Message/MessageContent.php index 7bf80b52..5037aebb 100644 --- a/src/Domain/Model/Messaging/Message/MessageContent.php +++ b/src/Domain/Model/Messaging/Message/MessageContent.php @@ -60,8 +60,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 b0ce77c6..57f19eb8 100644 --- a/src/Domain/Model/Messaging/Message/MessageFormat.php +++ b/src/Domain/Model/Messaging/Message/MessageFormat.php @@ -43,17 +43,7 @@ public function __construct( $this->htmlFormatted = $htmlFormatted; $this->sendFormat = $sendFormat; - 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; + $this->setFormatOptions($formatOptions); } public function isHtmlFormatted(): bool @@ -61,11 +51,23 @@ 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 setSendFormat(?string $sendFormat): self + { + $this->sendFormat = $sendFormat; + return $this; + } + public function isAsText(): bool { return $this->asText; @@ -91,39 +93,29 @@ public function isAsTextAndPdf(): bool return $this->asTextAndPdf; } - public function setSendFormat(?string $sendFormat): self + public function getFormatOptions(): array { - $this->sendFormat = $sendFormat; - return $this; + 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 setAsText(bool $asText): self + public function setFormatOptions(array $formatOptions): self { - $this->asText = $asText; - return $this; - } - - public function setAsHtml(bool $asHtml): self - { - $this->asHtml = $asHtml; - return $this; - } - - public function setAsPdf(bool $asPdf): self - { - $this->asPdf = $asPdf; - return $this; - } + 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) + }; + } - public function setAsTextAndHtml(bool $asTextAndHtml): self - { - $this->asTextAndHtml = $asTextAndHtml; - return $this; - } + $this->asTextAndHtml = $this->asText && $this->asHtml; + $this->asTextAndPdf = $this->asText && $this->asPdf; - public function setAsTextAndPdf(bool $asTextAndPdf): self - { - $this->asTextAndPdf = $asTextAndPdf; return $this; } } diff --git a/src/Domain/Model/Messaging/Message/MessageMetadata.php b/src/Domain/Model/Messaging/Message/MessageMetadata.php index 8e125a2c..bf125214 100644 --- a/src/Domain/Model/Messaging/Message/MessageMetadata.php +++ b/src/Domain/Model/Messaging/Message/MessageMetadata.php @@ -47,6 +47,12 @@ public function getStatus(): ?string return $this->status; } + public function setStatus(string $status): self + { + $this->status = $status; + return $this; + } + public function isProcessed(): bool { return $this->processed; @@ -83,4 +89,22 @@ 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; + } } diff --git a/src/Domain/Model/Messaging/Message/MessageOptions.php b/src/Domain/Model/Messaging/Message/MessageOptions.php index 806c4419..b6692b7f 100644 --- a/src/Domain/Model/Messaging/Message/MessageOptions.php +++ b/src/Domain/Model/Messaging/Message/MessageOptions.php @@ -19,9 +19,6 @@ 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; @@ -35,7 +32,6 @@ public function __construct( string $fromField = '', string $toField = '', string $replyTo = '', - ?DateTime $embargo = null, ?string $userSelection = null, ?DateTime $sendStart = null, ?string $rssTemplate = null @@ -43,7 +39,6 @@ public function __construct( $this->fromField = $fromField; $this->toField = $toField; $this->replyTo = $replyTo; - $this->embargo = $embargo; $this->userSelection = $userSelection; $this->sendStart = $sendStart; $this->rssTemplate = $rssTemplate; @@ -64,11 +59,6 @@ public function getReplyTo(): string return $this->replyTo; } - public function getEmbargo(): ?DateTime - { - return $this->embargo; - } - public function getUserSelection(): ?string { return $this->userSelection; @@ -83,4 +73,40 @@ public function getRssTemplate(): ?string { return $this->rssTemplate; } + + public function setFromField(string $fromField): self + { + $this->fromField = $fromField; + return $this; + } + + public function setToField(string $toField): self + { + $this->toField = $toField; + return $this; + } + + public function setReplyTo(string $replyTo): self + { + $this->replyTo = $replyTo; + return $this; + } + + public function setUserSelection(?string $userSelection): self + { + $this->userSelection = $userSelection; + return $this; + } + + public function setSendStart(?DateTime $sendStart): self + { + $this->sendStart = $sendStart; + 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 28b82c41..74782d7a 100644 --- a/src/Domain/Model/Messaging/Message/MessageSchedule.php +++ b/src/Domain/Model/Messaging/Message/MessageSchedule.php @@ -22,16 +22,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 +58,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/tests/Integration/Domain/Repository/Fixtures/Messaging/MessageFixture.php b/tests/Integration/Domain/Repository/Fixtures/Messaging/MessageFixture.php index 539e6eb4..24c041b4 100644 --- a/tests/Integration/Domain/Repository/Fixtures/Messaging/MessageFixture.php +++ b/tests/Integration/Domain/Repository/Fixtures/Messaging/MessageFixture.php @@ -62,7 +62,8 @@ public function load(ObjectManager $manager): void $row['repeatinterval'], $row['repeatuntil'], $row['requeueinterval'], - $row['requeueuntil'] + $row['requeueuntil'], + $row['embargo'], ); $metadata = new MessageMetadata( $row['status'], @@ -82,7 +83,6 @@ public function load(ObjectManager $manager): void $row['fromfield'], $row['tofield'], $row['replyto'], - $row['embargo'], $row['userselection'], $row['sendstart'], $row['rsstemplate'], diff --git a/tests/Integration/Domain/Repository/Messaging/MessageRepositoryTest.php b/tests/Integration/Domain/Repository/Messaging/MessageRepositoryTest.php index 45c4cf8a..a30c9e6d 100644 --- a/tests/Integration/Domain/Repository/Messaging/MessageRepositoryTest.php +++ b/tests/Integration/Domain/Repository/Messaging/MessageRepositoryTest.php @@ -47,7 +47,7 @@ public function testMessageIsPersistedAndFetchedCorrectly(): void $message = new Message( new MessageFormat(true, 'text'), - new MessageSchedule(1, null, 3, null), + new MessageSchedule(1, null, 3, null, null), new MessageMetadata('done'), new MessageContent('Hello world!'), new MessageOptions(), @@ -76,7 +76,7 @@ public function testGetByOwnerIdReturnsOnlyOwnedMessages(): void $msg1 = new Message( new MessageFormat(true, MessageFormat::FORMAT_TEXT), - new MessageSchedule(1, null, 3, null), + new MessageSchedule(1, null, 3, null, null), new MessageMetadata('done'), new MessageContent('Owned by Admin 1!'), new MessageOptions(), @@ -85,7 +85,7 @@ public function testGetByOwnerIdReturnsOnlyOwnedMessages(): void $msg2 = new Message( new MessageFormat(true, MessageFormat::FORMAT_TEXT), - new MessageSchedule(1, null, 3, null), + new MessageSchedule(1, null, 3, null, null), new MessageMetadata(null), new MessageContent('Owned by Admin 2!'), new MessageOptions(), @@ -94,7 +94,7 @@ public function testGetByOwnerIdReturnsOnlyOwnedMessages(): void $msg3 = new Message( new MessageFormat(true, MessageFormat::FORMAT_TEXT), - new MessageSchedule(1, null, 3, null), + new MessageSchedule(1, null, 3, null, null), new MessageMetadata(null), new MessageContent('Hello world!'), new MessageOptions(), @@ -119,7 +119,7 @@ public function testMessageTimestampsAreSetOnPersist(): void $message = new Message( new MessageFormat(true, MessageFormat::FORMAT_TEXT), - new MessageSchedule(1, null, 3, null), + new MessageSchedule(1, null, 3, null, null), new MessageMetadata(null), new MessageContent('Hello world!'), new MessageOptions(), diff --git a/tests/Unit/Domain/Model/Messaging/MessageTest.php b/tests/Unit/Domain/Model/Messaging/MessageTest.php index 70c89162..92ec6245 100644 --- a/tests/Unit/Domain/Model/Messaging/MessageTest.php +++ b/tests/Unit/Domain/Model/Messaging/MessageTest.php @@ -30,7 +30,7 @@ class MessageTest extends TestCase protected function setUp(): void { $this->format = new MessageFormat(true, MessageFormat::FORMAT_TEXT); - $this->schedule = new MessageSchedule(1, new DateTime(), 2, new DateTime()); + $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(); From 6d68353e9893fde5627bff3c1b535d0656a9e4de Mon Sep 17 00:00:00 2001 From: Tatevik Date: Sat, 19 Apr 2025 22:02:10 +0400 Subject: [PATCH 17/30] ISSUE-345: tests --- .../Fixtures/Messaging/MessageFixture.php | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/tests/Integration/Domain/Repository/Fixtures/Messaging/MessageFixture.php b/tests/Integration/Domain/Repository/Fixtures/Messaging/MessageFixture.php index 24c041b4..1cad56bc 100644 --- a/tests/Integration/Domain/Repository/Fixtures/Messaging/MessageFixture.php +++ b/tests/Integration/Domain/Repository/Fixtures/Messaging/MessageFixture.php @@ -49,7 +49,7 @@ public function load(ObjectManager $manager): void $template = $templateRepository->find($row['template']); $format = new MessageFormat( - $row['htmlformatted'], + (bool)$row['htmlformatted'], $row['sendformat'], array_keys(array_filter([ MessageFormat::FORMAT_TEXT => $row['astext'], @@ -59,17 +59,17 @@ public function load(ObjectManager $manager): void ); $schedule = new MessageSchedule( - $row['repeatinterval'], - $row['repeatuntil'], - $row['requeueinterval'], - $row['requeueuntil'], - $row['embargo'], + (int)$row['repeatinterval'], + new DateTime($row['repeatuntil']), + (int)$row['requeueinterval'], + new DateTime($row['requeueuntil']), + new DateTime($row['embargo']), ); $metadata = new MessageMetadata( $row['status'], - $row['bouncecount'], - $row['entered'], - $row['sent'] + (int)$row['bouncecount'], + new DateTime($row['entered']), + new DateTime($row['sent']) ); $metadata->setProcessed((bool) $row['processed']); $metadata->setViews($row['viewed']); @@ -84,7 +84,7 @@ public function load(ObjectManager $manager): void $row['tofield'], $row['replyto'], $row['userselection'], - $row['sendstart'], + new DateTime($row['sendstart']), $row['rsstemplate'], ); From 4476452815562a1a4866bc8e46dff0689a970b9d Mon Sep 17 00:00:00 2001 From: Tatevik Date: Mon, 21 Apr 2025 22:12:37 +0400 Subject: [PATCH 18/30] ISSUE-345: set message embedded elements --- src/Domain/Model/Messaging/Message.php | 36 ++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/Domain/Model/Messaging/Message.php b/src/Domain/Model/Messaging/Message.php index 08d8c1fc..b4ed60ce 100644 --- a/src/Domain/Model/Messaging/Message.php +++ b/src/Domain/Model/Messaging/Message.php @@ -117,4 +117,40 @@ 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; + } } From b003df674c91fefdb5a4f16d52311d82d78935b0 Mon Sep 17 00:00:00 2001 From: Tatevik Date: Mon, 21 Apr 2025 22:33:01 +0400 Subject: [PATCH 19/30] ISSUE-345: sendstart in metadata --- .../Model/Messaging/Message/MessageMetadata.php | 16 ++++++++++++++++ .../Model/Messaging/Message/MessageOptions.php | 16 ---------------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/Domain/Model/Messaging/Message/MessageMetadata.php b/src/Domain/Model/Messaging/Message/MessageMetadata.php index bf125214..28d61d80 100644 --- a/src/Domain/Model/Messaging/Message/MessageMetadata.php +++ b/src/Domain/Model/Messaging/Message/MessageMetadata.php @@ -28,11 +28,15 @@ 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 $bounceCount = 0, ?DateTime $entered = null, ?DateTime $sent = null, + ?DateTime $sendStart = null, ) { $this->status = $status; $this->processed = false; @@ -40,6 +44,7 @@ public function __construct( $this->bounceCount = $bounceCount; $this->entered = $entered ?? new DateTime(); $this->sent = $sent; + $this->sendStart = $sendStart; } public function getStatus(): ?string @@ -107,4 +112,15 @@ 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 b6692b7f..69d5884d 100644 --- a/src/Domain/Model/Messaging/Message/MessageOptions.php +++ b/src/Domain/Model/Messaging/Message/MessageOptions.php @@ -22,9 +22,6 @@ class MessageOptions #[ORM\Column(name: 'userselection', type: 'text', nullable: true)] private ?string $userSelection; - #[ORM\Column(name: 'sendstart', type: 'datetime', nullable: true)] - private ?DateTime $sendStart; - #[ORM\Column(name: 'rsstemplate', type: 'string', length: 100, nullable: true)] private ?string $rssTemplate; @@ -33,14 +30,12 @@ public function __construct( string $toField = '', string $replyTo = '', ?string $userSelection = null, - ?DateTime $sendStart = null, ?string $rssTemplate = null ) { $this->fromField = $fromField; $this->toField = $toField; $this->replyTo = $replyTo; $this->userSelection = $userSelection; - $this->sendStart = $sendStart; $this->rssTemplate = $rssTemplate; } @@ -64,11 +59,6 @@ public function getUserSelection(): ?string return $this->userSelection; } - public function getSendStart(): ?DateTime - { - return $this->sendStart; - } - public function getRssTemplate(): ?string { return $this->rssTemplate; @@ -98,12 +88,6 @@ public function setUserSelection(?string $userSelection): self return $this; } - public function setSendStart(?DateTime $sendStart): self - { - $this->sendStart = $sendStart; - return $this; - } - public function setRssTemplate(?string $rssTemplate): self { $this->rssTemplate = $rssTemplate; From 5ff1384653b5deef57857437dc3fb13fa4d0b87f Mon Sep 17 00:00:00 2001 From: Tatevik Date: Mon, 21 Apr 2025 22:57:23 +0400 Subject: [PATCH 20/30] ISSUE-345: EmbeddableInterface interface --- src/Domain/Model/Interfaces/EmbeddableInterface.php | 10 ++++++++++ src/Domain/Model/Messaging/Message/MessageContent.php | 3 ++- src/Domain/Model/Messaging/Message/MessageFormat.php | 3 ++- src/Domain/Model/Messaging/Message/MessageMetadata.php | 3 ++- src/Domain/Model/Messaging/Message/MessageOptions.php | 4 ++-- src/Domain/Model/Messaging/Message/MessageSchedule.php | 3 ++- .../Repository/Fixtures/Messaging/MessageFixture.php | 4 ++-- 7 files changed, 22 insertions(+), 8 deletions(-) create mode 100644 src/Domain/Model/Interfaces/EmbeddableInterface.php diff --git a/src/Domain/Model/Interfaces/EmbeddableInterface.php b/src/Domain/Model/Interfaces/EmbeddableInterface.php new file mode 100644 index 00000000..92524b7a --- /dev/null +++ b/src/Domain/Model/Interfaces/EmbeddableInterface.php @@ -0,0 +1,10 @@ + '(no subject)'])] private string $subject; diff --git a/src/Domain/Model/Messaging/Message/MessageFormat.php b/src/Domain/Model/Messaging/Message/MessageFormat.php index 57f19eb8..90fc56f0 100644 --- a/src/Domain/Model/Messaging/Message/MessageFormat.php +++ b/src/Domain/Model/Messaging/Message/MessageFormat.php @@ -6,9 +6,10 @@ 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(name: 'htmlformatted', type: 'boolean', options: ['default' => false])] private bool $htmlFormatted = false; diff --git a/src/Domain/Model/Messaging/Message/MessageMetadata.php b/src/Domain/Model/Messaging/Message/MessageMetadata.php index 28d61d80..3e4452a1 100644 --- a/src/Domain/Model/Messaging/Message/MessageMetadata.php +++ b/src/Domain/Model/Messaging/Message/MessageMetadata.php @@ -6,9 +6,10 @@ 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; diff --git a/src/Domain/Model/Messaging/Message/MessageOptions.php b/src/Domain/Model/Messaging/Message/MessageOptions.php index 69d5884d..002d3c9a 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; diff --git a/src/Domain/Model/Messaging/Message/MessageSchedule.php b/src/Domain/Model/Messaging/Message/MessageSchedule.php index 74782d7a..3448f8d1 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; diff --git a/tests/Integration/Domain/Repository/Fixtures/Messaging/MessageFixture.php b/tests/Integration/Domain/Repository/Fixtures/Messaging/MessageFixture.php index 1cad56bc..705baeb1 100644 --- a/tests/Integration/Domain/Repository/Fixtures/Messaging/MessageFixture.php +++ b/tests/Integration/Domain/Repository/Fixtures/Messaging/MessageFixture.php @@ -69,7 +69,8 @@ public function load(ObjectManager $manager): void $row['status'], (int)$row['bouncecount'], new DateTime($row['entered']), - new DateTime($row['sent']) + new DateTime($row['sent']), + new DateTime($row['sendstart']), ); $metadata->setProcessed((bool) $row['processed']); $metadata->setViews($row['viewed']); @@ -84,7 +85,6 @@ public function load(ObjectManager $manager): void $row['tofield'], $row['replyto'], $row['userselection'], - new DateTime($row['sendstart']), $row['rsstemplate'], ); From 7aa99b2a25434b62a0ccf23e59027b99d679f5a9 Mon Sep 17 00:00:00 2001 From: Tatevik Date: Tue, 22 Apr 2025 20:19:14 +0400 Subject: [PATCH 21/30] ISSUE-345: image data resource fix --- src/Domain/Model/Messaging/TemplateImage.php | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/Domain/Model/Messaging/TemplateImage.php b/src/Domain/Model/Messaging/TemplateImage.php index dd95f89d..f0c48abf 100644 --- a/src/Domain/Model/Messaging/TemplateImage.php +++ b/src/Domain/Model/Messaging/TemplateImage.php @@ -26,7 +26,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; @@ -51,6 +51,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 +89,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; } From 3882b9e782acdb0370e61011992f361dbdbb3128 Mon Sep 17 00:00:00 2001 From: Tatevik Date: Thu, 24 Apr 2025 11:49:18 +0400 Subject: [PATCH 22/30] ISSUE-345: update template property names --- src/Domain/Model/Messaging/Template.php | 32 +++++++++---------- .../Fixtures/Messaging/TemplateFixture.php | 4 +-- .../Messaging/TemplateRepositoryTest.php | 4 +-- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/Domain/Model/Messaging/Template.php b/src/Domain/Model/Messaging/Template.php index 48a8010b..08aed78d 100644 --- a/src/Domain/Model/Messaging/Template.php +++ b/src/Domain/Model/Messaging/Template.php @@ -23,10 +23,10 @@ class Template implements DomainModel, Identity private string $title; #[ORM\Column(name: 'template', type: 'blob', nullable: true)] - private mixed $template; + private mixed $content; #[ORM\Column(name: 'template_text', type: 'blob', nullable: true)] - private mixed $templateText; + private mixed $text; #[ORM\Column(name: 'listorder', type: 'integer', nullable: true)] private ?int $listOrder = null; @@ -50,24 +50,24 @@ public function getTitle(): string return $this->title; } - public function getTemplate(): ?string + public function getContent(): ?string { - if (is_resource($this->template)) { - rewind($this->template); - return stream_get_contents($this->template); + if (is_resource($this->content)) { + rewind($this->content); + return stream_get_contents($this->content); } - return $this->template; + return $this->content; } - public function getTemplateText(): ?string + public function getText(): ?string { - if (is_resource($this->templateText)) { - rewind($this->templateText); - return stream_get_contents($this->templateText); + if (is_resource($this->text)) { + rewind($this->text); + return stream_get_contents($this->text); } - return $this->templateText; + return $this->text; } public function getListOrder(): ?int @@ -86,16 +86,16 @@ public function setTitle(string $title): self return $this; } - public function setTemplate(?string $template): self + public function setContent(?string $content): self { - $this->template = $template !== null ? fopen('data://text/plain,' . $template, 'r') : null; + $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 !== null ? fopen('data://text/plain,' . $templateText, 'r') : null; + $this->text = $text !== null ? fopen('data://text/plain,' . $text, 'r') : null; return $this; } diff --git a/tests/Integration/Domain/Repository/Fixtures/Messaging/TemplateFixture.php b/tests/Integration/Domain/Repository/Fixtures/Messaging/TemplateFixture.php index b707a7db..e5222290 100644 --- a/tests/Integration/Domain/Repository/Fixtures/Messaging/TemplateFixture.php +++ b/tests/Integration/Domain/Repository/Fixtures/Messaging/TemplateFixture.php @@ -37,8 +37,8 @@ public function load(ObjectManager $manager): void $row = array_combine($headers, $data); $template = new Template($row['title']); - $template->setTemplate($row['template']); - $template->setTemplateText($row['template_text']); + $template->setContent($row['template']); + $template->setText($row['template_text']); $template->setListOrder((int)$row['listorder']); $this->setSubjectId($template, (int)$row['id']); diff --git a/tests/Integration/Domain/Repository/Messaging/TemplateRepositoryTest.php b/tests/Integration/Domain/Repository/Messaging/TemplateRepositoryTest.php index b729c359..2d49df1e 100644 --- a/tests/Integration/Domain/Repository/Messaging/TemplateRepositoryTest.php +++ b/tests/Integration/Domain/Repository/Messaging/TemplateRepositoryTest.php @@ -56,8 +56,8 @@ public function testTemplateIsPersistedAndFetchedCorrectly(): void self::assertInstanceOf(Template::class, $fetched); self::assertSame('Newsletter Template', $fetched->getTitle()); - self::assertSame('

Welcome

', $fetched->getTemplate()); - self::assertSame('', $fetched->getTemplateText()); + self::assertSame('

Welcome

', $fetched->getContent()); + self::assertSame('', $fetched->getText()); self::assertSame(1, $fetched->getListOrder()); } From 810f2da120245d76e4ce758abcfe34c8c54dd678 Mon Sep 17 00:00:00 2001 From: Tatevik Date: Thu, 24 Apr 2025 14:50:45 +0400 Subject: [PATCH 23/30] ISSUE-345: TemplateImageRepository --- config/repositories.yml | 5 +++++ src/Domain/Model/Messaging/TemplateImage.php | 3 ++- .../Repository/Messaging/TemplateImageRepository.php | 11 +++++++++++ 3 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 src/Domain/Repository/Messaging/TemplateImageRepository.php diff --git a/config/repositories.yml b/config/repositories.yml index e273225b..2373b0dc 100644 --- a/config/repositories.yml +++ b/config/repositories.yml @@ -35,3 +35,8 @@ services: 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/Messaging/TemplateImage.php b/src/Domain/Model/Messaging/TemplateImage.php index f0c48abf..bf275f32 100644 --- a/src/Domain/Model/Messaging/TemplateImage.php +++ b/src/Domain/Model/Messaging/TemplateImage.php @@ -8,8 +8,9 @@ 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 diff --git a/src/Domain/Repository/Messaging/TemplateImageRepository.php b/src/Domain/Repository/Messaging/TemplateImageRepository.php new file mode 100644 index 00000000..6106bbd1 --- /dev/null +++ b/src/Domain/Repository/Messaging/TemplateImageRepository.php @@ -0,0 +1,11 @@ + Date: Tue, 29 Apr 2025 20:26:35 +0400 Subject: [PATCH 24/30] ISSUE-345: update admin prop name (email) --- src/Domain/Model/Identity/Administrator.php | 12 ++++++------ .../Fixtures/Identity/AdministratorFixture.php | 2 +- .../Identity/AdministratorRepositoryTest.php | 2 +- .../Unit/Domain/Model/Identity/AdministratorTest.php | 6 +++--- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/Domain/Model/Identity/Administrator.php b/src/Domain/Model/Identity/Administrator.php index b02f2a1f..1dd938ad 100644 --- a/src/Domain/Model/Identity/Administrator.php +++ b/src/Domain/Model/Identity/Administrator.php @@ -38,7 +38,7 @@ class Administrator implements DomainModel, Identity, CreationDate, Modification private string $namelc; #[ORM\Column(name: 'email')] - private string $emailAddress; + private string $email; #[ORM\Column(name: 'created', type: 'datetime')] protected ?DateTime $creationDate = null; @@ -69,7 +69,7 @@ public function __construct() $this->loginName = ''; $this->passwordHash = ''; $this->modificationDate = null; - $this->emailAddress = ''; + $this->email = ''; } public function getLoginName(): string @@ -84,14 +84,14 @@ public function setLoginName(string $loginName): self return $this; } - public function getEmailAddress(): string + public function getEmail(): string { - return $this->emailAddress; + return $this->email; } - public function setEmailAddress(string $emailAddress): self + public function setEmail(string $email): self { - $this->emailAddress = $emailAddress; + $this->email = $email; return $this; } diff --git a/tests/Integration/Domain/Repository/Fixtures/Identity/AdministratorFixture.php b/tests/Integration/Domain/Repository/Fixtures/Identity/AdministratorFixture.php index c94bba86..dba893e1 100644 --- a/tests/Integration/Domain/Repository/Fixtures/Identity/AdministratorFixture.php +++ b/tests/Integration/Domain/Repository/Fixtures/Identity/AdministratorFixture.php @@ -39,7 +39,7 @@ 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']); diff --git a/tests/Integration/Domain/Repository/Identity/AdministratorRepositoryTest.php b/tests/Integration/Domain/Repository/Identity/AdministratorRepositoryTest.php index f69a63e3..aca2f26f 100644 --- a/tests/Integration/Domain/Repository/Identity/AdministratorRepositoryTest.php +++ b/tests/Integration/Domain/Repository/Identity/AdministratorRepositoryTest.php @@ -54,7 +54,7 @@ public function testFindReadsModelFromDatabase(): void $actual->getModificationDate()->getTimestamp(), 1 ); - $this->assertSame('john@example.com', $actual->getEmailAddress()); + $this->assertSame('john@example.com', $actual->getEmail()); $this->assertSame( '1491a3c7e7b23b9a6393323babbb095dee0d7d81b2199617b487bd0fb5236f3c', $actual->getPasswordHash() diff --git a/tests/Unit/Domain/Model/Identity/AdministratorTest.php b/tests/Unit/Domain/Model/Identity/AdministratorTest.php index 4bdca7dc..f78f3807 100644 --- a/tests/Unit/Domain/Model/Identity/AdministratorTest.php +++ b/tests/Unit/Domain/Model/Identity/AdministratorTest.php @@ -55,15 +55,15 @@ 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 From 4538aa9fbeb46f0e756c3388390487d69621142a Mon Sep 17 00:00:00 2001 From: Tatevik Date: Tue, 29 Apr 2025 21:13:02 +0400 Subject: [PATCH 25/30] ISSUE-345: createdAt/updatedAt --- .../Model/Analytics/LinkTrackForward.php | 13 ++++- .../Model/Analytics/LinkTrackUmlClick.php | 13 ++++- .../Model/Analytics/UserMessageView.php | 13 ++++- src/Domain/Model/Analytics/UserStats.php | 13 ++++- src/Domain/Model/Configuration/EventLog.php | 10 +++- src/Domain/Model/Configuration/UrlCache.php | 13 ++++- src/Domain/Model/Identity/AdminAttribute.php | 10 +++- src/Domain/Model/Identity/AdminLogin.php | 13 ++++- src/Domain/Model/Identity/Administrator.php | 57 +++++++++++++------ .../Model/Identity/AdministratorToken.php | 29 ++++++---- src/Domain/Model/Interfaces/CreationDate.php | 11 +--- src/Domain/Model/Interfaces/Identity.php | 5 +- .../Model/Interfaces/ModificationDate.php | 6 +- src/Domain/Model/Messaging/Attachment.php | 13 ++++- src/Domain/Model/Messaging/Bounce.php | 10 +++- src/Domain/Model/Messaging/BounceRegex.php | 10 +++- src/Domain/Model/Messaging/ListMessage.php | 34 +++++++++-- src/Domain/Model/Messaging/Message.php | 33 +++++++++-- .../Model/Messaging/MessageAttachment.php | 13 ++++- src/Domain/Model/Messaging/SendProcess.php | 32 +++++++++-- src/Domain/Model/Messaging/Template.php | 11 +++- src/Domain/Model/Messaging/TemplateImage.php | 12 +++- .../Model/Messaging/UserMessageBounce.php | 11 +++- .../Model/Messaging/UserMessageForward.php | 11 +++- .../Model/Subscription/SubscribePage.php | 13 ++++- src/Domain/Model/Subscription/Subscriber.php | 41 ++++++++++--- .../SubscriberAttributeDefinition.php | 13 ++++- .../Model/Subscription/SubscriberHistory.php | 13 ++++- .../Model/Subscription/SubscriberList.php | 41 ++++++++++--- .../Model/Subscription/Subscription.php | 34 +++++++++-- src/Domain/Model/Traits/CreationDateTrait.php | 50 ---------------- src/Domain/Model/Traits/IdentityTrait.php | 31 ---------- .../Model/Traits/ModificationDateTrait.php | 45 --------------- .../Identity/AdministratorFixture.php | 2 +- ...nistratorTokenWithAdministratorFixture.php | 2 +- .../DetachedAdministratorTokenFixture.php | 2 +- .../Fixtures/Messaging/MessageFixture.php | 2 +- .../Subscription/SubscriberFixture.php | 4 +- .../Subscription/SubscriberListFixture.php | 5 +- .../Subscription/SubscriptionFixture.php | 4 +- .../Identity/AdministratorRepositoryTest.php | 16 +++--- .../AdministratorTokenRepositoryTest.php | 8 +-- .../Messaging/MessageRepositoryTest.php | 2 +- .../SubscriberListRepositoryTest.php | 12 ++-- .../Subscription/SubscriberRepositoryTest.php | 8 +-- .../SubscriptionRepositoryTest.php | 8 +-- .../Model/Identity/AdministratorTest.php | 20 ++----- .../Model/Identity/AdministratorTokenTest.php | 8 +-- .../Model/Messaging/SubscriberListTest.php | 17 ++---- .../Model/Subscription/SubscriberTest.php | 16 +++--- .../Model/Subscription/SubscriptionTest.php | 19 ++----- 51 files changed, 498 insertions(+), 334 deletions(-) delete mode 100644 src/Domain/Model/Traits/CreationDateTrait.php delete mode 100644 src/Domain/Model/Traits/IdentityTrait.php delete mode 100644 src/Domain/Model/Traits/ModificationDateTrait.php diff --git a/src/Domain/Model/Analytics/LinkTrackForward.php b/src/Domain/Model/Analytics/LinkTrackForward.php index 2b42bc93..a06d66f6 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 964a8c99..e72f0242 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 19a6bbc1..673216d3 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 838b942e..07d7d5c9 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 d26ae733..40c5f327 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 5ea2f9eb..621878e8 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 39d23851..2e6a007b 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; } diff --git a/src/Domain/Model/Identity/AdminLogin.php b/src/Domain/Model/Identity/AdminLogin.php index d16bff16..653e5dc1 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 1dd938ad..815b09fd 100644 --- a/src/Domain/Model/Identity/Administrator.php +++ b/src/Domain/Model/Identity/Administrator.php @@ -10,10 +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\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 @@ -27,9 +25,17 @@ #[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; @@ -40,9 +46,6 @@ class Administrator implements DomainModel, Identity, CreationDate, Modification #[ORM\Column(name: 'email')] private string $email; - #[ORM\Column(name: 'created', type: 'datetime')] - protected ?DateTime $creationDate = null; - #[ORM\Column(name: 'modifiedby', type: 'string', length: 66, nullable: true)] protected ?string $modifiedBy; @@ -68,7 +71,8 @@ public function __construct() $this->passwordChangeDate = null; $this->loginName = ''; $this->passwordHash = ''; - $this->modificationDate = null; + $this->createdAt = new DateTime(); + $this->updatedAt = null; $this->email = ''; } @@ -104,7 +108,7 @@ public function getPasswordHash(): string public function setPasswordHash(string $passwordHash): self { $this->passwordHash = $passwordHash; - $this->setPasswordChangeDate(new DateTime()); + $this->passwordChangeDate = new DateTime(); return $this; } @@ -114,13 +118,6 @@ public function getPasswordChangeDate(): ?DateTime return $this->passwordChangeDate; } - private function setPasswordChangeDate(DateTime $changeDate): self - { - $this->passwordChangeDate = $changeDate; - - return $this; - } - public function isDisabled(): bool { return $this->disabled; @@ -168,4 +165,28 @@ 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 3178333a..e4f80395 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,29 +55,34 @@ 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): self + private function setCreatedAt(DateTime $createdAt): self { - $this->creationDate = $creationDate->getTimestamp(); + $this->createdAt = $createdAt->getTimestamp(); return $this; } #[ORM\PrePersist] - public function updateCreationDate(): DomainModel + public function updateCreatedAt(): DomainModel { - $this->setCreationDate(new DateTime()); + $this->setCreatedAt(new DateTime()); return $this; } diff --git a/src/Domain/Model/Interfaces/CreationDate.php b/src/Domain/Model/Interfaces/CreationDate.php index 5ff35925..813970f1 100644 --- a/src/Domain/Model/Interfaces/CreationDate.php +++ b/src/Domain/Model/Interfaces/CreationDate.php @@ -20,14 +20,5 @@ interface CreationDate /** * @return DateTime|null */ - public function getCreationDate(): ?DateTime; - - /** - * Updates the creation date to now. - * - * @PrePersist - * - * @return DomainModel - */ - public function updateCreationDate(): DomainModel; + public function getCreatedAt(): ?DateTime; } diff --git a/src/Domain/Model/Interfaces/Identity.php b/src/Domain/Model/Interfaces/Identity.php index 48433a34..17f2cdb7 100644 --- a/src/Domain/Model/Interfaces/Identity.php +++ b/src/Domain/Model/Interfaces/Identity.php @@ -13,8 +13,5 @@ */ interface Identity { - /** - * @return int - */ - public function getId(): int; + public function getId(): ?int; } diff --git a/src/Domain/Model/Interfaces/ModificationDate.php b/src/Domain/Model/Interfaces/ModificationDate.php index 1c40208d..ba8ccc50 100644 --- a/src/Domain/Model/Interfaces/ModificationDate.php +++ b/src/Domain/Model/Interfaces/ModificationDate.php @@ -19,15 +19,15 @@ interface ModificationDate /** * @return DateTime|null */ - public function getModificationDate(): ?DateTime; + public function getUpdatedAt(): ?DateTime; /** - * Updates the modification date to now. + * Updates the modification date to be now. * * @Mapping\PrePersist * @Mapping\PreUpdate * * @return DomainModel */ - public function updateModificationDate(): DomainModel; + public function updateUpdatedAt(): DomainModel; } diff --git a/src/Domain/Model/Messaging/Attachment.php b/src/Domain/Model/Messaging/Attachment.php index c5c4410b..67ab38d9 100644 --- a/src/Domain/Model/Messaging/Attachment.php +++ b/src/Domain/Model/Messaging/Attachment.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\AttachmentRepository; +use Symfony\Component\Serializer\Attribute\Groups; #[ORM\Entity(repositoryClass: AttachmentRepository::class)] #[ORM\Table(name: 'phplist_attachment')] class Attachment 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: 255, nullable: true)] private ?string $filename; @@ -45,6 +49,11 @@ public function __construct( $this->size = $size; } + public function getId(): ?int + { + return $this->id; + } + public function getFilename(): ?string { return $this->filename; diff --git a/src/Domain/Model/Messaging/Bounce.php b/src/Domain/Model/Messaging/Bounce.php index 79cbd2d6..a6a594d3 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; } diff --git a/src/Domain/Model/Messaging/BounceRegex.php b/src/Domain/Model/Messaging/BounceRegex.php index 505cbe73..67a5bbab 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; } diff --git a/src/Domain/Model/Messaging/ListMessage.php b/src/Domain/Model/Messaging/ListMessage.php index b587d8b3..e3b48fba 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 index b4ed60ce..8ea9f885 100644 --- a/src/Domain/Model/Messaging/Message.php +++ b/src/Domain/Model/Messaging/Message.php @@ -4,6 +4,7 @@ namespace PhpList\Core\Domain\Model\Messaging; +use DateTime; use Doctrine\ORM\Mapping as ORM; use PhpList\Core\Domain\Model\Identity\Administrator; use PhpList\Core\Domain\Model\Interfaces\DomainModel; @@ -14,9 +15,8 @@ use PhpList\Core\Domain\Model\Messaging\Message\MessageMetadata; use PhpList\Core\Domain\Model\Messaging\Message\MessageOptions; use PhpList\Core\Domain\Model\Messaging\Message\MessageSchedule; -use PhpList\Core\Domain\Model\Traits\IdentityTrait; -use PhpList\Core\Domain\Model\Traits\ModificationDateTrait; use PhpList\Core\Domain\Repository\Messaging\MessageRepository; +use Symfony\Component\Serializer\Attribute\Groups; #[ORM\Entity(repositoryClass: MessageRepository::class)] #[ORM\Table(name: 'phplist_message')] @@ -24,8 +24,14 @@ #[ORM\HasLifecycleCallbacks] class Message 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\Embedded(class: MessageFormat::class, columnPrefix: false)] private MessageFormat $format; @@ -72,6 +78,25 @@ public function __construct( $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; diff --git a/src/Domain/Model/Messaging/MessageAttachment.php b/src/Domain/Model/Messaging/MessageAttachment.php index a4baaf84..6f6ae724 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 1db36238..9c32a556 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 08aed78d..420ba9bc 100644 --- a/src/Domain/Model/Messaging/Template.php +++ b/src/Domain/Model/Messaging/Template.php @@ -9,7 +9,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; use PhpList\Core\Domain\Repository\Messaging\TemplateRepository; #[ORM\Entity(repositoryClass: TemplateRepository::class)] @@ -17,7 +16,10 @@ #[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; @@ -45,6 +47,11 @@ public function __construct(string $title) $this->images = new ArrayCollection(); } + public function getId(): ?int + { + return $this->id; + } + public function getTitle(): string { return $this->title; diff --git a/src/Domain/Model/Messaging/TemplateImage.php b/src/Domain/Model/Messaging/TemplateImage.php index bf275f32..09ff6b2e 100644 --- a/src/Domain/Model/Messaging/TemplateImage.php +++ b/src/Domain/Model/Messaging/TemplateImage.php @@ -7,7 +7,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; use PhpList\Core\Domain\Repository\Messaging\TemplateImageRepository; #[ORM\Entity(repositoryClass: TemplateImageRepository::class)] @@ -15,7 +14,11 @@ #[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; @@ -35,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; diff --git a/src/Domain/Model/Messaging/UserMessageBounce.php b/src/Domain/Model/Messaging/UserMessageBounce.php index 280c2d8f..c03ff8c1 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 ac79f4d6..153d3071 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 75f2b151..e58e1996 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 7897f571..0e693c27 100644 --- a/src/Domain/Model/Subscription/Subscriber.php +++ b/src/Domain/Model/Subscription/Subscriber.php @@ -14,9 +14,6 @@ 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; /** @@ -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')] @@ -106,6 +108,31 @@ 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 diff --git a/src/Domain/Model/Subscription/SubscriberAttributeDefinition.php b/src/Domain/Model/Subscription/SubscriberAttributeDefinition.php index f3678c5e..0210c0d5 100644 --- a/src/Domain/Model/Subscription/SubscriberAttributeDefinition.php +++ b/src/Domain/Model/Subscription/SubscriberAttributeDefinition.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_user_attribute')] @@ -15,7 +15,11 @@ #[ORM\Index(name: 'nameindex', columns: ['name'])] 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 SubscriberAttributeDefinition 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 ace918c7..47847a50 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/Subscription/SubscriberList.php b/src/Domain/Model/Subscription/SubscriberList.php index 2f0f7724..2a6d0163 100644 --- a/src/Domain/Model/Subscription/SubscriberList.php +++ b/src/Domain/Model/Subscription/SubscriberList.php @@ -13,9 +13,6 @@ 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; @@ -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')] @@ -91,12 +93,18 @@ 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; @@ -213,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 aaee8f66..ba1ade79 100644 --- a/src/Domain/Model/Subscription/Subscription.php +++ b/src/Domain/Model/Subscription/Subscription.php @@ -10,8 +10,6 @@ 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\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; @@ -32,12 +30,12 @@ #[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( @@ -58,6 +56,11 @@ 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; @@ -79,4 +82,23 @@ 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 885ef06c..00000000 --- a/src/Domain/Model/Traits/CreationDateTrait.php +++ /dev/null @@ -1,50 +0,0 @@ - - * @author Tatevik Grigoryan - */ -trait CreationDateTrait -{ - /** - * @return DateTime|null - */ - public function getCreationDate(): ?DateTime - { - return $this->creationDate; - } - - /** - * @param DateTime $creationDate - * - * @return DomainModel - */ - private function setCreationDate(DateTime $creationDate): DomainModel - { - $this->creationDate = $creationDate; - return $this; - } - - #[ORM\PrePersist] - public function updateCreationDate(): DomainModel - { - $this->setCreationDate(new DateTime()); - - return $this; - } -} diff --git a/src/Domain/Model/Traits/IdentityTrait.php b/src/Domain/Model/Traits/IdentityTrait.php deleted file mode 100644 index 4445ea26..00000000 --- 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 57c8260b..00000000 --- a/src/Domain/Model/Traits/ModificationDateTrait.php +++ /dev/null @@ -1,45 +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): DomainModel - { - $this->modificationDate = $modificationDate; - return $this; - } - - #[ORM\PrePersist] - #[ORM\PreUpdate] - public function updateModificationDate(): DomainModel - { - $this->setModificationDate(new DateTime()); - - return $this; - } -} diff --git a/tests/Integration/Domain/Repository/Fixtures/Identity/AdministratorFixture.php b/tests/Integration/Domain/Repository/Fixtures/Identity/AdministratorFixture.php index dba893e1..963d7648 100644 --- a/tests/Integration/Domain/Repository/Fixtures/Identity/AdministratorFixture.php +++ b/tests/Integration/Domain/Repository/Fixtures/Identity/AdministratorFixture.php @@ -45,7 +45,7 @@ public function load(ObjectManager $manager): void $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/Identity/AdministratorTokenWithAdministratorFixture.php b/tests/Integration/Domain/Repository/Fixtures/Identity/AdministratorTokenWithAdministratorFixture.php index 73a1bb5a..9805caea 100644 --- a/tests/Integration/Domain/Repository/Fixtures/Identity/AdministratorTokenWithAdministratorFixture.php +++ b/tests/Integration/Domain/Repository/Fixtures/Identity/AdministratorTokenWithAdministratorFixture.php @@ -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/Identity/DetachedAdministratorTokenFixture.php b/tests/Integration/Domain/Repository/Fixtures/Identity/DetachedAdministratorTokenFixture.php index 0935dfea..cd4bc687 100644 --- a/tests/Integration/Domain/Repository/Fixtures/Identity/DetachedAdministratorTokenFixture.php +++ b/tests/Integration/Domain/Repository/Fixtures/Identity/DetachedAdministratorTokenFixture.php @@ -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/Messaging/MessageFixture.php b/tests/Integration/Domain/Repository/Fixtures/Messaging/MessageFixture.php index 705baeb1..b65e66c2 100644 --- a/tests/Integration/Domain/Repository/Fixtures/Messaging/MessageFixture.php +++ b/tests/Integration/Domain/Repository/Fixtures/Messaging/MessageFixture.php @@ -101,7 +101,7 @@ public function load(ObjectManager $manager): void $this->setSubjectProperty($message, 'uuid', $row['uuid']); $manager->persist($message); - $this->setSubjectProperty($message, 'modificationDate', new DateTime($row['modified'])); + $this->setSubjectProperty($message, 'updatedAt', new DateTime($row['modified'])); } while (true); fclose($handle); diff --git a/tests/Integration/Domain/Repository/Fixtures/Subscription/SubscriberFixture.php b/tests/Integration/Domain/Repository/Fixtures/Subscription/SubscriberFixture.php index 36b69516..a9fc5867 100644 --- a/tests/Integration/Domain/Repository/Fixtures/Subscription/SubscriberFixture.php +++ b/tests/Integration/Domain/Repository/Fixtures/Subscription/SubscriberFixture.php @@ -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/Subscription/SubscriberListFixture.php b/tests/Integration/Domain/Repository/Fixtures/Subscription/SubscriberListFixture.php index 5b9ff102..954c3c0e 100644 --- a/tests/Integration/Domain/Repository/Fixtures/Subscription/SubscriberListFixture.php +++ b/tests/Integration/Domain/Repository/Fixtures/Subscription/SubscriberListFixture.php @@ -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/SubscriptionFixture.php b/tests/Integration/Domain/Repository/Fixtures/Subscription/SubscriptionFixture.php index e75b4e30..df1741c5 100644 --- a/tests/Integration/Domain/Repository/Fixtures/Subscription/SubscriptionFixture.php +++ b/tests/Integration/Domain/Repository/Fixtures/Subscription/SubscriptionFixture.php @@ -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 aca2f26f..05d0b83c 100644 --- a/tests/Integration/Domain/Repository/Identity/AdministratorRepositoryTest.php +++ b/tests/Integration/Domain/Repository/Identity/AdministratorRepositoryTest.php @@ -51,7 +51,7 @@ 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->getEmail()); @@ -59,26 +59,28 @@ public function testFindReadsModelFromDatabase(): void '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 23c9e8d5..b37d4e79 100644 --- a/tests/Integration/Domain/Repository/Identity/AdministratorTokenRepositoryTest.php +++ b/tests/Integration/Domain/Repository/Identity/AdministratorTokenRepositoryTest.php @@ -56,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()); } @@ -68,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() @@ -83,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 index a30c9e6d..fc16a416 100644 --- a/tests/Integration/Domain/Repository/Messaging/MessageRepositoryTest.php +++ b/tests/Integration/Domain/Repository/Messaging/MessageRepositoryTest.php @@ -128,6 +128,6 @@ public function testMessageTimestampsAreSetOnPersist(): void $this->entityManager->persist($message); - self::assertSimilarDates($expectedDate, $message->getModificationDate()); + self::assertSimilarDates($expectedDate, $message->getUpdatedAt()); } } diff --git a/tests/Integration/Domain/Repository/Messaging/SubscriberListRepositoryTest.php b/tests/Integration/Domain/Repository/Messaging/SubscriberListRepositoryTest.php index 97c948a7..c721cb57 100644 --- a/tests/Integration/Domain/Repository/Messaging/SubscriberListRepositoryTest.php +++ b/tests/Integration/Domain/Repository/Messaging/SubscriberListRepositoryTest.php @@ -59,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; @@ -71,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()); @@ -88,7 +88,7 @@ public function testCreationDateOfNewModelIsSetToNowOnPersist() $this->entityManager->persist($model); - self::assertSimilarDates($expectedCreationDate, $model->getCreationDate()); + self::assertSimilarDates($expectedCreationDate, $model->getCreatedAt()); } public function testModificationDateOfNewModelIsSetToNowOnPersist() @@ -98,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/Subscription/SubscriberRepositoryTest.php b/tests/Integration/Domain/Repository/Subscription/SubscriberRepositoryTest.php index f8098e88..7c779bfd 100644 --- a/tests/Integration/Domain/Repository/Subscription/SubscriberRepositoryTest.php +++ b/tests/Integration/Domain/Repository/Subscription/SubscriberRepositoryTest.php @@ -65,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()); @@ -85,7 +85,7 @@ public function testCreationDateOfNewModelIsSetToNowOnPersist() $this->entityManager->persist($model); - self::assertSimilarDates($expectedCreationDate, $model->getCreationDate()); + self::assertSimilarDates($expectedCreationDate, $model->getCreatedAt()); } public function testModificationDateOfNewModelIsSetToNowOnPersist() @@ -96,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 c36399e9..e394a3ff 100644 --- a/tests/Integration/Domain/Repository/Subscription/SubscriptionRepositoryTest.php +++ b/tests/Integration/Domain/Repository/Subscription/SubscriptionRepositoryTest.php @@ -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() diff --git a/tests/Unit/Domain/Model/Identity/AdministratorTest.php b/tests/Unit/Domain/Model/Identity/AdministratorTest.php index f78f3807..e5565c64 100644 --- a/tests/Unit/Domain/Model/Identity/AdministratorTest.php +++ b/tests/Unit/Domain/Model/Identity/AdministratorTest.php @@ -66,28 +66,16 @@ public function testSetEmailAddressSetsEmailAddress(): void 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 f28a2d70..5318782f 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/SubscriberListTest.php b/tests/Unit/Domain/Model/Messaging/SubscriberListTest.php index 2620966b..8b7afa5b 100644 --- a/tests/Unit/Domain/Model/Messaging/SubscriberListTest.php +++ b/tests/Unit/Domain/Model/Messaging/SubscriberListTest.php @@ -45,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 408d78b3..f61c3192 100644 --- a/tests/Unit/Domain/Model/Subscription/SubscriberTest.php +++ b/tests/Unit/Domain/Model/Subscription/SubscriberTest.php @@ -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 e83197b3..5cdf3c03 100644 --- a/tests/Unit/Domain/Model/Subscription/SubscriptionTest.php +++ b/tests/Unit/Domain/Model/Subscription/SubscriptionTest.php @@ -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()); } } From 6cb63415b931c156e39da835468ce2c0e3cf358e Mon Sep 17 00:00:00 2001 From: Tatevik Date: Thu, 1 May 2025 21:26:08 +0400 Subject: [PATCH 26/30] ISSUE-345: add missing repos + cursor trait --- .../Model/Analytics/LinkTrackForward.php | 2 - .../Model/Analytics/LinkTrackUmlClick.php | 2 - .../Model/Analytics/UserMessageView.php | 5 +-- src/Domain/Model/Analytics/UserStats.php | 5 +-- src/Domain/Model/Configuration/EventLog.php | 2 - src/Domain/Model/Configuration/UrlCache.php | 5 +-- src/Domain/Model/Identity/AdminAttribute.php | 2 - src/Domain/Model/Identity/AdminLogin.php | 41 ++++++++++--------- .../Model/Identity/AdminPasswordRequest.php | 13 +++--- src/Domain/Model/Identity/Administrator.php | 2 - .../Model/Identity/AdministratorToken.php | 23 +++-------- src/Domain/Model/Identity/UserBlacklist.php | 3 +- .../Model/Identity/UserBlacklistData.php | 3 +- src/Domain/Model/Messaging/Attachment.php | 2 - src/Domain/Model/Messaging/Bounce.php | 2 - src/Domain/Model/Messaging/BounceRegex.php | 2 - .../Model/Messaging/BounceRegexBounce.php | 4 +- src/Domain/Model/Messaging/ListMessage.php | 2 - src/Domain/Model/Messaging/Message.php | 2 - .../Model/Messaging/MessageAttachment.php | 5 +-- src/Domain/Model/Messaging/MessageData.php | 3 +- src/Domain/Model/Messaging/SendProcess.php | 5 +-- src/Domain/Model/Messaging/UserMessage.php | 34 ++++++--------- .../Model/Messaging/UserMessageBounce.php | 11 ++--- .../Model/Messaging/UserMessageForward.php | 20 ++++----- .../Model/Subscription/SubscribePage.php | 5 +-- .../Model/Subscription/SubscribePageData.php | 3 +- src/Domain/Model/Subscription/Subscriber.php | 20 --------- .../Subscription/SubscriberAttribute.php | 3 +- .../SubscriberAttributeDefinition.php | 5 +-- .../Model/Subscription/SubscriberHistory.php | 23 +++++------ .../Model/Subscription/SubscriberList.php | 19 --------- .../Analytics/LinkTrackForwardRepository.php | 2 + .../Analytics/LinkTrackRepository.php | 2 + .../Analytics/LinkTrackUmlClickRepository.php | 2 + .../Analytics/UserMessageViewRepository.php | 13 ++++++ .../Analytics/UserStatsRepository.php | 13 ++++++ .../Configuration/EventLogRepository.php | 2 + .../Configuration/UrlCacheRepository.php | 13 ++++++ .../Repository/CursorPaginationTrait.php | 26 ++++++++++++ .../Identity/AdminAttributeRepository.php | 2 + .../Identity/AdminLoginRepository.php | 2 + .../AdminPasswordRequestRepository.php | 2 + .../Identity/AdministratorRepository.php | 3 ++ .../Identity/AdministratorTokenRepository.php | 4 ++ .../Identity/UserBlacklistDataRepository.php | 11 +++++ .../Identity/UserBlacklistRepository.php | 11 +++++ .../Messaging/AttachmentRepository.php | 2 + .../Messaging/BounceRegexRepository.php | 2 + .../Repository/Messaging/BounceRepository.php | 2 + .../Messaging/ListMessageRepository.php | 2 + .../Messaging/MessageAttachmentRepository.php | 13 ++++++ .../Messaging/MessageDataRepository.php | 13 ++++++ .../Messaging/MessageRepository.php | 3 ++ .../Messaging/SendProcessRepository.php | 13 ++++++ .../Messaging/TemplateImageRepository.php | 2 + .../Messaging/TemplateRepository.php | 2 + .../Messaging/UserMessageBounceRepository.php | 13 ++++++ .../UserMessageForwardRepository.php | 13 ++++++ .../Messaging/UserMessageRepository.php | 11 +++++ ...ubscriberAttributeDefinitionRepository.php | 13 ++++++ .../SubscriberAttributeRepository.php | 11 +++++ .../SubscriberHistoryRepository.php | 13 ++++++ .../Subscription/SubscriberListRepository.php | 4 ++ .../SubscriberPageDataRepository.php | 13 ++++++ .../Subscription/SubscriberPageRepository.php | 13 ++++++ .../Subscription/SubscriberRepository.php | 4 ++ .../Subscription/SubscriptionRepository.php | 13 +----- 68 files changed, 369 insertions(+), 192 deletions(-) create mode 100644 src/Domain/Repository/Analytics/UserMessageViewRepository.php create mode 100644 src/Domain/Repository/Analytics/UserStatsRepository.php create mode 100644 src/Domain/Repository/Configuration/UrlCacheRepository.php create mode 100644 src/Domain/Repository/CursorPaginationTrait.php create mode 100644 src/Domain/Repository/Identity/UserBlacklistDataRepository.php create mode 100644 src/Domain/Repository/Identity/UserBlacklistRepository.php create mode 100644 src/Domain/Repository/Messaging/MessageAttachmentRepository.php create mode 100644 src/Domain/Repository/Messaging/MessageDataRepository.php create mode 100644 src/Domain/Repository/Messaging/SendProcessRepository.php create mode 100644 src/Domain/Repository/Messaging/UserMessageBounceRepository.php create mode 100644 src/Domain/Repository/Messaging/UserMessageForwardRepository.php create mode 100644 src/Domain/Repository/Messaging/UserMessageRepository.php create mode 100644 src/Domain/Repository/Subscription/SubscriberAttributeDefinitionRepository.php create mode 100644 src/Domain/Repository/Subscription/SubscriberAttributeRepository.php create mode 100644 src/Domain/Repository/Subscription/SubscriberHistoryRepository.php create mode 100644 src/Domain/Repository/Subscription/SubscriberPageDataRepository.php create mode 100644 src/Domain/Repository/Subscription/SubscriberPageRepository.php diff --git a/src/Domain/Model/Analytics/LinkTrackForward.php b/src/Domain/Model/Analytics/LinkTrackForward.php index a06d66f6..213ff342 100644 --- a/src/Domain/Model/Analytics/LinkTrackForward.php +++ b/src/Domain/Model/Analytics/LinkTrackForward.php @@ -8,7 +8,6 @@ use PhpList\Core\Domain\Model\Interfaces\DomainModel; use PhpList\Core\Domain\Model\Interfaces\Identity; use PhpList\Core\Domain\Repository\Analytics\LinkTrackForwardRepository; -use Symfony\Component\Serializer\Attribute\Groups; #[ORM\Entity(repositoryClass: LinkTrackForwardRepository::class)] #[ORM\Table(name: 'phplist_linktrack_forward')] @@ -20,7 +19,6 @@ class LinkTrackForward implements DomainModel, Identity #[ORM\Id] #[ORM\Column(type: 'integer')] #[ORM\GeneratedValue] - #[Groups(['SubscriberList', 'SubscriberListMembers'])] private ?int $id = null; #[ORM\Column(type: 'string', length: 2083, nullable: true)] diff --git a/src/Domain/Model/Analytics/LinkTrackUmlClick.php b/src/Domain/Model/Analytics/LinkTrackUmlClick.php index e72f0242..8cff6c1b 100644 --- a/src/Domain/Model/Analytics/LinkTrackUmlClick.php +++ b/src/Domain/Model/Analytics/LinkTrackUmlClick.php @@ -9,7 +9,6 @@ use PhpList\Core\Domain\Model\Interfaces\DomainModel; use PhpList\Core\Domain\Model\Interfaces\Identity; 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')] @@ -22,7 +21,6 @@ class LinkTrackUmlClick implements DomainModel, Identity #[ORM\Id] #[ORM\Column(type: 'integer')] #[ORM\GeneratedValue] - #[Groups(['SubscriberList', 'SubscriberListMembers'])] private ?int $id = null; #[ORM\Column(name: 'messageid', type: 'integer')] diff --git a/src/Domain/Model/Analytics/UserMessageView.php b/src/Domain/Model/Analytics/UserMessageView.php index 673216d3..d933e545 100644 --- a/src/Domain/Model/Analytics/UserMessageView.php +++ b/src/Domain/Model/Analytics/UserMessageView.php @@ -8,9 +8,9 @@ use Doctrine\ORM\Mapping as ORM; use PhpList\Core\Domain\Model\Interfaces\DomainModel; use PhpList\Core\Domain\Model\Interfaces\Identity; -use Symfony\Component\Serializer\Attribute\Groups; +use PhpList\Core\Domain\Repository\Analytics\UserMessageViewRepository; -#[ORM\Entity] +#[ORM\Entity(repositoryClass: UserMessageViewRepository::class)] #[ORM\Table(name: 'phplist_user_message_view')] #[ORM\Index(name: 'msgidx', columns: ['messageid'])] #[ORM\Index(name: 'useridx', columns: ['userid'])] @@ -20,7 +20,6 @@ class UserMessageView implements DomainModel, Identity #[ORM\Id] #[ORM\Column(type: 'integer')] #[ORM\GeneratedValue] - #[Groups(['SubscriberList', 'SubscriberListMembers'])] private ?int $id = null; #[ORM\Column(name: 'messageid', type: 'integer')] diff --git a/src/Domain/Model/Analytics/UserStats.php b/src/Domain/Model/Analytics/UserStats.php index 07d7d5c9..4907bb52 100644 --- a/src/Domain/Model/Analytics/UserStats.php +++ b/src/Domain/Model/Analytics/UserStats.php @@ -7,9 +7,9 @@ use Doctrine\ORM\Mapping as ORM; use PhpList\Core\Domain\Model\Interfaces\DomainModel; use PhpList\Core\Domain\Model\Interfaces\Identity; -use Symfony\Component\Serializer\Attribute\Groups; +use PhpList\Core\Domain\Repository\Analytics\UserStatsRepository; -#[ORM\Entity] +#[ORM\Entity(repositoryClass: UserStatsRepository::class)] #[ORM\Table(name: 'phplist_userstats')] #[ORM\UniqueConstraint(name: 'entry', columns: ['unixdate', 'item', 'listid'])] #[ORM\Index(name: 'dateindex', columns: ['unixdate'])] @@ -21,7 +21,6 @@ class UserStats implements DomainModel, Identity #[ORM\Id] #[ORM\Column(type: 'integer')] #[ORM\GeneratedValue] - #[Groups(['SubscriberList', 'SubscriberListMembers'])] private ?int $id = null; #[ORM\Column(name: 'unixdate', type: 'integer', nullable: true)] diff --git a/src/Domain/Model/Configuration/EventLog.php b/src/Domain/Model/Configuration/EventLog.php index 40c5f327..426cbb80 100644 --- a/src/Domain/Model/Configuration/EventLog.php +++ b/src/Domain/Model/Configuration/EventLog.php @@ -9,7 +9,6 @@ use PhpList\Core\Domain\Model\Interfaces\DomainModel; use PhpList\Core\Domain\Model\Interfaces\Identity; use PhpList\Core\Domain\Repository\Configuration\EventLogRepository; -use Symfony\Component\Serializer\Attribute\Groups; #[ORM\Entity(repositoryClass: EventLogRepository::class)] #[ORM\Table(name: 'phplist_eventlog')] @@ -20,7 +19,6 @@ class EventLog implements DomainModel, Identity #[ORM\Id] #[ORM\Column(type: 'integer')] #[ORM\GeneratedValue] - #[Groups(['SubscriberList', 'SubscriberListMembers'])] private ?int $id = null; #[ORM\Column(type: 'datetime', nullable: true)] diff --git a/src/Domain/Model/Configuration/UrlCache.php b/src/Domain/Model/Configuration/UrlCache.php index 621878e8..a53b68b6 100644 --- a/src/Domain/Model/Configuration/UrlCache.php +++ b/src/Domain/Model/Configuration/UrlCache.php @@ -8,9 +8,9 @@ use Doctrine\ORM\Mapping as ORM; use PhpList\Core\Domain\Model\Interfaces\DomainModel; use PhpList\Core\Domain\Model\Interfaces\Identity; -use Symfony\Component\Serializer\Attribute\Groups; +use PhpList\Core\Domain\Repository\Configuration\UrlCacheRepository; -#[ORM\Entity] +#[ORM\Entity(repositoryClass: UrlCacheRepository::class)] #[ORM\Table(name: 'phplist_urlcache')] #[ORM\Index(name: 'urlindex', columns: ['url'])] class UrlCache implements DomainModel, Identity @@ -18,7 +18,6 @@ class UrlCache implements DomainModel, Identity #[ORM\Id] #[ORM\Column(type: 'integer')] #[ORM\GeneratedValue] - #[Groups(['SubscriberList', 'SubscriberListMembers'])] private ?int $id = null; #[ORM\Column(name: 'url', type: 'string', length: 2083)] diff --git a/src/Domain/Model/Identity/AdminAttribute.php b/src/Domain/Model/Identity/AdminAttribute.php index 2e6a007b..be740895 100644 --- a/src/Domain/Model/Identity/AdminAttribute.php +++ b/src/Domain/Model/Identity/AdminAttribute.php @@ -8,7 +8,6 @@ use PhpList\Core\Domain\Model\Interfaces\DomainModel; use PhpList\Core\Domain\Model\Interfaces\Identity; use PhpList\Core\Domain\Repository\Identity\AdminAttributeRepository; -use Symfony\Component\Serializer\Attribute\Groups; #[ORM\Entity(repositoryClass: AdminAttributeRepository::class)] #[ORM\Table(name: 'phplist_admin_attribute')] @@ -18,7 +17,6 @@ class AdminAttribute implements DomainModel, Identity #[ORM\Id] #[ORM\Column(type: 'integer')] #[ORM\GeneratedValue] - #[Groups(['SubscriberList', 'SubscriberListMembers'])] private ?int $id = null; #[ORM\Column(name: 'name', type: 'string', length: 255)] diff --git a/src/Domain/Model/Identity/AdminLogin.php b/src/Domain/Model/Identity/AdminLogin.php index 653e5dc1..a5afaebb 100644 --- a/src/Domain/Model/Identity/AdminLogin.php +++ b/src/Domain/Model/Identity/AdminLogin.php @@ -4,11 +4,12 @@ namespace PhpList\Core\Domain\Model\Identity; +use DateTimeImmutable; +use DateTimeInterface; use Doctrine\ORM\Mapping as ORM; use PhpList\Core\Domain\Model\Interfaces\DomainModel; use PhpList\Core\Domain\Model\Interfaces\Identity; use PhpList\Core\Domain\Repository\Identity\AdminLoginRepository; -use Symfony\Component\Serializer\Attribute\Groups; #[ORM\Entity(repositoryClass: AdminLoginRepository::class)] #[ORM\Table(name: 'phplist_admin_login')] @@ -18,11 +19,11 @@ class AdminLogin implements DomainModel, Identity #[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; + #[ORM\ManyToOne(targetEntity: Administrator::class)] + #[ORM\JoinColumn(name: 'adminid', referencedColumnName: 'id', nullable: false)] + private Administrator $administrator; #[ORM\Column(name: 'moment', type: 'bigint')] private int $moment; @@ -30,24 +31,24 @@ class AdminLogin implements DomainModel, Identity #[ORM\Column(name: 'remote_ip4', type: 'string', length: 32)] private string $remoteIp4; - #[ORM\Column(name: 'remote_ip6', type: 'string', length:50)] + #[ORM\Column(name: 'remote_ip6', type: 'string', length: 50)] private string $remoteIp6; - #[ORM\Column(name: 'sessionid', type: 'string', length:50)] + #[ORM\Column(name: 'sessionid', type: 'string', length: 50)] private string $sessionId; #[ORM\Column(name: 'active', type: 'boolean')] private bool $active = false; public function __construct( - int $adminId, - int $moment, + Administrator $administrator, + DateTimeInterface $createdAt, string $remoteIp4, string $remoteIp6, string $sessionId, ) { - $this->adminId = $adminId; - $this->moment = $moment; + $this->administrator = $administrator; + $this->moment = $createdAt->getTimestamp(); $this->remoteIp4 = $remoteIp4; $this->remoteIp6 = $remoteIp6; $this->sessionId = $sessionId; @@ -58,20 +59,25 @@ public function getId(): ?int return $this->id; } + public function isActive(): bool + { + return $this->active; + } + public function setActive(bool $active): self { $this->active = $active; - return $this; } - public function getAdminId(): int + + public function getAdministrator(): Administrator { - return $this->adminId; + return $this->administrator; } - public function getMoment(): int + public function getCreatedAt(): DateTimeInterface { - return $this->moment; + return (new DateTimeImmutable())->setTimestamp($this->moment); } public function getRemoteIp4(): string @@ -88,9 +94,4 @@ public function getSessionId(): string { return $this->sessionId; } - - public function isActive(): bool - { - return $this->active; - } } diff --git a/src/Domain/Model/Identity/AdminPasswordRequest.php b/src/Domain/Model/Identity/AdminPasswordRequest.php index 990b75d2..b2ae7bcb 100644 --- a/src/Domain/Model/Identity/AdminPasswordRequest.php +++ b/src/Domain/Model/Identity/AdminPasswordRequest.php @@ -23,16 +23,17 @@ class AdminPasswordRequest implements DomainModel, Identity #[ORM\Column(name: 'date', type: 'datetime', nullable: true)] private ?DateTime $date; - #[ORM\Column(name: 'admin', type: 'integer', nullable: true, options: ['unsigned' => true])] - private ?int $adminId; + #[ORM\ManyToOne(targetEntity: Administrator::class)] + #[ORM\JoinColumn(name: 'admin', referencedColumnName: 'id', nullable: true)] + private Administrator $administrator; #[ORM\Column(name: 'key_value', type: 'string', length: 32)] private string $keyValue; - public function __construct(?DateTime $date, ?int $adminId, string $keyValue) + public function __construct(?DateTime $date, Administrator $admin, string $keyValue) { $this->date = $date; - $this->adminId = $adminId; + $this->administrator = $admin; $this->keyValue = $keyValue; } @@ -46,9 +47,9 @@ public function getDate(): DateTime return $this->date; } - public function getAdminId(): int + public function getAdmin(): Administrator { - return $this->adminId; + return $this->administrator; } public function getKeyValue(): string diff --git a/src/Domain/Model/Identity/Administrator.php b/src/Domain/Model/Identity/Administrator.php index 815b09fd..5657b711 100644 --- a/src/Domain/Model/Identity/Administrator.php +++ b/src/Domain/Model/Identity/Administrator.php @@ -11,7 +11,6 @@ use PhpList\Core\Domain\Model\Interfaces\Identity; use PhpList\Core\Domain\Model\Interfaces\ModificationDate; 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 @@ -28,7 +27,6 @@ class Administrator implements DomainModel, Identity, CreationDate, Modification #[ORM\Id] #[ORM\Column(type: 'integer')] #[ORM\GeneratedValue] - #[Groups(['SubscriberList', 'SubscriberListMembers'])] private ?int $id = null; #[ORM\Column(name: 'created', type: 'datetime')] diff --git a/src/Domain/Model/Identity/AdministratorToken.php b/src/Domain/Model/Identity/AdministratorToken.php index e4f80395..abac6261 100644 --- a/src/Domain/Model/Identity/AdministratorToken.php +++ b/src/Domain/Model/Identity/AdministratorToken.php @@ -9,32 +9,29 @@ use Doctrine\ORM\Mapping as ORM; use Doctrine\Persistence\Proxy; use PhpList\Core\Domain\Repository\Identity\AdministratorTokenRepository; -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 Symfony\Component\Serializer\Attribute\Groups; /** * This class represents an API authentication token for an administrator. * @author Oliver Klee + * @author Tateik Grigoryan */ #[ORM\Entity(repositoryClass: AdministratorTokenRepository::class)] #[ORM\Table(name: 'phplist_admintoken')] #[ORM\HasLifecycleCallbacks] class AdministratorToken implements DomainModel, Identity, CreationDate { + public const DEFAULT_EXPIRY = '+1 hour'; + #[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 $createdAt = 0; #[ORM\Column(name: 'expires', type: 'datetime')] @@ -47,7 +44,6 @@ class AdministratorToken implements DomainModel, Identity, CreationDate #[ORM\ManyToOne(targetEntity: Administrator::class)] #[ORM\JoinColumn(name: 'adminid')] - #[Ignore] private ?Administrator $administrator = null; public function __construct() @@ -72,17 +68,10 @@ public function getCreatedAt(): ?DateTime return $date; } - private function setCreatedAt(DateTime $createdAt): self - { - $this->createdAt = $createdAt->getTimestamp(); - - return $this; - } - #[ORM\PrePersist] public function updateCreatedAt(): DomainModel { - $this->setCreatedAt(new DateTime()); + $this->createdAt = (new DateTime())->getTimestamp(); return $this; } @@ -91,11 +80,9 @@ public function getExpiry(): DateTime return $this->expiry; } - private function setExpiry(DateTime $expiry): self + private function setExpiry(DateTime $expiry): void { $this->expiry = $expiry; - - return $this; } public function generateExpiry(): self diff --git a/src/Domain/Model/Identity/UserBlacklist.php b/src/Domain/Model/Identity/UserBlacklist.php index 3c352aa4..b0b60e9d 100644 --- a/src/Domain/Model/Identity/UserBlacklist.php +++ b/src/Domain/Model/Identity/UserBlacklist.php @@ -7,8 +7,9 @@ use DateTime; use Doctrine\ORM\Mapping as ORM; use PhpList\Core\Domain\Model\Interfaces\DomainModel; +use PhpList\Core\Domain\Repository\Identity\UserBlacklistRepository; -#[ORM\Entity] +#[ORM\Entity(repositoryClass: UserBlacklistRepository::class)] #[ORM\Table(name: 'phplist_user_blacklist')] #[ORM\Index(name: 'emailidx', columns: ['email'])] class UserBlacklist implements DomainModel diff --git a/src/Domain/Model/Identity/UserBlacklistData.php b/src/Domain/Model/Identity/UserBlacklistData.php index 76e1ca61..bfb2e1e9 100644 --- a/src/Domain/Model/Identity/UserBlacklistData.php +++ b/src/Domain/Model/Identity/UserBlacklistData.php @@ -6,8 +6,9 @@ use Doctrine\ORM\Mapping as ORM; use PhpList\Core\Domain\Model\Interfaces\DomainModel; +use PhpList\Core\Domain\Repository\Identity\UserBlacklistDataRepository; -#[ORM\Entity] +#[ORM\Entity(repositoryClass: UserBlacklistDataRepository::class)] #[ORM\Table(name: 'phplist_user_blacklist_data')] #[ORM\Index(name: 'emailidx', columns: ['email'])] #[ORM\Index(name: 'emailnameidx', columns: ['email', 'name'])] diff --git a/src/Domain/Model/Messaging/Attachment.php b/src/Domain/Model/Messaging/Attachment.php index 67ab38d9..99e205df 100644 --- a/src/Domain/Model/Messaging/Attachment.php +++ b/src/Domain/Model/Messaging/Attachment.php @@ -8,7 +8,6 @@ use PhpList\Core\Domain\Model\Interfaces\DomainModel; use PhpList\Core\Domain\Model\Interfaces\Identity; use PhpList\Core\Domain\Repository\Messaging\AttachmentRepository; -use Symfony\Component\Serializer\Attribute\Groups; #[ORM\Entity(repositoryClass: AttachmentRepository::class)] #[ORM\Table(name: 'phplist_attachment')] @@ -17,7 +16,6 @@ class Attachment implements DomainModel, Identity #[ORM\Id] #[ORM\Column(type: 'integer')] #[ORM\GeneratedValue] - #[Groups(['SubscriberList', 'SubscriberListMembers'])] private ?int $id = null; #[ORM\Column(type: 'string', length: 255, nullable: true)] diff --git a/src/Domain/Model/Messaging/Bounce.php b/src/Domain/Model/Messaging/Bounce.php index a6a594d3..5611f9b5 100644 --- a/src/Domain/Model/Messaging/Bounce.php +++ b/src/Domain/Model/Messaging/Bounce.php @@ -9,7 +9,6 @@ use PhpList\Core\Domain\Model\Interfaces\DomainModel; use PhpList\Core\Domain\Model\Interfaces\Identity; use PhpList\Core\Domain\Repository\Messaging\BounceRepository; -use Symfony\Component\Serializer\Attribute\Groups; #[ORM\Entity(repositoryClass: BounceRepository::class)] #[ORM\Table(name: 'phplist_bounce')] @@ -20,7 +19,6 @@ class Bounce implements DomainModel, Identity #[ORM\Id] #[ORM\Column(type: 'integer')] #[ORM\GeneratedValue] - #[Groups(['SubscriberList', 'SubscriberListMembers'])] private ?int $id = null; #[ORM\Column(type: 'datetime', nullable: true)] diff --git a/src/Domain/Model/Messaging/BounceRegex.php b/src/Domain/Model/Messaging/BounceRegex.php index 67a5bbab..88da280b 100644 --- a/src/Domain/Model/Messaging/BounceRegex.php +++ b/src/Domain/Model/Messaging/BounceRegex.php @@ -8,7 +8,6 @@ use PhpList\Core\Domain\Model\Interfaces\DomainModel; use PhpList\Core\Domain\Model\Interfaces\Identity; use PhpList\Core\Domain\Repository\Messaging\BounceRegexRepository; -use Symfony\Component\Serializer\Attribute\Groups; #[ORM\Entity(repositoryClass: BounceRegexRepository::class)] #[ORM\Table(name: 'phplist_bounceregex')] @@ -18,7 +17,6 @@ class BounceRegex implements DomainModel, Identity #[ORM\Id] #[ORM\Column(type: 'integer')] #[ORM\GeneratedValue] - #[Groups(['SubscriberList', 'SubscriberListMembers'])] private ?int $id = null; #[ORM\Column(type: 'string', length: 2083, nullable: true)] diff --git a/src/Domain/Model/Messaging/BounceRegexBounce.php b/src/Domain/Model/Messaging/BounceRegexBounce.php index de245fcb..f36a9f31 100644 --- a/src/Domain/Model/Messaging/BounceRegexBounce.php +++ b/src/Domain/Model/Messaging/BounceRegexBounce.php @@ -6,9 +6,9 @@ use Doctrine\ORM\Mapping as ORM; use PhpList\Core\Domain\Model\Interfaces\DomainModel; -use PhpList\Core\Domain\Repository\Messaging\BounceRepository; +use PhpList\Core\Domain\Repository\Messaging\BounceRegexBounceRepository; -#[ORM\Entity(repositoryClass: BounceRepository::class)] +#[ORM\Entity(repositoryClass: BounceRegexBounceRepository::class)] #[ORM\Table(name: 'phplist_bounceregex_bounce')] class BounceRegexBounce implements DomainModel { diff --git a/src/Domain/Model/Messaging/ListMessage.php b/src/Domain/Model/Messaging/ListMessage.php index e3b48fba..52a4dff0 100644 --- a/src/Domain/Model/Messaging/ListMessage.php +++ b/src/Domain/Model/Messaging/ListMessage.php @@ -11,7 +11,6 @@ use PhpList\Core\Domain\Model\Interfaces\Identity; use PhpList\Core\Domain\Model\Interfaces\ModificationDate; use PhpList\Core\Domain\Repository\Messaging\ListMessageRepository; -use Symfony\Component\Serializer\Attribute\Groups; #[ORM\Entity(repositoryClass: ListMessageRepository::class)] #[ORM\Table(name: 'phplist_listmessage')] @@ -23,7 +22,6 @@ class ListMessage implements DomainModel, Identity, ModificationDate #[ORM\Id] #[ORM\Column(type: 'integer')] #[ORM\GeneratedValue] - #[Groups(['SubscriberList', 'SubscriberListMembers'])] private ?int $id = null; #[ORM\Column(name: 'messageid', type: 'integer')] diff --git a/src/Domain/Model/Messaging/Message.php b/src/Domain/Model/Messaging/Message.php index 8ea9f885..278b2f6e 100644 --- a/src/Domain/Model/Messaging/Message.php +++ b/src/Domain/Model/Messaging/Message.php @@ -16,7 +16,6 @@ use PhpList\Core\Domain\Model\Messaging\Message\MessageOptions; use PhpList\Core\Domain\Model\Messaging\Message\MessageSchedule; use PhpList\Core\Domain\Repository\Messaging\MessageRepository; -use Symfony\Component\Serializer\Attribute\Groups; #[ORM\Entity(repositoryClass: MessageRepository::class)] #[ORM\Table(name: 'phplist_message')] @@ -27,7 +26,6 @@ class Message implements DomainModel, Identity, ModificationDate #[ORM\Id] #[ORM\Column(type: 'integer')] #[ORM\GeneratedValue] - #[Groups(['SubscriberList', 'SubscriberListMembers'])] private ?int $id = null; #[ORM\Column(name: 'modified', type: 'datetime')] diff --git a/src/Domain/Model/Messaging/MessageAttachment.php b/src/Domain/Model/Messaging/MessageAttachment.php index 6f6ae724..1f65656e 100644 --- a/src/Domain/Model/Messaging/MessageAttachment.php +++ b/src/Domain/Model/Messaging/MessageAttachment.php @@ -6,9 +6,9 @@ use Doctrine\ORM\Mapping as ORM; use PhpList\Core\Domain\Model\Interfaces\Identity; -use Symfony\Component\Serializer\Attribute\Groups; +use PhpList\Core\Domain\Repository\Messaging\MessageAttachmentRepository; -#[ORM\Entity] +#[ORM\Entity(repositoryClass: MessageAttachmentRepository::class)] #[ORM\Table(name: 'phplist_message_attachment')] #[ORM\Index(name: 'messageattidx', columns: ['messageid', 'attachmentid'])] #[ORM\Index(name: 'messageidx', columns: ['messageid'])] @@ -17,7 +17,6 @@ class MessageAttachment implements Identity #[ORM\Id] #[ORM\Column(type: 'integer')] #[ORM\GeneratedValue] - #[Groups(['SubscriberList', 'SubscriberListMembers'])] private ?int $id = null; #[ORM\Column(name: 'messageid', type: 'integer')] diff --git a/src/Domain/Model/Messaging/MessageData.php b/src/Domain/Model/Messaging/MessageData.php index 8daedeb7..686436f4 100644 --- a/src/Domain/Model/Messaging/MessageData.php +++ b/src/Domain/Model/Messaging/MessageData.php @@ -6,8 +6,9 @@ use Doctrine\ORM\Mapping as ORM; use PhpList\Core\Domain\Model\Interfaces\DomainModel; +use PhpList\Core\Domain\Repository\Messaging\MessageDataRepository; -#[ORM\Entity] +#[ORM\Entity(repositoryClass: MessageDataRepository::class)] #[ORM\Table(name: 'phplist_messagedata')] class MessageData implements DomainModel { diff --git a/src/Domain/Model/Messaging/SendProcess.php b/src/Domain/Model/Messaging/SendProcess.php index 9c32a556..0c86b941 100644 --- a/src/Domain/Model/Messaging/SendProcess.php +++ b/src/Domain/Model/Messaging/SendProcess.php @@ -9,9 +9,9 @@ use PhpList\Core\Domain\Model\Interfaces\DomainModel; use PhpList\Core\Domain\Model\Interfaces\Identity; use PhpList\Core\Domain\Model\Interfaces\ModificationDate; -use Symfony\Component\Serializer\Attribute\Groups; +use PhpList\Core\Domain\Repository\Messaging\SendProcessRepository; -#[ORM\Entity] +#[ORM\Entity(repositoryClass: SendProcessRepository::class)] #[ORM\Table(name: 'phplist_sendprocess')] #[ORM\HasLifecycleCallbacks] class SendProcess implements DomainModel, Identity, ModificationDate @@ -19,7 +19,6 @@ class SendProcess implements DomainModel, Identity, ModificationDate #[ORM\Id] #[ORM\Column(type: 'integer')] #[ORM\GeneratedValue] - #[Groups(['SubscriberList', 'SubscriberListMembers'])] private ?int $id = null; #[ORM\Column(name: 'modified', type: 'datetime')] diff --git a/src/Domain/Model/Messaging/UserMessage.php b/src/Domain/Model/Messaging/UserMessage.php index 2fc3eeb2..fbe606fe 100644 --- a/src/Domain/Model/Messaging/UserMessage.php +++ b/src/Domain/Model/Messaging/UserMessage.php @@ -8,8 +8,9 @@ use Doctrine\ORM\Mapping as ORM; use PhpList\Core\Domain\Model\Interfaces\DomainModel; use PhpList\Core\Domain\Model\Subscription\Subscriber; +use PhpList\Core\Domain\Repository\Messaging\UserMessageRepository; -#[ORM\Entity] +#[ORM\Entity(repositoryClass: UserMessageRepository::class)] #[ORM\Table(name: 'phplist_usermessage')] #[ORM\Index(name: 'enteredindex', columns: ['entered'])] #[ORM\Index(name: 'messageidindex', columns: ['messageid'])] @@ -29,7 +30,7 @@ class UserMessage implements DomainModel private Message $message; #[ORM\Column(name: 'entered', type: 'datetime')] - private DateTime $entered; + private DateTime $createdAt; #[ORM\Column(name: 'viewed', type: 'datetime', nullable: true)] private ?DateTime $viewed = null; @@ -37,6 +38,13 @@ class UserMessage implements DomainModel #[ORM\Column(name: 'status', type: 'string', length: 255, nullable: true)] private ?string $status = null; + public function __construct(Subscriber $user, Message $message) + { + $this->user = $user; + $this->message = $message; + $this->createdAt = new DateTime(); + } + public function getUser(): Subscriber { return $this->user; @@ -47,9 +55,9 @@ public function getMessage(): Message return $this->message; } - public function getEntered(): DateTime + public function getCreatedAt(): DateTime { - return $this->entered; + return $this->createdAt; } public function getViewed(): ?DateTime @@ -62,24 +70,6 @@ public function getStatus(): ?string return $this->status; } - public function setUser(Subscriber $user): self - { - $this->user = $user; - return $this; - } - - public function setMessage(Message $message): self - { - $this->message = $message; - return $this; - } - - public function setEntered(DateTime $entered): self - { - $this->entered = $entered; - return $this; - } - public function setViewed(?DateTime $viewed): self { $this->viewed = $viewed; diff --git a/src/Domain/Model/Messaging/UserMessageBounce.php b/src/Domain/Model/Messaging/UserMessageBounce.php index c03ff8c1..7d9ce4c4 100644 --- a/src/Domain/Model/Messaging/UserMessageBounce.php +++ b/src/Domain/Model/Messaging/UserMessageBounce.php @@ -8,8 +8,9 @@ use Doctrine\ORM\Mapping as ORM; use PhpList\Core\Domain\Model\Interfaces\DomainModel; use PhpList\Core\Domain\Model\Interfaces\Identity; +use PhpList\Core\Domain\Repository\Messaging\UserMessageBounceRepository; -#[ORM\Entity] +#[ORM\Entity(repositoryClass: UserMessageBounceRepository::class)] #[ORM\Table(name: 'phplist_user_message_bounce')] #[ORM\Index(name: 'bounceidx', columns: ['bounce'])] #[ORM\Index(name: 'msgidx', columns: ['message'])] @@ -33,11 +34,11 @@ class UserMessageBounce implements DomainModel, Identity private int $bounce; #[ORM\Column(name: 'time', type: 'datetime', options: ['default' => 'CURRENT_TIMESTAMP'])] - private DateTime $time; + private DateTime $createdAt; public function __construct() { - $this->time = new DateTime(); + $this->createdAt = new DateTime(); } public function getId(): ?int @@ -60,9 +61,9 @@ public function getBounce(): int return $this->bounce; } - public function getTime(): DateTime + public function getCreatedAt(): DateTime { - return $this->time; + return $this->createdAt; } public function setUser(int $user): self diff --git a/src/Domain/Model/Messaging/UserMessageForward.php b/src/Domain/Model/Messaging/UserMessageForward.php index 153d3071..1f69da23 100644 --- a/src/Domain/Model/Messaging/UserMessageForward.php +++ b/src/Domain/Model/Messaging/UserMessageForward.php @@ -8,8 +8,9 @@ use Doctrine\ORM\Mapping as ORM; use PhpList\Core\Domain\Model\Interfaces\DomainModel; use PhpList\Core\Domain\Model\Interfaces\Identity; +use PhpList\Core\Domain\Repository\Messaging\UserMessageForwardRepository; -#[ORM\Entity] +#[ORM\Entity(repositoryClass: UserMessageForwardRepository::class)] #[ORM\Table(name: 'phplist_user_message_forward')] #[ORM\Index(name: 'messageidx', columns: ['message'])] #[ORM\Index(name: 'useridx', columns: ['user'])] @@ -34,7 +35,12 @@ class UserMessageForward implements DomainModel, Identity private ?string $status = null; #[ORM\Column(name: 'time', type: 'datetime', options: ['default' => 'CURRENT_TIMESTAMP'])] - private DateTime $time; + private DateTime $createdAt; + + public function __construct() + { + $this->createdAt = new DateTime(); + } public function getId(): ?int { @@ -61,9 +67,9 @@ public function getStatus(): ?string return $this->status; } - public function getTime(): DateTime + public function getCreatedAt(): DateTime { - return $this->time; + return $this->createdAt; } public function setUser(int $user): self @@ -89,10 +95,4 @@ public function setStatus(?string $status): self $this->status = $status; return $this; } - - public function setTime(DateTime $time): self - { - $this->time = $time; - return $this; - } } diff --git a/src/Domain/Model/Subscription/SubscribePage.php b/src/Domain/Model/Subscription/SubscribePage.php index e58e1996..bd2d29cf 100644 --- a/src/Domain/Model/Subscription/SubscribePage.php +++ b/src/Domain/Model/Subscription/SubscribePage.php @@ -7,16 +7,15 @@ use Doctrine\ORM\Mapping as ORM; use PhpList\Core\Domain\Model\Interfaces\DomainModel; use PhpList\Core\Domain\Model\Interfaces\Identity; -use Symfony\Component\Serializer\Attribute\Groups; +use PhpList\Core\Domain\Repository\Subscription\SubscriberPageRepository; -#[ORM\Entity] +#[ORM\Entity(repositoryClass: SubscriberPageRepository::class)] #[ORM\Table(name: 'phplist_subscribepage')] class SubscribePage implements DomainModel, Identity { #[ORM\Id] #[ORM\Column(type: 'integer')] #[ORM\GeneratedValue] - #[Groups(['SubscriberList', 'SubscriberListMembers'])] private ?int $id = null; #[ORM\Column(name: 'title', type: 'string', length: 255)] diff --git a/src/Domain/Model/Subscription/SubscribePageData.php b/src/Domain/Model/Subscription/SubscribePageData.php index ecc6d615..7c99db46 100644 --- a/src/Domain/Model/Subscription/SubscribePageData.php +++ b/src/Domain/Model/Subscription/SubscribePageData.php @@ -6,8 +6,9 @@ use Doctrine\ORM\Mapping as ORM; use PhpList\Core\Domain\Model\Interfaces\DomainModel; +use PhpList\Core\Domain\Repository\Subscription\SubscriberPageDataRepository; -#[ORM\Entity] +#[ORM\Entity(repositoryClass: SubscriberPageDataRepository::class)] #[ORM\Table(name: 'phplist_subscribepage_data')] class SubscribePageData implements DomainModel { diff --git a/src/Domain/Model/Subscription/Subscriber.php b/src/Domain/Model/Subscription/Subscriber.php index 0e693c27..f06972ec 100644 --- a/src/Domain/Model/Subscription/Subscriber.php +++ b/src/Domain/Model/Subscription/Subscriber.php @@ -9,12 +9,10 @@ use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; use PhpList\Core\Domain\Repository\Subscription\SubscriberRepository; -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 Symfony\Component\Serializer\Attribute\Groups; /** * This class represents subscriber who can subscribe to multiple subscriber lists and can receive email messages from @@ -34,54 +32,36 @@ class Subscriber implements DomainModel, Identity, CreationDate, ModificationDat #[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 $createdAt = null; #[ORM\Column(name: 'modified', type: 'datetime')] private ?DateTime $updatedAt = null; #[ORM\Column(unique: true)] - #[SerializedName('email')] - #[Groups(['SubscriberListMembers'])] private string $email = ''; #[ORM\Column(type: 'boolean')] - #[SerializedName('confirmed')] - #[Groups(['SubscriberListMembers'])] private bool $confirmed = false; #[ORM\Column(type: 'boolean')] - #[SerializedName('blacklisted')] - #[Groups(['SubscriberListMembers'])] private bool $blacklisted = false; #[ORM\Column(name: 'bouncecount', type: 'integer')] - #[SerializedName('bounce_count')] - #[Groups(['SubscriberListMembers'])] private int $bounceCount = 0; #[ORM\Column(name: 'uniqid', unique: true)] - #[SerializedName('unique_id')] - #[Groups(['SubscriberListMembers'])] private string $uniqueId = ''; #[ORM\Column(name: 'htmlemail', type: 'boolean')] - #[SerializedName('html_email')] - #[Groups(['SubscriberListMembers'])] private bool $htmlEmail = false; #[ORM\Column(type: 'boolean')] - #[SerializedName('disabled')] - #[Groups(['SubscriberListMembers'])] private bool $disabled = false; #[ORM\Column(name: 'extradata', type: 'text')] - #[SerializedName('extra_data')] private ?string $extraData; #[ORM\OneToMany( diff --git a/src/Domain/Model/Subscription/SubscriberAttribute.php b/src/Domain/Model/Subscription/SubscriberAttribute.php index 47844e39..8484ff1d 100644 --- a/src/Domain/Model/Subscription/SubscriberAttribute.php +++ b/src/Domain/Model/Subscription/SubscriberAttribute.php @@ -6,8 +6,9 @@ use Doctrine\ORM\Mapping as ORM; use PhpList\Core\Domain\Model\Interfaces\DomainModel; +use PhpList\Core\Domain\Repository\Subscription\SubscriberAttributeRepository; -#[ORM\Entity] +#[ORM\Entity(repositoryClass: SubscriberAttributeRepository::class)] #[ORM\Table(name: 'phplist_user_user_attribute')] #[ORM\Index(name: 'attindex', columns: ['attributeid'])] #[ORM\Index(name: 'attuserid', columns: ['userid', 'attributeid'])] diff --git a/src/Domain/Model/Subscription/SubscriberAttributeDefinition.php b/src/Domain/Model/Subscription/SubscriberAttributeDefinition.php index 0210c0d5..9c9f51b4 100644 --- a/src/Domain/Model/Subscription/SubscriberAttributeDefinition.php +++ b/src/Domain/Model/Subscription/SubscriberAttributeDefinition.php @@ -7,9 +7,9 @@ use Doctrine\ORM\Mapping as ORM; use PhpList\Core\Domain\Model\Interfaces\DomainModel; use PhpList\Core\Domain\Model\Interfaces\Identity; -use Symfony\Component\Serializer\Attribute\Groups; +use PhpList\Core\Domain\Repository\Subscription\SubscriberAttributeDefinitionRepository; -#[ORM\Entity] +#[ORM\Entity(repositoryClass: SubscriberAttributeDefinitionRepository::class)] #[ORM\Table(name: 'phplist_user_attribute')] #[ORM\Index(name: 'idnameindex', columns: ['id', 'name'])] #[ORM\Index(name: 'nameindex', columns: ['name'])] @@ -18,7 +18,6 @@ class SubscriberAttributeDefinition implements DomainModel, Identity #[ORM\Id] #[ORM\Column(type: 'integer')] #[ORM\GeneratedValue] - #[Groups(['SubscriberList', 'SubscriberListMembers'])] private ?int $id = null; #[ORM\Column(name: 'name', type: 'string', length: 255)] diff --git a/src/Domain/Model/Subscription/SubscriberHistory.php b/src/Domain/Model/Subscription/SubscriberHistory.php index 47847a50..5761a96a 100644 --- a/src/Domain/Model/Subscription/SubscriberHistory.php +++ b/src/Domain/Model/Subscription/SubscriberHistory.php @@ -8,9 +8,9 @@ use Doctrine\ORM\Mapping as ORM; use PhpList\Core\Domain\Model\Interfaces\DomainModel; use PhpList\Core\Domain\Model\Interfaces\Identity; -use Symfony\Component\Serializer\Attribute\Groups; +use PhpList\Core\Domain\Repository\Subscription\SubscriberHistoryRepository; -#[ORM\Entity] +#[ORM\Entity(repositoryClass: SubscriberHistoryRepository::class)] #[ORM\Table(name: 'phplist_user_user_history')] #[ORM\Index(name: 'dateidx', columns: ['date'])] #[ORM\Index(name: 'userididx', columns: ['userid'])] @@ -19,7 +19,6 @@ class SubscriberHistory implements DomainModel, Identity #[ORM\Id] #[ORM\Column(type: 'integer')] #[ORM\GeneratedValue] - #[Groups(['SubscriberList', 'SubscriberListMembers'])] private ?int $id = null; #[ORM\ManyToOne(targetEntity: Subscriber::class)] @@ -30,7 +29,7 @@ class SubscriberHistory implements DomainModel, Identity private ?string $ip = null; #[ORM\Column(name: 'date', type: 'datetime', nullable: true)] - private ?DateTime $date = null; + private ?DateTime $createdAt = null; #[ORM\Column(name: 'summary', type: 'string', length: 255, nullable: true)] private ?string $summary = null; @@ -41,6 +40,12 @@ class SubscriberHistory implements DomainModel, Identity #[ORM\Column(name: 'systeminfo', type: 'text', nullable: true)] private ?string $systemInfo = null; + public function __construct(Subscriber $subscriber) + { + $this->subscriber = $subscriber; + $this->createdAt = new DateTime(); + } + public function getId(): ?int { return $this->id; @@ -56,9 +61,9 @@ public function getIp(): ?string return $this->ip; } - public function getDate(): ?DateTime + public function getCreatedAt(): ?DateTime { - return $this->date; + return $this->createdAt; } public function getSummary(): ?string @@ -88,12 +93,6 @@ public function setIp(?string $ip): self return $this; } - public function setDate(?DateTime $date): self - { - $this->date = $date; - return $this; - } - public function setSummary(?string $summary): self { $this->summary = $summary; diff --git a/src/Domain/Model/Subscription/SubscriberList.php b/src/Domain/Model/Subscription/SubscriberList.php index 2a6d0163..1b58875e 100644 --- a/src/Domain/Model/Subscription/SubscriberList.php +++ b/src/Domain/Model/Subscription/SubscriberList.php @@ -14,9 +14,6 @@ use PhpList\Core\Domain\Model\Interfaces\Identity; use PhpList\Core\Domain\Model\Interfaces\ModificationDate; 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; /** @@ -35,50 +32,34 @@ class SubscriberList implements DomainModel, Identity, CreationDate, Modificatio #[ORM\Id] #[ORM\Column(type: 'integer')] #[ORM\GeneratedValue] - #[Groups(['SubscriberList', 'SubscriberListMembers'])] private ?int $id = null; #[ORM\Column] - #[SerializedName('name')] - #[Groups(['SubscriberList'])] private string $name = ''; #[ORM\Column] - #[SerializedName('description')] - #[Groups(['SubscriberList'])] private string $description = ''; #[ORM\Column(name: 'entered', type: 'datetime', nullable: true)] - #[SerializedName('creation_date')] - #[Groups(['SubscriberList'])] 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')] - #[Groups(['SubscriberList'])] private ?int $listPosition; #[ORM\Column(name: 'prefix')] - #[SerializedName('subject_prefix')] - #[Groups(['SubscriberList'])] private ?string $subjectPrefix; #[ORM\Column(name: 'active', type: 'boolean')] - #[SerializedName('public')] - #[Groups(['SubscriberList'])] private bool $public; #[ORM\Column] - #[SerializedName('category')] - #[Groups(['SubscriberList'])] private string $category; #[ORM\ManyToOne(targetEntity: Administrator::class)] #[ORM\JoinColumn(name: 'owner')] - #[Ignore] private ?Administrator $owner = null; #[ORM\OneToMany( diff --git a/src/Domain/Repository/Analytics/LinkTrackForwardRepository.php b/src/Domain/Repository/Analytics/LinkTrackForwardRepository.php index c5e21bc0..899741b0 100644 --- a/src/Domain/Repository/Analytics/LinkTrackForwardRepository.php +++ b/src/Domain/Repository/Analytics/LinkTrackForwardRepository.php @@ -5,7 +5,9 @@ namespace PhpList\Core\Domain\Repository\Analytics; use PhpList\Core\Domain\Repository\AbstractRepository; +use PhpList\Core\Domain\Repository\CursorPaginationTrait; class LinkTrackForwardRepository extends AbstractRepository { + use CursorPaginationTrait; } diff --git a/src/Domain/Repository/Analytics/LinkTrackRepository.php b/src/Domain/Repository/Analytics/LinkTrackRepository.php index 44465ae0..8560b02e 100644 --- a/src/Domain/Repository/Analytics/LinkTrackRepository.php +++ b/src/Domain/Repository/Analytics/LinkTrackRepository.php @@ -5,7 +5,9 @@ namespace PhpList\Core\Domain\Repository\Analytics; use PhpList\Core\Domain\Repository\AbstractRepository; +use PhpList\Core\Domain\Repository\CursorPaginationTrait; class LinkTrackRepository extends AbstractRepository { + use CursorPaginationTrait; } diff --git a/src/Domain/Repository/Analytics/LinkTrackUmlClickRepository.php b/src/Domain/Repository/Analytics/LinkTrackUmlClickRepository.php index 08163303..d8737b85 100644 --- a/src/Domain/Repository/Analytics/LinkTrackUmlClickRepository.php +++ b/src/Domain/Repository/Analytics/LinkTrackUmlClickRepository.php @@ -5,7 +5,9 @@ namespace PhpList\Core\Domain\Repository\Analytics; use PhpList\Core\Domain\Repository\AbstractRepository; +use PhpList\Core\Domain\Repository\CursorPaginationTrait; class LinkTrackUmlClickRepository extends AbstractRepository { + use CursorPaginationTrait; } diff --git a/src/Domain/Repository/Analytics/UserMessageViewRepository.php b/src/Domain/Repository/Analytics/UserMessageViewRepository.php new file mode 100644 index 00000000..610a0311 --- /dev/null +++ b/src/Domain/Repository/Analytics/UserMessageViewRepository.php @@ -0,0 +1,13 @@ +createQueryBuilder('e') + ->where('e.id > :lastId') + ->setParameter('lastId', $lastId) + ->orderBy('e.id', 'ASC') + ->setMaxResults($limit) + ->getQuery() + ->getResult(); + } +} diff --git a/src/Domain/Repository/Identity/AdminAttributeRepository.php b/src/Domain/Repository/Identity/AdminAttributeRepository.php index 52d34cd3..c4a90caf 100644 --- a/src/Domain/Repository/Identity/AdminAttributeRepository.php +++ b/src/Domain/Repository/Identity/AdminAttributeRepository.php @@ -5,7 +5,9 @@ namespace PhpList\Core\Domain\Repository\Identity; use PhpList\Core\Domain\Repository\AbstractRepository; +use PhpList\Core\Domain\Repository\CursorPaginationTrait; class AdminAttributeRepository extends AbstractRepository { + use CursorPaginationTrait; } diff --git a/src/Domain/Repository/Identity/AdminLoginRepository.php b/src/Domain/Repository/Identity/AdminLoginRepository.php index 50289e72..8cc59bde 100644 --- a/src/Domain/Repository/Identity/AdminLoginRepository.php +++ b/src/Domain/Repository/Identity/AdminLoginRepository.php @@ -5,7 +5,9 @@ namespace PhpList\Core\Domain\Repository\Identity; use PhpList\Core\Domain\Repository\AbstractRepository; +use PhpList\Core\Domain\Repository\CursorPaginationTrait; class AdminLoginRepository extends AbstractRepository { + use CursorPaginationTrait; } diff --git a/src/Domain/Repository/Identity/AdminPasswordRequestRepository.php b/src/Domain/Repository/Identity/AdminPasswordRequestRepository.php index 75371c92..17ebca40 100644 --- a/src/Domain/Repository/Identity/AdminPasswordRequestRepository.php +++ b/src/Domain/Repository/Identity/AdminPasswordRequestRepository.php @@ -5,7 +5,9 @@ namespace PhpList\Core\Domain\Repository\Identity; use PhpList\Core\Domain\Repository\AbstractRepository; +use PhpList\Core\Domain\Repository\CursorPaginationTrait; class AdminPasswordRequestRepository extends AbstractRepository { + use CursorPaginationTrait; } diff --git a/src/Domain/Repository/Identity/AdministratorRepository.php b/src/Domain/Repository/Identity/AdministratorRepository.php index d98324b0..36a32a84 100644 --- a/src/Domain/Repository/Identity/AdministratorRepository.php +++ b/src/Domain/Repository/Identity/AdministratorRepository.php @@ -8,6 +8,7 @@ use Doctrine\ORM\Mapping\ClassMetadata; use PhpList\Core\Domain\Model\Identity\Administrator; use PhpList\Core\Domain\Repository\AbstractRepository; +use PhpList\Core\Domain\Repository\CursorPaginationTrait; use PhpList\Core\Security\HashGenerator; /** @@ -17,6 +18,8 @@ */ class AdministratorRepository extends AbstractRepository { + use CursorPaginationTrait; + private HashGenerator $hashGenerator; public function __construct( diff --git a/src/Domain/Repository/Identity/AdministratorTokenRepository.php b/src/Domain/Repository/Identity/AdministratorTokenRepository.php index 818b6bd0..95b9f0b0 100644 --- a/src/Domain/Repository/Identity/AdministratorTokenRepository.php +++ b/src/Domain/Repository/Identity/AdministratorTokenRepository.php @@ -10,14 +10,18 @@ use Doctrine\Common\Collections\Criteria; use PhpList\Core\Domain\Model\Identity\AdministratorToken; use PhpList\Core\Domain\Repository\AbstractRepository; +use PhpList\Core\Domain\Repository\CursorPaginationTrait; /** * Repository for AdministratorToken models. * * @author Oliver Klee + * @author Tatevik Grigoryan */ class AdministratorTokenRepository extends AbstractRepository { + use CursorPaginationTrait; + /** * Finds one unexpired token by the given key. Returns null if there is no match. * diff --git a/src/Domain/Repository/Identity/UserBlacklistDataRepository.php b/src/Domain/Repository/Identity/UserBlacklistDataRepository.php new file mode 100644 index 00000000..cfdde439 --- /dev/null +++ b/src/Domain/Repository/Identity/UserBlacklistDataRepository.php @@ -0,0 +1,11 @@ + + * @author Tatevik Grigoryan */ class SubscriberListRepository extends AbstractRepository { + use CursorPaginationTrait; + public function findWithSubscription($id) { return $this->createQueryBuilder('sl') diff --git a/src/Domain/Repository/Subscription/SubscriberPageDataRepository.php b/src/Domain/Repository/Subscription/SubscriberPageDataRepository.php new file mode 100644 index 00000000..01eeb9ff --- /dev/null +++ b/src/Domain/Repository/Subscription/SubscriberPageDataRepository.php @@ -0,0 +1,13 @@ + + * @author Tatevik Grigoryan */ class SubscriberRepository extends AbstractRepository { + use CursorPaginationTrait; + public function findSubscribersBySubscribedList(int $listId): ?Subscriber { return $this->createQueryBuilder('s') diff --git a/src/Domain/Repository/Subscription/SubscriptionRepository.php b/src/Domain/Repository/Subscription/SubscriptionRepository.php index ad6fa4b0..e1e97827 100644 --- a/src/Domain/Repository/Subscription/SubscriptionRepository.php +++ b/src/Domain/Repository/Subscription/SubscriptionRepository.php @@ -16,15 +16,10 @@ * @method Subscription[] findBySubscriberList(SubscriberList $list) * * @author Oliver Klee + * @author Tatevik Grigoryan */ class SubscriptionRepository extends AbstractRepository { - /** - * @param SubscriberList $list - * @param Subscriber $subscriber - * - * @return Subscription|null - */ public function findOneBySubscriberListAndSubscriber(SubscriberList $list, Subscriber $subscriber): ?Subscription { return $this->findOneBy( @@ -35,12 +30,6 @@ public function findOneBySubscriberListAndSubscriber(SubscriberList $list, Subsc ); } - /** - * @param int $listId - * @param string $email - * - * @return Subscription|null - */ public function findOneBySubscriberEmailAndListId(int $listId, string $email): ?Subscription { return $this->createQueryBuilder('subscription') From ed54fb256da34f607c23796c6e8da7cb32a8c018 Mon Sep 17 00:00:00 2001 From: Tatevik Date: Thu, 1 May 2025 21:51:23 +0400 Subject: [PATCH 27/30] ISSUE-345: modifiedBy getter/setter --- src/Domain/Model/Identity/Administrator.php | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/Domain/Model/Identity/Administrator.php b/src/Domain/Model/Identity/Administrator.php index 5657b711..9509269d 100644 --- a/src/Domain/Model/Identity/Administrator.php +++ b/src/Domain/Model/Identity/Administrator.php @@ -45,7 +45,7 @@ class Administrator implements DomainModel, Identity, CreationDate, Modification private string $email; #[ORM\Column(name: 'modifiedby', type: 'string', length: 66, nullable: true)] - protected ?string $modifiedBy; + private ?string $modifiedBy; #[ORM\Column(name: 'password')] private string $passwordHash; @@ -187,4 +187,15 @@ public function updateUpdatedAt(): DomainModel return $this; } + + public function setModifiedBy(?string $modifiedBy): self + { + $this->modifiedBy = $modifiedBy; + return $this; + } + + public function getModifiedBy(): ?string + { + return $this->modifiedBy; + } } From 4642d438d4e9a86b190555b97485d8681fc96953 Mon Sep 17 00:00:00 2001 From: Tatevik Date: Sat, 3 May 2025 21:30:25 +0400 Subject: [PATCH 28/30] ISSUE-345: PaginatableRepositoryInterface --- .../Analytics/LinkTrackForwardRepository.php | 3 ++- .../Repository/Analytics/LinkTrackRepository.php | 3 ++- .../Analytics/LinkTrackUmlClickRepository.php | 3 ++- .../Analytics/UserMessageViewRepository.php | 3 ++- .../Repository/Analytics/UserStatsRepository.php | 3 ++- .../Repository/Configuration/EventLogRepository.php | 3 ++- .../Repository/Configuration/UrlCacheRepository.php | 3 ++- .../Repository/Identity/AdminAttributeRepository.php | 3 ++- .../Repository/Identity/AdminLoginRepository.php | 3 ++- .../Identity/AdminPasswordRequestRepository.php | 3 ++- .../Repository/Identity/AdministratorRepository.php | 3 ++- .../Identity/AdministratorTokenRepository.php | 3 ++- .../Interfaces/PaginatableRepositoryInterface.php | 11 +++++++++++ .../Repository/Messaging/AttachmentRepository.php | 3 ++- .../Repository/Messaging/BounceRegexRepository.php | 3 ++- src/Domain/Repository/Messaging/BounceRepository.php | 3 ++- .../Repository/Messaging/ListMessageRepository.php | 3 ++- .../Messaging/MessageAttachmentRepository.php | 3 ++- .../Repository/Messaging/MessageDataRepository.php | 3 ++- src/Domain/Repository/Messaging/MessageRepository.php | 3 ++- .../Repository/Messaging/SendProcessRepository.php | 3 ++- .../Repository/Messaging/TemplateImageRepository.php | 3 ++- .../Repository/Messaging/TemplateRepository.php | 3 ++- .../Messaging/UserMessageBounceRepository.php | 3 ++- .../Messaging/UserMessageForwardRepository.php | 3 ++- .../SubscriberAttributeDefinitionRepository.php | 3 ++- .../Subscription/SubscriberHistoryRepository.php | 3 ++- .../Subscription/SubscriberListRepository.php | 3 ++- .../Subscription/SubscriberPageDataRepository.php | 3 ++- .../Subscription/SubscriberPageRepository.php | 3 ++- .../Repository/Subscription/SubscriberRepository.php | 3 ++- 31 files changed, 71 insertions(+), 30 deletions(-) create mode 100644 src/Domain/Repository/Interfaces/PaginatableRepositoryInterface.php diff --git a/src/Domain/Repository/Analytics/LinkTrackForwardRepository.php b/src/Domain/Repository/Analytics/LinkTrackForwardRepository.php index 899741b0..ff0b3c8d 100644 --- a/src/Domain/Repository/Analytics/LinkTrackForwardRepository.php +++ b/src/Domain/Repository/Analytics/LinkTrackForwardRepository.php @@ -6,8 +6,9 @@ use PhpList\Core\Domain\Repository\AbstractRepository; use PhpList\Core\Domain\Repository\CursorPaginationTrait; +use PhpList\Core\Domain\Repository\Interfaces\PaginatableRepositoryInterface; -class LinkTrackForwardRepository extends AbstractRepository +class LinkTrackForwardRepository extends AbstractRepository implements PaginatableRepositoryInterface { use CursorPaginationTrait; } diff --git a/src/Domain/Repository/Analytics/LinkTrackRepository.php b/src/Domain/Repository/Analytics/LinkTrackRepository.php index 8560b02e..acc63431 100644 --- a/src/Domain/Repository/Analytics/LinkTrackRepository.php +++ b/src/Domain/Repository/Analytics/LinkTrackRepository.php @@ -6,8 +6,9 @@ use PhpList\Core\Domain\Repository\AbstractRepository; use PhpList\Core\Domain\Repository\CursorPaginationTrait; +use PhpList\Core\Domain\Repository\Interfaces\PaginatableRepositoryInterface; -class LinkTrackRepository extends AbstractRepository +class LinkTrackRepository extends AbstractRepository implements PaginatableRepositoryInterface { use CursorPaginationTrait; } diff --git a/src/Domain/Repository/Analytics/LinkTrackUmlClickRepository.php b/src/Domain/Repository/Analytics/LinkTrackUmlClickRepository.php index d8737b85..dc0d4511 100644 --- a/src/Domain/Repository/Analytics/LinkTrackUmlClickRepository.php +++ b/src/Domain/Repository/Analytics/LinkTrackUmlClickRepository.php @@ -6,8 +6,9 @@ use PhpList\Core\Domain\Repository\AbstractRepository; use PhpList\Core\Domain\Repository\CursorPaginationTrait; +use PhpList\Core\Domain\Repository\Interfaces\PaginatableRepositoryInterface; -class LinkTrackUmlClickRepository extends AbstractRepository +class LinkTrackUmlClickRepository extends AbstractRepository implements PaginatableRepositoryInterface { use CursorPaginationTrait; } diff --git a/src/Domain/Repository/Analytics/UserMessageViewRepository.php b/src/Domain/Repository/Analytics/UserMessageViewRepository.php index 610a0311..da6f3c09 100644 --- a/src/Domain/Repository/Analytics/UserMessageViewRepository.php +++ b/src/Domain/Repository/Analytics/UserMessageViewRepository.php @@ -6,8 +6,9 @@ use PhpList\Core\Domain\Repository\AbstractRepository; use PhpList\Core\Domain\Repository\CursorPaginationTrait; +use PhpList\Core\Domain\Repository\Interfaces\PaginatableRepositoryInterface; -class UserMessageViewRepository extends AbstractRepository +class UserMessageViewRepository extends AbstractRepository implements PaginatableRepositoryInterface { use CursorPaginationTrait; } diff --git a/src/Domain/Repository/Analytics/UserStatsRepository.php b/src/Domain/Repository/Analytics/UserStatsRepository.php index bf301c94..a3ac95ed 100644 --- a/src/Domain/Repository/Analytics/UserStatsRepository.php +++ b/src/Domain/Repository/Analytics/UserStatsRepository.php @@ -6,8 +6,9 @@ use PhpList\Core\Domain\Repository\AbstractRepository; use PhpList\Core\Domain\Repository\CursorPaginationTrait; +use PhpList\Core\Domain\Repository\Interfaces\PaginatableRepositoryInterface; -class UserStatsRepository extends AbstractRepository +class UserStatsRepository extends AbstractRepository implements PaginatableRepositoryInterface { use CursorPaginationTrait; } diff --git a/src/Domain/Repository/Configuration/EventLogRepository.php b/src/Domain/Repository/Configuration/EventLogRepository.php index 8032b839..1e37714b 100644 --- a/src/Domain/Repository/Configuration/EventLogRepository.php +++ b/src/Domain/Repository/Configuration/EventLogRepository.php @@ -6,8 +6,9 @@ use PhpList\Core\Domain\Repository\AbstractRepository; use PhpList\Core\Domain\Repository\CursorPaginationTrait; +use PhpList\Core\Domain\Repository\Interfaces\PaginatableRepositoryInterface; -class EventLogRepository extends AbstractRepository +class EventLogRepository extends AbstractRepository implements PaginatableRepositoryInterface { use CursorPaginationTrait; } diff --git a/src/Domain/Repository/Configuration/UrlCacheRepository.php b/src/Domain/Repository/Configuration/UrlCacheRepository.php index 0b227bbc..b699a97a 100644 --- a/src/Domain/Repository/Configuration/UrlCacheRepository.php +++ b/src/Domain/Repository/Configuration/UrlCacheRepository.php @@ -6,8 +6,9 @@ use PhpList\Core\Domain\Repository\AbstractRepository; use PhpList\Core\Domain\Repository\CursorPaginationTrait; +use PhpList\Core\Domain\Repository\Interfaces\PaginatableRepositoryInterface; -class UrlCacheRepository extends AbstractRepository +class UrlCacheRepository extends AbstractRepository implements PaginatableRepositoryInterface { use CursorPaginationTrait; } diff --git a/src/Domain/Repository/Identity/AdminAttributeRepository.php b/src/Domain/Repository/Identity/AdminAttributeRepository.php index c4a90caf..c47797ba 100644 --- a/src/Domain/Repository/Identity/AdminAttributeRepository.php +++ b/src/Domain/Repository/Identity/AdminAttributeRepository.php @@ -6,8 +6,9 @@ use PhpList\Core\Domain\Repository\AbstractRepository; use PhpList\Core\Domain\Repository\CursorPaginationTrait; +use PhpList\Core\Domain\Repository\Interfaces\PaginatableRepositoryInterface; -class AdminAttributeRepository extends AbstractRepository +class AdminAttributeRepository extends AbstractRepository implements PaginatableRepositoryInterface { use CursorPaginationTrait; } diff --git a/src/Domain/Repository/Identity/AdminLoginRepository.php b/src/Domain/Repository/Identity/AdminLoginRepository.php index 8cc59bde..850ce208 100644 --- a/src/Domain/Repository/Identity/AdminLoginRepository.php +++ b/src/Domain/Repository/Identity/AdminLoginRepository.php @@ -6,8 +6,9 @@ use PhpList\Core\Domain\Repository\AbstractRepository; use PhpList\Core\Domain\Repository\CursorPaginationTrait; +use PhpList\Core\Domain\Repository\Interfaces\PaginatableRepositoryInterface; -class AdminLoginRepository extends AbstractRepository +class AdminLoginRepository extends AbstractRepository implements PaginatableRepositoryInterface { use CursorPaginationTrait; } diff --git a/src/Domain/Repository/Identity/AdminPasswordRequestRepository.php b/src/Domain/Repository/Identity/AdminPasswordRequestRepository.php index 17ebca40..46edcba3 100644 --- a/src/Domain/Repository/Identity/AdminPasswordRequestRepository.php +++ b/src/Domain/Repository/Identity/AdminPasswordRequestRepository.php @@ -6,8 +6,9 @@ use PhpList\Core\Domain\Repository\AbstractRepository; use PhpList\Core\Domain\Repository\CursorPaginationTrait; +use PhpList\Core\Domain\Repository\Interfaces\PaginatableRepositoryInterface; -class AdminPasswordRequestRepository extends AbstractRepository +class AdminPasswordRequestRepository extends AbstractRepository implements PaginatableRepositoryInterface { use CursorPaginationTrait; } diff --git a/src/Domain/Repository/Identity/AdministratorRepository.php b/src/Domain/Repository/Identity/AdministratorRepository.php index 36a32a84..5081578d 100644 --- a/src/Domain/Repository/Identity/AdministratorRepository.php +++ b/src/Domain/Repository/Identity/AdministratorRepository.php @@ -9,6 +9,7 @@ use PhpList\Core\Domain\Model\Identity\Administrator; use PhpList\Core\Domain\Repository\AbstractRepository; use PhpList\Core\Domain\Repository\CursorPaginationTrait; +use PhpList\Core\Domain\Repository\Interfaces\PaginatableRepositoryInterface; use PhpList\Core\Security\HashGenerator; /** @@ -16,7 +17,7 @@ * * @author Oliver Klee */ -class AdministratorRepository extends AbstractRepository +class AdministratorRepository extends AbstractRepository implements PaginatableRepositoryInterface { use CursorPaginationTrait; diff --git a/src/Domain/Repository/Identity/AdministratorTokenRepository.php b/src/Domain/Repository/Identity/AdministratorTokenRepository.php index 95b9f0b0..4e7c2d65 100644 --- a/src/Domain/Repository/Identity/AdministratorTokenRepository.php +++ b/src/Domain/Repository/Identity/AdministratorTokenRepository.php @@ -11,6 +11,7 @@ use PhpList\Core\Domain\Model\Identity\AdministratorToken; use PhpList\Core\Domain\Repository\AbstractRepository; use PhpList\Core\Domain\Repository\CursorPaginationTrait; +use PhpList\Core\Domain\Repository\Interfaces\PaginatableRepositoryInterface; /** * Repository for AdministratorToken models. @@ -18,7 +19,7 @@ * @author Oliver Klee * @author Tatevik Grigoryan */ -class AdministratorTokenRepository extends AbstractRepository +class AdministratorTokenRepository extends AbstractRepository implements PaginatableRepositoryInterface { use CursorPaginationTrait; diff --git a/src/Domain/Repository/Interfaces/PaginatableRepositoryInterface.php b/src/Domain/Repository/Interfaces/PaginatableRepositoryInterface.php new file mode 100644 index 00000000..5fdfd6b6 --- /dev/null +++ b/src/Domain/Repository/Interfaces/PaginatableRepositoryInterface.php @@ -0,0 +1,11 @@ + * @author Tatevik Grigoryan */ -class SubscriberListRepository extends AbstractRepository +class SubscriberListRepository extends AbstractRepository implements PaginatableRepositoryInterface { use CursorPaginationTrait; diff --git a/src/Domain/Repository/Subscription/SubscriberPageDataRepository.php b/src/Domain/Repository/Subscription/SubscriberPageDataRepository.php index 01eeb9ff..b8e4ab2b 100644 --- a/src/Domain/Repository/Subscription/SubscriberPageDataRepository.php +++ b/src/Domain/Repository/Subscription/SubscriberPageDataRepository.php @@ -6,8 +6,9 @@ use PhpList\Core\Domain\Repository\AbstractRepository; use PhpList\Core\Domain\Repository\CursorPaginationTrait; +use PhpList\Core\Domain\Repository\Interfaces\PaginatableRepositoryInterface; -class SubscriberPageDataRepository extends AbstractRepository +class SubscriberPageDataRepository extends AbstractRepository implements PaginatableRepositoryInterface { use CursorPaginationTrait; } diff --git a/src/Domain/Repository/Subscription/SubscriberPageRepository.php b/src/Domain/Repository/Subscription/SubscriberPageRepository.php index 4f37d4bb..4ef98771 100644 --- a/src/Domain/Repository/Subscription/SubscriberPageRepository.php +++ b/src/Domain/Repository/Subscription/SubscriberPageRepository.php @@ -6,8 +6,9 @@ use PhpList\Core\Domain\Repository\AbstractRepository; use PhpList\Core\Domain\Repository\CursorPaginationTrait; +use PhpList\Core\Domain\Repository\Interfaces\PaginatableRepositoryInterface; -class SubscriberPageRepository extends AbstractRepository +class SubscriberPageRepository extends AbstractRepository implements PaginatableRepositoryInterface { use CursorPaginationTrait; } diff --git a/src/Domain/Repository/Subscription/SubscriberRepository.php b/src/Domain/Repository/Subscription/SubscriberRepository.php index dbc9dd45..8ee0a94e 100644 --- a/src/Domain/Repository/Subscription/SubscriberRepository.php +++ b/src/Domain/Repository/Subscription/SubscriberRepository.php @@ -7,6 +7,7 @@ use PhpList\Core\Domain\Model\Subscription\Subscriber; use PhpList\Core\Domain\Repository\AbstractRepository; use PhpList\Core\Domain\Repository\CursorPaginationTrait; +use PhpList\Core\Domain\Repository\Interfaces\PaginatableRepositoryInterface; /** * Repository for Subscriber models. @@ -16,7 +17,7 @@ * @author Oliver Klee * @author Tatevik Grigoryan */ -class SubscriberRepository extends AbstractRepository +class SubscriberRepository extends AbstractRepository implements PaginatableRepositoryInterface { use CursorPaginationTrait; From 27759865594e4e01b5110734a56eeaadb8f507fb Mon Sep 17 00:00:00 2001 From: Tatevik Date: Sat, 3 May 2025 22:15:12 +0400 Subject: [PATCH 29/30] ISSUE-345: filter --- src/Domain/Filter/FilterRequestInterface.php | 10 +++ src/Domain/Filter/MessageFilter.php | 23 +++++++ src/Domain/Repository/AbstractRepository.php | 7 ++ .../Repository/CursorPaginationTrait.php | 44 ++++++++++-- .../PaginatableRepositoryInterface.php | 6 +- .../Messaging/MessageRepository.php | 15 +++++ .../Repository/CursorPaginationTraitTest.php | 67 +++++++++++++++++++ .../Domain/Repository/DummyRepository.php | 26 +++++++ 8 files changed, 190 insertions(+), 8 deletions(-) create mode 100644 src/Domain/Filter/FilterRequestInterface.php create mode 100644 src/Domain/Filter/MessageFilter.php create mode 100644 tests/Unit/Domain/Repository/CursorPaginationTraitTest.php create mode 100644 tests/Unit/Domain/Repository/DummyRepository.php diff --git a/src/Domain/Filter/FilterRequestInterface.php b/src/Domain/Filter/FilterRequestInterface.php new file mode 100644 index 00000000..cfe3710a --- /dev/null +++ b/src/Domain/Filter/FilterRequestInterface.php @@ -0,0 +1,10 @@ +owner; + } + + public function setOwner(?Administrator $admin): self + { + $this->owner = $admin; + return $this; + } +} diff --git a/src/Domain/Repository/AbstractRepository.php b/src/Domain/Repository/AbstractRepository.php index b5d56385..9770511f 100644 --- a/src/Domain/Repository/AbstractRepository.php +++ b/src/Domain/Repository/AbstractRepository.php @@ -15,6 +15,8 @@ */ abstract class AbstractRepository extends EntityRepository { + protected ?string $alias = null; + /** * Persists $model and flushes the entity manager change list. * @@ -46,4 +48,9 @@ public function remove(DomainModel $model): void $this->getEntityManager()->remove($model); $this->getEntityManager()->flush(); } + + public function getAlias(): string + { + return $this->alias ??= $this->getClassName(); + } } diff --git a/src/Domain/Repository/CursorPaginationTrait.php b/src/Domain/Repository/CursorPaginationTrait.php index 7eafea74..0b9d1159 100644 --- a/src/Domain/Repository/CursorPaginationTrait.php +++ b/src/Domain/Repository/CursorPaginationTrait.php @@ -4,23 +4,53 @@ namespace PhpList\Core\Domain\Repository; +use Doctrine\ORM\QueryBuilder; +use PhpList\Core\Domain\Filter\FilterRequestInterface; +use PhpList\Core\Domain\Model\Interfaces\DomainModel; +use RuntimeException; + trait CursorPaginationTrait { + abstract protected function createQueryBuilder(string $alias): QueryBuilder; + + abstract protected function getAlias(): string; + /** - * Provides cursor-based pagination using an integer ID. + * Apply cursor-based pagination to a QueryBuilder. * - * @param int $lastId The last seen ID to paginate after - * @param int $limit Max number of results to return + * @param QueryBuilder $queryBuilder + * @param int $lastId Last seen ID + * @param int $limit Max results * @return array */ - public function getAfterId(int $lastId, int $limit): array + public function getAfterId(QueryBuilder $queryBuilder, int $lastId, int $limit): array { - return $this->createQueryBuilder('e') - ->where('e.id > :lastId') + $alias = $this->getAlias(); + + return $queryBuilder + ->andWhere("$alias.id > :lastId") ->setParameter('lastId', $lastId) - ->orderBy('e.id', 'ASC') + ->orderBy("$alias.id", 'ASC') ->setMaxResults($limit) ->getQuery() ->getResult(); } + + /** + * Get filtered + paginated messages for a given owner and status. + * + * @return DomainModel[] + * @throws RuntimeException + */ + public function getFilteredAfterId(int $lastId, int $limit, ?FilterRequestInterface $filter = null): array + { + $alias = $this->getAlias(); + $queryBuilder = $this->createQueryBuilder($alias); + + if ($filter === null) { + return $this->getAfterId($queryBuilder, $lastId, $limit); + } + + throw new RuntimeException('Filter method not implemented'); + } } diff --git a/src/Domain/Repository/Interfaces/PaginatableRepositoryInterface.php b/src/Domain/Repository/Interfaces/PaginatableRepositoryInterface.php index 5fdfd6b6..571971fc 100644 --- a/src/Domain/Repository/Interfaces/PaginatableRepositoryInterface.php +++ b/src/Domain/Repository/Interfaces/PaginatableRepositoryInterface.php @@ -4,8 +4,12 @@ namespace PhpList\Core\Domain\Repository\Interfaces; +use Doctrine\ORM\QueryBuilder; +use PhpList\Core\Domain\Filter\FilterRequestInterface; + interface PaginatableRepositoryInterface { - public function getAfterId(int $afterId, int $limit): array; + public function getAfterId(QueryBuilder $queryBuilder, int $lastId, int $limit): array; + public function getFilteredAfterId(int $lastId, int $limit, ?FilterRequestInterface $filter = null): array; public function count(): int; } diff --git a/src/Domain/Repository/Messaging/MessageRepository.php b/src/Domain/Repository/Messaging/MessageRepository.php index 84919029..9354e328 100644 --- a/src/Domain/Repository/Messaging/MessageRepository.php +++ b/src/Domain/Repository/Messaging/MessageRepository.php @@ -4,6 +4,8 @@ namespace PhpList\Core\Domain\Repository\Messaging; +use PhpList\Core\Domain\Filter\FilterRequestInterface; +use PhpList\Core\Domain\Filter\MessageFilter; use PhpList\Core\Domain\Model\Messaging\Message; use PhpList\Core\Domain\Repository\AbstractRepository; use PhpList\Core\Domain\Repository\CursorPaginationTrait; @@ -12,6 +14,7 @@ class MessageRepository extends AbstractRepository implements PaginatableRepositoryInterface { use CursorPaginationTrait; + protected ?string $alias = 'm'; /** @return Message[] */ public function getByOwnerId(int $ownerId): array @@ -22,4 +25,16 @@ public function getByOwnerId(int $ownerId): array ->getQuery() ->getResult(); } + + public function getFilteredAfterId(int $lastId, int $limit, ?FilterRequestInterface $filter = null): array + { + $queryBuilder = $this->createQueryBuilder($this->getAlias());; + + if ($filter instanceof MessageFilter && $filter->getOwner() !== null) { + $queryBuilder->andWhere("IDENTITY({$this->getAlias()}.owner) = :ownerId") + ->setParameter('ownerId', $filter->getOwner()->getId()); + } + + return $this->getAfterId($queryBuilder, $lastId, $limit); + } } diff --git a/tests/Unit/Domain/Repository/CursorPaginationTraitTest.php b/tests/Unit/Domain/Repository/CursorPaginationTraitTest.php new file mode 100644 index 00000000..8aecc019 --- /dev/null +++ b/tests/Unit/Domain/Repository/CursorPaginationTraitTest.php @@ -0,0 +1,67 @@ +qb = $this->createMock(QueryBuilder::class); + $this->query = $this->createMock(Query::class); + + $this->qb->method('andWhere')->willReturnSelf(); + $this->qb->method('setParameter')->willReturnSelf(); + $this->qb->method('orderBy')->willReturnSelf(); + $this->qb->method('setMaxResults')->willReturnSelf(); + $this->qb->method('getQuery')->willReturn($this->query); + + $this->repo = new DummyRepository($this->qb); + } + + public function testGetAfterIdReturnsResults(): void + { + $expected = ['foo', 'bar']; + $this->query + ->expects(self::once()) + ->method('getResult') + ->willReturn($expected); + + $result = $this->repo->getAfterId($this->qb, 10, 2); + + self::assertSame($expected, $result); + } + + public function testGetFilteredAfterIdWithNullFilterDelegates(): void + { + $expected = ['cursor', 'pagination']; + // same expectations as previous test + $this->query->method('getResult')->willReturn($expected); + + $result = $this->repo->getFilteredAfterId(10, 2, null); + + self::assertSame($expected, $result); + } + + public function testGetFilteredAfterIdWithFilterThrows(): void + { + $dummyFilter = $this->createMock(FilterRequestInterface::class); + + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage('Filter method not implemented'); + + $this->repo->getFilteredAfterId(0, 10, $dummyFilter); + } +} diff --git a/tests/Unit/Domain/Repository/DummyRepository.php b/tests/Unit/Domain/Repository/DummyRepository.php new file mode 100644 index 00000000..e16b612e --- /dev/null +++ b/tests/Unit/Domain/Repository/DummyRepository.php @@ -0,0 +1,26 @@ +createQueryBuilder(). */ + protected function createQueryBuilder(string $alias): QueryBuilder + { + return $this->queryBuilder; + } +} From 9d4e98f6a295dfab8bce7a358369f5129740d3ee Mon Sep 17 00:00:00 2001 From: Tatevik Date: Sun, 4 May 2025 18:00:06 +0400 Subject: [PATCH 30/30] ISSUE-345: subscriber filter + refactor --- src/Domain/Filter/SubscriberFilter.php | 21 ++++++++++++ src/Domain/Repository/AbstractRepository.php | 7 +++- .../Repository/CursorPaginationTrait.php | 23 +++---------- .../PaginatableRepositoryInterface.php | 2 -- .../Messaging/MessageRepository.php | 17 +++++----- .../Subscription/SubscriberRepository.php | 33 +++++++++++++++++-- .../Repository/CursorPaginationTraitTest.php | 2 +- .../Domain/Repository/DummyRepository.php | 5 +++ 8 files changed, 77 insertions(+), 33 deletions(-) create mode 100644 src/Domain/Filter/SubscriberFilter.php diff --git a/src/Domain/Filter/SubscriberFilter.php b/src/Domain/Filter/SubscriberFilter.php new file mode 100644 index 00000000..7fae293b --- /dev/null +++ b/src/Domain/Filter/SubscriberFilter.php @@ -0,0 +1,21 @@ +listId = $listId; + return $this; + } + + public function getListId(): ?int + { + return $this->listId; + } +} diff --git a/src/Domain/Repository/AbstractRepository.php b/src/Domain/Repository/AbstractRepository.php index 9770511f..9fff90b7 100644 --- a/src/Domain/Repository/AbstractRepository.php +++ b/src/Domain/Repository/AbstractRepository.php @@ -5,6 +5,7 @@ namespace PhpList\Core\Domain\Repository; use Doctrine\ORM\EntityRepository; +use LogicException; use PhpList\Core\Domain\Model\Interfaces\DomainModel; /** @@ -51,6 +52,10 @@ public function remove(DomainModel $model): void public function getAlias(): string { - return $this->alias ??= $this->getClassName(); + if (!$this->alias) { + throw new LogicException('Alias not set in repository: ' . static::class); + } + + return $this->alias; } } diff --git a/src/Domain/Repository/CursorPaginationTrait.php b/src/Domain/Repository/CursorPaginationTrait.php index 0b9d1159..573435a1 100644 --- a/src/Domain/Repository/CursorPaginationTrait.php +++ b/src/Domain/Repository/CursorPaginationTrait.php @@ -4,33 +4,23 @@ namespace PhpList\Core\Domain\Repository; -use Doctrine\ORM\QueryBuilder; use PhpList\Core\Domain\Filter\FilterRequestInterface; use PhpList\Core\Domain\Model\Interfaces\DomainModel; use RuntimeException; trait CursorPaginationTrait { - abstract protected function createQueryBuilder(string $alias): QueryBuilder; - - abstract protected function getAlias(): string; - /** - * Apply cursor-based pagination to a QueryBuilder. - * - * @param QueryBuilder $queryBuilder * @param int $lastId Last seen ID * @param int $limit Max results * @return array */ - public function getAfterId(QueryBuilder $queryBuilder, int $lastId, int $limit): array + public function getAfterId(int $lastId, int $limit): array { - $alias = $this->getAlias(); - - return $queryBuilder - ->andWhere("$alias.id > :lastId") + return $this->createQueryBuilder('e') + ->andWhere('e.id > :lastId') ->setParameter('lastId', $lastId) - ->orderBy("$alias.id", 'ASC') + ->orderBy('e.id', 'ASC') ->setMaxResults($limit) ->getQuery() ->getResult(); @@ -44,11 +34,8 @@ public function getAfterId(QueryBuilder $queryBuilder, int $lastId, int $limit): */ public function getFilteredAfterId(int $lastId, int $limit, ?FilterRequestInterface $filter = null): array { - $alias = $this->getAlias(); - $queryBuilder = $this->createQueryBuilder($alias); - if ($filter === null) { - return $this->getAfterId($queryBuilder, $lastId, $limit); + return $this->getAfterId($lastId, $limit); } throw new RuntimeException('Filter method not implemented'); diff --git a/src/Domain/Repository/Interfaces/PaginatableRepositoryInterface.php b/src/Domain/Repository/Interfaces/PaginatableRepositoryInterface.php index 571971fc..e32706f8 100644 --- a/src/Domain/Repository/Interfaces/PaginatableRepositoryInterface.php +++ b/src/Domain/Repository/Interfaces/PaginatableRepositoryInterface.php @@ -4,12 +4,10 @@ namespace PhpList\Core\Domain\Repository\Interfaces; -use Doctrine\ORM\QueryBuilder; use PhpList\Core\Domain\Filter\FilterRequestInterface; interface PaginatableRepositoryInterface { - public function getAfterId(QueryBuilder $queryBuilder, int $lastId, int $limit): array; public function getFilteredAfterId(int $lastId, int $limit, ?FilterRequestInterface $filter = null): array; public function count(): int; } diff --git a/src/Domain/Repository/Messaging/MessageRepository.php b/src/Domain/Repository/Messaging/MessageRepository.php index 9354e328..c23097ef 100644 --- a/src/Domain/Repository/Messaging/MessageRepository.php +++ b/src/Domain/Repository/Messaging/MessageRepository.php @@ -8,15 +8,10 @@ use PhpList\Core\Domain\Filter\MessageFilter; use PhpList\Core\Domain\Model\Messaging\Message; use PhpList\Core\Domain\Repository\AbstractRepository; -use PhpList\Core\Domain\Repository\CursorPaginationTrait; use PhpList\Core\Domain\Repository\Interfaces\PaginatableRepositoryInterface; class MessageRepository extends AbstractRepository implements PaginatableRepositoryInterface { - use CursorPaginationTrait; - protected ?string $alias = 'm'; - - /** @return Message[] */ public function getByOwnerId(int $ownerId): array { return $this->createQueryBuilder('m') @@ -26,15 +21,21 @@ public function getByOwnerId(int $ownerId): array ->getResult(); } + /** @return Message[] */ public function getFilteredAfterId(int $lastId, int $limit, ?FilterRequestInterface $filter = null): array { - $queryBuilder = $this->createQueryBuilder($this->getAlias());; + $queryBuilder = $this->createQueryBuilder($this->getAlias()); if ($filter instanceof MessageFilter && $filter->getOwner() !== null) { - $queryBuilder->andWhere("IDENTITY({$this->getAlias()}.owner) = :ownerId") + $queryBuilder->andWhere('IDENTITY(m.owner) = :ownerId') ->setParameter('ownerId', $filter->getOwner()->getId()); } - return $this->getAfterId($queryBuilder, $lastId, $limit); + return $queryBuilder->andWhere('m.id > :lastId') + ->setParameter('lastId', $lastId) + ->orderBy('m.id', 'ASC') + ->setMaxResults($limit) + ->getQuery() + ->getResult(); } } diff --git a/src/Domain/Repository/Subscription/SubscriberRepository.php b/src/Domain/Repository/Subscription/SubscriberRepository.php index 8ee0a94e..40190746 100644 --- a/src/Domain/Repository/Subscription/SubscriberRepository.php +++ b/src/Domain/Repository/Subscription/SubscriberRepository.php @@ -4,9 +4,11 @@ namespace PhpList\Core\Domain\Repository\Subscription; +use InvalidArgumentException; +use PhpList\Core\Domain\Filter\FilterRequestInterface; +use PhpList\Core\Domain\Filter\SubscriberFilter; use PhpList\Core\Domain\Model\Subscription\Subscriber; use PhpList\Core\Domain\Repository\AbstractRepository; -use PhpList\Core\Domain\Repository\CursorPaginationTrait; use PhpList\Core\Domain\Repository\Interfaces\PaginatableRepositoryInterface; /** @@ -19,8 +21,6 @@ */ class SubscriberRepository extends AbstractRepository implements PaginatableRepositoryInterface { - use CursorPaginationTrait; - public function findSubscribersBySubscribedList(int $listId): ?Subscriber { return $this->createQueryBuilder('s') @@ -44,6 +44,33 @@ public function getSubscribersBySubscribedListId(int $listId): array ->getResult(); } + /** + * @return Subscriber[] + * @throws InvalidArgumentException + */ + public function getFilteredAfterId(int $lastId, int $limit, ?FilterRequestInterface $filter = null): array + { + if (!$filter instanceof SubscriberFilter) { + throw new InvalidArgumentException('Expected SubscriberFilterRequest.'); + } + + $queryBuilder = $this->createQueryBuilder('s') + ->innerJoin('s.subscriptions', 'subscription') + ->innerJoin('subscription.subscriberList', 'list'); + + if ($filter->getListId() !== null) { + $queryBuilder->where('list.id = :listId') + ->setParameter('listId', $filter->getListId()); + } + + return $queryBuilder->andWhere('s.id > :lastId') + ->setParameter('lastId', $lastId) + ->orderBy('s.id', 'ASC') + ->setMaxResults($limit) + ->getQuery() + ->getResult(); + } + public function findSubscriberWithSubscriptions(int $id): ?Subscriber { return $this->createQueryBuilder('s') diff --git a/tests/Unit/Domain/Repository/CursorPaginationTraitTest.php b/tests/Unit/Domain/Repository/CursorPaginationTraitTest.php index 8aecc019..1639b633 100644 --- a/tests/Unit/Domain/Repository/CursorPaginationTraitTest.php +++ b/tests/Unit/Domain/Repository/CursorPaginationTraitTest.php @@ -39,7 +39,7 @@ public function testGetAfterIdReturnsResults(): void ->method('getResult') ->willReturn($expected); - $result = $this->repo->getAfterId($this->qb, 10, 2); + $result = $this->repo->getAfterId(10, 2); self::assertSame($expected, $result); } diff --git a/tests/Unit/Domain/Repository/DummyRepository.php b/tests/Unit/Domain/Repository/DummyRepository.php index e16b612e..b9b2bfbe 100644 --- a/tests/Unit/Domain/Repository/DummyRepository.php +++ b/tests/Unit/Domain/Repository/DummyRepository.php @@ -18,6 +18,11 @@ public function __construct(private readonly QueryBuilder $queryBuilder) { } + public function getAlias(): string + { + return 'dummy'; + } + /** Doctrine normally injects the QB through $this->createQueryBuilder(). */ protected function createQueryBuilder(string $alias): QueryBuilder {