baseDirectory = $baseDirectory; $this->password = $password; } /** * Execute the job. */ public function handle(): void { try { Log::info("Starting PDF unlock process in directory: {$this->baseDirectory}"); // Check if directory exists if (!File::isDirectory($this->baseDirectory)) { Log::error("Directory not found: {$this->baseDirectory}"); return; } // Get all subdirectories (year folders like 202505) $yearDirectories = File::directories($this->baseDirectory); foreach ($yearDirectories as $yearDirectory) { $this->processYearDirectory($yearDirectory); } Log::info("PDF unlock process completed successfully."); } catch (Exception $e) { Log::error("Error unlocking PDF files: " . $e->getMessage()); } } /** * Process a year directory (e.g., 202505) * * @param string $yearDirectory Directory path to process */ protected function processYearDirectory(string $yearDirectory): void { try { // Get all ID directories (e.g., ID0010001) $idDirectories = File::directories($yearDirectory); foreach ($idDirectories as $idDirectory) { $this->processIdDirectory($idDirectory); } } catch (Exception $e) { Log::error("Error processing year directory {$yearDirectory}: " . $e->getMessage()); } } /** * Process an ID directory (e.g., ID0010001) * * @param string $idDirectory Directory path to process */ protected function processIdDirectory(string $idDirectory): void { try { // Get all PDF files in the directory $pdfFiles = File::glob($idDirectory . '/*.pdf'); foreach ($pdfFiles as $pdfFile) { $this->unlockPdf($pdfFile); } } catch (Exception $e) { Log::error("Error processing ID directory {$idDirectory}: " . $e->getMessage()); } } /** * Unlock a password-protected PDF file * * @param string $pdfFilePath Path to PDF file */ protected function unlockPdf(string $pdfFilePath): void { try { $filename = pathinfo($pdfFilePath, PATHINFO_FILENAME); $directory = pathinfo($pdfFilePath, PATHINFO_DIRNAME); $decryptedPdfPath = $directory . '/' . $filename . '.dec.pdf'; $finalPdfPath = $directory . '/' . $filename . '.pdf'; // Skip if the decrypted file already exists if (File::exists($decryptedPdfPath)) { Log::info("Decrypted file already exists: {$decryptedPdfPath}"); return; } // Create qpdf command $command = ['qpdf', '--password=' . $this->password, '--decrypt', $pdfFilePath, $decryptedPdfPath]; // Execute the command $process = new Process($command); $process->run(); // Check if the command was successful if (!$process->isSuccessful()) { throw new ProcessFailedException($process); } Log::info("Unlocked PDF: {$pdfFilePath} to {$decryptedPdfPath}"); // Remove the original encrypted file after successful decryption if (File::exists($decryptedPdfPath)) { // Delete the encrypted file File::delete($pdfFilePath); Log::info("Removed encrypted file: {$pdfFilePath}"); // Rename the decrypted file (remove .dec extension) File::move($decryptedPdfPath, $finalPdfPath); Log::info("Renamed decrypted file from {$decryptedPdfPath} to {$finalPdfPath}"); } } catch (Exception $e) { Log::error("Error unlocking PDF {$pdfFilePath}: " . $e->getMessage()); } } }