Skip to content

Commit d077d02

Browse files
committed
refactor: Improve code formatting and consistency in migration and pagination handling classes.
Added Confirmation check of potentially destructive DB commands
1 parent 30b07e8 commit d077d02

File tree

5 files changed

+140
-41
lines changed

5 files changed

+140
-41
lines changed

src/Commands/Handlers/LaravelSetup/MigrationHandler.php

Lines changed: 31 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -21,19 +21,20 @@ class MigrationHandler extends SetupHandler
2121
*/
2222
public function copyMigrationFiles(): void
2323
{
24-
$this->destinationMigrationsDir = $this->distPath . 'Database/Eloquent-Migrations';
25-
$this->sourceMigrationsDir = $this->sourcePath . 'Database/Eloquent-Migrations';
24+
$this->destinationMigrationsDir = $this->distPath.'Database/Eloquent-Migrations';
25+
$this->sourceMigrationsDir = $this->sourcePath.'Database/Eloquent-Migrations';
2626

27-
if (!$this->ensureDestinationDirectoryExists()) {
27+
if (! $this->ensureDestinationDirectoryExists()) {
2828
return;
2929
}
3030

31-
if (!$this->validateSourceDirectoryExists()) {
31+
if (! $this->validateSourceDirectoryExists()) {
3232
return;
3333
}
3434

35-
if (!$this->confirmProceedWithCopy()) {
36-
$this->error(" Skipped copying migration files.");
35+
if (! $this->confirmProceedWithCopy()) {
36+
$this->error(' Skipped copying migration files.');
37+
3738
return;
3839
}
3940

@@ -49,14 +50,16 @@ public function copyMigrationFiles(): void
4950
*/
5051
private function ensureDestinationDirectoryExists(): bool
5152
{
52-
if (!is_dir($this->destinationMigrationsDir)) {
53+
if (! is_dir($this->destinationMigrationsDir)) {
5354
if (mkdir($this->destinationMigrationsDir, 0777, true)) {
54-
$this->write(CLI::color(' Created: ', 'green') . clean_path($this->destinationMigrationsDir));
55+
$this->write(CLI::color(' Created: ', 'green').clean_path($this->destinationMigrationsDir));
5556
} else {
56-
$this->error(' Failed to create directory: ' . clean_path($this->destinationMigrationsDir));
57+
$this->error(' Failed to create directory: '.clean_path($this->destinationMigrationsDir));
58+
5759
return false;
5860
}
5961
}
62+
6063
return true;
6164
}
6265

@@ -67,10 +70,12 @@ private function ensureDestinationDirectoryExists(): bool
6770
*/
6871
private function validateSourceDirectoryExists(): bool
6972
{
70-
if (!is_dir($this->sourceMigrationsDir)) {
71-
$this->error(' Source migration directory not found: ' . clean_path($this->sourceMigrationsDir));
73+
if (! is_dir($this->sourceMigrationsDir)) {
74+
$this->error(' Source migration directory not found: '.clean_path($this->sourceMigrationsDir));
75+
7276
return false;
7377
}
78+
7479
return true;
7580
}
7681

@@ -86,9 +91,10 @@ private function confirmProceedWithCopy(): bool
8691
}
8792

8893
$promptMessage = sprintf(
89-
" Ready to copy migration files to %s. Continue?",
94+
' Ready to copy migration files to %s. Continue?',
9095
clean_path($this->destinationMigrationsDir)
9196
);
97+
9298
return $this->prompt($promptMessage, ['y', 'n']) === 'y';
9399
}
94100

@@ -99,7 +105,8 @@ private function processSourceMigrationFiles(): void
99105
{
100106
$files = scandir($this->sourceMigrationsDir);
101107
if ($files === false) {
102-
$this->error(' Could not read source migration directory: ' . clean_path($this->sourceMigrationsDir));
108+
$this->error(' Could not read source migration directory: '.clean_path($this->sourceMigrationsDir));
109+
103110
return;
104111
}
105112

@@ -109,40 +116,41 @@ private function processSourceMigrationFiles(): void
109116
continue;
110117
}
111118
$migrationFilesFound = true;
112-
$sourceFile = $this->sourceMigrationsDir . '/' . $file;
113-
$destFile = $this->destinationMigrationsDir . '/' . $file;
119+
$sourceFile = $this->sourceMigrationsDir.'/'.$file;
120+
$destFile = $this->destinationMigrationsDir.'/'.$file;
114121

115122
$this->copySingleMigrationFile($sourceFile, $destFile);
116123
}
117124

118-
if (!$migrationFilesFound) {
125+
if (! $migrationFilesFound) {
119126
$this->write(CLI::color(' No migration files found in the source directory.', 'yellow'));
120127
}
121128
}
122129

123130
/**
124131
* Handles the copying of a single migration file, including overwrite confirmation.
125132
*
126-
* @param string $sourceFile The full path to the source migration file.
127-
* @param string $destFile The full path to the destination migration file.
133+
* @param string $sourceFile The full path to the source migration file.
134+
* @param string $destFile The full path to the destination migration file.
128135
*/
129136
private function copySingleMigrationFile(string $sourceFile, string $destFile): void
130137
{
131-
if (file_exists($destFile) && !$this->skipConfirmations) {
138+
if (file_exists($destFile) && ! $this->skipConfirmations) {
132139
$promptMessage = sprintf(
133140
" File '%s' already exists. Overwrite?",
134141
clean_path($destFile)
135142
);
136143
if ($this->prompt($promptMessage, ['n', 'y']) === 'n') {
137-
$this->write(CLI::color(" Skipped: ", 'yellow') . clean_path($destFile));
144+
$this->write(CLI::color(' Skipped: ', 'yellow').clean_path($destFile));
145+
138146
return;
139147
}
140148
}
141149

142150
if (copy($sourceFile, $destFile)) {
143-
$this->write(CLI::color(' Copied: ', 'green') . clean_path($destFile));
151+
$this->write(CLI::color(' Copied: ', 'green').clean_path($destFile));
144152
} else {
145-
$this->error(' Error copying migration file: ' . basename($sourceFile) . ' to ' . clean_path($destFile));
153+
$this->error(' Error copying migration file: '.basename($sourceFile).' to '.clean_path($destFile));
146154
}
147155
}
148-
}
156+
}

src/Commands/Handlers/LaravelSetup/SetupHandler.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ abstract class SetupHandler
3030

3131
/**
3232
* Whether to skip individual confirmations
33-
*
33+
*
3434
* @var bool
3535
*/
3636
protected $skipConfirmations = false;
@@ -57,7 +57,7 @@ protected function copyAndReplace(string $file, array $replaces = []): void
5757
$path = "{$this->sourcePath}/{$file}";
5858

5959
if (! file_exists($path)) {
60-
$this->error(' Source file not found: ' . clean_path($path));
60+
$this->error(' Source file not found: '.clean_path($path));
6161

6262
return;
6363
}
@@ -99,10 +99,11 @@ protected function writeFile(string $file, string $content): void
9999
}
100100

101101
if (file_exists($path)) {
102-
if (!$this->skipConfirmations &&
102+
if (! $this->skipConfirmations &&
103103
$this->prompt(" File '{$cleanPath}' already exists in destination. Overwrite?", ['n', 'y']) === 'n'
104104
) {
105105
$this->error(" Skipped {$cleanPath}. If you wish to overwrite, please use the '-f' option or reply 'y' to the prompt.");
106+
106107
return;
107108
}
108109
}

src/Commands/Handlers/LaravelSetup/SystemHandler.php

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,26 +12,29 @@ class SystemHandler extends SetupHandler
1212
public function setupEvents(): void
1313
{
1414
$file = 'Config/Events.php';
15-
$path = $this->distPath . $file;
15+
$path = $this->distPath.$file;
1616
$cleanPath = clean_path($path);
1717

1818
if (! file_exists($path)) {
1919
$this->error(' Events file not found. Make sure you have a Config/Events.php file.');
20+
2021
return;
2122
}
2223

2324
$content = file_get_contents($path);
2425

2526
if (strpos($content, "service('eloquent')") !== false) {
26-
$this->write(CLI::color(' Events Setup: ', 'green') . 'Eloquent already initialized in events.');
27+
$this->write(CLI::color(' Events Setup: ', 'green').'Eloquent already initialized in events.');
28+
2729
return;
2830
}
2931

3032
if (
31-
!$this->skipConfirmations &&
33+
! $this->skipConfirmations &&
3234
$this->prompt(" Ready to update '{$cleanPath}' to initialize Eloquent and auth services. Continue?", ['y', 'n']) === 'n'
3335
) {
3436
$this->error(" Skipped updating {$cleanPath}.");
37+
3538
return;
3639
}
3740

@@ -50,7 +53,7 @@ public function setupEvents(): void
5053
$newContent = preg_replace($pattern, $eloquentCode, $content);
5154

5255
if ($newContent !== $content && write_file($path, $newContent)) {
53-
$this->write(CLI::color(' Updated: ', 'green') . $cleanPath);
56+
$this->write(CLI::color(' Updated: ', 'green').$cleanPath);
5457
} else {
5558
$this->error(' Error updating Events file.');
5659
}
@@ -62,7 +65,7 @@ public function setupEvents(): void
6265
public function setupFilters(): void
6366
{
6467
$file = 'Config/Filters.php';
65-
$path = $this->distPath . $file;
68+
$path = $this->distPath.$file;
6669
$cleanPath = clean_path($path);
6770

6871
if (! file_exists($path)) {
@@ -75,7 +78,7 @@ public function setupFilters(): void
7578

7679
// Check if the code is already there
7780
if (strpos($content, '\\Rcalicdan\\Ci4Larabridge\\Filters\\AuthFilter::class') !== false) {
78-
$this->write(CLI::color(' Filters Setup: ', 'green') . 'Auth filters already added.');
81+
$this->write(CLI::color(' Filters Setup: ', 'green').'Auth filters already added.');
7982

8083
return;
8184
}
@@ -92,7 +95,7 @@ public function setupFilters(): void
9295
$newContent = preg_replace($pattern, $filterAliases, $content);
9396

9497
if ($newContent !== $content && write_file($path, $newContent)) {
95-
$this->write(CLI::color(' Updated: ', 'green') . $cleanPath);
98+
$this->write(CLI::color(' Updated: ', 'green').$cleanPath);
9699
} else {
97100
$this->error(' Error updating Filters file.');
98101
}

src/Commands/LaravelMigrate.php

Lines changed: 91 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,13 @@ class LaravelMigrate extends BaseCommand
5757
];
5858

5959
/**
60-
* Command options (currently none).
60+
* Available options for the command.
6161
*
6262
* @var array
6363
*/
64-
protected $options = [];
64+
protected $options = [
65+
'-f' => 'Force the operation without confirmation, even in production',
66+
];
6567

6668
/**
6769
* Handler for database operations.
@@ -132,10 +134,10 @@ public function run(array $params)
132134
if (strpos($e->getMessage(), 'Unknown database') !== false) {
133135
$this->promptAndCreateDatabase();
134136
} else {
135-
CLI::error('Database connection error: '.$e->getMessage());
137+
CLI::error('Database connection error: ' . $e->getMessage());
136138
}
137139
} catch (\Exception $e) {
138-
CLI::error('Error executing migration command: '.$e->getMessage());
140+
CLI::error('Error executing migration command: ' . $e->getMessage());
139141
}
140142
}
141143

@@ -209,6 +211,10 @@ private function promptAndCreateDatabase()
209211
*/
210212
private function executeAction(string $action)
211213
{
214+
if (! $this->confirmDestructiveAction($action)) {
215+
return;
216+
}
217+
212218
switch ($action) {
213219
case 'up':
214220
$migrations = $this->migrationHandler->runMigrations();
@@ -246,6 +252,87 @@ private function executeAction(string $action)
246252
}
247253
}
248254

255+
/**
256+
* Confirms destructive actions in production environment.
257+
*
258+
* @param string $action The migration action to check
259+
* @return bool True if action is confirmed or no confirmation needed, false otherwise
260+
*/
261+
private function confirmDestructiveAction(string $action): bool
262+
{
263+
$destructiveActions = ['down', 'refresh', 'fresh'];
264+
265+
// If not a destructive action or not in production, no confirmation needed
266+
if (! in_array($action, $destructiveActions) || ENVIRONMENT !== 'production') {
267+
return true;
268+
}
269+
270+
// Check if force flag is set
271+
$force = (bool) CLI::getOption('f');
272+
if ($force) {
273+
return true;
274+
}
275+
276+
// Show warning and get basic confirmation
277+
if (! $this->showWarningAndConfirm($action)) {
278+
return false;
279+
}
280+
281+
// For fresh action, require additional confirmation
282+
if ($action === 'fresh' && ! $this->confirmFreshAction()) {
283+
return false;
284+
}
285+
286+
return true;
287+
}
288+
289+
/**
290+
* Shows warning and asks for confirmation for destructive actions.
291+
*
292+
* @param string $action The migration action
293+
* @return bool True if confirmed, false otherwise
294+
*/
295+
private function showWarningAndConfirm(string $action): bool
296+
{
297+
$actionDescription = match ($action) {
298+
'down' => 'roll back the last batch of migrations',
299+
'refresh' => 'roll back and re-run all migrations',
300+
'fresh' => 'drop all tables and run all migrations',
301+
default => $action
302+
};
303+
304+
CLI::write('⚠️ WARNING: You are about to ' . $actionDescription . ' in PRODUCTION!', 'red');
305+
CLI::write('This operation may cause data loss and application downtime.', 'yellow');
306+
307+
$confirm = CLI::prompt('Are you absolutely sure you want to continue?', ['n', 'y']);
308+
309+
if ($confirm !== 'y') {
310+
CLI::write('Operation cancelled.', 'yellow');
311+
312+
return false;
313+
}
314+
315+
return true;
316+
}
317+
318+
/**
319+
* Additional confirmation specifically for the 'fresh' action.
320+
*
321+
* @return bool True if confirmed, false otherwise
322+
*/
323+
private function confirmFreshAction(): bool
324+
{
325+
$confirmAgain = CLI::prompt('This will DELETE ALL DATA in your database. Type "DELETE" to confirm', null, 'required');
326+
327+
if ($confirmAgain !== 'DELETE') {
328+
CLI::write('Operation cancelled.', 'yellow');
329+
330+
return false;
331+
}
332+
333+
return true;
334+
}
335+
249336
/**
250337
* Handles the 'fresh' migration action.
251338
*

src/Commands/PublishPagination.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,8 @@ class PublishPagination extends BaseCommand
4848
*/
4949
public function run(array $params)
5050
{
51-
$sourcePath = __DIR__ . '/../Views/pagination';
52-
$destinationPath = APPPATH . 'Views/pagination';
51+
$sourcePath = __DIR__.'/../Views/pagination';
52+
$destinationPath = APPPATH.'Views/pagination';
5353

5454
if (! is_dir($sourcePath)) {
5555
CLI::error("Source directory not found: {$sourcePath}");
@@ -86,8 +86,8 @@ protected function copyFiles($source, $destination)
8686
continue;
8787
}
8888

89-
$sourcePath = $source . '/' . $file;
90-
$destPath = $destination . '/' . $file;
89+
$sourcePath = $source.'/'.$file;
90+
$destPath = $destination.'/'.$file;
9191

9292
if (is_file($sourcePath)) {
9393
if (copy($sourcePath, $destPath)) {

0 commit comments

Comments
 (0)