diff --git a/Web/Models/Entities/Post.php b/Web/Models/Entities/Post.php index 42941901..bb2b1e63 100644 --- a/Web/Models/Entities/Post.php +++ b/Web/Models/Entities/Post.php @@ -245,6 +245,23 @@ class Post extends Postable $this->unwire(); $this->save(); } + + function getGeo(): ?object + { + if (!$this->getRecord()->geo) return NULL; + + return (object) json_decode($this->getRecord()->geo, true, JSON_UNESCAPED_UNICODE); + } + + function getLat(): ?float + { + return (float) $this->getRecord()->geo_lat ?? NULL; + } + + function getLon(): ?float + { + return (float) $this->getRecord()->geo_lon ?? NULL; + } use Traits\TRichText; } diff --git a/Web/Models/sql/get-nearest-posts.tsql b/Web/Models/sql/get-nearest-posts.tsql new file mode 100644 index 00000000..d844a3ac --- /dev/null +++ b/Web/Models/sql/get-nearest-posts.tsql @@ -0,0 +1,10 @@ +SELECT *, + SQRT( + POW(69.1 * (? - geo_lat), 2) + + POW(69.1 * (? - geo_lon) * COS(RADIANS(geo_lat)), 2) + ) AS distance +FROM Posts +WHERE id <> ? +HAVING distance < 1 AND distance IS NOT NULL +ORDER BY distance +LIMIT 25; diff --git a/Web/Presenters/WallPresenter.php b/Web/Presenters/WallPresenter.php index 727101ff..8ee663fe 100644 --- a/Web/Presenters/WallPresenter.php +++ b/Web/Presenters/WallPresenter.php @@ -292,8 +292,17 @@ final class WallPresenter extends OpenVKPresenter $this->flashFail("err", " "); } } + + $geo = NULL; + + if (!is_null($this->postParam("geo")) && $this->postParam("geo") != "none") { + $geo = json_decode($this->postParam("geo"), true, JSON_UNESCAPED_UNICODE); + if (!$geo["lat"] || !$geo["lng"] || !$geo["name"]) { + $this->flashFail("err", tr("error"), "Ошибка при прикреплении геометки"); + } + } - if(empty($this->postParam("text")) && !$photo && !$video && !$poll && !$note) + if(empty($this->postParam("text")) && !$photo && !$video && !$poll && !$note && !$geo) $this->flashFail("err", tr("failed_to_publish_post"), tr("post_is_empty_or_too_big")); try { @@ -305,6 +314,11 @@ final class WallPresenter extends OpenVKPresenter $post->setAnonymous($anon); $post->setFlags($flags); $post->setNsfw($this->postParam("nsfw") === "on"); + if ($geo) { + $post->setGeo(json_encode($geo)); + $post->setGeo_Lat($geo["lat"]); + $post->setGeo_Lon($geo["lng"]); + } $post->save(); } catch (\LengthException $ex) { $this->flashFail("err", tr("failed_to_publish_post"), tr("post_is_too_big")); @@ -480,4 +494,49 @@ final class WallPresenter extends OpenVKPresenter # TODO localize message based on language and ?act=(un)pin $this->flashFail("succ", tr("information_-1"), tr("changes_saved_comment")); } + + function renderNearest(int $wall, int $post_id): void + { + if ($_SERVER["REQUEST_METHOD"] !== "POST") $this->notFound(); + $this->assertUserLoggedIn(); + + $post = $this->posts->getPostById($wall, $post_id); + if(!$post) + $this->notFound(); + + $lat = $post->getLat(); + $lon = $post->getLon(); + + if (!$lat || !$lon) + $this->returnJson(["success" => false, "error" => "У поста не указана гео-метка"]); + + $query = file_get_contents(__DIR__ . "/../Models/sql/get-nearest-posts.tsql"); + $_posts = DatabaseConnection::i()->getContext()->query($query, $lat, $lon, $post->getId())->fetchAll(); + $posts = []; + foreach ($_posts as $post) { + $distance = $post["distance"]; + $post = (new Posts)->get($post["id"]); + if (!$post || $post->isDeleted()) continue; + + $owner = $post->getOwner(); + + $preview = mb_substr($post->getText(), 0, 50) . (strlen($post->getText()) > 50 ? "..." : ""); + $posts[] = [ + "preview" => strlen($preview) > 0 ? $preview : "(нет текста)", + "url" => "/wall" . $post->getPrettyId(), + "time" => $post->getPublicationTime()->html(), + "owner" => [ + "url" => $owner->getURL(), + "avatar_url" => $owner->getAvatarURL(), + "name" => $owner->getCanonicalName(), + "verified" => $owner->isVerified(), + "writes" => ($owner instanceof User) ? ($owner->isFemale() ? tr("post_writes_f") : tr("post_writes_m")) : tr("post_writes_m") + ], + "geo" => $post->getGeo(), + "distance" => $distance + ]; + } + + $this->returnJson(["success" => true, "posts" => $posts, "need_count" => count($posts) === 25]); + } } diff --git a/Web/Presenters/templates/Wall/Feed.xml b/Web/Presenters/templates/Wall/Feed.xml index 5ed1e2fb..dba44ab3 100644 --- a/Web/Presenters/templates/Wall/Feed.xml +++ b/Web/Presenters/templates/Wall/Feed.xml @@ -16,7 +16,7 @@
+ + + + | +
+
+
+
+ ${post.preview}
+
+
+
+
+ Геометка: ${post.geo.name}
+ |
+
+