Skip to content

Commit 841b6ea

Browse files
committed
Add new $flush parameter to control flush mode for Compressor
1 parent 19a400f commit 841b6ea

File tree

4 files changed

+60
-3
lines changed

4 files changed

+60
-3
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ jobs:
88
PHPUnit:
99
name: PHPUnit (PHP ${{ matrix.php }} on ${{ matrix.os }})
1010
runs-on: ${{ matrix.os }}
11+
continue-on-error: $${{ matrix.os == 'windows-2025' }}
1112
strategy:
1213
matrix:
1314
os:

src/Compressor.php

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,15 @@ final class Compressor extends TransformStream
3434
/** @var ?resource */
3535
private $context;
3636

37+
/** @var int */
38+
private $flush;
39+
3740
/**
3841
* @param int $encoding ZLIB_ENCODING_GZIP, ZLIB_ENCODING_RAW or ZLIB_ENCODING_DEFLATE
3942
* @param int $level optional compression level
43+
* @param int $flush optional flush mode (ZLIB_NO_FLUSH, ZLIB_SYNC_FLUSH, ZLIB_FULL_FLUSH, ZLIB_FINISH)
4044
*/
41-
public function __construct($encoding, $level = -1)
45+
public function __construct($encoding, $level = -1, int $flush = ZLIB_NO_FLUSH)
4246
{
4347
$errstr = '';
4448
set_error_handler(function ($_, $error) use (&$errstr) {
@@ -61,12 +65,17 @@ public function __construct($encoding, $level = -1)
6165
throw new \InvalidArgumentException('Unable to initialize compressor' . $errstr); // @codeCoverageIgnore
6266
}
6367

68+
if (!in_array($flush, [ZLIB_NO_FLUSH, ZLIB_SYNC_FLUSH, ZLIB_FULL_FLUSH, ZLIB_FINISH], true)) {
69+
throw new \InvalidArgumentException('Argument #3 ($flush) must be one of ZLIB_NO_FLUSH, ZLIB_SYNC_FLUSH, ZLIB_FULL_FLUSH or ZLIB_FINISH');
70+
}
71+
6472
$this->context = $context;
73+
$this->flush = $flush;
6574
}
6675

6776
protected function transformData($chunk)
6877
{
69-
$ret = deflate_add($this->context, $chunk, ZLIB_NO_FLUSH);
78+
$ret = deflate_add($this->context, $chunk, $this->flush);
7079

7180
if ($ret !== '') {
7281
$this->emit('data', [$ret]);

tests/CompressorTest.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,10 @@ public function testCtorThrowsForInvalidEncodingAndUnsetsUsedErrorHandler()
3030

3131
$this->assertEquals($handler, $checkHandler);
3232
}
33+
34+
public function testCtorThrowsForInvalidFlushMode()
35+
{
36+
$this->expectException(\InvalidArgumentException::class);
37+
new Compressor(ZLIB_ENCODING_GZIP, -1, -1);
38+
}
3339
}

tests/GzipCompressorTest.php

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ public function testCompressEmpty()
2222
$this->markTestSkipped('Not supported on Windows');
2323
}
2424

25-
$os = DIRECTORY_SEPARATOR === '\\' ? "\x0a" : "\x03"; // NTFS(0x0a) or UNIX (0x03)
25+
$os = DIRECTORY_SEPARATOR === '\\' ? "\x0b" : "\x03"; // NTFS(0x0a) or UNIX (0x03)
2626
$this->compressor->on('data', $this->expectCallableOnceWith("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00" . $os . "\x03\x00" . "\x00\x00\x00\x00\x00\x00\x00\x00"));
2727
$this->compressor->on('end', $this->expectCallableOnce());
2828

@@ -58,4 +58,45 @@ public function testCompressBig()
5858
// PHP < 5.4 does not support gzdecode(), so let's assert this the other way around…
5959
$this->assertEquals(gzencode($data), $buffered);
6060
}
61+
62+
public function testWriteWillOnlyFlushHeaderByDefaultToBufferDataBeforeFlushing()
63+
{
64+
$compressor = new Compressor(ZLIB_ENCODING_GZIP);
65+
66+
$os = DIRECTORY_SEPARATOR === '\\' ? "\x0a" : "\x03"; // NTFS(0x0a) or UNIX (0x03)
67+
$compressor->on('data', $this->expectCallableOnceWith("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00" . $os));
68+
69+
$compressor->write('hello');
70+
}
71+
72+
public function testWriteWithSyncFlushWillFlushHeaderWithFirstChunkImmediately()
73+
{
74+
$compressor = new Compressor(ZLIB_ENCODING_GZIP, -1, ZLIB_SYNC_FLUSH);
75+
76+
$os = DIRECTORY_SEPARATOR === '\\' ? "\x0a" : "\x03"; // NTFS(0x0a) or UNIX (0x03)
77+
$compressor->on('data', $this->expectCallableOnceWith("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00" . $os . "\xca\x48\xcd\xc9\xc9\x07\x00\x00\x00\xff\xff"));
78+
79+
$compressor->write('hello');
80+
}
81+
82+
public function testWriteWithFinishFlushWillFlushEntireGzipHeaderAndFooterWithFirstChunkImmediately()
83+
{
84+
$compressor = new Compressor(ZLIB_ENCODING_GZIP, -1, ZLIB_FINISH);
85+
86+
$os = DIRECTORY_SEPARATOR === '\\' ? "\x0a" : "\x03"; // NTFS(0x0a) or UNIX (0x03)
87+
$compressor->on('data', $this->expectCallableOnceWith("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00" . $os . "\xcb\x48\xcd\xc9\xc9\x07\x00\x86\xa6\x10\x36" . "\x05\x00\x00\x00"));
88+
89+
$compressor->write('hello');
90+
}
91+
92+
public function testWriteAfterFinishFlushWillFlushEntireGzipWithSyncFlushWillFlushEntireGzipHeaderAndFooterAgainImmediately()
93+
{
94+
$compressor = new Compressor(ZLIB_ENCODING_GZIP, -1, ZLIB_FINISH);
95+
$compressor->write('hello');
96+
97+
$os = DIRECTORY_SEPARATOR === '\\' ? "\x0a" : "\x03"; // NTFS(0x0a) or UNIX (0x03)
98+
$compressor->on('data', $this->expectCallableOnceWith("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00" . $os . "\xcb\x48\xcd\xc9\xc9\x07\x00\x86\xa6\x10\x36" . "\x05\x00\x00\x00"));
99+
100+
$compressor->write('hello');
101+
}
61102
}

0 commit comments

Comments
 (0)