You are here

class FileDirectorySource in Backup and Migrate 8.4

Class FileDirectorySource.

@package BackupMigrate\Core\Source

Hierarchy

Expanded class hierarchy of FileDirectorySource

2 files declare their use of FileDirectorySource
DrupalPublicFilesSource.php in src/Source/DrupalPublicFilesSource.php
DrupalSiteArchiveSource.php in src/Source/DrupalSiteArchiveSource.php

File

lib/backup_migrate_core/src/Source/FileDirectorySource.php, line 21

Namespace

BackupMigrate\Core\Source
View source
class FileDirectorySource extends PluginBase implements SourceInterface, FileProcessorInterface, PluginCallerInterface {
  use FileProcessorTrait;
  use PluginCallerTrait;

  /**
   * @var \BackupMigrate\Core\Service\ArchiveWriterInterface
   */
  private $archive_writer;

  /**
   * @var \BackupMigrate\Core\Service\ArchiveReaderInterface
   */
  private $archive_reader;

  /**
   * {@inheritdoc}
   */
  public function supportedOps() {
    return [
      'exportToFile' => [],
      'importFromFile' => [],
    ];
  }

  /**
   * {@inheritdoc}
   */
  public function exportToFile() {
    if ($directory = $this
      ->confGet('directory')) {

      // Make sure the directory ends in exactly 1 slash:
      if (substr($directory, -1) !== '/') {
        $directory = $directory . '/';
      }
      if (!($writer = $this
        ->getArchiveWriter())) {
        throw new BackupMigrateException('A file directory source requires an archive writer object.');
      }
      $ext = $writer
        ->getFileExt();
      $file = $this
        ->getTempFileManager()
        ->create($ext);
      if ($files = $this
        ->getFilesToBackup($directory)) {
        $writer
          ->setArchive($file);
        foreach ($files as $new => $real) {
          $writer
            ->addFile($real, $new);
        }
        $writer
          ->closeArchive();
        return $file;
      }
      throw new BackupMigrateException('The directory %dir does not not have any files to be backed up.', [
        '%dir' => $directory,
      ]);
    }
    return FALSE;
  }

  /**
   * {@inheritdoc}
   */
  public function importFromFile(BackupFileReadableInterface $file) {
    if ($directory = $this
      ->confGet('directory')) {

      // Make sure the directory ends in exactly 1 slash:
      if (substr($directory, -1) !== '/') {
        $directory = $directory . '/';
      }
      if (!file_exists($directory)) {
        throw new BackupMigrateException('The directory %dir does not exist to restore to.', [
          '%dir' => $directory,
        ]);
      }
      if (!is_writable($directory)) {
        throw new BackupMigrateException('The directory %dir cannot be written to because of the operating system file permissions.', [
          '%dir' => $directory,
        ]);
      }
      if (!($reader = $this
        ->getArchiveReader())) {
        throw new BackupMigrateException('A file directory source requires an archive reader object.');
      }

      // Check that the file endings match.
      if ($reader
        ->getFileExt() !== $file
        ->getExtLast()) {
        throw new BackupMigrateException('This source expects a .%ext file.', [
          '%ext' => $reader
            ->getFileExt(),
        ]);
      }
      $reader
        ->setArchive($file);
      $reader
        ->extractTo($directory);
      $reader
        ->closeArchive();
      return TRUE;
    }
    return FALSE;
  }

  /**
   * Get a list if files to be backed up from the given directory.
   *
   * @param string $dir The name of the directory to list.
   *
   * @return array
   *
   * @throws \BackupMigrate\Core\Exception\BackupMigrateException
   * @throws \BackupMigrate\Core\Exception\IgnorableException
   *
   * @internal param $directory
   */
  protected function getFilesToBackup($dir) {

    // Add a trailing slash if there is none.
    if (substr($dir, -1) !== '/') {
      $dir .= '/';
    }
    if (!file_exists($dir)) {
      throw new BackupMigrateException('Directory %dir does not exist.', [
        '%dir' => $dir,
      ]);
    }
    if (!is_dir($dir)) {
      throw new BackupMigrateException('The file %dir is not a directory.', [
        '%dir' => $dir,
      ]);
    }
    if (!is_readable($dir)) {
      throw new BackupMigrateException('Directory %dir could not be read from.', [
        '%dir' => $dir,
      ]);
    }

    // Get a filtered list if files from the directory.
    list($out, $errors) = $this
      ->_getFilesFromDirectory($dir);

    // Alert the user to any errors there might have been.
    if ($errors) {
      $count = count($errors);
      $file_list = implode(', ', array_slice($errors, 0, 5));
      if ($count > 5) {
        $file_list .= ', ...';
      }
      if (!$this
        ->confGet('ignore_errors')) {
        throw new IgnorableException('The backup could not be completed because !count files could not be read: (!files).', [
          '!count' => $count,
          '!files' => $file_list,
        ]);
      }
      else {

        // throw new IgnorableException('!count files could not be read: (!files).', ['!files' => $filesmsg]);
        // @TODO: Log the ignored files.
      }
    }
    return $out;
  }

