simple_account_policy-1.0.0/simple_account_policy.module

simple_account_policy.module
<?php

/**
 * @file
 * Module File.
 *
 * @todo add extra email settings to the site.settings mail form (and store the input in our own config)
 */

use Drupal\Component\Render\PlainTextOutput;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Form\FormState;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Url;
use Drupal\user\Entity\User;
use Drupal\user\UserInterface;

/**
 * Implements hook_help().
 */
function simple_account_policy_help($route_name, RouteMatchInterface $route_match) {
  switch ($route_name) {
    // Main module help for the simple_account_policy module.
    case 'help.page.simple_account_policy':
      $output = '';
      $output .= '<h3>' . t('About') . '</h3>';
      $output .= '<p>' . t('This module implements a simple account policy with the following configurable rules:') . '</p>';
      $output .= '<ul>' . t('<li>Username email and username must match (enforces an email as username)</li>') . '</ul>';
      $output .= '<ul>' . t('<li>Username allowed patterns (usernames must follow this pattern to be valid)</li>') . '</ul>';
      $output .= '<ul>' . t('<li>Username ignore patterns (do not apply policy for usernames matching this pattern)</li>') . '</ul>';
      $output .= '<ul>' . t('<li>Email allowed patterns (email must follow this pattern to be valid)</li>') . '</ul>';
      $output .= '<ul>' . t('<li>Cron check interval (interval at which module will check user policy on all users)</li>') . '</ul>';
      $output .= '<ul>' . t('<li>The inactive period. When users do not login for this period of time, they will be blocked.</li>') . '</ul>';
      $output .= '<ul>' . t('<li>Inactive warning period. If users are about to be blocked, send out a warning mail.</li>') . '</ul>';
      $output .= '<ul>' . t('<li>The warning mail message and subject.</li>') . '</ul>';
      return $output;

    default:
  }
}

/**
 * Implements hook_cron().
 *
 * Block users after a period of time (default 3 months).
 */
function simple_account_policy_cron() {
  /** @var \Drupal\simple_account_policy\AccountPolicyInterface $accountPolicy */
  $accountPolicy = \Drupal::service('simple_account_policy');

  $requestTime = \Drupal::time()->getRequestTime();
  $last_run = \Drupal::state()
    ->get('simple_account_policy.last_cron_run', FALSE);
  $inactive_interval = $accountPolicy->inactiveInterval();
  if (empty($inactive_interval) || ($last_run && ($requestTime - $last_run) < $inactive_interval)) {
    return FALSE;
  }

  // @todo we should do this with a queue to prevent
  //   issues on sites with lots of user.
  $users = User::loadMultiple();

  foreach ($users as $user) {
    if ($accountPolicy->applyPolicy($user) && $accountPolicy->shouldBeDeleted($user)) {
      $accountPolicy->delete($user);
      continue;
    }

    /** @var \Drupal\user\Entity\User $user */
    if ($user->isBlocked()) {
      continue;
    }

    if ($accountPolicy->applyPolicy($user)) {
      if ($accountPolicy->shouldIssueWarning($user)) {
        $accountPolicy->issueWarning($user);
      }
      else {
        if ($accountPolicy->isInactive($user)) {
          $accountPolicy->block($user);
        }
      }
    }

  }

  \Drupal::state()->set('simple_account_policy.last_cron_run', time());
}

/**
 * Implements hook_form_FORM_ID_alter().
 */
function simple_account_policy_form_user_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  $build_info = $form_state->getBuildInfo();

  /** @var \Drupal\user\ProfileForm $profileForm */
  $profileForm = $build_info['callback_object'];

  /** @var \Drupal\user\Entity\User $currentUser */
  $currentUser = $profileForm->getEntity();

  /** @var \Drupal\simple_account_policy\AccountPolicyInterface $accountPolicy */
  $accountPolicy = \Drupal::service('simple_account_policy');

  $username_prevent_changes = ($accountPolicy->getConfiguration()->get('username_prevent_changes') ?? FALSE);
  if (!$currentUser->isNew() && $accountPolicy->applyPolicy($currentUser) && $username_prevent_changes) {
    $form['account']['name']['#disabled'] = TRUE;
  }

  // We need user input here, since fields are not in values (yet).
  $input = $form_state->getUserInput();
  $data = [
    'mail' => $input['mail'] ?? '',
    'name' => $input['name'] ?? '',
  ];
  $errors = empty($pass) ? [] : $accountPolicy->validate($currentUser, $data);
  $policy = $accountPolicy->policy($currentUser, $errors);

  if (!empty($policy['mail'])) {
    $form['account']['mail']['#description'] = $policy['mail'];
  }

  if (!empty($policy['name'])) {
    $form['account']['name']['#description'] = $policy['name'];
  }

  $form['#validate'][] = 'simple_account_policy_form_user_validate';
}

