PostValidatorTrait.php 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  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\Pages;
  10. use ForkBB\Core\Validator;
  11. use ForkBB\Models\Model;
  12. use function \ForkBB\__;
  13. trait PostValidatorTrait
  14. {
  15. /**
  16. * Дополнительная проверка subject
  17. */
  18. public function vCheckSubject(Validator $v, string $subject, $attr, bool $executive): string
  19. {
  20. // после цензуры заголовок темы путой
  21. if ('' == $this->c->censorship->censor($subject)) {
  22. $v->addError('No subject after censoring');
  23. // заголовок темы только заглавными буквами
  24. } elseif (
  25. ! $executive
  26. && 1 !== $this->c->config->b_subject_all_caps
  27. && \preg_match('%\p{Lu}%u', $subject)
  28. && ! \preg_match('%\p{Ll}%u', $subject)
  29. ) {
  30. $v->addError('All caps subject');
  31. }
  32. return $subject;
  33. }
  34. /**
  35. * Дополнительная проверка message
  36. */
  37. public function vCheckMessage(Validator $v, string $message, $attr, bool $executive): string
  38. {
  39. $prepare = null;
  40. // после цензуры текст сообщения пустой
  41. if ('' == $this->c->censorship->censor($message)) {
  42. $v->addError('No message after censoring');
  43. // проверка парсером
  44. } else {
  45. $prepare = true;
  46. $message = $this->c->Parser->prepare($message); //????
  47. foreach ($this->c->Parser->getErrors([], [], true) as $error) {
  48. $prepare = false;
  49. $v->addError($error);
  50. }
  51. }
  52. // текст сообщения только заглавными буквами
  53. if (
  54. true === $prepare
  55. && ! $executive
  56. && 1 !== $this->c->config->b_message_all_caps
  57. ) {
  58. $text = $this->c->Parser->getText();
  59. if (
  60. \preg_match('%\p{Lu}%u', $text)
  61. && ! \preg_match('%\p{Ll}%u', $text)
  62. ) {
  63. $v->addError('All caps message');
  64. }
  65. }
  66. return $message;
  67. }
  68. /**
  69. * Проверка времени ограничения флуда
  70. */
  71. public function vCheckTimeout(Validator $v, $submit, $attr, ?int $last)
  72. {
  73. if ($v->noValue($submit)) {
  74. return null;
  75. }
  76. $last = $last > 0 ? $last : $this->user->last_post;
  77. $time = \time() - $last;
  78. if ($time < $this->user->g_post_flood) {
  79. $v->addError(['Flood message', $this->user->g_post_flood - $time], 'e');
  80. }
  81. return $submit;
  82. }
  83. /**
  84. * Подготовка валидатора к проверке данных из формы создания темы/сообщения
  85. */
  86. protected function messageValidator(?Model $model, string $marker, array $args, bool $edit, bool $first): Validator
  87. {
  88. $this->c->Lang->load('validator');
  89. $notPM = $this->fIndex !== self::FI_PM;
  90. if ($this->user->isGuest) {
  91. $ruleEmail = 1 === $this->c->config->b_force_guest_email ? 'required' : 'exist';
  92. $ruleEmail .= '|string:trim,empty|email:noban';
  93. $ruleUsername = 'required|string:trim|username';
  94. } else {
  95. $ruleEmail = 'absent';
  96. $ruleUsername = 'absent';
  97. }
  98. if (
  99. $notPM
  100. && (
  101. $this->user->isAdmin
  102. || $this->user->isModerator($model)
  103. )
  104. ) {
  105. if ($first) {
  106. $ruleStickTopic = 'checkbox';
  107. $ruleStickFP = 'checkbox';
  108. } else {
  109. $ruleStickTopic = 'absent';
  110. $ruleStickFP = 'absent';
  111. }
  112. if (
  113. ! $first
  114. && ! $edit
  115. ) {
  116. $ruleMergePost = 'checkbox';
  117. } else {
  118. $ruleMergePost = 'absent';
  119. }
  120. if (
  121. $edit
  122. && ! $model->user->isGuest
  123. && ! $model->user->isAdmin
  124. ) {
  125. $ruleEditPost = 'checkbox';
  126. } else {
  127. $ruleEditPost = 'absent';
  128. }
  129. $executive = true;
  130. } else {
  131. $ruleStickTopic = 'absent';
  132. $ruleStickFP = 'absent';
  133. $ruleMergePost = 'absent:1';
  134. $ruleEditPost = 'absent';
  135. $executive = false;
  136. }
  137. if ($first) {
  138. $ruleSubject = 'required|string:trim,spaces|min:1|max:70|' . ($executive ? '' : 'noURL|') . 'check_subject';
  139. } else {
  140. $ruleSubject = 'absent';
  141. }
  142. if (
  143. ! $edit
  144. && $notPM
  145. && 1 === $this->c->config->b_topic_subscriptions
  146. && $this->user->email_confirmed
  147. ) {
  148. $ruleSubscribe = 'checkbox';
  149. } else {
  150. $ruleSubscribe = 'absent';
  151. }
  152. if (1 === $this->c->config->b_smilies) {
  153. $ruleHideSmilies = 'checkbox';
  154. } else {
  155. $ruleHideSmilies = 'absent';
  156. }
  157. $ruleMessage = 'required|string:trim|max:' . $this->c->MAX_POST_SIZE . ($executive ? '' : '|noURL') . '|check_message';
  158. $v = $this->c->Validator->reset()
  159. ->addValidators([
  160. 'check_subject' => [$this, 'vCheckSubject'],
  161. 'check_message' => [$this, 'vCheckMessage'],
  162. 'check_timeout' => [$this, 'vCheckTimeout'],
  163. ])->addRules([
  164. 'token' => 'token:' . $marker,
  165. 'email' => $ruleEmail,
  166. 'username' => $ruleUsername,
  167. 'subject' => $ruleSubject,
  168. 'stick_topic' => $ruleStickTopic,
  169. 'stick_fp' => $ruleStickFP,
  170. 'merge_post' => $ruleMergePost,
  171. 'hide_smilies' => $ruleHideSmilies,
  172. 'edit_post' => $ruleEditPost,
  173. 'subscribe' => $ruleSubscribe,
  174. 'preview' => 'string',
  175. 'submit' => 'string|check_timeout',
  176. 'message' => $ruleMessage,
  177. ])->addAliases([
  178. 'email' => 'Email',
  179. 'username' => 'Username',
  180. 'subject' => 'Subject',
  181. ])->addArguments([
  182. 'token' => $args,
  183. 'subject.check_subject' => $executive,
  184. 'message.check_message' => $executive,
  185. 'email.email' => $this->user,
  186. ])->addMessages([
  187. 'username.login' => 'Login format',
  188. ]);
  189. if (
  190. $first
  191. && $notPM
  192. && $this->user->usePoll
  193. ) {
  194. $v->addValidators([
  195. 'check_poll' => [$this, 'vCheckPoll'],
  196. ])->addRules([
  197. 'poll_enable' => 'checkbox|check_poll',
  198. 'poll.duration' => 'integer|min:0|max:366',
  199. 'poll.hide_result' => 'checkbox',
  200. 'poll.question.*' => 'string:trim|max:240',
  201. 'poll.type.*' => 'integer|min:1|max:' . $this->c->config->i_poll_max_fields,
  202. 'poll.answer.*.*' => 'string:trim|max:240',
  203. ]);
  204. }
  205. return $v;
  206. }
  207. /**
  208. * Дополнительная проверка опроса
  209. */
  210. public function vCheckPoll(Validator $v, /* string|false */ $enable, $attr) /* : string|false */
  211. {
  212. if (
  213. false !== $enable
  214. && empty($v->getErrors())
  215. ) {
  216. $poll = $this->c->polls->create([
  217. 'question' => $v->poll['question'],
  218. 'answer' => $v->poll['answer'],
  219. 'type' => $v->poll['type'],
  220. ]);
  221. $result = $this->c->polls->revision($poll);
  222. if (true !== $result) {
  223. $v->addError($result);
  224. }
  225. }
  226. return $enable;
  227. }
  228. }