Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
overtrue committed Nov 23, 2022
2 parents b8a9458 + 1c057b4 commit 2d84966
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 47 deletions.
62 changes: 29 additions & 33 deletions src/Traits/Liker.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@
use Illuminate\Contracts\Pagination\Paginator;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Pagination\AbstractCursorPaginator;
use Illuminate\Pagination\AbstractPaginator;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Collection;
use Illuminate\Support\Enumerable;
use Illuminate\Support\LazyCollection;
use Overtrue\LaravelLike\Like;
Expand Down Expand Up @@ -101,7 +104,7 @@ public function likes(): HasMany
/**
* Get Query Builder for likes
*
* @return Illuminate\Database\Eloquent\Builder
* @return \Illuminate\Database\Eloquent\Builder
*/
public function getLikedItems(string $model)
{
Expand All @@ -113,48 +116,41 @@ function ($q) {
);
}

public function attachLikeStatus($likeables, callable $resolver = null)
public function attachLikeStatus(&$likeables, callable $resolver = null)
{
$returnFirst = false;
$toArray = false;

switch (true) {
case $likeables instanceof Model:
$returnFirst = true;
$likeables = \collect([$likeables]);
break;
case $likeables instanceof LengthAwarePaginator:
$likeables = $likeables->getCollection();
break;
case $likeables instanceof Paginator:
case $likeables instanceof CursorPaginator:
$likeables = \collect($likeables->items());
break;
case $likeables instanceof LazyCollection:
$likeables = \collect($likeables->all());
break;
case \is_array($likeables):
$likeables = \collect($likeables);
$toArray = true;
break;
}

\abort_if(!($likeables instanceof Enumerable), 422, 'Invalid $likeables type');

$liked = $this->likes()->get()->keyBy(function ($item) {
$likes = $this->likes()->get()->keyBy(function ($item) {
return \sprintf('%s:%s', $item->likeable_type, $item->likeable_id);
});

$likeables->map(function ($likeable) use ($liked, $resolver) {
$attachStatus = function($likeable) use ($likes, $resolver) {
$resolver = $resolver ?? fn ($m) => $m;
$likeable = $resolver($likeable);

if ($likeable && \in_array(Likeable::class, \class_uses_recursive($likeable))) {
$key = \sprintf('%s:%s', $likeable->getMorphClass(), $likeable->getKey());
$likeable->setAttribute('has_liked', $liked->has($key));
$likeable->setAttribute('has_liked', $likes->has($key));
}
});

return $returnFirst ? $likeables->first() : ($toArray ? $likeables->all() : $likeables);
return $likeable;
};

switch (true) {
case $likeables instanceof Model:
return $attachStatus($likeables);
case $likeables instanceof Collection:
return $likeables->each($attachStatus);
case $likeables instanceof LazyCollection:
return $likeables = $likeables->map($attachStatus);
case $likeables instanceof AbstractPaginator:
case $likeables instanceof AbstractCursorPaginator:
return $likeables->through($attachStatus);
case $likeables instanceof Paginator:
// custom paginator will return a collection
return collect($likeables->items())->transform($attachStatus);
case \is_array($likeables):
return \collect($likeables)->transform($attachStatus);
default:
throw new \InvalidArgumentException('Invalid argument type.');
}
}
}
32 changes: 18 additions & 14 deletions tests/FeatureTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -182,50 +182,54 @@ public function test_liker_can_attach_like_status_to_votable_collection()
$user->like($post1);
$user->like($post2);

// model
$post1 = Post::find($post1->id);
$this->assertNull($post1->has_liked);
$user->attachLikeStatus($post1);
$this->assertTrue($post1->has_liked);

// collection
$posts = Post::oldest('id')->get();
$user->attachLikeStatus($posts);
$posts = $posts->toArray();
$this->assertTrue($posts[0]['has_liked']);
$this->assertTrue($posts[1]['has_liked']);
$this->assertFalse($posts[2]['has_liked']);

// user has up liked post1
// lazy collection
$posts = Post::oldest('id')->cursor();
$user->attachLikeStatus($posts);
$posts = $posts->toArray();
$this->assertTrue($posts[0]['has_liked']);
// user has down liked post2
$this->assertTrue($posts[1]['has_liked']);
// user hasn't liked post3
$this->assertFalse($posts[2]['has_liked']);

// paginator
$posts = Post::oldest('id')->paginate();
$user->attachLikeStatus($posts);
$posts = $posts->toArray()['data'];
$this->assertTrue($posts[0]['has_liked']);
$this->assertTrue($posts[1]['has_liked']);
$this->assertFalse($posts[2]['has_liked']);

// cursor paginator
$posts = Post::oldest('id')->cursorPaginate();
$user->attachLikeStatus($posts);
$posts = $posts->toArray()['data'];
$this->assertTrue($posts[0]['has_liked']);
$this->assertTrue($posts[1]['has_liked']);
$this->assertFalse($posts[2]['has_liked']);

// cursor
$posts = Post::oldest('id')->cursor();
$posts = $user->attachLikeStatus($posts);
$posts = $posts->toArray();
// array
$posts = Post::oldest('id')->get()->all();
$user->attachLikeStatus($posts);
$this->assertTrue($posts[0]['has_liked']);
$this->assertTrue($posts[1]['has_liked']);
$this->assertFalse($posts[2]['has_liked']);

// custom resolver
$posts = [['post' => $post1], ['post' => $post2], ['post' => $post3]];
$posts = $user->attachLikeStatus($posts, fn ($i) => $i['post']);
$user->attachLikeStatus($posts, fn ($i) => $i['post']);

// user has up liked post1
$this->assertTrue($posts[0]['post']['has_liked']);
// user has down liked post2
$this->assertTrue($posts[1]['post']['has_liked']);
// user hasn't liked post3
$this->assertFalse($posts[2]['post']['has_liked']);
}

Expand Down

0 comments on commit 2d84966

Please sign in to comment.