You are here

abstract class DatabaseFileUtilityBase in Smart IP 8.4

Same name and namespace in other branches
  1. 8.2 src/DatabaseFileUtilityBase.php \Drupal\smart_ip\DatabaseFileUtilityBase
  2. 8.3 src/DatabaseFileUtilityBase.php \Drupal\smart_ip\DatabaseFileUtilityBase

Database file utility methods class wrapper.

@package Drupal\smart_ip

Hierarchy

Expanded class hierarchy of DatabaseFileUtilityBase

4 files declare their use of DatabaseFileUtilityBase
DatabaseFileUtility.php in modules/smart_ip_maxmind_geoip2_bin_db/src/DatabaseFileUtility.php
Contains \Drupal\smart_ip_maxmind_geoip2_bin_db\DatabaseFileUtility.
DatabaseFileUtility.php in modules/smart_ip_ip2location_bin_db/src/DatabaseFileUtility.php
Contains \Drupal\smart_ip_ip2location_bin_db\DatabaseFileUtility.
SmartIpEventSubscriber.php in modules/smart_ip_maxmind_geoip2_bin_db/src/EventSubscriber/SmartIpEventSubscriber.php
Contains \Drupal\smart_ip_maxmind_geoip2_bin_db\EventSubscriber\SmartIpEventSubscriber.
SmartIpEventSubscriber.php in modules/smart_ip_ip2location_bin_db/src/EventSubscriber/SmartIpEventSubscriber.php
Contains \Drupal\smart_ip_ip2location_bin_db\EventSubscriber\SmartIpEventSubscriber.

File

src/DatabaseFileUtilityBase.php, line 22
Contains \Drupal\smart_ip\DatabaseFileUtilityBase.

Namespace

Drupal\smart_ip
View source
abstract class DatabaseFileUtilityBase implements DatabaseFileUtilityInterface {

  /**
   * Download Smart IP's data source module's database timout.
   */
  const DOWNLOAD_TIMEOUT = 600;

  /**
   * Fixed Drupal folder path of Smart IP data source module's database file is
   * stored.
   */
  const DRUPAL_FOLDER = 'private://smart_ip';

  /**
   * Drupal temporary folder path.
   */
  const DRUPAL_TEMP_FOLDER = 'temporary://smart_ip';

  /**
   * Download Smart IP's data source module's database file weekly.
   */
  const DOWNLOAD_WEEKLY = 0;

  /**
   * Download Smart IP's data source module's database file monthly.
   */
  const DOWNLOAD_MONTHLY = 1;

  /**
   * Get Smart IP's data source module's database file's path. This should
   * return the fixed Drupal folder if auto update is on or if custom path is
   * empty with auto update off.
   *
   * @param bool $autoUpdate
   * @param string $customPath
   * @return string
   */
  public static function getPath($autoUpdate, $customPath) {
    if ($autoUpdate == TRUE || $autoUpdate == FALSE && empty($customPath)) {

      /** @var \Drupal\Core\File\FileSystem $filesystem */
      $filesystem = \Drupal::service('file_system');
      return $filesystem
        ->realpath(self::DRUPAL_FOLDER);
    }
    return $customPath;
  }

  /**
   * {@inheritdoc}
   */
  public static function needsUpdate($lastUpdateTime, $autoUpdate = TRUE, $frequency = self::DOWNLOAD_MONTHLY) {
    if ($autoUpdate) {
      $timeNow = strtotime('midnight', \Drupal::time()
        ->getRequestTime());
      $lastUpdateTime = strtotime('midnight', $lastUpdateTime);
      if ($frequency == self::DOWNLOAD_WEEKLY) {
        $wednesday = strtotime('Wednesday this week', $timeNow);
        if ($wednesday <= $timeNow && $wednesday > $lastUpdateTime) {
          return TRUE;
        }
      }
      elseif ($frequency == self::DOWNLOAD_MONTHLY) {
        $firstWed = strtotime('first Wednesday of this month', $timeNow);
        if ($firstWed <= $timeNow && $firstWed > $lastUpdateTime) {
          return TRUE;
        }
      }
    }
    return FALSE;
  }