/**
 * Validation function for User form.
 */
function simple_account_policy_form_user_validate($form, FormState $form_state) {

  $build_info = $form_state->getBuildInfo();
  $form = $build_info['callback_object'];
  /** @var \Drupal\user\Entity\User $currentUser */
  $currentUser = $form->getEntity();

  /** @var \Drupal\simple_account_policy\AccountPolicyInterface $accountPolicy */
  $accountPolicy = \Drupal::service('simple_account_policy');

  if ($accountPolicy->applyPolicy($currentUser)) {

    $values = [
      'mail' => $form_state->getValue('mail'),
      'name' => $form_state->getValue('name'),
    ];

    $validation = $accountPolicy->validate($currentUser, $values);

    if (!empty($validation['mail'])) {
      $form_state->setErrorByName('mail', t("The email does not satisfy the account policy rules."));
    }

    if (!empty($validation['name'])) {
      $form_state->setErrorByName('name', t("The user name does not satisfy the account policy rules."));
    }

  }

}

/**
 * Set an extra operations to activate users.
 *
 * @param array $operations
 *   Operations.
 * @param \Drupal\Core\Entity\EntityInterface $entity
 *   Entity.
 */
function simple_account_policy_entity_operation_alter(array &$operations, EntityInterface $entity) {

  $currentUser = \Drupal::currentUser();

  if ($currentUser->hasPermission('account policy activate users') && $entity->getEntityTypeId() == 'user') {
    if ($entity instanceof UserInterface && $entity->isBlocked()) {
      $operations['activate'] = [
        'title' => t('Activate'),
        'weight' => 999,
        'url' => Url::fromRoute('simple_account_policy.activate', ['user' => $entity->id()]),
      ];
    }
  }

  if ($currentUser->hasPermission('account policy block users') && $entity->getEntityTypeId() == 'user') {
    if ($entity instanceof UserInterface && $entity->isActive()) {
      $operations['block'] = [
        'title' => t('Block'),
        'weight' => 999,
        'url' => Url::fromRoute('simple_account_policy.block', ['user' => $entity->id()]),
      ];
    }
  }

}

/**
 * Implements hook_mail().
 */
function simple_account_policy_mail($key, &$message, $params) {
  $token_service = \Drupal::token();
  $language_manager = \Drupal::languageManager();
  $langcode = $message['langcode'];
  $variables = ['user' => $params['account']];

  $language = $language_manager->getLanguage($langcode);
  $original_language = $language_manager->getConfigOverrideLanguage();
  $language_manager->setConfigOverrideLanguage($language);

  $config = \Drupal::config('simple_account_policy.settings');

  $token_options = ['langcode' => $langcode, 'clear' => TRUE];
  $message['subject'] .= PlainTextOutput::renderFromHtml($token_service->replace($config->get($key . '.subject'), $variables, $token_options));
  $message['body'][] = $token_service->replace($config->get($key . '.body'), $variables, $token_options);

  $language_manager->setConfigOverrideLanguage($original_language);
}

/**
 * Helper to print out a readable time period in the past or future.
 *
 * In 5 days
 * 5 days ago
 * ...
 *
 * @param string|int $ts
 *   The timestamp to calculate against the current time.
 * @param string $future_txt
 *   Untranslated text to display if timestamp is in the future.
 *   Use @output to position the resulting period.
 * @param string $past_txt
 *   Untranslated text to display if timestamp is in the past.
 *   Use @output to position the resulting period.
 * @param string $langcode
 *   The langcode to translate the result in, if none given this
 *   is the current language.
 *
 * @return string
 *   String
 */
