diff --git a/src/WordPress/Zip/ZipStreamWriter.php b/src/WordPress/Zip/ZipStreamWriter.php index 7656082e..848d8cc1 100644 --- a/src/WordPress/Zip/ZipStreamWriter.php +++ b/src/WordPress/Zip/ZipStreamWriter.php @@ -36,7 +36,7 @@ public function __construct($output_stream) * into memory. It reads and compresses the file in chunks, making it suitable for streaming * large files effectively. */ - public function writeFileFromPath($sourcePathOnDisk, $targetPathInZip, $should_deflate = true) { + public function writeFileFromPath($targetPathInZip, $sourcePathOnDisk, $should_deflate = true) { $uncompressedSize = 0; $compressedSize = 0; if (!$should_deflate) { @@ -181,6 +181,36 @@ public function writeFileFromPath($sourcePathOnDisk, $targetPathInZip, $should_d return true; } + public function writeFileFromString($targetPathInZip, $data, $should_deflate = true) + { + if ($should_deflate) { + $compressed_data = gzdeflate($data); + } else { + $compressed_data = $data; + } + + // Create the ZipFileEntry object + $entry = new ZipFileEntry( + 2, // Version needed to extract (minimum) + 0, // General purpose bit flag + $should_deflate ? 8 : 0, // Compression method (8 = deflate, 0 = none) + time() >> 16, // File last modification time + time() & 0xFFFF, // File last modification date + hexdec(hash('crc32b', $data)), // CRC-32 + strlen($compressed_data), // Uncompressed size + strlen($data), // Uncompressed size + $targetPathInZip, // File name + '', // Extra field + $compressed_data // Buffering bytes into memory + ); + + // Write the file entry header + static::writeFileEntry($this->fp, $entry); + $this->recordFileForCentralDirectory($entry); + $this->bytes_written += $entry->size(); + return $entry->size(); + } + private function recordFileForCentralDirectory(ZipFileEntry $file_entry) { $this->centralDirectory[] = new ZipCentralDirectoryEntry( 2, // Version made by diff --git a/tests/unit/zip/ZipStreamWriterTest.php b/tests/unit/zip/ZipStreamWriterTest.php index 75060fff..75d97895 100644 --- a/tests/unit/zip/ZipStreamWriterTest.php +++ b/tests/unit/zip/ZipStreamWriterTest.php @@ -50,7 +50,7 @@ public function testWriteFileFromPath($should_deflate) { $targetPathInZip = 'file'; // Test the function - $zipWriter->writeFileFromPath($sourcePathOnDisk, $targetPathInZip, $should_deflate); + $zipWriter->writeFileFromPath($targetPathInZip, $sourcePathOnDisk, $should_deflate); $zipWriter->finish(); fclose($fp); @@ -68,6 +68,37 @@ public function testWriteFileFromPath($should_deflate) { $zip->close(); } + /** + * @dataProvider shouldDeflateProvider + */ + public function testWriteFileFromString($should_deflate) + { + $this->tempZipPath = tempnam($this->tempDir, 'testzip'); + $fp = fopen($this->tempZipPath, 'wb'); + + $zipWriter = new ZipStreamWriter($fp); + $sourceContent = 'Hello'; + $targetPathInZip = 'file'; + + // Test the function + $zipWriter->writeFileFromString($targetPathInZip, $sourceContent, $should_deflate); + $zipWriter->finish(); + + fclose($fp); + + // Check that the ZIP file was created and is not empty + $this->assertFileExists($this->tempZipPath); + $this->assertGreaterThan(0, filesize($this->tempZipPath)); + + // Open the ZIP file and verify its contents + $zip = new \ZipArchive(); + $zip->open($this->tempZipPath); + $this->assertTrue($zip->locateName($targetPathInZip) !== false, "The file was not found in the ZIP"); + $fileContent = $zip->getFromName($targetPathInZip); + $this->assertEquals($sourceContent, $fileContent, "The file content does not match"); + $zip->close(); + } + static public function shouldDeflateProvider() { return [ [true],