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:
Fabien Potencier 2017-01-08 11:58:00 -08:00
commit 2ee8626e60
2 changed files with 101 additions and 1 deletions

View File

@ -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
*

View File

@ -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();