<?php
/**
* @property \modelModeration $model
* @property \messages $controller_messages
*/
class moderation extends cmsFrontend {
protected $useOptions = true;
/**
* Ставит запись на модерацию и отправляет уведомления модератору
*
* @param string $target_name Имя цели модерации
* @param array $item Массив модерируемой записи
* @param boolean $is_new_item Новая запись или редактируемая
* @param string $pm_message Текст сообщения для уведомления
* @return mixed
*/
public function requestModeration($target_name, $item, $is_new_item = true, $pm_message = LANG_MODERATION_NOTIFY) {
$moderator_id = $this->model->getNextModeratorId($target_name);
$moderator = $this->model_users->getUser($moderator_id);
if (!$moderator) {
return false;
}
list($moderator, $target_name, $item, $is_new_item, $pm_message) = cmsEventsManager::hook([
'moderation_request_before',
'moderation_' . $target_name . '_request_before'
], [$moderator, $target_name, $item, $is_new_item, $pm_message], null, $this->request);
if ($item['user_id']) {
$author = $this->model_users->getUser($item['user_id']);
if (!$author) {
return false;
}
} else {
$author = [
'nickname' => (!empty($item['author_name']) ? $item['author_name'] : LANG_GUEST)
];
}
// чтобы на рассылать множество уведомлений, проверяем, есть ли ожидающие модерации записи
if (!$this->model->isModeratorTaskExists($target_name, $moderator['id'])) {
// личное сообщение
$this->controller_messages->addRecipient($moderator['id'])->sendNoticePM([
'content' => $pm_message,
'actions' => [
'view' => [
'title' => LANG_SHOW,
'href' => $item['page_url']
]
]
]);
// EMAIL уведомление
$to = ['email' => $moderator['email'], 'name' => $moderator['nickname']];
$this->controller_messages->sendEmail($to, 'moderation', [
'moderation_text' => $pm_message,
'moderator' => $moderator['nickname'],
'author' => $author['nickname'],
'author_url' => (!empty($author['id']) ? href_to_profile($author, false, true) : (!empty($item['author_email']) ? 'mailto:' . $item['author_email'] : '')),
'page_title' => $item['title'],
'page_url' => $item['page_url'],
'date' => html_date_time()
]);
}
// добавляем задачу модератору
$this->model->addModeratorTask($target_name, $moderator['id'], $is_new_item, $item);
return sprintf(LANG_MODERATION_IDLE, $moderator['nickname']);
}
/**
* Отправляет автору уведомление о модерации
* успешной или неуспешной
*
* @param array $item Массив модерируемой записи
* @param string $type Типа уведомления moderation_approved | moderation_refused | moderation_rework | moderation_comment_refused
* Должна быть языковая константа LANG_PM_$type, либо, если передан аргумент $letter
* $type должен содержать текстовую фразу аналогично тем, что в константах LANG_PM_MODERATION_*
* @param ?string $letter Имя файла email письма без расширения
* @return $this
*/
public function moderationNotifyAuthor($item, $type, $letter = null) {
$page_url = $item['page_url'] ?? '';
$reason = $item['reason'] ?? '';
if (!$letter) {
$letter = $type;
}
// автор гость
if (empty($item['user_id'])) {
// если не заданы параметры гостя
if (empty($item['author_email'])) {
return $this;
}
$author_name = (!empty($item['author_name']) ? $item['author_name'] : $item['author_email']);
$to = ['email' => $item['author_email'], 'name' => $author_name];
$this->controller_messages->sendEmail($to, $letter, [
'nickname' => $author_name,
'page_title' => $item['title'],
'page_url' => $page_url,
'reason' => $reason,
'date' => html_date_time()
]);
return $this;
}
$author = $this->model_users->getUser($item['user_id']);
if (!$author) {
return $this;
}
// личное сообщение
$this->controller_messages->addRecipient($author['id'])->sendNoticePM([
'content' => sprintf(string_lang('PM_' . $type, $type), $item['title'], $page_url, $reason)
]);
// EMAIL уведомление
$to = ['email' => $author['email'], 'name' => $author['nickname']];
$this->controller_messages->sendEmail($to, $letter, [
'nickname' => $author['nickname'],
'page_title' => $item['title'],
'page_url' => $page_url,
'reason' => $reason,
'date' => html_date_time()
]);
return $this;
}
/**
* Одобряет модерацию для цели
*
* @param string $target_name Имя цели модерации
* @param array $item Массив модерируемой записи
* @param string $ups_key Ключ UPS для записей просмотра модераций
* @param string $letter_name Имя файла email письма без расширения для уведомления
* @return array $task
*/
public function approve($target_name, $item, $ups_key = false, $letter_name = 'moderation_approved') {
$letter = $this->getLetterForTarget($letter_name, $target_name);
if (is_array($letter)) {
list($type, $letter) = $letter;
} else {
$type = $letter;
}
$task = $this->model->getModeratorTask($target_name, $item['id']);
$this->model->closeModeratorTask($target_name, $item['id'], true, $this->cms_user->id);
$after_action = $task['is_new_item'] ? 'add' : 'update';
$data = cmsEventsManager::hook("content_after_{$after_action}_approve", ['ctype_name' => $target_name, 'item' => $item], null, $this->request);
$item = $data['item'];
$item = cmsEventsManager::hook("content_{$target_name}_after_{$after_action}_approve", $item, null, $this->request);
$this->moderationNotifyAuthor($item, $type, $letter);
if ($ups_key) {
cmsUser::deleteUPSlist($ups_key);
}
return $task;
}
/**
* Отзывает запись с модерации и отправляет уведомления модератору
*
* @param string $target_name Имя цели модерации
* @param array $item Массив модерируемой записи
* @param string $ups_key Ключ UPS для записей просмотра модераций
* @return boolean
*/
public function cancelModeratorTask($target_name, $item, $ups_key = false) {
$task = $this->model->cancelModeratorTask($target_name, $item['id'], $this->cms_user->id);
if (!$task) {
return false;
}
$moderator = $this->model_users->getUser($task['moderator_id']);
if (!$moderator) {
return false;
}
$author = $this->model_users->getUser($item['user_id']);
if (!$author) {
return false;
}
list($moderator, $target_name, $item, $task, $author) = cmsEventsManager::hook([
'moderation_cancel',
'moderation_' . $target_name . '_cancel'
], [$moderator, $target_name, $item, $task, $author], null, $this->request);
// личное сообщение
$this->controller_messages->addRecipient($moderator['id'])->sendNoticePM([
'content' => LANG_MODERATION_RETURN_NOTIFY,
'actions' => [
'view' => [
'title' => LANG_SHOW,
'href' => $item['page_url']
]
]
]);
// EMAIL уведомление
$to = ['email' => $moderator['email'], 'name' => $moderator['nickname']];
$this->controller_messages->sendEmail($to, 'moderation_return', [
'moderator' => $moderator['nickname'],
'author' => $author['nickname'],
'author_url' => href_to_profile($author, false, true),
'page_title' => $item['title'],
'page_url' => $item['page_url']
]);
if ($ups_key) {
cmsUser::deleteUPSlist($ups_key);
}
return true;
}
/**
* Отправляет запись на доработку
*
* @param string $target_name Имя цели модерации
* @param array $item Массив модерируемой записи
* @param string $ups_key Ключ UPS для записей просмотра модераций
* @return boolean
*/
public function reworkModeratorTask($target_name, $item, $ups_key = false) {
$task = $this->model->cancelModeratorTask($target_name, $item['id'], $this->cms_user->id);
if (!$task) {
return false;
}
list($target_name, $item, $task) = cmsEventsManager::hook([
'moderation_rework',
'moderation_' . $target_name . '_rework'
], [$target_name, $item, $task], null, $this->request);
$letter = $this->getLetterForTarget('moderation_rework', $target_name);
if (is_array($letter)) {
list($type, $letter) = $letter;
} else {
$type = $letter;
}
$this->moderationNotifyAuthor($item, $type, $letter);
if ($ups_key) {
cmsUser::deleteUPSlist($ups_key);
}
return true;
}
/**
* Возвращает массив кол-ва записей в черновиках,
* разделённых по контроллерам
*
* @param integer $user_id
* @return array
*/
public function getUserDraftCounts($user_id) {
$listeners = cmsEventsManager::getEventListeners('moderation_list');
$counts = [];
foreach ($listeners as $controller_name) {
if (!cmsController::enabled($controller_name)) {
continue;
}
$draft_counts = cmsCore::getModel($controller_name)->getDraftCounts($user_id);
if (!$draft_counts) {
continue;
}
if (is_numeric($draft_counts)) {
$counts[$controller_name] = $draft_counts;
} else {
$counts = array_merge($counts, $draft_counts);
}
}
return $counts;
}
/**
* Проверяет, что пользователь модератор
*
* @param string $ctype_name
* @param integer $user_id
* @param array $item
* @return boolean
*/
public function userIsContentModerator($ctype_name, $user_id, $item = []) {
if (!$user_id) {
return false;
}
if ($this->cms_user->is_admin || $this->model->userIsContentModerator($ctype_name, $user_id)) {
return true;
}
list($ctype_name, $user_id, $item, $is_moderator) = cmsEventsManager::hook([
'moderation_user_is_moderator',
'moderation_' . $ctype_name . '_user_is_moderator'
], [$ctype_name, $user_id, $item, false]);
return $is_moderator;
}
/**
* Возвращает имя файла email письма без расширения
* Если есть файл письма $letter_name . '_' . $target_name
* Возвращает это имя
*
* @param string $letter_name Имя файла email письма без расширения
* @param string $target_name Имя цели модерации
* @return string|array
*/
public function getLetterForTarget($letter_name, $target_name) {
$letter_target = $letter_name . '_' . $target_name;
if (cmsCore::isLanguageTextFileExists('letters/'.$letter_target)) {
return [$letter_name, $letter_target];
}
return $letter_name;
}
}