Przeglądaj źródła

Add Admin/Reports page

Visman 5 lat temu
rodzic
commit
bde1703a42

+ 3 - 0
app/Controllers/Routing.php

@@ -153,6 +153,9 @@ class Routing
                 $r->add(self::GET, '/admin/bans/result/{data}[/{page:[1-9]\d*}]',                     'AdminBans:result', 'AdminBansResult');
                 $r->add(self::GET, '/admin/bans/result/{data}[/{page:[1-9]\d*}]',                     'AdminBans:result', 'AdminBansResult');
                 $r->add(self::GET, '/admin/bans/delete/{id:[1-9]\d*}/{token}[/{uid:[2-9]|[1-9]\d+}]', 'AdminBans:delete', 'AdminBansDelete');
                 $r->add(self::GET, '/admin/bans/delete/{id:[1-9]\d*}/{token}[/{uid:[2-9]|[1-9]\d+}]', 'AdminBans:delete', 'AdminBansDelete');
             }
             }
+
+            $r->add(self::GET, '/admin/reports',                           'AdminReports:view', 'AdminReports');
+            $r->add(self::GET, '/admin/reports/zap/{id:[1-9]\d*}/{token}', 'AdminReports:zap',  'AdminReportsZap');
         }
         }
         // только админ
         // только админ
         if ($user->isAdmin) {
         if ($user->isAdmin) {

+ 1 - 1
app/Models/Pages/Admin.php

@@ -57,7 +57,7 @@ class Admin extends Page
             $nav['bans'] = [$r->link('AdminBans'), \ForkBB\__('Bans')];
             $nav['bans'] = [$r->link('AdminBans'), \ForkBB\__('Bans')];
         }
         }
         if ($this->user->isAdmin || $this->c->config->o_report_method == '0' || $this->c->config->o_report_method == '2') {
         if ($this->user->isAdmin || $this->c->config->o_report_method == '0' || $this->c->config->o_report_method == '2') {
-            $nav['reports'] = ['admin_reports.php', \ForkBB\__('Reports')];
+            $nav['reports'] = [$r->link('AdminReports'), \ForkBB\__('Reports')];
         }
         }
 
 
         if ($this->user->isAdmin) {
         if ($this->user->isAdmin) {

+ 140 - 0
app/Models/Pages/Admin/Reports.php

@@ -0,0 +1,140 @@
+<?php
+
+namespace ForkBB\Models\Pages\Admin;
+
+use ForkBB\Models\Page;
+use ForkBB\Models\Pages\Admin;
+use ForkBB\Models\Post\Model as Post;
+use ForkBB\Models\Report\Model as Report;
+
+class Reports extends Admin
+{
+    /**
+     * Подготавливает данные для шаблона
+     *
+     * @return Page
+     */
+    public function view(): Page
+    {
+        if ($this->user->last_report_id < $this->c->reports->lastId()) {
+            $this->user->last_report_id = $this->c->reports->lastId();
+
+            $this->c->users->update($this->user);
+        }
+
+        $this->c->Lang->load('admin_reports');
+
+        $this->nameTpl  = 'admin/reports';
+        $this->aIndex   = 'reports';
+        $this->formNew  = $this->form(true);
+        $this->formOld  = $this->form(false);
+
+        return $this;
+    }
+
+    /**
+     * Формирует данные для формы
+     *
+     * @param bool $noZapped
+     *
+     * @return array
+     */
+    protected function form(bool $noZapped): array
+    {
+        $form = [
+            'sets'   => [],
+        ];
+
+        foreach ($this->c->reports->loadList($noZapped) as $report) {
+            if ($noZapped) {
+                $cur = [
+                    'legend' => \ForkBB\__('Reported %s', \ForkBB\dt($report->created)),
+                ];
+            } else {
+                $cur = [
+                    'legend' => \ForkBB\__('Marked as read %1$s by %2$s', \ForkBB\dt($report->zapped), $report->marker->username),
+                ];
+            }
+            $cur['fields'] = [];
+            $author = $report->author;
+            $cur['fields']['report_by' . $report->id] = [
+                'type'    => $author->isGuest ? 'str' : 'link',
+                'value'   => $author->username,
+                'title'   => $author->username,
+                'caption' => \ForkBB\__('Reported by'),
+                'href'    => $author->link,
+            ];
+            $post = $report->post;
+            if ($post instanceof Post) {
+                $topic = $post->parent;
+                $forum = $topic->parent;
+                $cur['fields']['post' . $report->id] = [
+                    'type'    => 'str',
+                    'value'   => \ForkBB\__('Post #%s ', $post->id, $post->link, $topic->subject, $topic->link, $forum->forum_name, $forum->link),
+                    'html'    => true,
+                ];
+            } else {
+                $cur['fields']['post' . $report->id] = [
+                    'type'    => 'str',
+                    'value'   => \ForkBB\__('Post #%s', $report->post_id),
+                ];
+            }
+            $cur['fields']['reason' . $report->id] = [
+                'type'    => 'str',
+                'value'   => $report->message,
+                'caption' => \ForkBB\__('Reason'),
+            ];
+            if ($noZapped) {
+                $cur['fields']['zap' . $report->id] = [
+                    'type'    => 'btn',
+                    'value'   => \ForkBB\__('Zap'),
+                    'title'   => \ForkBB\__('Zap'),
+                    'link'    => $report->linkZap,
+                ];
+            }
+            $form['sets'][$report->id] = $cur;
+        }
+
+        if (empty($form['sets'])) {
+            $form['sets'][] = [
+                'info' => [
+                    'info1' => [
+                        'type'  => '', //????
+                        'value' => $noZapped ? \ForkBB\__('No new reports') : \ForkBB\__('No zapped reports'),
+                    ],
+                ],
+            ];
+        }
+
+        return $form;
+    }
+
+    /**
+     * Помечает сигнал обработанным
+     *
+     * @param array $args
+     * @param string $method
+     *
+     * @return Page
+     */
+    public function zap(array $args, string $method): Page
+    {
+        if (! $this->c->Csrf->verify($args['token'], 'AdminReportsZap', $args)) {
+            return $this->c->Redirect->url($forum->link)->message('Bad token');
+        }
+
+        $this->c->Lang->load('admin_reports');
+
+        $report = $this->c->reports->load((int) $args['id']);
+
+        if ($report instanceof Report) {
+            $report->zapped = \time(); // ???? перенести в модель?
+            $report->marker = $this->user;
+
+            $this->c->reports->update($report);
+            $this->c->reports->clear();
+        }
+
+        return $this->c->Redirect->page('AdminReports')->message('Report zapped redirect');
+    }
+}

+ 75 - 0
app/Models/Report/Load.php

@@ -0,0 +1,75 @@
+<?php
+
+namespace ForkBB\Models\Report;
+
+use ForkBB\Models\Action;
+use ForkBB\Models\Report\Model as Report;
+use InvalidArgumentException;
+
+class Load extends Action
+{
+    /**
+     * Загружает сигнал из БД
+     *
+     * @param int $id
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return null|Report
+     */
+    public function load(int $id): ?Report
+    {
+        if ($id < 1) {
+            throw new InvalidArgumentException('Expected a positive report id');
+        }
+
+        $vars = [
+            ':id' => $id,
+        ];
+        $sql = 'SELECT r.*
+                FROM ::reports AS r
+                WHERE r.id=?i:id';
+        $data = $this->c->DB->query($sql, $vars)->fetch();
+
+        if (empty($data)) {
+            return null;
+        }
+
+        $report  = $this->manager->create($data);
+
+        return $report;
+    }
+
+    /**
+     * Загрузка сигналов из БД
+     *
+     * @param bool $noZapped
+     *
+     * @return array
+     */
+    public function loadList(bool $noZapped): array
+    {
+        $result = [];
+        $vars = [];
+
+        if ($noZapped) {
+            $sql = 'SELECT r.*
+                    FROM ::reports AS r
+                    WHERE r.zapped=0
+                    ORDER BY r.id DESC';
+        } else {
+            $sql = 'SELECT r.*
+                    FROM ::reports AS r
+                    WHERE r.zapped!=0
+                    ORDER BY r.zapped DESC'; // LIMIT 10 не нужен, если при обработке сигнала будут удалены старые
+        }
+
+        $data = $this->c->DB->query($sql, $vars)->fetchAll();
+
+        foreach ($data as $row) {
+            $result[] = $this->manager->create($row);
+        }
+
+        return $result;
+    }
+}

+ 58 - 25
app/Models/Report/Manager.php

@@ -10,7 +10,7 @@ use RuntimeException;
 class Manager extends ManagerModel
 class Manager extends ManagerModel
 {
 {
     /**
     /**
-     * Создает новую модель сообщения
+     * Создает новую модель сигнала
      *
      *
      * @param array $attrs
      * @param array $attrs
      *
      *
@@ -22,56 +22,67 @@ class Manager extends ManagerModel
     }
     }
 
 
     /**
     /**
-     * Загружает сообщение из БД
+     * Загружает сигнал из БД
      *
      *
      * @param int $id
      * @param int $id
-     * @param int $tid
      *
      *
      * @return null|Report
      * @return null|Report
      */
      */
-    public function load(int $id, int $tid = null): ?Report
+    public function load(int $id): ?Report
     {
     {
-        $post = $this->get($id);
-
-        if ($post instanceof Report) {
-            if (null !== $tid && $post->topic_id !== $tid) {
-                return null;
-            }
+        if ($this->isset($id)) {
+            return $this->get($id);
         } else {
         } else {
-            if (null !== $tid) {
-                $post = $this->Load->loadFromTopic($id, $tid);
+            $report = $this->Load->load($id);
+            $this->set($id, $report);
+            return $report;
+        }
+    }
+
+    /**
+     * Загрузка сигналов из БД
+     *
+     * @param bool $noZapped
+     *
+     * @return array
+     */
+    public function loadList(bool $noZapped = true): array
+    {
+        $result = [];
+        foreach ($this->Load->loadList($noZapped) as $report) {
+            if ($this->isset($report->id)) {
+                $result[] = $this->get($report->id);
             } else {
             } else {
-                $post = $this->Load->load($id);
+                $result[] = $report;
+                $this->set($report->id, $report);
             }
             }
-            $this->set($id, $post);
         }
         }
-
-        return $post;
+        return $result;
     }
     }
 
 
     /**
     /**
-     * Обновляет сообщение в БД
+     * Обновляет сигнал в БД
      *
      *
-     * @param Report $post
+     * @param Report $report
      *
      *
      * @return Report
      * @return Report
      */
      */
-    public function update(Report $post): Report
+    public function update(Report $report): Report
     {
     {
-        return $this->Save->update($post);
+        return $this->Save->update($report);
     }
     }
 
 
     /**
     /**
-     * Добавляет новое сообщение в БД
+     * Добавляет новый сигнал в БД
      *
      *
-     * @param Report $post
+     * @param Report $report
      *
      *
      * @return int
      * @return int
      */
      */
-    public function insert(Report $post): int
+    public function insert(Report $report): int
     {
     {
-        $id = $this->Save->insert($post);
-        $this->set($id, $post);
+        $id = $this->Save->insert($report);
+        $this->set($id, $report);
         return $id;
         return $id;
     }
     }
 
 
@@ -92,4 +103,26 @@ class Manager extends ManagerModel
 
 
         return $last;
         return $last;
     }
     }
+
+    /**
+     * Удаляет старые обработанные сигналы
+     */
+    public function clear(): void
+    {
+        $sql = 'SELECT r.zapped
+                FROM ::reports as r
+                WHERE r.zapped!=0
+                ORDER BY r.zapped DESC
+                LIMIT 10,1';
+        $time = (int) $this->c->DB->query($sql)->fetchColumn();
+
+        if ($time > 0) {
+            $vars = [
+                ':time' => $time,
+            ];
+            $sql = 'DELETE FROM ::reports
+                    WHERE zapped<=?i:time';
+            $this->c->DB->exec($sql, $vars);
+        }
+    }
 }
 }

