You are here

private_message.module in Private Message 8

Same filename and directory in other branches
  1. 8.2 private_message.module

Contains hooks for the private message module.

File

private_message.module
View source
<?php

/**
 * @file
 * Contains hooks for the private message module.
 */
use Drupal\Component\Utility\SafeMarkup;
use Drupal\Component\Utility\Xss;
use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Mail\MailFormatHelper;
use Drupal\Core\Render\Element;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Url;
use Drupal\private_message\Entity\PrivateMessage;

/**
 * Implements hook_entity_extra_field_info().
 */
function private_message_entity_extra_field_info() {
  $private_message_thread_bundles = \Drupal::entityManager()
    ->getBundleInfo('private_message_thread');
  foreach (array_keys($private_message_thread_bundles) as $bundle) {
    $fields['private_message_thread'][$bundle]['display']['last_message'] = [
      'label' => t('Last Message'),
      'description' => t('Displays the last message in the thread'),
      'weight' => 100,
      'visible' => TRUE,
    ];
    $fields['private_message_thread'][$bundle]['display']['private_message_form'] = [
      'label' => t('Form'),
      'description' => t('The form to create a new message'),
      'weight' => 100,
      'visible' => FALSE,
    ];
    $fields['private_message_thread'][$bundle]['display']['delete_link'] = [
      'label' => t('Delete link'),
      'description' => t('The link to delete the thread'),
      'weight' => -100,
      'visible' => TRUE,
    ];
  }
  $private_message_bundles = \Drupal::entityManager()
    ->getBundleInfo('private_message');
  foreach (array_keys($private_message_bundles) as $bundle) {
    $fields['private_message'][$bundle]['form']['members'] = [
      'label' => t('Members'),
      'description' => t('The widget to add members to the private message thread'),
      'weight' => -100,
      'visible' => TRUE,
    ];
  }
  $user_bundles = \Drupal::entityManager()
    ->getBundleInfo('user');
  foreach (array_keys($user_bundles) as $bundle) {
    $fields['user'][$bundle]['display']['linked_username'] = [
      'label' => t('Username (linked if viewer has permission)'),
      'description' => t('Displays the username, linked to the user profile if the viewer has permission to access user profiles'),
      'weight' => 0,
      'visible' => FALSE,
    ];
    $fields['user'][$bundle]['display']['private_message_link'] = [
      'label' => t('Private message thread link'),
      'description' => t('Displays a link to send a private message to the user'),
      'weight' => 0,
      'visible' => FALSE,
    ];
    $fields['user'][$bundle]['form']['private_messages'] = [
      'label' => t('Private messages'),
      'description' => t('Settings related to private messages'),
      'weight' => 0,
      'visible' => TRUE,
    ];
  }
  $node_bundles = \Drupal::entityManager()
    ->getBundleInfo('node');
  foreach (array_keys($node_bundles) as $bundle) {
    $fields['node'][$bundle]['display']['private_message_link'] = [
      'label' => t('Private message thread link'),
      'description' => t('Displays a link to send a private message to the node author'),
      'weight' => 0,
      'visible' => FALSE,
    ];
  }
  $node_bundles = \Drupal::entityManager()
    ->getBundleInfo('comment');
  foreach (array_keys($node_bundles) as $bundle) {
    $fields['comment'][$bundle]['display']['private_message_link'] = [
      'label' => t('Private message thread link'),
      'description' => t('Displays a link to send a private message to the node author'),
      'weight' => 0,
      'visible' => FALSE,
    ];
  }
  return $fields;
}

/**
 * Implements hook_ENTITY_TYPYE_view().
 *
 * @see hook_entity_view()
 */
function private_message_private_message_thread_view(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display, $view_mode) {
  if ($display
    ->getComponent('last_message')) {
    $messages = $entity
      ->getMessages();
    if ($messages) {
      $last_message = array_pop($messages);
      $view_builder = \Drupal::entityManager()
        ->getViewBuilder('private_message');
      $build['last_message'] = $view_builder
        ->view($last_message, 'inbox');
    }
  }
  if ($display
    ->getComponent('private_message_form')) {
    $private_message = PrivateMessage::create();
    $form_object = \Drupal::entityTypeManager()
      ->getFormObject('private_message', 'add')
      ->setEntity($private_message);
    $build['private_message_form'] = Drupal::formBuilder()
      ->getForm($form_object, $entity);
  }
  if ($display
    ->getComponent('delete_link')) {
    $url = Url::fromRoute('entity.private_message_thread.delete_form', [
      'private_message_thread' => $entity
        ->id(),
    ]);
    $build['delete_link'] = [
      '#prefix' => '<div class="private_message_thread_delete_link_wrapper">',
      '#suffix' => '</div>',
      '#type' => 'link',
      '#url' => $url,
      '#title' => t('Delete thread'),
    ];
  }
}

