You are here

final class SitemapWarmer in Warmer 8

Same name and namespace in other branches
  1. 2.x modules/warmer_cdn/src/Plugin/warmer/SitemapWarmer.php \Drupal\warmer_cdn\Plugin\warmer\SitemapWarmer

The cache warmer for the built-in entity cache.

Plugin annotation


@Warmer(
  id = "sitemap",
  label = @Translation("CDN via Sitemap"),
  description = @Translation("Collects the URLs to warm from the sitemap. Then uses the CDN warmer for those.")
)

Hierarchy

Expanded class hierarchy of SitemapWarmer

File

modules/warmer_cdn/src/Plugin/warmer/SitemapWarmer.php, line 24

Namespace

Drupal\warmer_cdn\Plugin\warmer
View source
final class SitemapWarmer extends WarmerPluginBase {
  use UserInputParserTrait;

  /**
   * The sitemap parser.
   *
   * @var \vipnytt\SitemapParser
   */
  private $sitemapParser;

  /**
   * The CDN warmer.
   *
   * @var \Drupal\warmer_cdn\Plugin\warmer\CdnWarmer
   */
  private $warmer;

  /**
   * The warmer manager.
   *
   * @var \Drupal\warmer\Plugin\WarmerPluginManager
   */
  private $warmerManager;

  /**
   * The URL collection.
   *
   * @var array|NULL
   */
  private $urlCollection;

  /**
   * {@inheritdoc}
   *
   * @throws \Drupal\Component\Plugin\Exception\PluginException
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    $instance = parent::create($container, $configuration, $plugin_id, $plugin_definition);
    assert($instance instanceof SitemapWarmer);

    // Inject options to sitemap parser.
    $instance_configuration = $instance
      ->getConfiguration();
    $sitemap_parser_options = [
      'guzzle' => [
        'verify' => $instance_configuration['verify'],
      ],
    ];
    $factory = $container
      ->get('warmer_cdn.sitemap_parser.factory');
    assert($factory instanceof SitemapParserFactory);
    $parser = $factory
      ->get(SitemapParser::DEFAULT_USER_AGENT, $sitemap_parser_options);
    $instance
      ->setSitemapParser($parser);
    $warmer_manager = $container
      ->get('plugin.manager.warmer');
    assert($warmer_manager instanceof WarmerPluginManager);
    $instance
      ->setWarmerManager($warmer_manager);
    return $instance;
  }

  /**
   * {@inheritdoc}
   */
  public function loadMultiple(array $ids = []) {
    return $this
      ->cdnWarmer()
      ->loadMultiple($ids);
  }

  /**
   * {@inheritdoc}
   */
  public function warmMultiple(array $items = []) {
    return $this
      ->cdnWarmer()
      ->warmMultiple($items);
  }

  /**
   * {@inheritdoc}
   */
  public function buildIdsBatch($cursor) {

    // Parse the sitemaps and extract the URLs.
    $urls = $this
      ->parseSitemaps();
    $cursor_position = is_null($cursor) ? -1 : array_search($cursor, $urls);
    if ($cursor_position === FALSE) {
      return [];
    }
    return array_slice($urls, $cursor_position + 1, (int) $this
      ->getBatchSize());
  }

  /**
   * {@inheritdoc}
   */
  public function validateConfigurationForm(array &$form, FormStateInterface $form_state) {
    parent::validateConfigurationForm($form, $form_state);
    $min_priority = $form_state
      ->getValue('minPriority');
    if (!is_numeric($min_priority) || !is_float(floatval($min_priority)) || $min_priority < 0 || $min_priority > 1) {
      $form_state
        ->setError($form['minPriority'], $this
        ->t('minPriority should be a float between 0 and 1.'));
    }
    $this
      ->validateHeaders($form, $form_state);
  }

