SubscriptionsManager::processSubscribedUsers()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 16
ccs 0
cts 11
cp 0
rs 9.7333
c 0
b 0
f 0
cc 2
nc 2
nop 2
crap 6
1
<?php
2
3
namespace Skobkin\Bundle\PointToolsBundle\Service;
4
5
use Psr\Log\LoggerInterface;
6
use Skobkin\Bundle\PointToolsBundle\Entity\{Subscription, SubscriptionEvent, User};
7
use Skobkin\Bundle\PointToolsBundle\Event\UserSubscribersUpdatedEvent;
8
use Skobkin\Bundle\PointToolsBundle\Repository\{SubscriptionEventRepository, SubscriptionRepository};
9
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
10
11
class SubscriptionsManager
12
{
13
    /** @var SubscriptionRepository */
14
    private $subscriptionRepo;
15
16
    /** @var SubscriptionEventRepository */
17
    private $subscriptionRecordRepo;
18
19
    /** @var EventDispatcherInterface */
20
    private $eventDispatcher;
21
22
    /** @var LoggerInterface */
23
    private $logger;
24
25
26
    public function __construct(
27
        EventDispatcherInterface $eventDispatcher,
28
        LoggerInterface $logger,
29
        SubscriptionRepository $subscriptionRepo,
30
        SubscriptionEventRepository $subscriptionRecordRepo
31
    ) {
32
        $this->eventDispatcher = $eventDispatcher;
33
        $this->logger = $logger;
34
        $this->subscriptionRepo = $subscriptionRepo;
0 ignored issues
show
Documentation Bug introduced by
It seems like $subscriptionRepo of type object<Skobkin\Bundle\Po...SubscriptionRepository> is incompatible with the declared type object<SubscriptionRepository> of property $subscriptionRepo.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
35
        $this->subscriptionRecordRepo = $subscriptionRecordRepo;
0 ignored issues
show
Documentation Bug introduced by
It seems like $subscriptionRecordRepo of type object<Skobkin\Bundle\Po...riptionEventRepository> is incompatible with the declared type object<SubscriptionEventRepository> of property $subscriptionRecordRepo.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
36
    }
37
38
    /**
39
     * @param User $user
40
     * @param User[] $newSubscribersList
41
     */
42
    public function updateUserSubscribers(User $user, $newSubscribersList = []): void
43
    {
44
        // @todo optimize
45
        $tmpOldSubscribers = $user->getSubscribers();
46
47
        $oldSubscribersList = [];
48
49
        foreach ($tmpOldSubscribers as $subscription) {
50
            $oldSubscribersList[] = $subscription->getSubscriber();
51
        }
52
53
        $this->logger->debug('Counting user subscribers diff', ['user_id' => $user->getId()]);
54
55
        $subscribedList = $this->getUsersListsDiff($newSubscribersList, $oldSubscribersList);
56
        $unsubscribedList = $this->getUsersListsDiff($oldSubscribersList, $newSubscribersList);
57
58
        $this->logger->debug(sprintf('User has %d subscribed and %d unsubscribed users', count($subscribedList), count($unsubscribedList)));
59
60
        $this->processSubscribedUsers($user, $subscribedList);
61
        $this->processUnsubscribedUsers($user, $unsubscribedList);
62
63
        $this->dispatchSubscribersUpdatedEvent($user, $subscribedList, $unsubscribedList);
64
    }
65
66
    /**
67
     * Compares $list1 against $list2 and returns the values in $list1 that are not present in $list2.
68
     *
69
     * @param User[] $list1
70
     * @param User[] $list2
71
     *
72
     * @return User[]
73
     */
74
    public function getUsersListsDiff(array $list1 = [], array $list2 = []): array
75
    {
76
        $hash1 = [];
77
        $hash2 = [];
78
79
        foreach ($list1 as $user) {
80
            $hash1[$user->getId()] = $user;
81
        }
82
        foreach ($list2 as $user) {
83
            $hash2[$user->getId()] = $user;
84
        }
85
86
        return array_diff_key($hash1, $hash2);
87
    }
88
89
    /**
90
     * @param User $user
91
     * @param User[] $subscribers
92
     */
93
    private function processSubscribedUsers(User $user, array $subscribers): void
94
    {
95
        $this->logger->debug('Processing subscribed users');
96
97
        foreach ($subscribers as $subscriber) {
98
            $subscription = new Subscription($user, $subscriber);
99
100
            $user->addSubscriber($subscription);
101
            $this->subscriptionRepo->add($subscription);
102
103
            $logEvent = new SubscriptionEvent($user, $subscriber, SubscriptionEvent::ACTION_SUBSCRIBE);
104
            $this->subscriptionRecordRepo->add($logEvent);
105
106
            $user->addNewSubscriberEvent($logEvent);
107
        }
108
    }
109
110
    /**
111
     * @param User $user
112
     * @param User[] $subscribers
113
     */
114
    private function processUnsubscribedUsers(User $user, array $subscribers): void
115
    {
116
        $this->logger->debug('Processing unsubscribed users');
117
118
        foreach ($subscribers as $subscriber) {
119
            $logEvent = new SubscriptionEvent($user, $subscriber, SubscriptionEvent::ACTION_UNSUBSCRIBE);
120
            $this->subscriptionRecordRepo->add($logEvent);
121
122
            $user->addNewSubscriberEvent($logEvent);
123
        }
124
125
        // Removing users from database
126
        // @todo Refactor to collection usage (after dealing with orphanRemoval bug)
127
        $this->subscriptionRepo->removeSubscribers($user, $subscribers);
128
    }
129
130
    /**
131
     * @param User $user
132
     * @param User[] $subscribed
133
     * @param User[] $unsubscribed
134
     */
135
    private function dispatchSubscribersUpdatedEvent(User $user, array $subscribed, array $unsubscribed): void
136
    {
137
        if (0 !== count($subscribed) || 0 !== count($unsubscribed)) {
138
            // Dispatching event
139
            $subscribersUpdatedEvent = new UserSubscribersUpdatedEvent($user, $subscribed, $unsubscribed);
140
            $this->eventDispatcher->dispatch(UserSubscribersUpdatedEvent::NAME, $subscribersUpdatedEvent);
141
        }
142
    }
143
}