/**
 * Implements hook_ENTITY_TYPYE_view().
 *
 * Adds new elements to the User entity.
 *
 * @see hook_entity_view()
 */
function private_message_user_view(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display, $view_mode) {
  if ($display
    ->getComponent('linked_username')) {
    if (\Drupal::currentUser()
      ->hasPermission('access user profiles')) {
      $url = Url::fromRoute('entity.user.canonical', [
        'user' => $entity
          ->id(),
      ]);
      $build['linked_username'] = [
        '#prefix' => '<p class="username">',
        '#suffix' => '</p>',
        '#type' => 'link',
        '#url' => $url,
        '#title' => $entity
          ->getDisplayName(),
      ];
    }
    else {
      $build['linked_username'] = [
        '#prefix' => '<p class="username">',
        '#suffix' => '</p>',
        '#markup' => $entity
          ->getDisplayName(),
      ];
    }
  }
  if ($display
    ->getComponent('private_message_link')) {
    $current_user = \Drupal::currentUser();
    if ($current_user
      ->isAuthenticated()) {
      if ($current_user
        ->hasPermission('use private messaging system') && $current_user
        ->id() != $entity
        ->id()) {
        $members = [
          $current_user,
          $entity,
        ];
        $thread_id = \Drupal::service('private_message.mapper')
          ->getThreadIdForMembers($members);
        if ($thread_id) {
          $url = Url::fromRoute('entity.private_message_thread.canonical', [
            'private_message_thread' => $thread_id,
          ], [
            'attributes' => [
              'class' => [
                'private_message_link',
              ],
            ],
          ]);
          $build['private_message_link'] = [
            '#type' => 'link',
            '#url' => $url,
            '#title' => t('Send private message'),
            '#prefix' => '<div class="private_message_link_wrapper">',
            '#suffix' => '</div>',
          ];
        }
        else {
          $url = Url::fromRoute('private_message.private_message_create', [], [
            'query' => [
              'recipient' => $entity
                ->id(),
            ],
          ]);
          $build['private_message_link'] = [
            '#type' => 'link',
            '#url' => $url,
            '#title' => t('Send private message'),
            '#prefix' => '<div class="private_message_link_wrapper">',
            '#suffix' => '</div>',
          ];
        }
      }
    }
    else {
      $url = Url::fromRoute('user.login');
      $build['private_message_link'] = [
        '#type' => 'link',
        '#url' => $url,
        '#title' => t('Send private message'),
        '#prefix' => '<div class="private_message_link_wrapper">',
        '#suffix' => '</div>',
      ];
    }
  }
}

/**
 * Implements hook_ENTITY_TYPYE_view().
 *
 * Adds new elements to the Node entity.
 *
 * @see hook_entity_view()
 */
function private_message_node_view(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display, $view_mode) {
  if ($display
    ->getComponent('private_message_link')) {
    $author = $entity
      ->getOwner();
    $current_user = \Drupal::currentUser();
    if ($current_user
      ->isAuthenticated()) {
      if ($current_user
        ->hasPermission('use private messaging system') && $current_user
        ->id() != $author
        ->id()) {
        $members = [
          $current_user,
          $author,
        ];
        $thread_id = \Drupal::service('private_message.mapper')
          ->getThreadIdForMembers($members);
        if ($thread_id) {
          $url = Url::fromRoute('entity.private_message_thread.canonical', [
            'private_message_thread' => $thread_id,
          ], [
            'attributes' => [
              'class' => [
                'private_message_link',
              ],
            ],
          ]);
          $build['private_message_link'] = [
            '#type' => 'link',
            '#url' => $url,
            '#title' => t('Send private message to author'),
            '#prefix' => '<div class="private_message_link_wrapper">',
            '#suffix' => '</div>',
          ];
        }
        else {
          $url = Url::fromRoute('private_message.private_message_create', [], [
            'query' => [
              'recipient' => $author
                ->id(),
            ],
          ]);
          $build['private_message_link'] = [
            '#type' => 'link',
            '#url' => $url,
            '#title' => t('Send private message to author'),
            '#prefix' => '<div class="private_message_link_wrapper">',
            '#suffix' => '</div>',
          ];
        }
      }
    }
    else {
      $url = Url::fromRoute('user.login');
      $build['private_message_link'] = [
        '#type' => 'link',
        '#url' => $url,
        '#title' => t('Send private message'),
        '#prefix' => '<div class="private_message_link_wrapper">',
        '#suffix' => '</div>',
      ];
    }
  }
}

