You are here

ConfigurationForm.php in URLs queuer 8

File

src/Form/ConfigurationForm.php
View source
<?php

namespace Drupal\purge_queuer_url\Form;

use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\HtmlCommand;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Messenger\MessengerInterface;
use Drupal\purge_ui\Form\QueuerConfigFormBase;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Configuration form for the Url and Path queuer.
 */
class ConfigurationForm extends QueuerConfigFormBase {

  /**
   * The Messenger service.
   *
   * @var \Drupal\Core\Messenger\MessengerInterface
   */
  protected $messenger;

  /**
   * Constructs a ConfigurationForm object.
   *
   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
   *   The factory for configuration objects.
   * @param \Drupal\Core\Messenger\MessengerInterface $messenger
   *   The messenger service.
   */
  public final function __construct(ConfigFactoryInterface $config_factory, MessengerInterface $messenger) {
    $this
      ->setConfigFactory($config_factory);
    $this->messenger = $messenger;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static($container
      ->get('config.factory'), $container
      ->get('messenger'));
  }

  /**
   * {@inheritdoc}
   */
  protected function getEditableConfigNames() {
    return [
      'purge_queuer_url.settings',
    ];
  }

  /**
   * {@inheritdoc}
   */
  public function getFormId() {
    return 'purge_queuer_url.configuration_form';
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state) {
    $config = $this
      ->config('purge_queuer_url.settings');

    // Traffic collection.
    $form['collection'] = [
      '#type' => 'fieldset',
      '#title' => $this
        ->t('Traffic collection'),
    ];
    $form['collection']['queue_paths'] = [
      '#title' => $this
        ->t('Queue paths instead of URLs.'),
      '#type' => 'checkbox',
      '#description' => $this
        ->t("If checked this queues paths without the scheme and domain name."),
      '#default_value' => $config
        ->get('queue_paths'),
    ];
    $form['collection']['host_override'] = [
      '#title' => $this
        ->t('Hostname'),
      '#type' => 'checkbox',
      '#description' => $this
        ->t("You can override the hostname of the URLs that are queued. When you do this, you will lose any gathered domain names that have been collected but do have full control over how the queued URLs look like."),
      '#default_value' => $config
        ->get('host_override'),
      '#states' => [
        'visible' => [
          ':input[name="queue_paths"]' => [
            'checked' => FALSE,
          ],
        ],
      ],
    ];
    $form['collection']['host'] = [
      '#type' => 'textfield',
      '#size' => 30,
      '#default_value' => $config
        ->get('host'),
      '#states' => [
        'visible' => [
          ':input[name="queue_paths"]' => [
            'checked' => FALSE,
          ],
          ':input[name="host_override"]' => [
            'checked' => TRUE,
          ],
        ],
      ],
    ];
    $form['collection']['scheme_override'] = [
      '#title' => $this
        ->t('Scheme'),
      '#type' => 'checkbox',
      '#description' => $this
        ->t("When checked, you can enforce a single scheme like https:// for all the queued URLs instead of logging the schemes that visitors used."),
      '#default_value' => $config
        ->get('scheme_override'),
      '#states' => [
        'visible' => [
          ':input[name="queue_paths"]' => [
            'checked' => FALSE,
          ],
        ],
      ],
    ];
    $form['collection']['scheme'] = [
      '#type' => 'select',
      '#default_value' => $config
        ->get('scheme'),
      '#options' => [
        'http' => $this
          ->t('http://'),
        'https' => $this
          ->t('https://'),
      ],
      '#states' => [
        'visible' => [
          ':input[name="queue_paths"]' => [
            'checked' => FALSE,
          ],
          ':input[name="scheme_override"]' => [
            'checked' => TRUE,
          ],
        ],
      ],
    ];

    // Blacklist form elements (and ajax 'add more' logic).
    $form['blacklist'] = [
      '#type' => 'fieldset',
      '#title' => $this
        ->t('Blacklist'),
      '#description' => $this
        ->t('All cacheable HTTP responses with status code 200 generated by Drupal will be collected in the traffic registry. This approach has the disadvantage that crawlers generating query parameters can pollute your database. Blacklisting allows you to put in any string that will get blocked from entering the registry. It is recommended to <b>contribute back</b> blacklisted strings that are likely to affect any user of this module.'),
    ];

    // Retrieve the existing blacklist and initiatlize the counter.
    $blacklist = $config
      ->get('blacklist');
    if (is_null($form_state
      ->get('blacklist_items_count'))) {
      if (empty($blacklist)) {
        $form_state
          ->set('blacklist_items_count', 1);
      }
      else {
        $form_state
          ->set('blacklist_items_count', count($blacklist));
      }
    }

    // Define the fields based on whats stored in form state.
    $max = $form_state
      ->get('blacklist_items_count');
    $form['blacklist']['blacklist'] = [
      '#tree' => TRUE,
      '#prefix' => '<div id="blacklist-wrapper">',
      '#suffix' => '</div>',
    ];
    for ($delta = 0; $delta < $max; $delta++) {
      if (!isset($form['blacklist']['blacklist'][$delta])) {
        $element = [
          '#type' => 'textfield',
          '#default_value' => isset($blacklist[$delta]) ? $blacklist[$delta] : '',
        ];
        $form['blacklist']['blacklist'][$delta] = $element;
      }
    }

    // Define the add button.
    $form['blacklist']['add'] = [
      '#type' => 'submit',
      '#name' => 'add',
      '#value' => $this
        ->t('Add'),
      '#submit' => [
        [
          $this,
          'addMoreSubmit',
        ],
      ],
      '#ajax' => [
        'callback' => [
          $this,
          'addMoreCallback',
        ],
        'wrapper' => 'blacklist-wrapper',
        'effect' => 'fade',
      ],
    ];

    // Define a clear button to allow clearing the registry.
    $form['actions']['clear'] = [
      '#type' => 'submit',
      '#value' => $this
        ->t('Clear traffic history'),
      '#weight' => 10,
      '#button_type' => 'danger',
    ];
    if ($this
      ->isDialog($form, $form_state)) {
      $form['actions']['clear']['#ajax'] = [
        'callback' => '::submitFormClear',
      ];
    }
    else {
      $form['actions']['clear']['#submit'] = [
        [
          $this,
          'submitFormClear',
        ],
      ];
    }
    return parent::buildForm($form, $form_state);
  }

