Test Failed
Push — master ( 7405ac...f937f1 )
by Burak
05:02
created

MessageService::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 1
c 0
b 0
f 0
nc 1
nop 1
dl 0
loc 3
ccs 0
cts 2
cp 0
crap 2
rs 10
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
    public function __construct(ContactServiceInterface $contactService)
30
    {
31
        $this->contactService = $contactService;
32
    }
33
34
    /**
35
     * All threads that user is participating in.
36
     *
37
     * @param User $user
38
     * @return LengthAwarePaginator
39
     */
40
    public function threads(User $user): LengthAwarePaginator
41
    {
42
        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
    public function unreadThreads(User $user): Collection
52
    {
53
        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
    public function thread(string $thread_id): Thread
64
    {
65
        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
    public function threadParticipants(string $thread_id): Collection
75
    {
76
        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
    public function newThread(string $subject, User $user, array $content, ?array $recipients = []): Thread
89
    {
90
        /** @var $thread Thread */
91
        $thread = Thread::create([
92
            'subject' => $subject,
93
        ]);
94
95
        // Recipients are participants too
96
        collect($recipients)
97
            ->map(function ($recipient) {
98
                return User::find($recipient);
99
            })
100
            ->filter()
101
            ->each(function ($recipient) use ($thread) {
102
                $this->addParticipant($thread, $recipient);
103
            });
104
105
        $this->newMessage($thread, $user, $content);
106
107
        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
    public function newMessage(Thread $thread, User $user, array $content): Message
119
    {
120
        $activatedParticipants = $thread
121
            ->activateAllParticipants()
122
            ->pluck('user_id')
123
            ->push($user->id)
124
            ->unique()
125
            ->toArray();
126
127
        $message = Message::create([
128
            'thread_id' => $thread->id,
129
            'user_id' => $user->id,
130
            'body' => $content,
131
        ]);
132
133
        // Make participant if not
134
        $this->addParticipant($thread, $user, true);
135
136
        $recipients = User::find($activatedParticipants);
137
138
        Notification::send($recipients, new MessageCreated($message));
139
140
        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
    public function markAsRead(Thread $thread, User $user): Participant
151
    {
152
        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
    public function markAsReadAll(User $user): bool
162
    {
163
        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
            'user_id' => $user->id,
165
        ])->update([
166
            '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
    public function addParticipant(Thread $thread, User $user, bool $mark_as_read = false): Participant
179
    {
180
        $return = $thread->participants()->updateOrCreate([
181
            'user_id' => $user->id,
182
            'thread_id' => $thread->id,
183
        ],
184
            $mark_as_read ? ['last_read' => now()] : []);
185
186
        $users = $thread->users()->get();
187
188
        $users->each(function ($user) use ($users){
189
            $users->each(function ($contact) use ($user){
190
                if(!$user->is($contact))
191
                {
192
                    $this->contactService->addContact($user, $contact);
193
                }
194
            });
195
        });
196
197
        Notification::send($users, new ParticipantCreated($thread));
198
199
        return $return;
200
    }
201
}
202