/**
 * Implements hook_ENTITY_TYPYE_view().
 *
 * Adds new elements to the Comment entity.
 *
 * @see hook_entity_view()
 */
function private_message_comment_view(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display, $view_mode) {
  if ($display
    ->getComponent('private_message_link')) {
    $author = $entity
      ->getOwner();
    $current_user = \Drupal::currentUser();
    if ($current_user
      ->isAuthenticated()) {
      if ($current_user
        ->hasPermission('use private messaging system') && $current_user
        ->id() != $author
        ->id()) {
        $members = [
          $current_user,
          $author,
        ];
        $thread_id = \Drupal::service('private_message.mapper')
          ->getThreadIdForMembers($members);
        if ($thread_id) {
          $url = Url::fromRoute('entity.private_message_thread.canonical', [
            'private_message_thread' => $thread_id,
          ], [
            'attributes' => [
              'class' => [
                'private_message_link',
              ],
            ],
          ]);
          $build['private_message_link'] = [
            '#type' => 'link',
            '#url' => $url,
            '#title' => t('Send private message'),
            '#prefix' => '<div class="private_message_link_wrapper">',
            '#suffix' => '</div>',
          ];
        }
        else {
          $url = Url::fromRoute('private_message.private_message_create', [], [
            'query' => [
              'recipient' => $author
                ->id(),
            ],
          ]);
          $build['private_message_link'] = [
            '#type' => 'link',
            '#url' => $url,
            '#title' => t('Send private message to author'),
            '#prefix' => '<div class="private_message_link_wrapper">',
            '#suffix' => '</div>',
          ];
        }
      }
    }
    else {
      $url = Url::fromRoute('user.login');
      $build['private_message_link'] = [
        '#type' => 'link',
        '#url' => $url,
        '#title' => t('Send private message'),
        '#prefix' => '<div class="private_message_link_wrapper">',
        '#suffix' => '</div>',
      ];
    }
  }
}

/**
 * Implements hook_form_alter().
 */
function private_message_form_alter(&$form, FormStateInterface $form_state, $form_id) {

  // Act on any implementation of the private message entity form. This form
  // can potentially exist multiple times on a page, so the form ID will be
  // dynamic in such a case.
  if (preg_match('/^private_message_add_form/', $form_id)) {

    // The form is only ajaxified if/when thread_members has been set.
    if ($form_state
      ->get('thread_members')) {

      // Add a unique wrapper around the entire form. The build ID will always
      // be unique.
      $form['#prefix'] = '<div id="' . $form['#build_id'] . '">';
      $form['#suffix'] = '</div>';

      // Set the wrapper to the #ajax on the form button.
      $form['actions']['submit']['#ajax']['wrapper'] = $form['#build_id'];

      // Ensure ajax loaded buttons have a unique ID on every ajax load.
      $form['actions']['submit-' . \Drupal::time()
        ->getRequestTime()] = $form['actions']['submit'];
      $form['actions']['submit']['#access'] = FALSE;
    }
  }
}

/**
 * Implements hook_form_FORM_ID_alter().
 *
 * Add private message module specific form elements to the user form.
 *
 * @see hook_form_alter()
 */
function private_message_form_user_form_alter(array &$form, FormStateInterface $form_state) {
  $config = \Drupal::config('private_message.settings');

  // Get the user whose account is being modified.
  $user = $form_state
    ->getFormObject()
    ->getEntity();

  // The form elements are only added if/when email notifications have been
  // added, and the user being edited has permission to use the private message
  // system.
  if ($config
    ->get('enable_email_notifications') && $user
    ->hasPermission('use private messaging system')) {
    $form['private_messages'] = [
      '#type' => 'fieldset',
      '#title' => t('Private Messages'),
      '#tree' => TRUE,
    ];

    // User specific settings are stored and retrieved using the UserData
    // service.
    $user_data = \Drupal::service('user.data');
    $user_setting = $user_data
      ->get('private_message', $user
      ->id(), 'email_notification');

    // If the user has not set a value, the system-wide default is used.
    $default_value = is_numeric($user_setting) ? $user_setting : $config
      ->get('send_by_default');
    $form['private_messages']['email_notification'] = [
      '#type' => 'checkbox',
      '#title' => t('Email notification of private messages'),
      '#default_value' => $default_value,
    ];

    // Add a custom submit handler so the form values can be saved.
    $form['actions']['submit']['#submit'][] = 'private_message_user_form_submit';
  }
}

/**
 * Custom submit handler, saves user settings for the private message module.
 *
 * @see private_message_form_user_form_alter()
 */