  /**
   * Let the form rebuild the blacklist textfields.
   *
   * @param array $form
   *   An associative array containing the structure of the form.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The current state of the form.
   */
  public function addMoreSubmit(array &$form, FormStateInterface $form_state) {
    $count = $form_state
      ->get('blacklist_items_count');
    $count++;
    $form_state
      ->set('blacklist_items_count', $count);
    $form_state
      ->setRebuild();
  }

  /**
   * Adds more textfields to the blacklist fieldset.
   *
   * @param array $form
   *   An associative array containing the structure of the form.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The current state of the form.
   */
  public function addMoreCallback(array &$form, FormStateInterface $form_state) {
    return $form['blacklist']['blacklist'];
  }

  /**
   * {@inheritdoc}
   */
  public function validateForm(array &$form, FormStateInterface $form_state) {

    // Remove empty values from the blacklist so this doesn't cause issues.
    $blacklist = [];
    foreach ($form_state
      ->getValue('blacklist') as $string) {
      if (!empty(trim($string))) {
        $blacklist[] = $string;
      }
    }
    $form_state
      ->setValue('blacklist', $blacklist);
  }

  /**
   * Submit handler that clears the traffic registry.
   *
   * @param array $form
   *   An associative array containing the structure of the form.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The current state of the form.
   */
  public function submitFormClear(array &$form, FormStateInterface $form_state) {

    // Clear the traffic registry IF there are no ordinary form errors.
    if (!$form_state
      ->getErrors()) {
      \Drupal::service('purge_queuer_url.registry')
        ->clear();
      $this->messenger
        ->addMessage($this
        ->t("The traffic registry has been cleared, your site needs to get regular traffic before it starts queueing URLs or paths again! Pages currently cached in Drupal's render cache won't be collected unless you clear those, but be careful doing that on a busy site!"));
    }

    // Determine all the AJAX and non-AJAX logic depending on how we're called.
    if ($this
      ->isDialog($form, $form_state)) {
      $response = new AjaxResponse();
      unset($form['#prefix'], $form['#suffix']);
      $form['status_messages'] = [
        '#type' => 'status_messages',
        '#weight' => -10,
      ];
      $response
        ->addCommand(new HtmlCommand('#purgedialogform', $form));
      return $response;
    }
    return parent::submitForm($form, $form_state);
  }

  /**
   * {@inheritdoc}
   */
  public function submitFormSuccess(array &$form, FormStateInterface $form_state) {
    $this
      ->config('purge_queuer_url.settings')
      ->set('queue_paths', $form_state
      ->getValue('queue_paths'))
      ->set('host_override', $form_state
      ->getValue('host_override'))
      ->set('host', $form_state
      ->getValue('host'))
      ->set('scheme_override', $form_state
      ->getValue('scheme_override'))
      ->set('scheme', $form_state
      ->getValue('scheme'))
      ->set('blacklist', $form_state
      ->getValue('blacklist'))
      ->save();

    // Changes to the blacklist inevitably affect what should be in the registry
    // and what URLs should not be. Because already cached page cache responses
    // aren't checked in UrlRegistrar::determine(), wipe the render cache.
    foreach (Cache::getBins() as $service_id => $cache_backend) {
      if ($service_id === 'render') {
        $cache_backend
          ->deleteAll();
      }
    }
  }

}

Classes

Namesort descending Description
ConfigurationForm Configuration form for the Url and Path queuer.