You are here

private_message.install in Private Message 8.2

Same filename and directory in other branches
  1. 8 private_message.install

Holds install and update hooks for the Private Message module.

File

private_message.install
View source
<?php

/**
 * @file
 * Holds install and update hooks for the Private Message module.
 */
use Drupal\Core\Database\IntegrityConstraintViolationException;
define('PRIVATE_MESSAGE_UPDATE_LIMIT', 10);
define('PRIVATE_MESSAGE_LAST_STATE', 'wso_scalable_bridge_last');
define('PRIVATE_MESSAGE_THREADS_TABLE', 'private_message_threads');
define('PRIVATE_MESSAGE_MEMBERS_TABLE', 'private_message_thread__members');
define('PRIVATE_MESSAGE_LAST_ACCESS_TABLE', 'private_message_thread__last_access_time');
define('PRIVATE_MESSAGE_LAST_DELETE_TABLE', 'private_message_thread__last_delete_time');
define('PRIVATE_MESSAGE_ACCESS_TIME_TABLE', 'pm_thread_access_time');
define('PRIVATE_MESSAGE_DELETE_TIME_TABLE', 'pm_thread_delete_time');
define('PRIVATE_MESSAGE_HISTORY_TABLE', 'pm_thread_history');

/**
 * Implements hook_uninstall().
 */
function private_message_uninstall() {
  \Drupal::configFactory()
    ->getEditable('core.entity_view_display.user.user.private_message_author')
    ->delete();
  \Drupal::configFactory()
    ->getEditable('core.entity_view_mode.user.private_message_author')
    ->delete();
  \Drupal::configFactory()
    ->getEditable('message.template.private_message_notification')
    ->delete();
  \Drupal::configFactory()
    ->getEditable('core.entity_view_display.message.private_message_notification.mail_body')
    ->delete();
  \Drupal::configFactory()
    ->getEditable('core.entity_view_display.message.private_message_notification.mail_subject')
    ->delete();
  \Drupal::configFactory()
    ->getEditable('core.entity_form_display.message.private_message_notification.default')
    ->delete();
  \Drupal::configFactory()
    ->getEditable('core.entity_view_display.message.private_message_notification.default')
    ->delete();
}

/**
 * Implements hook_update_n().
 */
function private_message_update_8001() {
  $config_factory = \Drupal::configFactory();
  $config_factory
    ->getEditable('private_message.settings')
    ->set('enable_email_notifications', TRUE)
    ->set('send_by_default', TRUE)
    ->save(TRUE);
  $message_notifcation_mail_map = [
    'subject' => 'Private message at [site:name]',
    'body' => "[user:display-name],\n\nYou have received a private message at [site:name] from [private_message:author_name]\n\nThe message is as follows:\n\n[private_message:message]\n\nYou can view the entire thread and reply to this message at:\n\n[private_message_thread:url]\n\n\nThank you,\n\n--  [site:name]",
  ];
  $config_factory
    ->getEditable('private_message.mail')
    ->set('message_notification', $message_notifcation_mail_map)
    ->save(TRUE);
}

/**
 * Add the create private message label.
 */
function private_message_update_8002() {
  $config_factory = \Drupal::configFactory();
  $config_factory
    ->getEditable('private_message.settings')
    ->set('create_message_label', 'Create Private Message')
    ->save(TRUE);
}

/**
 * Implements hook_schema().
 */
function private_message_schema() {
  $schema['pm_thread_history'] = [
    'description' => 'A record of which {users} have read which {node}s.',
    'fields' => [
      'uid' => [
        'description' => 'The {users}.uid that read the {private_message_threads} id.',
        'type' => 'int',
        'not null' => TRUE,
        'default' => 0,
      ],
      'thread_id' => [
        'description' => 'The {private_message_threads}.id that was read.',
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
        'default' => 0,
      ],
      'access_timestamp' => [
        'description' => 'The Unix timestamp at which the read occurred.',
        'type' => 'int',
        'not null' => TRUE,
        'default' => 0,
      ],
      'delete_timestamp' => [
        'description' => 'The Unix timestamp at which the delete occurred.',
        'type' => 'int',
        'not null' => TRUE,
        'default' => 0,
      ],
    ],
    'primary key' => [
      'uid',
      'thread_id',
    ],
    'indexes' => [
      'thread_id' => [
        'thread_id',
      ],
    ],
  ];
  return $schema;
}

/**
 * Add the create private message label.
 */
function private_message_update_8003() {
  $config_factory = \Drupal::configFactory();
  $config_factory
    ->getEditable('private_message.settings')
    ->set('create_message_label', 'Create Private Message')
    ->save(TRUE);
}

/**
 * Install the module shcema.
 */
function private_message_update_8004() {
  $database = \Drupal::database();

  // Create database table.
  if (!$database
    ->schema()
    ->tableExists('pm_thread_history')) {
    $database
      ->schema()
      ->createTable('pm_thread_history', [
      'description' => 'A record of which {users} have read which {private_message_threads}.',
      'fields' => [
        'uid' => [
          'description' => 'The {users}.uid that read the {private_message_threads} id.',
          'type' => 'int',
          'not null' => TRUE,
          'default' => 0,
        ],
        'thread_id' => [
          'description' => 'The {private_message_threads}.id that was read.',
          'type' => 'int',
          'unsigned' => TRUE,
          'not null' => TRUE,
          'default' => 0,
        ],
        'access_timestamp' => [
          'description' => 'The Unix timestamp at which the read occurred.',
          'type' => 'int',
          'not null' => TRUE,
          'default' => 0,
        ],
        'delete_timestamp' => [
          'description' => 'The Unix timestamp at which the delete occurred.',
          'type' => 'int',
          'not null' => TRUE,
          'default' => 0,
        ],
      ],
      'primary key' => [
        'uid',
        'thread_id',
      ],
      'indexes' => [
        'thread_id' => [
          'thread_id',
        ],
      ],
    ]);
  }
}

