diff --git a/Web/Models/Entities/Post.php b/Web/Models/Entities/Post.php
index 9e74c2c0..fd15c8c0 100644
--- a/Web/Models/Entities/Post.php
+++ b/Web/Models/Entities/Post.php
@@ -1,5 +1,6 @@
getRecord()->pinned;
+ }
+
function isAd(): bool
{
return (bool) $this->getRecord()->ad;
@@ -72,6 +78,27 @@ class Post extends Postable
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
{
if($this->getTargetWall() < 0)
diff --git a/Web/Models/Repositories/Posts.php b/Web/Models/Repositories/Posts.php
index 12dc24ee..2c1a7f61 100644
--- a/Web/Models/Repositories/Posts.php
+++ b/Web/Models/Repositories/Posts.php
@@ -26,9 +26,38 @@ class Posts
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
{
- $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)
yield new Post($post);
diff --git a/Web/Presenters/WallPresenter.php b/Web/Presenters/WallPresenter.php
index fc908ad0..e500a25d 100644
--- a/Web/Presenters/WallPresenter.php
+++ b/Web/Presenters/WallPresenter.php
@@ -338,4 +338,26 @@ final class WallPresenter extends OpenVKPresenter
$this->redirect($wall < 0 ? "/club".($wall*-1) : "/id".$wall, static::REDIRECT_TEMPORARY);
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", "Операция успешна", "Операция успешна.");
+ }
}
diff --git a/Web/Presenters/templates/components/post/microblogpost.xml b/Web/Presenters/templates/components/post/microblogpost.xml
index 6cea48b3..43849a99 100644
--- a/Web/Presenters/templates/components/post/microblogpost.xml
+++ b/Web/Presenters/templates/components/post/microblogpost.xml
@@ -17,11 +17,24 @@
{if $author->isVerified()}{/if}
{ifset $compact}
- {$post->getPublicationTime()}
+
+ {if $post->isPinned()}
+ {$post->getPublicationTime()},
+ {_pinned}
+ {else}
+ {$post->getPublicationTime()}
+ {/if}
+
{/ifset}
{if $post->canBeDeletedBy($thisUser) && !($forceNoDeleteLink ?? false) && !isset($compact)}
+
+ {if $post->isPinned()}
+
+ {else}
+
+ {/if}
{/if}
diff --git a/Web/Presenters/templates/components/post/oldpost.xml b/Web/Presenters/templates/components/post/oldpost.xml
index e70c0361..a8f67f1e 100644
--- a/Web/Presenters/templates/components/post/oldpost.xml
+++ b/Web/Presenters/templates/components/post/oldpost.xml
@@ -34,7 +34,14 @@
{/if}
-
{$post->getPublicationTime()}
+
+ {if $post->isPinned()}
+ {$post->getPublicationTime()},
+ {_pinned}
+ {else}
+ {$post->getPublicationTime()}
+ {/if}
+