|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
namespace Skobkin\Bundle\PointToolsBundle\Service; |
|
4
|
|
|
|
|
5
|
|
|
use Doctrine\ORM\EntityManager; |
|
6
|
|
|
use Skobkin\Bundle\PointToolsBundle\Entity\Subscription; |
|
7
|
|
|
use Skobkin\Bundle\PointToolsBundle\Entity\SubscriptionEvent; |
|
8
|
|
|
use Skobkin\Bundle\PointToolsBundle\Entity\User; |
|
9
|
|
|
use Skobkin\Bundle\PointToolsBundle\Event\UserSubscribersUpdatedEvent; |
|
10
|
|
|
use Symfony\Component\EventDispatcher\EventDispatcherInterface; |
|
11
|
|
|
|
|
12
|
|
|
class SubscriptionsManager |
|
13
|
|
|
{ |
|
14
|
|
|
/** |
|
15
|
|
|
* @var EntityManager |
|
16
|
|
|
*/ |
|
17
|
|
|
private $em; |
|
18
|
|
|
|
|
19
|
|
|
/** |
|
20
|
|
|
* @var EventDispatcherInterface |
|
21
|
|
|
*/ |
|
22
|
|
|
private $eventDispatcher; |
|
23
|
|
|
|
|
24
|
|
|
|
|
25
|
|
|
public function __construct(EntityManager $entityManager, EventDispatcherInterface $eventDispatcher) |
|
|
|
|
|
|
26
|
|
|
{ |
|
27
|
|
|
$this->em = $entityManager; |
|
28
|
|
|
$this->eventDispatcher = $eventDispatcher; |
|
29
|
|
|
} |
|
30
|
|
|
|
|
31
|
|
|
/** |
|
32
|
|
|
* @param User $user |
|
33
|
|
|
* @param User[] $newSubscribersList |
|
34
|
|
|
*/ |
|
35
|
|
|
public function updateUserSubscribers(User $user, $newSubscribersList = []) |
|
36
|
|
|
{ |
|
37
|
|
|
$tmpOldSubscribers = $user->getSubscribers(); |
|
38
|
|
|
|
|
39
|
|
|
$oldSubscribersList = []; |
|
40
|
|
|
|
|
41
|
|
|
foreach ($tmpOldSubscribers as $subscription) { |
|
|
|
|
|
|
42
|
|
|
$oldSubscribersList[] = $subscription->getSubscriber(); |
|
43
|
|
|
} |
|
44
|
|
|
|
|
45
|
|
|
$subscribedList = $this->getUsersListsDiff($newSubscribersList, $oldSubscribersList); |
|
46
|
|
|
$unsubscribedList = $this->getUsersListsDiff($oldSubscribersList, $newSubscribersList); |
|
47
|
|
|
|
|
48
|
|
|
$this->processSubscribedUsers($user, $subscribedList); |
|
49
|
|
|
$this->processUnsubscribedUsers($user, $unsubscribedList); |
|
50
|
|
|
|
|
51
|
|
|
// Removing users from database |
|
52
|
|
|
// @todo Maybe remove via ORM |
|
53
|
|
|
$this->em->getRepository('SkobkinPointToolsBundle:Subscription')->removeSubscribers($user, $unsubscribedList); |
|
54
|
|
|
|
|
55
|
|
|
$this->dispatchSubscribersUpdatedEvent($user, $subscribedList, $unsubscribedList); |
|
56
|
|
|
} |
|
57
|
|
|
|
|
58
|
|
|
/** |
|
59
|
|
|
* Compares $list1 against $list2 and returns the values in $list1 that are not present in $list2. |
|
60
|
|
|
* |
|
61
|
|
|
* @param User[] $list1 |
|
62
|
|
|
* @param User[] $list2 |
|
63
|
|
|
* |
|
64
|
|
|
* @return User[] |
|
65
|
|
|
*/ |
|
66
|
|
|
public function getUsersListsDiff(array $list1 = [], array $list2 = []): array |
|
67
|
|
|
{ |
|
68
|
|
|
$hash1 = []; |
|
69
|
|
|
$hash2 = []; |
|
70
|
|
|
|
|
71
|
|
|
foreach ($list1 as $user) { |
|
72
|
|
|
$hash1[$user->getId()] = $user; |
|
73
|
|
|
} |
|
74
|
|
|
foreach ($list2 as $user) { |
|
75
|
|
|
$hash2[$user->getId()] = $user; |
|
76
|
|
|
} |
|
77
|
|
|
|
|
78
|
|
|
return array_diff_key($hash1, $hash2); |
|
79
|
|
|
} |
|
80
|
|
|
|
|
81
|
|
|
/** |
|
82
|
|
|
* @param User $user |
|
83
|
|
|
* @param User[] $subscribers |
|
84
|
|
|
*/ |
|
85
|
|
|
private function processSubscribedUsers(User $user, array $subscribers) |
|
86
|
|
|
{ |
|
87
|
|
|
foreach ($subscribers as $subscriber) { |
|
88
|
|
|
$subscription = new Subscription($user, $subscriber); |
|
89
|
|
|
|
|
90
|
|
|
$user->addSubscriber($subscription); |
|
91
|
|
|
$this->em->persist($subscription); |
|
92
|
|
|
|
|
93
|
|
|
$logEvent = new SubscriptionEvent($user, $subscriber, SubscriptionEvent::ACTION_SUBSCRIBE); |
|
94
|
|
|
$this->em->persist($logEvent); |
|
95
|
|
|
|
|
96
|
|
|
$user->addNewSubscriberEvent($logEvent); |
|
97
|
|
|
} |
|
98
|
|
|
} |
|
99
|
|
|
|
|
100
|
|
|
/** |
|
101
|
|
|
* @param User $user |
|
102
|
|
|
* @param User[] $subscribers |
|
103
|
|
|
*/ |
|
104
|
|
|
private function processUnsubscribedUsers(User $user, array $subscribers) |
|
105
|
|
|
{ |
|
106
|
|
|
foreach ($subscribers as $subscriber) { |
|
107
|
|
|
$logEvent = new SubscriptionEvent($user, $subscriber, SubscriptionEvent::ACTION_UNSUBSCRIBE); |
|
108
|
|
|
$this->em->persist($logEvent); |
|
109
|
|
|
|
|
110
|
|
|
$user->addNewSubscriberEvent($logEvent); |
|
111
|
|
|
} |
|
112
|
|
|
} |
|
113
|
|
|
|
|
114
|
|
|
/** |
|
115
|
|
|
* @param User $user |
|
116
|
|
|
* @param User[] $subscribed |
|
117
|
|
|
* @param User[] $unsubscribed |
|
118
|
|
|
*/ |
|
119
|
|
|
private function dispatchSubscribersUpdatedEvent(User $user, array $subscribed, array $unsubscribed) |
|
120
|
|
|
{ |
|
121
|
|
|
if (0 !== count($subscribed) || 0 !== count($unsubscribed)) { |
|
122
|
|
|
// Dispatching event |
|
123
|
|
|
$subscribersUpdatedEvent = new UserSubscribersUpdatedEvent($user, $subscribed, $unsubscribed); |
|
124
|
|
|
$this->eventDispatcher->dispatch(UserSubscribersUpdatedEvent::NAME, $subscribersUpdatedEvent); |
|
125
|
|
|
} |
|
126
|
|
|
} |
|
127
|
|
|
} |
The
EntityManagermight become unusable for example if a transaction is rolled back and it gets closed. Let’s assume that somewhere in your application, or in a third-party library, there is code such as the following:If that code throws an exception and the
EntityManageris closed. Any other code which depends on the same instance of theEntityManagerduring this request will fail.On the other hand, if you instead inject the
ManagerRegistry, thegetManager()method guarantees that you will always get a usable manager instance.