function private_message_user_form_submit(array &$form, FormStateInterface $form_state) {

  // Get the user whose account object is being modified.
  $user = $form_state
    ->getFormObject()
    ->getEntity();
  $user_data = \Drupal::service('user.data');

  // Save the submitted data to the user's UserData.
  $user_data
    ->set('private_message', $user
    ->id(), 'email_notification', $form_state
    ->getValue([
    'private_messages',
    'email_notification',
  ]));
}

/**
 * Implements hook_form_FORM_ID_alter().
 *
 * Adds private message emails to the configuration form so that administrators
 * can modify the email as necessary.
 *
 * @see hook_form_alter()
 * @see \Drupal\user\ProfileForm
 */
function private_message_form_user_admin_settings_alter(array &$form, FormStateInterface $form_state) {
  $config = \Drupal::config('private_message.settings');
  $mail_config = \Drupal::config('private_message.mail');

  // Only add the email to the form if private message email notifications
  // have been enabled.
  if ($config
    ->get('enable_email_notifications')) {

    // List the available tokens.
    $private_message_token_help = t('Available variables are: [site:name], [site:url], [user:display-name], [user:account-name], [user:mail], [site:login-url], [site:url-brief], [user:edit-url], [user:one-time-login-url], [user:cancel-url], [private_message:id], [private_message:author-name], [private_message:message], [private_message:url], [private_message:created], [private_message_thread:id], [private_message_thread:], [private_message_thread:url], [private_message_thread:updated].');
    $form['email_private_message'] = [
      '#type' => 'details',
      '#title' => t('Private message notification'),
      '#description' => t('Edit the notification mail sent to users when they receive a private message') . $private_message_token_help,
      '#group' => 'email',
      '#tree' => TRUE,
    ];
    $form['email_private_message']['settings'] = [
      '#type' => 'container',
    ];
    $form['email_private_message']['settings']['user_mail_private_message_notification_subject'] = [
      '#type' => 'textfield',
      '#title' => t('Subject'),
      '#default_value' => $mail_config
        ->get('message_notification.subject'),
      '#maxlength' => 180,
    ];
    $form['email_private_message']['settings']['user_mail_private_message_notification_body'] = [
      '#type' => 'textarea',
      '#title' => t('Body'),
      '#rows' => 17,
      '#default_value' => $mail_config
        ->get('message_notification.body'),
    ];
    $form['#submit'][] = 'private_message_user_admin_settings_submit';
  }
}

/**
 * Submit handler, saves alterations to private message emails.
 *
 * @see private_message_form_user_admin_settings_alter()
 * @see \Drupal\user\ProfileForm
 */
function private_message_user_admin_settings_submit(array &$form, FormStateInterface $form_state) {
  \Drupal::service('config.factory')
    ->getEditable('private_message.mail')
    ->set('message_notification.subject', $form_state
    ->getValue([
    'email_private_message',
    'settings',
    'user_mail_private_message_notification_subject',
  ]))
    ->set('message_notification.body', $form_state
    ->getValue([
    'email_private_message',
    'settings',
    'user_mail_private_message_notification_body',
  ]))
    ->save();
}

/**
 * Implements hook_mail().
 */
function private_message_mail($key, &$message, $params) {
  if ($key == 'message_notification') {
    $token = \Drupal::token();
    $mail_config = \Drupal::config('private_message.mail');
    $message_subject = $mail_config
      ->get('message_notification.subject');
    $message_body = $mail_config
      ->get('message_notification.body');
    $data['user'] = $params['member'];
    $data['private_message'] = $params['private_message'];
    $data['private_message_thread'] = $params['private_message_thread'];
    $message['subject'] = $token
      ->replace($message_subject, $data);
    $body = $token
      ->replace($message_body, $data);
    $message['from'] = \Drupal::config('system.site')
      ->get('mail');
    $message['subject'] = SafeMarkup::checkPlain($message['subject']);
    $message['body'][] = MailFormatHelper::htmlToText(Xss::filter($body));
  }
}

/**
 * Implements hook_theme().
 */
function private_message_theme() {
  return [
    'private_message_thread' => [
      'render element' => 'elements',
    ],
    'private_message' => [
      'render element' => 'elements',
    ],
    'private_message_notification_block' => [
      'variables' => [
        'new_message_count' => 0,
      ],
      'file' => 'private_message.theme.inc',
    ],
  ];
}

/**
 * Prepares variables for private_message_thread templates.
 *
 * Default template: private-message-thread.html.twig.
 *
 * @param array $variables
 *   An associative array containing:
 *   - elements: An array of elements to display in view mode.
 *   - private_message_thread: The private messsage thread object.
 *   - view_mode: View mode; e.g., 'full', 'teaser', etc.
 */
