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

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