|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
/** |
|
4
|
|
|
* This file is part of Friends. |
|
5
|
|
|
* |
|
6
|
|
|
* (c) Christopher Lass <[email protected]> |
|
7
|
|
|
* |
|
8
|
|
|
* For the full copyright and license information, please view the LICENSE |
|
9
|
|
|
* file that was distributed with this source code. |
|
10
|
|
|
*/ |
|
11
|
|
|
namespace Arubacao\Friends\Traits; |
|
12
|
|
|
|
|
13
|
|
|
use Arubacao\Friends\Status; |
|
14
|
|
|
use Illuminate\Support\Facades\Config; |
|
15
|
|
|
|
|
16
|
|
|
trait Friendable |
|
17
|
|
|
{ |
|
18
|
|
|
/** |
|
19
|
|
|
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany |
|
20
|
|
|
*/ |
|
21
|
22 |
View Code Duplication |
public function friends_i_am_sender() |
|
|
|
|
|
|
22
|
|
|
{ |
|
23
|
22 |
|
return $this->belongsToMany( |
|
|
|
|
|
|
24
|
22 |
|
Config::get('friends.user_model'), |
|
25
|
22 |
|
'friends', |
|
26
|
22 |
|
'sender_id', 'recipient_id') |
|
27
|
22 |
|
->withTimestamps() |
|
28
|
22 |
|
->withPivot([ |
|
29
|
22 |
|
'status', |
|
30
|
22 |
|
]) |
|
31
|
22 |
|
->orderBy('updated_at', 'desc'); |
|
32
|
|
|
} |
|
33
|
|
|
|
|
34
|
|
|
/** |
|
35
|
|
|
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany |
|
36
|
|
|
*/ |
|
37
|
22 |
View Code Duplication |
public function friends_i_am_recipient() |
|
|
|
|
|
|
38
|
|
|
{ |
|
39
|
22 |
|
return $this->belongsToMany( |
|
|
|
|
|
|
40
|
22 |
|
Config::get('friends.user_model'), |
|
41
|
22 |
|
'friends', |
|
42
|
22 |
|
'recipient_id', 'sender_id') |
|
43
|
22 |
|
->withTimestamps() |
|
44
|
22 |
|
->withPivot([ |
|
45
|
22 |
|
'status', |
|
46
|
22 |
|
]) |
|
47
|
22 |
|
->orderBy('updated_at', 'desc'); |
|
48
|
|
|
} |
|
49
|
|
|
|
|
50
|
|
|
/** |
|
51
|
|
|
* @return \Illuminate\Database\Eloquent\Builder |
|
52
|
|
|
*/ |
|
53
|
1 |
|
public function scopeIncludeRelationshipsWith($query, $user) |
|
54
|
|
|
{ |
|
55
|
1 |
|
$userId = $this->retrieveUserId($user); |
|
56
|
|
|
|
|
57
|
1 |
|
return $query->with([ |
|
58
|
|
|
'friends_i_am_sender' => function ($queryIn) use ($userId) { |
|
59
|
1 |
|
$queryIn->where('recipient_id', $userId) |
|
60
|
1 |
|
->get(); |
|
61
|
1 |
|
}, |
|
62
|
|
|
'friends_i_am_recipient' => function ($queryIn) use ($userId) { |
|
63
|
1 |
|
$queryIn->where('sender_id', $userId) |
|
64
|
1 |
|
->get(); |
|
65
|
1 |
|
}, |
|
66
|
1 |
|
]); |
|
67
|
|
|
} |
|
68
|
|
|
|
|
69
|
|
|
/** |
|
70
|
|
|
* @return \Illuminate\Database\Eloquent\Collection |
|
71
|
|
|
*/ |
|
72
|
10 |
|
public function friends() |
|
73
|
|
|
{ |
|
74
|
10 |
|
$me = $this->with([ |
|
|
|
|
|
|
75
|
|
|
'friends_i_am_sender' => function ($query) { |
|
76
|
10 |
|
$query->where('status', Status::ACCEPTED) |
|
77
|
10 |
|
->get(); |
|
78
|
10 |
|
}, |
|
79
|
|
|
'friends_i_am_recipient' => function ($query) { |
|
80
|
10 |
|
$query->where('status', Status::ACCEPTED) |
|
81
|
10 |
|
->get(); |
|
82
|
10 |
|
}, |
|
83
|
10 |
|
]) |
|
84
|
10 |
|
->where('id', '=', $this->getKey()) |
|
|
|
|
|
|
85
|
10 |
|
->first(); |
|
86
|
|
|
|
|
87
|
10 |
|
$friends = $this->mergedFriends($me); |
|
88
|
|
|
|
|
89
|
10 |
|
return $friends; |
|
90
|
|
|
} |
|
91
|
|
|
|
|
92
|
|
|
/** |
|
93
|
|
|
* @return \Illuminate\Database\Eloquent\Collection |
|
94
|
|
|
*/ |
|
95
|
2 |
View Code Duplication |
public function incoming_friends() |
|
|
|
|
|
|
96
|
|
|
{ |
|
97
|
2 |
|
$me = $this->with([ |
|
|
|
|
|
|
98
|
2 |
|
'friends_i_am_recipient' => function ($query) { |
|
99
|
2 |
|
$query->where('status', Status::PENDING) |
|
100
|
2 |
|
->get(); |
|
101
|
2 |
|
}, |
|
102
|
2 |
|
]) |
|
103
|
2 |
|
->where('id', '=', $this->getKey()) |
|
|
|
|
|
|
104
|
2 |
|
->first(); |
|
105
|
|
|
|
|
106
|
2 |
|
return $me->friends_i_am_recipient; |
|
107
|
|
|
} |
|
108
|
|
|
|
|
109
|
|
|
/** |
|
110
|
|
|
* @return \Illuminate\Database\Eloquent\Collection |
|
111
|
|
|
*/ |
|
112
|
11 |
View Code Duplication |
public function any_friends() |
|
|
|
|
|
|
113
|
|
|
{ |
|
114
|
11 |
|
$me = $this->with([ |
|
|
|
|
|
|
115
|
11 |
|
'friends_i_am_sender', |
|
116
|
11 |
|
'friends_i_am_recipient', |
|
117
|
11 |
|
]) |
|
118
|
11 |
|
->where('id', '=', $this->getKey()) |
|
|
|
|
|
|
119
|
11 |
|
->first(); |
|
120
|
|
|
|
|
121
|
11 |
|
$any_friends = $this->mergedFriends($me); |
|
122
|
|
|
|
|
123
|
11 |
|
return $any_friends; |
|
124
|
|
|
} |
|
125
|
|
|
|
|
126
|
|
|
/** |
|
127
|
|
|
* Alias to eloquent many-to-many relation's attach() method. |
|
128
|
|
|
* |
|
129
|
|
|
* @param int|User $user |
|
130
|
|
|
* @return bool |
|
131
|
|
|
*/ |
|
132
|
21 |
|
public function sendFriendRequestTo($user) |
|
133
|
|
|
{ |
|
134
|
21 |
|
$userId = $this->retrieveUserId($user); |
|
135
|
|
|
|
|
136
|
21 |
|
if ($userId == $this->getKey()) { |
|
|
|
|
|
|
137
|
|
|
// Method not allowed on self |
|
138
|
1 |
|
return false; |
|
139
|
|
|
} |
|
140
|
|
|
|
|
141
|
20 |
|
$relationship = $this->getRelationshipWith($userId, [ |
|
142
|
20 |
|
Status::PENDING, |
|
143
|
20 |
|
Status::ACCEPTED, |
|
144
|
20 |
|
]); |
|
145
|
|
|
|
|
146
|
20 |
|
if (! is_null($relationship)) { |
|
147
|
4 |
|
if ($relationship->pivot->status === Status::ACCEPTED) { |
|
148
|
|
|
// Already friends |
|
149
|
|
|
return false; |
|
150
|
|
|
} |
|
151
|
4 |
|
if ($relationship->pivot->status == Status::PENDING && |
|
152
|
4 |
|
$relationship->pivot->recipient_id == $this->getKey()) { |
|
|
|
|
|
|
153
|
|
|
// Recipient already sent a friend request |
|
154
|
|
|
// Accept pending friend request |
|
155
|
1 |
|
$relationship->pivot->status = Status::ACCEPTED; |
|
156
|
1 |
|
$relationship->pivot->save(); |
|
157
|
|
|
/* @todo: fire event friend request accepted */ |
|
158
|
1 |
|
$this->reload(); |
|
159
|
|
|
|
|
160
|
1 |
|
return true; |
|
161
|
|
|
} |
|
162
|
|
|
|
|
163
|
3 |
|
return false; |
|
164
|
|
|
} |
|
165
|
|
|
|
|
166
|
20 |
|
$this->friends_i_am_sender()->attach($userId, [ |
|
167
|
20 |
|
'status' => Status::PENDING, |
|
168
|
20 |
|
]); |
|
169
|
|
|
/* @todo: fire event friend request sent */ |
|
170
|
|
|
|
|
171
|
20 |
|
$this->reload(); |
|
172
|
|
|
|
|
173
|
20 |
|
return true; |
|
174
|
|
|
} |
|
175
|
|
|
|
|
176
|
|
|
/** |
|
177
|
|
|
* @param int|User $user |
|
178
|
|
|
* @return bool |
|
179
|
|
|
*/ |
|
180
|
14 |
View Code Duplication |
public function acceptFriendRequestFrom($user) |
|
|
|
|
|
|
181
|
|
|
{ |
|
182
|
14 |
|
$userId = $this->retrieveUserId($user); |
|
183
|
|
|
|
|
184
|
14 |
|
if ($userId == $this->getKey()) { |
|
|
|
|
|
|
185
|
|
|
// Method not allowed on self |
|
186
|
|
|
return false; |
|
187
|
|
|
} |
|
188
|
|
|
|
|
189
|
14 |
|
$relationship = $this->getPendingRequestFrom($userId); |
|
190
|
|
|
|
|
191
|
14 |
|
if (! is_null($relationship)) { |
|
192
|
13 |
|
$relationship->pivot->status = Status::ACCEPTED; |
|
193
|
13 |
|
$relationship->pivot->save(); |
|
194
|
|
|
/* @todo: fire event friend request accepted */ |
|
195
|
13 |
|
$this->reload(); |
|
196
|
|
|
|
|
197
|
13 |
|
return true; |
|
198
|
|
|
} |
|
199
|
|
|
|
|
200
|
1 |
|
return false; |
|
201
|
|
|
} |
|
202
|
|
|
|
|
203
|
|
|
/** |
|
204
|
|
|
* @param int|User $user |
|
205
|
|
|
* @return bool |
|
206
|
|
|
*/ |
|
207
|
2 |
View Code Duplication |
public function denyFriendRequestFrom($user) |
|
|
|
|
|
|
208
|
|
|
{ |
|
209
|
2 |
|
$userId = $this->retrieveUserId($user); |
|
210
|
|
|
|
|
211
|
2 |
|
if ($userId == $this->getKey()) { |
|
|
|
|
|
|
212
|
|
|
// Method not allowed on self |
|
213
|
|
|
return false; |
|
214
|
|
|
} |
|
215
|
|
|
|
|
216
|
2 |
|
$relationship = $this->getPendingRequestFrom($userId); |
|
217
|
|
|
|
|
218
|
2 |
|
if (! is_null($relationship)) { |
|
219
|
2 |
|
$relationship->pivot->delete(); |
|
220
|
|
|
/* @todo: fire event friend request denied */ |
|
221
|
2 |
|
$this->reload(); |
|
222
|
|
|
|
|
223
|
2 |
|
return true; |
|
224
|
|
|
} |
|
225
|
|
|
|
|
226
|
|
|
return false; |
|
227
|
|
|
} |
|
228
|
|
|
|
|
229
|
|
|
/** |
|
230
|
|
|
* @param int|User $user |
|
231
|
|
|
* @return bool |
|
232
|
|
|
*/ |
|
233
|
1 |
|
public function deleteFriend($user) |
|
234
|
|
|
{ |
|
235
|
1 |
|
$userId = $this->retrieveUserId($user); |
|
236
|
|
|
|
|
237
|
1 |
|
if ($userId == $this->getKey()) { |
|
|
|
|
|
|
238
|
|
|
// Method not allowed on self |
|
239
|
|
|
return false; |
|
240
|
|
|
} |
|
241
|
|
|
|
|
242
|
1 |
|
while ($relationship = $this->getRelationshipWith($userId, [ |
|
243
|
1 |
|
Status::ACCEPTED, |
|
244
|
1 |
|
Status::PENDING, |
|
245
|
1 |
|
])) { |
|
246
|
1 |
|
$relationship->pivot->delete(); |
|
247
|
|
|
/* @todo: fire event friend deleted */ |
|
248
|
1 |
|
} |
|
249
|
1 |
|
$this->reload(); |
|
250
|
|
|
|
|
251
|
1 |
|
return true; |
|
252
|
|
|
} |
|
253
|
|
|
|
|
254
|
|
|
/** |
|
255
|
|
|
* @param int|array|User $user |
|
256
|
|
|
* @return bool |
|
257
|
|
|
*/ |
|
258
|
2 |
|
public function isFriendWith($user) |
|
259
|
|
|
{ |
|
260
|
2 |
|
$userId = $this->retrieveUserId($user); |
|
261
|
|
|
|
|
262
|
2 |
|
return $this->hasRelationshipWith($userId, [Status::ACCEPTED]); |
|
263
|
|
|
} |
|
264
|
|
|
|
|
265
|
|
|
/** |
|
266
|
|
|
* @param int|array|User $user |
|
267
|
|
|
* @param array $status |
|
268
|
|
|
* @return bool |
|
269
|
|
|
*/ |
|
270
|
2 |
|
public function hasRelationshipWith($user, $status) |
|
271
|
|
|
{ |
|
272
|
2 |
|
$userId = $this->retrieveUserId($user); |
|
273
|
|
|
|
|
274
|
2 |
|
$relationship = $this->getRelationshipWith($userId, $status); |
|
275
|
|
|
|
|
276
|
2 |
|
return (is_null($relationship)) ? false : true; |
|
277
|
|
|
} |
|
278
|
|
|
|
|
279
|
|
|
/** |
|
280
|
|
|
* @param int|array|User $user |
|
281
|
|
|
* @param array $status |
|
282
|
|
|
* @return mixed |
|
283
|
|
|
*/ |
|
284
|
20 |
|
public function getRelationshipWith($user, $status) |
|
285
|
|
|
{ |
|
286
|
20 |
|
$userId = $this->retrieveUserId($user); |
|
287
|
|
|
|
|
288
|
20 |
|
if ($userId == $this->getKey()) { |
|
|
|
|
|
|
289
|
|
|
// Method not allowed on self |
|
290
|
|
|
return; |
|
291
|
|
|
} |
|
292
|
|
|
|
|
293
|
20 |
|
$attempt1 = $this->friends_i_am_recipient() |
|
294
|
20 |
|
->wherePivotIn('status', $status) |
|
295
|
20 |
|
->wherePivot('sender_id', $userId) |
|
296
|
20 |
|
->first(); |
|
297
|
|
|
|
|
298
|
20 |
|
if (! is_null($attempt1)) { |
|
299
|
3 |
|
return $attempt1; |
|
300
|
|
|
} |
|
301
|
|
|
|
|
302
|
20 |
|
$attempt2 = $this->friends_i_am_sender() |
|
303
|
20 |
|
->wherePivotIn('status', $status) |
|
304
|
20 |
|
->wherePivot('recipient_id', $userId) |
|
305
|
20 |
|
->first(); |
|
306
|
|
|
|
|
307
|
20 |
|
if (! is_null($attempt2)) { |
|
308
|
4 |
|
return $attempt2; |
|
309
|
|
|
} |
|
310
|
20 |
|
} |
|
311
|
|
|
|
|
312
|
|
|
/** |
|
313
|
|
|
* @param int|array|User $user |
|
314
|
|
|
* @return bool |
|
315
|
|
|
*/ |
|
316
|
4 |
|
public function hasPendingRequestFrom($user) |
|
317
|
|
|
{ |
|
318
|
4 |
|
$userId = $this->retrieveUserId($user); |
|
319
|
|
|
|
|
320
|
4 |
|
if ($userId == $this->getKey()) { |
|
|
|
|
|
|
321
|
|
|
// Method not allowed on self |
|
322
|
|
|
return false; |
|
323
|
|
|
} |
|
324
|
|
|
|
|
325
|
4 |
|
$relationship = $this->getPendingRequestFrom($userId); |
|
326
|
|
|
|
|
327
|
4 |
|
if (! is_null($relationship)) { |
|
328
|
2 |
|
return true; |
|
329
|
|
|
} |
|
330
|
|
|
|
|
331
|
4 |
|
return false; |
|
332
|
|
|
} |
|
333
|
|
|
|
|
334
|
|
|
/** |
|
335
|
|
|
* @param int|array|User $user |
|
336
|
|
|
* @return int|null |
|
337
|
|
|
*/ |
|
338
|
25 |
|
private function retrieveUserId($user) |
|
339
|
|
|
{ |
|
340
|
25 |
|
if (is_object($user)) { |
|
341
|
23 |
|
return $user->getKey(); |
|
342
|
|
|
} |
|
343
|
22 |
|
if (is_array($user) && isset($user['id'])) { |
|
344
|
1 |
|
return $user['id']; |
|
345
|
|
|
} |
|
346
|
|
|
|
|
347
|
21 |
|
return $user; |
|
348
|
|
|
} |
|
349
|
|
|
|
|
350
|
|
|
/** |
|
351
|
|
|
* @param int $userId |
|
352
|
|
|
* @return mixed |
|
353
|
|
|
*/ |
|
354
|
17 |
|
private function getPendingRequestFrom($userId) |
|
355
|
|
|
{ |
|
356
|
17 |
|
return $this->friends_i_am_recipient() |
|
357
|
17 |
|
->wherePivot('status', Status::PENDING) |
|
358
|
17 |
|
->wherePivot('sender_id', $userId) |
|
359
|
17 |
|
->first(); |
|
360
|
|
|
} |
|
361
|
|
|
|
|
362
|
|
|
/** |
|
363
|
|
|
* Eager load relations on the model. |
|
364
|
|
|
*/ |
|
365
|
20 |
|
private function reload() |
|
366
|
|
|
{ |
|
367
|
20 |
|
$this->load('friends_i_am_recipient', 'friends_i_am_sender'); |
|
|
|
|
|
|
368
|
20 |
|
} |
|
369
|
|
|
|
|
370
|
|
|
/** |
|
371
|
|
|
* @param User $me |
|
372
|
|
|
* @return \Illuminate\Database\Eloquent\Collection |
|
373
|
|
|
*/ |
|
374
|
18 |
|
private function mergedFriends($me) |
|
375
|
|
|
{ |
|
376
|
18 |
|
$friends = collect([]); |
|
377
|
18 |
|
$friends->push($me->friends_i_am_sender); |
|
378
|
18 |
|
$friends->push($me->friends_i_am_recipient); |
|
379
|
18 |
|
$friends = $friends->flatten(); |
|
380
|
|
|
|
|
381
|
18 |
|
return $friends; |
|
382
|
|
|
} |
|
383
|
|
|
} |
|
384
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.