Passed
Branch master (f937f1)
by Burak
05:52
created

MessageService::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace App\Services;
4
5
use App\Interfaces\ContactServiceInterface;
6
use App\Interfaces\MessageServiceInterface;
7
use App\Models\Message;
8
use App\Models\Participant;
9
use App\Models\Thread;
10
use App\Models\User;
11
use App\Notifications\MessageCreated;
12
use App\Notifications\ParticipantCreated;
13
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
14
use Illuminate\Database\Eloquent\ModelNotFoundException;
15
use Illuminate\Support\Collection;
16
use Illuminate\Support\Facades\Notification;
17
18
class MessageService implements MessageServiceInterface
19
{
20
    /**
21
     * @var ContactServiceInterface
22
     */
23
    public ContactServiceInterface $contactService;
24
25
    /**
26
     * MessageService constructor.
27
     * @param ContactServiceInterface $contactService
28
     */
29 9
    public function __construct(ContactServiceInterface $contactService)
30
    {
31 9
        $this->contactService = $contactService;
32 9
    }
33
34
    /**
35
     * All threads that user is participating in.
36
     *
37
     * @param User $user
38
     * @return LengthAwarePaginator
39
     */
40 2
    public function threads(User $user): LengthAwarePaginator
41
    {
42 2
        return Thread::forUser($user->id)->latest('updated_at')->paginate();
43
    }
44
45
    /**
46
     * All threads that user is participating in, with new messages.
47
     *
48
     * @param User $user
49
     * @return Collection
50
     */
51 3
    public function unreadThreads(User $user): Collection
52
    {
53 3
        return Thread::forUserWithNewMessages($user->id)->latest('updated_at')->get();
54
    }
55
56
    /**
57
     * Retrieve a thread.
58
     *
59
     * @param string $thread_id
60
     * @return Thread
61
     * @throws ModelNotFoundException
62
     */
63 4
    public function thread(string $thread_id): Thread
64
    {
65 4
        return Thread::with(['messages', 'participants.user'])->find($thread_id);
0 ignored issues
show
Bug Best Practice introduced by
The expression return App\Models\Thread...er'))->find($thread_id) could return the type null which is incompatible with the type-hinted return App\Models\Thread. Consider adding an additional type-check to rule them out.
Loading history...
66
    }
67
68
    /**
69
     * User ids that are associated with the thread.
70
     *
71
     * @param string $thread_id
72
     * @return Collection
73
     */
74 2
    public function threadParticipants(string $thread_id): Collection
75
    {
76 2
        return Thread::with('participants.user')->find($thread_id)->participants;
0 ignored issues
show
Bug Best Practice introduced by
The property participants does not exist on App\Models\Thread. Since you implemented __get, consider adding a @property annotation.
Loading history...
77
    }
78
79
    /**
80
     * New message thread.
81
     *
82
     * @param string $subject
83
     * @param User $user
84
     * @param array $content
85
     * @param null|array $recipients
86
     * @return Thread
87
     */
88 8
    public function newThread(string $subject, User $user, array $content, ?array $recipients = []): Thread
89
    {
90
        /** @var $thread Thread */
91 8
        $thread = Thread::create([
92 8
            'subject' => $subject,
93
        ]);
94
95
        // Recipients are participants too
96 8
        collect($recipients)
97 8
            ->map(function ($recipient) {
98 4
                return User::find($recipient);
99 8
            })
100 8
            ->filter()
101 8
            ->each(function ($recipient) use ($thread) {
102 4
                $this->addParticipant($thread, $recipient);
103 8
            });
104
105 8
        $this->newMessage($thread, $user, $content);
106
107 8
        return $thread;
108
    }
109
110
    /**
111
     * New message.
112
     *
113
     * @param Thread $thread
114
     * @param User $user
115
     * @param array $content
116
     * @return Message
117
     */
118 9
    public function newMessage(Thread $thread, User $user, array $content): Message
119
    {
120
        $activatedParticipants = $thread
121 9
            ->activateAllParticipants()
122 9
            ->pluck('user_id')
123 9
            ->push($user->id)
124 9
            ->unique()
125 9
            ->toArray();
126
127 9
        $message = Message::create([
128 9
            'thread_id' => $thread->id,
129 9
            'user_id' => $user->id,
130 9
            'body' => $content,
131
        ]);
132
133
        // Make participant if not
134 9
        $this->addParticipant($thread, $user, true);
135
136 9
        $recipients = User::find($activatedParticipants);
137
138 9
        Notification::send($recipients, new MessageCreated($message));
139
140 9
        return $message;
141
    }
142
143
    /**
144
     * Mark as read a tread of a user.
145
     *
146
     * @param Thread $thread
147
     * @param User $user
148
     * @return Participant
149
     */
150 1
    public function markAsRead(Thread $thread, User $user): Participant
151
    {
152 1
        return $thread->markAsRead($user->id);
153
    }
154
155
    /**
156
     * Mark as read all messages of a user.
157
     *
158
     * @param User $user
159
     * @return bool
160
     */
161 1
    public function markAsReadAll(User $user): bool
162
    {
163 1
        return Participant::where([
0 ignored issues
show
Bug Best Practice introduced by
The expression return App\Models\Partic...('last_read' => now())) returns the type integer which is incompatible with the type-hinted return boolean.
Loading history...
164 1
            'user_id' => $user->id,
165 1
        ])->update([
166 1
            'last_read' => now(),
167
        ]);
168
    }
169
170
    /**
171
     * Mark as read all messages of a user.
172
     *
173
     * @param Thread $thread
174
     * @param User $user
175
     * @param bool $mark_as_read
176
     * @return Participant
177
     */
178 9
    public function addParticipant(Thread $thread, User $user, bool $mark_as_read = false): Participant
179
    {
180 9
        $return = $thread->participants()->updateOrCreate([
181 9
            'user_id' => $user->id,
182 9
            'thread_id' => $thread->id,
183
        ],
184 9
            $mark_as_read ? ['last_read' => now()] : []);
185
186 9
        $users = $thread->users()->get();
187
188 9
        $users->each(function ($user) use ($users){
189 9
            $users->each(function ($contact) use ($user){
190 9
                if(!$user->is($contact))
191
                {
192 6
                    $this->contactService->addContact($user, $contact);
193
                }
194 9
            });
195 9
        });
196
197 9
        Notification::send($users, new ParticipantCreated($thread));
198
199 9
        return $return;
200
    }
201
}
202