Browse Source

Add loadByIds() to Topic\Manager

Visman 5 years ago
parent
commit
448ac9e070
3 changed files with 109 additions and 50 deletions
  1. 65 15
      app/Models/Topic/Load.php
  2. 33 1
      app/Models/Topic/Manager.php
  3. 11 34
      app/Models/Topic/View.php

+ 65 - 15
app/Models/Topic/Load.php

@@ -3,16 +3,44 @@
 namespace ForkBB\Models\Topic;
 
 use ForkBB\Models\Action;
+use ForkBB\Models\Forum\Model as Forum;
 use ForkBB\Models\Topic\Model as Topic;
 use InvalidArgumentException;
 
 class Load extends Action
 {
+    /**
+     * Создает текст запрос
+     */
+    protected function getSql(string $where, bool $full): string
+    {
+        if ($this->c->user->isGuest) {
+            $sql = 'SELECT t.*
+                    FROM ::topics AS t
+                    WHERE ' . $where;
+        } elseif ($full) {
+            $sql = 'SELECT t.*, s.user_id AS is_subscribed, mof.mf_mark_all_read, mot.mt_last_visit, mot.mt_last_read
+                    FROM ::topics AS t
+                    LEFT JOIN ::topic_subscriptions AS s ON (t.id=s.topic_id AND s.user_id=?i:uid)
+                    LEFT JOIN ::mark_of_forum AS mof ON (mof.uid=?i:uid AND t.forum_id=mof.fid)
+                    LEFT JOIN ::mark_of_topic AS mot ON (mot.uid=?i:uid AND t.id=mot.tid)
+                    WHERE ' . $where;
+        } else {
+            $sql = 'SELECT t.*, mot.mt_last_visit, mot.mt_last_read
+                    FROM ::topics AS t
+                    LEFT JOIN ::mark_of_topic AS mot ON (mot.uid=?i:uid AND t.id=mot.tid)
+                    WHERE ' . $where;
+        }
+        return $sql;
+    }
+
     /**
      * Загружает тему из БД
      *
      * @param int $id
      *
+     * @throws InvalidArgumentException
+     *
      * @return null|Topic
      */
     public function load(int $id): ?Topic
@@ -25,20 +53,7 @@ class Load extends Action
             ':tid' => $id,
             ':uid' => $this->c->user->id,
         ];
-        if ($this->c->user->isGuest) {
-            $sql = 'SELECT t.*
-                    FROM ::topics AS t
-                    WHERE t.id=?i:tid';
-
-        } else {
-            $sql = 'SELECT t.*, s.user_id AS is_subscribed, mof.mf_mark_all_read, mot.mt_last_visit, mot.mt_last_read
-                    FROM ::topics AS t
-                    LEFT JOIN ::topic_subscriptions AS s ON (t.id=s.topic_id AND s.user_id=?i:uid)
-                    LEFT JOIN ::mark_of_forum AS mof ON (mof.uid=?i:uid AND t.forum_id=mof.fid)
-                    LEFT JOIN ::mark_of_topic AS mot ON (mot.uid=?i:uid AND t.id=mot.tid)
-                    WHERE t.id=?i:tid';
-        }
-
+        $sql  = $this->getSql('t.id=?i:tid', true);
         $data = $this->c->DB->query($sql, $vars)->fetch();
 
         // тема отсутствует или недоступна
@@ -48,7 +63,7 @@ class Load extends Action
 
         $topic = $this->manager->create($data);
 
-        if (! $topic->parent) {
+        if (! $topic->parent instanceof Forum) {
             return null;
         }
 
@@ -56,4 +71,39 @@ class Load extends Action
 
         return $topic;
     }
+
+    /**
+     * Загружает список тем из БД
+     *
+     * @throws InvalidArgumentException
+     */
+    public function loadByIds(array $ids, bool $full): array
+    {
+        foreach ($ids as $id) {
+            if (! \is_int($id) || $id < 1) {
+                throw new InvalidArgumentException('Expected a positive topic id');
+            }
+        }
+
+        $vars = [
+            ':ids' => $ids,
+            ':uid' => $this->c->user->id,
+        ];
+        $sql  = $this->getSql('t.id IN (?ai:ids)', $full);
+        $stmt = $this->c->DB->query($sql, $vars);
+
+        $result = [];
+        while ($row = $stmt->fetch()) {
+            $topic = $this->manager->create($row);
+
+            if ($topic->parent instanceof Forum) {
+                $result[] = $topic;
+
+                if (! empty($row['mf_mark_all_read'])) {
+                    $topic->parent->__mf_mark_all_read = $row['mf_mark_all_read'];
+                }
+            }
+        }
+        return $result;
+    }
 }