+ 57 - 1
app/Models/Report/Model.php

@@ -44,7 +44,48 @@ class Model extends DataModel
             $user = $this->c->users->create();
             $user = $this->c->users->create();
 
 
             $user->__id       = $this->reported_by;
             $user->__id       = $this->reported_by;
-            $user->__username = 'User #' . $this->reported_by;
+            $user->__username = '{User #' . $this->reported_by .'}';
+        }
+
+        return $user;
+    }
+
+    /**
+     * Устанавливает расмотревшего
+     *
+     * @param User $user
+     *
+     * @throws RuntimeException
+     */
+    protected function setmarker(User $user): void
+    {
+        if ($user->isGuest) {
+            throw new RuntimeException('Bad marker');
+        }
+
+        $this->zapped_by = $user->id;
+    }
+
+    /**
+     * Рвассмотревший
+     *
+     * @throws RuntimeException
+     *
+     * @return User
+     */
+    protected function getmarker(): User
+    {
+        if ($this->zapped_by < 1) {
+            throw new RuntimeException('No marker data');
+        }
+
+        $user = $this->c->users->load($this->zapped_by);
+
+        if (! $user instanceof User || $user->isGuest) {
+            $user = $this->c->users->create();
+
+            $user->__id       = $this->zapped_by;
+            $user->__username = '{User #' . $this->zapped_by .'}';
         }
         }
 
 
         return $user;
         return $user;
