Browse Source

Create Sitemap page

Visman 1 year ago
parent
commit
a0eb7a0e27
2 changed files with 196 additions and 161 deletions
  1. 0 161
      app/Models/Pages/Misc.php
  2. 196 0
      app/Models/Pages/Sitemap.php

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

@@ -136,165 +136,4 @@ class Misc extends Page
 
         return $this->c->Message->message(['Confirm your email address', $link], true, 100);
     }
-
-    public array $sitemap = [];
-
-    /**
-     * Вывод sitemap
-     */
-    public function sitemap(array $args): Page
-    {
-        $gGroup = $this->c->groups->get(FORK_GROUP_GUEST);
-        $forums = $this->c->ForumManager->init($gGroup);
-        $id     = null === $args['id'] ? null : (int) $args['id'];
-        $max    = 50000;
-
-        $this->nameTpl = 'sitemap';
-
-        if (1 !== $gGroup->g_read_board) {
-
-        } elseif (null === $id) {
-            // sitemap.xml
-            $available = false;
-
-            foreach ($forums->loadTree(0)->descendants as $forum) {
-                if ($forum->last_post > 0) {
-                    $this->sitemap[$this->c->Router->link('Sitemap', ['id' => $forum->id])] = $forum->last_post;
-
-                    $available = true;
-                }
-            }
-
-            if (1 === $gGroup->g_view_users) {
-                $this->sitemap[$this->c->Router->link('Sitemap', ['id' => 0])] = null;
-            }
-
-            if (true === $available) {
-                $this->sitemap[$this->c->Router->link('Sitemap', ['id' => 2147483647])] = null;
-            }
-
-            $this->nameTpl = 'sitemap_index';
-
-        } elseif (2147483647 === $id) {
-            // sitemap2147483647.xml
-            $this->sitemap[$this->c->Router->link('Index')] = null;
-
-            --$max;
-
-            if (
-                1 === $this->c->config->b_rules
-                && 1 === $this->c->config->b_regs_allow
-            ) {
-                $this->sitemap[$this->c->Router->link('Rules')] = null;
-
-                --$max;
-            }
-
-            $dtd = $this->c->config->i_disp_topics_default;
-
-            foreach ($forums->loadTree(0)->descendants as $forum) {
-                if ($forum->last_post > 0) {
-                    $pages = (int) \ceil(($forum->num_topics ?: 1) / $dtd);
-                    $page  = 1;
-
-                    for (; $max > 0 && $page <= $pages; --$max, ++$page) {
-                        $this->sitemap[$this->c->Router->link(
-                            'Forum',
-                            [
-                                'id'   => $forum->id,
-                                'name' => $forum->friendly,
-                                'page' => $page,
-                            ]
-                        )] = null;
-                    }
-                }
-            }
-
-        } elseif (0 === $id) {
-            // sitemap0.xml
-            if (1 !== $gGroup->g_view_users) {
-                return $this->c->Message->message('Bad request');
-            }
-
-            $vars = [
-                ':max' => $max,
-            ];
-            $query = 'SELECT u.id, u.username
-                FROM ::users AS u
-                WHERE u.last_post!=0
-                ORDER BY u.id DESC
-                LIMIT ?i:max';
-
-            $stmt = $this->c->DB->query($query, $vars);
-
-            while ($cur = $stmt->fetch()) {
-                $name = $this->c->Func->friendly($cur['username']);
-
-                $this->sitemap[$this->c->Router->link(
-                    'User',
-                    [
-                        'id'   => $cur['id'],
-                        'name' => $name,
-                    ]
-                )] = null;
-            }
-
-        } else {
-            // sitemapN.xml
-            $forum = $forums->get($id);
-
-            if (! $forum instanceof Forum) {
-                return $this->c->Message->message('Bad request');
-            }
-
-            $dpd = $this->c->config->i_disp_posts_default;
-
-            $vars = [
-                ':fid' => $forum->id,
-            ];
-            $query = 'SELECT t.id, t.subject, t.last_post, t.num_replies
-                FROM ::topics AS t
-                WHERE t.moved_to=0 AND t.forum_id=?i:fid
-                ORDER BY t.last_post DESC';
-
-            $stmt = $this->c->DB->query($query, $vars);
-
-            while ($cur = $stmt->fetch()) {
-                $name = $this->c->Func->friendly($cur['subject']);
-                $page = (int) \ceil(($cur['num_replies'] + 1) / $dpd);
-                $last = $cur['last_post'];
-
-                for (; $max > 0 && $page > 0; --$max, --$page) {
-                    $this->sitemap[$this->c->Router->link(
-                        'Topic',
-                        [
-                            'id'   => $cur['id'],
-                            'name' => $name,
-                            'page' => $page,
-                        ]
-                    )] = $last;
-
-                    $last = null;
-                }
-            }
-        }
-
-        $this->onlinePos    = 'sitemap';
-        $this->onlineDetail = null;
-
-        $this->header('Content-type', 'application/xml; charset=utf-8');
-
-        $d = \number_format(\microtime(true) - $this->c->START, 3);
-
-        $this->c->Log->debug("{$this->nameTpl} : {$id} : time = {$d}", [
-            'user'    => $this->user->fLog(),
-            'headers' => true,
-        ]);
-
-        if (empty($this->sitemap)) {
-            return $this->c->Message->message('Bad request');
-        } else {
-            return $this;
-        }
-    }
 }

+ 196 - 0
app/Models/Pages/Sitemap.php

