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}
{var $data = is_array($iterator) ? $iterator : iterator_to_array($iterator)} + {ifset top} + {include top, x => $dat} + {/ifset} + {if sizeof($data) > 0}
- +
diff --git a/Web/Presenters/templates/Report/List.xml b/Web/Presenters/templates/Report/List.xml index fafb07f9..3d6a527b 100644 --- a/Web/Presenters/templates/Report/List.xml +++ b/Web/Presenters/templates/Report/List.xml @@ -1,8 +1,12 @@ {extends "../@listView.xml"} {var iterator = iterator_to_array($reports)} {var page = $paginatorConf->page} +{var table_body_id = "reports"} {block tabs}{include "../NoSpam/Tabs.xml", mode => "reports"}{/block} +{block before_content} + {include "./Tabs.xml", mode => $mode} +{/block} {block title}{_list_of_reports}{/block} @@ -14,6 +18,12 @@ {/block} +{block top} + {if !is_null($orig)} +

Дубликаты жалобы №{$orig}

+ {/if} +{/block} + {* BEGIN ELEMENTS DESCRIPTION *} {block link|strip|stripHtml} @@ -25,25 +35,26 @@ {/block} {block name} - {$x->getAuthor()->getCanonicalName()} + Жалоба №{$x->getId()} {/block} {block description} - {if $x->getContentType() == "post"} - {_text_of_the_post}: {$x->getContentObject()->getText()} - {elseif $x->getContentType() == "photo"} - {_photo} - {elseif $x->getContentType() == "video"} - {_video} - {elseif $x->getContentType() == "group"} - {_groups} - {elseif $x->getContentType() == "comment"} - {_comment} - {elseif $x->getContentType() == "app"} - {_app} - {elseif $x->getContentType() == "user"} - {_users} - {else} - Unknown +
+ {$x->getReportAuthor()->getCanonicalName()} + + пожаловал{!$x->getReportAuthor()->isFemale() ? 'ся' : 'ась'} на + {if $x->getContentType() === "user"}{/if} + {$x->getContentName()} + {if $x->getContentType() === "user"}{/if} + + {if $x->hasDuplicates() && !$orig} +
+ Другие жалобы на этот контент: {$x->getDuplicatesCount()} шт. {/if} {/block} + +{block bottom} + +{/block} diff --git a/Web/Presenters/templates/Report/Tabs.xml b/Web/Presenters/templates/Report/Tabs.xml new file mode 100644 index 00000000..e878ccb3 --- /dev/null +++ b/Web/Presenters/templates/Report/Tabs.xml @@ -0,0 +1,145 @@ + +
+
+ Все +
+ + + + + + + + +
+ + \ No newline at end of file diff --git a/Web/Presenters/templates/Report/View.xml b/Web/Presenters/templates/Report/View.xml index 404b91d5..4a0682d1 100644 --- a/Web/Presenters/templates/Report/View.xml +++ b/Web/Presenters/templates/Report/View.xml @@ -12,6 +12,8 @@
{include "../NoSpam/Tabs.xml", mode => "reports"}

+ {$report->getReportAuthor()->getCanonicalName()} пожаловался на {$report->getContentName()} +
{_comment}: {$report->getReason()}

{include "ViewContent.xml", type => $report->getContentType(), object => $report->getContentObject()} @@ -21,7 +23,7 @@
- +