2017-12-11

This commit is contained in:
Visman 2017-12-11 23:34:36 +07:00
parent 372521b5ff
commit 87b8c632ed
16 changed files with 565 additions and 442 deletions

View file

@ -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');
}
/**

View file

@ -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) {

View file

@ -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;
}
}

View 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;
}
}

View 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;
}
}

View file

@ -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();

View file

@ -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;
}

View file

@ -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;
}
}

View file

@ -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]);
}
}
/**

View file

@ -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',

View file

@ -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."

View file

@ -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 "Тема должна содержать заголовок."

View file

@ -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

View file

@ -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>

View file

@ -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>

View file

@ -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) {