Skip to content

Commit 0f02bc2

Browse files
committed
Basic migrations
1 parent ba94162 commit 0f02bc2

6 files changed

+346
-9
lines changed

src/App/Actions/Create_Middleware_Action.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ protected function formatPath(Request $Request): array {
4949
$path = $Request->getArgument('save_path') ?? '';
5050

5151
if (empty($path)) {
52-
$path = text(label: 'Where would you like to save the mieddleware?', default: $this->middleware_config['default_save_path']);
52+
$path = text(label: 'Where would you like to save the middleware?', default: $this->middleware_config['default_save_path']);
5353
}
5454

5555
$path = $path[0] !== '/' ? '/' . $path : $path;
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace GimliDev\Actions;
5+
6+
use Clyde\Actions\Action_Base;
7+
use Clyde\Request\Request;
8+
use Clyde\Request\Request_Response;
9+
use GimliDev\Builders\File_Builder;
10+
use Symfony\Component\Yaml\Yaml;
11+
12+
use function GimliDev\load_config;
13+
use function Laravel\Prompts\confirm;
14+
use function Laravel\Prompts\text;
15+
16+
class Create_Migration_Action extends Action_Base {
17+
18+
protected array $database_config = [];
19+
20+
/**
21+
* Execute the action
22+
*
23+
* @param Request $Request
24+
* @return Request_Response
25+
*/
26+
public function execute(Request $Request): Request_Response {
27+
28+
$config = load_config();
29+
30+
$this->database_config = $config['database'] ?? [
31+
"name" => "gimli",
32+
"user" => "dev_root",
33+
"password" => "dev_root",
34+
"host" => "0.0.0.0",
35+
"port" => "34003",
36+
"migrations" => ROOT . '/sql',
37+
];
38+
39+
return $this->createMigrationFile($Request);
40+
41+
}
42+
43+
/**
44+
* Build a migration file
45+
*
46+
* @param Request $Request
47+
* @return Request_Response
48+
*/
49+
protected function createMigrationFile(Request $Request): Request_Response {
50+
51+
$path = $Request->getArgument('save_path') ?? $this->database_config['migrations'];
52+
$path = rtrim($path, '/');
53+
54+
$name = "Migration_" . date('YmdHis') . ".yaml";
55+
56+
$full_path = $path . '/' . $name;
57+
58+
$yaml_content = Yaml::dump(['migration_name' => rtrim($name, '.yaml'),'metadata' => '', 'query' =>
59+
[
60+
"create" => "",
61+
"revert" => "",
62+
]
63+
]);
64+
65+
file_put_contents($full_path, $yaml_content);
66+
67+
$this->Printer->success("Migration file created at $full_path");
68+
69+
return new Request_Response(true);
70+
}
71+
}
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace GimliDev\Actions;
5+
6+
use Clyde\Actions\Action_Base;
7+
use Clyde\Request\Request;
8+
use Clyde\Request\Request_Response;
9+
use GimliDev\Database\Database;
10+
use PDOException;
11+
use Symfony\Component\Yaml\Yaml;
12+
13+
use function GimliDev\load_config;
14+
15+
class Revert_Migration_Action extends Action_Base {
16+
17+
protected array $database_config = [];
18+
19+
/**
20+
* Execute the action
21+
*
22+
* @param Request $Request
23+
* @return Request_Response
24+
*/
25+
public function execute(Request $Request): Request_Response {
26+
27+
$config = load_config();
28+
29+
$this->database_config = $config['database'] ?? [
30+
"name" => "gimli",
31+
"user" => "dev_root",
32+
"password" => "dev_root",
33+
"host" => "0.0.0.0",
34+
"port" => "34003",
35+
"migrations" => ROOT . '/sql',
36+
];
37+
38+
return $this->revertMigrationFiles($Request);
39+
40+
}
41+
42+
/**
43+
* revert migration files
44+
*
45+
* @param Request $Request
46+
* @return Request_Response
47+
*/
48+
protected function revertMigrationFiles(Request $Request): Request_Response {
49+
50+
$path = $Request->getArgument('save_path') ?? $this->database_config['migrations'];
51+
$path = rtrim($path, '/');
52+
53+
// get all yaml files in path
54+
$file_name = $Request->getArgument('file_name');
55+
$file_name = rtrim($file_name, '.yaml');
56+
$file_path = $path . '/' . $file_name . '.yaml';
57+
// get devtools.migration.json file
58+
$devtools_migration_file = ROOT . '/devtools.migration.json';
59+
$migration_log = json_decode(file_get_contents($devtools_migration_file), true);
60+
$database = (new Database($this->database_config))->getDb();
61+
62+
if (!in_array($file_path, $migration_log['processed'])) {
63+
$this->Printer->error("Migration $file_name has not been run");
64+
exit(1);
65+
}
66+
67+
$yaml = Yaml::parseFile($file_path);
68+
69+
// run migration
70+
$this->Printer->info("Reverting migration: $file_name");
71+
72+
// run create query
73+
$this->Printer->info("Running revert query");
74+
75+
try {
76+
$database->beginTransaction();
77+
$database->exec($yaml['query']['revert']);
78+
79+
$error = $database->errorInfo();
80+
81+
if ($error[0] !== '00000') {
82+
if ($database->inTransaction()) {
83+
$database->rollBack();
84+
}
85+
$this->Printer->error('Error running query: ' . $error[2]);
86+
exit(1);
87+
}
88+
89+
if ($database->inTransaction()) {
90+
$database->commit();
91+
}
92+
} catch (PDOException $e) {
93+
if ($database->inTransaction()) {
94+
$database->rollBack();
95+
$database->commit();
96+
}
97+
$this->Printer->error('Error running query: ' . $e->getMessage());
98+
exit(1);
99+
}
100+
101+
if ($Request->getArgument('erase_log') === true) {
102+
$migration_log['processed'] = array_filter($migration_log['processed'], function($item) use ($file_path) {
103+
return $item !== $file_path;
104+
});
105+
}
106+
107+
$this->Printer->success("Migration $file_name complete. " . $yaml['metadata']);
108+
109+
$migration_log['last_run'] = date('YmdHis');
110+
file_put_contents($devtools_migration_file, json_encode($migration_log, JSON_PRETTY_PRINT));
111+
112+
$this->Printer->success("Migrations reverted");
113+
114+
return new Request_Response(true);
115+
}
116+
}
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace GimliDev\Actions;
5+
6+
use Clyde\Actions\Action_Base;
7+
use Clyde\Request\Request;
8+
use Clyde\Request\Request_Response;
9+
use GimliDev\Database\Database;
10+
use PDOException;
11+
use Symfony\Component\Yaml\Yaml;
12+
13+
use function GimliDev\load_config;
14+
15+
class Run_Migration_Action extends Action_Base {
16+
17+
protected array $database_config = [];
18+
19+
/**
20+
* Execute the action
21+
*
22+
* @param Request $Request
23+
* @return Request_Response
24+
*/
25+
public function execute(Request $Request): Request_Response {
26+
27+
$config = load_config();
28+
29+
$this->database_config = $config['database'] ?? [
30+
"name" => "gimli",
31+
"user" => "dev_root",
32+
"password" => "dev_root",
33+
"host" => "0.0.0.0",
34+
"port" => "34003",
35+
"migrations" => ROOT . '/sql',
36+
];
37+
38+
return $this->runMigrationFiles($Request);
39+
40+
}
41+
42+
/**
43+
* run migration files
44+
*
45+
* @param Request $Request
46+
* @return Request_Response
47+
*/
48+
protected function runMigrationFiles(Request $Request): Request_Response {
49+
50+
$path = $Request->getArgument('save_path') ?? $this->database_config['migrations'];
51+
$path = rtrim($path, '/');
52+
53+
// get all yaml files in path
54+
$files = glob($path . '/*.yaml');
55+
56+
// get devtools.migration.json file
57+
$devtools_migration_file = ROOT . '/devtools.migration.json';
58+
$migration_log = json_decode(file_get_contents($devtools_migration_file), true);
59+
$database = (new Database($this->database_config))->getDb();
60+
foreach($files as $file) {
61+
// check if migration has been run
62+
if (in_array($file, $migration_log['processed'])) {
63+
continue;
64+
}
65+
66+
$yaml = Yaml::parseFile($file);
67+
68+
// run migration
69+
$this->Printer->info("Running migration: $file");
70+
71+
// run create query
72+
$this->Printer->info("Running create query");
73+
74+
try {
75+
$database->beginTransaction();
76+
$database->exec($yaml['query']['create']);
77+
78+
$error = $database->errorInfo();
79+
80+
if ($error[0] !== '00000') {
81+
if ($database->inTransaction()) {
82+
$database->rollBack();
83+
}
84+
$this->Printer->error('Error running query: ' . $error[2]);
85+
exit(1);
86+
}
87+
88+
if ($database->inTransaction()) {
89+
$database->commit();
90+
}
91+
} catch (PDOException $e) {
92+
if ($database->inTransaction()) {
93+
$database->rollBack();
94+
$database->commit();
95+
}
96+
$this->Printer->error('Error running query: ' . $e->getMessage());
97+
exit(1);
98+
}
99+
100+
// log migration
101+
$migration_log['processed'][] = $file;
102+
103+
$this->Printer->success("Migration $file complete. " . $yaml['metadata']);
104+
}
105+
106+
$migration_log['last_run'] = date('YmdHis');
107+
file_put_contents($devtools_migration_file, json_encode($migration_log, JSON_PRETTY_PRINT));
108+
109+
$this->Printer->success("Migrations run");
110+
111+
return new Request_Response(true);
112+
}
113+
}

src/App/Database/Database.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,15 @@ public function __construct() {
2121
$this->db = new PDO($dsn, $config['database']['user'], $config['database']['password']);
2222
}
2323

24+
/**
25+
* Get the database connection
26+
*
27+
* @return PDO
28+
*/
29+
public function getDb(): PDO {
30+
return $this->db;
31+
}
32+
2433
/**
2534
* Get the schema for a table
2635
*

0 commit comments

Comments
 (0)