From df0bb4127631f06fbfbe065fabca458338a42021 Mon Sep 17 00:00:00 2001
From: mrilyew <99399973+mrilyew@users.noreply.github.com>
Date: Sun, 2 Mar 2025 20:05:34 +0300
Subject: [PATCH 1/3] add liked content
---
Web/Models/Entities/User.php | 2 +
Web/Models/Repositories/Faves.php | 48 +++++++++++
Web/Presenters/GroupPresenter.php | 1 +
Web/Presenters/UserPresenter.php | 65 ++++++++++++++-
Web/Presenters/templates/@layout.xml | 3 +-
Web/Presenters/templates/User/Fave.xml | 80 +++++++++++++++++++
Web/Presenters/templates/User/Settings.xml | 11 +++
.../templates/components/comment.xml | 3 +-
Web/di.yml | 1 +
Web/routes.yml | 2 +
locales/en.strings | 17 ++++
locales/ru.strings | 17 ++++
12 files changed, 247 insertions(+), 3 deletions(-)
create mode 100644 Web/Models/Repositories/Faves.php
create mode 100644 Web/Presenters/templates/User/Fave.xml
diff --git a/Web/Models/Entities/User.php b/Web/Models/Entities/User.php
index 31d3d4fe..85731811 100644
--- a/Web/Models/Entities/User.php
+++ b/Web/Models/Entities/User.php
@@ -558,6 +558,7 @@ class User extends RowModel
"poster",
"apps",
"docs",
+ "fave",
],
])->get($id);
}
@@ -1195,6 +1196,7 @@ class User extends RowModel
"poster",
"apps",
"docs",
+ "fave",
],
])->set($id, (int) $status)->toInteger();
diff --git a/Web/Models/Repositories/Faves.php b/Web/Models/Repositories/Faves.php
new file mode 100644
index 00000000..d73b588b
--- /dev/null
+++ b/Web/Models/Repositories/Faves.php
@@ -0,0 +1,48 @@
+context = DatabaseConnection::i()->getContext();
+ $this->likes = $this->context->table("likes");
+ }
+
+ private function fetchLikes(User $user, string $class = 'Post')
+ {
+ $fetch = $this->likes->where([
+ "model" => "openvk\\Web\\Models\\Entities\\".$class,
+ "origin" => $user->getRealId(),
+ ]);
+
+ return $fetch;
+ }
+
+ function fetchLikesSection(User $user, string $class = 'Post', int $page = 1, ?int $perPage = NULL): \Traversable
+ {
+ $perPage ??= OPENVK_DEFAULT_PER_PAGE;
+ $fetch = $this->fetchLikes($user, $class)->page($page, $perPage);
+ foreach($fetch as $like) {
+ $className = "openvk\\Web\\Models\\Repositories\\".$class."s";
+ $repo = new $className;
+ if(!$repo) {
+ continue;
+ }
+
+ $entity = $repo->get($like->target);
+ yield $entity;
+ }
+ }
+
+ function fetchLikesSectionCount(User $user, string $class = 'Post')
+ {
+ return $this->fetchLikes($user, $class)->count();
+ }
+}
diff --git a/Web/Presenters/GroupPresenter.php b/Web/Presenters/GroupPresenter.php
index 1aa14213..b3e27512 100644
--- a/Web/Presenters/GroupPresenter.php
+++ b/Web/Presenters/GroupPresenter.php
@@ -373,6 +373,7 @@ final class GroupPresenter extends OpenVKPresenter
public function renderDeleteAvatar(int $id)
{
$this->assertUserLoggedIn();
+ $this->assertNoCSRF();
$this->willExecuteWriteAction();
$club = $this->clubs->get($id);
diff --git a/Web/Presenters/UserPresenter.php b/Web/Presenters/UserPresenter.php
index 8770b4de..07d702cd 100644
--- a/Web/Presenters/UserPresenter.php
+++ b/Web/Presenters/UserPresenter.php
@@ -9,7 +9,7 @@ use openvk\Web\Util\Sms;
use openvk\Web\Themes\Themepacks;
use openvk\Web\Models\Entities\{Photo, Post, EmailChangeVerification};
use openvk\Web\Models\Entities\Notifications\{CoinsTransferNotification, RatingUpNotification};
-use openvk\Web\Models\Repositories\{Users, Clubs, Albums, Videos, Notes, Vouchers, EmailChangeVerifications, Audios};
+use openvk\Web\Models\Repositories\{Users, Clubs, Albums, Videos, Notes, Vouchers, EmailChangeVerifications, Audios, Faves};
use openvk\Web\Models\Exceptions\InvalidUserNameException;
use openvk\Web\Util\Validator;
use Chandler\Security\Authenticator;
@@ -474,6 +474,7 @@ final class UserPresenter extends OpenVKPresenter
public function renderDeleteAvatar()
{
$this->assertUserLoggedIn();
+ $this->assertNoCSRF();
$this->willExecuteWriteAction();
$avatar = $this->user->identity->getAvatarPhoto();
@@ -666,6 +667,7 @@ final class UserPresenter extends OpenVKPresenter
"menu_standardo" => "poster",
"menu_aplikoj" => "apps",
"menu_doxc" => "docs",
+ "menu_feva" => "fave",
];
foreach ($settings as $checkbox => $setting) {
$user->setLeftMenuItemStatus($setting, $this->checkbox($checkbox));
@@ -942,4 +944,65 @@ final class UserPresenter extends OpenVKPresenter
$this->redirect("/settings");
}
}
+
+ function renderFave(): void
+ {
+ $this->assertUserLoggedIn();
+
+ $page = (int)($this->queryParam("p") ?? 1);
+ $section = $this->queryParam("section") ?? "posts";
+ $display_section = "posts";
+ $data = NULL;
+ $count = 0;
+
+ switch($section) {
+ default:
+ $this->notFound();
+ break;
+ case 'wall':
+ case 'post':
+ case 'posts':
+ $data = (new Faves)->fetchLikesSection($this->user->identity, 'Post', $page);
+ $count = (new Faves)->fetchLikesSectionCount($this->user->identity, 'Post');
+ $display_section = "posts";
+ break;
+ case 'comment':
+ case 'comments':
+ $data = (new Faves)->fetchLikesSection($this->user->identity, 'Comment', $page);
+ $count = (new Faves)->fetchLikesSectionCount($this->user->identity, 'Comment');
+ $display_section = "comments";
+ break;
+ case 'photo':
+ case 'photos':
+ $data = (new Faves)->fetchLikesSection($this->user->identity, 'Photo', $page);
+ $count = (new Faves)->fetchLikesSectionCount($this->user->identity, 'Photo');
+ $display_section = "photos";
+ break;
+ case 'video':
+ case 'videos':
+ $data = (new Faves)->fetchLikesSection($this->user->identity, 'Video', $page);
+ $count = (new Faves)->fetchLikesSectionCount($this->user->identity, 'Video');
+ $display_section = "videos";
+ break;
+ }
+
+ $this->template->data = iterator_to_array($data);
+ $this->template->count = $count;
+ $this->template->page = $page;
+ $this->template->perPage = OPENVK_DEFAULT_PER_PAGE;
+ $this->template->section = $display_section;
+
+ $this->template->paginatorConf = (object) [
+ "page" => $page,
+ "count" => $count,
+ "amount" => sizeof($this->template->data),
+ "perPage" => $this->template->perPage,
+ "atBottom" => false,
+ "tidy" => true,
+ 'pageCount' => ceil($count / $this->template->perPage),
+ ];
+ $this->template->extendedPaginatorConf = clone $this->template->paginatorConf;
+ $this->template->extendedPaginatorConf->space = 11;
+ $this->template->paginatorConf->atTop = true;
+ }
}
diff --git a/Web/Presenters/templates/@layout.xml b/Web/Presenters/templates/@layout.xml
index 2e8dc828..7a55a8b0 100644
--- a/Web/Presenters/templates/@layout.xml
+++ b/Web/Presenters/templates/@layout.xml
@@ -198,10 +198,11 @@
{_my_settings}
- {if $thisUser->getLeftMenuItemStatus('docs') || $thisUser->getLeftMenuItemStatus('apps')}
+ {if $thisUser->getLeftMenuItemStatus('docs') || $thisUser->getLeftMenuItemStatus('apps') || $thisUser->getLeftMenuItemStatus('fave')}
{_apps}
{_my_documents}
+ {_bookmarks_tab}
{/if}
{var $canAccessAdminPanel = $thisUser->getChandlerUser()->can("access")->model("admin")->whichBelongsTo(NULL)}
diff --git a/Web/Presenters/templates/User/Fave.xml b/Web/Presenters/templates/User/Fave.xml
new file mode 100644
index 00000000..50ead41f
--- /dev/null
+++ b/Web/Presenters/templates/User/Fave.xml
@@ -0,0 +1,80 @@
+{extends "../@layout.xml"}
+
+{block title}{_bookmarks_tab}{/block}
+
+{block header}
+ {_bookmarks_tab}
+{/block}
+
+{block wrap}
+
+
+
+
+
+ {tr("faves", $count)} {*tr("showing_x_y", $page, $count)*}
+
+
+ {include "../components/paginator.xml", conf => $paginatorConf}
+
+
+
+
+
+ {if $count > 0}
+ {foreach $data as $dat}
+ {if $section == "posts"}
+
+ {include "../components/post.xml", post => $dat, commentSection => true}
+
+ {elseif $section == "comments"}
+
+ {include "../components/comment.xml", comment => $dat, correctLink => true, no_reply_button => true}
+
+ {elseif $section == "photos"}
+
+ {elseif $section == "videos"}
+
+ {include "../components/video.xml", video => $dat}
+
+ {/if}
+ {/foreach}
+ {else}
+ {include "../components/content_error.xml", description => tr("faves_".$section."_empty_tip")}
+ {/if}
+
+
+
+
+
+ {include "../components/paginator.xml", conf => $extendedPaginatorConf}
+
+
+
+
+
+{/block}
diff --git a/Web/Presenters/templates/User/Settings.xml b/Web/Presenters/templates/User/Settings.xml
index 5ae6ee4b..f4cf0271 100644
--- a/Web/Presenters/templates/User/Settings.xml
+++ b/Web/Presenters/templates/User/Settings.xml
@@ -696,6 +696,17 @@
{_my_documents}
+
+
+
+ |
+
+ {_bookmarks_tab}
+ |
+
{_report}
{/if}
diff --git a/Web/di.yml b/Web/di.yml
index b9821fec..55ac4483 100644
--- a/Web/di.yml
+++ b/Web/di.yml
@@ -54,5 +54,6 @@ services:
- openvk\Web\Models\Repositories\BannedLinks
- openvk\Web\Models\Repositories\ChandlerGroups
- openvk\Web\Models\Repositories\Documents
+ - openvk\Web\Models\Repositories\Faves
- openvk\Web\Presenters\MaintenancePresenter
- openvk\Web\Presenters\NoSpamPresenter
diff --git a/Web/routes.yml b/Web/routes.yml
index eac95801..8014b0ef 100644
--- a/Web/routes.yml
+++ b/Web/routes.yml
@@ -413,6 +413,8 @@ routes:
handler: "InternalAPI->getPostTemplate"
- url: "/tour"
handler: "About->tour"
+ - url: "/fave"
+ handler: "User->fave"
- url: "/{?shortCode}"
handler: "UnknownTextRouteStrategy->delegate"
placeholders:
diff --git a/locales/en.strings b/locales/en.strings
index ae2bc52d..b215497d 100644
--- a/locales/en.strings
+++ b/locales/en.strings
@@ -641,6 +641,8 @@
"my_feed" = "My Feed";
"my_feedback" = "My Feedback";
"my_settings" = "My Settings";
+"bookmarks" = "Bookmarks";
+"bookmarks_tab" = "Saved";
"bug_tracker" = "Bug Tracker";
"menu_settings" = "Settings";
@@ -2113,6 +2115,7 @@
"s_apps" = "Applications";
"s_posts" = "Posts";
"s_comments" = "Comments";
+"s_photos" = "Photos";
"s_videos" = "Videos";
"s_audios" = "Music";
"s_audios_playlists" = "Playlists";
@@ -2385,3 +2388,17 @@
"select_doc" = "Attach document";
"no_documents" = "No documents found";
"go_to_my_documents" = "Go to own documents";
+
+/* Fave */
+
+"faves" = "Bookmarks";
+"faves_empty_tip" = "There will be your liked content.";
+"faves_posts_empty_tip" = "There will be posts liked by you.";
+"faves_comments_empty_tip" = "There will be comments liked by you.";
+"faves_photos_empty_tip" = "There will be photos liked by you.";
+"faves_videos_empty_tip" = "There will be videos liked by you.";
+"faves_zero" = "No bookmarks";
+"faves_one" = "One bookmark";
+"faves_few" = "$1 bookmarks";
+"faves_many" = "$1 bookmarks";
+"faves_other" = "$1 bookmarks";
diff --git a/locales/ru.strings b/locales/ru.strings
index 14f6f624..21c2fcf1 100644
--- a/locales/ru.strings
+++ b/locales/ru.strings
@@ -624,6 +624,8 @@
"my_feed" = "Мои Новости";
"my_feedback" = "Мои Ответы";
"my_settings" = "Мои Настройки";
+"bookmarks" = "Закладки";
+"bookmarks_tab" = "Избранное";
"bug_tracker" = "Баг-трекер";
"menu_settings" = "Настройки";
@@ -2008,6 +2010,7 @@
"s_apps" = "Приложения";
"s_posts" = "Записи";
"s_comments" = "Комментарии";
+"s_photos" = "Фотографии";
"s_videos" = "Видео";
"s_audios" = "Аудио";
"s_audios_playlists" = "Плейлисты";
@@ -2280,3 +2283,17 @@
"select_doc" = "Выбор документа";
"no_documents" = "Документов нет";
"go_to_my_documents" = "Перейти к своим документам";
+
+/* Fave */
+
+"faves" = "Закладки";
+"faves_empty_tip" = "Здесь будет отображаться понравившийся Вам контент...";
+"faves_posts_empty_tip" = "Здесь будут отображаться понравившиеся Вам записи.";
+"faves_comments_empty_tip" = "Здесь будут отображаться понравившиеся Вам комментарии.";
+"faves_photos_empty_tip" = "Здесь будут отображаться понравившиеся Вам фотографии.";
+"faves_videos_empty_tip" = "Здесь будут отображаться понравившиеся Вам видео.";
+"faves_zero" = "Ни одной закладки"; /* на украинском можно как ни одной вподобайки */
+"faves_one" = "Одна закладка";
+"faves_few" = "$1 закладки";
+"faves_many" = "$1 закладок";
+"faves_other" = "$1 закладок";
From 09d4855e75a653d9edb77fe8aee0e0e5fcc1021e Mon Sep 17 00:00:00 2001
From: mrilyew <99399973+mrilyew@users.noreply.github.com>
Date: Sun, 2 Mar 2025 20:16:44 +0300
Subject: [PATCH 2/3] fix order
---
Web/Models/Repositories/Faves.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Web/Models/Repositories/Faves.php b/Web/Models/Repositories/Faves.php
index d73b588b..6fb3f987 100644
--- a/Web/Models/Repositories/Faves.php
+++ b/Web/Models/Repositories/Faves.php
@@ -28,7 +28,7 @@ class Faves
function fetchLikesSection(User $user, string $class = 'Post', int $page = 1, ?int $perPage = NULL): \Traversable
{
$perPage ??= OPENVK_DEFAULT_PER_PAGE;
- $fetch = $this->fetchLikes($user, $class)->page($page, $perPage);
+ $fetch = $this->fetchLikes($user, $class)->page($page, $perPage)->order("index DESC");
foreach($fetch as $like) {
$className = "openvk\\Web\\Models\\Repositories\\".$class."s";
$repo = new $className;
From b23b7706340f392ce0d16862325851fdab10918c Mon Sep 17 00:00:00 2001
From: mrilyew <99399973+mrilyew@users.noreply.github.com>
Date: Sun, 2 Mar 2025 20:20:51 +0300
Subject: [PATCH 3/3] linter
---
Web/Models/Repositories/Faves.php | 12 ++++++++----
Web/Presenters/UserPresenter.php | 24 ++++++++++++------------
2 files changed, 20 insertions(+), 16 deletions(-)
diff --git a/Web/Models/Repositories/Faves.php b/Web/Models/Repositories/Faves.php
index 6fb3f987..dbe139ff 100644
--- a/Web/Models/Repositories/Faves.php
+++ b/Web/Models/Repositories/Faves.php
@@ -1,5 +1,9 @@
-context = DatabaseConnection::i()->getContext();
$this->likes = $this->context->table("likes");
@@ -25,7 +29,7 @@ class Faves
return $fetch;
}
- function fetchLikesSection(User $user, string $class = 'Post', int $page = 1, ?int $perPage = NULL): \Traversable
+ public function fetchLikesSection(User $user, string $class = 'Post', int $page = 1, ?int $perPage = NULL): \Traversable
{
$perPage ??= OPENVK_DEFAULT_PER_PAGE;
$fetch = $this->fetchLikes($user, $class)->page($page, $perPage)->order("index DESC");
@@ -41,7 +45,7 @@ class Faves
}
}
- function fetchLikesSectionCount(User $user, string $class = 'Post')
+ public function fetchLikesSectionCount(User $user, string $class = 'Post')
{
return $this->fetchLikes($user, $class)->count();
}
diff --git a/Web/Presenters/UserPresenter.php b/Web/Presenters/UserPresenter.php
index 07d702cd..7d152df4 100644
--- a/Web/Presenters/UserPresenter.php
+++ b/Web/Presenters/UserPresenter.php
@@ -945,43 +945,43 @@ final class UserPresenter extends OpenVKPresenter
}
}
- function renderFave(): void
+ public function renderFave(): void
{
$this->assertUserLoggedIn();
- $page = (int)($this->queryParam("p") ?? 1);
+ $page = (int) ($this->queryParam("p") ?? 1);
$section = $this->queryParam("section") ?? "posts";
$display_section = "posts";
- $data = NULL;
+ $data = null;
$count = 0;
- switch($section) {
+ switch ($section) {
default:
$this->notFound();
break;
case 'wall':
case 'post':
case 'posts':
- $data = (new Faves)->fetchLikesSection($this->user->identity, 'Post', $page);
- $count = (new Faves)->fetchLikesSectionCount($this->user->identity, 'Post');
+ $data = (new Faves())->fetchLikesSection($this->user->identity, 'Post', $page);
+ $count = (new Faves())->fetchLikesSectionCount($this->user->identity, 'Post');
$display_section = "posts";
break;
case 'comment':
case 'comments':
- $data = (new Faves)->fetchLikesSection($this->user->identity, 'Comment', $page);
- $count = (new Faves)->fetchLikesSectionCount($this->user->identity, 'Comment');
+ $data = (new Faves())->fetchLikesSection($this->user->identity, 'Comment', $page);
+ $count = (new Faves())->fetchLikesSectionCount($this->user->identity, 'Comment');
$display_section = "comments";
break;
case 'photo':
case 'photos':
- $data = (new Faves)->fetchLikesSection($this->user->identity, 'Photo', $page);
- $count = (new Faves)->fetchLikesSectionCount($this->user->identity, 'Photo');
+ $data = (new Faves())->fetchLikesSection($this->user->identity, 'Photo', $page);
+ $count = (new Faves())->fetchLikesSectionCount($this->user->identity, 'Photo');
$display_section = "photos";
break;
case 'video':
case 'videos':
- $data = (new Faves)->fetchLikesSection($this->user->identity, 'Video', $page);
- $count = (new Faves)->fetchLikesSectionCount($this->user->identity, 'Video');
+ $data = (new Faves())->fetchLikesSection($this->user->identity, 'Video', $page);
+ $count = (new Faves())->fetchLikesSectionCount($this->user->identity, 'Video');
$display_section = "videos";
break;
}
|