Forums.php 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541
  1. <?php
  2. namespace ForkBB\Models\Pages\Admin;
  3. use ForkBB\Core\Container;
  4. use ForkBB\Models\Page;
  5. use ForkBB\Models\Forum\Model as Forum;
  6. use ForkBB\Models\Pages\Admin;
  7. class Forums extends Admin
  8. {
  9. /**
  10. * Составление списка категорий/разделов для выбора родителя
  11. *
  12. * @param Forum $forum
  13. */
  14. protected function calcList(Forum $forum): void
  15. {
  16. $cid = null;
  17. $categories = $this->c->categories->getList();
  18. $options = [
  19. ['', \ForkBB\__('Not selected')],
  20. ];
  21. $idxs = [];
  22. $root = $this->c->forums->get(0);
  23. if ($root instanceof Forum) {
  24. foreach ($this->c->forums->depthList($root, 0) as $f) {
  25. if ($cid !== $f->cat_id) {
  26. $cid = $f->cat_id;
  27. $options[] = [-$cid, \ForkBB\__('Category prefix') . $f->cat_name];
  28. $idxs[] = -$cid;
  29. unset($categories[$cid]);
  30. }
  31. $indent = \str_repeat(\ForkBB\__('Forum indent'), $f->depth);
  32. if ($f->id === $forum->id || isset($forum->descendants[$f->id]) || $f->redirect_url) {
  33. $options[] = [$f->id, $indent . \ForkBB\__('Forum prefix') . $f->forum_name, true];
  34. } else {
  35. $options[] = [$f->id, $indent . \ForkBB\__('Forum prefix') . $f->forum_name];
  36. $idxs[] = $f->id;
  37. }
  38. }
  39. }
  40. foreach ($categories as $key => $row) {
  41. $idxs[] = -$key;
  42. $options[] = [-$key, \ForkBB\__('Category prefix') . $row['cat_name']];
  43. }
  44. $this->listOfIndexes = $idxs;
  45. $this->listForOptions = $options;
  46. }
  47. /**
  48. * Вычисление позиции для (нового) раздела
  49. *
  50. * @param Forum $forum
  51. *
  52. * @return int
  53. */
  54. protected function forumPos(Forum $forum): int
  55. {
  56. if (\is_int($forum->disp_position)) {
  57. return $forum->disp_position;
  58. }
  59. $root = $this->c->forums->get(0);
  60. if (! $root instanceof Forum) {
  61. return 0;
  62. }
  63. $max = 0;
  64. foreach ($root->descendants as $f) {
  65. if ($f->disp_position > $max) {
  66. $max = $f->disp_position;
  67. }
  68. }
  69. return $max + 1;
  70. }
  71. /**
  72. * Просмотр, редактирвоание и добавление разделов
  73. *
  74. * @param array $args
  75. * @param string $method
  76. *
  77. * @return Page
  78. */
  79. public function view(array $args, string $method): Page
  80. {
  81. $this->c->Lang->load('admin_forums');
  82. if ('POST' === $method) {
  83. $v = $this->c->Validator->reset()
  84. ->addRules([
  85. 'token' => 'token:AdminForums',
  86. 'form.*.disp_position' => 'required|integer|min:0|max:9999999999',
  87. ])->addAliases([
  88. ])->addArguments([
  89. ])->addMessages([
  90. ]);
  91. if ($v->validation($_POST)) {
  92. foreach ($v->form as $key => $row) {
  93. $forum = $this->c->forums->get((int) $key);
  94. $forum->disp_position = $row['disp_position'];
  95. $this->c->forums->update($forum);
  96. }
  97. $this->c->Cache->delete('forums_mark'); //????
  98. return $this->c->Redirect->page('AdminForums')->message('Forums updated redirect');
  99. }
  100. $this->fIswev = $v->getErrors();
  101. }
  102. $this->nameTpl = 'admin/form';
  103. $this->aIndex = 'forums';
  104. $this->form = $this->formView();
  105. $this->classForm = ['editforums', 'inline'];
  106. $this->titleForm = \ForkBB\__('Forums');
  107. return $this;
  108. }
  109. /**
  110. * Подготавливает массив данных для формы
  111. *
  112. * @return array
  113. */
  114. protected function formView(): array
  115. {
  116. $form = [
  117. 'action' => $this->c->Router->link('AdminForums'),
  118. 'hidden' => [
  119. 'token' => $this->c->Csrf->create('AdminForums'),
  120. ],
  121. 'sets' => [],
  122. 'btns' => [
  123. 'new' => [
  124. 'type' => 'btn',
  125. 'value' => \ForkBB\__('New forum'),
  126. 'link' => $this->c->Router->link('AdminForumsNew'),
  127. 'accesskey' => 'n',
  128. ],
  129. 'update' => [
  130. 'type' => 'submit',
  131. 'value' => \ForkBB\__('Update positions'),
  132. 'accesskey' => 's',
  133. ],
  134. ],
  135. ];
  136. $root = $this->c->forums->get(0);
  137. if ($root instanceof Forum) {
  138. $list = $this->c->forums->depthList($root, -1);
  139. $cid = null;
  140. foreach ($list as $forum) {
  141. if ($cid !== $forum->cat_id) {
  142. $form['sets']["category{$forum->cat_id}-info"] = [
  143. 'info' => [
  144. 'info1' => [
  145. 'type' => '', //????
  146. 'value' => $forum->cat_name,
  147. ],
  148. ],
  149. ];
  150. $cid = $forum->cat_id;
  151. }
  152. $fields = [];
  153. $fields["name-btn{$forum->id}"] = [
  154. 'class' => ['name', 'forum', 'depth' . $forum->depth],
  155. 'type' => 'btn',
  156. 'value' => $forum->forum_name,
  157. 'caption' => \ForkBB\__('Forum label'),
  158. 'link' => $this->c->Router->link('AdminForumsEdit', ['id' => $forum->id]),
  159. ];
  160. $fields["form[{$forum->id}][disp_position]"] = [
  161. 'class' => ['position', 'forum'],
  162. 'type' => 'number',
  163. 'min' => 0,
  164. 'max' => 9999999999,
  165. 'value' => $forum->disp_position,
  166. 'caption' => \ForkBB\__('Position label'),
  167. ];
  168. $disabled = (bool) $forum->subforums;
  169. $fields["delete-btn{$forum->id}"] = [
  170. 'class' => ['delete', 'forum'],
  171. 'type' => 'btn',
  172. 'value' => '❌',
  173. 'caption' => \ForkBB\__('Delete'),
  174. 'link' => $disabled ? '#' : $this->c->Router->link('AdminForumsDelete', ['id' => $forum->id]),
  175. 'disabled' => $disabled,
  176. ];
  177. $form['sets']["forum{$forum->id}"] = [
  178. 'class' => 'forum',
  179. 'legend' => $forum->cat_name . ' / ' . $forum->forum_name,
  180. 'fields' => $fields,
  181. ];
  182. }
  183. }
  184. return $form;
  185. }
  186. /**
  187. * Удаление раздела
  188. *
  189. * @param array $args
  190. * @param string $method
  191. *
  192. * @return Page
  193. */
  194. public function delete(array $args, string $method): Page
  195. {
  196. $forum = $this->c->forums->get((int) $args['id']);
  197. if (! $forum instanceof Forum || $forum->subforums) {
  198. return $this->c->Message->message('Bad request');
  199. }
  200. $this->c->Lang->load('admin_forums');
  201. if ('POST' === $method) {
  202. $v = $this->c->Validator->reset()
  203. ->addRules([
  204. 'token' => 'token:AdminForumsDelete',
  205. 'confirm' => 'integer', // ????
  206. 'delete' => 'string',
  207. ])->addAliases([
  208. ])->addArguments([
  209. 'token' => $args,
  210. ]);
  211. if (! $v->validation($_POST) || $v->confirm !== 1) {
  212. return $this->c->Redirect->page('AdminForums')->message('No confirm redirect');
  213. }
  214. $this->c->forums->delete($forum);
  215. $this->c->Cache->delete('forums_mark'); //????
  216. return $this->c->Redirect->page('AdminForums')->message('Forum deleted redirect');
  217. }
  218. $this->nameTpl = 'admin/form';
  219. $this->aIndex = 'forums';
  220. $this->aCrumbs[] = [$this->c->Router->link('AdminForumsDelete', ['id' => $forum->id]), \ForkBB\__('Delete forum head')];
  221. $this->aCrumbs[] = \ForkBB\__('"%s"', $forum->forum_name);
  222. $this->form = $this->formDelete($args, $forum);
  223. $this->classForm = 'deleteforum';
  224. $this->titleForm = \ForkBB\__('Delete forum head');
  225. return $this;
  226. }
  227. /**
  228. * Подготавливает массив данных для формы
  229. *
  230. * @param array $args
  231. * @param Forum $forum
  232. *
  233. * @return array
  234. */
  235. protected function formDelete(array $args, Forum $forum): array
  236. {
  237. return [
  238. 'action' => $this->c->Router->link('AdminForumsDelete', $args),
  239. 'hidden' => [
  240. 'token' => $this->c->Csrf->create('AdminForumsDelete', $args),
  241. ],
  242. 'sets' => [
  243. 'confirm' => [
  244. 'fields' => [
  245. 'confirm' => [
  246. 'caption' => \ForkBB\__('Confirm delete'),
  247. 'type' => 'checkbox',
  248. 'label' => \ForkBB\__('I want to delete forum %s', $forum->forum_name),
  249. 'value' => '1',
  250. 'checked' => false,
  251. ],
  252. ],
  253. ],
  254. [
  255. 'info' => [
  256. 'info1' => [
  257. 'type' => '', //????
  258. 'value' => \ForkBB\__('Delete forum warn'),
  259. 'html' => true,
  260. ],
  261. ],
  262. ],
  263. ],
  264. 'btns' => [
  265. 'delete' => [
  266. 'type' => 'submit',
  267. 'value' => \ForkBB\__('Delete forum'),
  268. 'accesskey' => 'd',
  269. ],
  270. 'cancel' => [
  271. 'type' => 'btn',
  272. 'value' => \ForkBB\__('Cancel'),
  273. 'link' => $this->c->Router->link('AdminForums'),
  274. ],
  275. ],
  276. ];
  277. }
  278. /**
  279. * Редактирование раздела
  280. * Создание нового раздела
  281. *
  282. * @param array $args
  283. * @param string $method
  284. *
  285. * @return Page
  286. */
  287. public function edit(array $args, string $method): Page
  288. {
  289. $this->c->Lang->load('admin_forums');
  290. if (empty($args['id'])) {
  291. $forum = $this->c->forums->create();
  292. $marker = 'AdminForumsNew';
  293. $this->aCrumbs[] = [$this->c->Router->link($marker), \ForkBB\__('Add forum head')];
  294. $this->titleForm = \ForkBB\__('Add forum head');
  295. $this->classForm = 'createforum';
  296. } else {
  297. $forum = $this->c->forums->loadTree((int) $args['id']); //?????
  298. $marker = 'AdminForumsEdit';
  299. $this->aCrumbs[] = [$this->c->Router->link($marker, $args), \ForkBB\__('Edit forum head')];
  300. $this->aCrumbs[] = \ForkBB\__('"%s"', $forum->forum_name);
  301. $this->titleForm = \ForkBB\__('Edit forum head');
  302. $this->classForm = 'editforum';
  303. }
  304. if (! $forum instanceof Forum) {
  305. return $this->c->Message->message('Bad request');
  306. }
  307. $this->calcList($forum);
  308. if ('POST' === $method) {
  309. $v = $this->c->Validator->reset()
  310. ->addRules([
  311. 'token' => 'token:' . $marker,
  312. 'forum_name' => 'required|string:trim|max:80',
  313. 'forum_desc' => 'string:trim|max:65000 bytes',
  314. 'parent' => 'required|integer|in:' . implode(',', $this->listOfIndexes),
  315. 'sort_by' => 'required|integer|in:0,1,2',
  316. 'redirect_url' => 'string:trim|max:255', //????
  317. 'perms.*.read_forum' => 'checkbox',
  318. 'perms.*.post_replies' => 'checkbox',
  319. 'perms.*.post_topics' => 'checkbox',
  320. 'submit' => 'string',
  321. 'reset' => empty($forum->id) ? 'absent' : 'string',
  322. ])->addAliases([
  323. ])->addArguments([
  324. 'token' => $args,
  325. ]);
  326. $valid = $v->validation($_POST);
  327. $forum->forum_name = $v->forum_name;
  328. $forum->forum_desc = $v->forum_desc;
  329. $forum->sort_by = $v->sort_by;
  330. $forum->redirect_url = $v->redirect_url;
  331. if ($v->parent > 0) {
  332. $forum->parent_forum_id = $v->parent;
  333. $forum->cat_id = $this->c->forums->get($v->parent)->cat_id;
  334. } elseif ($v->parent < 0) {
  335. $forum->cat_id = -$v->parent;
  336. $forum->parent_forum_id = 0;
  337. }
  338. if ($valid) {
  339. if ($v->reset) {
  340. $message = 'Perms reverted redirect';
  341. $this->c->groups->Perm->reset($forum);
  342. } else {
  343. if (empty($args['id'])) {
  344. $message = 'Forum added redirect';
  345. $forum->disp_position = $this->forumPos($forum);
  346. $forum->moderators = '';
  347. $this->c->forums->insert($forum);
  348. } else {
  349. $message = 'Forum updated redirect';
  350. $this->c->forums->update($forum);
  351. }
  352. $this->c->groups->Perm->update($forum, $v->perms);
  353. }
  354. $this->c->Cache->delete('forums_mark');
  355. return $this->c->Redirect->page('AdminForumsEdit', ['id' => $forum->id])->message($message);
  356. }
  357. $this->fIswev = $v->getErrors();
  358. }
  359. $this->nameTpl = 'admin/form';
  360. $this->aIndex = 'forums';
  361. $this->form = $this->formEdit($args, $forum, $marker);
  362. return $this;
  363. }
  364. /**
  365. * Подготавливает массив данных для формы
  366. *
  367. * @param array $args
  368. * @param Forum $forum
  369. * @param string $marker
  370. *
  371. * @return array
  372. */
  373. protected function formEdit(array $args, Forum $forum, string $marker): array
  374. {
  375. $form = [
  376. 'action' => $this->c->Router->link($marker, $args),
  377. 'hidden' => [
  378. 'token' => $this->c->Csrf->create($marker, $args),
  379. ],
  380. 'sets' => [],
  381. 'btns' => [],
  382. ];
  383. if ($forum->id > 0) {
  384. $form['btns']['reset'] = [
  385. 'type' => 'submit',
  386. 'value' => \ForkBB\__('Revert to default'),
  387. 'accesskey' => 'r',
  388. ];
  389. }
  390. $form['btns']['submit'] = [
  391. 'type' => 'submit',
  392. 'value' => empty($forum->id) ? \ForkBB\__('Add') : \ForkBB\__('Update'),
  393. 'accesskey' => 's',
  394. ];
  395. $form['sets']['forum'] = [
  396. 'fields' => [
  397. 'forum_name' => [
  398. 'type' => 'text',
  399. 'maxlength' => 80,
  400. 'value' => $forum->forum_name,
  401. 'caption' => \ForkBB\__('Forum name label'),
  402. 'required' => true,
  403. ],
  404. 'forum_desc' => [
  405. 'type' => 'textarea',
  406. 'value' => $forum->forum_desc,
  407. 'caption' => \ForkBB\__('Forum description label'),
  408. ],
  409. 'parent' => [
  410. 'type' => 'select',
  411. 'options' => $this->listForOptions,
  412. 'value' => $forum->parent_forum_id ? $forum->parent_forum_id : -$forum->cat_id,
  413. 'caption' => \ForkBB\__('Parent label'),
  414. 'info' => \ForkBB\__('Parent help'),
  415. 'required' => true,
  416. ],
  417. 'sort_by' => [
  418. 'type' => 'select',
  419. 'options' => [
  420. 0 => \ForkBB\__('Last post option'),
  421. 1 => \ForkBB\__('Topic start option'),
  422. 2 => \ForkBB\__('Subject option'),
  423. ],
  424. 'value' => $forum->sort_by,
  425. 'caption' => \ForkBB\__('Sort by label'),
  426. ],
  427. 'redirect_url' => [
  428. 'type' => 'text',
  429. 'maxlength' => 255,
  430. 'value' => $forum->redirect_url,
  431. 'caption' => \ForkBB\__('Redirect label'),
  432. 'info' => \ForkBB\__('Redirect help'),
  433. 'disabled' => $forum->num_topics || $forum->subforums ? true : null,
  434. ],
  435. ],
  436. ];
  437. $form['sets']['forum-info'] = [
  438. 'info' => [
  439. 'info1' => [
  440. 'type' => '', //????
  441. 'value' => \ForkBB\__('Group permissions info', $this->c->Router->link('AdminGroups'), \ForkBB\__('User groups')),
  442. 'html' => true,
  443. ],
  444. ],
  445. ];
  446. $aOn = ['cando', 'on'];
  447. $aOff = ['cando', 'off'];
  448. foreach ($this->c->groups->Perm->get($forum) as $id => $group) {
  449. $fields = [];
  450. $fields["perms[{$id}][read_forum]"] = [
  451. 'class' => $group->def_read_forum ? $aOn : $aOff,
  452. 'type' => 'checkbox',
  453. 'value' => '1',
  454. 'caption' => \ForkBB\__('Read forum label'),
  455. 'label' => \ForkBB\__('<span></span>'),
  456. 'checked' => $group->set_read_forum,
  457. 'disabled' => $group->dis_read_forum,
  458. ];
  459. $fields["perms[{$id}][post_replies]"] = [
  460. 'class' => $group->def_post_replies ? $aOn : $aOff,
  461. 'type' => 'checkbox',
  462. 'value' => '1',
  463. 'caption' => \ForkBB\__('Post replies label'),
  464. 'label' => \ForkBB\__('<span></span>'),
  465. 'checked' => $group->set_post_replies,
  466. 'disabled' => $group->dis_post_replies,
  467. ];
  468. $fields["perms[{$id}][post_topics]"] = [
  469. 'class' => $group->def_post_topics ? $aOn : $aOff,
  470. 'type' => 'checkbox',
  471. 'value' => '1',
  472. 'caption' => \ForkBB\__('Post topics label'),
  473. 'label' => \ForkBB\__('<span></span>'),
  474. 'checked' => $group->set_post_topics,
  475. 'disabled' => $group->dis_post_topics,
  476. ];
  477. $form['sets']["perms{$id}"] = [
  478. 'class' => 'permission',
  479. 'legend' => \ForkBB\e($group->g_title),
  480. 'fields' => $fields,
  481. ];
  482. }
  483. return $form;
  484. }
  485. }