block_inactive_users-8.x-1.4/src/InactiveUsersHandler.php

src/InactiveUsersHandler.php
<?php

namespace Drupal\block_inactive_users;

use Drupal\Component\Datetime\TimeInterface;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Language\LanguageManagerInterface;
use Drupal\Core\Logger\LoggerChannelFactoryInterface;
use Drupal\Core\Mail\MailManagerInterface;
use Drupal\Core\State\StateInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\Url;
use Drupal\Core\Utility\Token;
use Drupal\user\Entity\User;
use Drupal\user\UserInterface;

/**
 * The InactiveUsersHandler Class.
 *
 * @category Drupal
 * @package Drupal\block_inactive_users
 * @author Rodrigue Tusse
 * @license GPL-3.0+ https://www.gnu.org/licenses/gpl-3.0.txt
 * @link https://www.drupal.org/project/block_inactive_users
 */
class InactiveUsersHandler {

  use StringTranslationTrait;

  const FORM_SETTINGS_CONFIG_OBJ_NAME = "block_inactive_users.settings";
  const LOGGER_CHANNEL = "block_inactive_users";

  /**
   * A config factory service.
   *
   * @var \Drupal\Core\Config\ConfigFactoryInterface
   */
  protected $configFactoryService;

  /**
   * A logger instance.
   *
   * @var \Drupal\Core\Logger\LoggerChannelFactoryInterface
   */
  protected $logger;

  /**
   * An language manager instance.
   *
   * @var \Drupal\Core\Language\LanguageManagerInterface
   */
  protected $languageManager;

  /**
   * A time service.
   *
   * @var \Drupal\Component\Datetime\TimeInterface
   */
  protected $timeService;

  /**
   * The user storage interface.
   *
   * @var \Drupal\user\UserStorageInterface
   */
  protected $userStorage;

  /**
   * The module email configuration.
   *
   * @var \Drupal\Core\Config\ImmutableConfig
   */
  protected $emailConfig;

  /**
   * The state store.
   *
   * @var Drupal\Core\State\StateInterface
   */
  protected $state;

  /**
   * The token replacement instance.
   *
   * @var \Drupal\Core\Utility\Token
   */
  protected $token;

  /**
   * The mail manager service.
   *
   * @var \Drupal\Core\Mail\MailManagerInterface
   */
  protected $mailManager;

  /**
   * Constructor.
   *
   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
   *   The config factory service.
   * @param \Drupal\Core\Logger\LoggerChannelFactoryInterface $loggerChannelFactory
   *   The logger channel factory.
   * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
   *   The language manager service.
   * @param \Drupal\Component\Datetime\TimeInterface $time_service
   *   The time service.
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
   *   The entity type manager.
   * @param \Drupal\Core\State\StateInterface $state
   *   The state service.
   * @param \Drupal\Core\Utility\Token $token
   *   The token service.
   * @param \Drupal\Core\Mail\MailManagerInterface $mail_manager
   *   The mail manager service.
   */
  public function __construct(
    ConfigFactoryInterface $config_factory,
    LoggerChannelFactoryInterface $loggerChannelFactory,
    LanguageManagerInterface $language_manager,
    TimeInterface $time_service,
    EntityTypeManagerInterface $entity_type_manager,
    StateInterface $state,
    Token $token,
    MailManagerInterface $mail_manager,
  ) {

    $this->configFactoryService = $config_factory;
    $this->logger = $loggerChannelFactory;
    $this->languageManager = $language_manager;
    $this->timeService = $time_service;
    $this->userStorage = $entity_type_manager->getStorage('user');
    $this->emailConfig = $this->configFactoryService->get(self::FORM_SETTINGS_CONFIG_OBJ_NAME);
    $this->state = $state;
    $this->token = $token;
    $this->mailManager = $mail_manager;
  }

  /**
   * Disables an inactive user account.
   *
   * @param \Drupal\user\Entity\User $user
   *   A user object.
   * @param bool $sendmail
   *   Boolean to trigger email.
   *
   * @return \Drupal\user\Entity\User
   *   Returns a blocked user object.
   *
   * @throws \Drupal\Core\Entity\EntityStorageException
   */
  public function disableInactiveUsersStatus(User $user, $sendmail = TRUE) {

    $user->block();
    $user->save();
    $this->logger->get(self::LOGGER_CHANNEL)->info($user->getAccountName() . ' has been disabled.');

    if ($sendmail) {

      $activation_link = $this->createReactivationUrl($user);

      // Sends email notification.
      $this->mailUser(
            $this->emailConfig->get('block_inactive_users_from_email'),
            $user,
            $this->emailConfig->get('block_inactive_users_email_subject'),
            $this->emailConfig->get('block_inactive_users_email_content'),
            $activation_link
        );
    }

    return $user;

  }

