You are here

class DiskSpaceValidator in Automatic Updates 8.2

Validates that there is enough free disk space to do automatic updates.

Hierarchy

Expanded class hierarchy of DiskSpaceValidator

1 file declares its use of DiskSpaceValidator
DiskSpaceValidatorTest.php in tests/src/Kernel/ReadinessValidation/DiskSpaceValidatorTest.php
1 string reference to 'DiskSpaceValidator'
automatic_updates.services.yml in ./automatic_updates.services.yml
automatic_updates.services.yml
1 service uses DiskSpaceValidator
automatic_updates.disk_space_validator in ./automatic_updates.services.yml
Drupal\automatic_updates\Validator\DiskSpaceValidator

File

src/Validator/DiskSpaceValidator.php, line 18

Namespace

Drupal\automatic_updates\Validator
View source
class DiskSpaceValidator implements EventSubscriberInterface {
  use StringTranslationTrait;

  /**
   * The path locator service.
   *
   * @var \Drupal\automatic_updates\PathLocator
   */
  protected $pathLocator;

  /**
   * Constructs a DiskSpaceValidator object.
   *
   * @param \Drupal\automatic_updates\PathLocator $path_locator
   *   The path locator service.
   * @param \Drupal\Core\StringTranslation\TranslationInterface $translation
   *   The translation service.
   */
  public function __construct(PathLocator $path_locator, TranslationInterface $translation) {
    $this->pathLocator = $path_locator;
    $this
      ->setStringTranslation($translation);
  }

  /**
   * Wrapper around the disk_free_space() function.
   *
   * @param string $path
   *   The path for which to retrieve the amount of free disk space.
   *
   * @return float
   *   The number of bytes of free space on the disk.
   *
   * @throws \RuntimeException
   *   If the amount of free space could not be determined.
   */
  protected function freeSpace(string $path) : float {
    $free_space = disk_free_space($path);
    if ($free_space === FALSE) {
      throw new \RuntimeException("Cannot get disk information for {$path}.");
    }
    return $free_space;
  }

  /**
   * Wrapper around the stat() function.
   *
   * @param string $path
   *   The path to check.
   *
   * @return array
   *   The statistics for the path.
   *
   * @throws \RuntimeException
   *   If the statistics could not be determined.
   */
  protected function stat(string $path) : array {
    $stat = stat($path);
    if ($stat === FALSE) {
      throw new \RuntimeException("Cannot get information for {$path}.");
    }
    return $stat;
  }

  /**
   * Checks if two paths are located on the same logical disk.
   *
   * @param string $root
   *   The path of the project root.
   * @param string $vendor
   *   The path of the vendor directory.
   *
   * @return bool
   *   TRUE if the project root and vendor directory are on the same logical
   *   disk, FALSE otherwise.
   */
  protected function areSameLogicalDisk(string $root, string $vendor) : bool {
    $root_statistics = $this
      ->stat($root);
    $vendor_statistics = $this
      ->stat($vendor);
    return $root_statistics['dev'] === $vendor_statistics['dev'];
  }

  /**
   * Checks that there is enough free space to perform automatic updates.
   *
   * @param \Drupal\automatic_updates\Event\UpdateEvent $event
   *   The update event object.
   */
  public function checkDiskSpace(UpdateEvent $event) : void {
    $root_path = $this->pathLocator
      ->getProjectRoot();
    $vendor_path = $this->pathLocator
      ->getVendorDirectory();
    $messages = [];

    // @todo Make this configurable.
    $minimum_mb = 1024;
    $minimum_bytes = Bytes::toNumber($minimum_mb . 'M');
    if (!$this
      ->areSameLogicalDisk($root_path, $vendor_path)) {
      if ($this
        ->freeSpace($root_path) < $minimum_bytes) {
        $messages[] = $this
          ->t('Drupal root filesystem "@root" has insufficient space. There must be at least @space megabytes free.', [
          '@root' => $root_path,
          '@space' => $minimum_mb,
        ]);
      }
      if (is_dir($vendor_path) && $this
        ->freeSpace($vendor_path) < $minimum_bytes) {
        $messages[] = $this
          ->t('Vendor filesystem "@vendor" has insufficient space. There must be at least @space megabytes free.', [
          '@vendor' => $vendor_path,
          '@space' => $minimum_mb,
        ]);
      }
    }
    elseif ($this
      ->freeSpace($root_path) < $minimum_bytes) {
      $messages[] = $this
        ->t('Drupal root filesystem "@root" has insufficient space. There must be at least @space megabytes free.', [
        '@root' => $root_path,
        '@space' => $minimum_mb,
      ]);
    }
    $temp = $this
      ->temporaryDirectory();
    if ($this
      ->freeSpace($temp) < $minimum_bytes) {
      $messages[] = $this
        ->t('Directory "@temp" has insufficient space. There must be at least @space megabytes free.', [
        '@temp' => $temp,
        '@space' => $minimum_mb,
      ]);
    }
    if ($messages) {
      $summary = count($messages) > 1 ? $this
        ->t("There is not enough disk space to perform an automatic update.") : NULL;
      $error = ValidationResult::createError($messages, $summary);
      $event
        ->addValidationResult($error);
    }
  }

  /**
   * Returns the path of the system temporary directory.
   *
   * @return string
   *   The absolute path of the system temporary directory.
   */
  protected function temporaryDirectory() : string {
    return FileSystem::getOsTemporaryDirectory();
  }

  /**
   * {@inheritdoc}
   */
  public static function getSubscribedEvents() {
    return [
      AutomaticUpdatesEvents::READINESS_CHECK => 'checkDiskSpace',
    ];
  }

}

Members

Namesort descending Modifiers Type Description Overrides
DiskSpaceValidator::$pathLocator protected property The path locator service.
DiskSpaceValidator::areSameLogicalDisk protected function Checks if two paths are located on the same logical disk.
DiskSpaceValidator::checkDiskSpace public function Checks that there is enough free space to perform automatic updates.
DiskSpaceValidator::freeSpace protected function Wrapper around the disk_free_space() function.
DiskSpaceValidator::getSubscribedEvents public static function Returns an array of event names this subscriber wants to listen to.
DiskSpaceValidator::stat protected function Wrapper around the stat() function.
DiskSpaceValidator::temporaryDirectory protected function Returns the path of the system temporary directory.
DiskSpaceValidator::__construct public function Constructs a DiskSpaceValidator object.
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.