AutobanFormBase.php in Automatic IP ban (Autoban) 8
Class AutobanFormBase.
@package Drupal\autoban\Form
Namespace
Drupal\autoban\FormFile
src/Form/AutobanFormBase.phpView source
<?php
namespace Drupal\autoban\Form;
use Drupal\Core\Entity\EntityForm;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Url;
use Drupal\Core\Link;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Database\Database;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Drupal\autoban\Controller\AutobanController;
use Drupal\autoban\AutobanUtils;
use Drupal\Component\Utility\Html;
/**
* @file
* Class AutobanFormBase.
*
* @package Drupal\autoban\Form
*
* @ingroup autoban
*/
/**
* Autoban base form for add and edit.
*/
class AutobanFormBase extends EntityForm {
/**
* Define AutobanFormBase class.
*/
/**
* Entity Type Manager variable.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
* Define EntityTypeManager variable.
*/
protected $entityTypeManager;
/**
* Config factory variable.
*
* @var \Drupal\Core\Config\ConfigFactoryInterface
*/
protected $config;
/**
* The autoban object.
*
* @var \Drupal\autoban\Controller\AutobanController
*/
protected $autoban;
/**
* Construct the AutobanFormBase.
*
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* An entity type manager interface for the autoban entity type.
* @param \Drupal\Core\Config\ConfigFactoryInterface $config
* Store ConfigFactoryInterface manager.
* @param \Drupal\autoban\Controller\AutobanController $autoban
* Autoban object.
*/
public function __construct(EntityTypeManagerInterface $entity_type_manager, ConfigFactoryInterface $config, AutobanController $autoban) {
$this->entityTypeManager = $entity_type_manager;
$this->config = $config;
$this->autoban = $autoban;
}
/**
* Factory method for AutobanFormBase.
*/
public static function create(ContainerInterface $container) {
return new static($container
->get('entity_type.manager'), $container
->get('config.factory'), $container
->get('autoban'));
}
/**
* Overrides Drupal\Core\Entity\EntityFormController::form().
*
* Builds the entity add/edit form.
*
* @param array $form
* An associative array containing the structure of the form.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* An associative array containing the current state of the form.
* @param string $rule
* Rule ID (optional).
*
* @return array
* An associative array containing the autoban add/edit form.
*/
public function buildForm(array $form, FormStateInterface $form_state, $rule = NULL) {
$form = parent::buildForm($form, $form_state);
$params = $this
->getRequest()->query
->all();
if ($rule) {
$autoban = $this->entityTypeManager
->getStorage('autoban')
->load($rule);
if (!$autoban) {
throw new NotFoundHttpException();
}
}
else {
$autoban = $this->entity;
}
$controller = $this->autoban;
$is_new = $autoban
->isNew() || $rule;
$rule_type_value = $is_new ? AutobanUtils::AUTOBAN_RULE_MANUAL : $autoban->rule_type;
$form['rule_type'] = [
'#type' => 'hidden',
'#value' => $rule_type_value,
];
if (!empty($rule_type_value)) {
$form['rule_type_array'] = [
'#markup' => $this
->t('Rule type: @type', [
'@type' => $controller
->ruleTypeList($rule_type_value),
]),
];
}
$form['id'] = [
'#type' => 'machine_name',
'#title' => $this
->t('Id'),
'#description' => $this
->t('Unique rules name'),
'#default_value' => $is_new ? $this
->newDefaultId() : $autoban
->id(),
'#maxlength' => 64,
'#machine_name' => [
'exists' => [
$this,
'exists',
],
'replace_pattern' => '([^a-z0-9_]+)|(^custom$)',
'error' => $this
->t('Must be unique, and can only contain lowercase letters, numbers, and underscores. Additionally, it can not be the reserved word "custom".'),
],
'#disabled' => !$is_new,
];
// Type current groups.
$dblog_type_exclude = $this
->config('autoban.settings')
->get('autoban_dblog_type_exclude') ?: "autoban\ncron\nphp\nsystem\nuser";
$query = Database::getConnection()
->select('watchdog', 'log');
$query
->addField('log', 'type');
$query
->condition('type', explode("\n", $dblog_type_exclude), 'NOT IN');
$query
->orderBy('type');
$all_groups = $query
->execute()
->fetchAllKeyed(0, 0);
array_walk($all_groups, function (&$item, $key) {
$item = "<span>{$item}</span>";
});
$default_type = $autoban->type;
if (empty($default_type) && !empty($params['type'])) {
$default_type = $params['type'];
}
$form['type'] = [
'#type' => 'textfield',
'#title' => $this
->t('Type'),
'#description' => implode(', ', $all_groups),
'#maxlength' => 255,
'#default_value' => $default_type,
'#required' => TRUE,
];
$default_message = $autoban->message;
if (empty($default_message) && !empty($params['message'])) {
$default_message = Html::decodeEntities($params['message']);
}
$query_mode = $this
->config('autoban.settings')
->get('autoban_query_mode') ?: 'like';
$query_mode_message = strtoupper($query_mode);
$use_wildcards = $this
->config('autoban.settings')
->get('autoban_use_wildcards') ?: FALSE;
$use_wildcards_message = $use_wildcards ? $this
->t('yes') : $this
->t('no');
$form['message'] = [
'#type' => 'textfield',
'#title' => $this
->t('Message pattern'),
'#description' => $this
->t('Dblog message @query_mode pattern. Use delimiter "|" for multiple values. Use wildcards: @use_wildcards_message.', [
'@query_mode' => $query_mode_message,
'@use_wildcards_message' => $use_wildcards_message,
]),
'#maxlength' => 255,
'#default_value' => $default_message,
'#required' => TRUE,
];
$form['referer'] = [
'#type' => 'textfield',
'#title' => $this
->t('Referrer pattern'),
'#description' => $this
->t('URL referrer pattern.'),
'#maxlength' => 255,
'#default_value' => $autoban->referer,
'#required' => FALSE,
];
$thresholds_config = $this
->config('autoban.settings')
->get('autoban_thresholds');
$thresholds = !empty($thresholds_config) ? explode("\n", $thresholds_config) : [
1,
2,
3,
5,
10,
20,
50,
100,
];
if (empty($autoban->threshold)) {
$last_threshold = $this
->config('autoban.settings')
->get('autoban_threshold_last');
if ($last_threshold && in_array($last_threshold, $thresholds)) {
$autoban->threshold = $last_threshold;
}
}
$form['threshold'] = [
'#type' => 'select',
'#title' => $this
->t('Threshold'),
'#description' => $this
->t('The threshold number of the log entries.'),
'#default_value' => $autoban->threshold,
'#options' => array_combine($thresholds, $thresholds),
'#required' => TRUE,
];
$form['user_type'] = [
'#type' => 'select',
'#title' => $this
->t('User type'),
'#description' => $this
->t('User type: anonymous, authenticated or any.'),
'#default_value' => $autoban->user_type ?: 0,
'#options' => $controller
->userTypeList(),
'#required' => TRUE,
];
// Retrieve Ban manager list.
$providers = [];
$banManagerList = $controller
->getBanProvidersList();
if (!empty($banManagerList)) {
foreach ($banManagerList as $id => $item) {
$providers[$id] = $item['name'];
}
}
else {
$this
->messenger()
->addMessage($this
->t('List ban providers is empty. You have to enable at least one Autoban providers module.'), 'warning');
}
// For a single provider.
if ($autoban
->isNew() && count($providers) > 0) {
if (count($providers) == 1) {
$autoban->provider = array_keys($providers)[0];
}
else {
$last_provider = $this
->config('autoban.settings')
->get('autoban_provider_last');
if ($last_provider && isset($providers[$last_provider])) {
$autoban->provider = $last_provider;
}
}
}
$form['provider'] = [
'#type' => 'select',
'#title' => $this
->t('IP ban provider'),
'#default_value' => $autoban->provider,
'#options' => $providers,
'#required' => TRUE,
];
$destination = $this
->getDestinationArray();
$cancel_url = !empty($destination['destination']) && Url::fromRoute('<current>')
->toString() != $destination['destination'] ? Url::fromUserInput($destination['destination']) : Url::fromRoute('entity.autoban.list');
$cancel_link = Link::fromTextAndUrl($this
->t('Cancel'), $cancel_url)
->toString();
$form['actions']['cancel'] = [
'#markup' => $cancel_link,
'#weight' => 100,
];
$form['#attached']['library'][] = 'autoban/form';
return $form;
}
/**
* Checks for an existing autoban rule.
*
* @param string|int $entity_id
* The entity ID.
* @param array $element
* The form element.
* @param Drupal\Core\Form\FormStateInterface $form_state
* The form state.
*
* @return bool
* TRUE if this format already exists, FALSE otherwise.
*/
public function exists($entity_id, array $element, FormStateInterface $form_state) {
$query = $this->entityTypeManager
->getStorage('autoban')
->getQuery();
$result = $query
->condition('id', $element['#field_prefix'] . $entity_id)
->execute();
return (bool) $result;
}
/**
* Generate default ID for new item.
*
* @return string
* Default ID.
*/
public function newDefaultId() {
$query = $this->entityTypeManager
->getStorage('autoban')
->getQuery();
$query
->condition('rule_type', AutobanUtils::AUTOBAN_RULE_AUTO, '=');
$cnt_auto = $query
->count()
->execute();
$query = $this->entityTypeManager
->getStorage('autoban')
->getQuery();
$cnt_total = $query
->count()
->execute();
$next = $cnt_total - $cnt_auto + 1;
$entity_id = "rule{$next}";
$result = $query
->condition('id', $entity_id)
->execute();
$exists = (bool) $result;
return $exists ? '' : $entity_id;
}
/**
* Overrides Drupal\Core\Entity\EntityFormController::actions().
*
* To set the submit button text, we need to override actions().
*
* @param array $form
* An associative array containing the structure of the form.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* An associative array containing the current state of the form.
*
* @return array
* An array of supported actions for the current entity form.
*/
protected function actions(array $form, FormStateInterface $form_state) {
$actions = parent::actions($form, $form_state);
$actions['submit']['#value'] = $this
->t('Save');
return $actions;
}
/**
* Overrides Drupal\Core\Entity\EntityFormController::save().
*
* Saves the entity. This is called after submit() has built the entity from
* the form values. Do not override submit() as save() is the preferred
* method for entity form controllers.
*
* @param array $form
* An associative array containing the structure of the form.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* An associative array containing the current state of the form.
*/
public function save(array $form, FormStateInterface $form_state) {
$last_threshold = $form_state
->getValue('threshold');
$last_provider = $form_state
->getValue('provider');
$this->config
->getEditable('autoban.settings')
->set('autoban_threshold_last', $last_threshold)
->set('autoban_provider_last', $last_provider)
->save();
$autoban = $this
->getEntity();
$status = $autoban
->save();
$url = $autoban
->toUrl();
$edit_link = Link::fromTextAndUrl($this
->t('Edit'), $url)
->toString();
if ($status == SAVED_UPDATED) {
// If we edited an existing entity...
$this
->messenger()
->addMessage($this
->t('Autoban rule %label has been updated.', [
'%label' => $autoban
->id(),
]));
$this
->logger('autoban')
->notice('Autoban rule %label has been updated.', [
'%label' => $autoban
->id(),
'link' => $edit_link,
]);
}
else {
// If we created a new entity...
$this
->messenger()
->addMessage($this
->t('Autoban rule %label has been added.', [
'%label' => $autoban
->id(),
]));
$this
->logger('autoban')
->notice('Autoban rule %label has been added.', [
'%label' => $autoban
->id(),
'link' => $edit_link,
]);
}
// Redirect the user back to the listing route after the save operation.
$form_state
->setRedirect('entity.autoban.list');
}
}
Classes
Name | Description |
---|---|
AutobanFormBase | Autoban base form for add and edit. |