@@ -81,4 +122,19 @@ class Model extends DataModel
 
 
         return $this->c->posts->load($this->post_id);
         return $this->c->posts->load($this->post_id);
     }
     }
+
+    /**
+     * Ссылка на рассмотрение
+     */
+    public function getlinkZap(): string
+    {
+        if (empty($this->zapped)) {
+            return $this->c->Router->link('AdminReportsZap', [
+                'id'    => $this->id,
+                'token' => $this->c->Csrf->create('AdminReportsZap', ['id' => $this->id]),
+            ]);
+        } else {
+            return '';
+        }
+    }
 }
 }

+ 2 - 0
app/config/main.dist.php

@@ -180,6 +180,7 @@ return [
         'AdminUsersPromote' => \ForkBB\Models\Pages\Admin\Users\Promote::class,
         'AdminUsersPromote' => \ForkBB\Models\Pages\Admin\Users\Promote::class,
         'AdminHost'       => \ForkBB\Models\Pages\Admin\Host::class,
         'AdminHost'       => \ForkBB\Models\Pages\Admin\Host::class,
         'AdminBans'       => \ForkBB\Models\Pages\Admin\Bans::class,
         'AdminBans'       => \ForkBB\Models\Pages\Admin\Bans::class,
+        'AdminReports'    => \ForkBB\Models\Pages\Admin\Reports::class,
 
 
         'ConfigModel'     => \ForkBB\Models\Config\Model::class,
         'ConfigModel'     => \ForkBB\Models\Config\Model::class,
         'ConfigModelLoad' => \ForkBB\Models\Config\Load::class,
         'ConfigModelLoad' => \ForkBB\Models\Config\Load::class,
@@ -257,6 +258,7 @@ return [
 
 
         'ReportModel'             => \ForkBB\Models\Report\Model::class,
         'ReportModel'             => \ForkBB\Models\Report\Model::class,
         'ReportManagerSave'       => \ForkBB\Models\Report\Save::class,
         'ReportManagerSave'       => \ForkBB\Models\Report\Save::class,
+        'ReportManagerLoad'       => \ForkBB\Models\Report\Load::class,
 
 
         'GroupModel'         => \ForkBB\Models\Group\Model::class,
         'GroupModel'         => \ForkBB\Models\Group\Model::class,
         'GroupManager'       => \ForkBB\Models\Group\Manager::class,
         'GroupManager'       => \ForkBB\Models\Group\Manager::class,

+ 58 - 0
app/lang/en/admin_reports.po

@@ -0,0 +1,58 @@
+#
+msgid ""
+msgstr ""
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"Project-Id-Version: ForkBB\n"
+"POT-Creation-Date: \n"
+"PO-Revision-Date: \n"
+"Last-Translator: \n"
+"Language-Team: ForkBB <mio.visman@yandex.ru>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: en\n"
+
+msgid "Report zapped redirect"
+msgstr "Report marked as read. Redirecting …"
+
+msgid "New reports "
+msgstr "New reports"
+
+msgid "Deleted user"
+msgstr "Deleted user"
+
+msgid "Deleted"
+msgstr "Deleted"
+
+msgid "Post #%s"
+msgstr "Post #%s"
+
+msgid "Post #%s "
+msgstr "<a href=\"%6$s\">%5$s</a> » <a href=\"%4$s\">%3$s</a> » <a href=\"%2$s\">Post #%1$s</a>"
+
+msgid "Reported %s"
+msgstr "Reported %s"
+
+msgid "Reported by"
+msgstr "Reported by"
+
+msgid "Reason"
+msgstr "Reason"
+
+msgid "Zap"
+msgstr "Mark as read"
+
+msgid "No new reports"
+msgstr "There are no new reports."
+
+msgid "10 last read reports"
+msgstr "10 last read reports"
+
+msgid "NA"
+msgstr "N/A"
+
+msgid "Marked as read %1$s by %2$s"
+msgstr "Marked as read %1$s by %2$s"
+
+msgid "No zapped reports"
+msgstr "There are no read reports."

+ 58 - 0
app/lang/ru/admin_reports.po

@@ -0,0 +1,58 @@
+#
+msgid ""
+msgstr ""
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
+"Project-Id-Version: ForkBB\n"
+"POT-Creation-Date: \n"
+"PO-Revision-Date: \n"
+"Last-Translator: \n"
+"Language-Team: ForkBB <mio.visman@yandex.ru>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: ru\n"
+
+msgid "Report zapped redirect"
+msgstr "Сигнал рассмотрен. Переадресация …"
+
+msgid "New reports "
+msgstr "Новые сигналы"
+
+msgid "Deleted user"
+msgstr "Пользователь удалён"
+
+msgid "Deleted"
+msgstr "Удалено"
+
+msgid "Post #%s"
+msgstr "Сообщение #%s"
+
+msgid "Post #%s "
+msgstr "<a href=\"%6$s\">%5$s</a> » <a href=\"%4$s\">%3$s</a> » <a href=\"%2$s\">Сообщение #%1$s</a>"
+
+msgid "Reported %s"
+msgstr "Сигнал подан %s"
+
+msgid "Reported by"
+msgstr "Просигналил"
+
+msgid "Reason"
+msgstr "Причина"
+
+msgid "Zap"
+msgstr "Рассмотрено"
+
+msgid "No new reports"
+msgstr "Нет новых сигналов."
+
+msgid "10 last read reports"
+msgstr "Последние 10 из уже рассмотренных"
+
+msgid "NA"
+msgstr "Н/Д"
+
+msgid "Marked as read %1$s by %2$s"
+msgstr "Рассмотрен %1$s, %2$s"
+
+msgid "No zapped reports"
+msgstr "Пока нет рассмотренных сигналов."

+ 17 - 0
app/templates/admin/reports.forkbb.php

@@ -0,0 +1,17 @@
+@extends ('layouts/admin')
+@if ($form = $p->formNew)
+      <section class="f-admin f-reports f-reports-new">
+        <h2>{!! __('New reports ') !!}</h2>
+        <div class="f-fdiv">
+    @include ('layouts/form')
+        </div>
+      </section>
+@endif
+@if ($form = $p->formOld)
+      <section class="f-admin f-reports f-reports-old">
+        <h2>{!! __('10 last read reports') !!}</h2>
+        <div class="f-fdiv">
+    @include ('layouts/form')
+        </div>
+      </section>
+@endif

+ 1 - 1
app/templates/layouts/form.forkbb.php

@@ -93,7 +93,7 @@
                 @elseif ('btn' === $cur['type'])
                 @elseif ('btn' === $cur['type'])
                 <a class="f-btn @if ($cur['disabled']) f-disabled @endif" href="{!! $cur['link'] !!}" title="{{ $cur['title'] or '' }}" @if ($cur['disabled']) tabindex="-1" @endif>{{ $cur['value'] }}</a>
                 <a class="f-btn @if ($cur['disabled']) f-disabled @endif" href="{!! $cur['link'] !!}" title="{{ $cur['title'] or '' }}" @if ($cur['disabled']) tabindex="-1" @endif>{{ $cur['value'] }}</a>
                 @elseif ('str' === $cur['type'])
                 @elseif ('str' === $cur['type'])
-                <p class="f-str" id="id-{{ $key }}">{{ $cur['value'] }}</p>
+                <p class="f-str" id="id-{{ $key }}"> @if ($cur['html']){!! $cur['value'] !!} @else{{ $cur['value'] }} @endif</p>
                 @elseif ('link' === $cur['type'])
                 @elseif ('link' === $cur['type'])
                 <a class="f-link" id="id-{{ $key }}" href="{{ $cur['href'] or '' }}" title="{{ $cur['title'] or '' }}">{{ $cur['value'] or '' }}</a>
                 <a class="f-link" id="id-{{ $key }}" href="{{ $cur['href'] or '' }}" title="{{ $cur['title'] or '' }}">{{ $cur['value'] or '' }}</a>
                 @elseif ('yield' === $cur['type'])
                 @elseif ('yield' === $cur['type'])

+ 4 - 0
public/style/ForkBB/style.css

@@ -1733,6 +1733,10 @@ body,
 /**********/
 /**********/
 /* Репорт */
 /* Репорт */
 /**********/
 /**********/
+#fork .f-reports > h2 {
+  display: block;
+}
+
 #id-fs-report > legend {
 #id-fs-report > legend {
   display: none;
   display: none;
 }
 }