From f9f6270da022648a8dac114bfc07b3d687a4689a Mon Sep 17 00:00:00 2001 From: lalka2018 <99399973+lalka2016@users.noreply.github.com> Date: Sat, 10 Jun 2023 18:54:02 +0300 Subject: [PATCH] Search: Add search with parameters (#880) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Search with parameters * Small improvements * Small improvements no.2 Поиск теперь нормально выглядит на других темах При поиске по группам отображается количество участников там Костыль с пропуском постов возвращён но немного изменён Добавлен костыль к комментариям чтобы не показывались комменты с удалённых постов и не было бага как в вепуровке Добавлены ключи в советском и имперском языке для моих прошлых пуллов (ну и этого конечно) * Fix debilny oshibky Убрал лишние ключи локализации, исправил панель поеска и исправил hometown * fiksy bagiv * ok * ok 2 * ok * rrrrrrrrrrrrrrrr Добавил параметры в vkapi users.search(), пофиксил проверку коммерции, сузил параметры ещё больше и добавил анимацию выдвижения поиска чтобы красиво было --- VKAPI/Handlers/Users.php | 86 ++++- Web/Models/Repositories/Applications.php | 8 + Web/Models/Repositories/Clubs.php | 4 +- Web/Models/Repositories/Comments.php | 31 ++ Web/Models/Repositories/Posts.php | 34 +- Web/Models/Repositories/Users.php | 80 +++- Web/Models/Repositories/Videos.php | 32 ++ Web/Presenters/SearchPresenter.php | 71 +++- Web/Presenters/templates/@layout.xml | 52 ++- Web/Presenters/templates/Search/Index.xml | 347 +++++++++++++++--- Web/Presenters/templates/User/View.xml | 47 ++- .../templates/components/comment.xml | 5 +- Web/Presenters/templates/components/video.xml | 35 ++ Web/static/css/main.css | 170 +++++++++ Web/static/img/hide.png | Bin 0 -> 184 bytes Web/static/img/show.png | Bin 0 -> 169 bytes Web/static/js/openvk.cls.js | 74 ++++ locales/en.strings | 53 ++- locales/ru.strings | 55 ++- locales/ru_old.strings | 84 ++++- locales/ru_sov.strings | 91 ++++- themepacks/midnight/stylesheet.css | 104 ++++++ themepacks/openvk_modern/stylesheet.css | 92 +++++ 23 files changed, 1473 insertions(+), 82 deletions(-) create mode 100644 Web/Presenters/templates/components/video.xml create mode 100644 Web/static/img/hide.png create mode 100644 Web/static/img/show.png diff --git a/VKAPI/Handlers/Users.php b/VKAPI/Handlers/Users.php index acb29469..f48592b5 100644 --- a/VKAPI/Handlers/Users.php +++ b/VKAPI/Handlers/Users.php @@ -150,7 +150,10 @@ final class Users extends VKAPIRequestHandler break; case "interests": $response[$i]->interests = $usr->getInterests(); - break; + break; + case "rating": + $response[$i]->rating = $usr->getRating(); + break; } } @@ -188,19 +191,94 @@ final class Users extends VKAPIRequestHandler ]; } - function search(string $q, string $fields = "", int $offset = 0, int $count = 100) + function search(string $q, + string $fields = "", + int $offset = 0, + int $count = 100, + string $city = "", + string $hometown = "", + int $sex = 2, + int $status = 0, # это про marital status + bool $online = false, + # дальше идут параметры которых нету в vkapi но есть на сайте + string $profileStatus = "", # а это уже нормальный статус + int $sort = 0, + int $before = 0, + int $politViews = 0, + int $after = 0, + string $interests = "", + string $fav_music = "", + string $fav_films = "", + string $fav_shows = "", + string $fav_books = "", + string $fav_quotes = "" + ) { $users = new UsersRepo; + $sortg = "id ASC"; + + $nfilds = $fields; + + switch($sort) { + case 0: + $sortg = "id DESC"; + break; + case 1: + $sortg = "id ASC"; + break; + case 2: + $sortg = "first_name DESC"; + break; + case 3: + $sortg = "first_name ASC"; + break; + case 4: + $sortg = "rating DESC"; + + if(!str_contains($nfilds, "rating")) { + $nfilds .= "rating"; + } + + break; + case 5: + $sortg = "rating DESC"; + + if(!str_contains($nfilds, "rating")) { + $nfilds .= "rating"; + } + + break; + } + $array = []; - $find = $users->find($q); + + $parameters = [ + "city" => !empty($city) ? $city : NULL, + "hometown" => !empty($hometown) ? $hometown : NULL, + "gender" => $sex < 2 ? $sex : NULL, + "maritalstatus" => (bool)$status ? $status : NULL, + "politViews" => (bool)$politViews ? $politViews : NULL, + "is_online" => $online ? 1 : NULL, + "status" => !empty($profileStatus) ? $profileStatus : NULL, + "before" => $before != 0 ? $before : NULL, + "after" => $after != 0 ? $after : NULL, + "interests" => !empty($interests) ? $interests : NULL, + "fav_music" => !empty($fav_music) ? $fav_music : NULL, + "fav_films" => !empty($fav_films) ? $fav_films : NULL, + "fav_shows" => !empty($fav_shows) ? $fav_shows : NULL, + "fav_books" => !empty($fav_books) ? $fav_books : NULL, + "fav_quotes" => !empty($fav_quotes) ? $fav_quotes : NULL, + ]; + + $find = $users->find($q, $parameters, $sortg); foreach ($find as $user) $array[] = $user->getId(); return (object) [ "count" => $find->size(), - "items" => $this->get(implode(',', $array), $fields, $offset, $count) + "items" => $this->get(implode(',', $array), $nfilds, $offset, $count) ]; } } diff --git a/Web/Models/Repositories/Applications.php b/Web/Models/Repositories/Applications.php index 3aa6e5be..0687856e 100644 --- a/Web/Models/Repositories/Applications.php +++ b/Web/Models/Repositories/Applications.php @@ -66,4 +66,12 @@ class Applications { return sizeof($this->appRels->where("user", $user->getId())); } + + function find(string $query, array $pars = [], string $sort = "id"): Util\EntityStream + { + $query = "%$query%"; + $result = $this->apps->where("CONCAT_WS(' ', name, description) LIKE ?", $query)->where("enabled", 1); + + return new Util\EntityStream("Application", $result->order("$sort")); + } } \ No newline at end of file diff --git a/Web/Models/Repositories/Clubs.php b/Web/Models/Repositories/Clubs.php index 8e97f3eb..04bb30ab 100644 --- a/Web/Models/Repositories/Clubs.php +++ b/Web/Models/Repositories/Clubs.php @@ -43,12 +43,12 @@ class Clubs return $this->toClub($this->clubs->get($id)); } - function find(string $query, int $page = 1, ?int $perPage = NULL): \Traversable + function find(string $query, array $pars = [], string $sort = "id DESC", int $page = 1, ?int $perPage = NULL): \Traversable { $query = "%$query%"; $result = $this->clubs->where("name LIKE ? OR about LIKE ?", $query, $query); - return new Util\EntityStream("Club", $result); + return new Util\EntityStream("Club", $result->order($sort)); } function getCount(): int diff --git a/Web/Models/Repositories/Comments.php b/Web/Models/Repositories/Comments.php index 4774cf35..f4b8e5ac 100644 --- a/Web/Models/Repositories/Comments.php +++ b/Web/Models/Repositories/Comments.php @@ -59,4 +59,35 @@ class Comments "deleted" => false, ])); } + + function find(string $query = "", array $pars = [], string $sort = "id"): Util\EntityStream + { + $query = "%$query%"; + + $notNullParams = []; + + foreach($pars as $paramName => $paramValue) + if($paramName != "before" && $paramName != "after") + $paramValue != NULL ? $notNullParams+=["$paramName" => "%$paramValue%"] : NULL; + else + $paramValue != NULL ? $notNullParams+=["$paramName" => "$paramValue"] : NULL; + + $result = $this->comments->where("content LIKE ?", $query)->where("deleted", 0); + $nnparamsCount = sizeof($notNullParams); + + if($nnparamsCount > 0) { + foreach($notNullParams as $paramName => $paramValue) { + switch($paramName) { + case "before": + $result->where("created < ?", $paramValue); + break; + case "after": + $result->where("created > ?", $paramValue); + break; + } + } + } + + return new Util\EntityStream("Comment", $result->order("$sort")); + } } diff --git a/Web/Models/Repositories/Posts.php b/Web/Models/Repositories/Posts.php index 7aadc0bb..c354f152 100644 --- a/Web/Models/Repositories/Posts.php +++ b/Web/Models/Repositories/Posts.php @@ -99,7 +99,39 @@ class Posts return NULL; } - + + function find(string $query = "", array $pars = [], string $sort = "id"): Util\EntityStream + { + $query = "%$query%"; + + $notNullParams = []; + + foreach($pars as $paramName => $paramValue) + if($paramName != "before" && $paramName != "after") + $paramValue != NULL ? $notNullParams+=["$paramName" => "%$paramValue%"] : NULL; + else + $paramValue != NULL ? $notNullParams+=["$paramName" => "$paramValue"] : NULL; + + $result = $this->posts->where("content LIKE ?", $query)->where("deleted", 0); + $nnparamsCount = sizeof($notNullParams); + + if($nnparamsCount > 0) { + foreach($notNullParams as $paramName => $paramValue) { + switch($paramName) { + case "before": + $result->where("created < ?", $paramValue); + break; + case "after": + $result->where("created > ?", $paramValue); + break; + } + } + } + + + return new Util\EntityStream("Post", $result->order("$sort")); + } + function getPostCountOnUserWall(int $user): int { return sizeof($this->posts->where(["wall" => $user, "deleted" => 0])); diff --git a/Web/Models/Repositories/Users.php b/Web/Models/Repositories/Users.php index 63e77df0..0eec3306 100644 --- a/Web/Models/Repositories/Users.php +++ b/Web/Models/Repositories/Users.php @@ -49,12 +49,88 @@ class Users return $this->toUser($this->users->where("user", $user->getId())->fetch()); } - function find(string $query): Util\EntityStream + function find(string $query, array $pars = [], string $sort = "id DESC"): Util\EntityStream { $query = "%$query%"; $result = $this->users->where("CONCAT_WS(' ', first_name, last_name, pseudo, shortcode) LIKE ?", $query)->where("deleted", 0); - return new Util\EntityStream("User", $result); + $notNullParams = []; + $nnparamsCount = 0; + + foreach($pars as $paramName => $paramValue) + if($paramName != "before" && $paramName != "after" && $paramName != "gender" && $paramName != "maritalstatus" && $paramName != "politViews") + $paramValue != NULL ? $notNullParams += ["$paramName" => "%$paramValue%"] : NULL; + else + $paramValue != NULL ? $notNullParams += ["$paramName" => "$paramValue"] : NULL; + + $nnparamsCount = sizeof($notNullParams); + + if($nnparamsCount > 0) { + foreach($notNullParams as $paramName => $paramValue) { + switch($paramName) { + case "hometown": + $result->where("hometown LIKE ?", $paramValue); + break; + case "city": + $result->where("city LIKE ?", $paramValue); + break; + case "maritalstatus": + $result->where("marital_status ?", $paramValue); + break; + case "status": + $result->where("status LIKE ?", $paramValue); + break; + case "politViews": + $result->where("polit_views ?", $paramValue); + break; + case "email": + $result->where("email_contact LIKE ?", $paramValue); + break; + case "telegram": + $result->where("telegram LIKE ?", $paramValue); + break; + case "site": + $result->where("telegram LIKE ?", $paramValue); + break; + case "address": + $result->where("address LIKE ?", $paramValue); + break; + case "is_online": + $result->where("online >= ?", time() - 900); + break; + case "interests": + $result->where("interests LIKE ?", $paramValue); + break; + case "fav_mus": + $result->where("fav_music LIKE ?", $paramValue); + break; + case "fav_films": + $result->where("fav_films LIKE ?", $paramValue); + break; + case "fav_shows": + $result->where("fav_shows LIKE ?", $paramValue); + break; + case "fav_books": + $result->where("fav_books LIKE ?", $paramValue); + break; + case "fav_quote": + $result->where("fav_quote LIKE ?", $paramValue); + break; + case "before": + $result->where("UNIX_TIMESTAMP(since) < ?", $paramValue); + break; + case "after": + $result->where("UNIX_TIMESTAMP(since) > ?", $paramValue); + break; + case "gender": + $result->where("sex ?", $paramValue); + break; + } + } + } + + + return new Util\EntityStream("User", $result->order($sort)); } function getStatistics(): object diff --git a/Web/Models/Repositories/Videos.php b/Web/Models/Repositories/Videos.php index 5701b44e..30753371 100644 --- a/Web/Models/Repositories/Videos.php +++ b/Web/Models/Repositories/Videos.php @@ -45,4 +45,36 @@ class Videos { return sizeof($this->videos->where("owner", $user->getId())->where(["deleted" => 0, "unlisted" => 0])); } + + function find(string $query = "", array $pars = [], string $sort = "id"): Util\EntityStream + { + $query = "%$query%"; + + $notNullParams = []; + + foreach($pars as $paramName => $paramValue) + if($paramName != "before" && $paramName != "after") + $paramValue != NULL ? $notNullParams+=["$paramName" => "%$paramValue%"] : NULL; + else + $paramValue != NULL ? $notNullParams+=["$paramName" => "$paramValue"] : NULL; + + $result = $this->videos->where("name OR description LIKE ?", $query)->where("deleted", 0); + $nnparamsCount = sizeof($notNullParams); + + if($nnparamsCount > 0) { + foreach($notNullParams as $paramName => $paramValue) { + switch($paramName) { + case "before": + $result->where("created < ?", $paramValue); + break; + case "after": + $result->where("created > ?", $paramValue); + break; + } + } + } + + + return new Util\EntityStream("Video", $result->order("$sort")); + } } diff --git a/Web/Presenters/SearchPresenter.php b/Web/Presenters/SearchPresenter.php index 2171297c..fadf9954 100644 --- a/Web/Presenters/SearchPresenter.php +++ b/Web/Presenters/SearchPresenter.php @@ -1,18 +1,28 @@ users = $users; - $this->clubs = $clubs; + $this->users = $users; + $this->clubs = $clubs; + $this->posts = new Posts; + $this->comments = new Comments; + $this->videos = new Videos; + $this->apps = new Applications; + $this->notes = new Notes; parent::__construct(); } @@ -21,6 +31,8 @@ final class SearchPresenter extends OpenVKPresenter { $query = $this->queryParam("query") ?? ""; $type = $this->queryParam("type") ?? "users"; + $sorter = $this->queryParam("sort") ?? "id"; + $invert = $this->queryParam("invert") == 1 ? "ASC" : "DESC"; $page = (int) ($this->queryParam("p") ?? 1); $this->willExecuteWriteAction(); @@ -28,11 +40,58 @@ final class SearchPresenter extends OpenVKPresenter $this->assertUserLoggedIn(); # https://youtu.be/pSAWM5YuXx8 - - $repos = [ "groups" => "clubs", "users" => "users" ]; + + $repos = [ + "groups" => "clubs", + "users" => "users", + "posts" => "posts", + "comments" => "comments", + "videos" => "videos", + "audios" => "posts", + "apps" => "apps", + "notes" => "notes" + ]; + + switch($sorter) { + default: + case "id": + $sort = "id " . $invert; + break; + case "name": + $sort = "first_name " . $invert; + break; + case "rating": + $sort = "rating " . $invert; + break; + } + + $parameters = [ + "type" => $this->queryParam("type"), + "city" => $this->queryParam("city") != "" ? $this->queryParam("city") : NULL, + "maritalstatus" => $this->queryParam("maritalstatus") != 0 ? $this->queryParam("maritalstatus") : NULL, + "with_photo" => $this->queryParam("with_photo"), + "status" => $this->queryParam("status") != "" ? $this->queryParam("status") : NULL, + "politViews" => $this->queryParam("politViews") != 0 ? $this->queryParam("politViews") : NULL, + "email" => $this->queryParam("email"), + "telegram" => $this->queryParam("telegram"), + "site" => $this->queryParam("site") != "" ? "https://".$this->queryParam("site") : NULL, + "address" => $this->queryParam("address"), + "is_online" => $this->queryParam("is_online") == 1 ? 1 : NULL, + "interests" => $this->queryParam("interests") != "" ? $this->queryParam("interests") : NULL, + "fav_mus" => $this->queryParam("fav_mus") != "" ? $this->queryParam("fav_mus") : NULL, + "fav_films" => $this->queryParam("fav_films") != "" ? $this->queryParam("fav_films") : NULL, + "fav_shows" => $this->queryParam("fav_shows") != "" ? $this->queryParam("fav_shows") : NULL, + "fav_books" => $this->queryParam("fav_books") != "" ? $this->queryParam("fav_books") : NULL, + "fav_quote" => $this->queryParam("fav_quote") != "" ? $this->queryParam("fav_quote") : NULL, + "hometown" => $this->queryParam("hometown") != "" ? $this->queryParam("hometown") : NULL, + "before" => $this->queryParam("datebefore") != "" ? strtotime($this->queryParam("datebefore")) : NULL, + "after" => $this->queryParam("dateafter") != "" ? strtotime($this->queryParam("dateafter")) : NULL, + "gender" => $this->queryParam("gender") != "" && $this->queryParam("gender") != 2 ? $this->queryParam("gender") : NULL + ]; + $repo = $repos[$type] or $this->throwError(400, "Bad Request", "Invalid search entity $type."); - $results = $this->{$repo}->find($query); + $results = $this->{$repo}->find($query, $parameters, $sort); $iterator = $results->page($page); $count = $results->size(); diff --git a/Web/Presenters/templates/@layout.xml b/Web/Presenters/templates/@layout.xml index cd6e4891..7bb7e194 100644 --- a/Web/Presenters/templates/@layout.xml +++ b/Web/Presenters/templates/@layout.xml @@ -70,28 +70,60 @@ {_header_log_out} {else} -