Verified Commit c141f9e6 authored by Dave Long's avatar Dave Long
Browse files

Issue #3344877 by alexpott, silverham, quietone: [regression] FTPExtension...

Issue #3344877 by alexpott, silverham, quietone: [regression] FTPExtension class can no longer connect as of 9.5.x
parent 71b3b5c6
Loading
Loading
Loading
Loading
Loading
+11 −26
Original line number Diff line number Diff line
@@ -704,26 +704,11 @@
	'count' => 1,
	'path' => __DIR__ . '/lib/Drupal/Core/Field/Plugin/Field/FieldType/NumericItemBase.php',
];
$ignoreErrors[] = [
	'message' => '#^Access to an undefined property Drupal\\\\Core\\\\FileTransfer\\\\FTPExtension\\:\\:\\$connection\\.$#',
	'count' => 19,
	'path' => __DIR__ . '/lib/Drupal/Core/FileTransfer/FTPExtension.php',
];
$ignoreErrors[] = [
	'message' => '#^Access to an undefined property Drupal\\\\Core\\\\FileTransfer\\\\FileTransfer\\:\\:\\$chroot\\.$#',
	'count' => 3,
	'path' => __DIR__ . '/lib/Drupal/Core/FileTransfer/FileTransfer.php',
];
$ignoreErrors[] = [
	'message' => '#^Method Drupal\\\\Core\\\\FileTransfer\\\\FileTransfer\\:\\:__get\\(\\) should return bool\\|string but return statement is missing\\.$#',
	'count' => 1,
	'path' => __DIR__ . '/lib/Drupal/Core/FileTransfer/FileTransfer.php',
];
$ignoreErrors[] = [
	'message' => '#^Access to an undefined property Drupal\\\\Core\\\\FileTransfer\\\\SSH\\:\\:\\$connection\\.$#',
	'count' => 9,
	'path' => __DIR__ . '/lib/Drupal/Core/FileTransfer/SSH.php',
];
$ignoreErrors[] = [
	'message' => '#^Call to deprecated constant REQUEST_TIME\\: Deprecated in drupal\\:8\\.3\\.0 and is removed from drupal\\:11\\.0\\.0\\. Use \\\\Drupal\\:\\:time\\(\\)\\-\\>getRequestTime\\(\\); $#',
	'count' => 4,
@@ -2275,11 +2260,6 @@
	'count' => 1,
	'path' => __DIR__ . '/modules/system/tests/modules/service_provider_test/src/TestClass.php',
];
$ignoreErrors[] = [
	'message' => '#^Access to an undefined property Drupal\\\\Tests\\\\system\\\\Functional\\\\FileTransfer\\\\TestFileTransfer\\:\\:\\$connection\\.$#',
	'count' => 5,
	'path' => __DIR__ . '/modules/system/tests/src/Functional/FileTransfer/TestFileTransfer.php',
];
$ignoreErrors[] = [
	'message' => '#^Variable \\$form_output in empty\\(\\) always exists and is not falsy\\.$#',
	'count' => 2,
@@ -2370,6 +2350,11 @@
	'count' => 4,
	'path' => __DIR__ . '/modules/update/src/UpdateProcessor.php',
];
$ignoreErrors[] = [
	'message' => '#^Class Drupal\\\\update\\\\ProjectCoreCompatibility constructor invoked with 3 parameters, 2 required\\.$#',
	'count' => 1,
	'path' => __DIR__ . '/modules/update/tests/src/Unit/ProjectCoreCompatibilityTest.php',
];
$ignoreErrors[] = [
	'message' => '#^Variable \\$users might not be defined\\.$#',
	'count' => 1,
+18 −24
Original line number Diff line number Diff line
@@ -10,7 +10,15 @@
 * to the server using some backend (for example FTP or SSH). To keep security,
 * the password should always be asked from the user and never stored. For
 * safety, all methods operate only inside a "jail", by default the Drupal root.
 *
 * The following properties are managed by magic methods:
 *
 * @property string|false|null $chroot
 *   Path to connection chroot.
 * @property object|false|null $connection
 *   The instantiated connection object.
 */
#[\AllowDynamicProperties]
abstract class FileTransfer {

  /**
@@ -48,20 +56,6 @@ abstract class FileTransfer {
   */
  protected $jail;

  /**
   * Path to connection chroot.
   *
   * @var string|false|null
   */
  private $chrootPath;

  /**
   * The instantiated connection object.
   *
   * @var object|false|null
   */
  private $connectionHandle;

  /**
   * Constructs a Drupal\Core\FileTransfer\FileTransfer object.
   *
@@ -114,12 +108,12 @@ public static function factory($jail, $settings) {
  public function __get($name) {
    if ($name == 'connection') {
      $this->connect();
      return $this->connectionHandle;
      return $this->connection;
    }

    if ($name == 'chroot') {
      $this->setChroot();
      return $this->chrootPath;
      return $this->chroot;
    }
  }

@@ -128,10 +122,10 @@ public function __get($name) {
   */
  public function __set(string $name, $value): void {
    if ($name == 'connection') {
      $this->connectionHandle = $value;
      $this->connection = $value;
    }
    elseif ($name == 'chroot') {
      $this->chrootPath = $value;
      $this->chroot = $value;
    }
  }

@@ -140,10 +134,10 @@ public function __set(string $name, $value): void {
   */
  public function __isset(string $name): bool {
    if ($name == 'connection') {
      return isset($this->connectionHandle);
      return isset($this->connection);
    }
    if ($name == 'chroot') {
      return isset($this->chrootPath);
      return isset($this->chroot);
    }
    return FALSE;
  }
@@ -153,10 +147,10 @@ public function __isset(string $name): bool {
   */
  public function __unset(string $name): void {
    if ($name == 'connection') {
      unset($this->connectionHandle);
      unset($this->connection);
    }
    elseif ($name == 'chroot') {
      unset($this->chrootPath);
      unset($this->chroot);
    }
  }

@@ -293,8 +287,8 @@ final protected function fixRemotePath($path, $strip_chroot = TRUE) {
    // Strip out windows drive letter if its there.
    $path = preg_replace('|^([a-z]{1}):|i', '', $path);
    if ($strip_chroot) {
      if ($this->chrootPath && str_starts_with($path, $this->chrootPath)) {
        $path = ($path == $this->chrootPath) ? '' : substr($path, strlen($this->chrootPath));
      if ($this->chroot && str_starts_with($path, $this->chroot)) {
        $path = ($path == $this->chroot) ? '' : substr($path, strlen($this->chroot));
      }
    }
    return $path;
+4 −3
Original line number Diff line number Diff line
@@ -42,9 +42,10 @@ public static function factory($jail, $settings) {
  }

  public function connect() {
    $connection = new MockTestConnection();
    $connection->connectionString = 'test://' . urlencode($this->username) . ':' . urlencode($this->password) . "@$this->host:$this->port/";
    $this->connection = $connection;
    $this->connection = new MockTestConnection();
    // Access the connection via the property. The property used to be set via a
    // magic method and this can cause problems if coded incorrectly.
    $this->connection->connectionString = 'test://' . urlencode($this->username) . ':' . urlencode($this->password) . "@$this->host:$this->port/";
  }

  public function copyFileJailed($source, $destination) {
+34 −0
Original line number Diff line number Diff line
<?php

declare(strict_types=1);

namespace Drupal\Tests\system\Unit\FileTransfer;

use Drupal\Tests\system\Functional\FileTransfer\MockTestConnection;
use Drupal\Tests\system\Functional\FileTransfer\TestFileTransfer;
use Drupal\Tests\UnitTestCase;

/**
 * @group FileTransfer
 */
class FileTransferTest extends UnitTestCase {

  /**
   * @var \Drupal\Tests\system\Functional\FileTransfer\TestFileTransfer
   */
  protected TestFileTransfer $testConnection;

  /**
   * {@inheritdoc}
   */
  protected function setUp(): void {
    parent::setUp();
    $this->testConnection = TestFileTransfer::factory($this->root, []);
  }

  public function testFileTransferMagicMethods() {
    // Test to ensure __get() preserves public access.
    $this->assertInstanceOf(MockTestConnection::class, $this->testConnection->connection);
  }

}