Skip to content

Commit

Permalink
thephpleague#98: SftpAdapter tries to create a missing directory when…
Browse files Browse the repository at this point in the history
… rename is called
  • Loading branch information
proggeler committed Dec 19, 2019
1 parent 8ae057d commit b93df9f
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 65 deletions.
7 changes: 7 additions & 0 deletions src/SftpAdapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -518,6 +518,13 @@ public function rename($path, $newpath)
{
$connection = $this->getConnection();

$dirname = dirname($newpath);
$metadata = $this->getMetadata($dirname);

if ($metadata === false || $metadata['type'] !== 'dir') {
$this->createDir($dirname, new Config());
}

return $connection->rename($path, $newpath);
}

Expand Down
162 changes: 97 additions & 65 deletions tests/SftpAdapterTests.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ class SftpTests extends TestCase

protected function setup()
{
if (! defined('NET_SFTP_TYPE_DIRECTORY')) {
if (!defined('NET_SFTP_TYPE_REGULAR')) {
define('NET_SFTP_TYPE_REGULAR', 1);
}
if (!defined('NET_SFTP_TYPE_DIRECTORY')) {
define('NET_SFTP_TYPE_DIRECTORY', 2);
}
}
Expand All @@ -44,9 +47,9 @@ public function adapterProvider()
public function testHas($filesystem, $adapter, $mock)
{
$mock->shouldReceive('stat')->andReturn([
'type' => NET_SFTP_TYPE_DIRECTORY,
'mtime' => time(),
'size' => 20,
'type' => NET_SFTP_TYPE_DIRECTORY,
'mtime' => time(),
'size' => 20,
'permissions' => 0777,
]);

Expand Down Expand Up @@ -96,9 +99,9 @@ public function testDelete($filesystem, $adapter, $mock)
{
$mock->shouldReceive('delete')->andReturn(true, false);
$mock->shouldReceive('stat')->andReturn([
'type' => 1,
'mtime' => time(),
'size' => 20,
'type' => 1,
'mtime' => time(),
'size' => 20,
'permissions' => 0777,
]);
$this->assertTrue($filesystem->delete('something'));
Expand All @@ -112,9 +115,9 @@ public function testUpdate(FilesystemInterface $filesystem, $adapter, $mock)
{
$mock->shouldReceive('put')->andReturn(true, false);
$mock->shouldReceive('stat')->andReturn([
'type' => NET_SFTP_TYPE_DIRECTORY,
'mtime' => time(),
'size' => 20,
'type' => NET_SFTP_TYPE_DIRECTORY,
'mtime' => time(),
'size' => 20,
'permissions' => 0777,
]);
$this->assertTrue($filesystem->update('something', 'something'));
Expand All @@ -129,9 +132,9 @@ public function testUpdateStream(FilesystemInterface $filesystem, $adapter, $moc
$stream = tmpfile();
$mock->shouldReceive('put')->andReturn(true, false);
$mock->shouldReceive('stat')->andReturn([
'type' => NET_SFTP_TYPE_DIRECTORY,
'mtime' => time(),
'size' => 20,
'type' => NET_SFTP_TYPE_DIRECTORY,
'mtime' => time(),
'size' => 20,
'permissions' => 0777,
]);
$this->assertTrue($filesystem->updateStream('something', $stream));
Expand All @@ -145,9 +148,9 @@ public function testUpdateStream(FilesystemInterface $filesystem, $adapter, $moc
public function testSetVisibility($filesystem, $adapter, $mock)
{
$mock->shouldReceive('stat')->andReturn([
'type' => 1, // file
'mtime' => time(),
'size' => 20,
'type' => 1, // file
'mtime' => time(),
'size' => 20,
'permissions' => 0777,
]);
$mock->shouldReceive('chmod')->twice()->andReturn(true, false);
Expand All @@ -162,9 +165,9 @@ public function testSetVisibility($filesystem, $adapter, $mock)
public function testSetVisibilityInvalid($filesystem, $adapter, $mock)
{
$mock->shouldReceive('stat')->andReturn([
'type' => 1, // file
'mtime' => time(),
'size' => 20,
'type' => 1, // file
'mtime' => time(),
'size' => 20,
'permissions' => 0777,
]);
$mock->shouldReceive('stat')->once()->andReturn(true);
Expand All @@ -176,15 +179,44 @@ public function testSetVisibilityInvalid($filesystem, $adapter, $mock)
*/
public function testRename($filesystem, $adapter, $mock)
{
$mock->shouldReceive('stat')->andReturn([
'type' => NET_SFTP_TYPE_DIRECTORY,
'mtime' => time(),
'size' => 20,
$mock->shouldReceive('stat')->with('old')->andReturn([
'type' => NET_SFTP_TYPE_REGULAR, // file
'mtime' => time(),
'size' => 20,
'permissions' => 0777,
], false);
]);
$mock->shouldReceive('stat')->with('old')->andReturn(false);
$mock->shouldReceive('stat')->with('.')->andReturn([
'type' => NET_SFTP_TYPE_DIRECTORY,
'mtime' => time(),
'size' => 20,
'permissions' => 0777,
]);

$mock->shouldReceive('rename')->andReturn(true);
$result = $filesystem->rename('old', 'new');
$this->assertTrue($result);
$mock->shouldNotHaveReceived('mkdir');
}

/**
* @dataProvider adapterProvider
*/
public function testRenameCreatesDirectory($filesystem, $adapter, $mock)
{
$mock->shouldReceive('stat')->with('old_dir/file.ext')->andReturn([
'type' => NET_SFTP_TYPE_REGULAR, // file
'mtime' => time(),
'size' => 20,
'permissions' => 0777,
]);
$mock->shouldReceive('stat')->with('new_dir/file.ext')->andReturn(false);
$mock->shouldReceive('stat')->with('new_dir')->andReturn(false);

$mock->shouldReceive('rename')->andReturn(true);
$result = $filesystem->rename('old_dir/file.ext', 'new_dir/file.ext');
$this->assertTrue($result);
$mock->shouldHaveReceived('mkdir');
}

/**
Expand All @@ -203,19 +235,19 @@ public function testDeleteDir($filesystem, $adapter, $mock)
public function testListContents($filesystem, $adapter, $mock)
{
$mock->shouldReceive('rawlist')->andReturn(false, [
'.' => [],
'.' => [],
'dirname' => [
'type' => NET_SFTP_TYPE_DIRECTORY,
'mtime' => time(),
'size' => 20,
'type' => NET_SFTP_TYPE_DIRECTORY,
'mtime' => time(),
'size' => 20,
'permissions' => 0777,
],
], [
'..' => [],
'..' => [],
'dirname' => [
'type' => 1,
'mtime' => time(),
'size' => 20,
'type' => 1,
'mtime' => time(),
'size' => 20,
'permissions' => 0777,
],
]);
Expand Down Expand Up @@ -245,12 +277,12 @@ public function methodProvider()
public function testMetaMethods($filesystem, $adapter, $mock, $method, $type)
{
$mock->shouldReceive('stat')->andReturn([
'type' => NET_SFTP_TYPE_DIRECTORY,
'mtime' => time(),
'size' => 20,
'type' => NET_SFTP_TYPE_DIRECTORY,
'mtime' => time(),
'size' => 20,
'permissions' => 0777,
]);
$result = $filesystem->{$method}(uniqid().'object.ext');
$result = $filesystem->{$method}(uniqid() . 'object.ext');
$this->assertInternalType($type, $result);
}

Expand All @@ -260,12 +292,12 @@ public function testMetaMethods($filesystem, $adapter, $mock, $method, $type)
public function testGetVisibility($filesystem, $adapter, $mock)
{
$mock->shouldReceive('stat')->andReturn([
'type' => NET_SFTP_TYPE_DIRECTORY,
'mtime' => time(),
'size' => 20,
'type' => NET_SFTP_TYPE_DIRECTORY,
'mtime' => time(),
'size' => 20,
'permissions' => 0777,
]);
$result = $adapter->getVisibility(uniqid().'object.ext');
$result = $adapter->getVisibility(uniqid() . 'object.ext');
$this->assertInternalType('array', $result);
$result = $result['visibility'];
$this->assertInternalType('string', $result);
Expand All @@ -278,9 +310,9 @@ public function testGetVisibility($filesystem, $adapter, $mock)
public function testGetTimestamp($filesystem, $adapter, $mock)
{
$mock->shouldReceive('stat')->andReturn([
'type' => NET_SFTP_TYPE_DIRECTORY,
'mtime' => $time = time(),
'size' => 20,
'type' => NET_SFTP_TYPE_DIRECTORY,
'mtime' => $time = time(),
'size' => 20,
'permissions' => 0777,
]);
$result = $adapter->getTimestamp('object.ext');
Expand Down Expand Up @@ -309,9 +341,9 @@ public function testCreateDir($filesystem, $adapter, $mock)
public function testRead($filesystem, $adapter, $mock)
{
$mock->shouldReceive('stat')->andReturn([
'type' => 1,
'mtime' => time(),
'size' => 20,
'type' => 1,
'mtime' => time(),
'size' => 20,
'permissions' => 0777,
]);
$mock->shouldReceive('get')->andReturn('file contents', false);
Expand Down Expand Up @@ -343,9 +375,9 @@ public function testReadStream($filesystem, $adapter, $mock)
public function testGetMimetype($filesystem, $adapter, $mock)
{
$mock->shouldReceive('stat')->andReturn([
'type' => 1,
'mtime' => time(),
'size' => 20,
'type' => 1,
'mtime' => time(),
'size' => 20,
'permissions' => 0777,
]);

Expand Down Expand Up @@ -389,7 +421,7 @@ public function testAgentSetGet($filesystem, SftpAdapter $adapter, $mock)
*/
public function testPrivateKeyFileSetGet($filesystem, $adapter, $mock)
{
file_put_contents($key = __DIR__.'/some.key', 'key contents');
file_put_contents($key = __DIR__ . '/some.key', 'key contents');
$this->assertEquals($adapter, $adapter->setPrivateKey($key));
$this->assertInstanceOf('phpseclib\Crypt\RSA', $adapter->getPrivateKey());
@unlink($key);
Expand Down Expand Up @@ -489,7 +521,7 @@ public function testConnectWithDoubleAuthentication($filesystem, $adapter, $mock
$adapter->setNetSftpConnection($mock);

$expectedAuths = [$adapter->getPrivateKey(), 'test'];
$mock->shouldReceive('login')->with('test', Mockery::on(function($auth) use (&$expectedAuths) {
$mock->shouldReceive('login')->with('test', Mockery::on(function ($auth) use (&$expectedAuths) {
return $auth == array_shift($expectedAuths);
}))->twice()->andReturn(false, true);

Expand Down Expand Up @@ -574,17 +606,17 @@ public function testListContentsDir($filesystem, $adapter, $mock)
[
'dirname' =>
[
'type' => NET_SFTP_TYPE_DIRECTORY,
'mtime' => time(),
'permissions' => 0777,
'filename' => 'dirname'
'type' => NET_SFTP_TYPE_DIRECTORY,
'mtime' => time(),
'permissions' => 0777,
'filename' => 'dirname'
],
'filename' =>
[
'mtime' => time(),
'size' => 20,
'permissions' => 0777,
'filename' => 'filename'
'mtime' => time(),
'size' => 20,
'permissions' => 0777,
'filename' => 'filename'
],
]
);
Expand All @@ -607,7 +639,7 @@ public function testNetSftpConnectionSetter()
$this->assertEquals($mock, $adapter->getConnection());
}

public function testHostFingerprintIsVerifiedIfProvided ()
public function testHostFingerprintIsVerifiedIfProvided()
{
$adapter = new SftpAdapter([
'host' => 'example.org',
Expand All @@ -630,7 +662,7 @@ public function testHostFingerprintIsVerifiedIfProvided ()
$adapter->connect();
}

public function testHostFingerprintNotIsVerifiedIfNotProvided ()
public function testHostFingerprintNotIsVerifiedIfNotProvided()
{
$adapter = new SftpAdapter([
'host' => 'example.org',
Expand All @@ -656,7 +688,7 @@ public function testHostFingerprintNotIsVerifiedIfNotProvided ()
* @expectedException LogicException
* @expectedExceptionMessage The authenticity of host example.org can't be established.
*/
public function testMisMatchingHostFingerprintAbortsLogin ()
public function testMisMatchingHostFingerprintAbortsLogin()
{
$adapter = new SftpAdapter([
'host' => 'example.org',
Expand Down Expand Up @@ -721,10 +753,10 @@ public function testListContentsWithZeroNamedDir($filesystem, $adapter, $mock)
[
'0' =>
[
'type' => NET_SFTP_TYPE_DIRECTORY,
'mtime' => time(),
'type' => NET_SFTP_TYPE_DIRECTORY,
'mtime' => time(),
'permissions' => 0777,
'filename' => '0'
'filename' => '0'
]
]
);
Expand Down

0 comments on commit b93df9f

Please sign in to comment.