Issues (374)

app/Console/Commands/UpdateNNTmuxDB.php (2 issues)

1
<?php
2
3
namespace App\Console\Commands;
4
5
use Illuminate\Console\Command;
6
use Illuminate\Support\Facades\DB;
7
8
class UpdateNNTmuxDB extends Command
9
{
10
    /**
11
     * The name and signature of the console command.
12
     */
13
    protected $signature = 'nntmux:db
14
                            {--seed : Run database seeders after migration}
15
                            {--rollback= : Rollback the last N migrations}
16
                            {--check : Check migration status without running}';
17
18
    /**
19
     * The console command description.
20
     */
21
    protected $description = 'Update NNTmux database with enhanced safety and performance';
22
23
    /**
24
     * Execute the console command.
25
     */
26
    public function handle(): int
27
    {
28
        try {
29
            $this->info('🗄️ Starting database update process...');
30
31
            // Check database connection and detect database type
32
            $dbType = $this->checkDatabaseConnection();
33
            if (! $dbType) {
34
                $this->error('Database connection failed');
35
36
                return Command::FAILURE;
37
            }
38
39
            // Handle rollback if requested
40
            if ($this->option('rollback')) {
41
                return $this->handleRollback();
42
            }
43
44
            // Check migration status if requested
45
            if ($this->option('check')) {
46
                return $this->checkMigrationStatus();
47
            }
48
49
            // Run migrations
50
            $this->info('🔄 Running database migrations...');
51
            $this->runMigrations();
52
53
            // Run seeders if requested
54
            if ($this->option('seed')) {
55
                $this->info('🌱 Running database seeders...');
56
                $this->runSeeders();
57
            }
58
59
            /* <!-- disabled for now, can be re-enabled later -->
60
            // Optimize database
61
            $this->info('⚡ Optimizing database...');
62
            $this->optimizeDatabase($dbType);
63
            */
64
65
            $this->info('✅ Database update completed successfully');
66
67
            return Command::SUCCESS;
68
69
        } catch (\Exception $e) {
70
            $this->error('❌ Database update failed: '.$e->getMessage());
71
72
            return Command::FAILURE;
73
        }
74
    }
75
76
    /**
77
     * Check database connection and return database type
78
     */
79
    private function checkDatabaseConnection(): ?string
80
    {
81
        try {
82
            DB::connection()->getPdo();
83
84
            $dbConfig = config('database.connections.'.config('database.default'));
85
            $driver = $dbConfig['driver'] ?? null;
86
87
            // Detect actual database type for MySQL-compatible drivers
88
            if (in_array($driver, ['mysql', 'mariadb'])) {
89
                $version = DB::select('SELECT VERSION() as version')[0]->version;
90
91
                if (str_contains(strtolower($version), 'mariadb')) {
92
                    $actualType = 'mariadb';
93
                } else {
94
                    $actualType = 'mysql';
95
                }
96
97
                $this->line("  ✓ Database connection established ($actualType $version)");
98
99
                return $actualType;
100
            }
101
102
            $this->line("  ✓ Database connection established ($driver)");
103
104
            return $driver;
105
106
        } catch (\Exception $e) {
107
            $this->error('  ✗ Database connection failed: '.$e->getMessage());
108
109
            return null;
110
        }
111
    }
112
113
    /**
114
     * Handle migration rollback
115
     */
116
    private function handleRollback(): int
117
    {
118
        $steps = (int) $this->option('rollback');
119
120
        if ($steps <= 0) {
121
            $this->error('Invalid rollback steps. Must be a positive integer.');
122
123
            return Command::FAILURE;
124
        }
125
126
        $this->warn("⚠️ Rolling back $steps migrations...");
127
128
        if (! $this->confirm('Are you sure you want to rollback migrations? This may cause data loss.')) {
129
            $this->info('Rollback cancelled');
130
131
            return Command::SUCCESS;
132
        }
133
134
        $exitCode = $this->call('migrate:rollback', ['--step' => $steps]);
135
136
        if ($exitCode === 0) {
137
            $this->info("✅ Successfully rolled back $steps migrations");
138
        }
139
140
        return $exitCode;
141
    }
142
143
    /**
144
     * Check migration status
145
     */
146
    private function checkMigrationStatus(): int
147
    {
148
        $this->info('📊 Migration Status:');
149
150
        return $this->call('migrate:status');
151
    }
152
153
    /**
154
     * Run database migrations
155
     */
156
    private function runMigrations(): void
157
    {
158
        $migrateOptions = [];
159
160
        if (app()->environment('production')) {
0 ignored issues
show
The method environment() does not exist on Illuminate\Container\Container. Are you sure you never get this type here, but always one of the subclasses? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

160
        if (app()->/** @scrutinizer ignore-call */ environment('production')) {
Loading history...
161
            $migrateOptions['--force'] = true;
162
        }
163
164
        $exitCode = $this->call('migrate', $migrateOptions);
165
166
        if ($exitCode !== 0) {
167
            throw new \Exception('Migration failed');
168
        }
169
170
        $this->line('  ✓ Migrations completed successfully');
171
    }
172
173
    /**
174
     * Run database seeders
175
     */
176
    private function runSeeders(): void
177
    {
178
        $seedOptions = [];
179
180
        if (app()->environment('production')) {
181
            $seedOptions['--force'] = true;
182
        }
183
184
        $exitCode = $this->call('db:seed', $seedOptions);
185
186
        if ($exitCode !== 0) {
187
            throw new \Exception('Seeding failed');
188
        }
189
190
        $this->line('  ✓ Seeders completed successfully');
191
    }
192
193
    /**
194
     * Optimize database tables with proper driver detection
195
     */
196
    private function optimizeDatabase(string $dbType): void
0 ignored issues
show
The method optimizeDatabase() is not used, and could be removed.

This check looks for private methods that have been defined, but are not used inside the class.

Loading history...
197
    {
198
        try {
199
            if (in_array($dbType, ['mysql', 'mariadb'])) {
200
                $this->optimizeMysqlCompatible($dbType);
201
            } elseif ($dbType === 'pgsql') {
202
                $this->optimizePostgres();
203
            } else {
204
                $this->line("  ℹ Database optimization skipped (unsupported type: $dbType)");
205
            }
206
        } catch (\Exception $e) {
207
            $this->warn('  ⚠ Database optimization failed: '.$e->getMessage());
208
        }
209
    }
210
211
    /**
212
     * Optimize MySQL/MariaDB tables
213
     */
214
    private function optimizeMysqlCompatible(string $dbType): void
215
    {
216
        $dbConfig = config('database.connections.'.config('database.default'));
217
        $tables = DB::select('SHOW TABLES');
218
        $tableKey = 'Tables_in_'.$dbConfig['database'];
219
220
        $optimizedCount = 0;
221
        foreach ($tables as $table) {
222
            $tableName = $table->$tableKey;
223
            try {
224
                DB::statement("OPTIMIZE TABLE `$tableName`");
225
                $optimizedCount++;
226
            } catch (\Exception $e) {
227
                $this->warn("    ⚠ Failed to optimize table: $tableName");
228
            }
229
        }
230
231
        $this->line("  ✓ $dbType tables optimized ($optimizedCount/".count($tables).')');
232
    }
233
234
    /**
235
     * Optimize PostgreSQL database
236
     */
237
    private function optimizePostgres(): void
238
    {
239
        try {
240
            DB::statement('VACUUM ANALYZE');
241
            $this->line('  ✓ PostgreSQL database optimized (VACUUM ANALYZE)');
242
        } catch (\Exception $e) {
243
            $this->warn('  ⚠ PostgreSQL optimization failed: '.$e->getMessage());
244
        }
245
    }
246
}
247