function simple_account_policy_time_ago($ts, $future_txt = "@output", $past_txt = "@output", $langcode = NULL): string {

  $langcode = $langcode ?? \Drupal::languageManager()
    ->getCurrentLanguage()
    ->getId();

  if (is_string($ts) && !ctype_digit($ts)) {
    $ts = strtotime($ts);
  }

  $diff = time() - $ts;
  if ($diff == 0) {
    $output = t('now', [], ['langcode' => $langcode]);
    // phpcs:disable Drupal.Semantics.FunctionT.NotLiteralString
    return (string) t($future_txt, ['@output' => $output], ['langcode' => $langcode]);
  }
  elseif ($diff > 0) {
    $day_diff = floor($diff / 86400);
    switch (TRUE) {
      case ($day_diff == 0 && $diff < 60):
        $output = t('just now', [], ['langcode' => $langcode]);
        break;

      case ($day_diff == 0 && $diff < 120):
        $output = t('1 minute ago', [], ['langcode' => $langcode]);
        break;

      case ($day_diff == 0 && $diff < 3600):
        $output = t('@time minutes ago', ['@time' => floor($diff / 60)], ['langcode' => $langcode]);
        break;

      case ($day_diff == 0 && $diff < 7200):
        $output = t('1 hour ago', [], ['langcode' => $langcode]);
        break;

      case ($day_diff == 0 && $diff < 86400):
        $output = t('@time hours ago', ['@time' => floor($diff / 3600)], ['langcode' => $langcode]);
        break;

      case ($day_diff == 1):
        $output = t('yesterday', [], ['langcode' => $langcode]);
        break;

      case ($day_diff < 7):
        $output = t('@time days ago', ['@time' => $day_diff], ['langcode' => $langcode]);
        break;

      case ($day_diff < 31):
        $output = t('@time weeks ago', ['@time' => ceil($day_diff / 7)], ['langcode' => $langcode]);
        break;

      case ($day_diff < 60):
        $output = t('last month', [], ['langcode' => $langcode]);
        break;

      default:
        /** @var \Drupal\Core\Datetime\DateFormatterInterface $date_formatter */
        $date_formatter = \Drupal::service('date.formatter');
        $output = $date_formatter->format($ts, 'long');
    }

    // phpcs:disable Drupal.Semantics.FunctionT.NotLiteralString
    return (string) t($past_txt, ['@output' => $output], ['langcode' => $langcode]);
  }
  else {
    $diff = abs($diff);
    $day_diff = floor($diff / 86400);
    switch (TRUE) {
      case ($day_diff == 0 && $diff < 120):
        $output = t('in a minute', [], ['langcode' => $langcode]);
        break;

      case ($day_diff == 0 && $diff < 3600):
        $output = t('in @time minutes', ['@time' => floor($diff / 60)], ['langcode' => $langcode]);
        break;

      case ($day_diff == 0 && $diff < 7200):
        $output = t('in an hour', [], ['langcode' => $langcode]);
        break;

      case ($day_diff == 0 && $diff < 86400):
        $output = t('in @time hours', ['@time' => floor($diff / 3600)], ['langcode' => $langcode]);
        break;

      case ($day_diff == 1):
        $output = t('tomorrow', [], ['langcode' => $langcode]);
        break;

      case ($day_diff < 4):
        /** @var \Drupal\Core\Datetime\DateFormatterInterface $date_formatter */
        $date_formatter = \Drupal::service('date.formatter');
        $output = $date_formatter->format($ts, 'custom', 'l');
        break;

      case ($day_diff < 7 + (7 - intval(date('w')))):
        $output = t('next week', [], ['langcode' => $langcode]);
        break;

      case (ceil($day_diff / 7) < 4):
        $output = t('in @time weeks', ['@time' => ceil($day_diff / 7)], ['langcode' => $langcode]);
        break;

      case (date('n', $ts) == intval(date('n')) + 1):
        $output = t('next month', [], ['langcode' => $langcode]);
        break;

      default:
        /** @var \Drupal\Core\Datetime\DateFormatterInterface $date_formatter */
        $date_formatter = \Drupal::service('date.formatter');
        $output = $date_formatter->format($ts, 'long');
    }

    // phpcs:disable Drupal.Semantics.FunctionT.NotLiteralString
    return (string) t($future_txt, ['@output' => $output], ['langcode' => $langcode]);
  }
}

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

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