Skip to content

Commit

Permalink
feat: add support for stream_metadata operations with stream wrapper
Browse files Browse the repository at this point in the history
  • Loading branch information
carlalexander committed Aug 9, 2024
1 parent 6cf9eec commit bacc240
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 4 deletions.
13 changes: 11 additions & 2 deletions src/CloudStorage/AbstractCloudStorageStreamWrapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -332,9 +332,18 @@ public function stream_lock(): bool
*
* @see https://www.php.net/manual/en/streamwrapper.stream-metadata.php
*/
public function stream_metadata(): bool
public function stream_metadata(string $path, int $option): bool
{
return false;
return STREAM_META_TOUCH === $option ? $this->call(function () use ($path) {
$client = $this->getClient();
$key = $this->parsePath($path);

if (!$client->objectExists($key)) {
$client->putObject($key, '', $this->getAcl());
}

$this->removeCacheValue($path);
}) : true;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -496,6 +496,33 @@ public function testThrowsExceptionWhenContextHasNoClient()
]));
}

public function testTouchCreatesObjectIfItDoesntExist()
{
$this->client->expects($this->once())
->method('objectExists')
->with($this->identicalTo('/file.ext'))
->willReturn(false);

$this->client->expects($this->once())
->method('putObject')
->with($this->identicalTo('/file.ext'), $this->identicalTo(''), $this->identicalTo($this->getAcl()));

$this->assertTrue(touch("{$this->getProtocol()}:///file.ext"));
}

public function testTouchDoesntCreateObjectIfItExists()
{
$this->client->expects($this->once())
->method('objectExists')
->with($this->identicalTo('/file.ext'))
->willReturn(false);

$this->client->expects($this->once())
->method('putObject');

$this->assertTrue(touch("{$this->getProtocol()}:///file.ext"));
}

public function testTruncatesFile()
{
$this->client->expects($this->once())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,39 @@ public function testMkdirAndRmdir()
$this->assertFalse($this->client->objectExists($directoryPath.'/'));
}

public function testTouchCreatesEmptyFileIfFileDoesntExist()
{
$relativePath = '/'.basename(tempnam(sys_get_temp_dir(), 'ymir-').'.txt');
$s3FilePath = "{$this->getProtocol()}://".$relativePath;

$this->assertFalse(file_exists($s3FilePath));

$this->assertTrue(touch($s3FilePath));

$this->assertTrue(file_exists($s3FilePath));
$this->assertSame('', file_get_contents($s3FilePath));

$this->client->deleteObject($relativePath);
}

public function testTouchDoesNothingIfFileExists()
{
$relativePath = '/'.basename(tempnam(sys_get_temp_dir(), 'ymir-').'.txt');
$s3FilePath = "{$this->getProtocol()}://".$relativePath;

$this->assertFalse(file_exists($s3FilePath));

file_put_contents($s3FilePath, 'foo');

$this->assertTrue(file_exists($s3FilePath));

$this->assertTrue(touch($s3FilePath));

$this->assertSame('foo', file_get_contents($s3FilePath));

$this->client->deleteObject($relativePath);
}

public function testTruncateExistingFile()
{
$relativePath = '/'.basename(tempnam(sys_get_temp_dir(), 'ymir-').'.txt');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -643,9 +643,44 @@ public function testStreamLock()
$this->assertFalse($this->getStreamWrapperObject()->stream_lock());
}

public function testStreamMetadata()
public function testStreamMetadataWithNonTouchOption()
{
$this->assertFalse($this->getStreamWrapperObject()->stream_metadata());
$this->assertTrue($this->getStreamWrapperObject()->stream_metadata("{$this->getProtocol()}:///foo.txt", STREAM_META_GROUP));
}

public function testStreamMetadataWithTouchOptionWhenObjectDoesntExist()
{
$client = $this->getCloudStorageClientInterfaceMock();

$client->expects($this->once())
->method('objectExists')
->with($this->identicalTo('/foo.txt'))
->willReturn(false);

$client->expects($this->once())
->method('putObject')
->with($this->identicalTo('/foo.txt'), $this->identicalTo(''), $this->identicalTo($this->getAcl()));

$this->getStreamWrapperClass()::register($client, new \ArrayObject());

$this->assertTrue($this->getStreamWrapperObject()->stream_metadata("{$this->getProtocol()}:///foo.txt", STREAM_META_TOUCH));
}

public function testStreamMetadataWithTouchOptionWhenObjectExists()
{
$client = $this->getCloudStorageClientInterfaceMock();

$client->expects($this->once())
->method('objectExists')
->with($this->identicalTo('/foo.txt'))
->willReturn(true);

$client->expects($this->never())
->method('putObject');

$this->getStreamWrapperClass()::register($client, new \ArrayObject());

$this->assertTrue($this->getStreamWrapperObject()->stream_metadata("{$this->getProtocol()}:///foo.txt", STREAM_META_TOUCH));
}

public function testStreamOpenWithInvalidMode()
Expand Down

0 comments on commit bacc240

Please sign in to comment.