Permalink
Browse files

feature(file): adds ElggFile::transfer() for reliable renaming of files

rename() is not a reliable option to renaming files on filestore, as the
target file may be in a non-existent directory.

This adds a reliable and tested method to transfer an ElggFile to a new owner
and copy file contents into a file with a new filename
  • Loading branch information...
hypeJunction committed Apr 13, 2016
1 parent b793fb1 commit bf50c5d0d1ff5151e87c38438f312e25409bec1e
Showing with 72 additions and 0 deletions.
  1. +33 −0 engine/classes/ElggFile.php
  2. +39 −0 engine/tests/phpunit/ElggFileTest.php
@@ -502,6 +502,39 @@ public function save() {
return true;
}
/**
* Transfer a file to a new owner and sets a new filename,
* copies file contents to a new location.
*
* This is an alternative to using rename() which fails to move files to
* a non-existent directory under new owner's filestore directory
*
* @param int $owner_guid New owner's guid
* @param string $filename New filename (uses old filename if not set)
* @return bool
*/
public function transfer($owner_guid, $filename = null) {
if (!$owner_guid) {
return false;
}
if (!$this->exists()) {
return false;
}
if (!$filename) {
$filename = $this->getFilename();
}
$filestorename = $this->getFilenameOnFilestore();
$this->owner_guid = $owner_guid;
$this->setFilename($filename);
$this->open('write');
$this->close();
return rename($filestorename, $this->getFilenameOnFilestore());
}
/**
* Get property names to serialize.
*
@@ -376,4 +376,43 @@ public function testCanDeleteSymlinkWithMissingTarget() {
$this->assertFalse(is_link($from_filename));
$this->assertFalse($to->exists());
}
/**
* @group FileService
*/
public function testCanTransferFile() {
$dataroot = elgg_get_config('dataroot');
$file = new \ElggFile();
$file->owner_guid = 3;
$file->setFilename("file-to-transfer.txt");
$file->setFilename("file-to-transfer.txt");
// Fail with non-existent file
$this->assertFalse($file->transfer(4));
$file->open('write');
$file->write('Transfer');
$file->close();
$this->assertTrue($file->transfer(4));
$this->assertEquals(4, $file->owner_guid);
$this->assertEquals("file-to-transfer.txt", $file->getFilename());
$this->assertEquals("{$dataroot}1/4/file-to-transfer.txt", $file->getFilenameOnFilestore());
$this->assertTrue($file->exists());
$this->assertFalse(file_exists("{$dataroot}1/3/file-to-transfer.txt"));
$this->assertTrue($file->transfer(3, 'tmp/transferred-file.txt'));
$this->assertEquals(3, $file->owner_guid);
$this->assertEquals("tmp/transferred-file.txt", $file->getFilename());
$this->assertEquals("{$dataroot}1/3/tmp/transferred-file.txt", $file->getFilenameOnFilestore());
$this->assertTrue($file->exists());
$this->assertFalse(file_exists("{$dataroot}1/4/file-to-transfer.txt"));
// cleanup
_elgg_rmdir("{$dataroot}1/3/");
_elgg_rmdir("{$dataroot}1/4/");
}
}

0 comments on commit bf50c5d

Please sign in to comment.