clock = new SystemClock(); $this->uploadsPath = __DIR__ . '/storage/uploads'; // Initialize database $this->initializeDatabase(); } private function initializeDatabase(): void { // Simple SQLite connection for this script $pdo = new PDO('sqlite:' . __DIR__ . '/database.sqlite'); $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $this->db = $pdo; } public function run(): void { echo "šŸ” Scanning for images in: {$this->uploadsPath}\n"; if (!is_dir($this->uploadsPath)) { echo "āŒ Uploads directory not found: {$this->uploadsPath}\n"; return; } $imageFiles = $this->findImageFiles(); echo "šŸ“ Found " . count($imageFiles) . " image files\n"; if (empty($imageFiles)) { echo "ā„¹ļø No images to migrate\n"; return; } $this->migrateImages($imageFiles); echo "āœ… Migration completed!\n"; } private function findImageFiles(): array { $iterator = new RecursiveIteratorIterator( new RecursiveDirectoryIterator($this->uploadsPath) ); $imageFiles = []; $allowedExtensions = ['jpg', 'jpeg', 'png', 'gif', 'webp']; foreach ($iterator as $file) { if (!$file->isFile()) { continue; } $extension = strtolower($file->getExtension()); if (!in_array($extension, $allowedExtensions)) { continue; } $imageFiles[] = [ 'path' => $file->getPathname(), 'filename' => $file->getFilename(), 'extension' => $extension, 'size' => $file->getSize(), 'mtime' => $file->getMTime() ]; } return $imageFiles; } private function migrateImages(array $imageFiles): void { // Check current database schema $this->checkDatabaseSchema(); $migrated = 0; $errors = 0; foreach ($imageFiles as $fileInfo) { try { $this->migrateImageFile($fileInfo); $migrated++; echo "āœ“ Migrated: {$fileInfo['filename']}\n"; } catch (Exception $e) { $errors++; echo "āŒ Error migrating {$fileInfo['filename']}: " . $e->getMessage() . "\n"; } } echo "\nšŸ“Š Summary:\n"; echo " Migrated: $migrated\n"; echo " Errors: $errors\n"; } private function checkDatabaseSchema(): void { // Check what columns exist in the images table $stmt = $this->db->query("PRAGMA table_info(images)"); $columns = $stmt->fetchAll(PDO::FETCH_ASSOC); echo "šŸ“‹ Database schema (images table):\n"; foreach ($columns as $column) { echo " - {$column['name']} ({$column['type']})\n"; } echo "\n"; } private function migrateImageFile(array $fileInfo): void { $fullPath = $fileInfo['path']; // Extract image dimensions if possible $imageInfo = @getimagesize($fullPath); $width = $imageInfo[0] ?? 0; $height = $imageInfo[1] ?? 0; // Generate ULID $ulidGenerator = new UlidGenerator(); $ulidString = $ulidGenerator->generate($this->clock); // Calculate hash $hashValue = hash_file('sha256', $fullPath); // Determine MIME type $mimeTypeString = match (strtolower($fileInfo['extension'])) { 'jpg', 'jpeg' => 'image/jpeg', 'png' => 'image/png', 'gif' => 'image/gif', 'webp' => 'image/webp', default => 'image/jpeg' }; // Extract original filename from the complex filename structure $originalFilename = $this->extractOriginalFilename($fileInfo['filename']); // Get relative path from storage root $relativePath = str_replace($this->uploadsPath . '/', '', $fullPath); $pathOnly = dirname($relativePath); // Insert into database using the correct table structure $sql = "INSERT INTO images ( ulid, filename, original_filename, mime_type, file_size, width, height, hash, path, created_at, updated_at ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; $stmt = $this->db->prepare($sql); $now = date('Y-m-d H:i:s'); $stmt->execute([ $ulidString, $fileInfo['filename'], $originalFilename, $mimeTypeString, $fileInfo['size'], $width, $height, $hashValue, $pathOnly, $now, $now ]); } private function extractOriginalFilename(string $filename): string { // Pattern for files like: BFWCAKKEHTKF5SYR_6626fc6b...cd1_original.png if (preg_match('/^[A-Z0-9]{16}_[a-f0-9]{64}_original\.(.+)$/', $filename, $matches)) { // This is an original file, try to find the pattern in other files $basePattern = substr($filename, 0, strpos($filename, '_original.')); // For now, just return a cleaned version return "original." . $matches[1]; } // Pattern for simple files like: 00MF9VW9R36NJN3VCFSTS2CK6R.jpg if (preg_match('/^[A-Z0-9]{26}\.(.+)$/', $filename, $matches)) { return "image." . $matches[1]; } // Fallback: return as-is return $filename; } } // Run the migration echo "šŸš€ Starting image migration from filesystem to database...\n\n"; try { $migration = new ImageMigrationScript(); $migration->run(); } catch (Exception $e) { echo "šŸ’„ Migration failed: " . $e->getMessage() . "\n"; echo "Stack trace:\n" . $e->getTraceAsString() . "\n"; exit(1); } echo "\nšŸŽ‰ Migration script completed!\n";