  /**
   * Takes 2 timestamps and returns the interval as days or months.
   *
   * @param int $start
   *   A timestamp of the start time (e.g., last access or created time).
   * @param int $end
   *   A timestamp of the end time (e.g., current time).
   * @param string $unit
   *   The unit for the interval: 'months' (default) or 'days'.
   *
   * @return int
   *   Returns the interval in the requested unit.
   *
   * @throws \Exception
   */
  public function timestampdiff($start, $end, $unit = 'months') {
    if ($unit === 'days') {
      return floor(($end - $start) / 86400);
    }
    // Default: months.
    $begin = new \DateTime("@$start");
    $finish = new \DateTime("@$end");
    $interval = $begin->diff($finish);
    return ($interval->y * 12) + ($interval->m);
  }

  /**
   * Sends a email notification.
   *
   * @param string $from
   *   From email address.
   * @param \Drupal\user\Entity\User $user
   *   Users first name.
   * @param string $message_subject
   *   Message subject field.
   * @param string $message_content
   *   Email template.
   * @param string $activation_link
   *   Url to re-activate user.
   *
   * @return bool
   *   Returns true if mail was sent successfully.
   */
  public function mailUser($from, $user, $message_subject, $message_content, $activation_link) {

    $days_until_blocked = $this->emailConfig->get('block_inactive_users_days_until_blocked');

    $custom_tokens = [
      '[days-until-blocked]' => $days_until_blocked,
      '[activation-link]' => $activation_link,
    ];

    $from = $this->token->replace($from);

    $data = [];

    $data['params']['headers'] = [
      'Content-Type' => 'text/html',
      'MIME-Version' => '1.0',
      'reply-to' => $from,
      'from' => $this->token->replace('[site:name]') . ' <' . $from . '>',
    ];

    $data['to'] = $user->getEmail();
    $data['langcode'] = $user->getPreferredLangcode();

    $data['params']['subject'] = $this->token->replace(
          $message_subject, [
            'user' => $user,
          ]
      );

    $data['params']['body'] = $this->token->replace(
          $message_content, [
            'user' => $user,
          ]
      );

    // Replace pseudo-tokens.
    array_walk(
          $custom_tokens, function ($value, $token) use (&$data) {
              $data['params']['subject'] = str_replace($token, $value, $data['params']['subject']);
              $data['params']['body'] = str_replace($token, $value, $data['params']['body']);
          }
      );

    $mail = $this->mailManager->mail('block_inactive_users', 'block_inactive_users_warn', $data['to'], $data['langcode'], $data['params'], NULL, TRUE);

    if ($mail['result'] != TRUE) {
      $message = $this->t('There was a problem sending your email notification to @email.', ['@email' => $user->getEmail()]);

      $this->logger->get('mail-log')->error($message);
      return FALSE;
    }
    $message = $this->t('An email notification has been sent to @email.', ['@email' => $user->getEmail()]);
    $this->logger->get('mail-log')->notice($message);

    return FALSE;

  }

  /**
   * Generates a URL to confirm an account reactivation request.
   *
   * @param \Drupal\user\UserInterface $account
   *   The user account object.
   * @param array $options
   *   (optional) A keyed array of settings. Supported options are:
   *   - langcode: A language code to be used when generating locale-sensitive
   *   URLs. If langcode is NULL the users preferred language is used.
   *
   * @return string
   *   A unique URL that may be used to confirm the reactivation of the user
   *   account.
   */
  private function createReactivationUrl(UserInterface $account, array $options = []) {

    $timestamp = $this->timeService->getRequestTime();
    $langcode = $options['langcode'] ?? $account->getPreferredLangcode();
    $url_options = [
      'absolute' => TRUE,
      'language' => $this->languageManager->getLanguage($langcode),
    ];
    return Url::fromRoute(
          'block_inactive_users.reactivate_confirm', [
            'user' => $account->id(),
            'timestamp' => $timestamp,
            'hashed_pass' => user_pass_rehash($account, $timestamp),
          ], $url_options
      )->toString();

  }

