|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
namespace Skobkin\Bundle\PointToolsBundle\Service; |
|
4
|
|
|
|
|
5
|
|
|
use Doctrine\ORM\EntityManager; |
|
6
|
|
|
use Doctrine\ORM\QueryBuilder; |
|
7
|
|
|
use Skobkin\Bundle\PointToolsBundle\Entity\Subscription; |
|
8
|
|
|
use Skobkin\Bundle\PointToolsBundle\Entity\SubscriptionEvent; |
|
9
|
|
|
use Skobkin\Bundle\PointToolsBundle\Entity\User; |
|
10
|
|
|
|
|
11
|
|
|
class SubscriptionsManager |
|
12
|
|
|
{ |
|
13
|
|
|
/** |
|
14
|
|
|
* @var EntityManager |
|
15
|
|
|
*/ |
|
16
|
|
|
protected $em; |
|
17
|
|
|
|
|
18
|
|
|
|
|
19
|
|
|
// @todo Add logger |
|
20
|
|
|
public function __construct(EntityManager $entityManager) |
|
|
|
|
|
|
21
|
|
|
{ |
|
22
|
|
|
$this->em = $entityManager; |
|
23
|
|
|
} |
|
24
|
|
|
|
|
25
|
|
|
/** |
|
26
|
|
|
* @param User $user |
|
27
|
|
|
* @param User[]|array $newSubscribersList |
|
28
|
|
|
*/ |
|
29
|
|
|
public function updateUserSubscribers(User $user, $newSubscribersList = []) |
|
30
|
|
|
{ |
|
31
|
|
|
/** @var Subscription[] $tmpOldSubscribers */ |
|
32
|
|
|
$tmpOldSubscribers = $user->getSubscribers(); |
|
33
|
|
|
|
|
34
|
|
|
$oldSubscribersList = []; |
|
35
|
|
|
|
|
36
|
|
|
foreach ($tmpOldSubscribers as $subscription) { |
|
37
|
|
|
$oldSubscribersList[] = $subscription->getSubscriber(); |
|
38
|
|
|
} |
|
39
|
|
|
|
|
40
|
|
|
$isFirstTime = false; |
|
41
|
|
|
|
|
42
|
|
|
// Preventing to add garbage subscriptions for first processing |
|
43
|
|
|
// @todo improve algorithm |
|
44
|
|
|
if ((count($oldSubscribersList) === 0) && (count($newSubscribersList) > 1)) { |
|
45
|
|
|
$isFirstTime = true; |
|
46
|
|
|
} |
|
47
|
|
|
|
|
48
|
|
|
unset($tmpOldSubscribers); |
|
49
|
|
|
|
|
50
|
|
|
$subscribedList = $this->getUsersListsDiff($newSubscribersList, $oldSubscribersList); |
|
51
|
|
|
$unsubscribedList = $this->getUsersListsDiff($oldSubscribersList, $newSubscribersList); |
|
52
|
|
|
|
|
53
|
|
|
/** @var User $subscribedUser */ |
|
54
|
|
|
foreach ($subscribedList as $subscribedUser) { |
|
55
|
|
|
$subscription = new Subscription($user, $subscribedUser); |
|
56
|
|
|
|
|
57
|
|
|
$user->addSubscriber($subscription); |
|
58
|
|
|
$this->em->persist($subscription); |
|
59
|
|
|
|
|
60
|
|
|
// If it's not first processing |
|
61
|
|
|
if (!$isFirstTime) { |
|
62
|
|
|
$logEvent = new SubscriptionEvent($user, $subscribedUser, SubscriptionEvent::ACTION_SUBSCRIBE); |
|
63
|
|
|
$this->em->persist($logEvent); |
|
64
|
|
|
|
|
65
|
|
|
$user->addNewSubscriberEvent($logEvent); |
|
66
|
|
|
} |
|
67
|
|
|
} |
|
68
|
|
|
|
|
69
|
|
|
unset($subscribedList); |
|
70
|
|
|
|
|
71
|
|
|
/** @var QueryBuilder $unsubscribedQuery */ |
|
72
|
|
|
$unsubscribedQuery = $this->em->getRepository('SkobkinPointToolsBundle:Subscription')->createQueryBuilder('s'); |
|
73
|
|
|
$unsubscribedQuery |
|
74
|
|
|
->delete() |
|
75
|
|
|
->where('s.author = :author') |
|
76
|
|
|
->andWhere('s.subscriber IN (:subscribers)') |
|
77
|
|
|
; |
|
78
|
|
|
|
|
79
|
|
|
/** @var User $unsubscribedUser */ |
|
80
|
|
|
foreach ($unsubscribedList as $unsubscribedUser) { |
|
81
|
|
|
$logEvent = new SubscriptionEvent($user, $unsubscribedUser, SubscriptionEvent::ACTION_UNSUBSCRIBE); |
|
82
|
|
|
$this->em->persist($logEvent); |
|
83
|
|
|
|
|
84
|
|
|
$user->addNewSubscriberEvent($logEvent); |
|
85
|
|
|
} |
|
86
|
|
|
|
|
87
|
|
|
$unsubscribedQuery |
|
88
|
|
|
->setParameter('author', $user->getId()) |
|
89
|
|
|
->setParameter('subscribers', $unsubscribedList) |
|
90
|
|
|
->getQuery()->execute(); |
|
91
|
|
|
; |
|
92
|
|
|
|
|
93
|
|
|
unset($unsubscribedList); |
|
94
|
|
|
} |
|
95
|
|
|
|
|
96
|
|
|
/** |
|
97
|
|
|
* Compares $list1 against $list2 and returns the values in $list1 that are not present in $list2. |
|
98
|
|
|
* |
|
99
|
|
|
* @param User[] $list1 |
|
100
|
|
|
* @param User[] $list2 |
|
101
|
|
|
* |
|
102
|
|
|
* @return User[] Diff |
|
103
|
|
|
*/ |
|
104
|
|
|
public function getUsersListsDiff(array $list1 = [], array $list2 = []) |
|
105
|
|
|
{ |
|
106
|
|
|
$hash1 = []; |
|
107
|
|
|
$hash2 = []; |
|
108
|
|
|
|
|
109
|
|
|
foreach ($list1 as $user) { |
|
110
|
|
|
$hash1[$user->getId()] = $user; |
|
111
|
|
|
} |
|
112
|
|
|
foreach ($list2 as $user) { |
|
113
|
|
|
$hash2[$user->getId()] = $user; |
|
114
|
|
|
} |
|
115
|
|
|
|
|
116
|
|
|
return array_diff_key($hash1, $hash2); |
|
117
|
|
|
} |
|
118
|
|
|
} |
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.