From 8286173ed31b7f63703a183f90cfcfc094543e42 Mon Sep 17 00:00:00 2001 From: mrilyew <99399973+mrilyew@users.noreply.github.com> Date: Fri, 18 Oct 2024 22:29:40 +0300 Subject: [PATCH 1/9] search: a bit refactor --- ServiceAPI/Search.php | 76 -- VKAPI/Handlers/Groups.php | 8 +- VKAPI/Handlers/Users.php | 109 ++- VKAPI/Handlers/Video.php | 56 ++ Web/Models/Entities/Club.php | 2 +- Web/Models/Entities/Comment.php | 27 + Web/Models/Entities/Playlist.php | 5 + Web/Models/Entities/User.php | 14 +- Web/Models/Entities/Video.php | 4 +- Web/Models/Repositories/Applications.php | 17 +- Web/Models/Repositories/Audios.php | 75 +- Web/Models/Repositories/Clubs.php | 23 +- Web/Models/Repositories/Comments.php | 43 +- Web/Models/Repositories/Posts.php | 51 +- Web/Models/Repositories/Users.php | 143 ++-- Web/Models/Repositories/Videos.php | 46 +- Web/Presenters/AudioPresenter.php | 3 +- Web/Presenters/SearchPresenter.php | 138 ++-- Web/Presenters/templates/@layout.xml | 85 +-- Web/Presenters/templates/Audio/List.xml | 92 ++- Web/Presenters/templates/Audio/Playlist.xml | 4 +- Web/Presenters/templates/Audio/Upload.xml | 2 +- Web/Presenters/templates/Audio/player.xml | 2 +- Web/Presenters/templates/Audio/tabs.xml | 40 +- Web/Presenters/templates/Search/Index.xml | 690 +++++++++--------- Web/Presenters/templates/User/View.xml | 16 +- .../templates/components/comment.xml | 26 +- .../templates/components/content_error.xml | 6 + .../templates/components/paginator.xml | 6 +- Web/Util/Makima/Makima.php | 2 +- Web/static/css/audios.css | 21 +- Web/static/css/main.css | 468 +++++++----- Web/static/img/arrows.png | Bin 0 -> 219 bytes Web/static/img/hide.png | Bin 184 -> 0 bytes Web/static/img/show.png | Bin 169 -> 0 bytes Web/static/js/al_music.js | 35 +- Web/static/js/al_navigation.js | 141 ++++ Web/static/js/al_wall.js | 57 +- Web/static/js/openvk.cls.js | 118 +-- locales/en.strings | 22 +- locales/ru.strings | 28 +- locales/uk.strings | 4 - themepacks/openvk_modern/stylesheet.css | 84 +-- 43 files changed, 1460 insertions(+), 1329 deletions(-) delete mode 100644 ServiceAPI/Search.php create mode 100644 Web/Presenters/templates/components/content_error.xml create mode 100644 Web/static/img/arrows.png delete mode 100644 Web/static/img/hide.png delete mode 100644 Web/static/img/show.png create mode 100644 Web/static/js/al_navigation.js diff --git a/ServiceAPI/Search.php b/ServiceAPI/Search.php deleted file mode 100644 index de0f9d2c..00000000 --- a/ServiceAPI/Search.php +++ /dev/null @@ -1,76 +0,0 @@ -user = $user; - $this->users = new Users; - $this->clubs = new Clubs; - $this->videos = new Videos; - } - - function fastSearch(string $query, string $type = "users", callable $resolve, callable $reject) - { - if($query == "" || strlen($query) < 3) - $reject(12, "No input or input < 3"); - - $repo; - $sort; - - switch($type) { - default: - case "users": - $repo = (new Users); - $sort = "rating DESC"; - - break; - case "groups": - $repo = (new Clubs); - $sort = "id ASC"; - - break; - case "videos": - $repo = (new Videos); - $sort = "created ASC"; - - break; - } - - $res = $repo->find($query, ["doNotSearchMe" => $this->user->getId(), "doNotSearchPrivate" => true,], $sort); - - $results = array_slice(iterator_to_array($res), 0, 5); - - $count = sizeof($results); - - $arr = [ - "count" => $count, - "items" => [] - ]; - - if(sizeof($results) < 1) { - $reject(2, "No results"); - } - - foreach($results as $res) { - $arr["items"][] = [ - "id" => $res->getId(), - "name" => $type == "users" ? $res->getCanonicalName() : $res->getName(), - "avatar" => $type != "videos" ? $res->getAvatarUrl() : $res->getThumbnailURL(), - "url" => $type != "videos" ? $res->getUrl() : "/video".$res->getPrettyId(), - "description" => ovk_proc_strtr($res->getDescription() ?? "...", 40) - ]; - } - - $resolve($arr); - } -} diff --git a/VKAPI/Handlers/Groups.php b/VKAPI/Handlers/Groups.php index ca67e7b7..0b59f838 100644 --- a/VKAPI/Handlers/Groups.php +++ b/VKAPI/Handlers/Groups.php @@ -252,7 +252,7 @@ final class Groups extends VKAPIRequestHandler return $response; } - function search(string $q, int $offset = 0, int $count = 100) + function search(string $q, int $offset = 0, int $count = 100, string $fields = "screen_name,is_admin,is_member,is_advertiser,photo_50,photo_100,photo_200") { $clubs = new ClubsRepo; @@ -264,11 +264,7 @@ final class Groups extends VKAPIRequestHandler return (object) [ "count" => $find->size(), - "items" => $this->getById(implode(',', $array), "", "is_admin,is_member,is_advertiser,photo_50,photo_100,photo_200", $offset, $count) - /* - * As there is no thing as "fields" by the original documentation - * i'll just bake this param by the example shown here: https://dev.vk.com/method/groups.search - */ + "items" => $this->getById(implode(',', $array), "", $fields, $offset, $count) ]; } diff --git a/VKAPI/Handlers/Users.php b/VKAPI/Handlers/Users.php index 132b6204..d85053bb 100644 --- a/VKAPI/Handlers/Users.php +++ b/VKAPI/Handlers/Users.php @@ -263,6 +263,9 @@ final class Users extends VKAPIRequestHandler case 'is_dead': $response[$i]->is_dead = $usr->isDead(); break; + case 'nickname': + $response[$i]->nickname = $usr->getPseudo(); + break; } } @@ -314,89 +317,79 @@ final class Users extends VKAPIRequestHandler int $count = 100, string $city = "", string $hometown = "", - int $sex = 2, - int $status = 0, # это про marital status + int $sex = 3, + int $status = 0, # marital_status bool $online = false, - # дальше идут параметры которых нету в vkapi но есть на сайте - string $profileStatus = "", # а это уже нормальный статус + # non standart params: int $sort = 0, - int $before = 0, - int $politViews = 0, - int $after = 0, - string $interests = "", + int $polit_views = 0, string $fav_music = "", string $fav_films = "", string $fav_shows = "", - string $fav_books = "", - string $fav_quotes = "" + string $fav_books = "" ) { $users = new UsersRepo; - - $sortg = "id ASC"; - - $nfilds = $fields; + $output_sort = ['type' => 'id', 'invert' => false]; + $output_params = [ + "ignore_private" => true, + ]; switch($sort) { + default: case 0: - $sortg = "id DESC"; + $output_sort = ['type' => 'id', 'invert' => false]; break; case 1: - $sortg = "id ASC"; - break; - case 2: - $sortg = "first_name DESC"; - break; - case 3: - $sortg = "first_name ASC"; + $output_sort = ['type' => 'id', 'invert' => true]; 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"; - } - + $output_sort = ['type' => 'rating', 'invert' => false]; break; } + if(!empty($city)) + $output_params['city'] = $city; + + if(!empty($hometown)) + $output_params['hometown'] = $hometown; + + if($sex != 3) + $output_params['gender'] = $sex; + + if($status != 0) + $output_params['marital_status'] = $status; + + if($polit_views != 0) + $output_params['polit_views'] = $polit_views; + + if(!empty($interests)) + $output_params['interests'] = $interests; + + if(!empty($fav_music)) + $output_params['fav_music'] = $fav_music; + + if(!empty($fav_films)) + $output_params['fav_films'] = $fav_films; + + if(!empty($fav_shows)) + $output_params['fav_shows'] = $fav_shows; + + if(!empty($fav_books)) + $output_params['fav_books'] = $fav_books; + + if($online) + $output_params['is_online'] = 1; + $array = []; - - $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, - "doNotSearchPrivate" => true, - ]; - - $find = $users->find($q, $parameters, $sortg); + $find = $users->find($q, $output_params, $output_sort); foreach ($find as $user) $array[] = $user->getId(); return (object) [ "count" => $find->size(), - "items" => $this->get(implode(',', $array), $nfilds, $offset, $count) + "items" => $this->get(implode(',', $array), $fields, $offset, $count) ]; } diff --git a/VKAPI/Handlers/Video.php b/VKAPI/Handlers/Video.php index f468686d..d933f728 100755 --- a/VKAPI/Handlers/Video.php +++ b/VKAPI/Handlers/Video.php @@ -60,4 +60,60 @@ final class Video extends VKAPIRequestHandler ]; } } + + function search(string $q = '', int $sort = 0, int $offset = 0, int $count = 10, bool $extended = false, string $fields = ''): object + { + $this->requireUser(); + + $params = []; + $db_sort = ['type' => 'id', 'invert' => false]; + $videos = (new VideosRepo)->find($q, $params, $db_sort); + $items = iterator_to_array($videos->offsetLimit($offset, $count)); + $count = $videos->size(); + + $return_items = []; + $profiles = []; + $groups = []; + foreach($items as $item) + $return_item = $item->getApiStructure($this->getUser()); + $return_item = $return_item->video; + $return_items[] = $return_item; + + if($return_item['owner_id']) { + if($return_item['owner_id'] > 0) + $profiles[] = $return_item['owner_id']; + else + $groups[] = abs($return_item['owner_id']); + } + + if($extended) { + $profiles = array_unique($profiles); + $groups = array_unique($groups); + + $profilesFormatted = []; + $groupsFormatted = []; + + foreach($profiles as $prof) { + $profile = (new UsersRepo)->get($prof); + $profilesFormatted[] = $profile->toVkApiStruct($this->getUser(), $fields); + } + + foreach($groups as $gr) { + $group = (new ClubsRepo)->get($gr); + $groupsFormatted[] = $group->toVkApiStruct($this->getUser(), $fields); + } + + return (object) [ + "count" => $count, + "items" => $return_items, + "profiles" => $profilesFormatted, + "groups" => $groupsFormatted, + ]; + } + + return (object) [ + "count" => $count, + "items" => $return_items, + ]; + } } diff --git a/Web/Models/Entities/Club.php b/Web/Models/Entities/Club.php index dc1c356e..c919b059 100644 --- a/Web/Models/Entities/Club.php +++ b/Web/Models/Entities/Club.php @@ -437,7 +437,7 @@ class Club extends RowModel return (new \openvk\Web\Models\Repositories\Audios)->getClubCollectionSize($this); } - function toVkApiStruct(?User $user = NULL): object + function toVkApiStruct(?User $user = NULL, string $fields = ''): object { $res = (object) []; diff --git a/Web/Models/Entities/Comment.php b/Web/Models/Entities/Comment.php index 200d7a16..fd32c0b8 100644 --- a/Web/Models/Entities/Comment.php +++ b/Web/Models/Entities/Comment.php @@ -140,4 +140,31 @@ class Comment extends Post return $user->getId() == $this->getOwner(false)->getId(); } + + function getTargetURL(): string + { + $target = $this->getTarget(); + $target_name = 'wall'; + + if(!$target) { + return '/404'; + } + + switch(get_class($target)) { + case 'openvk\Web\Models\Entities\Note': + $target_name = 'note'; + break; + case 'openvk\Web\Models\Entities\Photo': + $target_name = 'photo'; + break; + case 'openvk\Web\Models\Entities\Video': + $target_name = 'video'; + break; + case 'openvk\Web\Models\Entities\Topic': + $target_name = 'topic'; + break; + } + + return $target_name . $target->getPrettyId(); + } } diff --git a/Web/Models/Entities/Playlist.php b/Web/Models/Entities/Playlist.php index c027a038..1e9ea6c3 100644 --- a/Web/Models/Entities/Playlist.php +++ b/Web/Models/Entities/Playlist.php @@ -199,6 +199,11 @@ class Playlist extends MediaCollection { return $this->getRecord()->cover_photo_id; } + + function getCoverPhoto(): ?Photo + { + return (new Photos)->get((int) $this->getRecord()->cover_photo_id); + } function canBeModifiedBy(User $user): bool { diff --git a/Web/Models/Entities/User.php b/Web/Models/Entities/User.php index e8756550..b18da92c 100644 --- a/Web/Models/Entities/User.php +++ b/Web/Models/Entities/User.php @@ -1331,7 +1331,7 @@ class User extends RowModel return $this->getId(); } - function toVkApiStruct(?User $user = NULL): object + function toVkApiStruct(?User $user = NULL, string $fields = ''): object { $res = (object) []; @@ -1349,8 +1349,16 @@ class User extends RowModel if(!is_null($user)) $res->can_access_closed = (bool)$this->canBeViewedBy($user); - if($user->isDead()) - $res->is_dead = 1; + if(!is_array($fields)) + $fields = explode(',', $fields); + + foreach($fields as $field) { + switch($field) { + case 'is_dead': + $res->is_dead = $user->isDead(); + break; + } + } return $res; } diff --git a/Web/Models/Entities/Video.php b/Web/Models/Entities/Video.php index 2c1c0b05..a4d0b898 100644 --- a/Web/Models/Entities/Video.php +++ b/Web/Models/Entities/Video.php @@ -181,8 +181,8 @@ class Video extends Media { if(preg_match(file_get_contents(__DIR__ . "/../VideoDrivers/regex/youtube.txt"), $link, $matches)) { $pointer = "YouTube:$matches[1]"; - } else if(preg_match(file_get_contents(__DIR__ . "/../VideoDrivers/regex/vimeo.txt"), $link, $matches)) { - $pointer = "Vimeo:$matches[1]"; + /*} else if(preg_match(file_get_contents(__DIR__ . "/../VideoDrivers/regex/vimeo.txt"), $link, $matches)) { + $pointer = "Vimeo:$matches[1]";*/ } else { throw new ISE("Invalid link"); } diff --git a/Web/Models/Repositories/Applications.php b/Web/Models/Repositories/Applications.php index 0687856e..d889a5a4 100644 --- a/Web/Models/Repositories/Applications.php +++ b/Web/Models/Repositories/Applications.php @@ -67,11 +67,20 @@ class Applications return sizeof($this->appRels->where("user", $user->getId())); } - function find(string $query, array $pars = [], string $sort = "id"): Util\EntityStream + function find(string $query = "", array $params = [], array $order = ['type' => 'id', 'invert' => false]): Util\EntityStream { - $query = "%$query%"; - $result = $this->apps->where("CONCAT_WS(' ', name, description) LIKE ?", $query)->where("enabled", 1); + $result = $this->apps->where("CONCAT_WS(' ', name, description) LIKE ?", "%$query%")->where("enabled", 1); + $order_str = 'id'; + + switch($order['type']) { + case 'id': + $order_str = 'id ' . ($order['invert'] ? 'ASC' : 'DESC'); + break; + } + + if($order_str) + $result->order($order_str); - return new Util\EntityStream("Application", $result->order("$sort")); + return new Util\EntityStream("Application", $result); } } \ No newline at end of file diff --git a/Web/Models/Repositories/Audios.php b/Web/Models/Repositories/Audios.php index 64457299..5843b2b2 100644 --- a/Web/Models/Repositories/Audios.php +++ b/Web/Models/Repositories/Audios.php @@ -208,7 +208,7 @@ class Audios $search = $this->audios->where([ "unlisted" => 0, "deleted" => 0, - ])->where("MATCH ($columns) AGAINST (? WITH QUERY EXPANSION)", $query)->order($order); + ])->where("MATCH ($columns) AGAINST (? IN BOOLEAN MODE)", "%$query%")->order($order); if($withLyrics) $search = $search->where("lyrics IS NOT NULL"); @@ -243,53 +243,62 @@ class Audios ])->fetch()); } - function find(string $query, array $pars = [], string $sort = "id DESC", int $page = 1, ?int $perPage = NULL): \Traversable + function find(string $query, array $params = [], array $order = ['type' => 'id', 'invert' => false], int $page = 1, ?int $perPage = NULL): \Traversable { - $query = "%$query%"; $result = $this->audios->where([ "unlisted" => 0, "deleted" => 0, ]); + $order_str = 'id'; - $notNullParams = []; - - foreach($pars as $paramName => $paramValue) - if($paramName != "before" && $paramName != "after" && $paramName != "only_performers") - $paramValue != NULL ? $notNullParams+=["$paramName" => "%$paramValue%"] : NULL; - else - $paramValue != NULL ? $notNullParams+=["$paramName" => "$paramValue"] : NULL; - - $nnparamsCount = sizeof($notNullParams); - - if($notNullParams["only_performers"] == "1") { - $result->where("performer LIKE ?", $query); - } else { - $result->where("name LIKE ? OR performer LIKE ?", $query, $query); + switch($order['type']) { + case 'id': + $order_str = 'id ' . ($order['invert'] ? 'ASC' : 'DESC'); + break; + case 'length': + $order_str = 'length ' . ($order['invert'] ? 'ASC' : 'DESC'); + break; + case 'listens': + $order_str = 'listens ' . ($order['invert'] ? 'ASC' : 'DESC'); + break; } - if($nnparamsCount > 0) { - foreach($notNullParams as $paramName => $paramValue) { - switch($paramName) { - case "before": - $result->where("created < ?", $paramValue); - break; - case "after": - $result->where("created > ?", $paramValue); - break; - case "with_lyrics": - $result->where("lyrics IS NOT NULL"); - break; - } + if($params["only_performers"] == "1") { + $result->where("performer LIKE ?", "%$query%"); + } else { + $result->where("name LIKE ? OR performer LIKE ?", "%$query%", "%$query%"); + } + + foreach($params as $paramName => $paramValue) { + if(is_null($paramValue) || $paramValue == '') continue; + + switch($paramName) { + case "before": + $result->where("created < ?", $paramValue); + break; + case "after": + $result->where("created > ?", $paramValue); + break; + case "with_lyrics": + $result->where("lyrics IS NOT NULL"); + break; + case 'genre': + if($paramValue == 'any') break; + + $result->where("genre", $paramValue); + break; } } - return new Util\EntityStream("Audio", $result->order($sort)); + if($order_str) + $result->order($order_str); + + return new Util\EntityStream("Audio", $result); } function findPlaylists(string $query, int $page = 1, ?int $perPage = NULL): \Traversable { - $query = "%$query%"; - $result = $this->playlists->where("name LIKE ?", $query); + $result = $this->playlists->where("name LIKE ?", "%$query%"); return new Util\EntityStream("Playlist", $result); } diff --git a/Web/Models/Repositories/Clubs.php b/Web/Models/Repositories/Clubs.php index d77eac63..2b303ff4 100644 --- a/Web/Models/Repositories/Clubs.php +++ b/Web/Models/Repositories/Clubs.php @@ -42,13 +42,24 @@ class Clubs { return $this->toClub($this->clubs->get($id)); } - - function find(string $query, array $pars = [], string $sort = "id DESC", int $page = 1, ?int $perPage = NULL): \Traversable + + function find(string $query, array $params = [], array $order = ['type' => 'id', 'invert' => false], 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->order($sort)); + $result = $this->clubs; + $order_str = 'id'; + + switch($order['type']) { + case 'id': + $order_str = 'id ' . ($order['invert'] ? 'ASC' : 'DESC'); + break; + } + + $result = $result->where("name LIKE ? OR about LIKE ?", "%$query%", "%$query%"); + + if($order_str) + $result->order($order_str); + + return new Util\EntityStream("Club", $result); } function getCount(): int diff --git a/Web/Models/Repositories/Comments.php b/Web/Models/Repositories/Comments.php index f4b8e5ac..811d1358 100644 --- a/Web/Models/Repositories/Comments.php +++ b/Web/Models/Repositories/Comments.php @@ -60,34 +60,31 @@ class Comments ])); } - function find(string $query = "", array $pars = [], string $sort = "id"): Util\EntityStream + function find(string $query, array $params = [], array $order = ['type' => 'id', 'invert' => false]): Util\EntityStream { - $query = "%$query%"; + $result = $this->comments->where("content LIKE ?", "%$query%")->where("deleted", 0); + $order_str = 'id'; - $notNullParams = []; + switch($order['type']) { + case 'id': + $order_str = 'created ' . ($order['invert'] ? 'ASC' : 'DESC'); + break; + } - 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; - } + foreach($params 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")); + if($order_str) + $result->order($order_str); + + return new Util\EntityStream("Comment", $result); } } diff --git a/Web/Models/Repositories/Posts.php b/Web/Models/Repositories/Posts.php index fb32fe6e..31406771 100644 --- a/Web/Models/Repositories/Posts.php +++ b/Web/Models/Repositories/Posts.php @@ -154,36 +154,43 @@ class Posts } - function find(string $query = "", array $pars = [], string $sort = "id"): Util\EntityStream + function find(string $query = "", array $params = [], array $order = ['type' => 'id', 'invert' => false]): Util\EntityStream { - $query = "%$query%"; + $result = $this->posts->where("content LIKE ?", "%$query%")->where("deleted", 0)->where("suggested", 0); + $order_str = 'id'; - $notNullParams = []; + switch($order['type']) { + case 'id': + $order_str = 'created ' . ($order['invert'] ? 'ASC' : 'DESC'); + break; + } - foreach($pars as $paramName => $paramValue) - if($paramName != "before" && $paramName != "after") - $paramValue != NULL ? $notNullParams+=["$paramName" => "%$paramValue%"] : NULL; - else - $paramValue != NULL ? $notNullParams+=["$paramName" => "$paramValue"] : NULL; + foreach($params as $paramName => $paramValue) { + if(is_null($paramValue) || $paramValue == '') continue; - $result = $this->posts->where("content LIKE ?", $query)->where("deleted", 0)->where("suggested", 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; - } + switch($paramName) { + case "before": + $result->where("created < ?", $paramValue); + break; + case "after": + $result->where("created > ?", $paramValue); + break; + /*case 'die_in_agony': + $result->where("nsfw", 1); + break; + case 'ads': + $result->where("ad", 1); + break;*/ + case 'from_me': + $result->where("owner", $paramValue); + break; } } + if($order_str) + $result->order($order_str); - return new Util\EntityStream("Post", $result->order("$sort")); + return new Util\EntityStream("Post", $result); } function getPostCountOnUserWall(int $user): int diff --git a/Web/Models/Repositories/Users.php b/Web/Models/Repositories/Users.php index e826f3b3..e9de0cf8 100644 --- a/Web/Models/Repositories/Users.php +++ b/Web/Models/Repositories/Users.php @@ -54,94 +54,75 @@ class Users return $user ? $this->getByChandlerUserId($user->getId()) : NULL; } - function find(string $query, array $pars = [], string $sort = "id DESC"): Util\EntityStream + function find(string $query, array $params = [], array $order = ['type' => 'id', 'invert' => false]): Util\EntityStream { - $query = "%$query%"; - $result = $this->users->where("CONCAT_WS(' ', first_name, last_name, pseudo, shortcode) LIKE ?", $query)->where("deleted", 0); - - $notNullParams = []; - $nnparamsCount = 0; - - foreach($pars as $paramName => $paramValue) - if($paramName != "before" && $paramName != "after" && $paramName != "gender" && $paramName != "maritalstatus" && $paramName != "politViews" && $paramName != "doNotSearchMe") - $paramValue != NULL ? $notNullParams += ["$paramName" => "%$paramValue%"] : NULL; - else - $paramValue != NULL ? $notNullParams += ["$paramName" => "$paramValue"] : NULL; + $result = $this->users->where("CONCAT_WS(' ', first_name, last_name, pseudo, shortcode) LIKE ?", "%$query%")->where("deleted", 0); + $order_str = 'id'; - $nnparamsCount = sizeof($notNullParams); + switch($order['type']) { + case 'id': + case 'reg_date': + $order_str = 'since ' . ($order['invert'] ? 'ASC' : 'DESC'); + break; + case 'rating': + $order_str = 'rating DESC'; + break; + } - 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; - case "doNotSearchMe": - $result->where("id !=", $paramValue); - break; - case "doNotSearchPrivate": - $result->where("profile_type", 0); - break; - } + foreach($params as $paramName => $paramValue) { + if(is_null($paramValue) || $paramValue == '') continue; + + switch($paramName) { + case "hometown": + $result->where("hometown LIKE ?", "%$paramValue%"); + break; + case "city": + $result->where("city LIKE ?", "%$paramValue%"); + break; + case "marital_status": + $result->where("marital_status ?", $paramValue); + break; + case "polit_views": + $result->where("polit_views ?", $paramValue); + break; + case "is_online": + $result->where("online >= ?", time() - 900); + 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 "before": + $result->where("UNIX_TIMESTAMP(since) < ?", $paramValue); + break; + case "after": + $result->where("UNIX_TIMESTAMP(since) > ?", $paramValue); + break; + case "gender": + if((int) $paramValue == 3) break; + $result->where("sex ?", (int) $paramValue); + break; + case "ignore_id": + $result->where("id != ?", $paramValue); + break; + case "ignore_private": + $result->where("profile_type", 0); + break; } } + if($order_str) + $result->order($order_str); - return new Util\EntityStream("User", $result->order($sort)); + return new Util\EntityStream("User", $result); } function getStatistics(): object diff --git a/Web/Models/Repositories/Videos.php b/Web/Models/Repositories/Videos.php index 2d41c3f9..0204e2ff 100644 --- a/Web/Models/Repositories/Videos.php +++ b/Web/Models/Repositories/Videos.php @@ -46,36 +46,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 + function find(string $query = "", array $params = [], array $order = ['type' => 'id', 'invert' => false]): Util\EntityStream { - $query = "%$query%"; + $result = $this->videos->where("CONCAT_WS(' ', name, description) LIKE ?", "%$query%")->where("deleted", 0); + $order_str = 'id'; - $notNullParams = []; + switch($order['type']) { + case 'id': + $order_str = 'id ' . ($order['invert'] ? 'ASC' : 'DESC'); + break; + } - 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("CONCAT_WS(' ', name, 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; - } + foreach($params as $paramName => $paramValue) { + switch($paramName) { + case "before": + $result->where("created < ?", $paramValue); + break; + case "after": + $result->where("created > ?", $paramValue); + break; + case 'only_youtube': + if((int) $paramValue != 1) break; + $result->where("link != ?", 'NULL'); + break; } } + if($order_str) + $result->order($order_str); - return new Util\EntityStream("Video", $result->order("$sort")); + return new Util\EntityStream("Video", $result); } function getLastVideo(User $user) diff --git a/Web/Presenters/AudioPresenter.php b/Web/Presenters/AudioPresenter.php index 8ec17012..78d3ab52 100644 --- a/Web/Presenters/AudioPresenter.php +++ b/Web/Presenters/AudioPresenter.php @@ -279,7 +279,7 @@ final class AudioPresenter extends OpenVKPresenter function renderSearch(): void { - $this->redirect("/search?type=audios"); + $this->redirect("/search?section=audios"); } function renderNewPlaylist(): void @@ -475,6 +475,7 @@ final class AudioPresenter extends OpenVKPresenter $this->template->playlist = $playlist; $this->template->page = $page; + $this->template->cover = $playlist->getCoverPhoto(); $this->template->audios = iterator_to_array($playlist->fetch($page, 10)); $this->template->ownerId = $owner_id; $this->template->owner = $playlist->getOwner(); diff --git a/Web/Presenters/SearchPresenter.php b/Web/Presenters/SearchPresenter.php index 02394503..0e23ac57 100644 --- a/Web/Presenters/SearchPresenter.php +++ b/Web/Presenters/SearchPresenter.php @@ -1,7 +1,7 @@ users = $users; - $this->clubs = $clubs; + $this->users = new Users; + $this->clubs = new Clubs; $this->posts = new Posts; $this->comments = new Comments; $this->videos = new Videos; $this->apps = new Applications; - $this->notes = new Notes; $this->audios = new Audios; parent::__construct(); @@ -33,13 +32,14 @@ final class SearchPresenter extends OpenVKPresenter { $this->assertUserLoggedIn(); - $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); - + $query = $this->queryParam("q") ?? ""; + $section = $this->queryParam("section") ?? "users"; + $order = $this->queryParam("order") ?? "id"; + $invert = (int) ($this->queryParam("invert") ?? 0) == 1; + $page = (int) ($this->queryParam("p") ?? 1); + # https://youtu.be/pSAWM5YuXx8 + # https://youtu.be/FfNZRhIn2Vk $repos = [ "groups" => "clubs", @@ -48,70 +48,74 @@ final class SearchPresenter extends OpenVKPresenter "comments" => "comments", "videos" => "videos", "audios" => "audios", - "apps" => "apps", - "notes" => "notes" + "apps" => "apps" + ]; + $parameters = [ + "ignore_private" => true, ]; - switch($sorter) { - default: - case "id": - $sort = "id " . $invert; - break; - case "name": - $sort = "first_name " . $invert; - break; - case "rating": - $sort = "rating " . $invert; - break; - case "length": - if($type != "audios") break; - - $sort = "length " . $invert; - break; - case "listens": - if($type != "audios") break; - - $sort = "listens " . $invert; - break; + foreach($_REQUEST as $param_name => $param_value) { + if(is_null($param_value)) continue; + + switch($param_name) { + default: + $parameters[$param_name] = $param_value; + break; + case 'marital_status': + case 'polit_views': + if((int) $param_value == 0) continue; + $parameters[$param_name] = $param_value; + + break; + case 'is_online': + if((int) $param_value == 1) + $parameters['is_online'] = 1; + + break; + case 'only_performers': + if((int) $param_value != 1 || $param_value != 'on') continue; + $parameters['only_performers'] = true; + + break; + case 'with_lyrics': + if($param_value == 'on' || $param_value == '1') + $parameters['with_lyrics'] = true; + + break; + case 'from_me': + if((int) $param_value != 1) continue; + $parameters['from_me'] = $this->user->id; + + 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, - "doNotSearchPrivate" => true, - "only_performers" => $this->queryParam("only_performers") == "on" ? "1" : NULL, - "with_lyrics" => $this->queryParam("with_lyrics") == "on" ? true : NULL, - ]; - - $repo = $repos[$type] or $this->throwError(400, "Bad Request", "Invalid search entity $type."); + $repo = $repos[$section] or $this->throwError(400, "Bad Request", "Invalid search entity $section."); - $results = $this->{$repo}->find($query, $parameters, $sort); - $iterator = $results->page($page, 14); + $results = $this->{$repo}->find($query, $parameters, ['type' => $order, 'invert' => $invert]); + $iterator = $results->page($page, OPENVK_DEFAULT_PER_PAGE); $count = $results->size(); - $this->template->iterator = iterator_to_array($iterator); + $this->template->order = $order; + $this->template->data = $this->template->iterator = iterator_to_array($iterator); $this->template->count = $count; - $this->template->type = $type; + $this->template->section = $section; $this->template->page = $page; - $this->template->perPage = 14; + $this->template->perPage = OPENVK_DEFAULT_PER_PAGE; + $this->template->query = $query; + $this->template->atSearch = true; + + $this->template->paginatorConf = (object) [ + "page" => $page, + "count" => $count, + "amount" => sizeof($this->template->data), + "perPage" => $this->template->perPage, + "atBottom" => false, + "tidy" => true, + "space" => 6, + 'pageCount' => ceil($count / $this->template->perPage), + ]; + $this->template->extendedPaginatorConf = clone $this->template->paginatorConf; + $this->template->extendedPaginatorConf->space = 12; } } diff --git a/Web/Presenters/templates/@layout.xml b/Web/Presenters/templates/@layout.xml index 803ebdd0..09270ea9 100644 --- a/Web/Presenters/templates/@layout.xml +++ b/Web/Presenters/templates/@layout.xml @@ -87,7 +87,7 @@