Просмотр файла app/Controllers/Forum/ForumController.php

Размер файла: 9.42Kb
  1. <?php
  2.  
  3. declare(strict_types=1);
  4.  
  5. namespace App\Controllers\Forum;
  6.  
  7. use App\Classes\Validator;
  8. use App\Controllers\BaseController;
  9. use App\Models\Flood;
  10. use App\Models\Forum;
  11. use App\Models\Post;
  12. use App\Models\Topic;
  13. use App\Models\Vote;
  14. use App\Models\VoteAnswer;
  15. use Illuminate\Database\Capsule\Manager as DB;
  16. use Illuminate\Database\Eloquent\Builder;
  17. use Illuminate\Database\Query\JoinClause;
  18. use Illuminate\Http\Request;
  19.  
  20. class ForumController extends BaseController
  21. {
  22. /**
  23. * Главная страница
  24. *
  25. * @return string
  26. */
  27. public function index(): string
  28. {
  29. $forums = Forum::query()
  30. ->where('parent_id', 0)
  31. ->with('lastTopic.lastPost.user')
  32. ->with('children')
  33. ->orderBy('sort')
  34. ->get();
  35.  
  36. if ($forums->isEmpty()) {
  37. abort('default', __('forums.empty_forums'));
  38. }
  39.  
  40. return view('forums/index', compact('forums'));
  41. }
  42.  
  43. /**
  44. * Страница списка тем
  45. *
  46. * @param int $id
  47. *
  48. * @return string
  49. */
  50. public function forum(int $id): string
  51. {
  52. /** @var Forum $forum */
  53. $forum = Forum::query()->with('parent', 'children.lastTopic.lastPost.user')->find($id);
  54.  
  55. if (! $forum) {
  56. abort(404, __('forums.forum_not_exist'));
  57. }
  58.  
  59. $user = getUser();
  60.  
  61. $topics = Topic::query()
  62. ->where('forum_id', $forum->id)
  63. ->when($user, static function (Builder $query) use ($user) {
  64. $query->select('topics.*', 'bookmarks.count_posts as bookmark_posts')
  65. ->leftJoin('bookmarks', static function (JoinClause $join) use ($user) {
  66. $join->on('topics.id', 'bookmarks.topic_id')
  67. ->where('bookmarks.user_id', $user->id);
  68. });
  69. })
  70. ->orderByDesc('locked')
  71. ->orderByDesc('updated_at')
  72. ->with('lastPost.user')
  73. ->paginate(setting('forumtem'));
  74.  
  75. return view('forums/forum', compact('forum', 'topics'));
  76. }
  77.  
  78. /**
  79. * Создание новой темы
  80. *
  81. * @param Request $request
  82. * @param Validator $validator
  83. * @param Flood $flood
  84. *
  85. * @return string
  86. */
  87. public function create(Request $request, Validator $validator, Flood $flood): string
  88. {
  89. $fid = int($request->input('fid'));
  90.  
  91. $forums = Forum::query()
  92. ->where('parent_id', 0)
  93. ->with('children')
  94. ->orderBy('sort')
  95. ->get();
  96.  
  97. if ($forums->isEmpty()) {
  98. abort('default', __('forums.empty_forums'));
  99. }
  100.  
  101. if (! $user = getUser()) {
  102. abort(403);
  103. }
  104.  
  105. if ($request->isMethod('post')) {
  106. $title = $request->input('title');
  107. $msg = $request->input('msg');
  108. $vote = empty($request->input('vote')) ? 0 : 1;
  109. $question = $request->input('question');
  110. $answers = (array) $request->input('answers');
  111.  
  112. /** @var Forum $forum */
  113. $forum = Forum::query()->find($fid);
  114.  
  115. $validator->equal($request->input('token'), $_SESSION['token'], __('validator.token'))
  116. ->notEmpty($forum, ['fid' => 'Форума для новой темы не существует!'])
  117. ->false($flood->isFlood(), ['msg' => __('validator.flood', ['sec' => $flood->getPeriod()])])
  118. ->length($title, 3, 50, ['title' => __('validator.text')])
  119. ->length($msg, 5, setting('forumtextlength'), ['msg' => __('validator.text')]);
  120.  
  121. if ($forum) {
  122. $validator->empty($forum->closed, ['fid' => __('forums.forum_closed')]);
  123. }
  124.  
  125. if ($vote) {
  126. $validator->length($question, 5, 100, ['question' => __('validator.text')]);
  127. $answers = array_unique(array_diff($answers, ['']));
  128.  
  129. foreach ($answers as $answer) {
  130. if (utfStrlen($answer) > 50) {
  131. $validator->addError(['answers' => __('votes.answer_wrong_length')]);
  132. break;
  133. }
  134. }
  135.  
  136. $validator->between(count($answers), 2, 10, ['answers' => __('votes.answer_not_enough')]);
  137. }
  138.  
  139. /* TODO: Сделать проверку поиска похожей темы */
  140.  
  141. if ($validator->isValid()) {
  142. $title = antimat($title);
  143. $msg = antimat($msg);
  144.  
  145. $user->increment('allforum');
  146. $user->increment('point');
  147. $user->increment('money', 5);
  148.  
  149. /** @var Topic $topic */
  150. $topic = Topic::query()->create([
  151. 'forum_id' => $forum->id,
  152. 'title' => $title,
  153. 'user_id' => getUser('id'),
  154. 'count_posts' => 1,
  155. 'created_at' => SITETIME,
  156. 'updated_at' => SITETIME,
  157. ]);
  158.  
  159. /** @var Post $post */
  160. $post = Post::query()->create([
  161. 'topic_id' => $topic->id,
  162. 'user_id' => getUser('id'),
  163. 'text' => $msg,
  164. 'created_at' => SITETIME,
  165. 'ip' => getIp(),
  166. 'brow' => getBrowser(),
  167. ]);
  168.  
  169. Topic::query()->where('id', $topic->id)->update(['last_post_id' => $post->id]);
  170.  
  171. $forum->update([
  172. 'count_topics' => DB::connection()->raw('count_topics + 1'),
  173. 'count_posts' => DB::connection()->raw('count_posts + 1'),
  174. 'last_topic_id' => $topic->id,
  175. ]);
  176.  
  177. // Обновление родительского форума
  178. if ($forum->parent->id) {
  179. $forum->parent->update([
  180. 'last_topic_id' => $topic->id
  181. ]);
  182. }
  183.  
  184. // Создание голосования
  185. if ($vote) {
  186. /** @var Vote $vote */
  187. $vote = Vote::query()->create([
  188. 'title' => $question,
  189. 'topic_id' => $topic->id,
  190. 'created_at' => SITETIME,
  191. ]);
  192.  
  193. $prepareAnswers = [];
  194. foreach ($answers as $answer) {
  195. $prepareAnswers[] = [
  196. 'vote_id' => $vote->id,
  197. 'answer' => $answer
  198. ];
  199. }
  200.  
  201. VoteAnswer::query()->insert($prepareAnswers);
  202. }
  203.  
  204. clearCache(['statForums', 'recentTopics']);
  205. $flood->saveState();
  206.  
  207. setFlash('success', __('forums.topic_success_created'));
  208. redirect('/topics/'.$topic->id);
  209. } else {
  210. setInput($request->all());
  211. setFlash('danger', $validator->getErrors());
  212. }
  213. }
  214.  
  215. return view('forums/topic_create', compact('forums', 'fid'));
  216. }
  217.  
  218. /**
  219. * RSS всех топиков
  220. *
  221. * @return string
  222. */
  223. public function rss(): string
  224. {
  225. $topics = Topic::query()
  226. ->where('closed', 0)
  227. ->with('lastPost.user')
  228. ->orderByDesc('updated_at')
  229. ->limit(15)
  230. ->get();
  231.  
  232. if ($topics->isEmpty()) {
  233. abort('default', __('forums.topics_not_created'));
  234. }
  235.  
  236. return view('forums/rss', compact('topics'));
  237. }
  238.  
  239. /**
  240. * RSS постов
  241. *
  242. * @param int $id
  243. *
  244. * @return string
  245. */
  246. public function rssPosts(int $id): string
  247. {
  248. /** @var Topic $topic */
  249. $topic = Topic::query()->find($id);
  250.  
  251. if (! $topic) {
  252. abort(404, __('forums.topic_not_exist'));
  253. }
  254.  
  255. $posts = Post::query()
  256. ->where('topic_id', $topic->id)
  257. ->orderByDesc('created_at')
  258. ->with('user')
  259. ->limit(15)
  260. ->get();
  261.  
  262. return view('forums/rss_posts', compact('topic', 'posts'));
  263. }
  264.  
  265. /**
  266. * Последние темы
  267. *
  268. * @return string
  269. */
  270. public function topTopics(): string
  271. {
  272. $topics = Topic::query()
  273. ->orderByDesc('count_posts')
  274. ->orderByDesc('updated_at')
  275. ->with('forum', 'user', 'lastPost.user')
  276. ->limit(100)
  277. ->get()
  278. ->all();
  279.  
  280. $topics = paginate($topics, setting('forumtem'));
  281.  
  282. return view('forums/top', compact('topics'));
  283. }
  284.  
  285. /**
  286. * Последние сообщения
  287. *
  288. * @param Request $request
  289. *
  290. * @return string
  291. */
  292. public function topPosts(Request $request): string
  293. {
  294. $period = int($request->input('period'));
  295.  
  296. $posts = Post::query()
  297. ->when($period, static function (Builder $query) use ($period) {
  298. return $query->where('created_at', '>', strtotime('-' . $period . ' day', SITETIME));
  299. })
  300. ->orderByDesc('rating')
  301. ->orderByDesc('created_at')
  302. ->with('topic', 'user')
  303. ->limit(100)
  304. ->get()
  305. ->all();
  306.  
  307. $posts = paginate($posts, setting('forumpost'), ['period' => $period]);
  308.  
  309. return view('forums/top_posts', compact('posts', 'period'));
  310. }
  311. }