  /**
   * Download Smart IP's data source module's database file and extract it.
   *
   * @param string $url
   *   URL of the Smart IP's data source module's service provider.
   * @param string $file
   *   File name of the Smart IP's data source module's database including its
   *   extension name.
   * @param string $sourceId
   *   Smart IP data source module's source ID.
   * @return bool
   *   Returns FALSE if process failed.
   */
  protected static function requestDatabaseFile($url, $file, $sourceId) {
    $destination = self::DRUPAL_FOLDER;
    $source = self::DRUPAL_TEMP_FOLDER;

    /** @var \Drupal\Core\File\FileSystem $filesystem */
    $filesystem = \Drupal::service('file_system');
    $sourceRealPath = $filesystem
      ->realpath($source);
    $destinationRealPath = $filesystem
      ->realpath($destination);

    /** @var \Drupal\Core\StreamWrapper\StreamWrapperManager $streamWrapper */
    $streamWrapper = \Drupal::service('stream_wrapper_manager');

    /** @var \Drupal\Core\StreamWrapper\StreamWrapperInterface $destinationStream */
    $destinationStream = $streamWrapper
      ->getViaUri($destination);

    /** @var \Drupal\Core\StreamWrapper\StreamWrapperInterface $sourceStream */
    $sourceStream = $streamWrapper
      ->getViaUri($source);
    if (!file_exists($destination)) {

      // The Smart IP folder does not exist then create it.
      $destinationStream
        ->mkdir($destination, NULL, STREAM_MKDIR_RECURSIVE);
      $filesystem
        ->prepareDirectory($destinationRealPath);
    }
    if (file_exists($destination)) {
      if (file_exists($source)) {

        // Remove old temporary database download directory if still exist.
        $filesystem
          ->deleteRecursive($source);
      }

      // Prepare temporary download directory.
      $sourceStream
        ->mkdir($source, NULL, STREAM_MKDIR_RECURSIVE);

      // Download the Smart IP's data source module's database file.

      /** @var \Drupal\Core\Http\ClientFactory $client */
      $client = \Drupal::service('http_client_factory');

      /** @var \Psr\Http\Message\ResponseInterface $uriData */
      $uriData = $client
        ->fromOptions([
        'timeout' => self::DOWNLOAD_TIMEOUT,
      ])
        ->get($url);

      /** @var \Psr\Http\Message\StreamInterface $data */
      $data = $uriData
        ->getBody();
      $parsedUrl = parse_url($url);
      $archivePath = "{$source}/" . $filesystem
        ->basename($parsedUrl['path']);
      $savedArchivePath = $filesystem
        ->saveData($data, $archivePath, FileSystemInterface::EXISTS_REPLACE);
      if (!$savedArchivePath) {
        $message = t('Failed to download %source.', [
          '%source' => $url,
        ]);
        \Drupal::state()
          ->set('smart_ip.request_db_error_source_id', $sourceId);
        \Drupal::state()
          ->set('smart_ip.request_db_error_message', $message);
        \Drupal::logger('smart_ip')
          ->error($message);
        return FALSE;
      }
      $savedArchiveRealPath = $filesystem
        ->realpath($savedArchivePath);
      $sourceFilePath = "{$source}/{$file}";
      $sourceFileRealPath = "{$sourceRealPath}/{$file}";
      if (file_exists($sourceFilePath)) {

        // Remove old database file from temp extract directory if still exist.
        $sourceStream
          ->unlink($sourceFilePath);
      }

      // Extract it.
      try {

        // Previous function used: update_manager_archive_extract().
        $finfo = new \finfo(FILEINFO_MIME_TYPE);
        if ($finfo
          ->file($savedArchiveRealPath) == 'application/zip') {
          $archive = new Zip($savedArchiveRealPath);
        }
        else {
          $archive = new Tar($savedArchiveRealPath);
        }
        $archive
          ->extract($sourceRealPath);
      } catch (\Exception $e) {
        $extractError = TRUE;
        \Drupal::logger('smart_ip')
          ->debug($e
          ->getMessage());
        if (class_exists('PharData')) {
          try {
            $extractError = FALSE;
            $archive = new \PharData($savedArchiveRealPath);
            $archive
              ->extractTo($sourceRealPath);
          } catch (\Exception $e) {
            \Drupal::logger('smart_ip')
              ->debug($e
              ->getMessage());
            if (!file_exists($sourceFilePath)) {
              $extractError = TRUE;
            }
          }
        }
        if ($extractError) {
          $sourceFp = gzopen($savedArchiveRealPath, 'rb');
          $targetFp = fopen($sourceFileRealPath, 'w');
          while (!gzeof($sourceFp)) {
            $data = gzread($sourceFp, 4096);
            fwrite($targetFp, $data, strlen($data));
          }
          gzclose($sourceFp);
          fclose($targetFp);
        }
      }
      $sourceScanFiles = $filesystem
        ->scanDirectory($sourceRealPath, "/^{$file}\$/");
      foreach ($sourceScanFiles as $sourceScanFile) {
        if ($sourceScanFile->filename == $file) {
          $filesystem
            ->move($sourceScanFile->uri, $sourceFilePath);
          break;
        }
      }

      // Verify it.
      if (!file_exists($sourceFilePath)) {
        $message = t('Failed extracting %file.', [
          '%file' => $savedArchiveRealPath,
        ]);
        \Drupal::state()
          ->set('smart_ip.request_db_error_source_id', $sourceId);
        \Drupal::state()
          ->set('smart_ip.request_db_error_message', $message);
        \Drupal::logger('smart_ip')
          ->error($message);
        return FALSE;
      }
      $destinationFilePath = "{$destination}/{$file}";
      $destinationFileRealPath = $filesystem
        ->realpath($destinationFilePath);
      if (file_exists($destinationFilePath)) {

        // Delete the old Smart IP data source module's database file.
        $destinationStream
          ->unlink($destinationFilePath);
      }
      if ($filesystem
        ->move($sourceFilePath, $destinationFilePath) === FALSE) {
        $message = t('The file %file could not be moved to %destination.', [
          '%file' => $sourceFileRealPath,
          '%destination' => $destinationFileRealPath,
        ]);
        \Drupal::state()
          ->set('smart_ip.request_db_error_source_id', $sourceId);
        \Drupal::state()
          ->set('smart_ip.request_db_error_message', $message);
        \Drupal::logger('smart_ip')
          ->error($message);
        return FALSE;
      }
      else {

        // Delete the temporary download directory.
        $filesystem
          ->deleteRecursive($source);

        // Success! Clear error flag and message.
        \Drupal::state()
          ->set('smart_ip.request_db_error_source_id', '');
        \Drupal::state()
          ->set('smart_ip.request_db_error_message', '');
        \Drupal::logger('smart_ip')
          ->info(t('The database file %file successfully downloaded to %destination', [
          '%file' => $file,
          '%destination' => $destinationFileRealPath,
        ]));
      }
    }
    else {
      $message = t('Your private file system path is not yet configured. Please check your @filesystem.', [
        '@filesystem' => Link::fromTextAndUrl(t('File system'), Url::fromRoute('system.file_system_settings'))
          ->toString(),
      ]);
      \Drupal::state()
        ->set('smart_ip.request_db_error_source_id', $sourceId);
      \Drupal::state()
        ->set('smart_ip.request_db_error_message', $message);
      return FALSE;
    }
    return TRUE;
  }

}

