automatic_updates-8.x-2.x-dev/src/Validation/StatusChecker.php

src/Validation/StatusChecker.php
<?php

declare(strict_types=1);

namespace Drupal\automatic_updates\Validation;

use Drupal\automatic_updates\CronUpdateRunner;
use Drupal\automatic_updates\ConsoleUpdateSandboxManager;
use Drupal\automatic_updates\StatusCheckMailer;
use Drupal\Core\Config\ConfigCrudEvent;
use Drupal\Core\Config\ConfigEvents;
use Drupal\Core\KeyValueStore\KeyValueStoreExpirableInterface;
use Drupal\package_manager\StatusCheckTrait;
use Drupal\automatic_updates\UpdateSandboxManager;
use Drupal\Component\Datetime\TimeInterface;
use Drupal\Core\KeyValueStore\KeyValueExpirableFactoryInterface;
use Drupal\package_manager\Event\PostApplyEvent;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

/**
 * Runs status checks and caches the results.
 */
final class StatusChecker implements EventSubscriberInterface {

  use StatusCheckTrait;

  /**
   * The key/value expirable storage.
   *
   * @var \Drupal\Core\KeyValueStore\KeyValueStoreExpirableInterface
   */
  private readonly KeyValueStoreExpirableInterface $keyValueExpirable;

  public function __construct(
    KeyValueExpirableFactoryInterface $key_value_expirable_factory,
    private readonly TimeInterface $time,
    private readonly EventDispatcherInterface $eventDispatcher,
    private readonly UpdateSandboxManager $updateStage,
    private readonly ConsoleUpdateSandboxManager $consoleUpdateStage,
    private readonly CronUpdateRunner $cronUpdateRunner,
    private readonly int $resultsTimeToLive,
  ) {
    $this->keyValueExpirable = $key_value_expirable_factory->get('automatic_updates');
  }

  /**
   * Dispatches the status check event and stores the results.
   *
   * @return $this
   */
  public function run(): self {
    // If updates will run during cron, use the console update stage service
    // provided by this module. This will allow validators to run specific
    // validation for conditions that only affect cron updates.
    if ($this->cronUpdateRunner->getMode() === CronUpdateRunner::DISABLED) {
      $sandbox_manager = $this->updateStage;
    }
    else {
      $sandbox_manager = $this->consoleUpdateStage;
    }
    $results = $this->runStatusCheck($sandbox_manager, $this->eventDispatcher);

    $this->keyValueExpirable->setWithExpire(
      'status_check_last_run',
      $results,
      $this->resultsTimeToLive * 60 * 60
    );
    $this->keyValueExpirable->set('status_check_timestamp', $this->time->getRequestTime());
    return $this;
  }

  /**
   * Dispatches the status check event if there no stored valid results.
   *
   * @return $this
   *
   * @see self::getResults()
   */
  public function runIfNoStoredResults(): self {
    if ($this->getResults() === NULL) {
      $this->run();
    }
    return $this;
  }

  /**
   * Gets the validation results from the last run.
   *
   * @param int|null $severity
   *   (optional) The severity for the results to return. Should be one of the
   *   SystemManager::REQUIREMENT_* constants.
   *
   * @return \Drupal\package_manager\ValidationResult[]|null
   *   The validation result objects or NULL if no results are
   *   available or if the stored results are no longer valid.
   */
  public function getResults(?int $severity = NULL): ?array {
    $results = $this->keyValueExpirable->get('status_check_last_run');
    if ($results !== NULL) {
      if ($severity !== NULL) {
        $results = array_filter($results, function ($result) use ($severity) {
          return $result->severity === $severity;
        });
      }
      return $results;
    }
    return NULL;
  }

  /**
   * Deletes any stored status check results.
   */
  public function clearStoredResults(): void {
    $this->keyValueExpirable->delete('status_check_last_run');
  }

  /**
   * Gets the timestamp of the last run.
   *
   * @return int|null
   *   The timestamp of the last completed run, or NULL if no run has
   *   been completed.
   */
  public function getLastRunTime(): ?int {
    return $this->keyValueExpirable->get('status_check_timestamp');
  }

  /**
   * Reacts when config is saved.
   *
   * @param \Drupal\Core\Config\ConfigCrudEvent $event
   *   The event object.
   */
  public function onConfigSave(ConfigCrudEvent $event): void {
    $config = $event->getConfig();

    // If the path of the Composer executable has changed, the status check
    // results are likely to change as well.
    if ($config->getName() === 'package_manager.settings' && $event->isChanged('executables.composer')) {
      $this->clearStoredResults();
    }
    elseif ($config->getName() === 'automatic_updates.settings') {
      // If anything about how we run unattended updates has changed, clear the
      // stored results, since they can be affected by these settings.
      if ($event->isChanged('unattended')) {
        $this->clearStoredResults();
      }
      // We only send status check failure notifications if unattended updates
      // are enabled. If notifications were previously disabled but have been
      // re-enabled, or their sensitivity level has changed, clear the stored
      // results so that we'll send accurate notifications next time cron runs.
      elseif ($event->isChanged('status_check_mail') && $config->get('status_check_mail') !== StatusCheckMailer::DISABLED) {
        $this->clearStoredResults();
      }
    }
  }

  /**
   * {@inheritdoc}
   */
  public static function getSubscribedEvents(): array {
    return [
      PostApplyEvent::class => 'clearStoredResults',
      ConfigEvents::SAVE => 'onConfigSave',
    ];
  }

}

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

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