Skip to content

Commit

Permalink
Add ability to proactively close FTP and SFTP connections.
Browse files Browse the repository at this point in the history
  • Loading branch information
frankdejonge committed Mar 8, 2024
1 parent 383e17d commit 74ddd89
Show file tree
Hide file tree
Showing 9 changed files with 100 additions and 10 deletions.
12 changes: 10 additions & 2 deletions src/Ftp/FtpAdapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,15 @@
use function error_clear_last;
use function error_get_last;
use function ftp_chdir;
use function ftp_close;
use function is_string;

class FtpAdapter implements FilesystemAdapter
{
private const SYSTEM_TYPE_WINDOWS = 'windows';
private const SYSTEM_TYPE_UNIX = 'unix';

private FtpConnectionProvider $connectionProvider;
private ConnectionProvider $connectionProvider;
private ConnectivityChecker $connectivityChecker;

/**
Expand All @@ -55,7 +56,7 @@ class FtpAdapter implements FilesystemAdapter

public function __construct(
private FtpConnectionOptions $connectionOptions,
FtpConnectionProvider $connectionProvider = null,
ConnectionProvider $connectionProvider = null,
ConnectivityChecker $connectivityChecker = null,
VisibilityConverter $visibilityConverter = null,
MimeTypeDetector $mimeTypeDetector = null,
Expand Down Expand Up @@ -104,6 +105,13 @@ private function connection()
return $this->connection;
}

public function disconnect(): void
{
if ($this->hasFtpConnection()) {
ftp_close($this->connection);
}
}

private function isPureFtpdServer(): bool
{
if ($this->isPureFtpdServer !== null) {
Expand Down
22 changes: 21 additions & 1 deletion src/Ftp/FtpAdapterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,13 @@ protected static function createFilesystemAdapter(): FilesystemAdapter
]);

static::$connectivityChecker = new ConnectivityCheckerThatCanFail(new NoopCommandConnectivityChecker());
static::$connectionProvider = new StubConnectionProvider(new FtpConnectionProvider());

Check failure on line 29 in src/Ftp/FtpAdapterTest.php

View workflow job for this annotation

GitHub Actions / PHPUnit tests on 8.1

Static property League\Flysystem\Ftp\FtpAdapterTestCase::$connectionProvider (Ftp\StubConnectionProvider) does not accept League\Flysystem\Ftp\StubConnectionProvider.

return new FtpAdapter($options, null, static::$connectivityChecker);
return new FtpAdapter(
$options,
static::$connectionProvider,
static::$connectivityChecker,
);
}

/**
Expand All @@ -50,6 +55,21 @@ public function disconnect_after_destruct(): void
$this->assertFalse((new NoopCommandConnectivityChecker())->isConnected($connection));
}

/**
* @test
*/
public function it_can_disconnect(): void
{
/** @var FtpAdapter $adapter */
$adapter = $this->adapter();

$this->assertFalse($adapter->fileExists('not-existing.file'));

self::assertTrue(static::$connectivityChecker->isConnected(static::$connectionProvider->connection));

Check failure on line 68 in src/Ftp/FtpAdapterTest.php

View workflow job for this annotation

GitHub Actions / PHPUnit tests on 8.1

Access to property $connection on an unknown class Ftp\StubConnectionProvider.
$adapter->disconnect();
self::assertFalse(static::$connectivityChecker->isConnected(static::$connectionProvider->connection));

Check failure on line 70 in src/Ftp/FtpAdapterTest.php

View workflow job for this annotation

GitHub Actions / PHPUnit tests on 8.1

Access to property $connection on an unknown class Ftp\StubConnectionProvider.
}

/**
* @test
*/
Expand Down
6 changes: 6 additions & 0 deletions src/Ftp/FtpAdapterTestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace League\Flysystem\Ftp;

use Ftp\StubConnectionProvider;
use Generator;
use League\Flysystem\AdapterTestUtilities\FilesystemAdapterTestCase;
use League\Flysystem\Config;
Expand Down Expand Up @@ -37,6 +38,11 @@ protected function setUp(): void
*/
protected static $connectivityChecker;

/**
* @var StubConnectionProvider
*/
protected static $connectionProvider;

Check failure on line 44 in src/Ftp/FtpAdapterTestCase.php

View workflow job for this annotation

GitHub Actions / PHPUnit tests on 8.1

Property League\Flysystem\Ftp\FtpAdapterTestCase::$connectionProvider has unknown class Ftp\StubConnectionProvider as its type.

/**
* @after
*/
Expand Down
18 changes: 18 additions & 0 deletions src/Ftp/StubConnectionProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php
declare(strict_types=1);

namespace League\Flysystem\Ftp;

class StubConnectionProvider implements ConnectionProvider
{
public mixed $connection;

public function __construct(private ConnectionProvider $provider)
{
}

public function createConnection(FtpConnectionOptions $options)
{
return $this->connection = $this->provider->createConnection($options);
}
}
3 changes: 3 additions & 0 deletions src/PhpseclibV3/ConnectionProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@

use phpseclib3\Net\SFTP;

/**
* @method void disconnect()
*/
interface ConnectionProvider
{
public function provideConnection(): SFTP;
Expand Down
5 changes: 5 additions & 0 deletions src/PhpseclibV3/SftpAdapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,11 @@ public function fileExists(string $path): bool
}
}

