user_registration_reminder-1.x-dev/src/Form/SettingsForm.php
src/Form/SettingsForm.php
<?php
declare(strict_types=1);
namespace Drupal\user_registration_reminder\Form;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Form\ConfigFormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\RendererInterface;
use Drupal\user_registration_reminder\Manager;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Configure User registration reminder settings for this site.
*/
final class SettingsForm extends ConfigFormBase {
/**
* SettingsForm constructor.
*
* @param \Drupal\Core\Extension\ModuleHandlerInterface $moduleHandler
* The Module Handler service.
* @param \Drupal\Core\Render\RendererInterface $renderer
* The Renderer service.
* @param \Drupal\user_registration_reminder\Manager $userRegistrationReminderManager
* The User Registration Reminder Manager
*/
public function __construct(protected ModuleHandlerInterface $moduleHandler, protected RendererInterface $renderer, protected Manager $userRegistrationReminderManager) {
}
/**
* {@inheritDoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('module_handler'),
$container->get('renderer'),
$container->get('user_registration_reminder.manager'),
);
}
/**
* {@inheritdoc}
*/
public function getFormId(): string {
return 'user_registration_reminder_settings';
}
/**
* {@inheritdoc}
*/
protected function getEditableConfigNames(): array {
return ['user_registration_reminder.settings'];
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state): array {
$config = $this->config('user_registration_reminder.settings');
// Provide token browser if the token module is installed:
$tokenModuleInstalled = $this->moduleHandler->moduleExists('token');
if ($tokenModuleInstalled) {
$token_tree = [
'#theme' => 'token_tree_link',
'#token_types' => ['user'],
];
$rendered_token_tree = $this->renderer->render($token_tree);
}
else {
$rendered_token_tree = $this->t('To use tokens, install the <a href="https://www.drupal.org/project/token" target="_blank">Token</a> module.');
}
$inactiveRegistrationUsers = $this->userRegistrationReminderManager->getInactiveRegistrationUsers();
$inactiveRegistrationUsersCount = count($inactiveRegistrationUsers);
$this->messenger()->addStatus($this->formatPlural($inactiveRegistrationUsersCount, '%count active user registered, who never logged in and exceeds at least the first reminder delay.', '%count active users registered, who never logged in and exceeded at least the first reminder delay.', [
'%count' => $inactiveRegistrationUsersCount,
]));
$form['enabled'] = [
'#type' => 'checkbox',
'#title' => $this->t('Enable user registration reminder'),
'#default_value' => $config->get('enabled') ?? FALSE,
];
$form['reminder_escalations'] = [
'#type' => 'fieldset',
'#tree' => TRUE,
'#title' => $this->t('Reminder escalation steps'),
];
$reminderEscalations = $config->get('reminder_escalations');
// Note that currently the number of reminders is controlled via the initial
// settings.yml installation that pre-provides three steps.
// This might become more dynamic (or a setting) one day, if needed.
foreach ($reminderEscalations as $i => $escalation) {
// For users - programmers count from zero ;)!
$visibleStepCount = $i + 1;
$form['reminder_escalations'][$i] = [
'#type' => 'fieldset',
'#title' => $this->t('Escalation step #@i', ['@i' => $visibleStepCount]),
];
$form['reminder_escalations'][$i]['delay'] = [
'#type' => 'number',
'#required' => TRUE,
'#title' => $this->t('Escalation delay (days) #@i', ['@i' => $visibleStepCount]),
'#default_value' => self::secondsToDays($escalation['delay']) ?? 1,
'#step' => 1,
'#min' => 1,
'#description' => $this->t('@i. reminder email delay after the previous one (or registration). Set to zero (0) to disable.', ['@i' => $visibleStepCount]),
];
$form['reminder_escalations'][$i]['email_subject'] = [
'#type' => 'textfield',
'#required' => TRUE,
'#title' => $this->t('Reminder email subject #@i', ['@i' => $visibleStepCount]),
'#default_value' => $escalation['email_subject'] ?: '',
'#description' => $this->t(
'The subject of the reminder email to send.<br /><em>You may also use tokens. Empty tokens will be cleared. @browse_tokens_link</em>', [
'@browse_tokens_link' => $rendered_token_tree,
]
),
'#states' => [
'invisible' => [
':input[name="reminder_escalations[' . $i . '][delay]"]' => ['value' => 0],
],
],
];
$form['reminder_escalations'][$i]['email_body'] = [
'#type' => 'textarea',
'#required' => TRUE,
'#title' => $this->t('Reminder email body #@i', ['@i' => $visibleStepCount]),
'#default_value' => $escalation['email_body'] ?: '',
'#description' => $this->t(
'The body of the reminder email to send.<br /><em>You may also use tokens. Empty tokens will be cleared. @browse_tokens_link</em>', [
'@browse_tokens_link' => $rendered_token_tree,
]
),
'#states' => [
'invisible' => [
':input[name="reminder_escalations[' . $i . '][delay]"]' => ['value' => 0],
],
],
];
}
$form['final_action'] = [
'#type' => 'fieldset',
'#tree' => TRUE,
'#title' => $this->t('Final action'),
'#description' => $this->t('The final action is taken after all escalation steps were executed for a user without login.'),
];
$form['final_action']['delay'] = [
'#type' => 'number',
'#required' => TRUE,
'#title' => $this->t('Final action delay (days)'),
'#default_value' => self::secondsToDays($config->get('final_action.delay')) ?? 7,
'#step' => 1,
'#min' => 1,
'#description' => $this->t('Final action delay after the final reminder email (@i.). Set to zero (0) to disable.', ['@i' => $visibleStepCount]),
];
$form['final_action']['action'] = [
'#type' => 'radios',
'#required' => TRUE,
'#title' => $this->t('Final action'),
'#options' => [
'none' => $this->t('None'),
'block' => $this->t('Block user'),
'delete' => $this->t('Delete user'),
],
'#default_value' => $config->get('final_action.action') ?: 'none',
'#description' => $this->t('The final action to handle users that did not even log in after the final action delay. Please note the following: <ul><li><code>None</code> will keep the users in the loop, as there currently is no good way to sort them out. So <code>block</code> or <code>delete</code> are preferred.</li></ul>'),
];
$form['advanced'] = [
'#type' => 'details',
'#tree' => FALSE,
'#title' => $this->t('Advanced settings'),
'#open' => FALSE,
];
$form['advanced']['cron_check_interval'] = [
'#type' => 'number',
'#required' => TRUE,
'#title' => $this->t('Cron check interval (seconds)'),
'#default_value' => $config->get('cron_check_interval') ?: 604800,
'#min' => 0,
'#step' => 1,
'#description' => $this->t('Interval to run the User Registration Reminder checks. Set to zero (0) to check on each cron run.'),
];
$form['advanced']['email_bcc'] = [
'#type' => 'textfield',
'#title' => $this->t('Send blind carbon copy (BCC) of reminders'),
'#default_value' => $config->get('email_bcc') ?? '',
'#description' => $this->t('Send a copy of the reminder to the given email address, e.g. for debug purposes or to be informed about inactive accounts. Leave empty to send no copy.'),
];
return parent::buildForm($form, $form_state);
}
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state): void {
$reminderEscalations = $form_state->getValue('reminder_escalations');
foreach ($reminderEscalations as &$reminderEscalation) {
$reminderEscalation['delay'] = self::daysToSeconds((int) $reminderEscalation['delay']);
}
$this->config('user_registration_reminder.settings')
->set('enabled', $form_state->getValue('enabled'))
->set('cron_check_interval', $form_state->getValue('cron_check_interval'))
->set('email_bcc', $form_state->getValue('email_bcc'))
->set('reminder_escalations', $reminderEscalations)
->set('final_action.delay', self::daysToSeconds((int) $form_state->getValue('final_action')['delay']))
->set('final_action.action', $form_state->getValue('final_action')['action'])
->save();
parent::submitForm($form, $form_state);
}
/**
* Converts seconds into days. Rounds if needed.
*
* @param int $seconds
* Seconds.
*
* @return int
* Days.
*/
protected static function secondsToDays(int $seconds): int {
return (int) round($seconds / 86400, 0, PHP_ROUND_HALF_UP);
}
/**
* Converts days into seconds.
*
* @param int $days
* Days.
*
* @return int
* Seconds.
*/
protected static function daysToSeconds(int $days): int {
return (int) $days * 86400;
}
}
