mirror of
https://github.com/demostf/backup.git
synced 2026-06-03 14:04:10 +02:00
initial backup script
This commit is contained in:
commit
d5896cc6f3
6 changed files with 147 additions and 0 deletions
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
.env
|
||||
vendor
|
||||
composer.lock
|
||||
27
backup.php
Normal file
27
backup.php
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
require 'vendor/autoload.php';
|
||||
|
||||
if (!getenv('STORAGE_ROOT')) {
|
||||
$env = new \Dotenv\Dotenv(__DIR__);
|
||||
$env->load();
|
||||
}
|
||||
|
||||
$store = new \Demostf\Backup\Store(getenv('STORAGE_ROOT'));
|
||||
$source = new \Demostf\Backup\Source(getenv('SOURCE'));
|
||||
$statePath = getenv('STATE_FILE');
|
||||
|
||||
|
||||
if (file_exists($statePath)) {
|
||||
$lastPage = intval(file_get_contents($statePath));
|
||||
if (!$lastPage) {
|
||||
$lastPage = 1;
|
||||
}
|
||||
} else {
|
||||
$lastPage = 1;
|
||||
}
|
||||
$backup = new \Demostf\Backup\Backup($source, $store);
|
||||
|
||||
$currentPage = $backup->backupFrom($lastPage);
|
||||
|
||||
file_put_contents($statePath, $currentPage);
|
||||
11
composer.json
Normal file
11
composer.json
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Demostf\\Backup\\": "src/",
|
||||
"Demostf\\Backup\\Test\\": "tests/"
|
||||
}
|
||||
},
|
||||
"require": {
|
||||
"vlucas/phpdotenv": "^2.4"
|
||||
}
|
||||
}
|
||||
50
src/Backup.php
Normal file
50
src/Backup.php
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Demostf\Backup;
|
||||
|
||||
class Backup {
|
||||
const SUCCESS = 1;
|
||||
const FAIL = -1;
|
||||
const EMPTY_PAGE = 0;
|
||||
|
||||
private $source;
|
||||
|
||||
private $store;
|
||||
|
||||
public function __construct(Source $source, Store $store) {
|
||||
$this->source = $source;
|
||||
$this->store = $store;
|
||||
}
|
||||
|
||||
private function backupDemo(string $name, string $url, string $hash): bool {
|
||||
$handle = fopen($url, 'r');
|
||||
$storedHash = $this->store->store($name, $handle);
|
||||
return $hash === '' || $hash === $storedHash;
|
||||
}
|
||||
|
||||
public function backupPage(int $page): int {
|
||||
$demos = $this->source->listDemos($page, 'ASC');
|
||||
if (count($demos) === 0) {
|
||||
return self::EMPTY_PAGE;
|
||||
}
|
||||
foreach ($demos as $demo) {
|
||||
$url = $demo['url'];
|
||||
$name = basename($url);
|
||||
if (!$this->store->exists($name)) {
|
||||
if (!$this->backupDemo($name, $url, $demo['hash'])) {
|
||||
echo "hash mismatch\n";
|
||||
return self::FAIL;
|
||||
}
|
||||
}
|
||||
}
|
||||
return self::SUCCESS;
|
||||
}
|
||||
|
||||
public function backupFrom(int $startPage): int {
|
||||
$currentPage = $startPage;
|
||||
while ($this->backupPage($currentPage) === self::SUCCESS) {
|
||||
$currentPage++;
|
||||
}
|
||||
return $currentPage;
|
||||
}
|
||||
}
|
||||
23
src/Source.php
Normal file
23
src/Source.php
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Demostf\Backup;
|
||||
|
||||
class Source {
|
||||
private $endpoint;
|
||||
|
||||
public function __construct($endpoint) {
|
||||
$this->endpoint = $endpoint;
|
||||
}
|
||||
|
||||
public function listDemos(int $page = 0, string $order = 'DESC'): array {
|
||||
$url = $this->endpoint . '/demos?page=' . $page . '&order=' . $order;
|
||||
$content = file_get_contents($url);
|
||||
$demos = json_decode($content, true);
|
||||
foreach ($demos as $data) {
|
||||
$date = new \DateTime();
|
||||
$date->setTimestamp($data['time']);
|
||||
$data['time'] = $date;
|
||||
}
|
||||
return $demos;
|
||||
}
|
||||
}
|
||||
33
src/Store.php
Normal file
33
src/Store.php
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Demostf\Backup;
|
||||
|
||||
class Store {
|
||||
private $baseDir;
|
||||
|
||||
public function __construct($baseDir) {
|
||||
$this->baseDir = $baseDir;
|
||||
}
|
||||
|
||||
public function store(string $name, $handle): string {
|
||||
$path = $this->generatePath($name);
|
||||
if (!is_dir(dirname($path))) {
|
||||
mkdir(dirname($path), 0775, true);
|
||||
}
|
||||
file_put_contents($path, $handle);
|
||||
echo "$name\n";
|
||||
return md5_file($path);
|
||||
}
|
||||
|
||||
private function generatePath(string $name): string {
|
||||
return $this->baseDir . $this->getPrefix($name) . $name;
|
||||
}
|
||||
|
||||
private function getPrefix(string $name): string {
|
||||
return '/' . substr($name, 0, 2) . '/' . substr($name, 2, 2) . '/';
|
||||
}
|
||||
|
||||
public function exists(string $name): bool {
|
||||
return file_exists($this->generatePath($name));
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue