diff --git a/README.md b/README.md index 8110983..a87caeb 100644 --- a/README.md +++ b/README.md @@ -60,7 +60,11 @@ Create a ZIP archive containing a file from a GitHub repository: $zipPath = GithubFile::zip('owner/repo', 'path/to/file.txt'); ``` -The ZIP file will be stored in the default disk's `zips` directory. +The ZIP file will be stored in the default disk's `zips` directory. Or zip multiple files at the same times. + +```php +$zipPath = GithubFile::zip('owner/repo', ['path/to/file.txt', 'path/to/file2.txt']); +``` ## Testing diff --git a/src/Facades/GithubFile.php b/src/Facades/GithubFile.php index 9c10698..7bf375e 100644 --- a/src/Facades/GithubFile.php +++ b/src/Facades/GithubFile.php @@ -8,7 +8,7 @@ /** * @method static string get(string $repository, string $filePath, string $branch = 'main') * @method static string download(string $repository, string $filePath, string $disk = 'local', string $branch = 'main') - * @method static string zip(string $repository, string $filePath, string $disk = 'local', string $branch = 'main') + * @method static string zip(string $repository, string|array $filePath, string $disk = 'local', string $branch = 'main') * * @see \VeiligLanceren\GithubFile\Services\GithubFileService */ diff --git a/src/Interfaces/IGithubFileService.php b/src/Interfaces/IGithubFileService.php index f539bf8..a09efbd 100644 --- a/src/Interfaces/IGithubFileService.php +++ b/src/Interfaces/IGithubFileService.php @@ -31,11 +31,11 @@ public function download(string $repository, string $filePath, string $disk = 'l * Create a ZIP archive containing a file from a GitHub repository. * * @param string $repository The GitHub repository in the format 'owner/repo'. - * @param string $filePath The path to the file within the repository. - * @param string $disk The disk where the ZIP file should be stored. - * @param string $branch The branch name. Defaults to 'main'. + * @param string|array $filePaths + * @param string $disk The disk where the ZIP file should be stored. + * @param string $branch The branch name. Defaults to 'main'. * * @return string The path where the ZIP file was stored. */ - public function zip(string $repository, string $filePath, string $disk = 'local', string $branch = 'main'): string; + public function zip(string $repository, string|array $filePaths, string $disk = 'local', string $branch = 'main'): string; } \ No newline at end of file diff --git a/src/Services/GithubFileService.php b/src/Services/GithubFileService.php index 6a390a1..a5c7027 100644 --- a/src/Services/GithubFileService.php +++ b/src/Services/GithubFileService.php @@ -59,34 +59,38 @@ public function download( /** * {@inheritDoc} */ - public function zip(string $repository, string $filePath, string $disk = 'local', string $branch = 'main'): string + public function zip(string $repository, string|array $filePaths, string $disk = 'local', string $branch = 'main'): string { - $files = []; - $filename = basename($filePath); + $filePaths = is_array($filePaths) ? $filePaths : [$filePaths]; + $allFiles = []; - if (substr($filePath, -1) === '/') { - $filePath = rtrim($filePath, '/'); - $url = "https://api.github.com/repos/{$repository}/contents/{$filePath}?ref={$branch}"; + foreach ($filePaths as $filePath) { + $cleanPath = rtrim($filePath, '/'); + $url = "https://api.github.com/repos/{$repository}/contents/{$cleanPath}?ref={$branch}"; $response = Http::get($url); - if ($response->successful()) { - $filesData = $response->json(); + if (! $response->successful()) { + throw new RuntimeException("Failed to fetch file from GitHub: {$url}"); + } + + $data = $response->json(); - foreach ($filesData as $file) { - if ($file['type'] === 'file') { - $fileContent = Http::get($file['download_url'])->body(); - $files[] = ['name' => $file['name'], 'content' => $fileContent]; + if (array_is_list($data)) { + foreach ($data as $item) { + if ($item['type'] === 'file') { + $fileContent = Http::get($item['download_url'])->body(); + $allFiles[] = ['name' => $item['name'], 'content' => $fileContent]; } } } else { - throw new RuntimeException("Failed to fetch directory contents from GitHub: {$url}"); + $content = base64_decode($data['content'] ?? ''); + $allFiles[] = ['name' => basename($filePath), 'content' => $content]; } - } else { - $fileContent = $this->get($repository, $filePath, $branch); - $files[] = ['name' => $filename, 'content' => $fileContent]; } - return $this->fileZipService->createZip($filePath, $files, $disk); + $zipName = 'github-files'; + + return $this->fileZipService->createZip($zipName, $allFiles, $disk); } } \ No newline at end of file diff --git a/tests/Unit/Services/GithubFileServiceTest.php b/tests/Unit/Services/GithubFileServiceTest.php index c2cf767..e361d69 100644 --- a/tests/Unit/Services/GithubFileServiceTest.php +++ b/tests/Unit/Services/GithubFileServiceTest.php @@ -31,11 +31,49 @@ }); it('creates a zip archive containing the file', function () { + Http::fake([ + 'https://api.github.com/repos/owner/repo/contents/path/to/file.txt?ref=main' => Http::response([ + 'content' => base64_encode('file content'), + ], 200), + ]); + $service = new GithubFileService(); $zipPath = $service->zip('owner/repo', 'path/to/file.txt'); + $relativePath = str_replace(Storage::disk('local')->path(''), '', $zipPath); + + Storage::disk('local')->assertExists($relativePath); + expect($zipPath)->toBe(Storage::disk('local')->path($relativePath)); +}); + +it('creates a zip archive from multiple GitHub file and folder paths', function () { + Http::fake([ + 'https://api.github.com/repos/owner/repo/contents/folder?ref=main' => Http::response([ + [ + 'type' => 'file', + 'name' => 'file1.txt', + 'download_url' => 'https://raw.githubusercontent.com/owner/repo/main/folder/file1.txt', + ], + [ + 'type' => 'file', + 'name' => 'file2.txt', + 'download_url' => 'https://raw.githubusercontent.com/owner/repo/main/folder/file2.txt', + ], + ]), - Storage::disk('local')->assertExists('zips/file.txt.zip'); + 'https://raw.githubusercontent.com/owner/repo/main/folder/file1.txt' => Http::response('content 1', 200), + 'https://raw.githubusercontent.com/owner/repo/main/folder/file2.txt' => Http::response('content 2', 200), + 'https://api.github.com/repos/owner/repo/contents/README.md?ref=main' => Http::response([ + 'content' => base64_encode('readme content'), + ]), + ]); + + $service = new GithubFileService(); + $zipPath = $service->zip('owner/repo', ['folder/', 'README.md']); + + expect($zipPath)->toBe(Storage::disk('local')->path('zips/github-files.zip')); - expect($zipPath) - ->toBe(Storage::disk('local')->path('zips/file.txt.zip')); + Storage::disk('local')->assertExists('zips/github-files.zip'); }); + + +