Browse Source

Control of redirects topics

 #22
Visman 1 year ago
parent
commit
9bf55098a1

+ 5 - 0
app/Models/Pages/Forum.php

@@ -122,6 +122,11 @@ class Forum extends Page
                     'type'      => 'submit',
                     'value'     => __('Merge'),
                 ],
+                'link' => [
+                    'class'     => ['origin'],
+                    'type'      => 'submit',
+                    'value'     => __('Link btn'),
+                ],
             ],
         ];
 

+ 161 - 0
app/Models/Pages/Moderate.php

@@ -39,6 +39,7 @@ class Moderate extends Page
         'unstick' => self::INTOPIC + self::TOTOPIC,
         'stick'   => self::INTOPIC + self::TOTOPIC,
         'split'   => self::INTOPIC,
+        'link'    => self::INFORUM,
     ];
 
     public function __construct(Container $container)
@@ -128,6 +129,12 @@ class Moderate extends Page
                 && \count($v->ids) < 2
             ) {
                 $v->addError('Not enough topics selected');
+            // управление перенаправлениями
+            } elseif (
+                'link' === $action
+                && \count($v->ids) > 1
+            ) {
+                $v->addError('Only one topic is permissible');
             // перенос тем или разделение постов
             } elseif (
                 'move' === $action
@@ -171,6 +178,8 @@ class Moderate extends Page
                 'page'        => 'integer|min:1',
                 'ids'         => 'required|array',
                 'ids.*'       => 'required|integer|min:1|max:9999999999',
+                'forums'      => 'array',
+                'forums.*'    => 'integer|min:1|max:9999999999', // ????
                 'confirm'     => 'integer',
                 'redirect'    => 'integer',
                 'subject'     => 'string:trim,spaces|min:1|max:70',
@@ -184,6 +193,7 @@ class Moderate extends Page
                 'unstick'     => 'string',
                 'stick'       => 'string',
                 'split'       => 'string',
+                'link'        => 'string',
                 'action'      => 'action_process',
             ])->addAliases([
             ])->addArguments([
@@ -570,6 +580,157 @@ class Moderate extends Page
         }
     }
 
