Merge.php 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. <?php
  2. /**
  3. * This file is part of the ForkBB <https://github.com/forkbb>.
  4. *
  5. * @copyright (c) Visman <mio.visman@yandex.ru, https://github.com/MioVisman>
  6. * @license The MIT License (MIT)
  7. */
  8. declare(strict_types=1);
  9. namespace ForkBB\Models\Topic;
  10. use ForkBB\Models\Action;
  11. use ForkBB\Models\Topic\Topic;
  12. use PDO;
  13. use InvalidArgumentException;
  14. use RuntimeException;
  15. class Merge extends Action
  16. {
  17. /**
  18. * Объединяет темы
  19. */
  20. public function merge(bool $redirect, Topic ...$topics): void
  21. {
  22. if (\count($topics) < 2) {
  23. throw new InvalidArgumentException('Expected at least 2 topics.');
  24. }
  25. $ids = [];
  26. $users = [];
  27. $forums = [];
  28. $firstTopic = null;
  29. $otherTopics = [];
  30. foreach ($topics as $topic) {
  31. if ($topic->moved_to) {
  32. throw new RuntimeException('Topic links cannot be merged');
  33. }
  34. $users[$topic->poster_id] = $topic->poster_id;
  35. $forums[$topic->forum_id] = $topic->parent;
  36. if (! $firstTopic instanceof Topic) {
  37. $firstTopic = $topic;
  38. } elseif ($topic->first_post_id < $firstTopic->first_post_id) {
  39. $otherTopics[] = $firstTopic;
  40. $ids[] = $firstTopic->id;
  41. $firstTopic = $topic;
  42. } else {
  43. $otherTopics[] = $topic;
  44. $ids[] = $topic->id;
  45. }
  46. }
  47. //???? перенести обработку в посты?
  48. $query = 'UPDATE ::posts
  49. SET message=CONCAT(?s:prefix, message), topic_id=?i:new
  50. WHERE topic_id=?i:id';
  51. foreach ($otherTopics as $topic) {
  52. $vars = [
  53. ':new' => $firstTopic->id,
  54. ':id' => $topic->id,
  55. ':prefix' => "[from]{$topic->subject}[/from]\n",
  56. ];
  57. $this->c->DB->exec($query, $vars);
  58. }
  59. // добавить перенос подписок на первую тему?
  60. if ($redirect) {
  61. foreach ($otherTopics as $topic) {
  62. $topic->moved_to = $firstTopic->id;
  63. $this->c->topics->update($topic->calcStat());
  64. }
  65. $vars = [
  66. 'topics' => $ids,
  67. ];
  68. $query = 'SELECT t.id
  69. FROM ::topics AS t
  70. WHERE t.moved_to IN (?ai:topics)';
  71. $linkTopics = $this->c->DB->query($query, $vars)->fetchAll(PDO::FETCH_COLUMN);
  72. foreach ($linkTopics as $topic) {
  73. $topic->moved_to = $firstTopic->id;
  74. $this->c->topics->update($topic->calcStat());
  75. }
  76. $this->c->topics->update($firstTopic->calcStat());
  77. foreach ($forums as $forum) {
  78. $this->c->forums->update($forum->calcStat());
  79. }
  80. if ($users) {
  81. $this->c->users->updateCountTopics(...$users);
  82. }
  83. } else {
  84. $this->c->topics->update($firstTopic->calcStat());
  85. $this->manager->delete(...$otherTopics);
  86. $this->c->forums->update($firstTopic->parent->calcStat());
  87. }
  88. }
  89. }