+ 33 - 1
app/Models/Topic/Manager.php

@@ -20,7 +20,7 @@ class Manager extends ManagerModel
     }
 
     /**
-     * Загружает тему из БД
+     * Получает тему по id
      *
      * @param int $id
      *
@@ -37,6 +37,38 @@ class Manager extends ManagerModel
         }
     }
 
+    /**
+     * Получает массив тем по ids
+     */
+    public function loadByIds(array $ids, bool $full = true): array
+    {
+        $result = [];
+        $data   = [];
+
+        foreach ($ids as $id) {
+            if ($this->isset($id)) {
+                $result[$id] = $this->get($id);
+            } else {
+                $result[$id] = null;
+                $data[]      = $id;
+                $this->set($id, null);
+            }
+        }
+
+        if (empty($data)) {
+            return $result;
+        }
+
+        foreach ($this->Load->loadByIds($data, $full) as $topic) {
+            if ($topic instanceof Topic) {
+                $result[$topic->id] = $topic;
+                $this->set($topic->id, $topic);
+            }
+        }
+
+        return $result;
+    }
+
     /**
      * Обновляет тему в БД
      *

+ 11 - 34
app/Models/Topic/View.php

@@ -25,9 +25,9 @@ class View extends Action
     public function view($arg): array
     {
         if ($arg instanceof Forum) {
-            $expanded = false;
+            $full = false;
         } elseif ($arg instanceof Search) {
-            $expanded = true;
+            $full = true;
         } else {
             throw new InvalidArgumentException('Expected Forum or Search');
         }
@@ -36,46 +36,23 @@ class View extends Action
             throw new RuntimeException('Model does not contain of topics list for display');
         }
 
-        $vars = [
-            ':uid' => $this->c->user->id,
-            ':ids' => $arg->idsList,
-        ];
+        $result = $this->c->topics->loadByIds($arg->idsList, $full);
 
         if (! $this->c->user->isGuest && '1' == $this->c->config->o_show_dot) {
+            $vars = [
+                ':uid' => $this->c->user->id,
+                ':ids' => $arg->idsList,
+            ];
             $sql = 'SELECT p.topic_id
                     FROM ::posts AS p
                     WHERE p.poster_id=?i:uid AND p.topic_id IN (?ai:ids)
                     GROUP BY p.topic_id';
             $dots = $this->c->DB->query($sql, $vars)->fetchAll(PDO::FETCH_COLUMN);
-            $dots = \array_flip($dots);
-        } else {
-            $dots = [];
-        }
-
-        if ($this->c->user->isGuest) {
-            $sql = 'SELECT t.*
-                    FROM ::topics AS t
-                    WHERE t.id IN(?ai:ids)';
-        } elseif ($expanded) {
-            $sql = 'SELECT t.*, mof.mf_mark_all_read, mot.mt_last_visit, mot.mt_last_read
-                    FROM ::topics AS t
-                    LEFT JOIN ::mark_of_forum AS mof ON (mof.uid=?i:uid AND t.forum_id=mof.fid)
-                    LEFT JOIN ::mark_of_topic AS mot ON (mot.uid=?i:uid AND t.id=mot.tid)
-                    WHERE t.id IN (?ai:ids)';
-        } else {
-            $sql = 'SELECT t.*, mot.mt_last_visit, mot.mt_last_read
-                    FROM ::topics AS t
-                    LEFT JOIN ::mark_of_topic AS mot ON (mot.uid=?i:uid AND t.id=mot.tid)
-                    WHERE t.id IN (?ai:ids)';
-        }
-        $stmt = $this->c->DB->query($sql, $vars);
 
-        $result = \array_flip($arg->idsList);
-        while ($row = $stmt->fetch()) {
-            $row['dot'] = isset($dots[$row['id']]);
-            $result[$row['id']] = $this->manager->create($row);
-            if ($expanded && ! $this->c->user->isGuest) {
-                $result[$row['id']]->parent->__mf_mark_all_read = $row['mf_mark_all_read'];
+            foreach ($dots as $id) {
+                if (isset($result[$id]) && $result[$id] instanceof Topic) {
+                    $result[$id]->__dot = true;
+                }
             }
         }