mirror of
https://github.com/openvk/openvk
synced 2024-12-23 09:01:15 +03:00
Add pinning feature
This commit is contained in:
parent
fd555d3d61
commit
839594cd70
7 changed files with 112 additions and 3 deletions
|
@ -1,5 +1,6 @@
|
||||||
<?php declare(strict_types=1);
|
<?php declare(strict_types=1);
|
||||||
namespace openvk\Web\Models\Entities;
|
namespace openvk\Web\Models\Entities;
|
||||||
|
use Chandler\Database\DatabaseConnection as DB;
|
||||||
use openvk\Web\Models\Repositories\Clubs;
|
use openvk\Web\Models\Repositories\Clubs;
|
||||||
use openvk\Web\Models\RowModel;
|
use openvk\Web\Models\RowModel;
|
||||||
|
|
||||||
|
@ -42,6 +43,11 @@ class Post extends Postable
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isPinned(): bool
|
||||||
|
{
|
||||||
|
return (bool) $this->getRecord()->pinned;
|
||||||
|
}
|
||||||
|
|
||||||
function isAd(): bool
|
function isAd(): bool
|
||||||
{
|
{
|
||||||
return (bool) $this->getRecord()->ad;
|
return (bool) $this->getRecord()->ad;
|
||||||
|
@ -72,6 +78,27 @@ class Post extends Postable
|
||||||
return $this->getRecord()->owner;
|
return $this->getRecord()->owner;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function pin(): void
|
||||||
|
{
|
||||||
|
DB::i()
|
||||||
|
->getContext()
|
||||||
|
->table("posts")
|
||||||
|
->where([
|
||||||
|
"wall" => $this->getTargetWall(),
|
||||||
|
"pinned" => true,
|
||||||
|
])
|
||||||
|
->update(["pinned" => false]);
|
||||||
|
|
||||||
|
$this->stateChanges("pinned", true);
|
||||||
|
$this->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
function unpin(): void
|
||||||
|
{
|
||||||
|
$this->stateChanges("pinned", false);
|
||||||
|
$this->save();
|
||||||
|
}
|
||||||
|
|
||||||
function canBeDeletedBy(User $user): bool
|
function canBeDeletedBy(User $user): bool
|
||||||
{
|
{
|
||||||
if($this->getTargetWall() < 0)
|
if($this->getTargetWall() < 0)
|
||||||
|
|
|
@ -26,9 +26,38 @@ class Posts
|
||||||
return $this->toPost($this->posts->get($id));
|
return $this->toPost($this->posts->get($id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getPinnedPost(int $user): ?Post
|
||||||
|
{
|
||||||
|
$post = (clone $this->posts)->where([
|
||||||
|
"wall" => $user,
|
||||||
|
"pinned" => true,
|
||||||
|
"deleted" => false,
|
||||||
|
])->fetch();
|
||||||
|
|
||||||
|
return $this->toPost($post);
|
||||||
|
}
|
||||||
|
|
||||||
function getPostsFromUsersWall(int $user, int $page = 1, ?int $perPage = NULL): \Traversable
|
function getPostsFromUsersWall(int $user, int $page = 1, ?int $perPage = NULL): \Traversable
|
||||||
{
|
{
|
||||||
$sel = $this->posts->where(["wall" => $user, "deleted" => 0])->order("created DESC")->page($page, $perPage ?? OPENVK_DEFAULT_PER_PAGE);
|
$perPage ??= OPENVK_DEFAULT_PER_PAGE;
|
||||||
|
$offset = $perPage * ($page - 1);
|
||||||
|
|
||||||
|
$pinPost = $this->getPinnedPost($user);
|
||||||
|
if(!is_null($pinPost)) {
|
||||||
|
if($page === 1) {
|
||||||
|
$perPage--;
|
||||||
|
|
||||||
|
yield $pinPost;
|
||||||
|
} else {
|
||||||
|
$offset--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$sel = $this->posts->where([
|
||||||
|
"wall" => $user,
|
||||||
|
"pinned" => false,
|
||||||
|
"deleted" => false,
|
||||||
|
])->order("created DESC")->limit($perPage, $offset);
|
||||||
|
|
||||||
foreach($sel as $post)
|
foreach($sel as $post)
|
||||||
yield new Post($post);
|
yield new Post($post);
|
||||||
|
|
|
@ -338,4 +338,26 @@ final class WallPresenter extends OpenVKPresenter
|
||||||
$this->redirect($wall < 0 ? "/club".($wall*-1) : "/id".$wall, static::REDIRECT_TEMPORARY);
|
$this->redirect($wall < 0 ? "/club".($wall*-1) : "/id".$wall, static::REDIRECT_TEMPORARY);
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function renderPin(int $wall, int $post_id): void
|
||||||
|
{
|
||||||
|
$this->assertUserLoggedIn();
|
||||||
|
$this->willExecuteWriteAction();
|
||||||
|
|
||||||
|
$post = $this->posts->getPostById($wall, $post_id);
|
||||||
|
if(!$post)
|
||||||
|
$this->notFound();
|
||||||
|
|
||||||
|
if(!$post->canBeDeletedBy($this->user->identity))
|
||||||
|
$this->flashFail("err", "Ошибка доступа", "Вам нельзя закреплять этот пост.");
|
||||||
|
|
||||||
|
if(($this->queryParam("act") ?? "pin") === "pin") {
|
||||||
|
$post->pin();
|
||||||
|
} else {
|
||||||
|
$post->unpin();
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO localize message based on language and ?act=(un)pin
|
||||||
|
$this->flashFail("succ", "Операция успешна", "Операция успешна.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,11 +17,24 @@
|
||||||
</a>
|
</a>
|
||||||
{if $author->isVerified()}<img class="name-checkmark" src="/assets/packages/static/openvk/img/checkmark.png">{/if}
|
{if $author->isVerified()}<img class="name-checkmark" src="/assets/packages/static/openvk/img/checkmark.png">{/if}
|
||||||
{ifset $compact}<br>
|
{ifset $compact}<br>
|
||||||
<a href="/wall{$post->getPrettyId()}" class="date">{$post->getPublicationTime()}</a>
|
<a href="/wall{$post->getPrettyId()}" class="date">
|
||||||
|
{if $post->isPinned()}
|
||||||
|
{$post->getPublicationTime()},
|
||||||
|
{_pinned}
|
||||||
|
{else}
|
||||||
|
{$post->getPublicationTime()}
|
||||||
|
{/if}
|
||||||
|
</a>
|
||||||
|
|
||||||
{/ifset}
|
{/ifset}
|
||||||
{if $post->canBeDeletedBy($thisUser) && !($forceNoDeleteLink ?? false) && !isset($compact)}
|
{if $post->canBeDeletedBy($thisUser) && !($forceNoDeleteLink ?? false) && !isset($compact)}
|
||||||
<a class="delete" href="/wall{$post->getPrettyId()}/delete"></a>
|
<a class="delete" href="/wall{$post->getPrettyId()}/delete"></a>
|
||||||
|
|
||||||
|
{if $post->isPinned()}
|
||||||
|
<a class="delete" href="/wall{$post->getPrettyId()}/pin?act=unpin&hash={rawurlencode($csrfToken)}"></a>
|
||||||
|
{else}
|
||||||
|
<a class="delete" href="/wall{$post->getPrettyId()}/pin?act=pin&hash={rawurlencode($csrfToken)}"></a>
|
||||||
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
<div class="post-content" id="{$post->getPrettyId()}">
|
<div class="post-content" id="{$post->getPrettyId()}">
|
||||||
|
|
|
@ -34,7 +34,14 @@
|
||||||
</a>
|
</a>
|
||||||
{/if}
|
{/if}
|
||||||
<br/>
|
<br/>
|
||||||
<a href="/wall{$post->getPrettyId()}" class="date">{$post->getPublicationTime()}</a>
|
<a href="/wall{$post->getPrettyId()}" class="date">
|
||||||
|
{if $post->isPinned()}
|
||||||
|
{$post->getPublicationTime()},
|
||||||
|
{_pinned}
|
||||||
|
{else}
|
||||||
|
{$post->getPublicationTime()}
|
||||||
|
{/if}
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="post-content" id="{$post->getPrettyId()}">
|
<div class="post-content" id="{$post->getPrettyId()}">
|
||||||
<div class="text" id="text{$post->getPrettyId()}">
|
<div class="text" id="text{$post->getPrettyId()}">
|
||||||
|
@ -63,6 +70,12 @@
|
||||||
<div n:if="isset($thisUser) &&! ($compact ?? false)" class="post-menu">
|
<div n:if="isset($thisUser) &&! ($compact ?? false)" class="post-menu">
|
||||||
{if $post->canBeDeletedBy($thisUser) && !($forceNoDeleteLink ?? false)}
|
{if $post->canBeDeletedBy($thisUser) && !($forceNoDeleteLink ?? false)}
|
||||||
<a href="/wall{$post->getPrettyId()}/delete">{_"delete"}</a> |
|
<a href="/wall{$post->getPrettyId()}/delete">{_"delete"}</a> |
|
||||||
|
|
||||||
|
{if $post->isPinned()}
|
||||||
|
<a href="/wall{$post->getPrettyId()}/pin?act=unpin&hash={rawurlencode($csrfToken)}">{_unpin}</a> |
|
||||||
|
{else}
|
||||||
|
<a href="/wall{$post->getPrettyId()}/pin?act=pin&hash={rawurlencode($csrfToken)}">{_pin}</a> |
|
||||||
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{if !($forceNoCommentsLink ?? false)}
|
{if !($forceNoCommentsLink ?? false)}
|
||||||
|
|
|
@ -93,6 +93,8 @@ routes:
|
||||||
handler: "Wall->share"
|
handler: "Wall->share"
|
||||||
- url: "/wall{num}_{num}/delete"
|
- url: "/wall{num}_{num}/delete"
|
||||||
handler: "Wall->delete"
|
handler: "Wall->delete"
|
||||||
|
- url: "/wall{num}_{num}/pin"
|
||||||
|
handler: "Wall->pin"
|
||||||
- url: "/blob_{text}/{text}.{text}"
|
- url: "/blob_{text}/{text}.{text}"
|
||||||
handler: "Blob->file"
|
handler: "Blob->file"
|
||||||
- url: "/themepack/{text}/{?version}/{?resClass}/{?any}"
|
- url: "/themepack/{text}/{?version}/{?resClass}/{?any}"
|
||||||
|
|
|
@ -104,6 +104,9 @@
|
||||||
"delete" = "Удалить";
|
"delete" = "Удалить";
|
||||||
"comments" = "Комментарии";
|
"comments" = "Комментарии";
|
||||||
"share" = "Поделиться";
|
"share" = "Поделиться";
|
||||||
|
"pin" = "Закрепить";
|
||||||
|
"unpin" = "Открепить";
|
||||||
|
"pinned" = "закреплено";
|
||||||
"comments_tip" = "Будьте первым, кто оставит комментарий!";
|
"comments_tip" = "Будьте первым, кто оставит комментарий!";
|
||||||
"your_comment" = "Ваш комментарий";
|
"your_comment" = "Ваш комментарий";
|
||||||
"comments" = "Комментарии";
|
"comments" = "Комментарии";
|
||||||
|
|
Loading…
Reference in a new issue