  /**
   * @param $base_path
   *  The name of the directory to list. This must always end in '/'.
   * @param string $subdir
   * @return array
   * @internal param string $dir
   */
  protected function _getFilesFromDirectory($base_path, $subdir = '') {
    $out = $errors = [];

    // Open the directory.
    if (!($handle = opendir($base_path . $subdir))) {
      $errors[] = $base_path . $subdir;
    }
    else {
      while (($file = readdir($handle)) !== FALSE) {

        // If not a dot file and the file name isn't excluded.
        if ($file != '.' && $file != '..') {

          // Get the full path of the file.
          $path = $base_path . $subdir . $file;

          // Allow filters to modify or exclude this path.
          $path = $this
            ->plugins()
            ->call('beforeFileBackup', $path, [
            'source' => $this,
            'base_path' => $base_path,
          ]);
          if ($path) {
            if (is_dir($path)) {
              list($sub_files, $sub_errors) = $this
                ->_getFilesFromDirectory($base_path, $subdir . $file . '/');

              // Add the directory if it is empty.
              if (empty($sub_files)) {
                $out[$subdir . $file] = $path;
              }

              // Add the sub-files to the output.
              $out = array_merge($out, $sub_files);
              $errors = array_merge($errors, $sub_errors);
            }
            else {
              if (is_readable($path)) {
                $out[$subdir . $file] = $path;
              }
              else {
                $errors[] = $path;
              }
            }
          }
        }
      }
      closedir($handle);
    }
    return [
      $out,
      $errors,
    ];
  }

  /**
   * @param \BackupMigrate\Core\Service\ArchiveWriterInterface $writer
   */
  public function setArchiveWriter(ArchiveWriterInterface $writer) {
    $this->archive_writer = $writer;
  }

  /**
   * @return \BackupMigrate\Core\Service\ArchiveWriterInterface
   */
  public function getArchiveWriter() {
    return $this->archive_writer;
  }

  /**
   * @return \BackupMigrate\Core\Service\ArchiveReaderInterface
   */
  public function getArchiveReader() {
    return $this->archive_reader;
  }

  /**
   * @param \BackupMigrate\Core\Service\ArchiveReaderInterface $archive_reader
   */
  public function setArchiveReader($archive_reader) {
    $this->archive_reader = $archive_reader;
  }

  /**
   * Get a definition for user-configurable settings.
   *
   * @param array $params
   *
   * @return array
   */
  public function configSchema($params = []) {
    $schema = [];

    // Init settings.
    if ($params['operation'] == 'initialize') {
      $schema['fields']['directory'] = [
        'type' => 'text',
        'title' => $this
          ->t('Directory Path'),
      ];
    }
    return $schema;
  }

  /**
   * Get the default values for the plugin.
   *
   * @return \BackupMigrate\Core\Config\Config
   */
  public function configDefaults() {
    return new Config([
      'directory' => '',
    ]);
  }

}

Members

Namesort descending Modifiers Type Description Overrides
ConfigurableTrait::$config protected property The object's configuration object.
ConfigurableTrait::$init protected property The initial configuration. These configuration options can be overriden by the config options but will not be overwritten. If the object is re-configured after construction any missing configuration options will revert to these values.
ConfigurableTrait::confGet public function Get a specific value from the configuration.
ConfigurableTrait::config public function Get the configuration object for this item.
ConfigurableTrait::configErrors public function Get any validation errors in the config.
ConfigurableTrait::setConfig public function Set the configuration for all plugins. 1
ConfigurableTrait::__construct public function 2
FileDirectorySource::$archive_reader private property
FileDirectorySource::$archive_writer private property
FileDirectorySource::configDefaults public function Get the default values for the plugin. Overrides ConfigurableTrait::configDefaults 1
FileDirectorySource::configSchema public function Get a definition for user-configurable settings. Overrides ConfigurableTrait::configSchema
FileDirectorySource::exportToFile public function Export this source to the given temp file. This should be the main back up function for this source. Overrides SourceInterface::exportToFile
FileDirectorySource::getArchiveReader public function
FileDirectorySource::getArchiveWriter public function
FileDirectorySource::getFilesToBackup protected function Get a list if files to be backed up from the given directory. 1
FileDirectorySource::importFromFile public function Import to this source from the given backup file. This is the main restore function for this source. Overrides SourceInterface::importFromFile 1
FileDirectorySource::setArchiveReader public function
FileDirectorySource::setArchiveWriter public function
FileDirectorySource::supportedOps public function Get a list of supported operations and their weight. Overrides PluginBase::supportedOps
FileDirectorySource::_getFilesFromDirectory protected function @internal param string $dir
FileProcessorTrait::$tempfilemanager protected property
FileProcessorTrait::alterMime public function Provide the file mime for the given file extension if known.
FileProcessorTrait::getTempFileManager public function Get the temp file manager.
FileProcessorTrait::setTempFileManager public function Inject the temp file manager.
PluginBase::opWeight public function What is the weight of the given operation for this plugin. Overrides PluginInterface::opWeight
PluginBase::supportsOp public function Does this plugin implement the given operation. Overrides PluginInterface::supportsOp
PluginCallerTrait::$plugins protected property
PluginCallerTrait::plugins public function Get the plugin manager.
PluginCallerTrait::setPluginManager public function Inject the plugin manager.
TranslatableTrait::$translator protected property
TranslatableTrait::setTranslator public function
TranslatableTrait::t public function Translate the given string if there is a translator service available.