Add loadByIds() to Topic\Manager

This commit is contained in:
Visman 2020-06-06 15:08:10 +07:00
parent 177f08674c
commit 448ac9e070
3 changed files with 109 additions and 50 deletions

View file

@ -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;
}
}

View file

@ -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;
}
/**
* Обновляет тему в БД
*

View file

@ -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;
}
}
}