LoadTree.php 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. <?php
  2. namespace ForkBB\Models\Forum;
  3. use ForkBB\Models\Action;
  4. use ForkBB\Models\Forum\Model as Forum;
  5. class LoadTree extends Action
  6. {
  7. /**
  8. * Загружает данные в модели для указанного раздела и всех его потомков
  9. *
  10. * @param int $rootId
  11. *
  12. * @return null|Forum
  13. */
  14. public function loadTree(int $rootId): ?Forum
  15. {
  16. $root = $this->manager->get($rootId);
  17. if (null === $root) {
  18. return null;
  19. }
  20. $list = [];
  21. if (! $root->ready) {
  22. $list[$rootId] = $root;
  23. }
  24. foreach ($root->descendants as $id => $descendant) {
  25. if (! $descendant->ready) {
  26. $list[$id] = $descendant;
  27. }
  28. }
  29. $this->loadData($list);
  30. if (! $this->c->user->isGuest) {
  31. $this->checkForNew($root->descendants);
  32. }
  33. return $root;
  34. }
  35. /**
  36. * Загружает данные из БД по списку разделов
  37. *
  38. * @param array $list
  39. */
  40. protected function loadData(array $list): void
  41. {
  42. if (empty($list)) {
  43. return;
  44. }
  45. $vars = [
  46. ':uid' => $this->c->user->id,
  47. ':forums' => \array_keys($list),
  48. ];
  49. if ($this->c->user->isGuest) {
  50. $sql = 'SELECT f.id, f.forum_desc, f.num_topics, f.sort_by, f.num_posts,
  51. f.last_post, f.last_post_id, f.last_poster, f.last_topic
  52. FROM ::forums AS f
  53. WHERE id IN (?ai:forums)';
  54. } elseif ('1' == $this->c->config->o_forum_subscriptions) {
  55. $sql = 'SELECT f.id, f.forum_desc, f.num_topics, f.sort_by, f.num_posts,
  56. f.last_post, f.last_post_id, f.last_poster, f.last_topic,
  57. mof.mf_mark_all_read, s.user_id AS is_subscribed
  58. FROM ::forums AS f
  59. LEFT JOIN ::forum_subscriptions AS s ON (s.user_id=?i:uid AND s.forum_id=f.id)
  60. LEFT JOIN ::mark_of_forum AS mof ON (mof.uid=?i:uid AND mof.fid=f.id)
  61. WHERE f.id IN (?ai:forums)';
  62. } else {
  63. $sql = 'SELECT f.id, f.forum_desc, f.num_topics, f.sort_by, f.num_posts,
  64. f.last_post, f.last_post_id, f.last_poster, f.last_topic,
  65. mof.mf_mark_all_read
  66. FROM ::forums AS f
  67. LEFT JOIN ::mark_of_forum AS mof ON (mof.uid=?i:id AND mof.fid=f.id)
  68. WHERE f.id IN (?ai:forums)';
  69. }
  70. $stmt = $this->c->DB->query($sql, $vars);
  71. while ($cur = $stmt->fetch()) {
  72. $list[$cur['id']]->replAttrs($cur)->__ready = true;
  73. }
  74. }
  75. /**
  76. * Проверяет наличие новых сообщений в разделах по их списку
  77. *
  78. * @param array $list
  79. */
  80. protected function checkForNew(array $list): void
  81. {
  82. if (
  83. empty($list)
  84. || $this->c->user->isGuest
  85. ) {
  86. return;
  87. }
  88. // предварительная проверка разделов
  89. $time = [];
  90. $max = \max((int) $this->c->user->last_visit, (int) $this->c->user->u_mark_all_read);
  91. foreach ($list as $forum) {
  92. $t = \max($max, (int) $forum->mf_mark_all_read);
  93. if ($forum->last_post > $t) {
  94. $time[$forum->id] = $t;
  95. }
  96. }
  97. if (empty($time)) {
  98. return;
  99. }
  100. // проверка по темам
  101. $vars = [
  102. ':uid' => $this->c->user->id,
  103. ':forums' => \array_keys($time),
  104. ':max' => $max,
  105. ];
  106. $sql = 'SELECT t.forum_id, t.last_post
  107. FROM ::topics AS t
  108. LEFT JOIN ::mark_of_topic AS mot ON (mot.uid=?i:uid AND mot.tid=t.id)
  109. WHERE t.forum_id IN(?ai:forums)
  110. AND t.last_post>?i:max
  111. AND t.moved_to=0
  112. AND (mot.mt_last_visit IS NULL OR t.last_post>mot.mt_last_visit)';
  113. $stmt = $this->c->DB->query($sql, $vars);
  114. while ($cur = $stmt->fetch()) {
  115. if ($cur['last_post'] > $time[$cur['forum_id']]) {
  116. $list[$cur['forum_id']]->__newMessages = true; //????
  117. }
  118. }
  119. }
  120. }