2017-12-11
This commit is contained in:
parent
372521b5ff
commit
87b8c632ed
16 changed files with 565 additions and 442 deletions
|
@ -50,6 +50,10 @@ class Parser extends Parserus
|
|||
|
||||
$this->setSmilies($smilies)->setSmTpl($info['smTpl'], $info['smTplTag'], $info['smTplBl']);
|
||||
}
|
||||
|
||||
$this->setAttr('baseUrl', $this->c->BASE_URL);
|
||||
$this->setAttr('showImg', $this->c->user->show_img != '0');
|
||||
$this->setAttr('showImgSign', $this->c->user->show_img_sig != '0');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -150,7 +150,7 @@ class Validator
|
|||
$rules = [];
|
||||
// псевдоним содержится в списке правил
|
||||
if (is_array($raw)) {
|
||||
list($raw, $this->aliases[$field]) = $raw;
|
||||
list($raw, $this->aliases[$field]) = $raw; //????
|
||||
}
|
||||
// перебор правил для текущего поля
|
||||
foreach (explode('|', $raw) as $rule) {
|
||||
|
|
|
@ -11,6 +11,8 @@ use ForkBB\Models\Page;
|
|||
class Post extends Page
|
||||
{
|
||||
use CrumbTrait;
|
||||
use PostFormTrait;
|
||||
use PostValidatorTrait;
|
||||
|
||||
/**
|
||||
* Подготовка данных для шаблона создания темы
|
||||
|
@ -123,8 +125,7 @@ class Post extends Page
|
|||
*/
|
||||
public function newReplyPost(array $args)
|
||||
{
|
||||
$tid = (int) $args['id'];
|
||||
$topic = $this->c->ModelTopic->load($tid);
|
||||
$topic = $this->c->ModelTopic->load((int) $args['id']);
|
||||
|
||||
if (empty($topic) || $topic->moved_to || ! $topic->canReply) {
|
||||
return $this->c->Message->message('Bad request');
|
||||
|
@ -264,333 +265,4 @@ class Post extends Page
|
|||
->page('ViewPost', ['id' => $merge ? $lastPost->id : $post->id])
|
||||
->message(__('Post redirect'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Дополнительная проверка email
|
||||
*
|
||||
* @param Validator $v
|
||||
* @param string $email
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function vCheckEmail(Validator $v, $email)
|
||||
{
|
||||
$user = $this->c->ModelUser;
|
||||
$user->email = $email;
|
||||
|
||||
// email забанен
|
||||
if ($this->c->bans->isBanned($user) > 0) {
|
||||
$v->addError('Banned email');
|
||||
}
|
||||
return $email;
|
||||
}
|
||||
|
||||
/**
|
||||
* Дополнительная проверка username
|
||||
*
|
||||
* @param Validator $v
|
||||
* @param string $username
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function vCheckUsername(Validator $v, $username)
|
||||
{
|
||||
$user = $this->c->ModelUser;
|
||||
$user->username = $username;
|
||||
|
||||
// username = Гость
|
||||
if (preg_match('%^(guest|' . preg_quote(__('Guest'), '%') . ')$%iu', $username)) {
|
||||
$v->addError('Username guest');
|
||||
// цензура
|
||||
} elseif ($user->cens()->username !== $username) {
|
||||
$v->addError('Username censor');
|
||||
// username забанен
|
||||
} elseif ($this->c->bans->isBanned($user) > 0) {
|
||||
$v->addError('Banned username');
|
||||
}
|
||||
return $username;
|
||||
}
|
||||
|
||||
/**
|
||||
* Дополнительная проверка subject
|
||||
*
|
||||
* @param Validator $v
|
||||
* @param string $subject
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function vCheckSubject(Validator $v, $subject, $attr, $executive)
|
||||
{
|
||||
// после цензуры заголовок темы путой
|
||||
if ($this->c->censorship->censor($subject) == '') {
|
||||
$v->addError('No subject after censoring');
|
||||
// заголовок темы только заглавными буквами
|
||||
} elseif (! $executive
|
||||
&& $this->c->config->p_subject_all_caps == '0'
|
||||
&& preg_match('%\p{Lu}%u', $subject)
|
||||
&& ! preg_match('%\p{Ll}%u', $subject)
|
||||
) {
|
||||
$v->addError('All caps subject');
|
||||
}
|
||||
return $subject;
|
||||
}
|
||||
|
||||
/**
|
||||
* Дополнительная проверка message
|
||||
*
|
||||
* @param Validator $v
|
||||
* @param string $message
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function vCheckMessage(Validator $v, $message, $attr, $executive)
|
||||
{
|
||||
// после цензуры текст сообщения пустой
|
||||
if ($this->c->censorship->censor($message) == '') {
|
||||
$v->addError('No message after censoring');
|
||||
// текст сообщения только заглавными буквами
|
||||
} elseif (! $executive
|
||||
&& $this->c->config->p_message_all_caps == '0'
|
||||
&& preg_match('%\p{Lu}%u', $message)
|
||||
&& ! preg_match('%\p{Ll}%u', $message)
|
||||
) {
|
||||
$v->addError('All caps message');
|
||||
// проверка парсером
|
||||
} else {
|
||||
$message = $this->c->Parser->prepare($message); //????
|
||||
|
||||
foreach($this->c->Parser->getErrors() as $error) {
|
||||
$v->addError($error);
|
||||
}
|
||||
}
|
||||
|
||||
return $message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверка времени ограничения флуда
|
||||
*
|
||||
* @param Validator $v
|
||||
* @param null|string $submit
|
||||
*
|
||||
* @return null|string
|
||||
*/
|
||||
public function vCheckTimeout(Validator $v, $submit)
|
||||
{
|
||||
if (null === $submit) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$user = $this->c->user;
|
||||
$time = time() - (int) $user->last_post;
|
||||
|
||||
if ($time < $user->g_post_flood) {
|
||||
$v->addError(__('Flood start', $user->g_post_flood, $user->g_post_flood - $time), 'e');
|
||||
}
|
||||
|
||||
return $submit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Подготовка валидатора к проверке данных из формы создания темы/сообщения
|
||||
*
|
||||
* @param Model $model
|
||||
* @param string $marker
|
||||
* @param array $args
|
||||
* @param bool $editSubject
|
||||
*
|
||||
* @return Validator
|
||||
*/
|
||||
protected function messageValidator(Model $model, $marker, array $args, $editSubject = false)
|
||||
{
|
||||
if ($this->c->user->isGuest) {
|
||||
$ruleEmail = ($this->c->config->p_force_guest_email == '1' ? 'required|' : '') . 'string:trim,lower|email|check_email';
|
||||
$ruleUsername = 'required|string:trim,spaces|min:2|max:25|login|check_username';
|
||||
} else {
|
||||
$ruleEmail = 'absent';
|
||||
$ruleUsername = 'absent';
|
||||
}
|
||||
|
||||
if ($editSubject) {
|
||||
$ruleSubject = 'required|string:trim,spaces|min:1|max:70|check_subject';
|
||||
} else {
|
||||
$ruleSubject = 'absent';
|
||||
}
|
||||
|
||||
if ($this->c->user->isAdmin || $this->c->user->isModerator($model)) {
|
||||
if ($editSubject) {
|
||||
$ruleStickTopic = 'checkbox';
|
||||
$ruleStickFP = 'checkbox';
|
||||
$ruleMergePost = 'absent';
|
||||
} else {
|
||||
$ruleStickTopic = 'absent';
|
||||
$ruleStickFP = 'absent';
|
||||
$ruleMergePost = 'checkbox';
|
||||
}
|
||||
$executive = true;
|
||||
} else {
|
||||
$ruleStickTopic = 'absent';
|
||||
$ruleStickFP = 'absent';
|
||||
$ruleMergePost = 'absent:1';
|
||||
$executive = false;
|
||||
}
|
||||
|
||||
if ($this->c->config->o_smilies == '1') {
|
||||
$ruleHideSmilies = 'checkbox';
|
||||
} else {
|
||||
$ruleHideSmilies = 'absent';
|
||||
}
|
||||
|
||||
$v = $this->c->Validator->addValidators([
|
||||
'check_email' => [$this, 'vCheckEmail'],
|
||||
'check_username' => [$this, 'vCheckUsername'],
|
||||
'check_subject' => [$this, 'vCheckSubject'],
|
||||
'check_message' => [$this, 'vCheckMessage'],
|
||||
'check_timeout' => [$this, 'vCheckTimeout'],
|
||||
])->setRules([
|
||||
'token' => 'token:' . $marker,
|
||||
'email' => [$ruleEmail, __('Email')],
|
||||
'username' => [$ruleUsername, __('Username')],
|
||||
'subject' => [$ruleSubject, __('Subject')],
|
||||
'stick_topic' => $ruleStickTopic,
|
||||
'stick_fp' => $ruleStickFP,
|
||||
'merge_post' => $ruleMergePost,
|
||||
'hide_smilies' => $ruleHideSmilies,
|
||||
'preview' => 'string', //????
|
||||
'submit' => 'string|check_timeout', //????
|
||||
'message' => 'required|string:trim|max:' . $this->c->MAX_POST_SIZE . '|check_message',
|
||||
])->setArguments([
|
||||
'token' => $args,
|
||||
'subject.check_subject' => $executive,
|
||||
'message.check_message' => $executive,
|
||||
])->setMessages([
|
||||
'username.login' => __('Login format'),
|
||||
]);
|
||||
|
||||
return $v;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает данные для построения формы создания темы/сообщения
|
||||
*
|
||||
* @param Model $model
|
||||
* @param string $marker
|
||||
* @param array $args
|
||||
* @param bool $editSubject
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function messageForm(Model $model, $marker, array $args, $editSubject = false)
|
||||
{
|
||||
$vars = isset($args['_vars']) ? $args['_vars'] : null;
|
||||
unset($args['_vars']);
|
||||
|
||||
$autofocus = true;
|
||||
$form = [
|
||||
'action' => $this->c->Router->link($marker, $args),
|
||||
'hidden' => [
|
||||
'token' => $this->c->Csrf->create($marker, $args),
|
||||
],
|
||||
'sets' => [],
|
||||
'btns' => [
|
||||
'submit' => ['submit', __('Submit'), 's'],
|
||||
'preview' => ['submit', __('Preview'), 'p'],
|
||||
],
|
||||
];
|
||||
|
||||
$fieldset = [];
|
||||
if ($this->c->user->isGuest) {
|
||||
$fieldset['username'] = [
|
||||
'dl' => 't1',
|
||||
'type' => 'text',
|
||||
'maxlength' => 25,
|
||||
'title' => __('Username'),
|
||||
'required' => true,
|
||||
'pattern' => '^.{2,25}$',
|
||||
'value' => isset($vars['username']) ? $vars['username'] : null,
|
||||
'autofocus' => $autofocus,
|
||||
];
|
||||
$fieldset['email'] = [
|
||||
'dl' => 't2',
|
||||
'type' => 'text',
|
||||
'maxlength' => 80,
|
||||
'title' => __('Email'),
|
||||
'required' => $this->c->config->p_force_guest_email == '1',
|
||||
'pattern' => '.+@.+',
|
||||
'value' => isset($vars['email']) ? $vars['email'] : null,
|
||||
];
|
||||
$autofocus = null;
|
||||
}
|
||||
|
||||
if ($editSubject) {
|
||||
$fieldset['subject'] = [
|
||||
'type' => 'text',
|
||||
'maxlength' => 70,
|
||||
'title' => __('Subject'),
|
||||
'required' => true,
|
||||
'value' => isset($vars['subject']) ? $vars['subject'] : null,
|
||||
'autofocus' => $autofocus,
|
||||
];
|
||||
$autofocus = null;
|
||||
}
|
||||
|
||||
$fieldset['message'] = [
|
||||
'type' => 'textarea',
|
||||
'title' => __('Message'),
|
||||
'required' => true,
|
||||
'value' => isset($vars['message']) ? $vars['message'] : null,
|
||||
'bb' => [
|
||||
['link', __('BBCode'), __($this->c->config->p_message_bbcode == '1' ? 'on' : 'off')],
|
||||
['link', __('url tag'), __($this->c->config->p_message_bbcode == '1' && $this->c->user->g_post_links == '1' ? 'on' : 'off')],
|
||||
['link', __('img tag'), __($this->c->config->p_message_bbcode == '1' && $this->c->config->p_message_img_tag == '1' ? 'on' : 'off')],
|
||||
['link', __('Smilies'), __($this->c->config->o_smilies == '1' ? 'on' : 'off')],
|
||||
],
|
||||
'autofocus' => $autofocus,
|
||||
];
|
||||
$form['sets'][] = [
|
||||
'fields' => $fieldset,
|
||||
];
|
||||
$autofocus = null;
|
||||
|
||||
$fieldset = [];
|
||||
if ($this->c->user->isAdmin || $this->c->user->isModerator($model)) {
|
||||
if ($editSubject) {
|
||||
$fieldset['stick_topic'] = [
|
||||
'type' => 'checkbox',
|
||||
'label' => __('Stick topic'),
|
||||
'value' => '1',
|
||||
'checked' => isset($vars['stick_topic']) ? (bool) $vars['stick_topic'] : false,
|
||||
];
|
||||
$fieldset['stick_fp'] = [
|
||||
'type' => 'checkbox',
|
||||
'label' => __('Stick first post'),
|
||||
'value' => '1',
|
||||
'checked' => isset($vars['stick_fp']) ? (bool) $vars['stick_fp'] : false,
|
||||
];
|
||||
} else {
|
||||
$fieldset['merge_post'] = [
|
||||
'type' => 'checkbox',
|
||||
'label' => __('Merge posts'),
|
||||
'value' => '1',
|
||||
'checked' => isset($vars['merge_post']) ? (bool) $vars['merge_post'] : true,
|
||||
];
|
||||
}
|
||||
}
|
||||
if ($this->c->config->o_smilies == '1') {
|
||||
$fieldset['hide_smilies'] = [
|
||||
'type' => 'checkbox',
|
||||
'label' => __('Hide smilies'),
|
||||
'value' => '1',
|
||||
'checked' => isset($vars['hide_smilies']) ? (bool) $vars['hide_smilies'] : false,
|
||||
];
|
||||
}
|
||||
if ($fieldset) {
|
||||
$form['sets'][] = [
|
||||
'legend' => __('Options'),
|
||||
'fields' => $fieldset,
|
||||
];
|
||||
}
|
||||
|
||||
return $form;
|
||||
}
|
||||
}
|
||||
|
|
142
app/Models/Pages/PostFormTrait.php
Normal file
142
app/Models/Pages/PostFormTrait.php
Normal file
|
@ -0,0 +1,142 @@
|
|||
<?php
|
||||
|
||||
namespace ForkBB\Models\Pages;
|
||||
|
||||
use ForkBB\Models\Model;
|
||||
|
||||
trait PostFormTrait
|
||||
{
|
||||
/**
|
||||
* Возвращает данные для построения формы создания темы/сообщения
|
||||
*
|
||||
* @param Model $model
|
||||
* @param string $marker
|
||||
* @param array $args
|
||||
* @param bool $editSubject
|
||||
* @param bool $quickReply
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function messageForm(Model $model, $marker, array $args, $editSubject = false, $quickReply = false)
|
||||
{
|
||||
$vars = isset($args['_vars']) ? $args['_vars'] : null;
|
||||
unset($args['_vars']);
|
||||
|
||||
$autofocus = $quickReply ? null : true;
|
||||
$form = [
|
||||
'action' => $this->c->Router->link($marker, $args),
|
||||
'hidden' => [
|
||||
'token' => $this->c->Csrf->create($marker, $args),
|
||||
],
|
||||
'sets' => [],
|
||||
'btns' => [
|
||||
'submit' => [
|
||||
'type' => 'submit',
|
||||
'value' => __('Submit'),
|
||||
'accesskey' => 's',
|
||||
],
|
||||
'preview' => [
|
||||
'type' => 'submit',
|
||||
'value' => __('Preview'),
|
||||
'accesskey' => 'p',
|
||||
'class' => 'f-minor',
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
$fieldset = [];
|
||||
if ($this->c->user->isGuest) {
|
||||
$fieldset['username'] = [
|
||||
'dl' => 't1',
|
||||
'type' => 'text',
|
||||
'maxlength' => 25,
|
||||
'title' => __('Username'),
|
||||
'required' => true,
|
||||
'pattern' => '^.{2,25}$',
|
||||
'value' => isset($vars['username']) ? $vars['username'] : null,
|
||||
'autofocus' => $autofocus,
|
||||
];
|
||||
$fieldset['email'] = [
|
||||
'dl' => 't2',
|
||||
'type' => 'text',
|
||||
'maxlength' => 80,
|
||||
'title' => __('Email'),
|
||||
'required' => $this->c->config->p_force_guest_email == '1',
|
||||
'pattern' => '.+@.+',
|
||||
'value' => isset($vars['email']) ? $vars['email'] : null,
|
||||
];
|
||||
$autofocus = null;
|
||||
}
|
||||
|
||||
if ($editSubject) {
|
||||
$fieldset['subject'] = [
|
||||
'type' => 'text',
|
||||
'maxlength' => 70,
|
||||
'title' => __('Subject'),
|
||||
'required' => true,
|
||||
'value' => isset($vars['subject']) ? $vars['subject'] : null,
|
||||
'autofocus' => $autofocus,
|
||||
];
|
||||
$autofocus = null;
|
||||
}
|
||||
|
||||
$fieldset['message'] = [
|
||||
'type' => 'textarea',
|
||||
'title' => __('Message'),
|
||||
'required' => true,
|
||||
'value' => isset($vars['message']) ? $vars['message'] : null,
|
||||
'bb' => [
|
||||
['link', __('BBCode'), __($this->c->config->p_message_bbcode == '1' ? 'on' : 'off')],
|
||||
['link', __('url tag'), __($this->c->config->p_message_bbcode == '1' && $this->c->user->g_post_links == '1' ? 'on' : 'off')],
|
||||
['link', __('img tag'), __($this->c->config->p_message_bbcode == '1' && $this->c->config->p_message_img_tag == '1' ? 'on' : 'off')],
|
||||
['link', __('Smilies'), __($this->c->config->o_smilies == '1' ? 'on' : 'off')],
|
||||
],
|
||||
'autofocus' => $autofocus,
|
||||
];
|
||||
$form['sets'][] = [
|
||||
'fields' => $fieldset,
|
||||
];
|
||||
$autofocus = null;
|
||||
|
||||
$fieldset = [];
|
||||
if ($this->c->user->isAdmin || $this->c->user->isModerator($model)) {
|
||||
if ($editSubject) {
|
||||
$fieldset['stick_topic'] = [
|
||||
'type' => 'checkbox',
|
||||
'label' => __('Stick topic'),
|
||||
'value' => '1',
|
||||
'checked' => isset($vars['stick_topic']) ? (bool) $vars['stick_topic'] : false,
|
||||
];
|
||||
$fieldset['stick_fp'] = [
|
||||
'type' => 'checkbox',
|
||||
'label' => __('Stick first post'),
|
||||
'value' => '1',
|
||||
'checked' => isset($vars['stick_fp']) ? (bool) $vars['stick_fp'] : false,
|
||||
];
|
||||
} else {
|
||||
$fieldset['merge_post'] = [
|
||||
'type' => 'checkbox',
|
||||
'label' => __('Merge posts'),
|
||||
'value' => '1',
|
||||
'checked' => isset($vars['merge_post']) ? (bool) $vars['merge_post'] : true,
|
||||
];
|
||||
}
|
||||
}
|
||||
if (! $quickReply && $this->c->config->o_smilies == '1') {
|
||||
$fieldset['hide_smilies'] = [
|
||||
'type' => 'checkbox',
|
||||
'label' => __('Hide smilies'),
|
||||
'value' => '1',
|
||||
'checked' => isset($vars['hide_smilies']) ? (bool) $vars['hide_smilies'] : false,
|
||||
];
|
||||
}
|
||||
if ($fieldset) {
|
||||
$form['sets'][] = [
|
||||
'legend' => __('Options'),
|
||||
'fields' => $fieldset,
|
||||
];
|
||||
}
|
||||
|
||||
return $form;
|
||||
}
|
||||
}
|
219
app/Models/Pages/PostValidatorTrait.php
Normal file
219
app/Models/Pages/PostValidatorTrait.php
Normal file
|
@ -0,0 +1,219 @@
|
|||
<?php
|
||||
|
||||
namespace ForkBB\Models\Pages;
|
||||
|
||||
use ForkBB\Core\Validator;
|
||||
use ForkBB\Models\Model;
|
||||
|
||||
trait PostValidatorTrait
|
||||
{
|
||||
/**
|
||||
* Дополнительная проверка email
|
||||
*
|
||||
* @param Validator $v
|
||||
* @param string $email
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function vCheckEmail(Validator $v, $email)
|
||||
{
|
||||
$user = $this->c->ModelUser;
|
||||
$user->email = $email;
|
||||
|
||||
// email забанен
|
||||
if ($this->c->bans->isBanned($user) > 0) {
|
||||
$v->addError('Banned email');
|
||||
}
|
||||
return $email;
|
||||
}
|
||||
|
||||
/**
|
||||
* Дополнительная проверка username
|
||||
*
|
||||
* @param Validator $v
|
||||
* @param string $username
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function vCheckUsername(Validator $v, $username)
|
||||
{
|
||||
$user = $this->c->ModelUser;
|
||||
$user->username = $username;
|
||||
|
||||
// username = Гость
|
||||
if (preg_match('%^(guest|' . preg_quote(__('Guest'), '%') . ')$%iu', $username)) {
|
||||
$v->addError('Username guest');
|
||||
// цензура
|
||||
} elseif ($user->cens()->username !== $username) {
|
||||
$v->addError('Username censor');
|
||||
// username забанен
|
||||
} elseif ($this->c->bans->isBanned($user) > 0) {
|
||||
$v->addError('Banned username');
|
||||
}
|
||||
return $username;
|
||||
}
|
||||
|
||||
/**
|
||||
* Дополнительная проверка subject
|
||||
*
|
||||
* @param Validator $v
|
||||
* @param string $subject
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function vCheckSubject(Validator $v, $subject, $attr, $executive)
|
||||
{
|
||||
// после цензуры заголовок темы путой
|
||||
if ($this->c->censorship->censor($subject) == '') {
|
||||
$v->addError('No subject after censoring');
|
||||
// заголовок темы только заглавными буквами
|
||||
} elseif (! $executive
|
||||
&& $this->c->config->p_subject_all_caps == '0'
|
||||
&& preg_match('%\p{Lu}%u', $subject)
|
||||
&& ! preg_match('%\p{Ll}%u', $subject)
|
||||
) {
|
||||
$v->addError('All caps subject');
|
||||
} elseif (! $executive
|
||||
&& $this->c->user->g_post_links != '1'
|
||||
&& preg_match('%https?://|www\.%ui', $subject)
|
||||
) {
|
||||
$v->addError('You can not post links in subject');
|
||||
}
|
||||
return $subject;
|
||||
}
|
||||
|
||||
/**
|
||||
* Дополнительная проверка message
|
||||
*
|
||||
* @param Validator $v
|
||||
* @param string $message
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function vCheckMessage(Validator $v, $message, $attr, $executive)
|
||||
{
|
||||
// после цензуры текст сообщения пустой
|
||||
if ($this->c->censorship->censor($message) == '') {
|
||||
$v->addError('No message after censoring');
|
||||
// текст сообщения только заглавными буквами
|
||||
} elseif (! $executive
|
||||
&& $this->c->config->p_message_all_caps == '0'
|
||||
&& preg_match('%\p{Lu}%u', $message)
|
||||
&& ! preg_match('%\p{Ll}%u', $message)
|
||||
) {
|
||||
$v->addError('All caps message');
|
||||
// проверка парсером
|
||||
} else {
|
||||
$message = $this->c->Parser->prepare($message); //????
|
||||
|
||||
foreach($this->c->Parser->getErrors() as $error) {
|
||||
$v->addError($error);
|
||||
}
|
||||
}
|
||||
|
||||
return $message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверка времени ограничения флуда
|
||||
*
|
||||
* @param Validator $v
|
||||
* @param null|string $submit
|
||||
*
|
||||
* @return null|string
|
||||
*/
|
||||
public function vCheckTimeout(Validator $v, $submit)
|
||||
{
|
||||
if (null === $submit) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$user = $this->c->user;
|
||||
$time = time() - (int) $user->last_post;
|
||||
|
||||
if ($time < $user->g_post_flood) {
|
||||
$v->addError(__('Flood start', $user->g_post_flood, $user->g_post_flood - $time), 'e');
|
||||
}
|
||||
|
||||
return $submit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Подготовка валидатора к проверке данных из формы создания темы/сообщения
|
||||
*
|
||||
* @param Model $model
|
||||
* @param string $marker
|
||||
* @param array $args
|
||||
* @param bool $editSubject
|
||||
*
|
||||
* @return Validator
|
||||
*/
|
||||
protected function messageValidator(Model $model, $marker, array $args, $editSubject = false)
|
||||
{
|
||||
if ($this->c->user->isGuest) {
|
||||
$ruleEmail = ($this->c->config->p_force_guest_email == '1' ? 'required|' : '') . 'string:trim,lower|email|check_email';
|
||||
$ruleUsername = 'required|string:trim,spaces|min:2|max:25|login|check_username';
|
||||
} else {
|
||||
$ruleEmail = 'absent';
|
||||
$ruleUsername = 'absent';
|
||||
}
|
||||
|
||||
if ($editSubject) {
|
||||
$ruleSubject = 'required|string:trim,spaces|min:1|max:70|check_subject';
|
||||
} else {
|
||||
$ruleSubject = 'absent';
|
||||
}
|
||||
|
||||
if ($this->c->user->isAdmin || $this->c->user->isModerator($model)) {
|
||||
if ($editSubject) {
|
||||
$ruleStickTopic = 'checkbox';
|
||||
$ruleStickFP = 'checkbox';
|
||||
$ruleMergePost = 'absent';
|
||||
} else {
|
||||
$ruleStickTopic = 'absent';
|
||||
$ruleStickFP = 'absent';
|
||||
$ruleMergePost = 'checkbox';
|
||||
}
|
||||
$executive = true;
|
||||
} else {
|
||||
$ruleStickTopic = 'absent';
|
||||
$ruleStickFP = 'absent';
|
||||
$ruleMergePost = 'absent:1';
|
||||
$executive = false;
|
||||
}
|
||||
|
||||
if ($this->c->config->o_smilies == '1') {
|
||||
$ruleHideSmilies = 'checkbox';
|
||||
} else {
|
||||
$ruleHideSmilies = 'absent';
|
||||
}
|
||||
|
||||
$v = $this->c->Validator->addValidators([
|
||||
'check_email' => [$this, 'vCheckEmail'],
|
||||
'check_username' => [$this, 'vCheckUsername'],
|
||||
'check_subject' => [$this, 'vCheckSubject'],
|
||||
'check_message' => [$this, 'vCheckMessage'],
|
||||
'check_timeout' => [$this, 'vCheckTimeout'],
|
||||
])->setRules([
|
||||
'token' => 'token:' . $marker,
|
||||
'email' => [$ruleEmail, __('Email')],
|
||||
'username' => [$ruleUsername, __('Username')],
|
||||
'subject' => [$ruleSubject, __('Subject')],
|
||||
'stick_topic' => $ruleStickTopic,
|
||||
'stick_fp' => $ruleStickFP,
|
||||
'merge_post' => $ruleMergePost,
|
||||
'hide_smilies' => $ruleHideSmilies,
|
||||
'preview' => 'string',
|
||||
'submit' => 'string|check_timeout',
|
||||
'message' => 'required|string:trim|max:' . $this->c->MAX_POST_SIZE . '|check_message',
|
||||
])->setArguments([
|
||||
'token' => $args,
|
||||
'subject.check_subject' => $executive,
|
||||
'message.check_message' => $executive,
|
||||
])->setMessages([
|
||||
'username.login' => __('Login format'),
|
||||
]);
|
||||
|
||||
return $v;
|
||||
}
|
||||
}
|
|
@ -7,6 +7,7 @@ use ForkBB\Models\Page;
|
|||
class Topic extends Page
|
||||
{
|
||||
use CrumbTrait;
|
||||
use PostFormTrait;
|
||||
|
||||
/**
|
||||
* Переход к первому новому сообщению темы (или в конец)
|
||||
|
@ -135,75 +136,6 @@ class Topic extends Page
|
|||
|
||||
$this->c->Lang->load('topic');
|
||||
|
||||
$user = $this->c->user;
|
||||
|
||||
// данные для формы быстрого ответа
|
||||
$form = null;
|
||||
if ($topic->canReply && $this->c->config->o_quickpost == '1') {
|
||||
$form = [
|
||||
'action' => $this->c->Router->link('NewReply', ['id' => $topic->id]),
|
||||
'hidden' => [
|
||||
'token' => $this->c->Csrf->create('NewReply', ['id' => $topic->id]),
|
||||
],
|
||||
'sets' => [],
|
||||
'btns' => [
|
||||
'submit' => ['submit', __('Submit'), 's'],
|
||||
'preview' => ['submit', __('Preview'), 'p'],
|
||||
],
|
||||
];
|
||||
|
||||
$fieldset = [];
|
||||
if ($user->isGuest) {
|
||||
$fieldset['username'] = [
|
||||
'dl' => 't1',
|
||||
'type' => 'text',
|
||||
'maxlength' => 25,
|
||||
'title' => __('Username'),
|
||||
'required' => true,
|
||||
'pattern' => '^.{2,25}$',
|
||||
];
|
||||
$fieldset['email'] = [
|
||||
'dl' => 't2',
|
||||
'type' => 'text',
|
||||
'maxlength' => 80,
|
||||
'title' => __('Email'),
|
||||
'required' => $this->c->config->p_force_guest_email == '1',
|
||||
'pattern' => '.+@.+',
|
||||
];
|
||||
}
|
||||
|
||||
$fieldset['message'] = [
|
||||
'type' => 'textarea',
|
||||
'title' => __('Message'),
|
||||
'required' => true,
|
||||
'bb' => [
|
||||
['link', __('BBCode'), __($this->c->config->p_message_bbcode == '1' ? 'on' : 'off')],
|
||||
['link', __('url tag'), __($this->c->config->p_message_bbcode == '1' && $user->g_post_links == '1' ? 'on' : 'off')],
|
||||
['link', __('img tag'), __($this->c->config->p_message_bbcode == '1' && $this->c->config->p_message_img_tag == '1' ? 'on' : 'off')],
|
||||
['link', __('Smilies'), __($this->c->config->o_smilies == '1' ? 'on' : 'off')],
|
||||
],
|
||||
];
|
||||
$form['sets'][] = [
|
||||
'fields' => $fieldset,
|
||||
];
|
||||
|
||||
$fieldset = [];
|
||||
if ($user->isAdmin || $user->isModerator($topic)) {
|
||||
$fieldset['merge_post'] = [
|
||||
'type' => 'checkbox',
|
||||
'label' => __('Merge posts'),
|
||||
'value' => '1',
|
||||
'checked' => true,
|
||||
];
|
||||
}
|
||||
if ($fieldset) {
|
||||
$form['sets'][] = [
|
||||
'legend' => __('Options'),
|
||||
'fields' => $fieldset,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
$this->nameTpl = 'topic';
|
||||
$this->onlinePos = 'topic-' . $topic->id;
|
||||
$this->onlineDetail = true;
|
||||
|
@ -213,7 +145,9 @@ class Topic extends Page
|
|||
$this->crumbs = $this->crumbs($topic);
|
||||
$this->online = $this->c->Online->calc($this)->info();
|
||||
$this->stats = null;
|
||||
$this->form = $form;
|
||||
$this->form = $topic->canReply && $this->c->config->o_quickpost == '1'
|
||||
? $this->messageForm($topic, 'NewReply', ['id' => $topic->id], false, true)
|
||||
: null;
|
||||
|
||||
if ($topic->showViews) {
|
||||
$topic->incViews();
|
||||
|
|
|
@ -21,7 +21,7 @@ class Post extends DataModel
|
|||
/**
|
||||
* Автор сообщения
|
||||
*
|
||||
* @return Models\User
|
||||
* @return User
|
||||
*/
|
||||
protected function getuser()
|
||||
{
|
||||
|
@ -103,7 +103,7 @@ class Post extends DataModel
|
|||
}
|
||||
}
|
||||
if ($this->parent->canReply) {
|
||||
$controls['quote'] = [$this->c->Router->link('NewReply', ['id' => $this->parent->id, 'quote' => $this->id]), 'Reply'];
|
||||
$controls['quote'] = [$this->c->Router->link('NewReply', ['id' => $this->parent->id, 'quote' => $this->id]), 'Quote'];
|
||||
}
|
||||
return $controls;
|
||||
}
|
||||
|
|
|
@ -7,6 +7,54 @@ use ForkBB\Models\Topic;
|
|||
|
||||
class Load extends MethodModel
|
||||
{
|
||||
protected $aliases;
|
||||
|
||||
protected function queryFields(array $args)
|
||||
{
|
||||
$result = [];
|
||||
$fields = [];
|
||||
$aliases = [];
|
||||
foreach ($args as $alias => $rawFields) {
|
||||
$aliases[$alias] = [];
|
||||
foreach ($rawFields as $originalName => $replName) {
|
||||
if (null === $replName || false === $replName) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$name = $alias . '.' . $originalName;
|
||||
|
||||
if (true === $replName && isset($fields[$originalName])) {
|
||||
$replName = "alias_{$alias}_{$originalName}";
|
||||
}
|
||||
|
||||
if (true === $replName) {
|
||||
$result[] = $name;
|
||||
$aliases[$alias][$originalName] = true;
|
||||
$fields[$originalName] = $alias;
|
||||
} else {
|
||||
$result[] = $name . ' AS '. $replName;
|
||||
$aliases[$alias][$replName] = $originalName;
|
||||
$fields[$replName] = $alias;
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->aliases = $aliases;
|
||||
|
||||
return implode(', ', $result);
|
||||
}
|
||||
|
||||
protected function setData(array $data, array $args)
|
||||
{
|
||||
foreach ($args as $alias => $model) {
|
||||
$attrs = [];
|
||||
foreach ($this->aliases[$alias] as $key => $repl) {
|
||||
$name = true === $repl ? $key : $repl;
|
||||
$attrs[$name] = $data[$key];
|
||||
}
|
||||
$model->setAttrs($attrs);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Заполняет модель данными из БД
|
||||
*
|
||||
|
@ -17,30 +65,53 @@ class Load extends MethodModel
|
|||
*/
|
||||
public function load($id, Topic $topic = null)
|
||||
{
|
||||
$vars = [
|
||||
':pid' => $id,
|
||||
];
|
||||
$where = 'p.id=?i:pid';
|
||||
// пост + топик
|
||||
if (null === $topic) {
|
||||
|
||||
if ($topic) {
|
||||
$vars[':tid'] = $topic->id;
|
||||
$where .= ' AND p.topic_id=?i:tid';
|
||||
$fileds = $this->queryFields([
|
||||
'p' => array_map(function($val) {return true;}, $this->c->dbMap->posts), // все поля в true
|
||||
't' => array_map(function($val) {return true;}, $this->c->dbMap->topics), // все поля в true
|
||||
]);
|
||||
|
||||
$vars = [
|
||||
':pid' => $id,
|
||||
':fields' => $fields,
|
||||
];
|
||||
|
||||
$sql = 'SELECT ?p:fileds
|
||||
FROM ::posts AS p
|
||||
INNER JOIN ::topics AS t ON t.id=p.topic_id
|
||||
WHERE p.id=?i:pid';
|
||||
// только пост
|
||||
} else {
|
||||
$vars = [
|
||||
':pid' => $id,
|
||||
':tid' => $topic->id,
|
||||
];
|
||||
|
||||
$sql = 'SELECT p.*
|
||||
FROM ::posts AS p
|
||||
WHERE p.id=?i:pid AND p.topic_id=?i:tid';
|
||||
}
|
||||
|
||||
$sql = 'SELECT p.* FROM ::posts AS p WHERE ' . $where;
|
||||
|
||||
$data = $this->c->DB->query($sql, $vars)->fetch();
|
||||
|
||||
|
||||
// пост отсутствует или недоступен
|
||||
if (empty($data)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$this->model->setAttrs($data);
|
||||
if ($topic) {
|
||||
$this->model->__parent = $topic;
|
||||
if (null === $topic) {
|
||||
$topic = $this->c->ModelTopic;
|
||||
$this->setData($data, [
|
||||
'p' => $this->model,
|
||||
't' => $topic,
|
||||
]);
|
||||
} else {
|
||||
$this->model->setAttrs($data);
|
||||
}
|
||||
|
||||
$this->model->__parent = $topic;
|
||||
|
||||
return $this->model;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -63,6 +63,10 @@ class User extends DataModel
|
|||
*/
|
||||
public function isModerator(Model $model)
|
||||
{
|
||||
if ($this->g_moderator != '1') {
|
||||
return false;
|
||||
}
|
||||
|
||||
while (! $model instanceof Forum) {
|
||||
$model = $model->parent;
|
||||
if (! $model instanceof Model) {
|
||||
|
@ -135,11 +139,15 @@ class User extends DataModel
|
|||
/**
|
||||
* Ссылка на профиль пользователя
|
||||
*
|
||||
* @return string
|
||||
* @return null|string
|
||||
*/
|
||||
protected function getlink()
|
||||
{
|
||||
return $this->c->Router->link('User', ['id' => $this->id, 'name' => $this->username]);
|
||||
if ($this->isGuest) {
|
||||
return null;
|
||||
} else {
|
||||
return $this->c->Router->link('User', ['id' => $this->id, 'name' => $this->username]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -30,17 +30,17 @@ return [
|
|||
'no attr' => true,
|
||||
],
|
||||
'handler' => function($body, $attrs) {
|
||||
return '</p><div class="codebox"><pre><code>' . trim($body, "\n\r") . '</code></pre></div><p>';
|
||||
return '</p><pre class="f-bb-code"><code>' . trim($body, "\n\r") . '</code></pre><p>';
|
||||
},
|
||||
],
|
||||
['tag' => 'b',
|
||||
'handler' => function($body) {
|
||||
return '<strong>' . $body . '</strong>';
|
||||
return '<b>' . $body . '</b>';
|
||||
},
|
||||
],
|
||||
['tag' => 'i',
|
||||
'handler' => function($body) {
|
||||
return '<em>' . $body . '</em>';
|
||||
return '<i>' . $body . '</i>';
|
||||
},
|
||||
],
|
||||
['tag' => 'em',
|
||||
|
@ -50,12 +50,12 @@ return [
|
|||
],
|
||||
['tag' => 'u',
|
||||
'handler' => function($body) {
|
||||
return '<span class="bbu">' . $body . '</span>';
|
||||
return '<span class="f-bb-u">' . $body . '</span>';
|
||||
},
|
||||
],
|
||||
['tag' => 's',
|
||||
'handler' => function($body) {
|
||||
return '<span class="bbs">' . $body . '</span>';
|
||||
return '<s>' . $body . '</s>';
|
||||
},
|
||||
],
|
||||
['tag' => 'del',
|
||||
|
@ -71,7 +71,7 @@ return [
|
|||
['tag' => 'h',
|
||||
'type' => 'h',
|
||||
'handler' => function($body) {
|
||||
return '</p><h5>' . $body . '</h5><p>';
|
||||
return '</p><p class="f-bb-header">' . $body . '</p><p>';
|
||||
},
|
||||
],
|
||||
['tag' => 'hr',
|
||||
|
@ -205,11 +205,11 @@ return [
|
|||
|
||||
switch ($attrs['Def'][0]) {
|
||||
case 'a':
|
||||
return '</p><ol class="alpha">' . $body . '</ol><p>';
|
||||
return '</p><ol class="f-bb-l-lat">' . $body . '</ol><p>';
|
||||
case '1':
|
||||
return '</p><ol class="decimal">' . $body . '</ol><p>';
|
||||
return '</p><ol class="f-bb-l-dec">' . $body . '</ol><p>';
|
||||
default:
|
||||
return '</p><ul>' . $body . '</ul><p>';
|
||||
return '</p><ul class="f-bb-l-disc">' . $body . '</ul><p>';
|
||||
}
|
||||
},
|
||||
],
|
||||
|
@ -242,7 +242,7 @@ return [
|
|||
|
||||
$attr = __('After time') . ' ' . implode(' ', $arr);
|
||||
|
||||
return '<span style="color: #808080"><em>' . $attr . ':</em></span><br />';
|
||||
return '</p><p class="f-bb-after">' . $attr . ':</p><p>';
|
||||
},
|
||||
],
|
||||
['tag' => 'quote',
|
||||
|
@ -253,13 +253,8 @@ return [
|
|||
'no attr' => true,
|
||||
],
|
||||
'handler' => function($body, $attrs) {
|
||||
if (isset($attrs['Def'])) {
|
||||
$st = '</p><div class="quotebox"><cite>' . $attrs['Def'] . ' ' . __('wrote') . '</cite><blockquote><div><p>';
|
||||
} else {
|
||||
$st = '</p><div class="quotebox"><blockquote><div><p>';
|
||||
}
|
||||
|
||||
return $st . $body . '</p></div></blockquote></div><p>';
|
||||
$header = isset($attrs['Def']) ? '<div class="f-bb-q-header">' . $attrs['Def'] . ' ' . __('wrote') . '</div>' : '';
|
||||
return "</p><blockquote class=\"f-bb-quote\">{$header}<div class=\"f-bb-q-body\"><p>{$body}</p></div></blockquote><p>";
|
||||
},
|
||||
],
|
||||
['tag' => 'spoiler',
|
||||
|
|
|
@ -12,6 +12,9 @@ msgstr ""
|
|||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: en\n"
|
||||
|
||||
msgid "You can not post links in subject"
|
||||
msgstr "You can not post links in subject."
|
||||
|
||||
msgid "No subject"
|
||||
msgstr "Topics must contain a subject."
|
||||
|
||||
|
|
|
@ -12,6 +12,9 @@ msgstr ""
|
|||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: ru\n"
|
||||
|
||||
msgid "You can not post links in subject"
|
||||
msgstr "Вы не можете публиковать ссылки в заголовке темы."
|
||||
|
||||
msgid "No subject"
|
||||
msgstr "Тема должна содержать заголовок."
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
<dt>{!! __('Environment label') !!}</dt>
|
||||
<dd>
|
||||
{!! __('Environment data OS', PHP_OS) !!}<br>
|
||||
{!! __('Environment data version', phpversion()) !!} - <a href="{!! $p->linkInfo !!}">{!! __('Show info') !!}</a><br>
|
||||
{!! __('Environment data version', PHP_VERSION) !!} - <a href="{!! $p->linkInfo !!}">{!! __('Show info') !!}</a><br>
|
||||
@if ($p->linkAcc)
|
||||
{!! __('Environment data acc') !!} <a href="{!! $p->linkAcc !!}">{{ $p->accelerator }}</a>
|
||||
@else
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
@endforeach
|
||||
<p>
|
||||
@foreach ($form['btns'] as $key => $cur)
|
||||
<input class="f-btn" type="{{ $cur[0] }}" name="{{ $key }}" value="{{ $cur[1] }}" accesskey="{{ $cur[2] }}">
|
||||
<input class="f-btn @if(isset($cur['class'])) {{ $cur['class'] }} @endif" type="{{ $cur['type'] }}" name="{{ $key }}" value="{{ $cur['value'] }}" @if (isset($cur['accesskey'])) accesskey="{{ $cur['accesskey'] }}" @endif>
|
||||
@endforeach
|
||||
</p>
|
||||
</form>
|
||||
|
|
|
@ -64,7 +64,7 @@
|
|||
<div class="f-post-body clearfix">
|
||||
<address class="f-post-left clearfix">
|
||||
<ul class="f-user-info">
|
||||
@if ($post->showUserLink)
|
||||
@if ($post->showUserLink && $post->user->link)
|
||||
<li class="f-username"><a href="{!! $post->user->link !!}">{{ $post->user->username }}</a></li>
|
||||
@else
|
||||
<li class="f-username">{{ $post->user->username }}</li>
|
||||
|
@ -75,7 +75,7 @@
|
|||
</li>
|
||||
@endif
|
||||
<li class="f-usertitle"><span>{{ $post->user->title() }}</span></li>
|
||||
@if ($post->showUserInfo)
|
||||
@if ($post->showUserInfo && $post->user->num_posts)
|
||||
<li class="f-postcount"><span>{!! __('%s post', $post->user->num_posts, $post->user->num()->num_posts) !!}</span></li>
|
||||
@endif
|
||||
</ul>
|
||||
|
|
|
@ -150,6 +150,10 @@ body,
|
|||
user-select: none;
|
||||
}
|
||||
|
||||
.f-btn.f-minor {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.f-wrap a:hover,
|
||||
.f-wrap a:focus,
|
||||
.f-btn:hover,
|
||||
|
@ -1202,11 +1206,13 @@ select {
|
|||
}
|
||||
|
||||
.f-post-right {
|
||||
padding: 0.625rem;
|
||||
padding: 0.625rem 0.625rem 0 0.625rem;
|
||||
}
|
||||
|
||||
.f-post-footer .f-post-right {
|
||||
text-align: right;
|
||||
padding-top: 0;
|
||||
padding-bottom: 0.625rem;
|
||||
}
|
||||
|
||||
.f-post-footer .f-post-left {
|
||||
|
@ -1254,6 +1260,72 @@ li + li .f-btn {
|
|||
.f-post-signature {
|
||||
font-size: 0.875rem;
|
||||
opacity: 0.5;
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
/*********************/
|
||||
.f-bb-u {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.f-bb-header {
|
||||
font-weight: bold;
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
|
||||
.f-bb-after {
|
||||
opacity: 0.5;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.f-bb-quote {
|
||||
border-left: 0.1875rem solid #AA7939;
|
||||
border-top: 0.0625rem solid #AA7939;
|
||||
}
|
||||
|
||||
.f-bb-q-header {
|
||||
padding: 0.625rem;
|
||||
background-color: #D3B58D;
|
||||
}
|
||||
|
||||
.f-bb-q-body {
|
||||
padding: 0.625rem;
|
||||
}
|
||||
|
||||
.f-bb-code {
|
||||
border: 0.0625rem solid #AA7939;
|
||||
padding: 0.625rem;
|
||||
background-color: #D3B58D;
|
||||
overflow: auto;
|
||||
max-height: 45rem;
|
||||
}
|
||||
|
||||
.f-bb-l-disc {
|
||||
list-style-type: disc;
|
||||
list-style-position: outside;
|
||||
padding-left: 1.5rem;
|
||||
}
|
||||
|
||||
.f-bb-l-dec {
|
||||
list-style-type: decimal;
|
||||
list-style-position: outside;
|
||||
padding-left: 1.5rem;
|
||||
}
|
||||
|
||||
.f-bb-l-lat {
|
||||
list-style-type: lower-alpha;
|
||||
list-style-position: outside;
|
||||
padding-left: 1.5rem;
|
||||
}
|
||||
|
||||
.f-post-main p,
|
||||
.f-post-main blockquote,
|
||||
.f-post-main br,
|
||||
.f-post-main pre,
|
||||
.f-post-main ol,
|
||||
.f-post-main ul {
|
||||
margin-bottom: 0.625rem;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 50rem) {
|
||||
|
|
Loading…
Reference in a new issue