From 5c9d3c085ebdc788f9e03793171b65e742c71863 Mon Sep 17 00:00:00 2001 From: Maxim Leshchenko <50026114+maksalees@users.noreply.github.com> Date: Sat, 13 Nov 2021 22:28:17 +0200 Subject: [PATCH] When you like a repost, put likes on the entire hierarchy of repost posts recursively (#287) --- Web/Models/Entities/Post.php | 41 ++++++++++++++++++++++++++++++++ Web/Models/Entities/Postable.php | 24 ++++++++++++++++--- Web/Presenters/WallPresenter.php | 5 +--- quirks.yml | 10 ++++++++ 4 files changed, 73 insertions(+), 7 deletions(-) diff --git a/Web/Models/Entities/Post.php b/Web/Models/Entities/Post.php index fe6a3078..17c096fa 100644 --- a/Web/Models/Entities/Post.php +++ b/Web/Models/Entities/Post.php @@ -3,11 +3,33 @@ namespace openvk\Web\Models\Entities; use Chandler\Database\DatabaseConnection as DB; use openvk\Web\Models\Repositories\Clubs; use openvk\Web\Models\RowModel; +use openvk\Web\Models\Entities\Notifications\LikeNotification; class Post extends Postable { protected $tableName = "posts"; protected $upperNodeReferenceColumnName = "wall"; + + private function setLikeRecursively(bool $liked, User $user, int $depth): void + { + $searchData = [ + "origin" => $user->getId(), + "model" => static::class, + "target" => $this->getRecord()->id, + ]; + + if((sizeof(DB::i()->getContext()->table("likes")->where($searchData)) > 0) !== $liked) { + if($this->getOwner(false)->getId() !== $user->getId() && !($this->getOwner() instanceof Club)) + (new LikeNotification($this->getOwner(false), $this, $user))->emit(); + + parent::setLike($liked, $user); + } + + if($depth < ovkGetQuirk("wall.repost-liking-recursion-limit")) + foreach($this->getChildren() as $attachment) + if($attachment instanceof Post) + $attachment->setLikeRecursively($liked, $user, $depth + 1); + } /** * May return fake owner (group), if flags are [1, (*)] @@ -121,6 +143,25 @@ class Post extends Postable $this->stateChanges("content", $content); } + + function toggleLike(User $user): bool + { + $liked = parent::toggleLike($user); + + if($this->getOwner(false)->getId() !== $user->getId() && !($this->getOwner() instanceof Club)) + (new LikeNotification($this->getOwner(false), $this, $user))->emit(); + + foreach($this->getChildren() as $attachment) + if($attachment instanceof Post) + $attachment->setLikeRecursively($liked, $user, 2); + + return $liked; + } + + function setLike(bool $liked, User $user): void + { + $this->setLikeRecursively($liked, $user, 1); + } function deletePost(): void { diff --git a/Web/Models/Entities/Postable.php b/Web/Models/Entities/Postable.php index 05a39777..26670e94 100644 --- a/Web/Models/Entities/Postable.php +++ b/Web/Models/Entities/Postable.php @@ -96,17 +96,35 @@ abstract class Postable extends Attachable yield (new Users)->get($like->origin); } - function toggleLike(User $user): void + function toggleLike(User $user): bool { $searchData = [ "origin" => $user->getId(), "model" => static::class, "target" => $this->getRecord()->id, ]; - if(sizeof(DB::i()->getContext()->table("likes")->where($searchData)) > 0) + + if(sizeof(DB::i()->getContext()->table("likes")->where($searchData)) > 0) { DB::i()->getContext()->table("likes")->where($searchData)->delete(); - else + return false; + } + + DB::i()->getContext()->table("likes")->insert($searchData); + return true; + } + + function setLike(bool $liked, User $user): void + { + $searchData = [ + "origin" => $user->getId(), + "model" => static::class, + "target" => $this->getRecord()->id, + ]; + + if($liked) DB::i()->getContext()->table("likes")->insert($searchData); + else + DB::i()->getContext()->table("likes")->where($searchData)->delete(); } function hasLikeFrom(User $user): bool diff --git a/Web/Presenters/WallPresenter.php b/Web/Presenters/WallPresenter.php index d36d3db1..51734a3d 100644 --- a/Web/Presenters/WallPresenter.php +++ b/Web/Presenters/WallPresenter.php @@ -1,7 +1,7 @@ user)) { $post->toggleLike($this->user->identity); - - if($post->getOwner(false)->getId() !== $this->user->identity->getId() && !($post->getOwner() instanceof Club)) - (new LikeNotification($post->getOwner(false), $post, $this->user->identity))->emit(); } $this->redirect( diff --git a/quirks.yml b/quirks.yml index 54b0301f..c7967fc8 100644 --- a/quirks.yml +++ b/quirks.yml @@ -34,3 +34,13 @@ blobs.erase-upon-deletion: 0 # + Set this option to 1 if you want to use quirky VK Mobile behaviour (yes graffiti in comments) # + Set this option to 0 if you want to use VK Desktop behaviour (no graffiti in comments) comments.allow-graffiti: 0 + +# Maximum recursion depth of likes on reposts +# Restriction on the recursion depth of repost likes. +# For example, if the value is 5, likes will be set for a maximum of 5 posts, even if there are more posts in the repost hierarchy. +# Needed to protect against attacks +# +# Possible values: +# + Set this option to -1 if you want to disable the limit +# + Set this option to any non-negative number to be this limit +wall.repost-liking-recursion-limit: 10