Members

Namesort descending Modifiers Type Description Overrides
DatabaseFileUtilityBase::DOWNLOAD_MONTHLY constant Download Smart IP's data source module's database file monthly.
DatabaseFileUtilityBase::DOWNLOAD_TIMEOUT constant Download Smart IP's data source module's database timout.
DatabaseFileUtilityBase::DOWNLOAD_WEEKLY constant Download Smart IP's data source module's database file weekly.
DatabaseFileUtilityBase::DRUPAL_FOLDER constant Fixed Drupal folder path of Smart IP data source module's database file is stored.
DatabaseFileUtilityBase::DRUPAL_TEMP_FOLDER constant Drupal temporary folder path.
DatabaseFileUtilityBase::getPath public static function Get Smart IP's data source module's database file's path. This should return the fixed Drupal folder if auto update is on or if custom path is empty with auto update off. Overrides DatabaseFileUtilityInterface::getPath
DatabaseFileUtilityBase::needsUpdate public static function Checks if Smart IP's data source module's database file needs update. Overrides DatabaseFileUtilityInterface::needsUpdate
DatabaseFileUtilityBase::requestDatabaseFile protected static function Download Smart IP's data source module's database file and extract it.
DatabaseFileUtilityInterface::getFilename public static function Get Smart IP's data source module's database filename. 2