From 53f6b3e12be9a191c48178fe4728a7fbeb69972e Mon Sep 17 00:00:00 2001 From: mrilyew <99399973+mrilyew@users.noreply.github.com> Date: Fri, 25 Oct 2024 16:28:35 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9E=D0=B1=D0=BD=D0=BE=D0=B2=D1=8B=20=D0=B4?= =?UTF-8?q?=D0=BB=D1=8F=20=D0=BF=D0=BB=D0=B5=D0=B9=D0=BB=D0=B8=D1=81=D1=82?= =?UTF-8?q?=D0=BE=D0=B2=20=D0=B8=20=D0=BF=D0=BE=D0=B8=D1=81=D0=BA=D0=B0=20?= =?UTF-8?q?(#1137)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * search: a bit refactor * search: a bit refactor 2 * audios: a bit changes * results highlight, midnight changes, player insear * add audio download button, simplify css * upload page changes, add playlist add menu * -comments search, arrow keys on tips * move $query var and optimize users/groups.search го рофлить * слегка проебался --- ServiceAPI/Search.php | 76 -- VKAPI/Handlers/Audio.php | 13 +- VKAPI/Handlers/Groups.php | 21 +- VKAPI/Handlers/Users.php | 118 +-- VKAPI/Handlers/Video.php | 56 ++ Web/Models/Entities/Audio.php | 5 + Web/Models/Entities/Club.php | 2 +- Web/Models/Entities/Comment.php | 27 + Web/Models/Entities/Playlist.php | 26 + Web/Models/Entities/Traits/TRichText.php | 2 +- Web/Models/Entities/User.php | 21 +- Web/Models/Entities/Video.php | 4 +- Web/Models/Repositories/Applications.php | 16 +- Web/Models/Repositories/Audios.php | 82 ++- Web/Models/Repositories/Clubs.php | 24 +- Web/Models/Repositories/Comments.php | 43 +- Web/Models/Repositories/Posts.php | 53 +- Web/Models/Repositories/Users.php | 146 ++-- Web/Models/Repositories/Videos.php | 47 +- Web/Presenters/AudioPresenter.php | 151 +++- Web/Presenters/SearchPresenter.php | 148 ++-- Web/Presenters/templates/@layout.xml | 84 +-- .../templates/Audio/EditPlaylist.xml | 11 +- Web/Presenters/templates/Audio/List.xml | 87 +-- .../templates/Audio/NewPlaylist.xml | 10 +- Web/Presenters/templates/Audio/Playlist.xml | 32 +- Web/Presenters/templates/Audio/Upload.xml | 82 ++- Web/Presenters/templates/Audio/bigplayer.xml | 10 +- Web/Presenters/templates/Audio/player.xml | 32 +- .../templates/Audio/playlistListView.xml | 20 + Web/Presenters/templates/Audio/tabs.xml | 42 +- Web/Presenters/templates/Search/Index.xml | 697 +++++++++--------- Web/Presenters/templates/User/View.xml | 16 +- Web/Presenters/templates/Videos/List.xml | 6 +- .../templates/components/comment.xml | 37 +- .../templates/components/content_error.xml | 6 + .../templates/components/paginator.xml | 6 +- Web/Presenters/templates/components/video.xml | 8 +- Web/Util/Makima/Makima.php | 2 +- Web/static/css/audios.css | 256 +++++-- Web/static/css/main.css | 507 ++++++++----- Web/static/img/arrows.png | Bin 0 -> 219 bytes Web/static/img/audios_controls.png | Bin 3706 -> 4259 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 | 349 ++++++--- Web/static/js/al_navigation.js | 190 +++++ Web/static/js/al_wall.js | 59 +- Web/static/js/openvk.cls.js | 132 +--- install/sqls/00047-unlisted-playlists.sql | 1 + locales/en.strings | 44 +- locales/ru.strings | 48 +- locales/uk.strings | 4 - themepacks/midnight/stylesheet.css | 64 +- themepacks/openvk_modern/stylesheet.css | 84 +-- 55 files changed, 2451 insertions(+), 1556 deletions(-) delete mode 100644 ServiceAPI/Search.php create mode 100644 Web/Presenters/templates/Audio/playlistListView.xml 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 create mode 100644 install/sqls/00047-unlisted-playlists.sql diff --git a/ServiceAPI/Search.php b/ServiceAPI/Search.php deleted file mode 100644 index de0f9d2c3..000000000 --- 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/Audio.php b/VKAPI/Handlers/Audio.php index 004daef49..e0991af92 100644 --- a/VKAPI/Handlers/Audio.php +++ b/VKAPI/Handlers/Audio.php @@ -581,13 +581,18 @@ function getAlbums(int $owner_id = 0, int $offset = 0, int $count = 50, int $dro ]; } - function searchAlbums(string $query, int $offset = 0, int $limit = 25, int $drop_private = 0): object + function searchAlbums(string $query = '', int $offset = 0, int $limit = 25, int $drop_private = 0, int $order = 0, int $from_me = 0): object { $this->requireUser(); $playlists = []; - $search = (new Audios)->searchPlaylists($query)->offsetLimit($offset, $limit); - foreach($search as $playlist) { + $params = []; + $order_str = (['id', 'length', 'listens'][$order] ?? 'id'); + if($from_me === 1) + $params['from_me'] = $this->getUser()->getId(); + + $search = (new Audios)->findPlaylists($query, $params, ['type' => $order_str, 'invert' => false]); + foreach($search->offsetLimit($offset, $limit) as $playlist) { if(!$playlist->canBeViewedBy($this->getUser())) { if($drop_private == 0) $playlists[] = NULL; @@ -599,7 +604,7 @@ function searchAlbums(string $query, int $offset = 0, int $limit = 25, int $drop } return (object) [ - "count" => sizeof($playlists), + "count" => $search->size(), "items" => $playlists, ]; } diff --git a/VKAPI/Handlers/Groups.php b/VKAPI/Handlers/Groups.php index ca67e7b76..f87061911 100644 --- a/VKAPI/Handlers/Groups.php +++ b/VKAPI/Handlers/Groups.php @@ -252,23 +252,30 @@ function getById(string $group_ids = "", string $group_id = "", string $fields = 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") { + if($count > 100) { + $this->fail(100, "One of the parameters specified was missing or invalid: count should be less or equal to 100"); + } + $clubs = new ClubsRepo; $array = []; $find = $clubs->find($q); - foreach ($find as $group) + foreach ($find->offsetLimit($offset, $count) as $group) $array[] = $group->getId(); + + if(!$array || sizeof($array) < 1) { + return (object) [ + "count" => 0, + "items" => [], + ]; + } 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) ]; } diff --git a/VKAPI/Handlers/Users.php b/VKAPI/Handlers/Users.php index 132b62044..704823be8 100644 --- a/VKAPI/Handlers/Users.php +++ b/VKAPI/Handlers/Users.php @@ -263,6 +263,9 @@ function get(string $user_ids = "0", string $fields = "", int $offset = 0, int $ case 'is_dead': $response[$i]->is_dead = $usr->isDead(); break; + case 'nickname': + $response[$i]->nickname = $usr->getPseudo(); + break; } } @@ -314,89 +317,90 @@ function search(string $q, 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"; + if($count > 100) { + $this->fail(100, "One of the parameters specified was missing or invalid: count should be less or equal to 100"); + } - $nfilds = $fields; + $users = new UsersRepo; + $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"; + $output_sort = ['type' => 'rating', 'invert' => false]; + break; + } - if(!str_contains($nfilds, "rating")) { - $nfilds .= "rating"; - } + if(!empty($city)) + $output_params['city'] = $city; - break; - case 5: - $sortg = "rating DESC"; + if(!empty($hometown)) + $output_params['hometown'] = $hometown; - if(!str_contains($nfilds, "rating")) { - $nfilds .= "rating"; - } + if($sex != 3) + $output_params['gender'] = $sex; - break; - } + if($status != 0) + $output_params['marital_status'] = $status; + + if($polit_views != 0) + $output_params['polit_views'] = $polit_views; - $array = []; + if(!empty($interests)) + $output_params['interests'] = $interests; - $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, - ]; + if(!empty($fav_music)) + $output_params['fav_music'] = $fav_music; + + if(!empty($fav_films)) + $output_params['fav_films'] = $fav_films; - $find = $users->find($q, $parameters, $sortg); + if(!empty($fav_shows)) + $output_params['fav_shows'] = $fav_shows; + + if(!empty($fav_books)) + $output_params['fav_books'] = $fav_books; - foreach ($find as $user) + if($online) + $output_params['is_online'] = 1; + + $array = []; + $find = $users->find($q, $output_params, $output_sort); + + foreach ($find->offsetLimit($offset, $count) as $user) $array[] = $user->getId(); + if(!$array || sizeof($array) < 1) { + return (object) [ + "count" => 0, + "items" => [], + ]; + } + return (object) [ - "count" => $find->size(), - "items" => $this->get(implode(',', $array), $nfilds, $offset, $count) + "count" => $find->size(), + "items" => $this->get(implode(',', $array), $fields) ]; } diff --git a/VKAPI/Handlers/Video.php b/VKAPI/Handlers/Video.php index f468686dc..d933f728e 100755 --- a/VKAPI/Handlers/Video.php +++ b/VKAPI/Handlers/Video.php @@ -60,4 +60,60 @@ function get(int $owner_id, string $videos = "", int $offset = 0, int $count = 3 ]; } } + + 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/Audio.php b/Web/Models/Entities/Audio.php index 6be207ddd..3b998f329 100644 --- a/Web/Models/Entities/Audio.php +++ b/Web/Models/Entities/Audio.php @@ -152,6 +152,11 @@ function getName(): string return $this->getPerformer() . " — " . $this->getTitle(); } + function getDownloadName(): string + { + return preg_replace('/[\\/:*?"<>|]/', '_', str_replace(' ', '_', $this->getName())); + } + function getGenre(): ?string { return $this->getRecord()->genre; diff --git a/Web/Models/Entities/Club.php b/Web/Models/Entities/Club.php index dc1c356e7..c919b059b 100644 --- a/Web/Models/Entities/Club.php +++ b/Web/Models/Entities/Club.php @@ -437,7 +437,7 @@ function getAudiosCollectionSize() 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 200d7a168..fd32c0b8b 100644 --- a/Web/Models/Entities/Comment.php +++ b/Web/Models/Entities/Comment.php @@ -140,4 +140,31 @@ function canBeEditedBy(?User $user = NULL): bool 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 c027a0387..ac36b4f34 100644 --- a/Web/Models/Entities/Playlist.php +++ b/Web/Models/Entities/Playlist.php @@ -41,6 +41,21 @@ function getLength(): int { return $this->getRecord()->length; } + + function fetchClassic(int $offset = 0, ?int $limit = NULL): \Traversable + { + $related = $this->getRecord()->related("$this->relTableName.collection") + ->limit($limit ?? OPENVK_DEFAULT_PER_PAGE, $offset) + ->order("index ASC"); + + foreach($related as $rel) { + $media = $rel->ref($this->entityTableName, "media"); + if(!$media) + continue; + + yield new $this->entityClassName($media); + } + } function getAudios(int $offset = 0, ?int $limit = NULL, ?int $shuffleSeed = NULL): \Traversable { @@ -162,6 +177,7 @@ function toVkApiStruct(?User $user = NULL): object "bookmarked" => $this->isBookmarkedBy($user), "listens" => $this->getListens(), "cover_url" => $this->getCoverURL(), + "searchable" => !$this->isUnlisted(), ]; } @@ -199,6 +215,11 @@ function getCoverPhotoId(): ?int { return $this->getRecord()->cover_photo_id; } + + function getCoverPhoto(): ?Photo + { + return (new Photos)->get((int) $this->getRecord()->cover_photo_id); + } function canBeModifiedBy(User $user): bool { @@ -253,4 +274,9 @@ function getMetaDescription(): string return implode(" • ", $props); } + + function isUnlisted(): bool + { + return (bool)$this->getRecord()->unlisted; + } } diff --git a/Web/Models/Entities/Traits/TRichText.php b/Web/Models/Entities/Traits/TRichText.php index dc78a0345..0f02a8ab4 100644 --- a/Web/Models/Entities/Traits/TRichText.php +++ b/Web/Models/Entities/Traits/TRichText.php @@ -123,7 +123,7 @@ function getText(bool $html = true): string $text = preg_replace_callback("%([\n\r\s]|^)(\#([\p{L}_0-9][\p{L}_0-9\(\)\-\']+[\p{L}_0-9\(\)]|[\p{L}_0-9]{1,2}))%Xu", function($m) { $slug = rawurlencode($m[3]); - return "$m[1]$m[2]"; + return "$m[1]$m[2]"; }, $text); $text = $this->formatEmojis($text); diff --git a/Web/Models/Entities/User.php b/Web/Models/Entities/User.php index e8756550c..18d7fea9e 100644 --- a/Web/Models/Entities/User.php +++ b/Web/Models/Entities/User.php @@ -1321,17 +1321,22 @@ function canBeViewedBy(?User $user = NULL): bool return true; } - function isClosed() + function isClosed(): bool { return (bool) $this->getProfileType(); } + + function isHideFromGlobalFeedEnabled(): bool + { + return $this->isClosed(); + } function getRealId() { return $this->getId(); } - function toVkApiStruct(?User $user = NULL): object + function toVkApiStruct(?User $user = NULL, string $fields = ''): object { $res = (object) []; @@ -1349,8 +1354,16 @@ function toVkApiStruct(?User $user = NULL): object 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 2c1c0b051..a4d0b8987 100644 --- a/Web/Models/Entities/Video.php +++ b/Web/Models/Entities/Video.php @@ -181,8 +181,8 @@ function setLink(string $link): string { 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 0687856e6..c09060676 100644 --- a/Web/Models/Repositories/Applications.php +++ b/Web/Models/Repositories/Applications.php @@ -67,11 +67,21 @@ function getInstalledCount(User $user): int 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%"; + $query = "%$query%"; $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 64457299f..73f5ac293 100644 --- a/Web/Models/Repositories/Audios.php +++ b/Web/Models/Repositories/Audios.php @@ -208,7 +208,7 @@ function search(string $query, int $sortMode = 0, bool $performerOnly = false, b $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"); @@ -219,6 +219,7 @@ function search(string $query, int $sortMode = 0, bool $performerOnly = false, b function searchPlaylists(string $query): EntityStream { $search = $this->playlists->where([ + "unlisted" => 0, "deleted" => 0, ])->where("MATCH (`name`, `description`) AGAINST (? IN BOOLEAN MODE)", $query); @@ -243,53 +244,72 @@ function isAdded(int $user_id, int $audio_id): bool ])->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%"; + $query = "%$query%"; $result = $this->audios->where([ "unlisted" => 0, "deleted" => 0, ]); + $order_str = (in_array($order['type'], ['id', 'length', 'listens']) ? $order['type'] : 'id') . ' ' . ($order['invert'] ? 'ASC' : 'DESC');; - $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") { + if($params["only_performers"] == "1") { $result->where("performer LIKE ?", $query); } else { $result->where("name LIKE ? OR performer LIKE ?", $query, $query); } - 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; - } + 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 + function findPlaylists(string $query, array $params = [], array $order = ['type' => 'id', 'invert' => false]): \Traversable { - $query = "%$query%"; - $result = $this->playlists->where("name LIKE ?", $query); + $query = "%$query%"; + $result = $this->playlists->where([ + "deleted" => 0, + ])->where("CONCAT_WS(' ', name, description) LIKE ?", $query); + $order_str = (in_array($order['type'], ['id', 'length', 'listens']) ? $order['type'] : 'id') . ' ' . ($order['invert'] ? 'ASC' : 'DESC'); + + if(is_null($params['from_me']) || empty($params['from_me'])) + $result->where(["unlisted" => 0]); + + foreach($params as $paramName => $paramValue) { + if(is_null($paramValue) || $paramValue == '') continue; + + switch($paramName) { + # БУДЬ МАКСИМАЛЬНО АККУРАТЕН С ДАННЫМ ПАРАМЕТРОМ + case "from_me": + $result->where("owner", $paramValue); + break; + } + } + + if($order_str) + $result->order($order_str); return new Util\EntityStream("Playlist", $result); } diff --git a/Web/Models/Repositories/Clubs.php b/Web/Models/Repositories/Clubs.php index d77eac638..b393952fe 100644 --- a/Web/Models/Repositories/Clubs.php +++ b/Web/Models/Repositories/Clubs.php @@ -42,13 +42,25 @@ function get(int $id): ?Club { 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)); + $query = "%$query%"; + $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 f4b8e5ace..811d1358c 100644 --- a/Web/Models/Repositories/Comments.php +++ b/Web/Models/Repositories/Comments.php @@ -60,34 +60,31 @@ function getCommentsCountByTarget(Postable $target): int ])); } - 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 = []; - - 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); + switch($order['type']) { + case 'id': + $order_str = 'created ' . ($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; - } + 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 fb32fe6e5..36082f245 100644 --- a/Web/Models/Repositories/Posts.php +++ b/Web/Models/Repositories/Posts.php @@ -154,36 +154,45 @@ function getPostById(int $wall, int $post, bool $forceSuggestion = false): ?Post } - 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%"; + $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 e826f3b3c..cc75b50f0 100644 --- a/Web/Models/Repositories/Users.php +++ b/Web/Models/Repositories/Users.php @@ -54,94 +54,76 @@ function getByChandlerUser(?ChandlerUser $user): ?User 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%"; + $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; - - $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; - case "doNotSearchMe": - $result->where("id !=", $paramValue); - break; - case "doNotSearchPrivate": - $result->where("profile_type", 0); - break; - } + $order_str = 'id'; + + switch($order['type']) { + case 'id': + case 'reg_date': + $order_str = 'id ' . ($order['invert'] ? 'ASC' : 'DESC'); + break; + case 'rating': + $order_str = 'rating DESC'; + 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 2d41c3f9a..e91c226d1 100644 --- a/Web/Models/Repositories/Videos.php +++ b/Web/Models/Repositories/Videos.php @@ -46,36 +46,37 @@ function getUserVideosCount(User $user): int 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%"; - - $notNullParams = []; - - foreach($pars as $paramName => $paramValue) - if($paramName != "before" && $paramName != "after") - $paramValue != NULL ? $notNullParams+=["$paramName" => "%$paramValue%"] : NULL; - else - $paramValue != NULL ? $notNullParams+=["$paramName" => "$paramValue"] : NULL; - + $query = "%$query%"; $result = $this->videos->where("CONCAT_WS(' ', name, description) LIKE ?", $query)->where("deleted", 0); - $nnparamsCount = sizeof($notNullParams); + $order_str = 'id'; + + switch($order['type']) { + case 'id': + $order_str = 'id ' . ($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; - } + 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 8ec17012d..7e2825c13 100644 --- a/Web/Presenters/AudioPresenter.php +++ b/Web/Presenters/AudioPresenter.php @@ -75,7 +75,7 @@ function renderList(?int $owner = NULL, ?string $mode = "list"): void if (!$entity || $entity->isBanned()) $this->redirect("/playlists" . $this->user->id); - $playlists = $this->audios->getPlaylistsByClub($entity, $page, 10); + $playlists = $this->audios->getPlaylistsByClub($entity, $page, OPENVK_DEFAULT_PER_PAGE); $playlistsCount = $this->audios->getClubPlaylistsCount($entity); } else { $entity = (new Users)->get($owner); @@ -85,7 +85,7 @@ function renderList(?int $owner = NULL, ?string $mode = "list"): void if(!$entity->getPrivacyPermission("audios.read", $this->user->identity)) $this->flashFail("err", tr("forbidden"), tr("forbidden_comment")); - $playlists = $this->audios->getPlaylistsByUser($entity, $page, 9); + $playlists = $this->audios->getPlaylistsByUser($entity, $page, OPENVK_DEFAULT_PER_PAGE); $playlistsCount = $this->audios->getUserPlaylistsCount($entity); } @@ -109,8 +109,8 @@ function renderList(?int $owner = NULL, ?string $mode = "list"): void $this->template->mode = $mode; $this->template->page = $page; - - if(in_array($mode, ["list", "new", "popular"]) && $this->user->identity) + + if(in_array($mode, ["list", "new", "popular"]) && $this->user->identity && $page < 2) $this->template->friendsAudios = $this->user->identity->getBroadcastList("all", true); } @@ -142,7 +142,13 @@ function renderUpload(): void $this->assertUserLoggedIn(); $group = NULL; + $playlist = NULL; $isAjax = $this->postParam("ajax", false) == 1; + + if(!is_null($this->queryParam("gid")) && !is_null($this->queryParam("playlist"))) { + $this->flashFail("err", tr("forbidden"), tr("not_enough_permissions_comment"), null, $isAjax); + } + if(!is_null($this->queryParam("gid"))) { $gid = (int) $this->queryParam("gid"); $group = (new Clubs)->get($gid); @@ -153,6 +159,19 @@ function renderUpload(): void $this->flashFail("err", tr("forbidden"), tr("not_enough_permissions_comment"), null, $isAjax); } + if(!is_null($this->queryParam("playlist"))) { + $playlist_id = (int)$this->queryParam("playlist"); + $playlist = (new Audios)->getPlaylist($playlist_id); + if(!$playlist || $playlist->isDeleted()) + $this->flashFail("err", tr("forbidden"), tr("not_enough_permissions_comment"), null, $isAjax); + + if(!$playlist->canBeModifiedBy($this->user->identity)) + $this->flashFail("err", tr("forbidden"), tr("not_enough_permissions_comment"), null, $isAjax); + + $this->template->playlist = $playlist; + $this->template->owner = $playlist->getOwner(); + } + $this->template->group = $group; if($_SERVER["REQUEST_METHOD"] !== "POST") @@ -196,6 +215,8 @@ function renderUpload(): void $lyrics = $this->postParam("lyrics"); $genre = empty($this->postParam("genre")) ? "Other" : $this->postParam("genre"); $nsfw = ($this->postParam("explicit") ?? "off") === "on"; + $is_unlisted = ($this->postParam("unlisted") ?? "off") === "on"; + if(empty($performer) || empty($name) || iconv_strlen($performer . $name) > 128) # FQN of audio must not be more than 128 chars $this->flashFail("err", tr("error"), tr("error_insufficient_info"), null, $isAjax); @@ -206,6 +227,7 @@ function renderUpload(): void $audio->setLyrics(empty($lyrics) ? NULL : $lyrics); $audio->setGenre($genre); $audio->setExplicit($nsfw); + $audio->setUnlisted($is_unlisted); try { $audio->setFile($upload); @@ -215,13 +237,18 @@ function renderUpload(): void } catch(\RuntimeException $ex) { $this->flashFail("err", tr("error"), tr("ffmpeg_timeout"), null, $isAjax); } catch(\BadMethodCallException $ex) { - $this->flashFail("err", tr("error"), "Загрузка аудио под Linux на данный момент не реализована. Следите за обновлениями: https://github.com/openvk/openvk/pull/512/commits", null, $isAjax); + $this->flashFail("err", tr("error"), "хз", null, $isAjax); } catch(\Exception $ex) { $this->flashFail("err", tr("error"), tr("ffmpeg_not_installed"), null, $isAjax); } $audio->save(); - $audio->add($group ?? $this->user->identity); + + if($playlist) { + $playlist->add($audio); + } else { + $audio->add($group ?? $this->user->identity); + } if(!$isAjax) $this->redirect(is_null($group) ? "/audios" . $this->user->id : "/audios-" . $group->getId()); @@ -233,9 +260,9 @@ function renderUpload(): void else $redirectLink .= $this->user->id; - $pagesCount = (int)ceil((new Audios)->getCollectionSizeByEntityId(isset($group) ? $group->getRealId() : $this->user->id) / 10); - $redirectLink .= "?p=".$pagesCount; - + if($playlist) + $redirectLink = "/playlist" . $playlist->getPrettyId(); + $this->returnJson([ "success" => true, "redirect_link" => $redirectLink, @@ -279,7 +306,7 @@ function renderListen(int $id): void function renderSearch(): void { - $this->redirect("/search?type=audios"); + $this->redirect("/search?section=audios"); } function renderNewPlaylist(): void @@ -304,6 +331,8 @@ function renderNewPlaylist(): void if ($_SERVER["REQUEST_METHOD"] === "POST") { $title = $this->postParam("title"); $description = $this->postParam("description"); + $is_unlisted = (int)$this->postParam('is_unlisted'); + $audios = !empty($this->postParam("audios")) ? array_slice(explode(",", $this->postParam("audios")), 0, 1000) : []; if(empty($title) || iconv_strlen($title) < 1) @@ -313,7 +342,9 @@ function renderNewPlaylist(): void $playlist->setOwner($owner); $playlist->setName(substr($title, 0, 125)); $playlist->setDescription(substr($description, 0, 2045)); - + if($is_unlisted == 1) + $playlist->setUnlisted(true); + if($_FILES["cover"]["error"] === UPLOAD_ERR_OK) { if(!str_starts_with($_FILES["cover"]["type"], "image")) $this->flashFail("err", tr("error"), tr("not_a_photo")); @@ -427,6 +458,7 @@ function renderEditPlaylist(int $owner_id, int $virtual_id) $title = $this->postParam("title"); $description = $this->postParam("description"); + $is_unlisted = (int)$this->postParam('is_unlisted'); $new_audios = !empty($this->postParam("audios")) ? explode(",", rtrim($this->postParam("audios"), ",")) : []; if(empty($title) || iconv_strlen($title) < 1) @@ -436,6 +468,7 @@ function renderEditPlaylist(int $owner_id, int $virtual_id) $playlist->setDescription(ovk_proc_strtr($description, 2045)); $playlist->setEdited(time()); $playlist->resetLength(); + $playlist->setUnlisted((bool)$is_unlisted); if($_FILES["new_cover"]["error"] === UPLOAD_ERR_OK) { if(!str_starts_with($_FILES["new_cover"]["type"], "image")) @@ -475,12 +508,15 @@ function renderPlaylist(int $owner_id, int $virtual_id): void $this->template->playlist = $playlist; $this->template->page = $page; + $this->template->cover = $playlist->getCoverPhoto(); + $this->template->cover_url = $this->template->cover ? $this->template->cover->getURL() : "/assets/packages/static/openvk/img/song.jpg"; $this->template->audios = iterator_to_array($playlist->fetch($page, 10)); $this->template->ownerId = $owner_id; $this->template->owner = $playlist->getOwner(); $this->template->isBookmarked = $this->user->identity && $playlist->isBookmarkedBy($this->user->identity); $this->template->isMy = $this->user->identity && $playlist->getOwner()->getId() === $this->user->id; - $this->template->canEdit = $this->user->identity && $playlist->canBeModifiedBy($this->user->identity); + $this->template->canEdit = $this->user->identity && $playlist->canBeModifiedBy($this->user->identity); + $this->template->count = $playlist->size(); } function renderAction(int $audio_id): void @@ -531,16 +567,65 @@ function renderAction(int $audio_id): void break; case "add_to_club": - $club = (new Clubs)->get((int)$this->postParam("club")); - - if(!$club || !$club->canBeModifiedBy($this->user->identity)) - $this->flashFail("err", "error", tr("access_denied"), null, true); - - if(!$audio->isInLibraryOf($club)) - $audio->add($club); - else - $this->flashFail("err", "error", tr("group_has_audio"), null, true); - + $detailed = []; + if($audio->isWithdrawn()) + $this->flashFail("err", "error", tr("invalid_audio"), null, true); + + if(empty($this->postParam("clubs"))) + $this->flashFail("err", "error", 'clubs not passed', null, true); + + $clubs_arr = explode(',', $this->postParam("clubs")); + $count = sizeof($clubs_arr); + if($count < 1 || $count > 10) { + $this->flashFail("err", "error", tr('too_many_or_to_lack'), null, true); + } + + foreach($clubs_arr as $club_id) { + $club = (new Clubs)->get((int)$club_id); + if(!$club || !$club->canBeModifiedBy($this->user->identity)) + continue; + + if(!$audio->isInLibraryOf($club)) { + $detailed[$club_id] = true; + $audio->add($club); + } else { + $detailed[$club_id] = false; + continue; + } + } + + $this->returnJson(["success" => true, 'detailed' => $detailed]); + break; + case "add_to_playlist": + $detailed = []; + if($audio->isWithdrawn()) + $this->flashFail("err", "error", tr("invalid_audio"), null, true); + + if(empty($this->postParam("playlists"))) + $this->flashFail("err", "error", 'playlists not passed', null, true); + + $playlists_arr = explode(',', $this->postParam("playlists")); + $count = sizeof($playlists_arr); + if($count < 1 || $count > 10) { + $this->flashFail("err", "error", tr('too_many_or_to_lack'), null, true); + } + + foreach($playlists_arr as $playlist_id) { + $pid = explode('_', $playlist_id); + $playlist = (new Audios)->getPlaylistByOwnerAndVID((int)$pid[0], (int)$pid[1]); + if(!$playlist || !$playlist->canBeModifiedBy($this->user->identity)) + continue; + + if(!$playlist->hasAudio($audio)) { + $playlist->add($audio); + $detailed[$playlist_id] = true; + } else { + $detailed[$playlist_id] = false; + continue; + } + } + + $this->returnJson(["success" => true, 'detailed' => $detailed]); break; case "delete": if($audio->canBeModifiedBy($this->user->identity)) @@ -653,6 +738,28 @@ function renderApiGetContext() $audios = $stream->page($page, 10); $audiosCount = $stream->size(); break; + case "classic_search_context": + $data = json_decode($this->postParam("context_entity"), true); + + $params = []; + $order = [ + "type" => $data['order'] ?? 'id', + "invert" => (int)$data['invert'] == 1 ? true : false + ]; + + if($data['genre'] && $data['genre'] != 'any') + $params['genre'] = $data['genre']; + + if($data['only_performers'] && (int)$data['only_performers'] == 1) + $params['only_performers'] = '1'; + + if($data['with_lyrics'] && (int)$data['with_lyrics'] == 1) + $params['with_lyrics'] = '1'; + + $stream = $this->audios->find($data['query'], $params, $order); + $audios = $stream->page($page, 10); + $audiosCount = $stream->size(); + break; } $pagesCount = ceil($audiosCount / $perPage); diff --git a/Web/Presenters/SearchPresenter.php b/Web/Presenters/SearchPresenter.php index 023945035..72c34e895 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,85 +29,101 @@ function renderIndex(): void { $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", "users" => "users", "posts" => "posts", - "comments" => "comments", "videos" => "videos", "audios" => "audios", "apps" => "apps", - "notes" => "notes" + "audios_playlists" => "audios" ]; + $parameters = [ + "ignore_private" => true, + ]; + + 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') + $parameters['only_performers'] = true; + + break; + case 'with_lyrics': + if($param_value == 'on' || $param_value == '1') + $parameters['with_lyrics'] = true; + + break; + # дай бог работал этот case + case 'from_me': + if((int) $param_value != 1) continue; + $parameters['from_me'] = $this->user->id; + + break; + } + } - switch($sorter) { + $repo = $repos[$section] or $this->throwError(400, "Bad Request", "Invalid search entity $section."); + + $results = NULL; + switch($section) { default: - case "id": - $sort = "id " . $invert; - break; - case "name": - $sort = "first_name " . $invert; - break; - case "rating": - $sort = "rating " . $invert; + $results = $this->{$repo}->find($query, $parameters, ['type' => $order, 'invert' => $invert]); break; - case "length": - if($type != "audios") break; - - $sort = "length " . $invert; + case 'audios_playlists': + $results = $this->{$repo}->findPlaylists($query, $parameters, ['type' => $order, 'invert' => $invert]); break; - case "listens": - if($type != "audios") break; - - $sort = "listens " . $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, - "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."); - $results = $this->{$repo}->find($query, $parameters, $sort); - $iterator = $results->page($page, 14); + $iterator = $results->page($page, OPENVK_DEFAULT_PER_PAGE); $count = $results->size(); - $this->template->iterator = iterator_to_array($iterator); + $this->template->order = $order; + $this->template->invert = $invert; + $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 803ebdd0d..b54ef44c7 100644 --- a/Web/Presenters/templates/@layout.xml +++ b/Web/Presenters/templates/@layout.xml @@ -87,7 +87,7 @@
-
+
{if $instance_name != OPENVK_DEFAULT_INSTANCE_NAME}{$instance_name}{/if}
{ifset $thisUser} @@ -96,67 +96,45 @@ {_header_log_out}
{else} -