Skip to content

Commit

Permalink
feat: add support for ftruncate to stream wrapper
Browse files Browse the repository at this point in the history
  • Loading branch information
carlalexander committed Mar 19, 2022
1 parent 383b074 commit cdc9f69
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 0 deletions.
18 changes: 18 additions & 0 deletions src/CloudStorage/AbstractCloudStorageStreamWrapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,24 @@ public function stream_tell()
return ftell($this->openedStreamObjectResource);
}

/**
* Truncate stream.
*
* @see https://www.php.net/manual/en/streamwrapper.stream-truncate.php
*/
public function stream_truncate(int $newSize): bool
{
return $this->call(function () use ($newSize) {
rewind($this->openedStreamObjectResource);

ftruncate($this->openedStreamObjectResource, $newSize);

$this->getClient()->putObject($this->openedStreamObjectKey, stream_get_contents($this->openedStreamObjectResource), $this->getMimetype());

$this->removeCacheValue(static::getProtocol().'://'.$this->openedStreamObjectKey);
});
}

/**
* Write to cloud storage object.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -496,6 +496,26 @@ public function testThrowsExceptionWhenContextHasNoClient()
]));
}

public function testTruncatesFile()
{
$this->client->expects($this->once())
->method('getObject')
->with($this->identicalTo('/file.ext'))
->willReturn('testing');

$this->client->expects($this->exactly(2))
->method('putObject')
->withConsecutive(
[$this->identicalTo('/file.ext'), $this->identicalTo('testing')],
[$this->identicalTo('/file.ext'), $this->identicalTo('test'), $this->identicalTo('')]
);

$file = fopen("{$this->getProtocol()}:///file.ext", 'a');

$this->assertTrue(ftruncate($file, 4));
$this->assertTrue(fclose($file));
}

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

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

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

file_put_contents($s3FilePath, 'tests');

$this->assertSame(5, filesize($s3FilePath));

$file = fopen($s3FilePath, 'a');
$stat = fstat($file);

ftruncate($file, $stat['size'] - 1);
fclose($file);

$this->assertSame('test', file_get_contents($s3FilePath));
$this->assertSame(4, filesize($s3FilePath));

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

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

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

$file = fopen($s3FilePath, 'w');

fwrite($file, 'tests');
$stat = fstat($file);

$this->assertSame(5, $stat['size']);

ftruncate($file, $stat['size'] - 1);
fclose($file);

$this->assertSame('test', file_get_contents($s3FilePath));
$this->assertSame(4, filesize($s3FilePath));

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

abstract protected function getStreamWrapper(): string;

private function getProtocol(): string
Expand Down

0 comments on commit cdc9f69

Please sign in to comment.