diff --git a/Web/Models/Entities/Report.php b/Web/Models/Entities/Report.php index 2d0d81df..4070952e 100644 --- a/Web/Models/Entities/Report.php +++ b/Web/Models/Entities/Report.php @@ -4,7 +4,7 @@ use openvk\Web\Util\DateTime; use Nette\Database\Table\ActiveRow; use openvk\Web\Models\RowModel; use Chandler\Database\DatabaseConnection; -use openvk\Web\Models\Repositories\{Applications, Comments, Notes, Users, Posts, Photos, Videos, Clubs}; +use openvk\Web\Models\Repositories\{Applications, Comments, Notes, Reports, Users, Posts, Photos, Videos, Clubs}; use Chandler\Database\DatabaseConnection as DB; use Nette\InvalidStateException as ISE; use Nette\Database\Table\Selection; @@ -81,6 +81,11 @@ class Report extends RowModel return (new Posts)->get($this->getContentId())->getOwner(); } + function getReportAuthor(): User + { + return (new Users)->get($this->getRecord()->user_id); + } + function banUser($initiator) { $reason = $this->getContentType() !== "user" ? ("**content-" . $this->getContentType() . "-" . $this->getContentId() . "**") : ("Подозрительная активность"); @@ -95,6 +100,42 @@ class Report extends RowModel $this->getAuthor()->adminNotify("Ваш контент, который вы опубликовали $pubTime ($name) был удалён модераторами инстанса. За повторные или серьёзные нарушения вас могут заблокировать."); $this->getContentObject()->delete($this->getContentType() !== "app"); } + + $this->delete(); + } + + function getDuplicates(): \Traversable + { + return (new Reports)->getDuplicates($this->getContentType(), $this->getContentId(), $this->getId()); + } + + function getDuplicatesCount(): int + { + return count(iterator_to_array($this->getDuplicates())); + } + + function hasDuplicates(): bool + { + return $this->getDuplicatesCount() > 0; + } + + function getContentName(): string + { + if (method_exists($this->getContentObject(), "getCanonicalName")) + return $this->getContentObject()->getCanonicalName(); + + return $this->getContentType() . " #" . $this->getContentId(); + } + + public function delete(bool $softly = true): void + { + if ($this->hasDuplicates()) { + foreach ($this->getDuplicates() as $duplicate) { + $duplicate->setDeleted(1); + $duplicate->save(); + } + } + $this->setDeleted(1); $this->save(); } diff --git a/Web/Models/Repositories/Reports.php b/Web/Models/Repositories/Reports.php index 9f32cc50..edce8980 100644 --- a/Web/Models/Repositories/Reports.php +++ b/Web/Models/Repositories/Reports.php @@ -20,15 +20,22 @@ class Reports return is_null($ar) ? NULL : new Report($ar); } - function getReports(int $state = 0, int $page = 1): \Traversable + function getReports(int $state = 0, int $page = 1, ?string $type = NULL, ?bool $pagination = true): \Traversable { - foreach($this->reports->where(["deleted" => 0])->order("created DESC")->page($page, 15) as $t) + $filter = ["deleted" => 0]; + if ($type) $filter["type"] = $type; + + $reports = $this->reports->where($filter)->order("created DESC")->group("target_id, type"); + if ($pagination) + $reports = $reports->page($page, 15); + + foreach($reports as $t) yield new Report($t); } function getReportsCount(int $state = 0): int { - return sizeof($this->reports->where(["deleted" => 0, "type" => $state])); + return sizeof($this->reports->where(["deleted" => 0, "type" => $state])->group("target_id, type")); } function get(int $id): ?Report @@ -45,6 +52,16 @@ class Reports else return null; } - + + function getDuplicates(string $type, int $target_id, ?int $orig = NULL, ?int $user_id = NULL): \Traversable + { + $filter = ["deleted" => 0, "type" => $type, "target_id" => $target_id]; + if ($orig) $filter[] = "id != $orig"; + if ($user_id) $filter["user_id"] = $user_id; + + foreach ($this->reports->where($filter) as $report) + yield new Report($report); + } + use \Nette\SmartObject; } diff --git a/Web/Presenters/ReportPresenter.php b/Web/Presenters/ReportPresenter.php index dc965e22..68d27861 100644 --- a/Web/Presenters/ReportPresenter.php +++ b/Web/Presenters/ReportPresenter.php @@ -20,15 +20,52 @@ final class ReportPresenter extends OpenVKPresenter { $this->assertUserLoggedIn(); $this->assertPermission('openvk\Web\Models\Entities\TicketReply', 'write', 0); + if ($_SERVER["REQUEST_METHOD"] === "POST") + $this->assertNoCSRF(); - $this->template->reports = $this->reports->getReports(0, (int)($this->queryParam("p") ?? 1)); - $this->template->count = $this->reports->getReportsCount(); + $act = in_array($this->queryParam("act"), ["post", "photo", "video", "group", "comment", "note", "app", "user"]) ? $this->queryParam("act") : NULL; + + if (!$this->queryParam("orig")) { + $this->template->reports = $this->reports->getReports(0, (int)($this->queryParam("p") ?? 1), $act, $_SERVER["REQUEST_METHOD"] !== "POST"); + $this->template->count = $this->reports->getReportsCount(); + } else { + $orig = $this->reports->get((int) $this->queryParam("orig")); + if (!$orig) $this->redirect("/scumfeed"); + + $this->template->reports = $orig->getDuplicates(); + $this->template->count = $orig->getDuplicatesCount(); + $this->template->orig = $orig->getId(); + } $this->template->paginatorConf = (object) [ "count" => $this->template->count, "page" => $this->queryParam("p") ?? 1, "amount" => NULL, "perPage" => 15, ]; + $this->template->mode = $act ?? "all"; + + if ($_SERVER["REQUEST_METHOD"] === "POST") { + $reports = []; + foreach ($this->reports->getReports(0, 0, $act, false) as $report) { + $reports[] = [ + "id" => $report->getId(), + "author" => [ + "id" => $report->getReportAuthor()->getId(), + "url" => $report->getReportAuthor()->getURL(), + "name" => $report->getReportAuthor()->getCanonicalName(), + "is_female" => $report->getReportAuthor()->isFemale() + ], + "content" => [ + "name" => $report->getContentName(), + "type" => $report->getContentType(), + "id" => $report->getContentId(), + "url" => $report->getContentType() === "user" ? (new Users)->get((int) $report->getContentId())->getURL() : NULL + ], + "duplicates" => $report->getDuplicatesCount(), + ]; + } + $this->returnJson(["reports" => $reports]); + } } function renderView(int $id): void @@ -52,13 +89,15 @@ final class ReportPresenter extends OpenVKPresenter exit(json_encode([ "error" => tr("error_segmentation") ])); if(in_array($this->queryParam("type"), ["post", "photo", "video", "group", "comment", "note", "app", "user"])) { - $report = new Report; - $report->setUser_id($this->user->id); - $report->setTarget_id($id); - $report->setType($this->queryParam("type")); - $report->setReason($this->queryParam("reason")); - $report->setCreated(time()); - $report->save(); + if (count(iterator_to_array($this->reports->getDuplicates($this->queryParam("type"), $id, NULL, $this->user->id))) <= 0) { + $report = new Report; + $report->setUser_id($this->user->id); + $report->setTarget_id($id); + $report->setType($this->queryParam("type")); + $report->setReason($this->queryParam("reason")); + $report->setCreated(time()); + $report->save(); + } exit(json_encode([ "reason" => $this->queryParam("reason") ])); } else { diff --git a/Web/Presenters/templates/@listView.xml b/Web/Presenters/templates/@listView.xml index 34739b59..f2342a85 100644 --- a/Web/Presenters/templates/@listView.xml +++ b/Web/Presenters/templates/@listView.xml @@ -12,16 +12,24 @@ {include size, x => $dat} {/ifset} + {ifset before_content} + {include before_content, x => $dat} + {/ifset} + {ifset specpage} {include specpage, x => $dat} {else}