function template_preprocess_private_message_thread(array &$variables) {
  $variables['view_mode'] = $variables['elements']['#view_mode'];

  // Provide a distinct $teaser boolean.
  $variables['private_message_thread'] = $variables['elements']['#private_message_thread'];
  $private_message_thread = $variables['private_message_thread'];
  $variables['last_update'] = drupal_render($variables['elements']['updated']);
  $variables['url'] = $private_message_thread
    ->url('canonical', [
    'language' => $private_message_thread
      ->language(),
  ]);

  // Helpful $content variable for templates.
  $variables += [
    'content' => [],
  ];
  foreach (Element::children($variables['elements']) as $key) {
    $variables['content'][$key] = $variables['elements'][$key];
  }
}

/**
 * Prepares variables for private_message templates.
 *
 * Default template: private-message.html.twig.
 *
 * @param array $variables
 *   An associative array containing:
 *   - elements: An array of elements to display in view mode.
 *   - private_message: The private messsage object.
 *   - view_mode: View mode; e.g., 'full', 'teaser', etc.
 */
function template_preprocess_private_message(array &$variables) {
  $variables['view_mode'] = $variables['elements']['#view_mode'];

  // Provide a distinct $teaser boolean.
  $variables['private_message'] = $variables['elements']['#private_message'];
  $private_message = $variables['private_message'];
  $variables['url'] = $private_message
    ->url('canonical', [
    'language' => $private_message
      ->language(),
  ]);

  // Helpful $content variable for templates.
  $variables += [
    'content' => [],
  ];
  foreach (Element::children($variables['elements']) as $key) {
    $variables['content'][$key] = $variables['elements'][$key];
  }
}

/**
 * Implements hook_help().
 */
function private_message_help($route_name, RouteMatchInterface $route_match) {
  switch ($route_name) {
    case 'help.page.private_message':
      return t('<p>A private message system for users to send messages to each other. It has been written to be fully extendable using Drupal 8 APIs.</p>
        <p>See the <a href=":project_page">project page on Drupal.org</a> for more details.</p>', [
        ':project_page' => 'https://www.drupal.org/project/private_message',
      ]);
  }
}

/**
 * Implements hook_preprocess_field().
 *
 * Adds a custom class to the field that can be targeted, as the default classes
 * may be altered in themes/templates, and therefore should not be depended
 * upon.
 */
function private_message_preprocess_field__private_message_thread__private_messages(&$vars) {
  foreach (array_keys($vars['items']) as $index) {
    $vars['items'][$index]['attributes']
      ->setAttribute('class', 'private-message-wrapper');
  }
}

/**
 * Implements template_preprocess_container().
 *
 * Adds a custom class to the containers that can be targeted, as the default
 * classes may be altered in themes/templates, and therefore should not be
 * depended upon.
 */
function private_message_preprocess_container(&$vars) {
  if (!empty($vars['element']['#id'])) {
    if (strpos('edit-members-wrapper', $vars['element']['#id']) === 0) {

      // Add a custom class to the private message members widget container.
      $vars['attributes']['class'][] = 'private_message_members_widget_default_wrapper';
    }
    elseif (strpos('edit-message-wrapper', $vars['element']['#id']) === 0) {

      // Add a custom class to the private message message widget container.
      $vars['attributes']['class'][] = 'private_message_message_widget_default_wrapper';
    }
  }
}

Functions

Namesort descending Description
private_message_comment_view Implements hook_ENTITY_TYPYE_view().
private_message_entity_extra_field_info Implements hook_entity_extra_field_info().
private_message_form_alter Implements hook_form_alter().
private_message_form_user_admin_settings_alter Implements hook_form_FORM_ID_alter().
private_message_form_user_form_alter Implements hook_form_FORM_ID_alter().
private_message_help Implements hook_help().
private_message_mail Implements hook_mail().
private_message_node_view Implements hook_ENTITY_TYPYE_view().
private_message_preprocess_container Implements template_preprocess_container().
private_message_preprocess_field__private_message_thread__private_messages Implements hook_preprocess_field().
private_message_private_message_thread_view Implements hook_ENTITY_TYPYE_view().
private_message_theme Implements hook_theme().
private_message_user_admin_settings_submit Submit handler, saves alterations to private message emails.
private_message_user_form_submit Custom submit handler, saves user settings for the private message module.
private_message_user_view Implements hook_ENTITY_TYPYE_view().
template_preprocess_private_message Prepares variables for private_message templates.
template_preprocess_private_message_thread Prepares variables for private_message_thread templates.