  /**
   * Takes 3 parameters to cancel user depending on rules setup.
   *
   * @param string $uid
   *   Uid of the user account being canceled.
   * @param string $block_inactive_users_cancel_email
   *   Block inactive users cancel email.
   * @param string $disable_account_method
   *   Disable account method.
   *
   * @return void
   *   No return value.
   *
   * @throws \Exception
   */
  public function cancelUser($uid, $block_inactive_users_cancel_email, $disable_account_method) {
    user_cancel(
          [
            'user_cancel_notify' => $block_inactive_users_cancel_email,
            'user_cancel_method' => $disable_account_method,
          ], $uid, $disable_account_method
      );
  }

  /**
   * Warn inactive users of their impending block.
   *
   * @return void
   *   No return value.
   */
  public function warn() {
    // Bail if option is not enabled.
    if (!$this->emailConfig->get('block_inactive_users_warn_send_email')) {
      return;
    }

    $users = $this->getUsers();
    $idle_time = $this->configFactoryService
      ->get(self::FORM_SETTINGS_CONFIG_OBJ_NAME)
      ->get('block_inactive_users_idle_time');
    $days_until_blocked = $this->emailConfig->get('block_inactive_users_days_until_blocked');
    $include_never_accessed = $this->emailConfig->get('block_inactive_users_include_never_accessed');
    $current_time = time();
    $current_time_obj = new \Datetime("@$current_time");
    $from = $this->emailConfig->get('block_inactive_users_warn_from_email');
    $subject = $this->emailConfig->get('block_inactive_users_warn_email_subject');
    $template = $this->emailConfig->get('block_inactive_users_warn_email_content');

    foreach ($users as $user) {
      $warned_users = $this->state->get('block_inactive_users.warn') ?: [];

      // Skip users who have already been warned.
      if (in_array($user->id(), $warned_users)) {
        continue;
      }

      $last_access = $user->getLastAccessedTime();

      // Add months from configuration.
      $ban_alert_date = strtotime("+$idle_time months", (int) $last_access);

      // Remove days from ban date.
      $ban_alert_date = strtotime("-$days_until_blocked days", $ban_alert_date);
      $ban_alert_date = new \Datetime("@$ban_alert_date");

      $user_days_until_blocked = $ban_alert_date->diff($current_time_obj)->days;

      $activation_link = $this->createReactivationUrl($user);

      if ($last_access != 0
            && $user_days_until_blocked <= $days_until_blocked
        ) {
        $this->mailUser($from, $user, $subject, $template, $activation_link);

        // Add state so that user doesn't receive multiple emails.
        $this->state->set('block_inactive_users.warn', [...$warned_users, $user->id()]);
      }

      // If option enabled to include blocking of users
      // who have never logged in.
      // Calculate the creation time and block the user if the idle time period
      // has elapsed.
      if ($include_never_accessed == 1
            && $last_access == 0
            && $user_days_until_blocked <= $days_until_blocked
        ) {
        $this->mailUser($from, $user, $subject, $template, $activation_link);

        // Add state so that user doesn't receive multiple emails.
        $this->state->set('block_inactive_users.warn', [...$warned_users, $user->id()]);
      }
    }
  }

  /**
   * Get list of users to be possibly banned.
   *
   * @return \Drupal\user\Entity\User[]
   *   Array of user entities.
   */
  public function getUsers() {
    $exclude_user_roles = $this->emailConfig->get('block_inactive_users_exclude_roles');
    $query = $this->userStorage->getQuery()->accessCheck(TRUE);

    // Only return active users.
    $query->condition('status', 1);

    // Subquery to find users with excluded roles.
    if (!empty($exclude_user_roles)) {
      $subquery = $this->userStorage->getQuery()
        ->condition('roles', $exclude_user_roles, 'IN')
        ->accessCheck(TRUE)
        ->execute();

      // Assuming execute() returns an array of user IDs, adjust as necessary.
      if (!empty($subquery)) {
        $query->condition('uid', $subquery, 'NOT IN');
      }
    }

    // Don't block the admin account.
    $query->condition('uid', 1, '!=');

    $user_ids = $query->execute();

    return $this->userStorage->loadMultiple($user_ids);
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc