Skip to content

Commit b8404df

Browse files
committed
Automatically subscribe users when replying
Also refactor the internals of subscriptions to an interface and move some of the logic.
1 parent 308afc1 commit b8404df

File tree

11 files changed

+90
-61
lines changed

11 files changed

+90
-61
lines changed
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php
2+
3+
namespace App\Helpers;
4+
5+
use App\User;
6+
use App\Models\Subscription;
7+
use Illuminate\Database\Eloquent\Relations\MorphMany;
8+
9+
trait ProvidesSubscriptions
10+
{
11+
/**
12+
* @return \App\Models\Subscription[]
13+
*/
14+
public function subscriptions()
15+
{
16+
return $this->subscriptionsRelation;
17+
}
18+
19+
public function subscriptionsRelation(): MorphMany
20+
{
21+
return $this->morphMany(Subscription::class, 'subscriptionable');
22+
}
23+
24+
public function hasSubscriber(User $user): bool
25+
{
26+
return $this->subscriptionsRelation()
27+
->where('user_id', $user->id())
28+
->exists();
29+
}
30+
}

app/Helpers/ReceivesReplies.php

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
namespace App\Helpers;
44

55
use App\Models\Reply;
6-
use App\Models\Subscription;
76
use Illuminate\Database\Eloquent\Relations\MorphMany;
87

98
trait ReceivesReplies
@@ -33,17 +32,4 @@ public function repliesRelation(): MorphMany
3332
{
3433
return $this->morphMany(Reply::class, 'replyable');
3534
}
36-
37-
/**
38-
* @return \App\Models\Subscription[]
39-
*/
40-
public function subscriptions()
41-
{
42-
return $this->subscriptionsRelation;
43-
}
44-
45-
public function subscriptionsRelation(): MorphMany
46-
{
47-
return $this->morphMany(Subscription::class, 'subscriptionable');
48-
}
4935
}

app/Jobs/CreateReply.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
namespace App\Jobs;
44

5+
use App\Models\Subscription;
6+
use App\Models\SubscriptionAble;
57
use App\User;
68
use App\Models\Reply;
79
use App\Models\ReplyAble;
@@ -52,6 +54,14 @@ public function handle(): Reply
5254

5355
event(new ReplyWasCreated($reply));
5456

57+
if ($this->replyAble instanceof SubscriptionAble && ! $this->replyAble->hasSubscriber($this->author)) {
58+
$subscription = new Subscription();
59+
$subscription->userRelation()->associate($this->author);
60+
$subscription->subscriptionAbleRelation()->associate($this->replyAble);
61+
62+
$this->replyAble->subscriptionsRelation()->save($subscription);
63+
}
64+
5565
return $reply;
5666
}
5767
}

app/Jobs/CreateThread.php

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace App\Jobs;
44

5+
use App\Models\Subscription;
56
use App\User;
67
use App\Models\Thread;
78
use App\Http\Requests\ThreadRequest;
@@ -66,10 +67,11 @@ public function handle(): Thread
6667
$thread->save();
6768

6869
// Subscribe author to the thread.
69-
$this->author->subscriptionAble()->create([
70-
'subscriptionable_id' => $thread->id(),
71-
'subscriptionable_type' => Thread::TABLE,
72-
]);
70+
$subscription = new Subscription();
71+
$subscription->userRelation()->associate($this->author);
72+
$subscription->subscriptionAbleRelation()->associate($thread);
73+
74+
$thread->subscriptionsRelation()->save($subscription);
7375

7476
return $thread;
7577
}

app/Models/ReplyAble.php

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,4 @@ public function latestReplies(int $amount = 5);
2222
public function deleteReplies();
2323

2424
public function repliesRelation(): MorphMany;
25-
26-
/**
27-
* @return \App\Models\Subscription[]
28-
*/
29-
public function subscriptions();
30-
31-
public function subscriptionsRelation(): MorphMany;
3225
}

app/Models/Subscription.php

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use App\User;
66
use Illuminate\Database\Eloquent\Model;
77
use Illuminate\Database\Eloquent\Relations\BelongsTo;
8+
use Illuminate\Database\Eloquent\Relations\MorphTo;
89

