opigno_messaging.module in Opigno messaging 8
Same filename and directory in other branches
Contains opigno_messaging.module.
File
opigno_messaging.moduleView source
<?php
/**
* @file
* Contains opigno_messaging.module.
*/
use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Link;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\group\Entity\Group;
use Drupal\opigno_class\Form\SocialSettingsForm;
use Drupal\opigno_messaging\OpignoMessageThread;
use Drupal\private_message\Entity\PrivateMessageThread;
use Drupal\private_message\Mapper\PrivateMessageMapper;
use Drupal\user\Entity\User;
use Drupal\views\Plugin\views\query\QueryPluginBase;
use Drupal\views\ViewExecutable;
/**
* Implements hook_help().
*/
function opigno_messaging_help($route_name, RouteMatchInterface $route_match) {
switch ($route_name) {
// Main module help for the opigno_messaging module.
case 'help.page.opigno_messaging':
$output = '';
$output .= '<h3>' . t('About') . '</h3>';
$output .= '<p>' . t('Opigno app for messaging') . '</p>';
return $output;
default:
}
}
/**
* Implements hook_theme().
*/
function opigno_messaging_theme() {
return [
'opigno_messaging' => [
'render element' => 'children',
],
];
}
/**
* Implements hook_form_alter().
*/
function opigno_messaging_form_private_message_add_form_alter(&$form, FormStateInterface $form_state, $form_id) {
$thread_members = $form_state
->get('thread_members');
// Only add the select if we are in the context
// of a new message (not in a tread context).
if (!isset($thread_members)) {
$current_user = \Drupal::currentUser();
$uid = $current_user
->id();
$current_user = User::load($uid);
// Add the subject.
$form['subject'] = [
'#type' => 'textfield',
'#title' => t('Subject'),
'#placeholder' => t('Enter a subject'),
'#default_value' => "",
'#size' => 60,
'#maxlength' => 128,
'#required' => FALSE,
'#weight' => -3,
];
// Hide the default messaging to field.
$form['members']['#type'] = 'hidden';
$plugin_service = \Drupal::service('opigno_learning_path.members.manager');
$plugin_instance = $plugin_service
->createInstance('recipients_plugin');
$plugin_instance
->getMembersForm($form, $form_state, $current_user);
unset($form['message']['widget']['#title']);
unset($form['message']['widget'][0]['#title']);
$form['message']['widget']['#placeholder'] = t('your message');
$form['actions']['submit']['#value'] = t('Send');
// Validation function so we can move the values of the users_to_send
// to the default messaging module field.
$form['#validate'][] = 'opigno_messaging_private_message_add_form_validate_replace_to';
}
// Remove default & set custom submit handler.
$form['#submit'] = [
'opigno_messaging_private_message_add_form_submit',
];
$form['actions']['submit']['#submit'] = [
'opigno_messaging_private_message_add_form_submit',
];
$form['actions']['submit']['#value'] = t('Send');
$route_name = \Drupal::routeMatch()
->getRouteName();
if ($route_name == 'private_message.private_message_page') {
// Save current thread id in form storage.
// For "private_messages" page (not PM thread page).
$user = \Drupal::currentUser();
$db_connection = \Drupal::service('database');
$pm_mapper = new PrivateMessageMapper($db_connection, $user);
$user = User::load($user
->id());
$thread_id = $pm_mapper
->getFirstThreadIdForUser($user);
$form_state
->set('thread_id', $thread_id);
}
}
/**
* Helper function to get users for group.
*
* @param int $group_id
* Group.
*
* @return \Drupal\user\UserInterface[]
* User ID.
*/
function opigno_messaging_get_user_for_group($group_id = NULL, $show_all = FALSE) {
if ($group_id === NULL || $group_id === 0) {
return opigno_messaging_get_all_recipients($show_all);
}
$users = [];
$group = Group::load($group_id);
$members = $group
->getMembers();
$current_user = \Drupal::currentUser();
if ($show_all) {
if ($members) {
$users = array_map(function ($member) {
/** @var \Drupal\group\GroupMembership $member */
return $member
->getUser();
}, $members);
$users = array_filter($users, function ($user) {
/** @var \Drupal\user\UserInterface $user */
return $user
->id() > 0 && $user
->isActive();
});
}
return $users;
}
$member = $group
->getMember($current_user);
$member_roles = $member
->getRoles();
if (opigno_messaging_user_is_manager($member_roles)) {
$users = array_map(function ($member) {
/** @var \Drupal\group\GroupMembership $member */
return $member
->getUser();
}, $members);
$users = array_filter($users, function ($user) {
/** @var \Drupal\user\UserInterface $user */
return $user
->id() > 0 && $user
->isActive();
});
}
else {
$owner = $group
->getOwner();
foreach ($members as $member) {
$member_roles = $member
->getRoles();
if (opigno_messaging_social_sharing($group) || opigno_messaging_user_is_manager($member_roles) || $member
->getUser()
->id() == $owner
->id()) {
if ($member
->getUser()
->isActive()) {
$users[] = $member
->getUser();
}
}
}
}
return $users;
}
/**
* Check socials sharing settings.
*
* @param \Drupal\Core\Entity\EntityInterface $group
*
* @return bool
* Social sharing is allowed.
*/
function opigno_messaging_social_sharing($group) {
$social_config = \Drupal::config('opigno_class.socialsettings')
->get('social');
return $social_config & SocialSettingsForm::SAME_CLASS && $group
->getGroupType()
->id() == 'opigno_class' || $social_config & SocialSettingsForm::SAME_TRAINING && $group
->getGroupType()
->id() == 'learning_path' || $social_config === SocialSettingsForm::ALL_USERS;
}
/**
* Checks the member roles is an manager.
*
* @param \Drupal\group\GroupMembership[] $member_roles
* Group member roles.
*
* @return bool
* User membership is manager.
*/
function opigno_messaging_user_is_manager($member_roles) {
return count(array_intersect(array_keys($member_roles), [
'learning_path-user_manager',
'opigno_class-class_manager',
])) > 0;
}
/**
* Helper function to get all users that current user can message to.
*/
function opigno_messaging_get_all_users() {
$current_user = \Drupal::currentUser();
if ($current_user
->hasPermission('message anyone regardless of groups')) {
return array_filter(User::loadMultiple(), function ($user) {
/** @var \Drupal\user\UserInterface $user */
return $user
->id() > 0;
});
}
$users = [];
$groups = opigno_messaging_get_groups('opigno_class') + opigno_messaging_get_groups('learning_path');
/** @var \Drupal\group\Entity\GroupInterface $group */
foreach ($groups as $group_info) {
$group = Group::load($group_info['entity_id']);
$members = $group
->getMembers();
foreach ($members as $member) {
$user = $member
->getUser();
if ($user) {
$users[$user
->id()] = $member
->getUser();
}
}
}
unset($users[0]);
return array_values($users);
}
/**
* Helper function to get list of all users that current user can message to.
*/
function opigno_messaging_get_all_recipients($show_all) {
$current_user = \Drupal::currentUser();
$social_config = \Drupal::config('opigno_class.socialsettings')
->get('social');
if ($social_config == SocialSettingsForm::ALL_USERS || $show_all) {
return array_filter(User::loadMultiple(), function ($user) {
/** @var \Drupal\user\UserInterface $user */
return $user
->id() > 0 && $user
->isActive();
});
}
else {
$users = [];
// Get all users with roles 'user manager' or 'content manager' or 'administrator'.
$global_managers_roles = [
'user_manager',
'content_manager',
'administrator',
];
$global_managers_ids = \Drupal::entityQuery('user')
->condition('status', 1)
->condition('roles', $global_managers_roles, 'IN')
->execute();
$users = array_merge($users, $global_managers_ids);
// Get users with group roles 'student manager' or 'content manager' in which the current user is a member.
/* @var \Drupal\group\GroupMembershipLoaderInterface $membership_service */
$membership_service = \Drupal::service('group.membership_loader');
/* @var \Drupal\group\GroupMembership[] $memberships */
$memberships = $membership_service
->loadByUser($current_user);
foreach ($memberships as $membership) {
$group = $membership
->getGroup();
$members = $group
->getMembers();
$owner = $group
->getOwner();
foreach ($members as $member) {
$member_roles = $member
->getRoles();
if (opigno_messaging_social_sharing($group) || opigno_messaging_user_is_manager($member_roles) || $member
->getUser()
->id() == $owner
->id()) {
$users[] = $member
->getUser()
->id();
}
}
}
// Get members from groups and classes where current user is a 'class manager' in a class,
// 'student manager' or 'content manager' in a group.
$memberships = $membership_service
->loadByUser($current_user, [
'learning_path-user_manager',
// 'learning_path-content_manager',
'opigno_class-class_manager',
]);
foreach ($memberships as $membership) {
$group = $membership
->getGroup();
$members = $group
->getMembers();
foreach ($members as $member) {
$users[] = $member
->getUser()
->id();
}
}
}
$users = User::loadMultiple($users);
return array_values($users);
}
/**
* Helper function to get all groups that current user can message to.
*/
function opigno_messaging_get_groups($group_type) {
$current_user = \Drupal::currentUser();
$groups = \Drupal::entityTypeManager()
->getStorage('group')
->loadByProperties([
'type' => $group_type,
]);
if (!$current_user
->hasPermission('message all groups')) {
$groups = array_filter($groups, function ($group) use ($current_user) {
/** @var \Drupal\group\Entity\GroupInterface $group */
return $group
->getMember($current_user) !== FALSE;
});
}
return array_map(function ($group) {
/** @var \Drupal\group\Entity\Group $group */
return [
'entity_id' => $group
->id(),
'title' => $group
->label(),
];
}, $groups);
}
/**
* For validation.
*
* Sets the values of the default messaging "to" field with the
* values of our multiselect.
*/
function opigno_messaging_private_message_add_form_validate_replace_to(&$form, FormStateInterface $form_state) {
$selected_users = $form_state
->getValue('users_to_send');
$selected_members = $form_state
->getValue('members');
// The select member should be empty at this point,
// fill it with the users to send.
$i = 0;
foreach ($selected_users as $selected_user) {
$selected_members[$i]['target_id'] = $selected_user;
$selected_members[$i]['_weight'] = $i;
$i++;
}
// Update the form state with the values we want.
$form_state
->setValue('members', $selected_members);
// Send error message if fields are empty.
$message = $form_state
->getValue('message');
if (empty($selected_members['0']['target_id'])) {
$form_state
->setErrorByName('members', t("Please select user for sending message!"));
}
if (empty($message[0]['value'])) {
$form_state
->setErrorByName('message', t("Please enter a message!"));
}
}
/**
* Add private message form custom submit handler.
*/
function opigno_messaging_private_message_add_form_submit(array $form, FormStateInterface $form_state) {
/** @var \Drupal\Core\Entity\ContentEntityFormInterface $form_obj */
$form_obj = $form_state
->getFormObject();
$current_user = \Drupal::currentUser();
/** @var \Drupal\user\UserDataInterface $user_data */
$user_data = \Drupal::service('user.data');
$pm_config = \Drupal::config('private_message.settings');
/** @var \Drupal\private_message\Service\PrivateMessageServiceInterface $pm_service */
$pm_service = \Drupal::service('private_message.service');
$form_state
->cleanValues();
/** @var \Drupal\private_message\Entity\PrivateMessageInterface $entity */
$entity = $form_obj
->buildEntity($form, $form_state);
$entity
->save();
/** @var \Drupal\user\UserInterface[] $members */
$members = $form_state
->get('thread_members');
if (!$members) {
// Generate an array containing the members of the thread.
$members = [
$current_user,
];
foreach ($form_state
->getValue('members') as $info) {
$user = User::load($info['target_id']);
if ($user) {
$members[] = $user;
}
}
}
$subject = $form_state
->getValue('subject');
// If subject is set, create new thread.
if ($subject) {
$private_message_thread = PrivateMessageThread::create();
foreach ($members as $member) {
$private_message_thread
->addMember($member);
}
$private_message_thread
->set('field_pm_subject', $subject);
$private_message_thread
->save();
}
else {
// Try get thread from path.
$parameters = \Drupal::routeMatch()
->getParameters();
$private_message_thread = $parameters
->get('private_message_thread');
if ($private_message_thread === NULL) {
$storage = $form_state
->getStorage();
if (isset($storage['thread_id'])) {
// Get current thread for "private_messages" page (not PM thread page).
$private_message_thread = PrivateMessageThread::load($storage['thread_id']);
}
else {
$private_message_thread = $pm_service
->getThreadForMembers($members);
}
}
}
// Add the new message to the thread and save.
/** @var \Drupal\private_message\Entity\PrivateMessageThreadInterface $private_message_thread */
$private_message_thread
->addMessage($entity);
$private_message_thread
->save();
$mailManager = \Drupal::service('plugin.manager.mail');
$params = [
'private_message' => $entity,
'private_message_thread' => $private_message_thread,
];
$config_factory = \Drupal::configFactory();
$message_notification_mail_map = $config_factory
->getEditable('private_message.mail')
->get('message_notification');
$site_name = \Drupal::config('system.site')
->get('name');
$params['subject'] = str_replace('[site:name]', $site_name, $message_notification_mail_map['subject']);
if ($members) {
$db_connection = \Drupal::service('database');
$thread_url = $private_message_thread
->toUrl();
$thread_url
->setOption('absolute', TRUE);
$thread_url = Link::fromTextAndUrl($thread_url
->toString(), $thread_url)
->toString();
$delta = 0;
// Send email notifications for members.
foreach ($members as $member) {
if ($member
->id() != $current_user
->id()) {
$params['member'] = $member;
$send = $user_data
->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) {
$user_name = $member
->getDisplayName();
$author_name = $entity
->getOwner()
->getDisplayName();
$message = $entity
->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_url . '</strong>',
], $message_notification_mail_map['body']);
$mailManager
->mail('opigno_messaging', 'message_notification', $member
->getEmail(), $member
->getPreferredLangcode(), $params);
}
}
$query = $db_connection
->select('pm_thread_delete_time', 'pmtdt');
$query
->join('private_message_thread__last_delete_time', 'pmtldt', 'pmtldt.last_delete_time_target_id = pmtdt.id');
$query
->fields('pmtdt', [
'id',
]);
$query
->condition('pmtldt.entity_id', $private_message_thread
->id());
$query
->condition('pmtdt.owner', $member
->id());
$member_last_delete_time = $query
->execute()
->fetchField();
// Restore delete time for users who have deleted thread.
if (!$member_last_delete_time) {
try {
$db_connection
->insert('pm_thread_delete_time')
->fields([
'uuid' => \Drupal::service('uuid')
->generate(),
'owner' => $member
->id(),
'delete_time' => 0,
])
->execute();
} catch (Exception $e) {
\Drupal::logger('opigno_messaging')
->error($e
->getMessage());
}
if (empty($e)) {
$query = $db_connection
->select('pm_thread_delete_time', 'pmtdt');
$query
->fields('pmtdt', [
'id',
]);
$query
->condition('pmtdt.owner', $member
->id());
$query
->orderBy('id', 'DESC');
$query
->range(0, 1);
$member_last_delete_time = $query
->execute()
->fetchField();
if ($member_last_delete_time) {
try {
$db_connection
->insert('private_message_thread__last_delete_time')
->fields([
'bundle' => 'private_message_thread',
'deleted' => 0,
'entity_id' => $private_message_thread
->id(),
'revision_id' => $private_message_thread
->id(),
'langcode' => 'und',
'delta' => $delta,
'last_delete_time_target_id' => $member_last_delete_time,
])
->execute();
} catch (Exception $e) {
\Drupal::logger('opigno_messaging')
->error($e
->getMessage());
}
if (empty($e)) {
$delta++;
}
}
}
}
}
// Update delete time thread with a new message for members (set to 0).
$delete_times = $private_message_thread
->getLastDeleteTimes();
if ($delete_times) {
$delete_times = array_map(function ($delete_time) {
return $delete_time
->id();
}, $delete_times);
try {
$db_connection
->update('pm_thread_delete_time')
->fields([
'delete_time' => 0,
])
->condition('id', $delete_times, 'IN')
->execute();
} catch (Exception $e) {
\Drupal::logger('opigno_messaging')
->error($e
->getMessage());
}
}
}
// Send the user to the private message page. As this thread is the newest,
// it wll be at the top of the list.
$form_state
->setRedirect('entity.private_message_thread.canonical', [
'private_message_thread' => $private_message_thread
->id(),
]);
}
/**
* Implements hook_mail().
*/
function opigno_messaging_mail($key, &$message, $params) {
if ($key == 'message_notification') {
$message['from'] = \Drupal::config('system.site')
->get('name');
$message['subject'] = $params['subject'];
$message['body'][] = $params['message'];
}
}
/**
* Implements hook_ENTITY_TYPE_view_alter().
*
* Changes 'last_message' view mode to 'thread_preview'
* if 'private_message_thread' view mode is 'preview'.
*
* @see private_message_private_message_thread_view()
*/
function opigno_messaging_private_message_thread_view_alter(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display) {
if (isset($build['last_message']) && $build['#view_mode'] === 'preview') {
/** @var \Drupal\private_message\Entity\PrivateMessageThreadInterface $entity */
$messages = $entity
->getMessages();
$last_message = array_pop($messages);
$view_builder = \Drupal::entityTypeManager()
->getViewBuilder('private_message');
$build['last_message'] = $view_builder
->view($last_message, 'thread_preview');
}
}
/**
* Implements hook_preprocess_views_view().
*/
function opigno_messaging_preprocess_views_view(&$vars) {
// Attach js & css to view.
if (isset($vars['view_array']['#name']) && $vars['view_array']['#name'] === 'private_message') {
$vars['#attached']['library'][] = 'opigno_messaging/view_private_message';
$vars['#attached']['drupalSettings']['multiLingual'] = \Drupal::languageManager()
->isMultilingual();
}
}
/**
* Implements hook_preprocess_views_view_field().
*
* Sets class for unread message thread.
*/
function opigno_messaging_preprocess_views_view_field(&$variables) {
if ($variables['view']
->id() == 'private_message') {
$ids =& drupal_static(__FUNCTION__);
$variables['unread_class'] = '';
if (!isset($ids)) {
$ids = OpignoMessageThread::getUnreadThreadCount('entity_id');
}
if ($ids && in_array($variables['row']->id, $ids)) {
// Set class for unread message thread.
$variables['unread_class'] = 'new';
}
}
}
/**
* Implements hook_views_query_alter().
*/
function opigno_messaging_views_query_alter(ViewExecutable $view, QueryPluginBase $query) {
if ($view
->id() == 'private_message') {
static $threads;
if (!isset($threads)) {
// Get all message treads of current user.
$uid = \Drupal::currentUser()
->id();
$threads = OpignoMessageThread::getUserThreads($uid);
if ($threads) {
// Get threads delete/access time
// for whenever deleted threads of current user.
$db_connection = \Drupal::service('database');
$query_thread = $db_connection
->select('pm_thread_delete_time', 'tdt');
$query_thread
->join('private_message_thread__last_delete_time', 'ldt', 'ldt.last_delete_time_target_id = tdt.id');
$query_thread
->join('private_message_thread__last_access_time', 'tlat', 'tlat.entity_id = ldt.entity_id');
$query_thread
->join('pm_thread_access_time', 'tat', 'tat.id = tlat.last_access_time_target_id AND tat.owner = :uid', [
':uid' => $uid,
]);
$query_thread
->fields('ldt', [
'entity_id',
])
->condition('tdt.owner', $uid)
->condition('tdt.delete_time', 0, '>')
->condition('tdt.delete_time', 'tat.access_time', '>');
$deleted_threads = $query_thread
->execute()
->fetchCol();
if ($deleted_threads) {
// Remove deleted threads from threads array.
$threads = array_diff($threads, $deleted_threads);
}
}
}
if ($threads) {
// Add allowed threads to query.
$query
->addWhere('', 'private_message_threads.id', $threads, 'IN');
}
else {
$query
->addWhere('', 'private_message_threads.id', [
0,
], 'IN');
}
}
}
/**
* Implements hook_menu_local_actions_alter().
*/
function opigno_messaging_menu_local_actions_alter(&$local_actions) {
// Remove default 'Create private message' button.
unset($local_actions['private_message.private_message_add']);
}