@@ -0,0 +1,196 @@
+<?php
+/**
+ * This file is part of the ForkBB <https://github.com/forkbb>.
+ *
+ * @copyright (c) Visman <mio.visman@yandex.ru, https://github.com/MioVisman>
+ * @license   The MIT License (MIT)
+ */
+
+declare(strict_types=1);
+
+namespace ForkBB\Models\Pages;
+
+use ForkBB\Models\Page;
+use ForkBB\Models\Forum\Forum;
+use ForkBB\Models\Forum\Forums;
+use ForkBB\Models\Group\Group;
+
+class Sitemap extends Page
+{
+
+    public array $sitemap = [];
+
+    /**
+     * Вывод sitemap
+     */
+    public function view(array $args): Page
+    {
+        $this->nameTpl      = 'sitemap';
+        $this->onlinePos    = 'sitemap';
+        $this->onlineDetail = null;
+
+        $gGroup = $this->c->groups->get(FORK_GROUP_GUEST);
+        $forums = $this->c->ForumManager->init($gGroup);
+        $max    = 50000;
+
+        if (1 === $gGroup->g_read_board) {
+            $result = match ($args['id']) {
+                null    => $this->sitemap($forums, $gGroup, $max),
+                '0'     => $this->sitemap0($forums, $gGroup, $max),
+                '00'    => $this->sitemap00($forums, $gGroup, $max),
+                default => $this->sitemapN($forums, $gGroup, $max, $args['id']),
+            };
+        }
+
+        $d = \number_format(\microtime(true) - $this->c->START, 3);
+
+        $this->c->Log->debug("{$this->nameTpl} : {$args['id']} : time = {$d}", [
+            'user'    => $this->user->fLog(),
+            'headers' => true,
+        ]);
+
+        if (empty($this->sitemap)) {
+            return $this->c->Message->message('Bad request');
+        } else {
+            $this->header('Content-type', 'application/xml; charset=utf-8');
+
+            return $this;
+        }
+    }
+
+    protected function sitemap(Forums $forums, Group $gGroup, int $max): bool
+    {
+        foreach ($forums->loadTree(0)->descendants as $forum) {
+            if ($forum->last_post > 0) {
+                $this->sitemap[$this->c->Router->link('Sitemap', ['id' => $forum->id])] = $forum->last_post;
+            }
+        }
+
+        if (1 === $gGroup->g_view_users) {
+            $this->sitemap[$this->c->Router->link('Sitemap', ['id' => '0'])] = null;
+        }
+
+        $this->sitemap[$this->c->Router->link('Sitemap', ['id' => '00'])] = null;
+
+        $this->nameTpl = 'sitemap_index';
+
+        return true;
+    }
+
+    protected function sitemap00(Forums $forums, Group $gGroup, int $max): bool
+    {
+        $this->sitemap[$this->c->Router->link('Index')] = null;
+
+        --$max;
+
+        if (
+            1 === $this->c->config->b_rules
+            && 1 === $this->c->config->b_regs_allow
+        ) {
+            $this->sitemap[$this->c->Router->link('Rules')] = null;
+
+            --$max;
+        }
+
+        $dtd = $this->c->config->i_disp_topics_default;
+
+        foreach ($forums->loadTree(0)->descendants as $forum) {
+            if ($forum->last_post > 0) {
+                $pages = (int) \ceil(($forum->num_topics ?: 1) / $dtd);
+                $page  = 1;
+
+                for (; $max > 0 && $page <= $pages; --$max, ++$page) {
+                    $this->sitemap[$this->c->Router->link(
+                        'Forum',
+                        [
+                            'id'   => $forum->id,
+                            'name' => $forum->friendly,
+                            'page' => $page,
+                        ]
+                    )] = null;
+                }
+            }
+        }
+
+        return true;
+    }
+
+    protected function sitemap0(Forums $forums, Group $gGroup, int $max): bool
+    {
+        if (1 !== $gGroup->g_view_users) {
+            return false;
+        }
+
+        $vars = [
+            ':max' => $max,
+        ];
+        $query = 'SELECT u.id, u.username
+            FROM ::users AS u
+            WHERE u.last_post!=0
+            ORDER BY u.id DESC
+            LIMIT ?i:max';
+
+        $stmt = $this->c->DB->query($query, $vars);
+
+        while ($cur = $stmt->fetch()) {
+            $name = $this->c->Func->friendly($cur['username']);
+
+            $this->sitemap[$this->c->Router->link(
+                'User',
+                [
+                    'id'   => $cur['id'],
+                    'name' => $name,
+                ]
+            )] = null;
+        }
+
+        return true;
+    }
+
+    protected function sitemapN(Forums $forums, Group $gGroup, int $max, string $raw): bool
+    {
+        if (! \preg_match('%^[1-9]\d*$%', $raw)) {
+            return false;
+        }
+
+        $id    = (int) $raw;
+        $forum = $forums->get($id);
+
+        if (! $forum instanceof Forum) {
+            return false;
+        }
+
+        $dpd = $this->c->config->i_disp_posts_default;
+
+        $vars = [
+            ':fid' => $forum->id,
+        ];
+        $query = 'SELECT t.id, t.subject, t.last_post, t.num_replies
+            FROM ::topics AS t
+            WHERE t.moved_to=0 AND t.forum_id=?i:fid
+            ORDER BY t.last_post DESC';
+
+        $stmt = $this->c->DB->query($query, $vars);
+
+        while ($cur = $stmt->fetch()) {
+            $name = $this->c->Func->friendly($cur['subject']);
+            $page = (int) \ceil(($cur['num_replies'] + 1) / $dpd);
+            $last = $cur['last_post'];
+
+            for (; $max > 0 && $page > 0; --$max, --$page) {
+                $this->sitemap[$this->c->Router->link(
+                    'Topic',
+                    [
+                        'id'   => $cur['id'],
+                        'name' => $name,
+                        'page' => $page,
+                    ]
+                )] = $last;
+
+                $last = null;
+            }
+        }
+
+        return false;
+    }
+}