diff --git a/VKAPI/Handlers/Users.php b/VKAPI/Handlers/Users.php index b09e82a55..3bfb52311 100644 --- a/VKAPI/Handlers/Users.php +++ b/VKAPI/Handlers/Users.php @@ -297,7 +297,7 @@ public function get(string $user_ids = "0", string $fields = "", int $offset = 0 "notes" => (new Notes())->getUserNotesCount($usr), "groups" => $usr->getClubCount(), "online_friends" => $usr->getFriendsOnlineCount(), - "mutual_friends" => 0, // FIXME: not implemented + "mutual_friends" => $authuser ? $usr->getCommonFriendsCount($authuser) : 0, "user_photos" => 0, // FIXME: not implemented "albums" => (new Albums())->getUserAlbumsCount($usr), "followers" => $usr->getFollowersCount(), diff --git a/Web/Models/Entities/User.php b/Web/Models/Entities/User.php index 819efdd40..abe2c4b83 100644 --- a/Web/Models/Entities/User.php +++ b/Web/Models/Entities/User.php @@ -46,14 +46,16 @@ class User extends RowModel private $_avatarAlbum = null; private $_avatarPhoto = false; // false - not resolved, null - no avatar - protected function _abstractRelationGenerator(string $filename, int $page = 1, int $limit = 6): \Traversable + protected function _abstractRelationGenerator(string $filename, int $page = 1, int $limit = 6, $second_id = null): \Traversable { $id = $this->getId(); + $second_id ??= $id; + $query = "SELECT id FROM\n" . file_get_contents(__DIR__ . "/../sql/$filename.tsql"); $query .= "\n LIMIT " . $limit . " OFFSET " . (($page - 1) * $limit); $ids = []; - $rels = DatabaseConnection::i()->getConnection()->query($query, $id, $id); + $rels = DatabaseConnection::i()->getConnection()->query($query, $id, $second_id); foreach ($rels as $rel) { $rel = (new Users())->get($rel->id); if (!$rel) { @@ -68,12 +70,14 @@ protected function _abstractRelationGenerator(string $filename, int $page = 1, i } } - protected function _abstractRelationCount(string $filename): int + protected function _abstractRelationCount(string $filename, $second_id = null): int { $id = $this->getId(); + $second_id ??= $id; + $query = "SELECT COUNT(*) AS cnt FROM\n" . file_get_contents(__DIR__ . "/../sql/$filename.tsql"); - return (int) DatabaseConnection::i()->getConnection()->query($query, $id, $id)->fetch()->cnt; + return (int) DatabaseConnection::i()->getConnection()->query($query, $id, $second_id)->fetch()->cnt; } public function getId(): int @@ -701,6 +705,16 @@ public function getFriendsOnlineCount(): int return $this->_abstractRelationCount("get-online-friends"); } + public function getCommonFriends(User $me, int $page = 1, int $limit = 6): \Traversable + { + return $this->_abstractRelationGenerator("get-common-friends", $page, $limit, $me->getId()); + } + + public function getCommonFriendsCount(User $me): int + { + return $this->_abstractRelationCount("get-common-friends", $me->getId()); + } + public function getFriendsBday(bool $today): array { $users = $this->_abstractRelationGenerator($today ? "get-bday-today" : "get-bday-tomorrow", 1, 3000); diff --git a/Web/Models/sql/get-common-friends.tsql b/Web/Models/sql/get-common-friends.tsql new file mode 100644 index 000000000..ba6439285 --- /dev/null +++ b/Web/Models/sql/get-common-friends.tsql @@ -0,0 +1 @@ +(SELECT DISTINCT p.* FROM subscriptions af1 INNER JOIN subscriptions af2 ON af1.follower = af2.target AND af2.follower = af1.target AND af1.model="openvk\\Web\\Models\\Entities\\User" AND af2.model="openvk\\Web\\Models\\Entities\\User" INNER JOIN subscriptions bf1 ON bf1.follower = af1.follower INNER JOIN subscriptions bf2 ON bf1.follower = bf2.target AND bf2.follower = bf1.target AND bf1.model="openvk\\Web\\Models\\Entities\\User" AND bf2.model="openvk\\Web\\Models\\Entities\\User" INNER JOIN profiles p ON p.id = af1.follower WHERE af1.target = ? AND bf1.target = ?) as common \ No newline at end of file diff --git a/Web/Presenters/UserPresenter.php b/Web/Presenters/UserPresenter.php index 4a7e759df..94e443104 100644 --- a/Web/Presenters/UserPresenter.php +++ b/Web/Presenters/UserPresenter.php @@ -95,20 +95,54 @@ public function renderFriends(int $id): void $this->template->user = $user; } - $this->template->mode = in_array($this->queryParam("act"), [ - "incoming", "outcoming", "friends", + $this->template->act = in_array($this->queryParam("act"), [ + "incoming", "outcoming", "friends", "common", "online", ]) ? $this->queryParam("act") - : "friends"; + : "friends"; + $this->template->page = $page; if (!is_null($this->user->identity)) { - if ($this->template->mode !== "friends" && $this->user->id !== $id) { + if (!in_array($this->template->act, ["friends", "common"]) && $this->user->id !== $id) { $name = $user->getFullName(); $this->flash("err", tr("error_access_denied_short"), tr("error_viewing_subs", $name)); $this->redirect($user->getURL()); } } + + if ($this->template->act === "common" && is_null($this->user->identity)) { + $this->template->act = "friends"; + } + + switch ($this->template->act) { + case "incoming": + $iterator = $user->getRequests($page); + $count = $user->getRequestsCount(); + break; + case "outcoming": + $iterator = $user->getSubscriptions($page); + $count = $user->getSubscriptionsCount(); + break; + case "followers": + $iterator = $user->getFollowers($page); + $count = $user->getFollowersCount(); + break; + case "online": + $iterator = $user->getFriendsOnline($page); + $count = $user->getFriendsOnlineCount(); + break; + case "common": + $iterator = $user->getCommonFriends($this->user->identity, $page); + $count = $user->getCommonFriendsCount($this->user->identity); + break; + default: + $iterator = $user->getFriends($page); + $count = $user->getFriendsCount(); + break; + } + $this->template->iterator = iterator_to_array($iterator); + $this->template->count = $count; } public function renderGroups(int $id): void diff --git a/Web/Presenters/templates/User/Friends.latte b/Web/Presenters/templates/User/Friends.latte index 89f1f9fa3..216a51e9e 100644 --- a/Web/Presenters/templates/User/Friends.latte +++ b/Web/Presenters/templates/User/Friends.latte @@ -1,37 +1,8 @@ {extends "../@listView.latte"} {var $perPage = 6} {* Why 6? Check User::_abstractRelationGenerator *} -{var $act = $_GET["act"] ?? "friends"} - -{if $act == "incoming"} - {var $iterator = iterator_to_array($user->getRequests($page))} - {var $count = $user->getRequestsCount()} -{elseif $act == "outcoming"} - {var $iterator = iterator_to_array($user->getSubscriptions($page))} - {var $count = $user->getSubscriptionsCount()} -{elseif $act == "followers"} - {var $iterator = iterator_to_array($user->getFollowers($page))} - {var $count = $user->getFollowersCount()} -{elseif $act == "online"} - {var $iterator = iterator_to_array($user->getFriendsOnline($page))} - {var $count = $user->getFriendsOnlineCount()} -{else} - {var $iterator = iterator_to_array($user->getFriends($page))} - {var $count = $user->getFriendsCount()} -{/if} - {block title} - {if $act == "incoming"} - {_incoming_req} - {elseif $act == "outcoming"} - {_outcoming_req} - {elseif $act == "followers"} - {_followers} - {elseif $act == "online"} - {_friends_online} - {else} - {_friends} - {/if} + {include "Friends/Title.latte", act => $act} {/block} {block header} @@ -39,17 +10,7 @@ {_my_friends} {else} {$user->getCanonicalName()} » - {if $act == "incoming"} - {_incoming_req} - {elseif $act == "outcoming"} - {_outcoming_req} - {elseif $act == "followers"} - {_followers} - {elseif $act == "online"} - {_friends_online} - {else} - {_friends} - {/if} + {include "Friends/Title.latte", act => $act} {/if} {/block} @@ -63,6 +24,9 @@
+ {/block} {block size} @@ -97,6 +61,8 @@ {else} {tr("friends_list", $count)} {/if} + {elseif $act == "common"} + {tr("friends_list_common", $count)} {else} {tr("friends", $count)} {/if} diff --git a/Web/Presenters/templates/User/Friends/Title.latte b/Web/Presenters/templates/User/Friends/Title.latte new file mode 100644 index 000000000..24fde637e --- /dev/null +++ b/Web/Presenters/templates/User/Friends/Title.latte @@ -0,0 +1,13 @@ +{if $act == "incoming"} + {_incoming_req} +{elseif $act == "outcoming"} + {_outcoming_req} +{elseif $act == "followers"} + {_followers} +{elseif $act == "online"} + {_friends_online} +{elseif $act == "common"} + {_friends_common} +{else} + {_friends} +{/if} \ No newline at end of file diff --git a/Web/Presenters/templates/User/Thumb.latte b/Web/Presenters/templates/User/Thumb.latte new file mode 100644 index 000000000..484c8af31 --- /dev/null +++ b/Web/Presenters/templates/User/Thumb.latte @@ -0,0 +1,11 @@ + \ No newline at end of file diff --git a/Web/Presenters/templates/User/View.latte b/Web/Presenters/templates/User/View.latte index eda7416d1..7d40a944f 100644 --- a/Web/Presenters/templates/User/View.latte +++ b/Web/Presenters/templates/User/View.latte @@ -215,6 +215,24 @@ {/if}