Skip to content

Commit

Permalink
Merge pull request #1744 from howardlopez/stream_wrapper_fixes
Browse files Browse the repository at this point in the history
S3 stream wrapper write empty files
  • Loading branch information
howardlopez committed Mar 7, 2019
2 parents 875786b + 56e1be2 commit 94c8d9d
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 0 deletions.
7 changes: 7 additions & 0 deletions .changes/nextrelease/stream_wrapper_fixes.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[
{
"type": "feature",
"category": "S3",
"description": "Updates the S3 stream wrapper to be able to write empty files for PHP 7+."
}
]
8 changes: 8 additions & 0 deletions src/S3/StreamWrapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ class StreamWrapper
/** @var string The opened protocol (e.g., "s3") */
private $protocol = 's3';

/** @var bool Keeps track of whether stream has been flushed since opening */
private $isFlushed = false;

/**
* Register the 's3://' stream wrapper
*
Expand Down Expand Up @@ -127,12 +130,16 @@ public static function register(

public function stream_close()
{
if ($this->body->getSize() === 0 && !($this->isFlushed)) {
$this->stream_flush();
}
$this->body = $this->cache = null;
}

public function stream_open($path, $mode, $options, &$opened_path)
{
$this->initProtocol($path);
$this->isFlushed = false;
$this->params = $this->getBucketKey($path);
$this->mode = rtrim($mode, 'bt');

Expand All @@ -156,6 +163,7 @@ public function stream_eof()

public function stream_flush()
{
$this->isFlushed = true;
if ($this->mode == 'r') {
return false;
}
Expand Down
19 changes: 19 additions & 0 deletions tests/S3/StreamWrapperTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,25 @@ public function testCanOpenWriteOnlyStreams()
$this->assertEquals('test', (string) $cmd['Body']);
}

public function testCanWriteEmptyFileToStream()
{
$history = new History();
$this->client->getHandlerList()->appendSign(Middleware::history($history));
$this->addMockResults($this->client, [new Result()]);
$s = fopen('s3://bucket/key', 'w');
$this->assertEquals(0, fwrite($s, ''));
$this->assertTrue(fclose($s));

// Ensure that the stream was flushed even with zero characters, and
// that it only executed PutObject once.
$this->assertCount(1, $history);
$cmd = $history->getLastCommand();
$this->assertEquals('PutObject', $cmd->getName());
$this->assertEquals('bucket', $cmd['Bucket']);
$this->assertEquals('key', $cmd['Key']);
$this->assertEquals('', (string) $cmd['Body']);
}

/**
* @expectedException \PHPUnit\Framework\Error\Warning
* @expectedExceptionMessage 403 Forbidden
Expand Down

0 comments on commit 94c8d9d

Please sign in to comment.