Skip to content

Support for sftp - #88

Open
bartoszkubicki wants to merge 1 commit into
masterfrom
feature/support-for-sftp-files
Open

Support for sftp#88
bartoszkubicki wants to merge 1 commit into
masterfrom
feature/support-for-sftp-files

Conversation

@bartoszkubicki

@bartoszkubicki bartoszkubicki commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

This pull request adds support for a new sftpfiles import type, enabling file imports over SFTP with configurable connection details and archiving behavior. It introduces a new SFTP archiver, updates configuration handling to support the new type, and provides a fully working example module to demonstrate usage. Additionally, the project is now explicitly licensed under the MIT License.

New SFTP Import Type and Example Module

  • Added support for sftpfiles as a new import type, including configuration schema, type registration, and example implementation:
    • Updated Converter to recognize and process sftpfiles imports, with fields for SFTP connection, file matching, archiving, and processing options (F0bed31fR1, src/Config/Converter.phpR68-R78).
    • Registered the new type in the import manager for runtime support [1] [2].
    • Added a full example Magento module (examples/sftpfiles/MyVendor/Import) with DI and import configuration, a sample LocationConfigProvider, and minimal Specification and Writer classes [1] [2] [3] [4] [5] [6] [7].

SFTP Archiving Support

  • Introduced the SftpArchiver class to handle archiving or deleting imported files on the remote SFTP server after successful import, and mapped it to the new source type in the archiver factory [1] [2] [3].

General Improvements and Maintenance

  • Updated the license to MIT, making the project's licensing explicit and permissive.
  • Refactored configuration and type handling for clarity and maintainability, including improved type hints and imports in Converter [1] [2] [3] [4] [5] [6] [7].

@bartoszkubicki
bartoszkubicki marked this pull request as draft August 6, 2026 14:35
@bartoszkubicki
bartoszkubicki force-pushed the feature/support-for-sftp-files branch 2 times, most recently from 7279bc1 to c6ec760 Compare August 27, 2026 16:31
@bartoszkubicki
bartoszkubicki force-pushed the feature/support-for-sftp-files branch from c6ec760 to 360cdc6 Compare August 27, 2026 22:29
@bartoszkubicki
bartoszkubicki marked this pull request as ready for review August 27, 2026 22:29

public function getLocationConfig(): LocationConfig
{
return new LocationConfig(

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would this not be better using a factory rather than "new" ing?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah would be, followed here convention in the module, will change it


public function finish(Source $source): Result
{
return new Result([]);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would this not be better using a factory rather than "new" ing?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah would be, followed here convention in the module, will change it

Comment thread src/Config/Converter.php
Comment on lines +8 to +12
use JhImport\Import\Config\AppConfigProvider;
use JhImport\Import\Source\Csv;
use JhImport\Import\Source\Db;
use JhImport\Import\Source\SftpCsv;
use JhImport\Import\Source\Webapi;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should these be Jh\Import?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah yes, I worked on it in CDC project so I can test it and there is a conflict there as namespace is JH so had to change it locally, and then when commiting I must have forgotten to change it back

Comment on lines +7 to +9
use JhImport\Import\Archiver\Archiver;
use JhImport\Import\Config;
use JhImport\Import\Source\SftpCsv;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should these be Jh\Import?

Comment thread src/Source/SftpCsv.php

$this->localTempFile = $localTempFile;
$this->client->get($this->remoteFile, $this->localTempFile);
$this->csv = new Csv($this->localTempFile, $delimiter, $enclosure, $escape, $headerRowNum);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this use a factory rather than "new" ing?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah would be, followed here convention in the module, will change it

}

return array_values(array_filter(array_map(
static fn (string $file): string => $remotePath . '/' . $file,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd recommend using DIRECTORY_SEPARATOR rather than hardcoding "/" for better cross-OS support

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah you are right

{
$basename = basename($file);

return $basename !== '.' && $basename !== '..' && !str_contains($basename, '..');

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Edge case, but technically file names could contain ".." (my-import..csv would be valid, for example)

*/
private function assertWithinRemotePath(string $remoteFile): void
{
$remotePath = rtrim($this->locationConfig->getRemotePath(), '/') . '/';

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, would suggest DIRECTORY_SEPARATOR for better support as this is a public module

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah you are right

{
$remotePath = rtrim($this->locationConfig->getRemotePath(), '/') . '/';

if (str_contains($remoteFile, '..') || !str_starts_with($remoteFile, $remotePath)) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, files may contain ".." and be valid - the path itself shouldn't (though you can also use realpath to expand these out and then validate the end result is in an expected parent and avoid the situation entirely)

return $this->connection;
}

$sftp = new SFTP($this->locationConfig->getHost(), $this->locationConfig->getPort());

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be worth a comment that this cannot use a factory because it's not a Magento module so autogeneration won't work (well, not in later versions of Magento - some older versions allowed autogen of library classes, which broke the Klevu php-sdk later because we'd relied on that)

Just in case anyone like me comes along and goes "why is this 'new'-ed?"

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah factory wouldn't work, will add a comment

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants