Passed
Push — 5.0.0 ( 9d1037...fbd7bb )
by Fèvre
05:16
created

BadgeSubscriber::handleNewLeaderboard()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 4
nc 1
nop 1
dl 0
loc 8
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Xetaravel\Listeners\Subscribers;
6
7
use Carbon\Carbon;
8
use Illuminate\Contracts\Queue\ShouldQueueAfterCommit;
9
use Illuminate\Database\Eloquent\Collection;
10
use Illuminate\Events\Dispatcher;
11
use Xetaravel\Events\Badges\ExperienceEvent;
12
use Xetaravel\Events\Badges\LeaderboardEvent;
13
use Xetaravel\Events\Badges\RegisterEvent;
14
use Xetaravel\Events\Blog\CommentWasCreatedEvent;
15
use Xetaravel\Events\Discuss\PostWasCreatedEvent;
16
use Xetaravel\Events\Discuss\PostWasSolvedEvent;
17
use Xetaravel\Models\Badge;
18
use Xetaravel\Models\DiscussPost;
19
use Xetaravel\Models\User;
20
use Xetaravel\Notifications\BadgeNotification;
21
22
class BadgeSubscriber implements ShouldQueueAfterCommit
23
{
24
    /**
25
     * The events mapping to the listener function.
26
     *
27
     * @var array
28
     */
29
    protected array $events = [
30
        CommentWasCreatedEvent::class => 'handleNewComment',
31
        RegisterEvent::class => 'handleNewRegister',
32
        PostWasCreatedEvent::class => 'handleNewPost',
33
        PostWasSolvedEvent::class => 'handleNewPostSolved',
34
        ExperienceEvent::class => 'handleNewExperiences',
35
        LeaderboardEvent::class => 'handleNewLeaderboard'
36
    ];
37
38
    /**
39
     * Send a notification for each new badge unlocked.
40
     *
41
     * @param array $result The result of the synchronization.
42
     * @param Collection $badges The badges collection related to the listener.
43
     * @param User $user The user to notify.
44
     *
45
     * @return bool
46
     */
47
    protected function sendNotifications(array $result, Collection $badges, User $user): bool
48
    {
49
        if (empty($result['attached'])) {
50
            return true;
51
        }
52
53
        $sendNotification = function ($badgeId, $key, $badges) use ($user) {
54
            $badgeCollection = $badges->filter(function ($badge) use ($badgeId) {
55
                return $badge->id === $badgeId;
56
            })->first();
57
58
            $user->notify(new BadgeNotification($badgeCollection));
59
        };
60
61
        return array_walk($result['attached'], $sendNotification, $badges);
62
    }
63
64
    /**
65
     * Register the listeners for the subscriber.
66
     *
67
     * @param Dispatcher $events
68
     *
69
     * @return void
70
     */
71
    public function subscribe(Dispatcher $events): void
72
    {
73
        foreach ($this->events as $event => $action) {
74
            $events->listen($event, self::class . '@' . $action);
75
        }
76
    }
77
78
    /**
79
     * Listener related to the comment badge.
80
     *
81
     * @param CommentWasCreatedEvent $event The event that was fired.
82
     *
83
     * @return bool
84
     */
85
    public function handleNewComment(CommentWasCreatedEvent $event): bool
86
    {
87
        $user = $event->user;
88
        $badges = Badge::where('type', 'onNewComment')->get();
89
90
        $collection = $badges->filter(function ($badge) use ($user) {
91
            return $badge->rule <= $user->blog_comment_count;
92
        });
93
94
        $result = $user->badges()->syncWithoutDetaching($collection);
95
96
        return $this->sendNotifications($result, $badges, $user);
97
    }
98
99
    /**
100
     * Listener related to the posts badge.
101
     *
102
     * @param PostWasCreatedEvent $event The event that was fired.
103
     *
104
     * @return bool
105
     */
106
    public function handleNewPost(PostWasCreatedEvent $event): bool
107
    {
108
        $user = $event->user;
109
        $badges = Badge::where('type', 'onNewPost')->get();
110
111
        $collection = $badges->filter(function ($badge) use ($user) {
112
            return $badge->rule <= $user->discuss_post_count;
113
        });
114
115
        $result = $user->badges()->syncWithoutDetaching($collection);
116
117
        return $this->sendNotifications($result, $badges, $user);
118
    }
119
120
    /**
121
     * Listener related to the post solved badge.
122
     *
123
     * @param PostWasSolvedEvent $event The event that was fired.
124
     *
125
     * @return bool
126
     */
127
    public function handleNewPostSolved(PostWasSolvedEvent $event): bool
128
    {
129
        $user = $event->user;
130
        $badges = Badge::where('type', 'onNewPostSolved')->get();
131
132
        $collection = $badges->filter(function ($badge) use ($user) {
133
            $postsSolved = DiscussPost::where('user_id', $user->id)
134
                    ->where('is_solved', true)
135
                    ->count();
136
137
            return $badge->rule <= $postsSolved;
138
        });
139
140
        $result = $user->badges()->syncWithoutDetaching($collection);
141
142
        return $this->sendNotifications($result, $badges, $user);
143
    }
144
145
    /**
146
     * Listener related to the experiences badge.
147
     *
148
     * @param ExperienceEvent $event The event that was fired.
149
     *
150
     * @return bool
151
     */
152
    public function handleNewExperiences(ExperienceEvent $event): bool
153
    {
154
        $user = $event->user;
155
        $badges = Badge::where('type', 'onNewExperience')->get();
156
157
        $collection = $badges->filter(function ($badge) use ($user) {
158
            return $badge->rule <= $user->experiences_total;
159
        });
160
161
        $result = $user->badges()->syncWithoutDetaching($collection);
162
163
        return $this->sendNotifications($result, $badges, $user);
164
    }
165
166
    /**
167
     * Listener related to the register badge.
168
     *
169
     * @param RegisterEvent $event The event that was fired.
170
     *
171
     * @return bool
172
     */
173
    public function handleNewRegister(RegisterEvent $event): bool
174
    {
175
        $user = $event->user;
176
        $badges = Badge::where('type', 'onNewRegister')->get();
177
178
        $today = new Carbon();
179
        $diff = $today->diff($user->created_at)->y;
180
181
        $collection = $badges->filter(function ($badge) use ($diff) {
182
            return $badge->rule <= $diff;
183
        });
184
185
        $result = $user->badges()->syncWithoutDetaching($collection);
186
187
        return $this->sendNotifications($result, $badges, $user);
188
    }
189
190
    /**
191
     * Listener related to the leaderboard badge.
192
     *
193
     * @param LeaderboardEvent $event The event that was fired.
194
     *
195
     * @return bool
196
     */
197
    public function handleNewLeaderboard(LeaderboardEvent $event): bool
198
    {
199
        $user = $event->user;
200
        $badges = Badge::where('type', 'topLeaderboard')->get();
201
202
        $result = $user->badges()->syncWithoutDetaching($badges);
203
204
        return $this->sendNotifications($result, $badges, $user);
205
    }
206
}
207