Skip to content

Commit c904eb7

Browse files
committed
ISSUE-122: deleteLeavingBlacklist
1 parent a5d85bf commit c904eb7

File tree

8 files changed

+515
-14
lines changed

8 files changed

+515
-14
lines changed

config/services/managers.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,3 +71,8 @@ services:
7171
PhpList\Core\Domain\Configuration\Service\Manager\ConfigManager:
7272
autowire: true
7373
autoconfigure: true
74+
75+
PhpList\Core\Domain\Subscription\Service\SubscriberDeletionService:
76+
autowire: true
77+
autoconfigure: true
78+
public: true

config/services/repositories.yml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,3 +85,18 @@ services:
8585
parent: PhpList\Core\Domain\Common\Repository\AbstractRepository
8686
arguments:
8787
- PhpList\Core\Domain\Analytics\Model\UserMessageView
88+
89+
PhpList\Core\Domain\Analytics\Repository\LinkTrackUmlClickRepository:
90+
parent: PhpList\Core\Domain\Common\Repository\AbstractRepository
91+
arguments:
92+
- PhpList\Core\Domain\Analytics\Model\LinkTrackUmlClick
93+
94+
PhpList\Core\Domain\Messaging\Repository\UserMessageRepository:
95+
parent: PhpList\Core\Domain\Common\Repository\AbstractRepository
96+
arguments:
97+
- PhpList\Core\Domain\Messaging\Model\UserMessage
98+
99+
PhpList\Core\Domain\Subscription\Repository\SubscriberHistoryRepository:
100+
parent: PhpList\Core\Domain\Common\Repository\AbstractRepository
101+
arguments:
102+
- PhpList\Core\Domain\Subscription\Model\SubscriberHistory

src/Domain/Messaging/Model/UserMessageBounce.php

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ class UserMessageBounce implements DomainModel, Identity
2525
private ?int $id = null;
2626

2727
#[ORM\Column(name: 'user', type: 'integer')]
28-
private int $user;
28+
private int $userId;
2929

3030
#[ORM\Column(name: 'message', type: 'integer')]
3131
private int $messageId;
@@ -36,8 +36,9 @@ class UserMessageBounce implements DomainModel, Identity
3636
#[ORM\Column(name: 'time', type: 'datetime', options: ['default' => 'CURRENT_TIMESTAMP'])]
3737
private DateTime $createdAt;
3838

39-
public function __construct()
39+
public function __construct(int $bounce)
4040
{
41+
$this->bounce = $bounce;
4142
$this->createdAt = new DateTime();
4243
}
4344

@@ -46,9 +47,9 @@ public function getId(): ?int
4647
return $this->id;
4748
}
4849

49-
public function getUser(): int
50+
public function getUserId(): int
5051
{
51-
return $this->user;
52+
return $this->userId;
5253
}
5354

5455
public function getMessageId(): int
@@ -66,9 +67,9 @@ public function getCreatedAt(): DateTime
6667
return $this->createdAt;
6768
}
6869

69-
public function setUser(int $user): self
70+
public function setUserId(int $userId): self
7071
{
71-
$this->user = $user;
72+
$this->userId = $userId;
7273
return $this;
7374
}
7475

src/Domain/Messaging/Model/UserMessageForward.php

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ class UserMessageForward implements DomainModel, Identity
2323
private ?int $id = null;
2424

2525
#[ORM\Column(name: 'user', type: 'integer')]
26-
private int $user;
26+
private int $userId;
2727

2828
#[ORM\Column(name: 'message', type: 'integer')]
2929
private int $messageId;
@@ -47,9 +47,9 @@ public function getId(): ?int
4747
return $this->id;
4848
}
4949

50-
public function getUser(): int
50+
public function getUserId(): int
5151
{
52-
return $this->user;
52+
return $this->userId;
5353
}
5454

5555
public function getMessageId(): int
@@ -72,9 +72,9 @@ public function getCreatedAt(): DateTime
7272
return $this->createdAt;
7373
}
7474

75-
public function setUser(int $user): self
75+
public function setUserId(int $userId): self
7676
{
77-
$this->user = $user;
77+
$this->userId = $userId;
7878
return $this;
7979
}
8080

src/Domain/Subscription/Service/Manager/SubscriberManager.php

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,23 @@
1010
use PhpList\Core\Domain\Subscription\Model\Dto\UpdateSubscriberDto;
1111
use PhpList\Core\Domain\Subscription\Model\Subscriber;
1212
use PhpList\Core\Domain\Subscription\Repository\SubscriberRepository;
13+
use PhpList\Core\Domain\Subscription\Service\SubscriberDeletionService;
1314
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
1415