  /**
   * {@inheritdoc}
   */
  public function addMoreConfigurationFormElements(array $form, SubformStateInterface $form_state) {

    // Remove manual URLs.
    $configuration = $this
      ->getConfiguration();
    $form['sitemaps'] = [
      '#type' => 'textarea',
      '#title' => $this
        ->t('Sitemaps'),
      '#description' => $this
        ->t('Enter the list of sitemap URLs. One on each line. Examples: https://example.org/sitemap.xml, /drupal-sitemap.xml.'),
      '#default_value' => empty($configuration['sitemaps']) ? '' : implode("\n", $configuration['sitemaps']),
    ];
    $form['minPriority'] = [
      '#type' => 'textfield',
      '#title' => $this
        ->t('Minimum Priority'),
      '#description' => $this
        ->t('URLs with a lower priority than the configured will not be warmed. A float value between 0 and 1.'),
      '#default_value' => empty($configuration['minPriority']) ? 0 : $configuration['minPriority'],
    ];
    $form['headers'] = [
      '#type' => 'textarea',
      '#title' => $this
        ->t('Headers'),
      '#description' => $this
        ->t('Specific headers to use when making HTTP requests. Format: <code>Header-Name: value1; value2</code>'),
      '#default_value' => empty($configuration['headers']) ? '' : implode('\\n\\r', $configuration['headers']),
    ];
    $form['verify'] = [
      '#type' => 'checkbox',
      '#title' => $this
        ->t('Enable SSL verification'),
      '#description' => $this
        ->t('Enable SSL verification. Recommended to keep it checked for security reasons.'),
      '#default_value' => $configuration['verify'],
    ];
    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
    $configuration = $form_state
      ->getValues() + $this->configuration;
    $configuration['sitemaps'] = $this
      ->extractTextarea($configuration, 'sitemaps');
    $configuration['headers'] = $this
      ->extractTextarea($configuration, 'headers');
    $this
      ->setConfiguration($configuration);
  }

  /**
   * Set the sitemap parser.
   *
   * @param \vipnytt\SitemapParser $parser
   *   The client.
   */
  public function setSitemapParser(SitemapParser $parser) {
    $this->sitemapParser = $parser;
  }

  /**
   * Set the warmer manager.
   *
   * @param \Drupal\warmer\Plugin\WarmerPluginManager $warmer_manager
   *   The warmer manager.
   */
  public function setWarmerManager(WarmerPluginManager $warmer_manager) {
    $this->warmerManager = $warmer_manager;
  }

  /**
   * Parse and cache the configured sitemaps.
   *
   * @return string[]
   *   The URLs from parsing the sitemap.
   */
  private function parseSitemaps() {
    if (isset($this->urlCollection)) {
      return $this->urlCollection;
    }
    $configuration = $this
      ->getConfiguration();
    $sitemaps = empty($configuration['sitemaps']) ? [] : $configuration['sitemaps'];
    $sitemap_urls = array_map([
      $this,
      'resolveUri',
    ], $sitemaps);
    array_map([
      $this,
      'parseSitemap',
    ], $sitemap_urls);
    $min_priority = empty($configuration['minPriority']) ? 0 : $configuration['minPriority'];
    $min_priority = floatval($min_priority);

    // Only keep the URLs with enough priority.
    $parsed_urls = array_filter($this->sitemapParser
      ->getURLs(), function (array $tags) use ($min_priority) {
      return $tags['priority'] >= $min_priority;
    });
    $this->urlCollection = array_keys($parsed_urls);
    return $this->urlCollection;
  }

  /**
   * Parses a sitemap and logs exceptions.
   *
   * @param string $location
   *   The fully loaded URL for the sitemap.
   */
  private function parseSitemap($location) {
    try {
      $this->sitemapParser
        ->parseRecursive($location);
    } catch (SitemapParserException $exception) {
      watchdog_exception('warmer_cdn', $exception);
      $message = $this
        ->t('There was an error parsing the Sitemap in %location. Please check the watchdog logs for more information.', [
        '%location' => $location,
      ]);
      $this
        ->messenger()
        ->addError($message);
    }
  }

  /**
   * Lazily get the CDN warmer.
   *
   * @return \Drupal\warmer_cdn\Plugin\warmer\CdnWarmer
   *   The CDN warmer.
   *
   * @throws \Drupal\Component\Plugin\Exception\PluginException
   */
  private function cdnWarmer() {
    if ($this->warmer instanceof CdnWarmer) {
      return $this->warmer;
    }
    $configuration = $this
      ->getConfiguration();
    $warmer = $this->warmerManager
      ->createInstance('cdn', [
      'headers' => $configuration['headers'],
      'verify' => $configuration['verify'],
    ]);
    assert($warmer instanceof CdnWarmer);
    $this->warmer = $warmer;
    return $warmer;
  }

  /**
   * {@inheritdoc}
   */
  public function defaultConfiguration() {
    return [
      'verify' => TRUE,
    ] + parent::defaultConfiguration();
  }

}

Members

