View source
<?php
namespace Drupal\opigno_messaging\Services;
use Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException;
use Drupal\Component\Plugin\Exception\PluginNotFoundException;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Database\Connection;
use Drupal\Core\Datetime\DateFormatterInterface;
use Drupal\Core\Entity\EntityStorageException;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Link;
use Drupal\Core\Mail\MailManagerInterface;
use Drupal\Core\Render\Markup;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\Url;
use Drupal\opigno_statistics\Services\UserStatisticsManager;
use Drupal\private_message\Entity\PrivateMessage;
use Drupal\private_message\Entity\PrivateMessageInterface;
use Drupal\private_message\Entity\PrivateMessageThreadInterface;
use Drupal\user\UserDataInterface;
use Drupal\user\UserInterface;
class OpignoMessageThread {
use StringTranslationTrait;
protected $account;
protected $dateFormatter;
protected $threadStorage = NULL;
protected $mailService;
protected $config;
protected $userData;
protected $database;
public function __construct(AccountInterface $account, DateFormatterInterface $date_formatter, EntityTypeManagerInterface $entity_type_manager, MailManagerInterface $mail_manager, ConfigFactoryInterface $config_factory, UserDataInterface $user_data, Connection $database) {
$this->account = $account;
$this->dateFormatter = $date_formatter;
$this->mailService = $mail_manager;
$this->config = $config_factory;
$this->userData = $user_data;
$this->database = $database;
try {
$this->threadStorage = $entity_type_manager
->getStorage('private_message_thread');
} catch (PluginNotFoundException|InvalidPluginDefinitionException $e) {
watchdog_exception('opigno_messaging_exception', $e);
}
}
public function getUserThreads(int $uid = 0) : array {
if (!$uid) {
$uid = (int) $this->account
->id();
}
$query = $this->database
->select('pm_thread_history', 'pth');
$query
->join('private_message_threads', 'pmt', 'pmt.id = pth.thread_id');
$query
->fields('pth', [
'thread_id',
])
->condition('pth.uid', $uid);
$or_condition = $query
->orConditionGroup()
->condition('pth.delete_timestamp', 0)
->where('pmt.updated > pth.delete_timestamp');
$query
->condition($or_condition);
$result = $query
->execute()
->fetchCol();
return is_array($result) ? $result : [];
}
public function getThreadDisplayData(PrivateMessageThreadInterface $thread) : array {
$members = $thread
->getMembers();
$count = count($members);
$messages = $thread
->getMessages();
$message = end($messages);
$data = [];
if ($message instanceof PrivateMessage) {
$data['date'] = $this
->getMessageFormattedDate($message);
$length = 20;
$text = strip_tags($message
->getMessage());
$text = trim(html_entity_decode($text, ENT_NOQUOTES), " \n\r\t\v\0 ");
$text = mb_strlen($text) > $length ? mb_substr($text, 0, $length) . '...' : $text;
$data['text'] = Markup::create($text);
}
if ($count < 2) {
return $data + [
'title' => $this
->t('Deleted user'),
'image' => UserStatisticsManager::getDefaultUserPicture(),
];
}
if ($count === 2) {
foreach ($members as $member) {
if ($member instanceof UserInterface && (int) $member
->id() !== (int) $this->account
->id()) {
return $data + [
'title' => $member
->getDisplayName(),
'image' => UserStatisticsManager::getUserPicture($member),
];
}
}
}
$title = $thread
->get('field_pm_subject')
->getString() ?: $this
->t('Discussion');
if (!$thread
->get('field_image')
->isEmpty()) {
$image = $thread
->get('field_image')
->view([
'label' => 'hidden',
'type' => 'image',
'settings' => [
'image_style' => 'user_compact_image',
],
]);
}
else {
$path = drupal_get_path('theme', 'aristotle') . '/src/images/content/group_profile.svg';
$image = [
'#theme' => 'image',
'#uri' => file_exists($path) ? file_url_transform_relative(base_path() . $path) : '',
'#alt' => $title,
'#title' => $title,
];
}
$message_author = $message
->getOwner();
if ($message_author instanceof UserInterface) {
$data['text'] = $message_author
->getDisplayName();
}
return $data + [
'title' => $title,
'image' => $image,
'unread_count' => $this
->getThreadUnreadMessagesCount($thread),
];
}
public function getThreadUnreadMessagesCount(PrivateMessageThreadInterface $thread) : int {
$last_access = $thread
->getLastAccessTimestamp($this->account);
$query = $this->database
->select('private_messages', 'pm');
$query
->join('private_message_thread__private_messages', 't', 't.private_messages_target_id = pm.id');
$query
->fields('pm', [
'id',
])
->condition('t.entity_id', (int) $thread
->id())
->condition('pm.owner', (int) $this->account
->id(), '!=')
->condition('pm.created', $last_access, '>');
$count = $query
->countQuery()
->execute()
->fetchField();
return (int) $count;
}
public function getMessageFormattedDate(PrivateMessage $message) {
$timestamp = $message
->getCreatedTime();
switch ($timestamp) {
case $timestamp >= strtotime('today'):
$time = $this->dateFormatter
->format($timestamp, 'hour_minute');
$created = $this
->t('today - @time', [
'@time' => $time,
]);
break;
case $timestamp >= strtotime('yesterday'):
$time = $this->dateFormatter
->format($timestamp, 'hour_minute');
$created = $this
->t('yesterday - @time', [
'@time' => $time,
]);
break;
default:
$created = $this->dateFormatter
->format($timestamp, 'date_short_with_time');
}
return $created;
}
public function getThreadForMembers(array $uids, bool $create = TRUE) : ?PrivateMessageThreadInterface {
if (!$this->threadStorage instanceof EntityStorageInterface) {
return NULL;
}
$threads = $this->threadStorage
->loadByProperties([
'members' => $uids,
]);
if ($threads) {
$count = count($uids);
foreach ($threads as $thread) {
if (!$thread instanceof PrivateMessageThreadInterface) {
continue;
}
$members = $thread
->getMembersId();
if ($count === count($members) && !array_diff($uids, $members)) {
return $thread;
}
}
}
if (!$create) {
return NULL;
}
$thread = $this->threadStorage
->create([
'members' => $uids,
]);
try {
$thread
->save();
} catch (EntityStorageException $e) {
watchdog_exception('opigno_messaging_exception', $e);
$thread = NULL;
}
return $thread instanceof PrivateMessageThreadInterface ? $thread : NULL;
}
public function sendEmailToThreadMembers(PrivateMessageThreadInterface $thread, PrivateMessageInterface $message) : void {
$members = $thread
->getMembers();
if (!$members) {
return;
}
$pm_config = $this->config
->get('private_message.settings');
$message_notification_mail_map = $this->config
->getEditable('private_message.mail')
->get('message_notification');
$site_name = $this->config
->get('system.site')
->get('name') ?? 'Opigno';
$params = [
'private_message' => $message,
'private_message_thread' => $thread,
'subject' => str_replace('[site:name]', $site_name, $message_notification_mail_map['subject']),
];
$thread_url = Url::fromRoute('entity.private_message_thread.canonical', [
'private_message_thread' => $thread
->id(),
])
->setAbsolute();
$thread_link = Link::fromTextAndUrl($thread_url
->toString(), $thread_url)
->toString();
foreach ($members as $member) {
if (!$member instanceof UserInterface || (int) $member
->id() === (int) $this->account
->id()) {
continue;
}
$params['member'] = $member;
$send = $this->userData
->get('private_message', $member
->id(), 'email_notification');
$send = is_numeric($send) ? (bool) $send : $pm_config
->get('enable_email_notifications') && $pm_config
->get('send_by_default');
if (!$send) {
continue;
}
$user_name = $member
->getDisplayName();
$author_name = $message
->getOwner()
->getDisplayName();
$message = $message
->getMessage();
$params['message'] = str_replace([
'[site:name]',
'[user:display-name]',
'[private_message:author-name]',
'[private_message:message]',
'[private_message_thread:url]',
], [
'<strong>' . $site_name . '</strong>',
'<strong>' . $user_name . '</strong>',
'<strong>' . $author_name . '</strong>',
'<strong>' . $message . '</strong>',
'<strong>' . $thread_link . '</strong>',
], $message_notification_mail_map['body']);
$this->mailService
->mail('opigno_messaging', 'message_notification', $member
->getEmail(), $member
->getPreferredLangcode(), $params);
}
}
public function getThreadActions(PrivateMessageThreadInterface $thread) : array {
$actions = [];
$tid = (int) $thread
->id();
$links = [
'opigno_messaging.confirm_delete_form' => $this
->t('Delete'),
'opigno_messaging.get_edit_thread_form' => $this
->t('Edit'),
];
$params = [
'private_message_thread' => $tid,
];
$options = [
'attributes' => [
'class' => [
'dropdown-item-text',
'use-ajax',
],
],
];
foreach ($links as $route => $title) {
$url = Url::fromRoute($route, $params, $options);
if ($url
->access()) {
$actions[] = Link::fromTextAndUrl($title, $url);
}
}
return [
'#theme' => 'opigno_pm_thread_actions',
'#actions' => $actions,
'#cache' => [
'contexts' => Cache::mergeContexts($thread
->getCacheContexts(), [
'user',
]),
'tags' => $thread
->getCacheTags(),
],
];
}
}