' . Html::escape($text) . ''; } return ''; } /** * Implements hook_theme(). */ function privatemsg_theme() { return [ 'privatemsg_thread' => [ 'render element' => 'elements', ], 'privatemsg_message' => [ 'render element' => 'elements', ], 'views_exposed_form__all_privatemsg_threads__page_1' => [ 'render element' => 'form', ], ]; } /** * Returns pager array. */ function _privatemsg_pager_array(array $items, int $itemsPerPage): ?array { $total = \count($items); $currentPage = \Drupal::service('pager.manager')->createPager($total, $itemsPerPage)->getCurrentPage(); $chunks = \array_chunk($items, $itemsPerPage); $currentPageItemsRaw = $chunks[$currentPage]; foreach ($currentPageItemsRaw as $currentPageItem) { $currentPageItems[$currentPageItem->id()] = $currentPageItem; } return $currentPageItems; } /** * Implements hook_preprocess_HOOK(). */ function privatemsg_preprocess_privatemsg_thread(&$variables) { $variables['content'] = []; foreach (Element::children($variables['elements']) as $key) { $variables['content'][$key] = $variables['elements'][$key]; } $thread = $variables['elements']['#privatemsg_thread']; $messages = $thread->getMessages(); $messages = _privatemsg_pager_array($messages, 50); $private_messages = []; foreach ($messages as $message) { $private_messages[] = \Drupal::entityTypeManager()->getViewBuilder('privatemsg_message')->view($message); } $variables['messages'] = $private_messages; $variables['pager'] = ['#type' => 'pager']; $current_user = \Drupal::currentUser(); if ($current_user->hasPermission('privatemsg write messages') && $thread->isMember($current_user->id())) { $entity = PrivatemsgMessage::create(); $message_form = \Drupal::service('entity.form_builder')->getForm($entity, 'add'); $variables['privatemsg_message_form'] = $message_form; } $add_tag_form = \Drupal::formBuilder()->getForm(PrivatemsgAddTagForm::class); $variables['add_tag_form'] = $add_tag_form; if (isset($variables['elements']['tags']['#items'])) { $tags = $variables['elements']['tags']['#items']->referencedEntities(); $output = ''; foreach ($tags as $tag) { $output .= '' . $tag->getName() . ', '; } if (!empty($output)) { $variables['thread_tags'] = Markup::create($output); } } } /** * Implements hook_preprocess_HOOK(). */ function privatemsg_preprocess_privatemsg_message(&$variables) { $variables['content'] = []; foreach (Element::children($variables['elements']) as $key) { $variables['content'][$key] = $variables['elements'][$key]; } $variables['#cache']['max-age'] = 0; $current_user = \Drupal::currentUser(); /** @var \Drupal\privatemsg\Entity\PrivatemsgMessage $message */ $message = $variables['elements']['#privatemsg_message']; if ($message) { $message_deleted_time = $message->getMarkAsDeletedTime(); if ($message_deleted_time) { $variables['marked_as_deleted'] = TRUE; $message_owner = User::load($message->getOwnerId()); if ($message_owner) { $variables['message_owner'] = $message_owner->getAccountName(); } $variables['message_deleted_time'] = \Drupal::service('date.formatter')->format($message_deleted_time, 'medium', NULL); if ($current_user->hasPermission('privatemsg view deleted messages')) { $variables['can_view_deleted_messages'] = TRUE; } return; } /** @var \Drupal\privatemsg\PrivateMsgServiceInterface $privatemsg_service */ $privatemsg_service = \Drupal::service('privatemsg.common'); /** @var \Drupal\privatemsg\Entity\PrivatemsgThread $thread */ $thread = $privatemsg_service->getThreadFromMessage($message->id(), $current_user->id()); if ($thread) { if ($current_user->hasPermission('privatemsg delete own messages') && $message->getOwnerId() === $current_user->id()) { $url_object = Url::fromRoute('privatemsg.delete_message', [ 'mid' => $message->id(), 'thread_id' => $thread->id(), ]); if ($url_object) { $variables['delete_message_link'] = $url_object->toString(); } } if ($current_user->hasPermission('privatemsg block users') && $message->getOwnerId() !== $current_user->id()) { $members = $thread->getMembers(); if (count($members) < 3) { $url_object = Url::fromRoute('privatemsg.block_user', [ 'user' => $message->getOwnerId(), ]); $variables['block_user_id'] = $message->getOwnerId(); if ($url_object) { $variables['block_user'] = $url_object->toString(); } $can_be_blocked = $privatemsg_service->canBeBlocked($message->getOwnerId()); if ($can_be_blocked) { $isBlocked = $privatemsg_service->isUserBlocked($current_user->id(), $message->getOwnerId()); $isBlocked ? $variables['block_user_text'] = t('unblock') : $variables['block_user_text'] = t('block'); } } } } } } /** * Implements hook_views_data_alter(). */ function privatemsg_field_views_data_alter(array &$data) { $data['views']['privatemsg_messages_counter_views_field'] = [ 'title' => t('Count of messages in the thread.'), 'group' => t('PrivateMsg Thread'), 'help' => t('Count of messages in the thread.'), 'field' => [ 'id' => 'privatemsg_messages_counter_views_field', ], ]; return $data; } /** * Implements hook_views_pre_render(). */ function privatemsg_views_pre_render(ViewExecutable $view) { if ($view->storage->id() === 'all_privatemsg_threads') { $view->element['#attached']['library'][] = 'privatemsg/privatemsg'; } } /** * Implements hook_preprocess_HOOK(). */ function privatemsg_preprocess_views_view_table(&$variables) { $view = $variables['view']; if ($view->id() === 'all_privatemsg_threads' && $view->current_display === 'page_1') { $current_user = \Drupal::entityTypeManager()->getStorage('user')->load(\Drupal::currentUser()->id()); $is_messages_enabled = \Drupal::service('user.data')->get('privatemsg', $current_user->id(), 'enable'); if ($is_messages_enabled) { $rows = $variables['rows']; foreach ($rows as $id => $row) { $entity = $variables['result'][$id]->_entity; $current_user = \Drupal::currentUser(); /** @var \Drupal\privatemsg\PrivateMsgServiceInterface $privatemsg_service */ $privatemsg_service = \Drupal::service('privatemsg.common'); $last_access_time = $privatemsg_service->getThreadGroupLastAccessTime($current_user->id(), $entity->getGroup()); $messages = $entity->getMessages(); foreach ($messages as $message) { if ($last_access_time <= $message->getCreatedTime() && $message->getOwnerId() != $current_user->id()) { $variables['rows'][$id]['attributes']->addClass('privatemsg-unread-thread'); } } } } else { throw new NotFoundHttpException(); } } } /** * Implements hook_cron(). */ function privatemsg_cron() { $days = \Drupal::config('privatemsg.settings')->get('remove_after'); if ($days) { $mark_as_deleted_messages_ids = \Drupal::entityQuery('privatemsg_message') ->accessCheck(FALSE) ->condition('deleted', '', '<>') ->execute(); $messages_to_delete = \Drupal::entityTypeManager()->getStorage('privatemsg_message')->loadMultiple($mark_as_deleted_messages_ids); /** @var \Drupal\privatemsg\Entity\PrivatemsgMessage $message */ foreach ($messages_to_delete as $message) { $remove_after_time = $days * 3600; $current_time = \Drupal::time()->getRequestTime(); $deleted_time = $message->getMarkAsDeletedTime(); if (($deleted_time + $remove_after_time) < $current_time) { $threads = \Drupal::entityTypeManager()->getStorage('privatemsg_thread')->loadByProperties([ 'private_messages' => $message->id(), ]); foreach ($threads as $thread) { /** @var \Drupal\privatemsg\Entity\PrivatemsgThread $thread */ $thread->removeMessageFromThread($message->id()); $thread->save(); $message->delete(); } } } } } /** * Implements hook_form_views_exposed_form_alter(). */ function privatemsg_form_views_exposed_form_alter(&$form, &$form_state, $form_id) { if ($form['#id'] === 'views-exposed-form-all-privatemsg-threads-page-1') { $form['subject']['#title'] = t('Subject'); $form['uid']['#title'] = t('Members'); $form['uid']['#selection_handler'] = 'default:privatemsg_views'; $form['tags_target_id']['#title'] = t('Tags'); if (isset($form['tags_target_id'])) { $options = ['' => (string) \t('- Any -')]; /** @var \Drupal\privatemsg\PrivateMsgServiceInterface $privatemsg_service */ $privatemsg_service = \Drupal::service('privatemsg.common'); $user_threads = $privatemsg_service->getThreadsForUser(\Drupal::currentUser()->id()); foreach ($user_threads as $thread) { $tags[] = $thread->getTags(); } // Remove empty elements. if (!empty($tags)) { $tags = array_filter($tags); // Flat array. $tags = array_merge(...$tags); foreach ($tags as $tag) { $options[$tag->id()] = $tag->getName(); } $form['tags_target_id'] = [ '#type' => 'select', '#title' => \t('Tags'), '#options' => $options, ]; } } } } /** * Implements hook_mail(). */ function privatemsg_mail(string $key, array &$message, array $params) { if ($key === 'privatemsg') { $message['subject'] = $params['subject']; $message['body'][] = $params['message']; } } /** * Implements hook_ENTITY_TYPE_insert(). */ function privatemsg_taxonomy_term_insert(EntityInterface $entity) { if ($entity->bundle() === 'privatemsg_tags' && $entity->get('field_privatemsg_tag_author')->isEmpty()) { $entity->set('field_privatemsg_tag_author', \Drupal::currentUser()->id()); $entity->save(); } } /** * Implements hook_preprocess_HOOK(). */ function privatemsg_preprocess_views_view_field(&$variables) { $view = $variables['view']; $field = $variables['field']; if ($view->id() === 'all_privatemsg_threads' && $view->current_display === 'page_1' && $field->field === 'tags_target_id' && isset($variables['output']) && !empty($variables['output']) ) { $raw_output = $variables['output']->__toString(); $output = str_replace('/taxonomy/term/', '/messages?tags_target_id=', $raw_output); $variables['output'] = Markup::create($output); } if ($view->id() === 'all_privatemsg_threads' && $view->current_display === 'page_1' && $field->field === 'subject' && isset($variables['output']) && !empty($variables['output']) ) { $raw_output = $variables['output']->__toString(); preg_match_all('/]+href=([\'"])(?.+?)\1[^>]*>/i', $raw_output, $result); if (!empty($result)) { $link = $result['href'][0]; /** @var \Drupal\privatemsg\Entity\PrivatemsgThread $thread */ $thread = $variables["row"]->_entity; if ($link && $thread) { $privatemsg_service = \Drupal::service('privatemsg.common'); $last_access_time = $privatemsg_service->getThreadGroupLastAccessTime(\Drupal::currentUser()->id(), $thread->getGroup()); $messages = $thread->getMessages(); $last_unread_message_number = 1; // Find last unread message if it exists. foreach ($messages as $key => $message) { if ($last_access_time <= $message->getCreatedTime() && $message->getOwnerId() !== \Drupal::currentUser()->id()) { $last_unread_message_number = $key; break; } } // If not new unread messages than get page only. if ($last_unread_message_number === 1) { $page = (int) (count($messages) / 50); } // Get page of last unread message. else { $page = (int) ($last_unread_message_number / 50); } if ($page > 0) { $new_link = $link . '?page=' . $page; $output = str_replace($link, $new_link, $raw_output); $variables['output'] = Markup::create($output); } } } } } /** * Implements hook_views_query_alter(). */ function privatemsg_views_query_alter(ViewExecutable $view, QueryPluginBase $query) { if (($view->storage->id() === 'all_privatemsg_threads')) { // Remove duplicates. // See https://www.drupal.org/project/paragraphs/issues/2941499 // And https://www.drupal.org/project/drupal/issues/2993688 $query->addField('privatemsg_thread', 'id', '', ['function' => 'groupby']); $query->addGroupBy('id'); } } /** * Implements hook_form_FORM_ID_alter(). */ function privatemsg_form_views_form_all_privatemsg_threads_page_1_alter(&$form, FormStateInterface $form_state, $form_id) { $form['header']['views_bulk_operations_bulk_form']['select_all']['#access'] = FALSE; $form['header']['views_bulk_operations_bulk_form']['multipage']['#access'] = FALSE; $form['actions']['#access'] = FALSE; } /** * Implements hook_form_FORM_ID_alter(). */ function privatemsg_form_user_form_alter(&$form, FormStateInterface $form_state) { $form['privatemsg'] = [ '#type' => 'details', '#title' => t('Private Messages'), '#open' => TRUE, '#weight' => 5, ]; $account = $form_state->getFormObject()->getEntity(); if (!\Drupal::currentUser()->isAnonymous() && $account->id()) { $privatemsg_enable = \Drupal::service('user.data')->get('privatemsg', $account->id(), 'enable'); $privatemsg_notify = \Drupal::service('user.data')->get('privatemsg', $account->id(), 'notify'); } $form['privatemsg']['privatemsg_enable'] = [ '#type' => 'checkbox', '#title' => t('Enable private messages'), '#description' => t('Disabling private messages prevents you from sending or receiving messages from other users.'), '#default_value' => $privatemsg_enable ?? TRUE, ]; $form['privatemsg']['privatemsg_notify'] = [ '#type' => 'checkbox', '#title' => t('Receive email notification for incoming private messages'), '#default_value' => $privatemsg_notify ?? TRUE, ]; $form['actions']['submit']['#submit'][] = 'privatemsg_user_profile_form_submit'; } /** * Submit callback for the user profile form to save the privatemsg setting. */ function privatemsg_user_profile_form_submit($form, FormStateInterface $form_state) { $account = $form_state->getFormObject()->getEntity(); if ($account->id() && $form_state->hasValue('privatemsg_enable')) { \Drupal::service('user.data')->set('privatemsg', $account->id(), 'enable', (int) $form_state->getValue('privatemsg_enable')); } if ($account->id() && $form_state->hasValue('privatemsg_notify')) { \Drupal::service('user.data')->set('privatemsg', $account->id(), 'notify', (int) $form_state->getValue('privatemsg_notify')); } }