Namesort descending Modifiers Type Description Overrides
DependencySerializationTrait::$_entityStorages protected property An array of entity type IDs keyed by the property name of their storages.
DependencySerializationTrait::$_serviceIds protected property An array of service IDs keyed by property name used for serialization.
DependencySerializationTrait::__sleep public function 1
DependencySerializationTrait::__wakeup public function 2
MessengerTrait::$messenger protected property The messenger. 29
MessengerTrait::messenger public function Gets the messenger. 29
MessengerTrait::setMessenger public function Sets the messenger.
PluginBase::$configuration protected property Configuration information passed into the plugin. 1
PluginBase::$pluginDefinition protected property The plugin implementation definition. 1
PluginBase::$pluginId protected property The plugin_id.
PluginBase::DERIVATIVE_SEPARATOR constant A string which is used to separate base plugin IDs from the derivative ID.
PluginBase::getBaseId public function Gets the base_plugin_id of the plugin instance. Overrides DerivativeInspectionInterface::getBaseId
PluginBase::getDerivativeId public function Gets the derivative_id of the plugin instance. Overrides DerivativeInspectionInterface::getDerivativeId
PluginBase::getPluginDefinition public function Gets the definition of the plugin implementation. Overrides PluginInspectionInterface::getPluginDefinition 3
PluginBase::getPluginId public function Gets the plugin_id of the plugin instance. Overrides PluginInspectionInterface::getPluginId
PluginBase::isConfigurable public function Determines if the plugin is configurable.
SitemapWarmer::$sitemapParser private property The sitemap parser.
SitemapWarmer::$urlCollection private property The URL collection.
SitemapWarmer::$warmer private property The CDN warmer.
SitemapWarmer::$warmerManager private property The warmer manager.
SitemapWarmer::addMoreConfigurationFormElements public function Adds additional form elements to the configuration form. Overrides WarmerInterface::addMoreConfigurationFormElements
SitemapWarmer::buildIdsBatch public function Builds the next batch of IDs based on a position cursor. Overrides WarmerInterface::buildIdsBatch
SitemapWarmer::cdnWarmer private function Lazily get the CDN warmer.
SitemapWarmer::create public static function Overrides WarmerPluginBase::create
SitemapWarmer::defaultConfiguration public function Gets default configuration for this plugin. Overrides WarmerPluginBase::defaultConfiguration
SitemapWarmer::loadMultiple public function Loads multiple items based on their IDs. Overrides WarmerInterface::loadMultiple
SitemapWarmer::parseSitemap private function Parses a sitemap and logs exceptions.
SitemapWarmer::parseSitemaps private function Parse and cache the configured sitemaps.
SitemapWarmer::setSitemapParser public function Set the sitemap parser.
SitemapWarmer::setWarmerManager public function Set the warmer manager.
SitemapWarmer::submitConfigurationForm public function Form submission handler. Overrides WarmerPluginBase::submitConfigurationForm
SitemapWarmer::validateConfigurationForm public function Form validation handler. Overrides WarmerPluginBase::validateConfigurationForm
SitemapWarmer::warmMultiple public function Warms multiple items. Overrides WarmerInterface::warmMultiple
StringTranslationTrait::$stringTranslation protected property The string translation service. 1
StringTranslationTrait::formatPlural protected function Formats a string containing a count of items.
StringTranslationTrait::getNumberOfPlurals protected function Returns the number of plurals supported by a given language.
StringTranslationTrait::getStringTranslation protected function Gets the string translation service.
StringTranslationTrait::setStringTranslation public function Sets the string translation service to use. 2
StringTranslationTrait::t protected function Translates a string to the current language or to a given language.
UserInputParserTrait::extractTextarea private function Parses the string under $key in the $values collection.
UserInputParserTrait::resolveUri private function Resolves a URI into a fully loaded URL.
UserInputParserTrait::validateHeaders private function Validate the input for the headers.
WarmerPluginBase::$state protected property The state service.
WarmerPluginBase::$time protected property The time service.
WarmerPluginBase::buildConfigurationForm final public function Form constructor. Overrides PluginFormInterface::buildConfigurationForm
WarmerPluginBase::calculateDependencies public function Calculates dependencies for the configured plugin. Overrides DependentPluginInterface::calculateDependencies
WarmerPluginBase::getBatchSize public function Returns the batch size for the warming operation. Overrides WarmerInterface::getBatchSize
WarmerPluginBase::getConfiguration public function Gets this plugin's configuration. Overrides ConfigurableInterface::getConfiguration
WarmerPluginBase::getFrequency public function Returns the frequency for the warming operation. Overrides WarmerInterface::getFrequency
WarmerPluginBase::isActive public function Checks if the plugin should warm in this particular moment. Overrides WarmerInterface::isActive
WarmerPluginBase::markAsEnqueued public function Marks a warmer as enqueued. Overrides WarmerInterface::markAsEnqueued
WarmerPluginBase::setConfiguration public function Sets the configuration for this plugin instance. Overrides ConfigurableInterface::setConfiguration
WarmerPluginBase::__construct public function Constructs a \Drupal\Component\Plugin\PluginBase object. Overrides PluginBase::__construct