sitemap_status-1.0.0-alpha4/src/Form/SettingsForm.php

src/Form/SettingsForm.php
<?php

namespace Drupal\sitemap_status\Form;

use Drupal\Core\Form\ConfigFormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\sitemap_status\SitemapStatusInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Class SettingsForm.
 */
class SettingsForm extends ConfigFormBase {

  /**
   * Drupal\sitemap_status\SitemapStatusInterface definition.
   *
   * @var \Drupal\sitemap_status\SitemapStatusInterface
   */
  protected $sitemapStatus;

  /**
   * Drupal\Core\Queue\QueueFactory definition.
   *
   * @var \Drupal\Core\Queue\QueueFactory
   */
  protected $queueFactory;

  /**
   * Drupal\Core\Datetime\DateFormatterInterface definition.
   *
   * @var \Drupal\Core\Datetime\DateFormatterInterface
   */
  protected $dateFormatter;

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    $instance = parent::create($container);
    $instance->sitemapStatus = $container->get('sitemap_status');
    $instance->queueFactory = $container->get('queue');
    $instance->dateFormatter = $container->get('date.formatter');
    return $instance;
  }

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

  /**
   * {@inheritdoc}
   */
  public function getFormId() {
    return 'sitemap_status_settings';
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state) {
    $config = $this->config('sitemap_status.settings');
    $summary = $this->sitemapStatus->getStatusSummary();
    /** @var \Drupal\Core\Render\RendererInterface $renderer */
    $renderer = \Drupal::service('renderer');
    $form['summary'] = [
      '#type' => 'details',
      '#title' => $this->t('Status summary'),
      '#open' => TRUE,
    ];
    $form['summary']['status_summary'] = [
      '#type' => 'item',
      '#markup' => $renderer->render($summary),
    ];
    $form['dom'] = [
      '#type' => 'details',
      '#title' => $this->t('DOM based check'),
      '#description' => $this->t('By default, only the http status is checked. Optionally check the DOM for errors or elements.'),
      '#open' => TRUE,
    ];
    $form['dom']['has_error_check'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Check errors'),
      '#description' => $this->t('Status check passes if no errors are contained in the DOM.'),
      '#default_value' => $config->get('has_error_check'),
    ];
    $form['dom']['error_classes'] = [
      '#type' => 'textarea',
      '#title' => $this->t('Error classes'),
      '#description' => $this->t('If the DOM contains one of these classes the status check fails. One per line, without the dot prefix. Defaults to <code>messages--error</code> if not set.'),
      '#default_value' => $config->get('error_classes'),
      '#states' => [
        'invisible' => [
          ':input[name="has_error_check"]' => ['checked' => FALSE],
        ],
      ],
    ];
    $form['dom']['has_element_check'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Check elements'),
      '#description' => $this->t('Status check passes if elements are contained in the DOM.'),
      '#default_value' => $config->get('has_element_check'),
    ];
    $form['dom']['elements'] = [
      '#type' => 'textarea',
      '#title' => $this->t('Elements'),
      '#description' => $this->t('If the DOM does not contains all of these elements, the status check fails. One per line, without the tag opening/closing (e.g. <code>heading</code>). Defaults to <code>h1</code> if not set.'),
      '#default_value' => $config->get('elements'),
      '#states' => [
        'invisible' => [
          ':input[name="has_element_check"]' => ['checked' => FALSE],
        ],
      ],
    ];
    $form['locations'] = [
      '#type' => 'details',
      '#title' => $this->t('Locations'),
      '#open' => TRUE,
    ];
    $form['locations']['basic_auth'] = [
      '#type' => 'textfield',
      '#title' => $this->t('Basic auth'),
      '#description' => $this->t('Optionally appends basic auth credentials to the locations status check. Format: <em>username:password</em>'),
      '#maxlength' => 255,
      '#size' => 64,
      '#default_value' => $config->get('basic_auth'),
    ];
    $form['locations']['path_prefix'] = [
      '#type' => 'textfield',
      '#title' => $this->t('Path prefix'),
      '#description' => $this->t('Can be used for a specific directory or a region based redirect, to be able to distinguish other 301 redirects. Without leading or trailing slashes.'),
      '#maxlength' => 64,
      '#size' => 64,
      '#default_value' => $config->get('path_prefix'),
    ];
    $form['locations']['async'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Async requests'),
      '#description' => $this->t('Fetches locations status asynchronously, faster but uses more resources.'),
      '#default_value' => $config->get('async'),
    ];
    $form['locations']['concurrent_requests'] = [
      '#type' => 'number',
      '#title' => $this->t('Maximum concurrent requests'),
      '#default_value' => $config->get('concurrent_requests') ?: SitemapStatusInterface::MAX_CONCURRENT_REQUESTS,
      '#min' => 2,
      '#states' => [
        'invisible' => [
          ':input[name="async"]' => ['checked' => FALSE],
        ],
      ],
    ];
    $form['locations']['maximum_locations'] = [
      '#type' => 'number',
      '#title' => $this->t('Maximum amount of locations to check'),
      '#description' => $this->t('If set to 0, no maximum. Otherwise, checks the first locations found in the sitemap.'),
      '#default_value' => $config->get('maximum_locations') ?: 0,
      '#min' => 0,
    ];

    $form['process'] = [
      '#type' => 'details',
      '#title' => t('Process'),
      '#open' => TRUE,
    ];
    $form['process']['stop_on_error'] = [
      '#type' => 'checkbox',
      // @todo batch needs to be adapted first
      // @see LocationBatch::batchLocationProcess()
      // @see LocationBatch::batchLocationsGroupProcess()
      '#access' => FALSE,
      '#title' => $this->t('Stop on error'),
      '#description' => $this->t('Stops the status check on the first error met.'),
      '#default_value' => $config->get('stop_on_error'),
    ];
    $form['process']['cron_frequency'] = [
      '#type' => 'select',
      '#title' => $this->t('Cron frequency'),
      '#default_value' => $config->get('cron_frequency'),
      '#options' => [
        0 => '<' . $this->t('Disable cron check') . '>',
        1 => $this->t('Daily'),
        7 => $this->t('Weekly'),
      ],
      '#description' => $this->t('Optionally triggers the sitemap status on cron.'),
    ];

    $form['cache'] = [
      '#type' => 'details',
      '#title' => $this->t('Cache'),
      '#open' => TRUE,
    ];
    $form['cache']['preserve_cache'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Preserve status check cache on cache rebuild.'),
      '#default_value' => $config->get('preserve_cache'),
    ];

    $form['actions_message'] = [
      '#type' => 'item',
      '#markup' => $this->t('If the configuration has changed, it should be saved to apply while checking the status.'),
    ];
    $form = parent::buildForm($form, $form_state);
    $form['actions']['check_status'] = [
      '#type' => 'submit',
      '#value' => $this->t('Check sitemap status'),
      '#submit' => [[$this, 'batchCheckStatus']],
    ];
    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {
    parent::submitForm($form, $form_state);

    $this->config('sitemap_status.settings')
      ->set('has_error_check', $form_state->getValue('has_error_check'))
      ->set('error_classes', $form_state->getValue('error_classes'))
      ->set('has_element_check', $form_state->getValue('has_element_check'))
      ->set('elements', $form_state->getValue('elements'))
      ->set('path_prefix', $form_state->getValue('path_prefix'))
      ->set('basic_auth', $form_state->getValue('basic_auth'))
      ->set('async', $form_state->getValue('async'))
      ->set('concurrent_requests', $form_state->getValue('concurrent_requests'))
      ->set('maximum_locations', $form_state->getValue('maximum_locations'))
      ->set('cron_frequency', $form_state->getValue('cron_frequency'))
      ->set('stop_on_error', $form_state->getValue('stop_on_error'))
      ->set('preserve_cache', $form_state->getValue('preserve_cache'))
      ->save();
  }

  /**
   * {@inheritdoc}
   */
  public function validateForm(array &$form, FormStateInterface $form_state) {
    $pathPrefix = $form_state->getValue('path_prefix');
    $basicAuth = $form_state->getValue('basic_auth');
    $asyncRequests = $form_state->getValue('async');
    $concurrentRequests = (int) $form_state->getValue('concurrent_requests');

    // @todo validate errors classes (no dot, class safe) and elements (valid tag)

    // @todo improve validation / possibly refactor with sitemap status service.
    if (!empty($pathPrefix)) {
      $currentHost = \Drupal::request()->getSchemeAndHttpHost();
      $environmentUrl = $currentHost . '/' . $pathPrefix;
      if (!$this->sitemapStatus->isUrlValid($environmentUrl)) {
        $form_state->setError(
          $form['path_prefix'],
          $this->t('The resulting url with the path prefix (@environment_url) is not valid.', [
            '@environment_url' => $environmentUrl,
          ])
        );
      }
    }

    if (!empty($basicAuth)) {
      $basicAuthParts = explode(':', $basicAuth);
      if (count($basicAuthParts) !== 2) {
        $form_state->setError(
          $form['basic_auth'],
          $this->t('The basic auth must be with the format <em>username:password</em>.')
        );
      }
    }

    if ($asyncRequests === 1 && $concurrentRequests > SitemapStatusInterface::MAX_CONCURRENT_REQUESTS) {
      $this->messenger()->addWarning($this->t('The maximum amount of concurrent requests might vary depending on the available resources. It is advised to not configure more than @max_requests.', [
        '@max_requests' => SitemapStatusInterface::MAX_CONCURRENT_REQUESTS,
      ]));
    }
  }

  /**
   * Submit handler that checks the locations status with a batch.
   *
   * @todo move in the sitemap status service.
   *
   * @param array $form
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   */
  public function batchCheckStatus(array &$form, FormStateInterface $form_state) {
    // Make sure to delete the state override from Drush.
    // To be removed once onQueueFinishedProcessing is implemented.
    // @see SitemapStatusCommand.
    \Drupal::state()->delete(SitemapStatusInterface::STATE_CONFIG_OVERRIDE);

    $config = $this->config('sitemap_status.settings');
    $asyncRequests = $config->get('async');
    $sitemapLocations = $this->sitemapStatus->fetchSitemapLocations();
    $operations = [];
    $progressMessage = '';
    if ($asyncRequests === 1) {
      $concurrentRequests = $config->get('concurrent_requests');
      if (empty($concurrentRequests)) {
        $concurrentRequests = SitemapStatusInterface::MAX_CONCURRENT_REQUESTS;
      }
      $locationsGroups = array_chunk($sitemapLocations, $concurrentRequests);
      foreach ($locationsGroups as $locationGroup) {
        $operations[] = [
          '\Drupal\sitemap_status\LocationBatch::batchLocationsGroupProcess', [$locationGroup],
        ];
      }
      $progressMessage = $this->t('Checked @current locations group on @total.');
    }
    else {
      foreach ($sitemapLocations as $location) {
        $operations[] = [
          '\Drupal\sitemap_status\LocationBatch::batchLocationProcess', [$location],
        ];
      }
      $progressMessage = $this->t('Checked @current locations on @total.');
    }

    $batch = [
      'title' => $this->t('Status check of @total sitemap locations', ['@total' => count($sitemapLocations)]),
      'operations' => $operations,
      'progress_message' => $progressMessage,
      'finished' => ['\Drupal\sitemap_status\LocationBatch', 'batchFinished'],
    ];

    batch_set($batch);
  }

}

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

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