diff --git a/README.md b/README.md index e9743d8..1e7e4f6 100644 --- a/README.md +++ b/README.md @@ -145,6 +145,11 @@ $user->getFriendRequests(); $user->getFriendsCount(); ``` +#### Get the number of mutual Friends with another user +```php +$user->getMutualFriendsCount($otherUser); +``` + ## Friends To get a collection of friend models (ex. User) use the following methods: #### Get Friends @@ -167,6 +172,11 @@ $user->getFriendsOfFriends($perPage = 20); $user->getFriends($perPage = 20, $group_name); ``` +#### Get mutual Friends with another user +```php +$user->getMutualFriends($otherUser, $perPage = 20); +``` + ## Friend groups The friend groups are defined in the `config/friendships.php` file. The package comes with a few default groups. diff --git a/src/Traits/Friendable.php b/src/Traits/Friendable.php index 62c76aa..4c7107d 100644 --- a/src/Traits/Friendable.php +++ b/src/Traits/Friendable.php @@ -279,6 +279,33 @@ public function getFriends($perPage = 0, $group_slug = '') return $this->getFriendsQueryBuilder($group_slug)->paginate($perPage); } } + + /** + * This method will not return Friendship models + * It will return the 'friends' models. ex: App\User + * + * @param int $perPage Number + * + * @return \Illuminate\Database\Eloquent\Collection + */ + public function getMutualFriends(Model $other, $perPage = 0) + { + if ($perPage == 0) { + return $this->getMutualFriendsQueryBuilder($other)->get(); + } else { + return $this->getMutualFriendsQueryBuilder($other)->paginate($perPage); + } + } + + /** + * Get the number of friends + * + * @return \Illuminate\Database\Eloquent\Collection + */ + public function getMutualFriendsCount($other) + { + return $this->getMutualFriendsQueryBuilder($other)->count(); + } /** * This method will not return Friendship models @@ -387,6 +414,31 @@ private function getFriendsQueryBuilder($group_slug = '') return $this->where('id', '!=', $this->getKey())->whereIn('id', array_merge($recipients, $senders)); } + + /** + * Get the query builder of the 'friend' model + * + * @return \Illuminate\Database\Eloquent\Builder + */ + private function getMutualFriendsQueryBuilder(Model $other) + { + $user1['friendships'] = $this->findFriendships(Status::ACCEPTED)->get(['sender_id', 'recipient_id']); + $user1['recipients'] = $user1['friendships']->lists('recipient_id')->all(); + $user1['senders'] = $user1['friendships']->lists('sender_id')->all(); + + $user2['friendships'] = $other->findFriendships(Status::ACCEPTED)->get(['sender_id', 'recipient_id']); + $user2['recipients'] = $user2['friendships']->lists('recipient_id')->all(); + $user2['senders'] = $user2['friendships']->lists('sender_id')->all(); + + $mutual_friendships = array_unique( + array_intersect( + array_merge($user1['recipients'], $user1['senders']), + array_merge($user2['recipients'], $user2['senders']) + ) + ); + + return $this->whereNotIn('id', [$this->getKey(), $other->getKey()])->whereIn('id', $mutual_friendships); + } /** * Get the query builder for friendsOfFriends ('friend' model) diff --git a/tests/FriendshipsTest.php b/tests/FriendshipsTest.php index 2f1feaa..3b351bf 100644 --- a/tests/FriendshipsTest.php +++ b/tests/FriendshipsTest.php @@ -360,6 +360,92 @@ public function it_returns_user_friends_of_friends() $this->containsOnlyInstancesOf(\App\User::class, $sender->getFriendsOfFriends()); } - - -} \ No newline at end of file + + /** @test */ + public function it_returns_user_mutual_friends() + { + $sender = createUser(); + $recipients = createUser([], 2); + $fofs = createUser([], 5)->chunk(3); + + foreach ($recipients as $recipient) { + $sender->befriend($recipient); + $recipient->acceptFriendRequest($sender); + + //add some friends to each recipient too + foreach ($fofs->shift() as $fof) { + $recipient->befriend($fof); + $fof->acceptFriendRequest($recipient); + $fof->befriend($sender); + $sender->acceptFriendRequest($fof); + } + } + + $this->assertCount(3, $sender->getMutualFriends($recipients[0])); + $this->assertCount(3, $recipients[0]->getMutualFriends($sender)); + + $this->assertCount(2, $sender->getMutualFriends($recipients[1])); + $this->assertCount(2, $recipients[1]->getMutualFriends($sender)); + + $this->containsOnlyInstancesOf(\App\User::class, $sender->getMutualFriends($recipients[0])); + } + + /** @test */ + public function it_returns_user_mutual_friends_per_page() + { + $sender = createUser(); + $recipients = createUser([], 2); + $fofs = createUser([], 8)->chunk(5); + + foreach ($recipients as $recipient) { + $sender->befriend($recipient); + $recipient->acceptFriendRequest($sender); + + //add some friends to each recipient too + foreach ($fofs->shift() as $fof) { + $recipient->befriend($fof); + $fof->acceptFriendRequest($recipient); + $fof->befriend($sender); + $sender->acceptFriendRequest($fof); + } + } + + $this->assertCount(2, $sender->getMutualFriends($recipients[0], 2)); + $this->assertCount(5, $sender->getMutualFriends($recipients[0], 0)); + $this->assertCount(5, $sender->getMutualFriends($recipients[0], 10)); + $this->assertCount(2, $recipients[0]->getMutualFriends($sender, 2)); + $this->assertCount(5, $recipients[0]->getMutualFriends($sender, 0)); + $this->assertCount(5, $recipients[0]->getMutualFriends($sender, 10)); + + $this->assertCount(1, $recipients[1]->getMutualFriends($recipients[0], 10)); + + $this->containsOnlyInstancesOf(\App\User::class, $sender->getMutualFriends($recipients[0], 2)); + } + + /** @test */ + public function it_returns_user_mutual_friends_number() + { + $sender = createUser(); + $recipients = createUser([], 2); + $fofs = createUser([], 5)->chunk(3); + + foreach ($recipients as $recipient) { + $sender->befriend($recipient); + $recipient->acceptFriendRequest($sender); + + //add some friends to each recipient too + foreach ($fofs->shift() as $fof) { + $recipient->befriend($fof); + $fof->acceptFriendRequest($recipient); + $fof->befriend($sender); + $sender->acceptFriendRequest($fof); + } + } + + $this->assertEquals(3, $sender->getMutualFriendsCount($recipients[0])); + $this->assertEquals(3, $recipients[0]->getMutualFriendsCount($sender)); + + $this->assertEquals(2, $sender->getMutualFriendsCount($recipients[1])); + $this->assertEquals(2, $recipients[1]->getMutualFriendsCount($sender)); + } +}