feature #20612 [Filesystem] Add appendToFile() (chalasr)
This PR was merged into the 3.3-dev branch.
Discussion
----------
[Filesystem] Add appendToFile()
| Q | A
| ------------- | ---
| Branch? | master
| Bug fix? | no
| New feature? | yes
| BC breaks? | no
| Deprecations? | no
| Tests pass? | yes
| Fixed tickets | n/a
| License | MIT
| Doc PR | todo
So we could append content to a file:
```php
(new Filesystem)->appendToFile($file, 'bar');
```
instead of doing it in two steps:
```php
if (false === $content = @file_get_contents($file)) {
throw new \Exception();
}
(new Filesystem)->dumpFile($file, $content.'bar');
```
Doing it opt-in using `dumpFile(..., $append = false)` would have been enough but not possible for BC.
Commits
-------
9fb5293122
[Filesystem] Add appendToFile()
This commit is contained in:
commit
2ee8626e60
@ -624,7 +624,7 @@ class Filesystem
|
||||
* @param string $filename The file to be written to
|
||||
* @param string $content The data to write into the file
|
||||
*
|
||||
* @throws IOException If the file cannot be written to.
|
||||
* @throws IOException If the file cannot be written to
|
||||
*/
|
||||
public function dumpFile($filename, $content)
|
||||
{
|
||||
@ -648,6 +648,31 @@ class Filesystem
|
||||
$this->rename($tmpFile, $filename, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends content to an existing file.
|
||||
*
|
||||
* @param string $filename The file to which to append content
|
||||
* @param string $content The content to append
|
||||
*
|
||||
* @throws IOException If the file is not writable
|
||||
*/
|
||||
public function appendToFile($filename, $content)
|
||||
{
|
||||
$dir = dirname($filename);
|
||||
|
||||
if (!is_dir($dir)) {
|
||||
$this->mkdir($dir);
|
||||
}
|
||||
|
||||
if (!is_writable($dir)) {
|
||||
throw new IOException(sprintf('Unable to write to the "%s" directory.', $dir), 0, null, $dir);
|
||||
}
|
||||
|
||||
if (false === @file_put_contents($filename, $content, FILE_APPEND)) {
|
||||
throw new IOException(sprintf('Failed to write file "%s".', $filename), 0, null, $filename);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $files
|
||||
*
|
||||
|
@ -1406,6 +1406,81 @@ class FilesystemTest extends FilesystemTestCase
|
||||
$this->assertSame('bar', file_get_contents($filename));
|
||||
}
|
||||
|
||||
public function testAppendToFile()
|
||||
{
|
||||
$filename = $this->workspace.DIRECTORY_SEPARATOR.'foo'.DIRECTORY_SEPARATOR.'bar.txt';
|
||||
|
||||
// skip mode check on Windows
|
||||
if ('\\' !== DIRECTORY_SEPARATOR) {
|
||||
$oldMask = umask(0002);
|
||||
}
|
||||
|
||||
$this->filesystem->dumpFile($filename, 'foo');
|
||||
|
||||
$this->filesystem->appendToFile($filename, 'bar');
|
||||
|
||||
$this->assertFileExists($filename);
|
||||
$this->assertSame('foobar', file_get_contents($filename));
|
||||
|
||||
// skip mode check on Windows
|
||||
if ('\\' !== DIRECTORY_SEPARATOR) {
|
||||
$this->assertFilePermissions(664, $filename, 'The written file should keep the same permissions as before.');
|
||||
umask($oldMask);
|
||||
}
|
||||
}
|
||||
|
||||
public function testAppendToFileWithScheme()
|
||||
{
|
||||
if (defined('HHVM_VERSION')) {
|
||||
$this->markTestSkipped('HHVM does not handle the file:// scheme correctly');
|
||||
}
|
||||
|
||||
$scheme = 'file://';
|
||||
$filename = $scheme.$this->workspace.DIRECTORY_SEPARATOR.'foo'.DIRECTORY_SEPARATOR.'baz.txt';
|
||||
$this->filesystem->dumpFile($filename, 'foo');
|
||||
|
||||
$this->filesystem->appendToFile($filename, 'bar');
|
||||
|
||||
$this->assertFileExists($filename);
|
||||
$this->assertSame('foobar', file_get_contents($filename));
|
||||
}
|
||||
|
||||
public function testAppendToFileWithZlibScheme()
|
||||
{
|
||||
$scheme = 'compress.zlib://';
|
||||
$filename = $this->workspace.DIRECTORY_SEPARATOR.'foo'.DIRECTORY_SEPARATOR.'baz.txt';
|
||||
$this->filesystem->dumpFile($filename, 'foo');
|
||||
|
||||
// Zlib stat uses file:// wrapper so remove it
|
||||
$this->assertSame('foo', file_get_contents(str_replace($scheme, '', $filename)));
|
||||
|
||||
$this->filesystem->appendToFile($filename, 'bar');
|
||||
|
||||
$this->assertFileExists($filename);
|
||||
$this->assertSame('foobar', file_get_contents($filename));
|
||||
}
|
||||
|
||||
public function testAppendToFileCreateTheFileIfNotExists()
|
||||
{
|
||||
$filename = $this->workspace.DIRECTORY_SEPARATOR.'foo'.DIRECTORY_SEPARATOR.'bar.txt';
|
||||
|
||||
// skip mode check on Windows
|
||||
if ('\\' !== DIRECTORY_SEPARATOR) {
|
||||
$oldMask = umask(0002);
|
||||
}
|
||||
|
||||
$this->filesystem->appendToFile($filename, 'bar');
|
||||
|
||||
// skip mode check on Windows
|
||||
if ('\\' !== DIRECTORY_SEPARATOR) {
|
||||
$this->assertFilePermissions(664, $filename);
|
||||
umask($oldMask);
|
||||
}
|
||||
|
||||
$this->assertFileExists($filename);
|
||||
$this->assertSame('bar', file_get_contents($filename));
|
||||
}
|
||||
|
||||
public function testCopyShouldKeepExecutionPermission()
|
||||
{
|
||||
$this->markAsSkippedIfChmodIsMissing();
|
||||
|
Reference in New Issue
Block a user