1516
class SubscriberManager
1617
{
1718
private SubscriberRepository $subscriberRepository;
1819
private EntityManagerInterface $entityManager;
20+
private SubscriberDeletionService $subscriberDeletionService;
1921

20-
public function __construct(SubscriberRepository $subscriberRepository, EntityManagerInterface $entityManager)
21-
{
22+
public function __construct(
23+
SubscriberRepository $subscriberRepository,
24+
EntityManagerInterface $entityManager,
25+
SubscriberDeletionService $subscriberDeletionService
26+
) {
2227
$this->subscriberRepository = $subscriberRepository;
2328
$this->entityManager = $entityManager;
29+
$this->subscriberDeletionService = $subscriberDeletionService;
2430
}
2531

2632
public function createSubscriber(CreateSubscriberDto $subscriberDto): Subscriber
@@ -68,7 +74,7 @@ public function updateSubscriber(UpdateSubscriberDto $subscriberDto): Subscriber
6874

6975
public function deleteSubscriber(Subscriber $subscriber): void
7076
{
71-
$this->subscriberRepository->remove($subscriber);
77+
$this->subscriberDeletionService->deleteLeavingBlacklist($subscriber);
7278
}
7379

7480
public function createFromImport(ImportSubscriberDto $subscriberDto): Subscriber
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PhpList\Core\Domain\Subscription\Service;
6+
7+
use Doctrine\ORM\EntityManagerInterface;
8+
use PhpList\Core\Domain\Analytics\Repository\LinkTrackUmlClickRepository;
9+
use PhpList\Core\Domain\Analytics\Repository\UserMessageViewRepository;
10+
use PhpList\Core\Domain\Messaging\Repository\UserMessageBounceRepository;
11+
use PhpList\Core\Domain\Messaging\Repository\UserMessageForwardRepository;
12+
use PhpList\Core\Domain\Messaging\Repository\UserMessageRepository;
13+
use PhpList\Core\Domain\Subscription\Model\Subscriber;
14+
use PhpList\Core\Domain\Subscription\Repository\SubscriberAttributeValueRepository;
15+
use PhpList\Core\Domain\Subscription\Repository\SubscriberHistoryRepository;
16+
use PhpList\Core\Domain\Subscription\Repository\SubscriptionRepository;
17+
18+
class SubscriberDeletionService
19+
{
20+
private LinkTrackUmlClickRepository $linkTrackUmlClickRepository;
21+
private EntityManagerInterface $entityManager;
22+
private UserMessageRepository $userMessageRepository;
23+
private SubscriberAttributeValueRepository $subscriberAttributeValueRepository;
24+
private SubscriberHistoryRepository $subscriberHistoryRepository;
25+
private UserMessageBounceRepository $userMessageBounceRepository;
26+
private UserMessageForwardRepository $userMessageForwardRepository;
27+
private UserMessageViewRepository $userMessageViewRepository;
28+
private SubscriptionRepository $subscriptionRepository;
29+
30+
public function __construct(
31+
LinkTrackUmlClickRepository $linkTrackUmlClickRepository,
32+
EntityManagerInterface $entityManager,
33+
UserMessageRepository $userMessageRepository,
34+
SubscriberAttributeValueRepository $subscriberAttributeValueRepository,
35+
SubscriberHistoryRepository $subscriberHistoryRepository,
36+
UserMessageBounceRepository $userMessageBounceRepository,
37+
UserMessageForwardRepository $userMessageForwardRepository,
38+
UserMessageViewRepository $userMessageViewRepository,
39+
SubscriptionRepository $subscriptionRepository
40+
) {
41+
$this->linkTrackUmlClickRepository = $linkTrackUmlClickRepository;
42+
$this->entityManager = $entityManager;
43+
$this->userMessageRepository = $userMessageRepository;
44+
$this->subscriberAttributeValueRepository = $subscriberAttributeValueRepository;
45+
$this->subscriberHistoryRepository = $subscriberHistoryRepository;
46+
$this->userMessageBounceRepository = $userMessageBounceRepository;
47+
$this->userMessageForwardRepository = $userMessageForwardRepository;
48+
$this->userMessageViewRepository = $userMessageViewRepository;
49+
$this->subscriptionRepository = $subscriptionRepository;
50+
}
51+
52+
public function deleteLeavingBlacklist(Subscriber $subscriber): void
53+
{
54+
$linkTrackUmlClick = $this->linkTrackUmlClickRepository->findBy(['userId' => $subscriber->getId()]);
55+
foreach ($linkTrackUmlClick as $click) {
56+
$this->entityManager->remove($click);
57+
}
58+
59+
$subscriptions = $this->subscriptionRepository->findBy(['subscriber' => $subscriber]);
60+
foreach ($subscriptions as $subscription) {
61+
$this->entityManager->remove($subscription);
62+
}
63+
64+
$userMessages = $this->userMessageRepository->findBy(['user' => $subscriber]);
65+
foreach ($userMessages as $message) {
66+
$this->entityManager->remove($message);
67+
}
68+
69+
$subscriberAttributes = $this->subscriberAttributeValueRepository->findBy(['subscriber' => $subscriber]);
70+
foreach ($subscriberAttributes as $attribute) {
71+
$this->entityManager->remove($attribute);
72+
}
73+
74+
$subscriberHistory = $this->subscriberHistoryRepository->findBy(['subscriber' => $subscriber]);
75+
foreach ($subscriberHistory as $history) {
76+
$this->entityManager->remove($history);
77+
}
78+
79+
$userMessageBounces = $this->userMessageBounceRepository->findBy(['userId' => $subscriber->getId()]);
80+
foreach ($userMessageBounces as $bounce) {
81+
$this->entityManager->remove($bounce);
82+
}
83+
84+
$userMessageForwards = $this->userMessageForwardRepository->findBy(['userId' => $subscriber->getId()]);
85+
foreach ($userMessageForwards as $forward) {
86+
$this->entityManager->remove($forward);
87+
}
88+
89+
$userMessageViews = $this->userMessageViewRepository->findBy(['userId' => $subscriber->getId()]);
90+
foreach ($userMessageViews as $view) {
91+
$this->entityManager->remove($view);
92+
}
93+
94+
$this->entityManager->remove($subscriber);
95+
}
96+
}
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PhpList\Core\Tests\Integration\Domain\Subscription\Service;
6+
7+
use Doctrine\ORM\EntityManagerInterface;
8+
use Doctrine\ORM\Tools\SchemaTool;
9+
use Exception;
10+
use PhpList\Core\Domain\Analytics\Model\LinkTrackUmlClick;
11+
use PhpList\Core\Domain\Analytics\Model\UserMessageView;
12+
use PhpList\Core\Domain\Identity\Model\Administrator;
13+
use PhpList\Core\Domain\Messaging\Model\Message;
14+
use PhpList\Core\Domain\Messaging\Model\Message\MessageContent;
15+
use PhpList\Core\Domain\Messaging\Model\Message\MessageFormat;
16+
use PhpList\Core\Domain\Messaging\Model\Message\MessageMetadata;
17+
use PhpList\Core\Domain\Messaging\Model\Message\MessageOptions;
18+
use PhpList\Core\Domain\Messaging\Model\Message\MessageSchedule;
19+
use PhpList\Core\Domain\Messaging\Model\UserMessage;
20+
use PhpList\Core\Domain\Messaging\Model\UserMessageBounce;
21+
use PhpList\Core\Domain\Messaging\Model\UserMessageForward;
22+
use PhpList\Core\Domain\Subscription\Model\Subscriber;
23+
use PhpList\Core\Domain\Subscription\Model\SubscriberList;
24+
use PhpList\Core\Domain\Subscription\Model\Subscription;
25+
use PhpList\Core\Domain\Subscription\Service\SubscriberDeletionService;
26+
use PhpList\Core\TestingSupport\Traits\DatabaseTestTrait;
27+
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
28+
29+
class SubscriberDeletionServiceTest extends KernelTestCase
30+
{
31+
use DatabaseTestTrait;
32+
33+
private ?SubscriberDeletionService $subscriberDeletionService = null;
34+
protected ?EntityManagerInterface $entityManager = null;
35+
36+
protected function setUp(): void
37+
{
38+
parent::setUp();
39+
$this->loadSchema();
40+
41+
$this->subscriberDeletionService = self::getContainer()->get(SubscriberDeletionService::class);
42+
$this->entityManager = self::getContainer()->get(EntityManagerInterface::class);
43+
}
44+
45+
protected function tearDown(): void
46+
{
47+
$schemaTool = new SchemaTool($this->entityManager);
48+
$schemaTool->dropDatabase();
49+
parent::tearDown();
50+
}
51+
52+
public function testDeleteSubscriberWithRelatedDataDoesNotThrowDoctrineError(): void
53+
{
54+
$admin = new Administrator();
55+
$this->entityManager->persist($admin);
56+
57+
$msg = new Message(
58+
new MessageFormat(true, MessageFormat::FORMAT_TEXT),
59+
new MessageSchedule(1, null, 3, null, null),
60+
new MessageMetadata('done'),
61+
new MessageContent('Owned by Admin 1!'),
62+
new MessageOptions(),
63+
$admin
64+
);
65+
$this->entityManager->persist($msg);
66+
67+
$subscriber = new Subscriber();
68+
$subscriber->setEmail('[email protected]');
69+
$subscriber->setConfirmed(true);
70+
$subscriber->setHtmlEmail(true);
71+
$subscriber->setBlacklisted(false);
72+
$subscriber->setDisabled(false);
73+
$this->entityManager->persist($subscriber);
74+
$this->entityManager->flush();
75+
76+
$subscriberId = $subscriber->getId();
77+
$this->assertNotNull($subscriberId, 'Subscriber ID should not be null');
78+
79+
$subscriberList = new SubscriberList();
80+
$subscriberList->setDescription('Test List Description');
81+
$this->entityManager->persist($subscriberList);
82+
83+
$subscription = new Subscription();
84+
$subscription->setSubscriber($subscriber);
85+
$subscription->setSubscriberList($subscriberList);
86+
$this->entityManager->persist($subscription);
87+
88+
$linkTrackUmlClick = new LinkTrackUmlClick();
89+
$linkTrackUmlClick->setMessageId(1);
90+
$linkTrackUmlClick->setUserId($subscriberId);
91+
$this->entityManager->persist($linkTrackUmlClick);
92+
93+
$userMessage = new UserMessage($subscriber, $msg);
94+
$userMessage->setStatus('sent');
95+
$this->entityManager->persist($userMessage);
96+
97+
$userMessageBounce = new UserMessageBounce(1);
98+
$userMessageBounce->setUserId($subscriberId);
99+
$userMessageBounce->setMessageId(1);
100+
$this->entityManager->persist($userMessageBounce);
101+
102+
$userMessageForward = new UserMessageForward();
103+
$userMessageForward->setUserId($subscriberId);
104+
$userMessageForward->setMessageId(1);
105+
$this->entityManager->persist($userMessageForward);
106+
107+
$userMessageView = new UserMessageView();
108+
$userMessageView->setMessageId(1);
109+
$userMessageView->setUserid($subscriberId);
110+
$this->entityManager->persist($userMessageView);
111+
112+
$this->entityManager->flush();
113+
114+
try {
115+
$this->subscriberDeletionService->deleteLeavingBlacklist($subscriber);
116+
$this->entityManager->flush();
117+
$this->assertTrue(true, 'No exception was thrown');
118+
} catch (Exception $e) {
119+
$this->fail('Exception was thrown: ' . $e->getMessage());
120+
}
121+
122+
// Verify the subscriber was deleted
123+
$deletedSubscriber = $this->entityManager->getRepository(Subscriber::class)->find($subscriberId);
124+
$this->assertNull($deletedSubscriber, 'Subscriber should be deleted');
125+
126+
// Verify related entities were deleted
127+
$subscriptions = $this->entityManager->getRepository(Subscription::class)->findBy(['subscriber' => $subscriber]);
128+
$this->assertEmpty($subscriptions, 'Subscriptions should be deleted');
129+
130+
$linkTrackUmlClicks = $this->entityManager->getRepository(LinkTrackUmlClick::class)->findBy(['userId' => $subscriberId]);
131+
$this->assertEmpty($linkTrackUmlClicks, 'LinkTrackUmlClicks should be deleted');
132+
133+
$userMessages = $this->entityManager->getRepository(UserMessage::class)->findBy(['user' => $subscriber]);
134+
$this->assertEmpty($userMessages, 'UserMessages should be deleted');
135+
136+
$userMessageBounces = $this->entityManager->getRepository(UserMessageBounce::class)->findBy(['userId' => $subscriberId]);
137+
$this->assertEmpty($userMessageBounces, 'UserMessageBounces should be deleted');
138+
139+
$userMessageForwards = $this->entityManager->getRepository(UserMessageForward::class)->findBy(['userId' => $subscriberId]);
140+
$this->assertEmpty($userMessageForwards, 'UserMessageForwards should be deleted');
141+
142+
$userMessageViews = $this->entityManager->getRepository(UserMessageView::class)->findBy(['userId' => $subscriberId]);
143+
$this->assertEmpty($userMessageViews, 'UserMessageViews should be deleted');
144+
}
145+
}

0 commit comments

Comments
 (0)