3declare(strict_types=1);
5require_once dirname(__DIR__) .
'/include/dbxUpdateService.class.php';
16 $this->calls[] =
'prepare';
17 return array(
'pending' => array(
'test-migration'),
'backups' => array());
22 $this->calls[] =
'apply';
23 if ($this->failApply) {
24 throw new RuntimeException(
'erwarteter DB-Fehler');
26 return array(
'applied' =>
$state[
'pending']);
31 $this->calls[] =
'rollback';
32 return array(
'rolled_back' =>
$state[
'pending']);
38 if (!is_dir(dirname(
$file))) {
39 mkdir(dirname(
$file), 0775,
true);
49 $iterator =
new RecursiveIteratorIterator(
50 new RecursiveDirectoryIterator(
$root, FilesystemIterator::SKIP_DOTS),
51 RecursiveIteratorIterator::CHILD_FIRST
54 $item->isDir() ? rmdir($item->getPathname()) : unlink($item->getPathname());
67 $oldInventory = array(
69 'product' =>
'dbxapp',
72 'VERSION' => hash(
'sha256',
"4.0.1\n"),
73 'index.php' => hash(
'sha256',
"<?php echo 'old';\n"),
74 'dbx/include/dbxApi.php' => hash(
'sha256',
"<?php // old api\n"),
75 '.dbx-release-files.json' =>
null,
79 $root .
'/.dbx-release-files.json',
80 json_encode($oldInventory, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)
86 mkdir(dirname(
$zipFile), 0775,
true);
90 'index.php' => $newIndex,
91 'dbx/include/dbxApi.php' =>
"<?php // new api\n",
94 foreach ($contents as $path =>
$content) {
97 $files[
'.dbx-release-files.json'] =
null;
98 $inventory = json_encode(array(
100 'product' =>
'dbxapp',
103 ), JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES) . PHP_EOL;
105 $zip =
new ZipArchive();
106 $zip->open(
$zipFile, ZipArchive::CREATE | ZipArchive::OVERWRITE);
107 foreach ($contents as $path =>
$content) {
108 $zip->addFromString($path,
$content);
110 $zip->addFromString(
'.dbx-release-files.json', $inventory);
115 'product' =>
'dbxapp',
116 'channel' =>
'stable',
118 'release_url' =>
'https://github.com/ecb-dbxApp/dbxapp/releases/tag/v' .
$version,
119 'zip_url' =>
'https://github.com/ecb-dbxApp/dbxapp/releases/download/v'
121 'sha256' => hash_file(
'sha256',
$zipFile),
124 'extensions' => array(
'json',
'pdo',
'zip'),
132 $zip =
new ZipArchive();
138 'staged_at' => gmdate(
'c'),
143 ), JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
151 throw new RuntimeException($message);
155$root = sys_get_temp_dir() .
'/dbx-update-db-adapter-' . bin2hex(random_bytes(5));
162 $adapter->calls === array(
'prepare',
'apply'),
163 'DB-Adapter wurde bei erfolgreicher Installation nicht korrekt aufgerufen.'
167 $adapter->calls === array(
'prepare',
'apply',
'rollback')
168 && trim((
string)file_get_contents(
$root .
'/VERSION')) ===
'4.0.1',
169 'Expliziter Rollback hat DB und Dateien nicht gemeinsam behandelt.'
175$root = sys_get_temp_dir() .
'/dbx-update-db-failure-' . bin2hex(random_bytes(5));
179 $adapter->failApply =
true;
183 throw new RuntimeException(
'Erwarteter DB-Migrationsfehler blieb aus.');
184 }
catch (RuntimeException $exception) {
186 str_contains($exception->getMessage(),
'zurückgerollt'),
187 'DB-Migrationsfehler meldet keinen koordinierten Rollback.'
191 $adapter->calls === array(
'prepare',
'apply',
'rollback')
192 && trim((
string)file_get_contents(
$root .
'/VERSION')) ===
'4.0.1'
193 && str_contains((
string)file_get_contents(
$root .
'/index.php'),
'old'),
194 'Fehlerpfad hat DB und Dateien nicht vollständig zurückgerollt.'
200echo
"OK updater coordinates database prepare, apply and rollback\n";
prepare(string $root, array $manifest, string $backup)
Sicherer dbxApp Release-Updater fuer Dateien und optionale DB-Migrationen.
update_db_assert(bool $condition, string $message)
update_db_stage(string $root, string $version, string $newIndex)
update_db_remove(string $root)
update_db_write(string $file, string $content)
catch(RuntimeException $exception) $staging