+    protected function actionLink(array $topics, Validator $v): Page
+    {
+        $topic = \array_pop($topics);
+
+        if ($topic->moved_to) {
+            return $this->c->Message->message('Need full topic for this operation');
+        }
+
+        $links = $this->c->topics->loadLinks($topic);
+        $ft    = [];
+
+        foreach ($links as $link) {
+            $ft[$link->parent->id][] = $link;
+        }
+
+        switch ($v->step) {
+            case 1:
+                $this->formTitle   = 'Control of redirects title';
+                $this->crumbs      = $this->crumbs($this->formTitle, 'Moderate', $this->curForum);
+                $this->form        = $this->formLinks($topic, $ft, $v);
+
+                return $this;
+            case 2:
+                $root = $this->c->forums->get(0);
+
+                if ($root instanceof Forum) {
+                    $selected = $v->forums ?: [];
+                    $delLinks = [];
+
+                    foreach ($this->c->forums->depthList($root, 0) as $forum) {
+                        if ('' != $forum->redirect_url) {
+                            continue;
+                        }
+
+                        // создать тему-перенаправление
+                        if (
+                            empty($ft[$forum->id])
+                            && \in_array($forum->id, $selected, true)
+                        ) {
+                            $rTopic            = $this->c->topics->create();
+                            $rTopic->poster    = $topic->poster;
+                            $rTopic->poster_id = $topic->poster_id;
+                            $rTopic->subject   = $topic->subject;
+                            $rTopic->posted    = $topic->posted;
+                            $rTopic->last_post = $topic->last_post;
+                            $rTopic->moved_to  = $topic->moved_to ?: $topic->id;
+                            $rTopic->forum_id  = $forum->id;
+
+                            $this->c->topics->insert($rTopic);
+                            $this->c->forums->update($forum->calcStat());
+                        // удалить тему(ы)-перенаправление
+                        } elseif (
+                            ! empty($ft[$forum->id])
+                            && ! \in_array($forum->id, $selected, true)
+                        ) {
+                            foreach ($ft[$forum->id] as $link) {
+                                $delLinks[] = $link;
+                            }
+                        }
+                    }
+
+                    if ($delLinks) {
+                        $this->c->topics->delete(...$delLinks);
+                    }
+                }
+
+                return $this->c->Redirect->url($topic->linkCrumbExt)->message('Redirects changed redirect', FORK_MESS_SUCC);
+            default:
+                return $this->c->Message->message('Bad request');
+        }
+    }
+
+    /**
+     * Подготавливает массив данных для формы управления переадресацией
+     */
+    protected function formLinks(Topic $topic, array $ft, Validator $v): array
+    {
+        $form = [
+            'action' => $this->c->Router->link('Moderate'),
+            'hidden' => [
+                'token'  => $this->c->Csrf->create('Moderate'),
+                'step'   => $v->step + 1,
+                'forum'  => $v->forum,
+                'ids'    => $v->ids,
+            ],
+            'sets' => [
+                'info' => [
+                    'inform' => [
+                        [
+                            'html' => __(['Topic «%s»', $topic->name]),
+                        ],
+                    ],
+                ],
+            ],
+            'btns' => [
+                'link' => [
+                    'type'  => 'submit',
+                    'value' => __('Change btn'),
+                ],
+                'cancel' => [
+                    'type'  => 'submit',
+                    'value' => __('Cancel'),
+                ],
+            ],
+        ];
+
+        $root = $this->c->forums->get(0);
+
+        if ($root instanceof Forum) {
+            $list = $this->c->forums->depthList($root, 0);
+            $cid  = null;
+
+            foreach ($list as $forum) {
+                if ($cid !== $forum->cat_id) {
+                    $form['sets']["category{$forum->cat_id}-info"] = [
+                        'inform' => [
+                            [
+                                'message' => $forum->cat_name,
+                            ],
+                        ],
+                    ];
+                    $cid = $forum->cat_id;
+                }
+
+                $fields = [];
+                $fields["name{$forum->id}"] = [
+                    'class'   => ['modforum', 'name', 'depth' . $forum->depth],
+                    'type'    => 'label',
+                    'value'   => $forum->forum_name,
+                    'caption' => 'Forum label',
+                    'for'     => "forums[{$forum->id}]",
+                ];
+                $fields["forums[{$forum->id}]"] = [
+                    'class'    => ['modforum', 'moderator'],
+                    'type'     => 'checkbox',
+                    'value'    => $forum->id,
+                    'checked'  => ! empty($ft[$forum->id]),
+                    'disabled' => '' != $forum->redirect_url,
+                    'caption'  => 'Redir label',
+                ];
+                $form['sets']["forum{$forum->id}"] = [
+                    'class'  => $topic->parent->id === $forum->id ? ['modforum', 'current'] : ['modforum'],
+                    'legend' => $forum->cat_name . ' / ' . $forum->forum_name,
+                    'fields' => $fields,
+                ];
+            }
+        }
+
+        return $form;
+    }
+
     /**
      * Подготавливает массив данных для формы подтверждения
      */

+ 35 - 5
app/Models/Topic/Load.php

@@ -58,14 +58,14 @@ class Load extends Action
         ];
         $query = $this->getSql('t.id=?i:tid', true);
 
-        $data = $this->c->DB->query($query, $vars)->fetch();
+        $row = $this->c->DB->query($query, $vars)->fetch();
 
         // тема отсутствует или недоступна
-        if (empty($data)) {
+        if (empty($row)) {
             return null;
         }
 
-        $topic = $this->manager->create($data);
+        $topic = $this->manager->create($row);
         $forum = $topic->parent;
 
         if ($forum instanceof Forum) {
@@ -75,8 +75,6 @@ class Load extends Action
         } else {
             return null;
         }
-
-
     }
 
     /**
@@ -117,4 +115,36 @@ class Load extends Action
 
         return $result;
     }
+
+    /**
+     * Загружает список тем при открытие которых идет переадресация на тему c указанным id
+     */
+    public function loadLinks(int $id): array
+    {
+        if ($id < 1) {
+            throw new InvalidArgumentException('Expected a positive topic id');
+        }
+
+        $vars = [
+            ':id' => $id,
+        ];
+        $query = 'SELECT *
+            FROM ::topics
+            WHERE moved_to=?i:id
+            ORDER BY id';
+
+        $stmt = $this->c->DB->query($query, $vars);
+
+        $result = [];
+
+        while ($row = $stmt->fetch()) {
+            $topic = $this->manager->create($row);
+
+            if ($topic->parent instanceof Forum) {
+                $result[] = $topic;
+            }
+        }
+
+        return $result;
+    }
 }

+ 25 - 0
app/Models/Topic/Topics.php

@@ -37,6 +37,7 @@ class Topics extends Manager
             return $this->get($id);
         } else {
             $topic = $this->Load->load($id);
+
             $this->set($id, $topic);
 
             return $topic;
@@ -57,6 +58,7 @@ class Topics extends Manager
             } else {
                 $result[$id] = null;
                 $data[]      = $id;
+
                 $this->set($id, null);
             }
         }
@@ -68,6 +70,28 @@ class Topics extends Manager
         foreach ($this->Load->loadByIds($data, $full) as $topic) {
             if ($topic instanceof Topic) {
                 $result[$topic->id] = $topic;
+
+                $this->set($topic->id, $topic);
+            }
+        }
+
+        return $result;
+    }
+
+    /**
+     * Получает список тем при открытие которых идет переадресация на текущую тему
+     */
+    public function loadLinks(int|Topic $arg): array
+    {
+        $id     = \is_int($arg) ? $arg : (int) $arg->id;
+        $result = [];
+
+        foreach ($this->Load->loadLinks($id) as $topic) {
+            if ($this->isset($topic->id)) {
+                $result[$topic->id] = $this->get($topic->id);
+            } else {
+                $result[$topic->id] = $topic;
+
                 $this->set($topic->id, $topic);
             }
         }
@@ -89,6 +113,7 @@ class Topics extends Manager
     public function insert(Topic $topic): int
     {
         $id = $this->Save->insert($topic);
+
         $this->set($id, $topic);
 
         return $id;

+ 24 - 0
app/lang/en/misc.po

@@ -270,3 +270,27 @@ msgstr "First, please <a href=\"%s\">confirm</a> your email address."
 
 msgid "Poll cannot be attached"
 msgstr "Topic with a poll cannot be attached to another topic."
+
+msgid "Link btn"
+msgstr "Redirect"
+
+msgid "Only one topic is permissible"
+msgstr "Only one topic should be selected to manage links to it."
+
+msgid "Control of redirects title"
+msgstr "Control of redirects topics"
+
+msgid "Need full topic for this operation"
+msgstr "You need to choose a full-fledged topic for this operation."
+
+msgid "Forum label"
+msgstr "Forum"
+
+msgid "Redir label"
+msgstr "Set redirect topic"
+
+msgid "Change btn"
+msgstr "Change"
+
+msgid "Redirects changed redirect"
+msgstr "Redirects topics changed."

+ 24 - 0
app/lang/ru/misc.po

@@ -290,3 +290,27 @@ msgstr "Вначале, пожалуйста, <a href=\"%s\">подтверди
 
 msgid "Poll cannot be attached"
 msgstr "Тему с опросом нельзя прикрепить к другой теме."
+
+msgid "Link btn"
+msgstr "Перенапр."
+
+msgid "Only one topic is permissible"
+msgstr "Только одна тема должна быть выбрана для управления ссылками на неё."
+
+msgid "Control of redirects title"
+msgstr "Управление темами-ссылками"
+
+msgid "Need full topic for this operation"
+msgstr "Нужно выбрать полноценную тему для этой операции."
+
+msgid "Forum label"
+msgstr "Раздел"
+
+msgid "Redir label"
+msgstr "Установить тему для переадресации"
+
+msgid "Change btn"
+msgstr "Изменить"
+
+msgid "Redirects changed redirect"
+msgstr "Ссылающиеся темы изменены."

+ 15 - 1
public/style/ForkBB/style.css

@@ -2285,6 +2285,15 @@ body,
   inset-inline-start: 0;
 }
 
+#fork-modform .f-fs-modforum.f-fs-current {
+  font-weight: bolder;
+  font-style: italic;
+}
+
+#fork-modform .f-finform + .f-finform {
+  margin-top: 0.3125rem;
+}
+
 /*********/
 /* Поиск */
 /*********/
@@ -2980,7 +2989,8 @@ body,
   #fork-mod .f-btn[name="merge"] > span,
   #fork-mod .f-btn[name="split"] > span,
   #fork-mod .f-btn[name="stick"] > span,
-  #fork-mod .f-btn[name="unstick"] > span {
+  #fork-mod .f-btn[name="unstick"] > span,
+  #fork-mod .f-btn[name="link"] > span {
     display: none;
   }
 
@@ -3015,6 +3025,10 @@ body,
   #fork-mod .f-btn[name="unstick"]::before {
     content: "\f358";
   }
+
+  #fork-mod .f-btn[name="link"]::before {
+    content: "\f0c1";
+  }
 }
 
 @media screen and (max-width: 49.9999rem) {