File tree Expand file tree Collapse file tree 6 files changed +151
-0
lines changed
Expand file tree Collapse file tree 6 files changed +151
-0
lines changed Original file line number Diff line number Diff line change 1+ <?php
2+
3+ declare (strict_types=1 );
4+
5+ namespace App \Action \Tweet ;
6+
7+ use App \Entity \Like ;
8+ use App \Repository \LikeRepository ;
9+ use App \Repository \TweetRepository ;
10+ use Illuminate \Support \Facades \Auth ;
11+
12+ final class LikeTweetAction
13+ {
14+ private $ tweetRepository ;
15+ private $ likeRepository ;
16+
17+ public function __construct (TweetRepository $ tweetRepository , LikeRepository $ likeRepository )
18+ {
19+ $ this ->tweetRepository = $ tweetRepository ;
20+ $ this ->likeRepository = $ likeRepository ;
21+ }
22+
23+ public function execute (LikeTweetRequest $ request ): void
24+ {
25+ $ tweet = $ this ->tweetRepository ->getById ($ request ->getTweetId ());
26+
27+ $ userId = Auth::id ();
28+
29+ // if user already liked tweet, we remove previous like
30+ if ($ this ->likeRepository ->existsForTweetByUser ($ tweet ->id , $ userId )) {
31+ $ this ->likeRepository ->deleteForTweetByUser ($ tweet ->id , $ userId );
32+
33+ return ;
34+ }
35+
36+ $ like = new Like ();
37+ $ like ->forTweet (Auth::id (), $ tweet ->id );
38+
39+ $ this ->likeRepository ->save ($ like );
40+ }
41+ }
Original file line number Diff line number Diff line change 1+ <?php
2+
3+ declare (strict_types=1 );
4+
5+ namespace App \Action \Tweet ;
6+
7+ final class LikeTweetRequest
8+ {
9+ private $ tweetId ;
10+
11+ public function __construct (int $ tweetId )
12+ {
13+ $ this ->tweetId = $ tweetId ;
14+ }
15+
16+ public function getTweetId (): int
17+ {
18+ return $ this ->tweetId ;
19+ }
20+ }
Original file line number Diff line number Diff line change 88use Illuminate \Database \Eloquent \Model ;
99use Illuminate \Database \Eloquent \Relations \BelongsTo ;
1010use Illuminate \Database \Eloquent \Relations \MorphTo ;
11+ use InvalidArgumentException ;
1112
1213/**
1314 * Class Like
@@ -27,6 +28,9 @@ final class Like extends Model
2728{
2829 protected $ table = 'likes ' ;
2930
31+ // no timestamps for likes migration
32+ public $ timestamps = false ;
33+
3034 protected $ fillable = [
3135 'user_id ' ,
3236 'likeable_id ' ,
@@ -64,4 +68,26 @@ public function getUser(): User
6468 {
6569 return $ this ->user ;
6670 }
71+
72+ public function forTweet (int $ userId , int $ tweetId ): void
73+ {
74+ $ this ->assertIdIsValid ($ userId );
75+ $ this ->assertIdIsValid ($ tweetId );
76+
77+ $ this ->user_id = $ userId ;
78+ $ this ->likeable_id = $ tweetId ;
79+ $ this ->likeable_type = Tweet::class;
80+ $ this ->created_at = Carbon::now ();
81+ }
82+
83+ /**
84+ * @param int $id
85+ * @throws InvalidArgumentException
86+ */
87+ private function assertIdIsValid (int $ id ): void
88+ {
89+ if ($ id < 1 ) {
90+ throw new InvalidArgumentException ('Id cannot be less than 1. ' );
91+ }
92+ }
6793}
Original file line number Diff line number Diff line change 1+ <?php
2+
3+ declare (strict_types=1 );
4+
5+ namespace App \Http \Controllers \Api ;
6+
7+ use App \Action \Tweet \LikeTweetAction ;
8+ use App \Action \Tweet \LikeTweetRequest ;
9+ use App \Http \Controllers \ApiController ;
10+ use App \Http \Response \ApiResponse ;
11+
12+ final class LikeController extends ApiController
13+ {
14+ private $ likeTweetAction ;
15+
16+ public function __construct (LikeTweetAction $ likeTweetAction )
17+ {
18+ $ this ->likeTweetAction = $ likeTweetAction ;
19+ }
20+
21+ public function likeOrDislikeTweet (string $ id ): ApiResponse
22+ {
23+ $ this ->likeTweetAction ->execute (new LikeTweetRequest ((int )$ id ));
24+
25+ return $ this ->createEmptyResponse ();
26+ }
27+ }
Original file line number Diff line number Diff line change 1+ <?php
2+
3+ declare (strict_types=1 );
4+
5+ namespace App \Repository ;
6+
7+ use App \Entity \Like ;
8+ use App \Entity \Tweet ;
9+
10+ final class LikeRepository
11+ {
12+ public function save (Like $ like ): Like
13+ {
14+ $ like ->save ();
15+
16+ return $ like ;
17+ }
18+
19+ public function existsForTweetByUser (int $ tweetId , int $ userId ): bool
20+ {
21+ return Like::where ([
22+ 'likeable_id ' => $ tweetId ,
23+ 'likeable_type ' => Tweet::class,
24+ 'user_id ' => $ userId
25+ ])->exists ();
26+ }
27+
28+ public function deleteForTweetByUser (int $ tweetId , int $ userId ): void
29+ {
30+ Like::where ([
31+ 'likeable_id ' => $ tweetId ,
32+ 'likeable_type ' => Tweet::class,
33+ 'user_id ' => $ userId
34+ ])->delete ();
35+ }
36+ }
Original file line number Diff line number Diff line change 4545 Route::post ('/{id}/image ' , 'TweetController@uploadTweetImage ' );
4646 Route::put ('/{id} ' , 'TweetController@updateTweetById ' );
4747 Route::delete ('/{id} ' , 'TweetController@deleteTweetById ' );
48+ Route::put ('/{id}/like ' , 'LikeController@likeOrDislikeTweet ' );
4849 });
4950
5051 Route::group ([
You can’t perform that action at this time.
0 commit comments