<?php
/**
* @property \modelComments $model
*/
class actionCommentsSubmit extends cmsAction {
/**
* @var array Описание правил валидации входных данных
*/
public $request_params = [
'tc' => [
'default' => '',
'rules' => [
['required'],
['sysname'],
['max_length', 32]
]
],
'ts' => [
'default' => '',
'rules' => [
['required'],
['sysname'],
['max_length', 32]
]
],
'ti' => [
'default' => 0,
'rules' => [
['required'],
['digits']
]
],
'parent_id' => [
'default' => 0,
'rules' => [
['digits']
]
],
'tud' => [
'default' => 0,
'rules' => [
['digits']
]
],
'id' => [
'default' => 0,
'rules' => [
['digits']
]
],
'author_email' => [
'default' => '',
'rules' => [
['email'],
['max_length', 100]
]
],
'author_name' => [
'default' => '',
'rules' => [
['localealphanumeric'],
['max_length', 100]
]
],
'action' => [
'default' => '',
'rules' => [
['required'],
['array_key', ['add' => 'add', 'preview' => 'preview', 'update' => 'update']]
]
]
];
public function run() {
if (!$this->request->isAjax()) {
return cmsCore::error404();
}
// Проверяем CSRF токен
if (!cmsForm::validateCSRFToken($this->request->get('csrf_token', ''))) {
return $this->cms_template->renderJSON([
'error' => true,
'message' => LANG_COMMENT_ERROR
]);
}
// параметры комментария
$this->target_controller = $this->request->get('tc');
$this->target_subject = $this->request->get('ts');
$this->target_id = $this->request->get('ti');
$this->target_user_id = $this->request->get('tud');
$this->parent_id = $this->request->get('parent_id');
$this->comment_id = $this->request->get('id');
$this->content = $this->request->get('content', '');
$this->author_name = $this->request->get('author_name');
$this->author_email = $this->request->get('author_email');
// Проверяем наличие контроллера и модели
if (!(cmsCore::isControllerExists($this->target_controller) &&
cmsCore::isModelExists($this->target_controller) &&
cmsController::enabled($this->target_controller))) {
return $this->cms_template->renderJSON([
'error' => true,
'message' => LANG_COMMENT_ERROR
]);
}
$typograph_id = $this->options['typograph_id'] ?? 1;
$editor_params = cmsCore::getController('wysiwygs')->getEditorParams([
'editor' => $this->options['editor'],
'presets' => $this->options['editor_presets']
]);
// Типографируем текст для вывода
$this->content_html = cmsEventsManager::hook('html_filter', [
'text' => $this->content,
'typograph_id' => $typograph_id,
'is_auto_br' => !$editor_params['editor'] ? true : null
]);
// Типографируем исходный текст без колбэков
$this->content = cmsEventsManager::hook('html_filter', [
'text' => $this->content,
'is_process_callback' => false,
'typograph_id' => $typograph_id,
'is_auto_br' => false
]);
// Если редактор не указан, то это textarea, вырезаем все теги
if (!$editor_params['editor']) {
$this->content_html = trim(strip_tags($this->content_html, '<br>'));
$this->content = strip_tags($this->content, '<br>');
}
if (!$this->content_html) {
return $this->cms_template->renderJSON([
'error' => true,
'message' => ERR_VALIDATE_REQUIRED,
'html' => false
]);
}
return call_user_func([$this, 'run' . ucfirst($this->request->get('action'))]);
}
/**
* Превью комментария
* @return json
*/
private function runPreview() {
if (!$this->cms_user->is_logged && empty($this->options['is_guests'])) {
return cmsCore::error404();
}
return $this->cms_template->renderJSON([
'error' => false,
'html' => cmsEventsManager::hook('parse_text', $this->content_html)
]);
}
/**
* Добавление комментария
* @return json
*/
private function runAdd() {
// Собираем данные комментария
$comment = [
'parent_id' => $this->parent_id,
'target_controller' => $this->target_controller,
'target_subject' => $this->target_subject,
'target_id' => $this->target_id,
'content' => $this->content,
'content_html' => $this->content_html,
'author_ip' => function ($db) {
return '\'' . $db->escape(string_iptobin($this->cms_user->ip)) . '\'';
}
];
// гость
if (!$this->cms_user->is_logged) {
$comment['author_name'] = $this->author_name;
$comment['author_email'] = $this->author_email;
if (empty($this->options['is_guests'])) {
return cmsCore::error404();
}
if (!empty($this->options['show_author_email']) && !$this->author_email) {
return $this->cms_template->renderJSON([
'error' => true,
'message' => LANG_COMMENT_ERROR_EMAIL,
'html' => false
]);
}
if (!$this->author_name) {
return $this->cms_template->renderJSON([
'error' => true,
'message' => LANG_COMMENT_ERROR_NAME,
'html' => false
]);
}
// запрещенные ip
if (!empty($this->options['restricted_ips'])) {
if (string_in_mask_list($this->cms_user->ip, $this->options['restricted_ips'])) {
return $this->cms_template->renderJSON([
'error' => true,
'message' => LANG_COMMENT_ERROR_IP,
'html' => false
]);
}
}
// запрещенные email
if (!empty($this->options['show_author_email']) && !empty($this->options['restricted_emails'])) {
if (string_in_mask_list($this->author_email, $this->options['restricted_emails'])) {
return $this->cms_template->renderJSON([
'error' => true,
'message' => LANG_COMMENT_ERROR_EMAIL,
'html' => false
]);
}
}
// запрещенные имена
if (!empty($this->options['restricted_names'])) {
if (string_in_mask_list($this->author_name, $this->options['restricted_names'])) {
return $this->cms_template->renderJSON([
'error' => true,
'message' => ERR_VALIDATE_INVALID,
'html' => false
]);
}
}
// комментарии с одного ip
if (!empty($this->options['guest_ip_delay'])) {
$last_comment_time = $this->model->getGuestLastCommentTime($this->cms_user->ip);
$minutes_passed = (time() - $last_comment_time) / 60;
if ($minutes_passed < $this->options['guest_ip_delay']) {
$spellcount = html_spellcount($this->options['guest_ip_delay'], LANG_MINUTE1, LANG_MINUTE2, LANG_MINUTE10);
return $this->cms_template->renderJSON([
'error' => true,
'message' => sprintf(LANG_COMMENT_ERROR_TIME, $spellcount),
'html' => false
]);
}
}
// авторизованный юзер
} else {
$comment['user_id'] = $this->cms_user->id;
$is_user_allowed = cmsUser::isAllowed('comments', 'add');
$is_karma_allowed = !cmsUser::isPermittedLimitHigher('comments', 'karma', $this->cms_user->karma);
if (!$is_user_allowed || !$is_karma_allowed) {
return cmsCore::error404();
}
}
// Получаем модель целевого контроллера
$target_model = cmsCore::getModel($this->target_controller);
$target_info = [];
// Получаем URL и заголовок комментируемой страницы
if (method_exists($target_model, 'getTargetItemInfo')) {
$target_info = $target_model->getTargetItemInfo($this->target_subject, $this->target_id);
}
if (!$target_info) {
return $this->cms_template->renderJSON([
'error' => true,
'message' => LANG_COMMENT_ERROR
]);
}
$comment['target_url'] = $target_info['url'];
$comment['target_title'] = $target_info['title'];
$comment['is_private'] = empty($target_info['is_private']) ? false : $target_info['is_private'];
// проверяем модерацию
$comment['is_approved'] = $this->isApproved($comment);
list($comment, $permissions) = cmsEventsManager::hook('comment_add_permissions', [
$comment,
['error' => false, 'message' => '']
]);
if ($permissions['error']) {
return $this->cms_template->renderJSON($permissions);
}
// Сохраняем комментарий
$comment_id = $this->model->addComment(cmsEventsManager::hook('comment_before_add', $comment, null, $this->request));
// успешно добавился?
if (!$comment_id) {
return $this->cms_template->renderJSON([
'error' => true,
'message' => LANG_COMMENT_ERROR
]);
}
// Получаем список из одного комментария
$comments = $this->model->filterEqual('id', $comment_id)->
disableApprovedFilter()->getComments($this->getCommentActions());
// Добавленный комментарий
$comment = reset($comments);
$comment['content_html'] = cmsEventsManager::hook('parse_text', $comment['content_html']);
// Уведомление модерации
if (!$comment['is_approved']) {
return $this->cms_template->renderJSON([
'error' => false,
'on_moderate' => true,
'message' => LANG_COMMENTS_MODERATE_HINT . ' ' . $this->notifyModerators($comment)
]);
} else {
// Уведомляем модель целевого контента об изменении количества комментариев
$comments_count = $this->model->
filterEqual('target_controller', $this->target_controller)->
filterEqual('target_subject', $this->target_subject)->
filterEqual('target_id', $this->target_id)->
getCommentsCount();
$this->model->resetFilters();
$target_model->updateCommentsCount($this->target_subject, $this->target_id, $comments_count);
$parent_comment = $comment['parent_id'] ? $this->model->getComment($comment['parent_id']) : false;
// Уведомляем подписчиков
$this->notifySubscribers($comment, $parent_comment);
// Уведомляем об ответе на комментарий
if ($parent_comment) {
$this->notifyParent($comment, $parent_comment);
}
$comment = cmsEventsManager::hook('comment_after_add', $comment, null, $this->request);
}
// получаем опции, если есть
$target_options = [];
if (method_exists($target_model, 'getCommentsOptions')) {
$target_options = $target_model->getCommentsOptions($this->target_subject);
}
$template_name = !empty($target_options['template']) ? $target_options['template'] : $this->comment_template;
// Формируем и возвращаем результат
return $this->cms_template->renderJSON([
'error' => false,
'message' => LANG_COMMENT_SUCCESS,
'id' => $comment_id,
'parent_id' => isset($comment['parent_id']) ? $comment['parent_id'] : 0,
'level' => isset($comment['level']) ? $comment['level'] : 0,
'html' => $this->cms_template->render($template_name, [
'comments' => [$comment],
'target_user_id' => $this->target_user_id,
'user' => $this->cms_user,
'is_levels' => true,
'is_controls' => true,
'is_show_target' => false
], new cmsRequest(array(), cmsRequest::CTX_INTERNAL))
]);
}
/**
* Редактирование комментария
* @return json
*/
private function runUpdate() {
if (!$this->cms_user->is_logged || !cmsUser::isAllowed('comments', 'edit')) {
return cmsCore::error404();
}
$comment = $this->model->getComment($this->comment_id);
if (!$comment) {
return $this->cms_template->renderJSON([
'error' => true,
'message' => '404'
]);
}
if (!cmsUser::isAllowed('comments', 'edit', 'all')) {
if (cmsUser::isAllowed('comments', 'edit', 'own') && $comment['user']['id'] != $this->cms_user->id) {
return $this->cms_template->renderJSON([
'error' => true,
'message' => LANG_COMMENT_ERROR
]);
}
}
if (cmsUser::isPermittedLimitReached('comments', 'times', ((time() - strtotime($comment['date_pub'])) / 60))) {
return $this->cms_template->renderJSON([
'error' => true,
'message' => 'Time is over'
]);
}
list($this->comment_id, $this->content, $this->content_html, $data) = cmsEventsManager::hook('comment_before_update', [
$this->comment_id,
$this->content,
$this->content_html,
[]
], null, $this->request);
$this->model->updateCommentContent($this->comment_id, $this->content, $this->content_html, $data);
$comment = $this->model->getComment($this->comment_id);
$comment = cmsEventsManager::hook('comment_after_update', $comment, null, $this->request);
$comment['content_html'] = cmsEventsManager::hook('parse_text', $comment['content_html']);
return $this->cms_template->renderJSON([
'error' => false,
'message' => LANG_SUCCESS_MSG,
'id' => $this->comment_id,
'parent_id' => isset($comment['parent_id']) ? $comment['parent_id'] : 0,
'level' => isset($comment['level']) ? $comment['level'] : 0,
'html' => $comment['content_html']
]);
}
}