public function disconnect(): void
{
$this->connectionProvider->disconnect();
}

public function directoryExists(string $path): bool
{
$location = $this->prefixer->prefixDirectoryPath($path);
Expand Down
26 changes: 21 additions & 5 deletions src/PhpseclibV3/SftpAdapterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public static function setUpBeforeClass(): void
}

/**
* @var ConnectionProvider
* @var StubSftpConnectionProvider
*/
private static $connectionProvider;

Expand Down Expand Up @@ -214,9 +214,26 @@ public function list_contents_directory_does_not_exist(): void
$this->assertCount(0, iterator_to_array($contents));
}

private static function connectionProvider(): ConnectionProvider
/**
* @test
*/
public function it_can_proactively_close_a_connection(): void
{
/** @var SftpAdapter $adapter */
$adapter = $this->adapter();

self::assertFalse($adapter->fileExists('does not exists at all'));

self::assertTrue(static::$connectionProvider->connection->isConnected());

$adapter->disconnect();

self::assertFalse(static::$connectionProvider->connection->isConnected());
}

private static function connectionProvider(): StubSftpConnectionProvider
{
if ( ! static::$connectionProvider instanceof ConnectionProvider) {
if ( ! static::$connectionProvider instanceof StubSftpConnectionProvider) {
static::$connectionProvider = new StubSftpConnectionProvider('localhost', 'foo', 'pass', 2222);
}

Expand All @@ -229,8 +246,7 @@ private static function connectionProvider(): ConnectionProvider
private function adapterWithInvalidRoot(): SftpAdapter
{
$provider = static::connectionProvider();
$adapter = new SftpAdapter($provider, '/invalid');

return $adapter;
return new SftpAdapter($provider, '/invalid');
}
}
7 changes: 7 additions & 0 deletions src/PhpseclibV3/SftpConnectionProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,13 @@ public function provideConnection(): SFTP
return $this->connection = $connection;
}

public function disconnect(): void
{
if ($this->connection) {
$this->connection->disconnect();
}
}

private function setupConnection(): SFTP
{
$connection = new SFTP($this->host, $this->port, $this->timeout);
Expand Down
11 changes: 9 additions & 2 deletions src/PhpseclibV3/StubSftpConnectionProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
class StubSftpConnectionProvider implements ConnectionProvider
{
/**
* @var SftpStub
* @var SftpStub|null
*/
private $connection;
public $connection;

public function __construct(
private string $host,
Expand All @@ -21,6 +21,13 @@ public function __construct(
) {
}

public function disconnect(): void
{
if ($this->connection) {
$this->connection->disconnect();
}
}

public function provideConnection(): SFTP
{
if ( ! $this->connection instanceof SFTP) {
Expand Down

0 comments on commit 74ddd89

Please sign in to comment.