Primo Committ
This commit is contained in:
306
vendor/spatie/laravel-backup/src/Tasks/Backup/BackupJob.php
vendored
Normal file
306
vendor/spatie/laravel-backup/src/Tasks/Backup/BackupJob.php
vendored
Normal file
@@ -0,0 +1,306 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\Backup\Tasks\Backup;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Exception;
|
||||
use Illuminate\Support\Collection;
|
||||
use Spatie\Backup\BackupDestination\BackupDestination;
|
||||
use Spatie\Backup\Events\BackupHasFailed;
|
||||
use Spatie\Backup\Events\BackupManifestWasCreated;
|
||||
use Spatie\Backup\Events\BackupWasSuccessful;
|
||||
use Spatie\Backup\Events\BackupZipWasCreated;
|
||||
use Spatie\Backup\Events\DumpingDatabase;
|
||||
use Spatie\Backup\Exceptions\InvalidBackupJob;
|
||||
use Spatie\DbDumper\Compressors\GzipCompressor;
|
||||
use Spatie\DbDumper\Databases\MongoDb;
|
||||
use Spatie\DbDumper\Databases\Sqlite;
|
||||
use Spatie\DbDumper\DbDumper;
|
||||
use Spatie\TemporaryDirectory\TemporaryDirectory;
|
||||
|
||||
class BackupJob
|
||||
{
|
||||
public const FILENAME_FORMAT = 'Y-m-d-H-i-s.\z\i\p';
|
||||
|
||||
/** @var \Spatie\Backup\Tasks\Backup\FileSelection */
|
||||
protected $fileSelection;
|
||||
|
||||
/** @var \Illuminate\Support\Collection */
|
||||
protected $dbDumpers;
|
||||
|
||||
/** @var \Illuminate\Support\Collection */
|
||||
protected $backupDestinations;
|
||||
|
||||
/** @var string */
|
||||
protected $filename;
|
||||
|
||||
/** @var \Spatie\TemporaryDirectory\TemporaryDirectory */
|
||||
protected $temporaryDirectory;
|
||||
|
||||
/** @var bool */
|
||||
protected $sendNotifications = true;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->dontBackupFilesystem();
|
||||
$this->dontBackupDatabases();
|
||||
$this->setDefaultFilename();
|
||||
|
||||
$this->backupDestinations = new Collection();
|
||||
}
|
||||
|
||||
public function dontBackupFilesystem(): self
|
||||
{
|
||||
$this->fileSelection = FileSelection::create();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function onlyDbName(array $allowedDbNames): self
|
||||
{
|
||||
$this->dbDumpers = $this->dbDumpers->filter(
|
||||
function (DbDumper $dbDumper, string $connectionName) use ($allowedDbNames) {
|
||||
return in_array($connectionName, $allowedDbNames);
|
||||
}
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function dontBackupDatabases(): self
|
||||
{
|
||||
$this->dbDumpers = new Collection();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function disableNotifications(): self
|
||||
{
|
||||
$this->sendNotifications = false;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setDefaultFilename(): self
|
||||
{
|
||||
$this->filename = Carbon::now()->format(static::FILENAME_FORMAT);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setFileSelection(FileSelection $fileSelection): self
|
||||
{
|
||||
$this->fileSelection = $fileSelection;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setDbDumpers(Collection $dbDumpers): self
|
||||
{
|
||||
$this->dbDumpers = $dbDumpers;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setFilename(string $filename): self
|
||||
{
|
||||
$this->filename = $filename;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function onlyBackupTo(string $diskName): self
|
||||
{
|
||||
$this->backupDestinations = $this->backupDestinations->filter(function (BackupDestination $backupDestination) use ($diskName) {
|
||||
return $backupDestination->diskName() === $diskName;
|
||||
});
|
||||
|
||||
if (! count($this->backupDestinations)) {
|
||||
throw InvalidBackupJob::destinationDoesNotExist($diskName);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setBackupDestinations(Collection $backupDestinations): self
|
||||
{
|
||||
$this->backupDestinations = $backupDestinations;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function run()
|
||||
{
|
||||
$temporaryDirectoryPath = config('backup.backup.temporary_directory') ?? storage_path('app/backup-temp');
|
||||
|
||||
$this->temporaryDirectory = (new TemporaryDirectory($temporaryDirectoryPath))
|
||||
->name('temp')
|
||||
->force()
|
||||
->create()
|
||||
->empty();
|
||||
|
||||
try {
|
||||
if (! count($this->backupDestinations)) {
|
||||
throw InvalidBackupJob::noDestinationsSpecified();
|
||||
}
|
||||
|
||||
$manifest = $this->createBackupManifest();
|
||||
|
||||
if (! $manifest->count()) {
|
||||
throw InvalidBackupJob::noFilesToBeBackedUp();
|
||||
}
|
||||
|
||||
$zipFile = $this->createZipContainingEveryFileInManifest($manifest);
|
||||
|
||||
$this->copyToBackupDestinations($zipFile);
|
||||
} catch (Exception $exception) {
|
||||
consoleOutput()->error("Backup failed because {$exception->getMessage()}.".PHP_EOL.$exception->getTraceAsString());
|
||||
|
||||
$this->sendNotification(new BackupHasFailed($exception));
|
||||
|
||||
$this->temporaryDirectory->delete();
|
||||
|
||||
throw $exception;
|
||||
}
|
||||
|
||||
$this->temporaryDirectory->delete();
|
||||
}
|
||||
|
||||
protected function createBackupManifest(): Manifest
|
||||
{
|
||||
$databaseDumps = $this->dumpDatabases();
|
||||
|
||||
consoleOutput()->info('Determining files to backup...');
|
||||
|
||||
$manifest = Manifest::create($this->temporaryDirectory->path('manifest.txt'))
|
||||
->addFiles($databaseDumps)
|
||||
->addFiles($this->filesToBeBackedUp());
|
||||
|
||||
$this->sendNotification(new BackupManifestWasCreated($manifest));
|
||||
|
||||
return $manifest;
|
||||
}
|
||||
|
||||
public function filesToBeBackedUp()
|
||||
{
|
||||
$this->fileSelection->excludeFilesFrom($this->directoriesUsedByBackupJob());
|
||||
|
||||
return $this->fileSelection->selectedFiles();
|
||||
}
|
||||
|
||||
protected function directoriesUsedByBackupJob(): array
|
||||
{
|
||||
return $this->backupDestinations
|
||||
->filter(function (BackupDestination $backupDestination) {
|
||||
return $backupDestination->filesystemType() === 'local';
|
||||
})
|
||||
->map(function (BackupDestination $backupDestination) {
|
||||
return $backupDestination->disk()->getDriver()->getAdapter()->applyPathPrefix('').$backupDestination->backupName();
|
||||
})
|
||||
->each(function (string $backupDestinationDirectory) {
|
||||
$this->fileSelection->excludeFilesFrom($backupDestinationDirectory);
|
||||
})
|
||||
->push($this->temporaryDirectory->path())
|
||||
->toArray();
|
||||
}
|
||||
|
||||
protected function createZipContainingEveryFileInManifest(Manifest $manifest)
|
||||
{
|
||||
consoleOutput()->info("Zipping {$manifest->count()} files and directories...");
|
||||
|
||||
$pathToZip = $this->temporaryDirectory->path(config('backup.backup.destination.filename_prefix').$this->filename);
|
||||
|
||||
$zip = Zip::createForManifest($manifest, $pathToZip);
|
||||
|
||||
consoleOutput()->info("Created zip containing {$zip->count()} files and directories. Size is {$zip->humanReadableSize()}");
|
||||
|
||||
if ($this->sendNotifications) {
|
||||
$this->sendNotification(new BackupZipWasCreated($pathToZip));
|
||||
} else {
|
||||
app()->call('\Spatie\Backup\Listeners\EncryptBackupArchive@handle', ['event' => new BackupZipWasCreated($pathToZip)]);
|
||||
}
|
||||
|
||||
return $pathToZip;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dumps the databases to the given directory.
|
||||
* Returns an array with paths to the dump files.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function dumpDatabases(): array
|
||||
{
|
||||
return $this->dbDumpers->map(function (DbDumper $dbDumper, $key) {
|
||||
consoleOutput()->info("Dumping database {$dbDumper->getDbName()}...");
|
||||
|
||||
$dbType = mb_strtolower(basename(str_replace('\\', '/', get_class($dbDumper))));
|
||||
|
||||
$dbName = $dbDumper->getDbName();
|
||||
if ($dbDumper instanceof Sqlite) {
|
||||
$dbName = $key.'-database';
|
||||
}
|
||||
|
||||
$fileName = "{$dbType}-{$dbName}.{$this->getExtension($dbDumper)}";
|
||||
|
||||
if (config('backup.backup.gzip_database_dump')) {
|
||||
$dbDumper->useCompressor(new GzipCompressor());
|
||||
$fileName .= '.'.$dbDumper->getCompressorExtension();
|
||||
}
|
||||
|
||||
if ($compressor = config('backup.backup.database_dump_compressor')) {
|
||||
$dbDumper->useCompressor(new $compressor());
|
||||
$fileName .= '.'.$dbDumper->getCompressorExtension();
|
||||
}
|
||||
|
||||
$temporaryFilePath = $this->temporaryDirectory->path('db-dumps'.DIRECTORY_SEPARATOR.$fileName);
|
||||
|
||||
event(new DumpingDatabase($dbDumper));
|
||||
|
||||
$dbDumper->dumpToFile($temporaryFilePath);
|
||||
|
||||
return $temporaryFilePath;
|
||||
})->toArray();
|
||||
}
|
||||
|
||||
protected function copyToBackupDestinations(string $path)
|
||||
{
|
||||
$this->backupDestinations->each(function (BackupDestination $backupDestination) use ($path) {
|
||||
try {
|
||||
consoleOutput()->info("Copying zip to disk named {$backupDestination->diskName()}...");
|
||||
|
||||
$backupDestination->write($path);
|
||||
|
||||
consoleOutput()->info("Successfully copied zip to disk named {$backupDestination->diskName()}.");
|
||||
|
||||
$this->sendNotification(new BackupWasSuccessful($backupDestination));
|
||||
} catch (Exception $exception) {
|
||||
consoleOutput()->error("Copying zip failed because: {$exception->getMessage()}.");
|
||||
|
||||
$this->sendNotification(new BackupHasFailed($exception, $backupDestination ?? null));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected function sendNotification($notification)
|
||||
{
|
||||
if ($this->sendNotifications) {
|
||||
rescue(function () use ($notification) {
|
||||
event($notification);
|
||||
}, function () {
|
||||
consoleOutput()->error('Sending notification failed');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
protected function getExtension(DbDumper $dbDumper): string
|
||||
{
|
||||
if ($extension = config('backup.backup.database_dump_file_extension')) {
|
||||
return $extension;
|
||||
}
|
||||
|
||||
return $dbDumper instanceof MongoDb
|
||||
? 'archive'
|
||||
: 'sql';
|
||||
}
|
||||
}
|
||||
33
vendor/spatie/laravel-backup/src/Tasks/Backup/BackupJobFactory.php
vendored
Normal file
33
vendor/spatie/laravel-backup/src/Tasks/Backup/BackupJobFactory.php
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\Backup\Tasks\Backup;
|
||||
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Collection;
|
||||
use Spatie\Backup\BackupDestination\BackupDestinationFactory;
|
||||
|
||||
class BackupJobFactory
|
||||
{
|
||||
public static function createFromArray(array $config): BackupJob
|
||||
{
|
||||
return (new BackupJob())
|
||||
->setFileSelection(static::createFileSelection($config['backup']['source']['files']))
|
||||
->setDbDumpers(static::createDbDumpers($config['backup']['source']['databases']))
|
||||
->setBackupDestinations(BackupDestinationFactory::createFromArray($config['backup']));
|
||||
}
|
||||
|
||||
protected static function createFileSelection(array $sourceFiles): FileSelection
|
||||
{
|
||||
return FileSelection::create($sourceFiles['include'])
|
||||
->excludeFilesFrom($sourceFiles['exclude'])
|
||||
->shouldFollowLinks(isset($sourceFiles['follow_links']) && $sourceFiles['follow_links'])
|
||||
->shouldIgnoreUnreadableDirs(Arr::get($sourceFiles, 'ignore_unreadable_directories', false));
|
||||
}
|
||||
|
||||
protected static function createDbDumpers(array $dbConnectionNames): Collection
|
||||
{
|
||||
return collect($dbConnectionNames)->mapWithKeys(function (string $dbConnectionName) {
|
||||
return [$dbConnectionName => DbDumperFactory::createFromConnection($dbConnectionName)];
|
||||
});
|
||||
}
|
||||
}
|
||||
138
vendor/spatie/laravel-backup/src/Tasks/Backup/DbDumperFactory.php
vendored
Normal file
138
vendor/spatie/laravel-backup/src/Tasks/Backup/DbDumperFactory.php
vendored
Normal file
@@ -0,0 +1,138 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\Backup\Tasks\Backup;
|
||||
|
||||
use Exception;
|
||||
use Illuminate\Database\ConfigurationUrlParser;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Str;
|
||||
use Spatie\Backup\Exceptions\CannotCreateDbDumper;
|
||||
use Spatie\DbDumper\Databases\MongoDb;
|
||||
use Spatie\DbDumper\Databases\MySql;
|
||||
use Spatie\DbDumper\Databases\PostgreSql;
|
||||
use Spatie\DbDumper\Databases\Sqlite;
|
||||
use Spatie\DbDumper\DbDumper;
|
||||
|
||||
class DbDumperFactory
|
||||
{
|
||||
protected static $custom = [];
|
||||
|
||||
public static function createFromConnection(string $dbConnectionName): DbDumper
|
||||
{
|
||||
$parser = new ConfigurationUrlParser();
|
||||
|
||||
if (config("database.connections.{$dbConnectionName}") === null) {
|
||||
throw CannotCreateDbDumper::unsupportedDriver($dbConnectionName);
|
||||
}
|
||||
|
||||
try {
|
||||
$dbConfig = $parser->parseConfiguration(config("database.connections.{$dbConnectionName}"));
|
||||
} catch (Exception $e) {
|
||||
throw CannotCreateDbDumper::unsupportedDriver($dbConnectionName);
|
||||
}
|
||||
|
||||
if (isset($dbConfig['read'])) {
|
||||
$dbConfig = Arr::except(
|
||||
array_merge($dbConfig, $dbConfig['read']),
|
||||
['read', 'write']
|
||||
);
|
||||
}
|
||||
|
||||
$dbDumper = static::forDriver($dbConfig['driver'] ?? '')
|
||||
->setHost(Arr::first(Arr::wrap($dbConfig['host'] ?? '')))
|
||||
->setDbName($dbConfig['database'])
|
||||
->setUserName($dbConfig['username'] ?? '')
|
||||
->setPassword($dbConfig['password'] ?? '');
|
||||
|
||||
if ($dbDumper instanceof MySql) {
|
||||
$dbDumper->setDefaultCharacterSet($dbConfig['charset'] ?? '');
|
||||
}
|
||||
|
||||
if ($dbDumper instanceof MongoDb) {
|
||||
$dbDumper->setAuthenticationDatabase($dbConfig['dump']['mongodb_user_auth'] ?? '');
|
||||
}
|
||||
|
||||
if (isset($dbConfig['port'])) {
|
||||
$dbDumper = $dbDumper->setPort($dbConfig['port']);
|
||||
}
|
||||
|
||||
if (isset($dbConfig['dump'])) {
|
||||
$dbDumper = static::processExtraDumpParameters($dbConfig['dump'], $dbDumper);
|
||||
}
|
||||
|
||||
if (isset($dbConfig['unix_socket'])) {
|
||||
$dbDumper = $dbDumper->setSocket($dbConfig['unix_socket']);
|
||||
}
|
||||
|
||||
return $dbDumper;
|
||||
}
|
||||
|
||||
public static function extend(string $driver, callable $callback)
|
||||
{
|
||||
static::$custom[$driver] = $callback;
|
||||
}
|
||||
|
||||
protected static function forDriver($dbDriver): DbDumper
|
||||
{
|
||||
$driver = strtolower($dbDriver);
|
||||
|
||||
if (isset(static::$custom[$driver])) {
|
||||
return (static::$custom[$driver])();
|
||||
}
|
||||
|
||||
if ($driver === 'mysql' || $driver === 'mariadb') {
|
||||
return new MySql();
|
||||
}
|
||||
|
||||
if ($driver === 'pgsql') {
|
||||
return new PostgreSql();
|
||||
}
|
||||
|
||||
if ($driver === 'sqlite') {
|
||||
return new Sqlite();
|
||||
}
|
||||
|
||||
if ($driver === 'mongodb') {
|
||||
return new MongoDb();
|
||||
}
|
||||
|
||||
throw CannotCreateDbDumper::unsupportedDriver($driver);
|
||||
}
|
||||
|
||||
protected static function processExtraDumpParameters(array $dumpConfiguration, DbDumper $dbDumper): DbDumper
|
||||
{
|
||||
collect($dumpConfiguration)->each(function ($configValue, $configName) use ($dbDumper) {
|
||||
$methodName = lcfirst(Str::studly(is_numeric($configName) ? $configValue : $configName));
|
||||
$methodValue = is_numeric($configName) ? null : $configValue;
|
||||
|
||||
$methodName = static::determineValidMethodName($dbDumper, $methodName);
|
||||
|
||||
if (method_exists($dbDumper, $methodName)) {
|
||||
static::callMethodOnDumper($dbDumper, $methodName, $methodValue);
|
||||
}
|
||||
});
|
||||
|
||||
return $dbDumper;
|
||||
}
|
||||
|
||||
protected static function callMethodOnDumper(DbDumper $dbDumper, string $methodName, $methodValue): DbDumper
|
||||
{
|
||||
if (! $methodValue) {
|
||||
$dbDumper->$methodName();
|
||||
|
||||
return $dbDumper;
|
||||
}
|
||||
|
||||
$dbDumper->$methodName($methodValue);
|
||||
|
||||
return $dbDumper;
|
||||
}
|
||||
|
||||
protected static function determineValidMethodName(DbDumper $dbDumper, string $methodName): string
|
||||
{
|
||||
return collect([$methodName, 'set'.ucfirst($methodName)])
|
||||
->first(function (string $methodName) use ($dbDumper) {
|
||||
return method_exists($dbDumper, $methodName);
|
||||
}, '');
|
||||
}
|
||||
}
|
||||
186
vendor/spatie/laravel-backup/src/Tasks/Backup/FileSelection.php
vendored
Normal file
186
vendor/spatie/laravel-backup/src/Tasks/Backup/FileSelection.php
vendored
Normal file
@@ -0,0 +1,186 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\Backup\Tasks\Backup;
|
||||
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Str;
|
||||
use Symfony\Component\Finder\Finder;
|
||||
|
||||
class FileSelection
|
||||
{
|
||||
/** @var \Illuminate\Support\Collection */
|
||||
protected $includeFilesAndDirectories;
|
||||
|
||||
/** @var \Illuminate\Support\Collection */
|
||||
protected $excludeFilesAndDirectories;
|
||||
|
||||
/** @var bool */
|
||||
protected $shouldFollowLinks = false;
|
||||
|
||||
/** @var bool */
|
||||
protected $shouldIgnoreUnreadableDirs = false;
|
||||
|
||||
/**
|
||||
* @param array|string $includeFilesAndDirectories
|
||||
*
|
||||
* @return \Spatie\Backup\Tasks\Backup\FileSelection
|
||||
*/
|
||||
public static function create($includeFilesAndDirectories = []): self
|
||||
{
|
||||
return new static($includeFilesAndDirectories);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array|string $includeFilesAndDirectories
|
||||
*/
|
||||
public function __construct($includeFilesAndDirectories = [])
|
||||
{
|
||||
$this->includeFilesAndDirectories = collect($includeFilesAndDirectories);
|
||||
|
||||
$this->excludeFilesAndDirectories = collect();
|
||||
}
|
||||
|
||||
/**
|
||||
* Do not included the given files and directories.
|
||||
*
|
||||
* @param array|string $excludeFilesAndDirectories
|
||||
*
|
||||
* @return \Spatie\Backup\Tasks\Backup\FileSelection
|
||||
*/
|
||||
public function excludeFilesFrom($excludeFilesAndDirectories): self
|
||||
{
|
||||
$this->excludeFilesAndDirectories = $this->excludeFilesAndDirectories->merge($this->sanitize($excludeFilesAndDirectories));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function shouldFollowLinks(bool $shouldFollowLinks): self
|
||||
{
|
||||
$this->shouldFollowLinks = $shouldFollowLinks;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set if it should ignore the unreadable directories.
|
||||
*
|
||||
* @param bool $ignoreUnreadableDirs
|
||||
*
|
||||
* @return \Spatie\Backup\Tasks\Backup\FileSelection
|
||||
*/
|
||||
public function shouldIgnoreUnreadableDirs(bool $ignoreUnreadableDirs): self
|
||||
{
|
||||
$this->shouldIgnoreUnreadableDirs = $ignoreUnreadableDirs;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Generator|string[]
|
||||
*/
|
||||
public function selectedFiles()
|
||||
{
|
||||
if ($this->includeFilesAndDirectories->isEmpty()) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$finder = (new Finder())
|
||||
->ignoreDotFiles(false)
|
||||
->ignoreVCS(false);
|
||||
|
||||
if ($this->shouldFollowLinks) {
|
||||
$finder->followLinks();
|
||||
}
|
||||
|
||||
if ($this->shouldIgnoreUnreadableDirs) {
|
||||
$finder->ignoreUnreadableDirs();
|
||||
}
|
||||
|
||||
foreach ($this->includedFiles() as $includedFile) {
|
||||
yield $includedFile;
|
||||
}
|
||||
|
||||
if (! count($this->includedDirectories())) {
|
||||
return;
|
||||
}
|
||||
|
||||
$finder->in($this->includedDirectories());
|
||||
|
||||
foreach ($finder->getIterator() as $file) {
|
||||
if ($this->shouldExclude($file)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
yield $file->getPathname();
|
||||
}
|
||||
}
|
||||
|
||||
protected function includedFiles(): array
|
||||
{
|
||||
return $this->includeFilesAndDirectories->filter(function ($path) {
|
||||
return is_file($path);
|
||||
})->toArray();
|
||||
}
|
||||
|
||||
protected function includedDirectories(): array
|
||||
{
|
||||
return $this->includeFilesAndDirectories->reject(function ($path) {
|
||||
return is_file($path);
|
||||
})->toArray();
|
||||
}
|
||||
|
||||
protected function shouldExclude(string $path): bool
|
||||
{
|
||||
$path = realpath($path);
|
||||
if (is_dir($path)) {
|
||||
$path .= DIRECTORY_SEPARATOR ;
|
||||
}
|
||||
foreach ($this->excludeFilesAndDirectories as $excludedPath) {
|
||||
if (Str::startsWith($path, $excludedPath.(is_dir($excludedPath) ? DIRECTORY_SEPARATOR : ''))) {
|
||||
if ($path != $excludedPath && is_file($excludedPath)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|array $paths
|
||||
*
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
protected function sanitize($paths): Collection
|
||||
{
|
||||
return collect($paths)
|
||||
->reject(function ($path) {
|
||||
return $path === '';
|
||||
})
|
||||
->flatMap(function ($path) {
|
||||
return $this->getMatchingPaths($path);
|
||||
})
|
||||
->map(function ($path) {
|
||||
return realpath($path);
|
||||
})
|
||||
->reject(function ($path) {
|
||||
return $path === false;
|
||||
});
|
||||
}
|
||||
|
||||
protected function getMatchingPaths(string $path): array
|
||||
{
|
||||
if ($this->canUseGlobBrace($path)) {
|
||||
return glob(str_replace('*', '{.[!.],}*', $path), GLOB_BRACE);
|
||||
}
|
||||
|
||||
return glob($path);
|
||||
}
|
||||
|
||||
protected function canUseGlobBrace(string $path): bool
|
||||
{
|
||||
return strpos($path, '*') !== false && defined('GLOB_BRACE');
|
||||
}
|
||||
}
|
||||
74
vendor/spatie/laravel-backup/src/Tasks/Backup/Manifest.php
vendored
Normal file
74
vendor/spatie/laravel-backup/src/Tasks/Backup/Manifest.php
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\Backup\Tasks\Backup;
|
||||
|
||||
use Countable;
|
||||
use SplFileObject;
|
||||
|
||||
class Manifest implements Countable
|
||||
{
|
||||
/** @var string */
|
||||
protected $manifestPath;
|
||||
|
||||
public static function create(string $manifestPath): self
|
||||
{
|
||||
return new static($manifestPath);
|
||||
}
|
||||
|
||||
public function __construct(string $manifestPath)
|
||||
{
|
||||
$this->manifestPath = $manifestPath;
|
||||
|
||||
touch($manifestPath);
|
||||
}
|
||||
|
||||
public function path(): string
|
||||
{
|
||||
return $this->manifestPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array|string $filePaths
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function addFiles($filePaths): self
|
||||
{
|
||||
if (is_string($filePaths)) {
|
||||
$filePaths = [$filePaths];
|
||||
}
|
||||
|
||||
foreach ($filePaths as $filePath) {
|
||||
if (! empty($filePath)) {
|
||||
file_put_contents($this->manifestPath, $filePath.PHP_EOL, FILE_APPEND);
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Generator|string[]
|
||||
*/
|
||||
public function files()
|
||||
{
|
||||
$file = new SplFileObject($this->path());
|
||||
|
||||
while (! $file->eof()) {
|
||||
$filePath = $file->fgets();
|
||||
|
||||
if (! empty($filePath)) {
|
||||
yield trim($filePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function count(): int
|
||||
{
|
||||
$file = new SplFileObject($this->manifestPath, 'r');
|
||||
|
||||
$file->seek(PHP_INT_MAX);
|
||||
|
||||
return $file->key();
|
||||
}
|
||||
}
|
||||
127
vendor/spatie/laravel-backup/src/Tasks/Backup/Zip.php
vendored
Normal file
127
vendor/spatie/laravel-backup/src/Tasks/Backup/Zip.php
vendored
Normal file
@@ -0,0 +1,127 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\Backup\Tasks\Backup;
|
||||
|
||||
use Illuminate\Support\Str;
|
||||
use Spatie\Backup\Helpers\Format;
|
||||
use ZipArchive;
|
||||
|
||||
class Zip
|
||||
{
|
||||
/** @var \ZipArchive */
|
||||
protected $zipFile;
|
||||
|
||||
/** @var int */
|
||||
protected $fileCount = 0;
|
||||
|
||||
/** @var string */
|
||||
protected $pathToZip;
|
||||
|
||||
public static function createForManifest(Manifest $manifest, string $pathToZip): self
|
||||
{
|
||||
$relativePath = config('backup.backup.source.files.relative_path') ?
|
||||
rtrim(config('backup.backup.source.files.relative_path'), DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR : false;
|
||||
|
||||
$zip = new static($pathToZip);
|
||||
|
||||
$zip->open();
|
||||
|
||||
foreach ($manifest->files() as $file) {
|
||||
$zip->add($file, self::determineNameOfFileInZip($file, $pathToZip, $relativePath));
|
||||
}
|
||||
|
||||
$zip->close();
|
||||
|
||||
return $zip;
|
||||
}
|
||||
|
||||
protected static function determineNameOfFileInZip(string $pathToFile, string $pathToZip, string $relativePath)
|
||||
{
|
||||
$fileDirectory = pathinfo($pathToFile, PATHINFO_DIRNAME) . DIRECTORY_SEPARATOR;
|
||||
|
||||
$zipDirectory = pathinfo($pathToZip, PATHINFO_DIRNAME) . DIRECTORY_SEPARATOR;
|
||||
|
||||
if (Str::startsWith($fileDirectory, $zipDirectory)) {
|
||||
return str_replace($zipDirectory, '', $pathToFile);
|
||||
}
|
||||
|
||||
if ($relativePath && $relativePath != DIRECTORY_SEPARATOR && Str::startsWith($fileDirectory, $relativePath)) {
|
||||
return str_replace($relativePath, '', $pathToFile);
|
||||
}
|
||||
|
||||
return $pathToFile;
|
||||
}
|
||||
|
||||
public function __construct(string $pathToZip)
|
||||
{
|
||||
$this->zipFile = new ZipArchive();
|
||||
|
||||
$this->pathToZip = $pathToZip;
|
||||
|
||||
$this->open();
|
||||
}
|
||||
|
||||
public function path(): string
|
||||
{
|
||||
return $this->pathToZip;
|
||||
}
|
||||
|
||||
public function size(): float
|
||||
{
|
||||
if ($this->fileCount === 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return filesize($this->pathToZip);
|
||||
}
|
||||
|
||||
public function humanReadableSize(): string
|
||||
{
|
||||
return Format::humanReadableSize($this->size());
|
||||
}
|
||||
|
||||
public function open()
|
||||
{
|
||||
$this->zipFile->open($this->pathToZip, ZipArchive::CREATE);
|
||||
}
|
||||
|
||||
public function close()
|
||||
{
|
||||
$this->zipFile->close();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|array $files
|
||||
* @param string $nameInZip
|
||||
*
|
||||
* @return \Spatie\Backup\Tasks\Backup\Zip
|
||||
*/
|
||||
public function add($files, string $nameInZip = null): self
|
||||
{
|
||||
if (is_array($files)) {
|
||||
$nameInZip = null;
|
||||
}
|
||||
|
||||
if (is_string($files)) {
|
||||
$files = [$files];
|
||||
}
|
||||
|
||||
foreach ($files as $file) {
|
||||
if (is_dir($file)) {
|
||||
$this->zipFile->addEmptyDir(ltrim($nameInZip ?: $file, DIRECTORY_SEPARATOR));
|
||||
}
|
||||
|
||||
if (is_file($file)) {
|
||||
$this->zipFile->addFile($file, ltrim($nameInZip, DIRECTORY_SEPARATOR)).PHP_EOL;
|
||||
}
|
||||
$this->fileCount++;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function count(): int
|
||||
{
|
||||
return $this->fileCount;
|
||||
}
|
||||
}
|
||||
66
vendor/spatie/laravel-backup/src/Tasks/Cleanup/CleanupJob.php
vendored
Normal file
66
vendor/spatie/laravel-backup/src/Tasks/Cleanup/CleanupJob.php
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\Backup\Tasks\Cleanup;
|
||||
|
||||
use Exception;
|
||||
use Illuminate\Support\Collection;
|
||||
use Spatie\Backup\BackupDestination\BackupDestination;
|
||||
use Spatie\Backup\Events\CleanupHasFailed;
|
||||
use Spatie\Backup\Events\CleanupWasSuccessful;
|
||||
use Spatie\Backup\Helpers\Format;
|
||||
|
||||
class CleanupJob
|
||||
{
|
||||
/** @var \Illuminate\Support\Collection */
|
||||
protected $backupDestinations;
|
||||
|
||||
/** @var \Spatie\Backup\Tasks\Cleanup\CleanupStrategy */
|
||||
protected $strategy;
|
||||
|
||||
/** @var bool */
|
||||
protected $sendNotifications = true;
|
||||
|
||||
public function __construct(Collection $backupDestinations, CleanupStrategy $strategy, bool $disableNotifications = false)
|
||||
{
|
||||
$this->backupDestinations = $backupDestinations;
|
||||
|
||||
$this->strategy = $strategy;
|
||||
|
||||
$this->sendNotifications = ! $disableNotifications;
|
||||
}
|
||||
|
||||
public function run()
|
||||
{
|
||||
$this->backupDestinations->each(function (BackupDestination $backupDestination) {
|
||||
try {
|
||||
if (! $backupDestination->isReachable()) {
|
||||
throw new Exception("Could not connect to disk {$backupDestination->diskName()} because: {$backupDestination->connectionError()}");
|
||||
}
|
||||
|
||||
consoleOutput()->info("Cleaning backups of {$backupDestination->backupName()} on disk {$backupDestination->diskName()}...");
|
||||
|
||||
$this->strategy
|
||||
->setBackupDestination($backupDestination)
|
||||
->deleteOldBackups($backupDestination->backups());
|
||||
|
||||
$this->sendNotification(new CleanupWasSuccessful($backupDestination));
|
||||
|
||||
$usedStorage = Format::humanReadableSize($backupDestination->fresh()->usedStorage());
|
||||
consoleOutput()->info("Used storage after cleanup: {$usedStorage}.");
|
||||
} catch (Exception $exception) {
|
||||
consoleOutput()->error("Cleanup failed because: {$exception->getMessage()}.");
|
||||
|
||||
$this->sendNotification(new CleanupHasFailed($exception));
|
||||
|
||||
throw $exception;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected function sendNotification($notification)
|
||||
{
|
||||
if ($this->sendNotifications) {
|
||||
event($notification);
|
||||
}
|
||||
}
|
||||
}
|
||||
43
vendor/spatie/laravel-backup/src/Tasks/Cleanup/CleanupStrategy.php
vendored
Normal file
43
vendor/spatie/laravel-backup/src/Tasks/Cleanup/CleanupStrategy.php
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\Backup\Tasks\Cleanup;
|
||||
|
||||
use Illuminate\Contracts\Config\Repository;
|
||||
use Spatie\Backup\BackupDestination\BackupCollection;
|
||||
use Spatie\Backup\BackupDestination\BackupDestination;
|
||||
|
||||
abstract class CleanupStrategy
|
||||
{
|
||||
/** @var \Illuminate\Contracts\Config\Repository */
|
||||
protected $config;
|
||||
|
||||
/** @var \Spatie\Backup\BackupDestination\BackupDestination */
|
||||
protected $backupDestination;
|
||||
|
||||
public function __construct(Repository $config)
|
||||
{
|
||||
$this->config = $config;
|
||||
}
|
||||
|
||||
abstract public function deleteOldBackups(BackupCollection $backups);
|
||||
|
||||
/**
|
||||
* @param \Spatie\Backup\BackupDestination\BackupDestination $backupDestination
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setBackupDestination(BackupDestination $backupDestination)
|
||||
{
|
||||
$this->backupDestination = $backupDestination;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Spatie\Backup\BackupDestination\BackupDestination
|
||||
*/
|
||||
public function backupDestination(): BackupDestination
|
||||
{
|
||||
return $this->backupDestination;
|
||||
}
|
||||
}
|
||||
31
vendor/spatie/laravel-backup/src/Tasks/Cleanup/Period.php
vendored
Normal file
31
vendor/spatie/laravel-backup/src/Tasks/Cleanup/Period.php
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\Backup\Tasks\Cleanup;
|
||||
|
||||
use Carbon\Carbon;
|
||||
|
||||
class Period
|
||||
{
|
||||
/** @var \Carbon\Carbon */
|
||||
protected $startDate;
|
||||
|
||||
/** @var \Carbon\Carbon */
|
||||
protected $endDate;
|
||||
|
||||
public function __construct(Carbon $startDate, Carbon $endDate)
|
||||
{
|
||||
$this->startDate = $startDate;
|
||||
|
||||
$this->endDate = $endDate;
|
||||
}
|
||||
|
||||
public function startDate(): Carbon
|
||||
{
|
||||
return $this->startDate->copy();
|
||||
}
|
||||
|
||||
public function endDate(): Carbon
|
||||
{
|
||||
return $this->endDate->copy();
|
||||
}
|
||||
}
|
||||
117
vendor/spatie/laravel-backup/src/Tasks/Cleanup/Strategies/DefaultStrategy.php
vendored
Normal file
117
vendor/spatie/laravel-backup/src/Tasks/Cleanup/Strategies/DefaultStrategy.php
vendored
Normal file
@@ -0,0 +1,117 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\Backup\Tasks\Cleanup\Strategies;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Collection;
|
||||
use Spatie\Backup\BackupDestination\Backup;
|
||||
use Spatie\Backup\BackupDestination\BackupCollection;
|
||||
use Spatie\Backup\Tasks\Cleanup\CleanupStrategy;
|
||||
use Spatie\Backup\Tasks\Cleanup\Period;
|
||||
|
||||
class DefaultStrategy extends CleanupStrategy
|
||||
{
|
||||
/** @var \Spatie\Backup\BackupDestination\Backup */
|
||||
protected $newestBackup;
|
||||
|
||||
public function deleteOldBackups(BackupCollection $backups)
|
||||
{
|
||||
// Don't ever delete the newest backup.
|
||||
$this->newestBackup = $backups->shift();
|
||||
|
||||
$dateRanges = $this->calculateDateRanges();
|
||||
|
||||
$backupsPerPeriod = $dateRanges->map(function (Period $period) use ($backups) {
|
||||
return $backups->filter(function (Backup $backup) use ($period) {
|
||||
return $backup->date()->between($period->startDate(), $period->endDate());
|
||||
});
|
||||
});
|
||||
|
||||
$backupsPerPeriod['daily'] = $this->groupByDateFormat($backupsPerPeriod['daily'], 'Ymd');
|
||||
$backupsPerPeriod['weekly'] = $this->groupByDateFormat($backupsPerPeriod['weekly'], 'YW');
|
||||
$backupsPerPeriod['monthly'] = $this->groupByDateFormat($backupsPerPeriod['monthly'], 'Ym');
|
||||
$backupsPerPeriod['yearly'] = $this->groupByDateFormat($backupsPerPeriod['yearly'], 'Y');
|
||||
|
||||
$this->removeBackupsForAllPeriodsExceptOne($backupsPerPeriod);
|
||||
|
||||
$this->removeBackupsOlderThan($dateRanges['yearly']->endDate(), $backups);
|
||||
|
||||
$this->removeOldBackupsUntilUsingLessThanMaximumStorage($backups);
|
||||
}
|
||||
|
||||
protected function calculateDateRanges(): Collection
|
||||
{
|
||||
$config = $this->config->get('backup.cleanup.default_strategy');
|
||||
|
||||
$daily = new Period(
|
||||
Carbon::now()->subDays($config['keep_all_backups_for_days']),
|
||||
Carbon::now()
|
||||
->subDays($config['keep_all_backups_for_days'])
|
||||
->subDays($config['keep_daily_backups_for_days'])
|
||||
);
|
||||
|
||||
$weekly = new Period(
|
||||
$daily->endDate(),
|
||||
$daily->endDate()
|
||||
->subWeeks($config['keep_weekly_backups_for_weeks'])
|
||||
);
|
||||
|
||||
$monthly = new Period(
|
||||
$weekly->endDate(),
|
||||
$weekly->endDate()
|
||||
->subMonths($config['keep_monthly_backups_for_months'])
|
||||
);
|
||||
|
||||
$yearly = new Period(
|
||||
$monthly->endDate(),
|
||||
$monthly->endDate()
|
||||
->subYears($config['keep_yearly_backups_for_years'])
|
||||
);
|
||||
|
||||
return collect(compact('daily', 'weekly', 'monthly', 'yearly'));
|
||||
}
|
||||
|
||||
protected function groupByDateFormat(Collection $backups, string $dateFormat): Collection
|
||||
{
|
||||
return $backups->groupBy(function (Backup $backup) use ($dateFormat) {
|
||||
return $backup->date()->format($dateFormat);
|
||||
});
|
||||
}
|
||||
|
||||
protected function removeBackupsForAllPeriodsExceptOne(Collection $backupsPerPeriod)
|
||||
{
|
||||
$backupsPerPeriod->each(function (Collection $groupedBackupsByDateProperty, string $periodName) {
|
||||
$groupedBackupsByDateProperty->each(function (Collection $group) {
|
||||
$group->shift();
|
||||
|
||||
$group->each->delete();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
protected function removeBackupsOlderThan(Carbon $endDate, BackupCollection $backups)
|
||||
{
|
||||
$backups->filter(function (Backup $backup) use ($endDate) {
|
||||
return $backup->exists() && $backup->date()->lt($endDate);
|
||||
})->each->delete();
|
||||
}
|
||||
|
||||
protected function removeOldBackupsUntilUsingLessThanMaximumStorage(BackupCollection $backups)
|
||||
{
|
||||
if (! $oldest = $backups->oldest()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$maximumSize = $this->config->get('backup.cleanup.default_strategy.delete_oldest_backups_when_using_more_megabytes_than')
|
||||
* 1024 * 1024;
|
||||
|
||||
if (($backups->size() + $this->newestBackup->size()) <= $maximumSize) {
|
||||
return;
|
||||
}
|
||||
$oldest->delete();
|
||||
|
||||
$backups = $backups->filter->exists();
|
||||
|
||||
$this->removeOldBackupsUntilUsingLessThanMaximumStorage($backups);
|
||||
}
|
||||
}
|
||||
70
vendor/spatie/laravel-backup/src/Tasks/Monitor/BackupDestinationStatus.php
vendored
Normal file
70
vendor/spatie/laravel-backup/src/Tasks/Monitor/BackupDestinationStatus.php
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\Backup\Tasks\Monitor;
|
||||
|
||||
use Exception;
|
||||
use Illuminate\Support\Collection;
|
||||
use Spatie\Backup\BackupDestination\BackupDestination;
|
||||
use Spatie\Backup\Tasks\Monitor\HealthChecks\IsReachable;
|
||||
|
||||
class BackupDestinationStatus
|
||||
{
|
||||
/** @var \Spatie\Backup\BackupDestination\BackupDestination */
|
||||
protected $backupDestination;
|
||||
|
||||
/** @var array */
|
||||
protected $healthChecks;
|
||||
|
||||
/** @var HealthCheckFailure|null */
|
||||
protected $healthCheckFailure;
|
||||
|
||||
public function __construct(BackupDestination $backupDestination, array $healthChecks = [])
|
||||
{
|
||||
$this->backupDestination = $backupDestination;
|
||||
|
||||
$this->healthChecks = $healthChecks;
|
||||
}
|
||||
|
||||
public function backupDestination(): BackupDestination
|
||||
{
|
||||
return $this->backupDestination;
|
||||
}
|
||||
|
||||
public function check(HealthCheck $check)
|
||||
{
|
||||
try {
|
||||
$check->checkHealth($this->backupDestination());
|
||||
} catch (Exception $exception) {
|
||||
return new HealthCheckFailure($check, $exception);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getHealthChecks(): Collection
|
||||
{
|
||||
return collect($this->healthChecks)->prepend(new IsReachable());
|
||||
}
|
||||
|
||||
public function getHealthCheckFailure(): ?HealthCheckFailure
|
||||
{
|
||||
return $this->healthCheckFailure;
|
||||
}
|
||||
|
||||
public function isHealthy(): bool
|
||||
{
|
||||
$healthChecks = $this->getHealthChecks();
|
||||
|
||||
foreach ($healthChecks as $healthCheck) {
|
||||
$checkResult = $this->check($healthCheck);
|
||||
|
||||
if ($checkResult instanceof HealthCheckFailure) {
|
||||
$this->healthCheckFailure = $checkResult;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
52
vendor/spatie/laravel-backup/src/Tasks/Monitor/BackupDestinationStatusFactory.php
vendored
Normal file
52
vendor/spatie/laravel-backup/src/Tasks/Monitor/BackupDestinationStatusFactory.php
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\Backup\Tasks\Monitor;
|
||||
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Collection;
|
||||
use Spatie\Backup\BackupDestination\BackupDestination;
|
||||
|
||||
class BackupDestinationStatusFactory
|
||||
{
|
||||
public static function createForMonitorConfig(array $monitorConfiguration): Collection
|
||||
{
|
||||
return collect($monitorConfiguration)->flatMap(function (array $monitorProperties) {
|
||||
return self::createForSingleMonitor($monitorProperties);
|
||||
})->sortBy(function (BackupDestinationStatus $backupDestinationStatus) {
|
||||
return $backupDestinationStatus->backupDestination()->backupName().'-'.
|
||||
$backupDestinationStatus->backupDestination()->diskName();
|
||||
});
|
||||
}
|
||||
|
||||
public static function createForSingleMonitor(array $monitorConfig): Collection
|
||||
{
|
||||
return collect($monitorConfig['disks'])->map(function ($diskName) use ($monitorConfig) {
|
||||
$backupDestination = BackupDestination::create($diskName, $monitorConfig['name']);
|
||||
|
||||
return new BackupDestinationStatus($backupDestination, static::buildHealthChecks($monitorConfig));
|
||||
});
|
||||
}
|
||||
|
||||
protected static function buildHealthChecks($monitorConfig)
|
||||
{
|
||||
return collect(Arr::get($monitorConfig, 'health_checks'))->map(function ($options, $class) {
|
||||
if (is_int($class)) {
|
||||
$class = $options;
|
||||
$options = [];
|
||||
}
|
||||
|
||||
return static::buildHealthCheck($class, $options);
|
||||
})->toArray();
|
||||
}
|
||||
|
||||
protected static function buildHealthCheck($class, $options)
|
||||
{
|
||||
// A single value was passed - we'll instantiate it manually assuming it's the first argument
|
||||
if (! is_array($options)) {
|
||||
return new $class($options);
|
||||
}
|
||||
|
||||
// A config array was given. Use reflection to match arguments
|
||||
return app()->makeWith($class, $options);
|
||||
}
|
||||
}
|
||||
36
vendor/spatie/laravel-backup/src/Tasks/Monitor/HealthCheck.php
vendored
Normal file
36
vendor/spatie/laravel-backup/src/Tasks/Monitor/HealthCheck.php
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\Backup\Tasks\Monitor;
|
||||
|
||||
use Illuminate\Support\Str;
|
||||
use Spatie\Backup\BackupDestination\BackupDestination;
|
||||
use Spatie\Backup\Exceptions\InvalidHealthCheck;
|
||||
|
||||
abstract class HealthCheck
|
||||
{
|
||||
abstract public function checkHealth(BackupDestination $backupDestination);
|
||||
|
||||
public function name()
|
||||
{
|
||||
return Str::title(class_basename($this));
|
||||
}
|
||||
|
||||
protected function fail(string $message)
|
||||
{
|
||||
throw InvalidHealthCheck::because($message);
|
||||
}
|
||||
|
||||
protected function failIf(bool $condition, string $message)
|
||||
{
|
||||
if ($condition) {
|
||||
$this->fail($message);
|
||||
}
|
||||
}
|
||||
|
||||
protected function failUnless(bool $condition, string $message)
|
||||
{
|
||||
if (! $condition) {
|
||||
$this->fail($message);
|
||||
}
|
||||
}
|
||||
}
|
||||
37
vendor/spatie/laravel-backup/src/Tasks/Monitor/HealthCheckFailure.php
vendored
Normal file
37
vendor/spatie/laravel-backup/src/Tasks/Monitor/HealthCheckFailure.php
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\Backup\Tasks\Monitor;
|
||||
|
||||
use Exception;
|
||||
use Spatie\Backup\Exceptions\InvalidHealthCheck;
|
||||
|
||||
class HealthCheckFailure
|
||||
{
|
||||
/** @var \Spatie\Backup\Tasks\Monitor */
|
||||
protected $healthCheck;
|
||||
|
||||
/** @var \Exception */
|
||||
protected $exception;
|
||||
|
||||
public function __construct(HealthCheck $healthCheck, Exception $exception)
|
||||
{
|
||||
$this->healthCheck = $healthCheck;
|
||||
|
||||
$this->exception = $exception;
|
||||
}
|
||||
|
||||
public function healthCheck(): HealthCheck
|
||||
{
|
||||
return $this->healthCheck;
|
||||
}
|
||||
|
||||
public function exception(): Exception
|
||||
{
|
||||
return $this->exception;
|
||||
}
|
||||
|
||||
public function wasUnexpected(): bool
|
||||
{
|
||||
return ! $this->exception instanceof InvalidHealthCheck;
|
||||
}
|
||||
}
|
||||
19
vendor/spatie/laravel-backup/src/Tasks/Monitor/HealthChecks/IsReachable.php
vendored
Normal file
19
vendor/spatie/laravel-backup/src/Tasks/Monitor/HealthChecks/IsReachable.php
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\Backup\Tasks\Monitor\HealthChecks;
|
||||
|
||||
use Spatie\Backup\BackupDestination\BackupDestination;
|
||||
use Spatie\Backup\Tasks\Monitor\HealthCheck;
|
||||
|
||||
class IsReachable extends HealthCheck
|
||||
{
|
||||
public function checkHealth(BackupDestination $backupDestination)
|
||||
{
|
||||
$this->failUnless(
|
||||
$backupDestination->isReachable(),
|
||||
trans('backup::notification.unhealthy_backup_found_not_reachable', [
|
||||
'error' => $backupDestination->connectionError,
|
||||
])
|
||||
);
|
||||
}
|
||||
}
|
||||
51
vendor/spatie/laravel-backup/src/Tasks/Monitor/HealthChecks/MaximumAgeInDays.php
vendored
Normal file
51
vendor/spatie/laravel-backup/src/Tasks/Monitor/HealthChecks/MaximumAgeInDays.php
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\Backup\Tasks\Monitor\HealthChecks;
|
||||
|
||||
use Spatie\Backup\BackupDestination\Backup;
|
||||
use Spatie\Backup\BackupDestination\BackupDestination;
|
||||
use Spatie\Backup\Tasks\Monitor\HealthCheck;
|
||||
|
||||
class MaximumAgeInDays extends HealthCheck
|
||||
{
|
||||
/** @var int */
|
||||
protected $days;
|
||||
|
||||
public function __construct($days = 1)
|
||||
{
|
||||
$this->days = $days;
|
||||
}
|
||||
|
||||
public function checkHealth(BackupDestination $backupDestination)
|
||||
{
|
||||
$this->failIf(
|
||||
$this->hasNoBackups($backupDestination),
|
||||
trans('backup::notifications.unhealthy_backup_found_empty')
|
||||
);
|
||||
|
||||
$newestBackup = $backupDestination->backups()->newest();
|
||||
|
||||
$this->failIf(
|
||||
$this->isTooOld($newestBackup),
|
||||
trans('backup::notifications.unhealthy_backup_found_old', ['date' => $newestBackup->date()->format('Y/m/d h:i:s')])
|
||||
);
|
||||
}
|
||||
|
||||
protected function hasNoBackups(BackupDestination $backupDestination)
|
||||
{
|
||||
return $backupDestination->backups()->isEmpty();
|
||||
}
|
||||
|
||||
protected function isTooOld(Backup $backup)
|
||||
{
|
||||
if (is_null($this->days)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($backup->date()->gt(now()->subDays($this->days))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
46
vendor/spatie/laravel-backup/src/Tasks/Monitor/HealthChecks/MaximumStorageInMegabytes.php
vendored
Normal file
46
vendor/spatie/laravel-backup/src/Tasks/Monitor/HealthChecks/MaximumStorageInMegabytes.php
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\Backup\Tasks\Monitor\HealthChecks;
|
||||
|
||||
use Spatie\Backup\BackupDestination\BackupDestination;
|
||||
use Spatie\Backup\Helpers\Format;
|
||||
use Spatie\Backup\Tasks\Monitor\HealthCheck;
|
||||
|
||||
class MaximumStorageInMegabytes extends HealthCheck
|
||||
{
|
||||
/** @var int */
|
||||
protected $maximumSizeInMegaBytes;
|
||||
|
||||
public function __construct(int $maximumSizeInMegaBytes = 5000)
|
||||
{
|
||||
$this->maximumSizeInMegaBytes = $maximumSizeInMegaBytes;
|
||||
}
|
||||
|
||||
public function checkHealth(BackupDestination $backupDestination)
|
||||
{
|
||||
$usageInBytes = $backupDestination->usedStorage();
|
||||
|
||||
$this->failIf(
|
||||
$this->exceedsAllowance($usageInBytes),
|
||||
trans('backup::notifications.unhealthy_backup_found_full', [
|
||||
'disk_usage' => $this->humanReadableSize($usageInBytes),
|
||||
'disk_limit' => $this->humanReadableSize($this->bytes($this->maximumSizeInMegaBytes)),
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
protected function exceedsAllowance(float $usageInBytes): bool
|
||||
{
|
||||
return $usageInBytes > $this->bytes($this->maximumSizeInMegaBytes);
|
||||
}
|
||||
|
||||
protected function bytes(int $megaBytes): int
|
||||
{
|
||||
return $megaBytes * 1024 * 1024;
|
||||
}
|
||||
|
||||
protected function humanReadableSize(float $sizeInBytes): string
|
||||
{
|
||||
return Format::humanReadableSize($sizeInBytes);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user