910
class Subscription extends Model
1011
{
@@ -13,14 +14,6 @@ class Subscription extends Model
1314
*/
1415
protected $table = 'subscriptions';
1516

16-
/**
17-
* {@inheritdoc}
18-
*/
19-
protected $fillable = [
20-
'subscriptionable_id',
21-
'subscriptionable_type',
22-
];
23-
2417
public function user(): User
2518
{
2619
return $this->userRelation;
@@ -30,4 +23,14 @@ public function userRelation(): BelongsTo
3023
{
3124
return $this->belongsTo(User::class, 'user_id');
3225
}
26+
27+
public function subscriptionAble(): SubscriptionAble
28+
{
29+
return $this->subscriptionAbleRelation;
30+
}
31+
32+
public function subscriptionAbleRelation(): MorphTo
33+
{
34+
return $this->morphTo('subscriptionable');
35+
}
3336
}

app/Models/SubscriptionAble.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
3+
namespace App\Models;
4+
5+
use App\User;
6+
use Illuminate\Database\Eloquent\Relations\MorphMany;
7+
8+
interface SubscriptionAble
9+
{
10+
/**
11+
* @return \App\Models\Subscription[]
12+
*/
13+
public function subscriptions();
14+
15+
public function subscriptionsRelation(): MorphMany;
16+
17+
public function hasSubscriber(User $user): bool;
18+
}

app/Models/Thread.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,17 @@
99
use App\Helpers\ModelHelpers;
1010
use App\Helpers\HasTimestamps;
1111
use App\Helpers\ReceivesReplies;
12+
use App\Helpers\ProvidesSubscriptions;
1213
use Illuminate\Database\Eloquent\Model;
1314
use Illuminate\Database\Eloquent\Builder;
1415
use Illuminate\Database\Eloquent\Collection;
1516
use Illuminate\Contracts\Pagination\Paginator;
1617
use App\Exceptions\CouldNotMarkReplyAsSolution;
1718
use Illuminate\Database\Eloquent\Relations\BelongsTo;
1819

19-
class Thread extends Model implements ReplyAble
20+
class Thread extends Model implements ReplyAble, SubscriptionAble
2021
{
21-
use HasAuthor, HasSlug, HasTimestamps, ModelHelpers, ReceivesReplies, HasTags;
22+
use HasAuthor, HasSlug, HasTimestamps, ModelHelpers, ProvidesSubscriptions, ReceivesReplies, HasTags;
2223

2324
const TABLE = 'threads';
2425

app/User.php

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
use App\Models\Reply;
66
use App\Models\Thread;
7-
use App\Models\Subscription;
87
use App\Helpers\ModelHelpers;
98
use App\Helpers\HasTimestamps;
109
use Illuminate\Notifications\Notifiable;
@@ -239,17 +238,4 @@ public function delete()
239238

240239
parent::delete();
241240
}
242-
243-
public function isSubscribedTo($subscriptionAble): bool
244-
{
245-
return $this->subscriptionAble()
246-
->where('subscriptionable_id', $subscriptionAble->id())
247-
->where('subscriptionable_type', $subscriptionAble::TABLE)
248-
->exists();
249-
}
250-
251-
public function subscriptionAble(): HasMany
252-
{
253-
return $this->hasMany(Subscription::class, 'user_id');
254-
}
255241
}

tests/Components/Models/UserTest.php

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
namespace Tests\Components\Models;
44

5-
use App\Models\Subscription;
65
use App\User;
76
use Tests\TestCase;
87
use App\Models\Reply;
@@ -48,14 +47,4 @@ private function createTwoSolutionReplies(User $user)
4847
$reply = factory(Reply::class)->create(['replyable_id' => $thread->id(), 'author_id' => $user->id()]);
4948
$thread->markSolution($reply);
5049
}
51-
52-
/** @test */
53-
public function it_can_check_if_its_subscribed_to_a_thread()
54-
{
55-
$user = $this->createUser();
56-
$thread = factory(Thread::class)->create();
57-
factory(Subscription::class)->create(['user_id' => $user->id(), 'subscriptionable_id' => $thread->id()]);
58-
59-
$this->assertTrue($user->isSubscribedTo($thread));
60-
}
6150
}

0 commit comments

Comments
 (0)