backup_migrate-5.0.0-rc2/src/Drupal/Destination/DrupalDirectoryDestination.php
src/Drupal/Destination/DrupalDirectoryDestination.php
<?php
namespace Drupal\backup_migrate\Drupal\Destination;
use Drupal\backup_migrate\Core\Destination\DirectoryDestination;
use Drupal\backup_migrate\Core\Exception\BackupMigrateException;
use Drupal\backup_migrate\Core\File\BackupFileReadableInterface;
use Drupal\Core\File\Exception\FileException;
use Drupal\Core\File\FileSystemInterface;
use Drupal\Core\StreamWrapper\PrivateStream;
/**
*
*
* @package Drupal\backup_migrate\Drupal\Destination
*/
class DrupalDirectoryDestination extends DirectoryDestination {
/**
* Do the actual file save.
*
* This function is called to save the data file AND the metadata sidecar
* file.
*
* @param \Drupal\backup_migrate\Core\File\BackupFileReadableInterface $file
*
* @throws \Drupal\backup_migrate\Core\Exception\BackupMigrateException
*/
public function saveTheFile(BackupFileReadableInterface $file) {
// Check if the directory exists.
$this->checkDirectory();
try {
// @phpstan-ignore-next-line as it is deprecated in D10.3 and removed from D12.
\Drupal::service('file_system')->move($file->realpath(), $this->idToPath($file->getFullName()), FileSystemInterface::EXISTS_REPLACE);
}
catch (FileException $e) {
return FALSE;
}
}
/**
* Check that the directory can be used for backup.
*
* @throws \Drupal\backup_migrate\Core\Exception\BackupMigrateException
*/
protected function checkDirectory() {
// @todo Figure out if the file is or might be accessible via the web.
$dir = $this->confGet('directory');
$is_private = strpos($dir, 'private://') === 0;
// Attempt to create/prepare the directory if it is in the private
// directory.
if ($is_private) {
if (!PrivateStream::basePath()) {
throw new BackupMigrateException(
"The backup file could not be saved to '%dir' because your private files system path has not been set.",
['%dir' => $dir]
);
}
if (!\Drupal::service('file_system')->prepareDirectory($dir, FileSystemInterface::CREATE_DIRECTORY && FileSystemInterface::MODIFY_PERMISSIONS)) {
throw new BackupMigrateException(
"The backup file could not be saved to '%dir' because the directory could not be created or cannot be written to. Please make sure your private files directory is writable by the web server.",
['%dir' => $dir]
);
}
}
// Not a private directory. Make sure it is outside the web root.
else {
// If the file is local to the server.
$real = \Drupal::service('file_system')->realpath($dir);
if ($real) {
// If the file is within the docroot.
$in_root = strpos($real, DRUPAL_ROOT) === 0;
if ($in_root) {
throw new BackupMigrateException(
"The backup file could not be saved to '%dir' because that directory may be publicly accessible via the web. Please save your backups to the private file directory or a directory outside of the web root.",
['%dir' => $dir]
);
}
}
}
// Do the regular exists/writable checks.
parent::checkDirectory();
// @todo Warn if the realpath cannot be resolved (because we cannot
// determine if the file is publicly accessible).
}
/**
* {@inheritdoc}
*/
public function queryFiles(array $filters = [], $sort = 'datestamp', $sort_direction = SORT_DESC, $count = 100, $start = 0) {
// Get the full list of files.
$out = $this->listFiles($count + $start);
foreach ($out as $key => $file) {
$out[$key] = $this->loadFileMetadata($file);
}
// Filter the output.
if ($filters) {
$out = array_filter($out, function ($file) use ($filters) {
foreach ($filters as $key => $value) {
if ($file->getMeta($key) !== $value) {
return FALSE;
}
}
return TRUE;
});
}
// Sort the files.
if ($sort && $sort_direction) {
uasort($out, function ($a, $b) use ($sort, $sort_direction) {
if ($sort_direction == SORT_DESC) {
if ($sort == 'name') {
return $a->getFullName() <=> $b->getFullName();
}
// @todo fix this in core
return $b->getMeta($sort) <=> $a->getMeta($sort);
}
else {
if ($sort == 'name') {
return $b->getFullName() <=> $a->getFullName();
}
// @todo fix this in core
return $b->getMeta($sort) <=> $a->getMeta($sort);
}
});
}
// Slice the return array.
if ($count || $start) {
$out = array_slice($out, $start, $count);
}
return $out;
}
}