/**
 * Migrate the records into a new table.
 */
function private_message_update_8005(&$sandbox) {

  // Store last processed thread ID, so the sites with a huge amount of threads
  // will have at least some chances to complete this update in a few runs.
  $last_processed = \Drupal::state()
    ->get(PRIVATE_MESSAGE_LAST_STATE, 0);
  $database = \Drupal::database();
  if (empty($sandbox['max'])) {
    $sandbox['progress'] = 0;
    $sandbox['max'] = $database
      ->select(PRIVATE_MESSAGE_THREADS_TABLE, 't')
      ->condition('t.id', $last_processed, '>')
      ->countQuery()
      ->execute()
      ->fetchField();
  }

  // Select a range of the threads:
  $query = $database
    ->select(PRIVATE_MESSAGE_THREADS_TABLE, 't');
  $query
    ->fields('t', [
    'id',
  ]);
  $query
    ->condition('t.id', $last_processed, '>');
  $query
    ->range(0, PRIVATE_MESSAGE_UPDATE_LIMIT);
  $query
    ->orderBy('t.id');
  $threads = $query
    ->execute()
    ->fetchCol();
  if (empty($threads)) {
    $sandbox['#finished'] = 1;

    // Reset last processed thread.
    \Drupal::state()
      ->delete(PRIVATE_MESSAGE_LAST_STATE);
    $sandbox['messages'][] = t('@total threads processed.', [
      '@total' => $sandbox['max'],
    ]);
    return;
  }

  // Select the thread-member pairs:
  $query = $database
    ->select(PRIVATE_MESSAGE_THREADS_TABLE, 't');
  $query
    ->fields('t', [
    'id',
  ]);
  $query
    ->condition('t.id', $threads, 'IN');
  $query
    ->orderBy('t.id');
  $query
    ->leftJoin(PRIVATE_MESSAGE_MEMBERS_TABLE, 'm', 't.id = m.entity_id');
  $query
    ->fields('m', [
    'members_target_id',
  ]);
  $thread_member_pairs = $query
    ->execute()
    ->fetchAll();
  foreach ($thread_member_pairs as $thread_member_pair) {
    $thread_id = $thread_member_pair->id;
    $member_id = $thread_member_pair->members_target_id;

    // Get the last access timestamp of the member for thread.
    $query = $database
      ->select(PRIVATE_MESSAGE_LAST_ACCESS_TABLE, 'la');
    $query
      ->leftJoin(PRIVATE_MESSAGE_ACCESS_TIME_TABLE, 'at', 'at.id = la.last_access_time_target_id');
    $query
      ->condition('la.entity_id', $thread_id);
    $query
      ->condition('at.owner', $member_id);
    $query
      ->addExpression('MAX(at.access_time)', 'access_time');
    $access_timestamp = $query
      ->execute()
      ->fetchField() ?: 0;

    // Get the last delete timestamp of the member for thread.
    $query = $database
      ->select(PRIVATE_MESSAGE_LAST_DELETE_TABLE, 'ld');
    $query
      ->leftJoin(PRIVATE_MESSAGE_DELETE_TIME_TABLE, 'dt', 'dt.id = ld.last_delete_time_target_id');
    $query
      ->condition('ld.entity_id', $thread_id);
    $query
      ->condition('dt.owner', $member_id);
    $query
      ->addExpression('MAX(dt.delete_time)', 'delete_time');
    $delete_timestamp = $query
      ->execute()
      ->fetchField() ?: 0;
    try {

      // Update the new table with the access/delete time.
      $database
        ->insert(PRIVATE_MESSAGE_HISTORY_TABLE)
        ->fields([
        'uid' => $member_id,
        'thread_id' => $thread_id,
        'access_timestamp' => $access_timestamp,
        'delete_timestamp' => $delete_timestamp,
      ])
        ->execute();
    } catch (IntegrityConstraintViolationException $e) {

      // Just skip if row already exists.
    }
  }
  $sandbox['progress'] += count($threads);
  $sandbox['#finished'] = $sandbox['progress'] / $sandbox['max'];

  // At the end of run update the last processed thread ID.
  $last_processed = end($threads);
  \Drupal::state()
    ->set(PRIVATE_MESSAGE_LAST_STATE, $last_processed);

  // Or reset it when all the threads processed.
  if ($sandbox['#finished'] === 1) {
    \Drupal::state()
      ->delete(PRIVATE_MESSAGE_LAST_STATE);
  }
  $sandbox['messages'][] = t('@current/@total threads processed.', [
    '@count' => $sandbox['progress'],
    '@total' => $sandbox['max'],
  ]);
}

/**
 * Drop the old entity types and field definitions.
 */
function private_message_update_8006(&$sandbox) {
  $entity_update_manager = \Drupal::entityDefinitionUpdateManager();
  foreach ([
    'pm_thread_access_time',
    'pm_thread_delete_time',
  ] as $entity_type_id) {
    $entity_type = $entity_update_manager
      ->getEntityType($entity_type_id);
    $entity_update_manager
      ->uninstallEntityType($entity_type);
  }
  foreach ([
    'last_access_time',
    'last_delete_time',
  ] as $field_name) {
    $definition = $entity_update_manager
      ->getFieldStorageDefinition($field_name, 'private_message_thread');
    $entity_update_manager
      ->uninstallFieldStorageDefinition($definition);
  }
}