diff --git a/.env.example b/.env.example index b8c9afca..fa11d7f5 100644 --- a/.env.example +++ b/.env.example @@ -92,4 +92,8 @@ PUSHER_APP_PORT= IS_ADMIN_VUEFILEMANAGER_BAR=true IS_SETUP_WIZARD_DEMO=false -IS_SETUP_WIZARD_DEBUG=false \ No newline at end of file +IS_SETUP_WIZARD_DEBUG=false + +FTP_HOST= +FTP_USERNAME= +FTP_PASSWORD= \ No newline at end of file diff --git a/README.md b/README.md index e7148126..598e5a27 100644 --- a/README.md +++ b/README.md @@ -90,6 +90,10 @@ That was the hardest part of installation process. Please follow instructions in ``` php replace_by_your_path/artisan schedule:run >> /dev/null 2>&1 ``` +6. If you have multiple php versions installed on your server, you should specify php path to the latest php version (8+). So, you should edit `php` in command above and replace it by path. For Example: +``` +/usr/bin/php8.1/php replace_by_your_path/artisan schedule:run >> /dev/null 2>&1 +``` #### If you are running VueFileManager on linux server 1. Search the absolute directory path where you uploaded VueFileManager files (like `/www/project_files`). The path must start with `/`. diff --git a/composer.json b/composer.json index 1eddb6c1..081e4277 100644 --- a/composer.json +++ b/composer.json @@ -28,6 +28,7 @@ "laravel/tinker": "^2.7", "laravel/ui": "^3.4.2", "league/flysystem-aws-s3-v3": "^3.0.9", + "league/flysystem-ftp": "^3.0", "makingcg/subscription": "^1.0.4", "pusher/pusher-php-server": "^7.0", "spatie/data-transfer-object": "^3.7.3", diff --git a/composer.lock b/composer.lock index 86be86d9..231ce91e 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "e528b8d32f34a87acd381ac8c3f3cef1", + "content-hash": "75d7553c92e60b3cb2b9aa94f8154d78", "packages": [ { "name": "amphp/amp", @@ -4193,6 +4193,70 @@ }, "time": "2022-04-01T22:05:11+00:00" }, + { + "name": "league/flysystem-ftp", + "version": "3.0.9", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/flysystem-ftp.git", + "reference": "38d829f6bbb1a5368e9bf9117273df6aaaa51938" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/flysystem-ftp/zipball/38d829f6bbb1a5368e9bf9117273df6aaaa51938", + "reference": "38d829f6bbb1a5368e9bf9117273df6aaaa51938", + "shasum": "" + }, + "require": { + "ext-ftp": "*", + "league/flysystem": "^2.0.0 || ^3.0.0", + "league/mime-type-detection": "^1.0.0", + "php": "^8.0.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "League\\Flysystem\\Ftp\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Frank de Jonge", + "email": "info@frankdejonge.nl" + } + ], + "description": "FTP filesystem adapter for Flysystem.", + "keywords": [ + "Flysystem", + "file", + "files", + "filesystem", + "ftp", + "ftpd" + ], + "support": { + "source": "https://github.com/thephpleague/flysystem-ftp/tree/3.0.9" + }, + "funding": [ + { + "url": "https://offset.earth/frankdejonge", + "type": "custom" + }, + { + "url": "https://github.com/frankdejonge", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/league/flysystem", + "type": "tidelift" + } + ], + "time": "2022-02-22T07:15:18+00:00" + }, { "name": "league/mime-type-detection", "version": "1.9.0", diff --git a/config/filesystems.php b/config/filesystems.php index 54de23e2..9d5886c7 100644 --- a/config/filesystems.php +++ b/config/filesystems.php @@ -46,5 +46,11 @@ return [ 'bucket' => env('S3_BUCKET'), 'endpoint' => env('S3_URL'), ], + 'ftp' => [ + 'driver' => 'ftp', + 'host' => env('FTP_HOST'), + 'username' => env('FTP_USERNAME'), + 'password' => env('FTP_PASSWORD'), + ], ], ]; diff --git a/public/mix-manifest.json b/public/mix-manifest.json index a82da831..c0b38774 100644 --- a/public/mix-manifest.json +++ b/public/mix-manifest.json @@ -1,75 +1,75 @@ { "/js/main.js": "/js/main.js", - "/chunks/request.js": "/chunks/request.js?id=fea6307367e6e6ca", - "/chunks/request-upload.js": "/chunks/request-upload.js?id=0f882d370ccf9383", - "/chunks/setup-wizard.js": "/chunks/setup-wizard.js?id=3c2fc454c3fce8d2", - "/chunks/status-check.js": "/chunks/status-check.js?id=33911b8a77451a0e", - "/chunks/purchase-code.js": "/chunks/purchase-code.js?id=c1df85c34d7e9521", - "/chunks/database.js": "/chunks/database.js?id=c686d46622194c7e", - "/chunks/environment.js": "/chunks/environment.js?id=fda7f74549fd6e4a", - "/chunks/app-setup.js": "/chunks/app-setup.js?id=56ac1474e0e87cb0", - "/chunks/admin-account.js": "/chunks/admin-account.js?id=666e7ee49b02b57c", - "/chunks/shared.js": "/chunks/shared.js?id=5c2821fbe760e925", - "/chunks/shared/browser.js": "/chunks/shared/browser.js?id=b01315acabcd3e60", - "/chunks/shared/single-file.js": "/chunks/shared/single-file.js?id=35f9213d84588b26", - "/chunks/shared/authenticate.js": "/chunks/shared/authenticate.js?id=ca8cc89fe5982782", - "/chunks/not-found.js": "/chunks/not-found.js?id=4cb8d3a7a2212c3c", - "/chunks/temporary-unavailable.js": "/chunks/temporary-unavailable.js?id=c71981d946a9ca71", - "/chunks/admin.js": "/chunks/admin.js?id=16f7b7d85aabefd9", - "/chunks/dashboard.js": "/chunks/dashboard.js?id=fc21740426a423aa", - "/chunks/invoices.js": "/chunks/invoices.js?id=0a624b82d1c4718d", - "/chunks/subscriptions.js": "/chunks/subscriptions.js?id=33f376a6d6902203", - "/chunks/pages.js": "/chunks/pages.js?id=23998e89c386c5ea", - "/chunks/page-edit.js": "/chunks/page-edit.js?id=ba309ccc95221294", - "/chunks/plans.js": "/chunks/plans.js?id=b86c5aa8f667ff14", - "/chunks/users.js": "/chunks/users.js?id=7d5ac62bdad89ad7", - "/chunks/user-create.js": "/chunks/user-create.js?id=a29fdec565540fa4", - "/chunks/plan-create/fixed.js": "/chunks/plan-create/fixed.js?id=b2e842f4f312aff2", - "/chunks/plan-create/metered.js": "/chunks/plan-create/metered.js?id=140d3aa05e7a450e", - "/chunks/user.js": "/chunks/user.js?id=53dc314fab72f8f2", - "/chunks/user-detail.js": "/chunks/user-detail.js?id=598392ba77bb2681", - "/chunks/user-storage.js": "/chunks/user-storage.js?id=0293215520c5e771", - "/chunks/user-subscription.js": "/chunks/user-subscription.js?id=c5274a294947d9a2", - "/chunks/user-password.js": "/chunks/user-password.js?id=3fb4538cd2283ff5", - "/chunks/user-delete.js": "/chunks/user-delete.js?id=5a4fad364a41a35c", - "/chunks/plan.js": "/chunks/plan.js?id=d8ffa85dc9b68966", - "/chunks/plan-subscribers.js": "/chunks/plan-subscribers.js?id=48733b9a221da1a2", - "/chunks/plan-settings.js": "/chunks/plan-settings.js?id=f41fe30f2273279c", - "/chunks/plan-delete.js": "/chunks/plan-delete.js?id=6432308fb4313d44", - "/chunks/payments.js": "/chunks/payments.js?id=051e8246e2b5c9d0", - "/chunks/payments/billings.js": "/chunks/payments/billings.js?id=9068ff2602b50ab4", - "/chunks/payments/settings.js": "/chunks/payments/settings.js?id=71fc3009f78d4fb8", - "/chunks/app-settings.js": "/chunks/app-settings.js?id=692d3291fb9d2cf7", - "/chunks/app-appearance.js": "/chunks/app-appearance.js?id=aef973f6a55425e8", - "/chunks/app-index.js": "/chunks/app-index.js?id=6a442cd46f8ae636", - "/chunks/app-environment.js": "/chunks/app-environment.js?id=bb4473cd45704609", - "/chunks/app-others.js": "/chunks/app-others.js?id=7407aeeb824211f6", - "/chunks/app-sign-in-out.js": "/chunks/app-sign-in-out.js?id=91065b9cee23b7b4", - "/chunks/app-adsense.js": "/chunks/app-adsense.js?id=18842ed46783ea39", - "/chunks/app-server.js": "/chunks/app-server.js?id=2813cb2498226c31", - "/chunks/app-language.js": "/chunks/app-language.js?id=2e68060389be3dc8", - "/chunks/homepage.js": "/chunks/homepage.js?id=4b9bf26e8b0a3e97", - "/chunks/dynamic-page.js": "/chunks/dynamic-page.js?id=e110e8923b6ca22f", - "/chunks/contact-us.js": "/chunks/contact-us.js?id=5ca104a75598dd39", - "/chunks/successfully-email-verified.js": "/chunks/successfully-email-verified.js?id=3153532f0d2273c8", - "/chunks/successfully-email-send.js": "/chunks/successfully-email-send.js?id=d630ed9f6f558509", - "/chunks/sign-in.js": "/chunks/sign-in.js?id=be5114e1ac636bc7", - "/chunks/sign-up.js": "/chunks/sign-up.js?id=6485e895d1352492", - "/chunks/forgotten-password.js": "/chunks/forgotten-password.js?id=9c62b8573fbdd567", - "/chunks/create-new-password.js": "/chunks/create-new-password.js?id=926b35b6745d99ba", - "/chunks/settings.js": "/chunks/settings.js?id=f9d77fef45f55249", - "/chunks/profile.js": "/chunks/profile.js?id=4f1d8cad4a4cc40c", - "/chunks/settings-password.js": "/chunks/settings-password.js?id=359880c6417b14fe", - "/chunks/settings-storage.js": "/chunks/settings-storage.js?id=68765cac4e648e90", - "/chunks/billing.js": "/chunks/billing.js?id=7a4b42efea2d1682", - "/chunks/platform.js": "/chunks/platform.js?id=259e5c427e714099", - "/chunks/files.js": "/chunks/files.js?id=3fea7a76a035e4a4", - "/chunks/recent-uploads.js": "/chunks/recent-uploads.js?id=61255bc9213dc775", - "/chunks/my-shared-items.js": "/chunks/my-shared-items.js?id=28a5f528d7fc7912", - "/chunks/trash.js": "/chunks/trash.js?id=0c96d954b4ec14d5", - "/chunks/team-folders.js": "/chunks/team-folders.js?id=24d19010a71e37d8", - "/chunks/shared-with-me.js": "/chunks/shared-with-me.js?id=d9981a4d60ddc8e0", - "/chunks/invitation.js": "/chunks/invitation.js?id=6b72d3c395a75eb1", + "/chunks/request.js": "/chunks/request.js?id=faab026c7f8e266c", + "/chunks/request-upload.js": "/chunks/request-upload.js?id=aa9e376ed29686ee", + "/chunks/setup-wizard.js": "/chunks/setup-wizard.js?id=19a0784e59d768ec", + "/chunks/status-check.js": "/chunks/status-check.js?id=f82f9939c1326fe2", + "/chunks/purchase-code.js": "/chunks/purchase-code.js?id=df5bd89528649783", + "/chunks/database.js": "/chunks/database.js?id=15cc488117dccf7b", + "/chunks/environment.js": "/chunks/environment.js?id=4764d8f6d5c22b3c", + "/chunks/app-setup.js": "/chunks/app-setup.js?id=15938ff1ad2d6ed2", + "/chunks/admin-account.js": "/chunks/admin-account.js?id=916450217130f3b8", + "/chunks/shared.js": "/chunks/shared.js?id=ec06bf0d3ada0f65", + "/chunks/shared/browser.js": "/chunks/shared/browser.js?id=11b8eb58eaf3608a", + "/chunks/shared/single-file.js": "/chunks/shared/single-file.js?id=b6445167f46a0480", + "/chunks/shared/authenticate.js": "/chunks/shared/authenticate.js?id=672e931a9fb0b672", + "/chunks/not-found.js": "/chunks/not-found.js?id=9f6ce23ce5d969f1", + "/chunks/temporary-unavailable.js": "/chunks/temporary-unavailable.js?id=f564565faa09d6d6", + "/chunks/admin.js": "/chunks/admin.js?id=3f9153ced94aa636", + "/chunks/dashboard.js": "/chunks/dashboard.js?id=28169f03aee0e3a0", + "/chunks/invoices.js": "/chunks/invoices.js?id=a4785aea6257404e", + "/chunks/subscriptions.js": "/chunks/subscriptions.js?id=51b6098a72f1fcdb", + "/chunks/pages.js": "/chunks/pages.js?id=4529e647b15e5c98", + "/chunks/page-edit.js": "/chunks/page-edit.js?id=fb3f9eda3dc1d15c", + "/chunks/plans.js": "/chunks/plans.js?id=64803e40b7a125e5", + "/chunks/users.js": "/chunks/users.js?id=8bc57edd89c4ca11", + "/chunks/user-create.js": "/chunks/user-create.js?id=8dd9d29f024132f5", + "/chunks/plan-create/fixed.js": "/chunks/plan-create/fixed.js?id=c994595021a98ce6", + "/chunks/plan-create/metered.js": "/chunks/plan-create/metered.js?id=d9f1bcb1fe44a6ae", + "/chunks/user.js": "/chunks/user.js?id=c191b906a0496fe5", + "/chunks/user-detail.js": "/chunks/user-detail.js?id=d53bfd58090b79e2", + "/chunks/user-storage.js": "/chunks/user-storage.js?id=a8e0bce4703232a0", + "/chunks/user-subscription.js": "/chunks/user-subscription.js?id=3ef8231d279d83bb", + "/chunks/user-password.js": "/chunks/user-password.js?id=23d3aee39f539a3c", + "/chunks/user-delete.js": "/chunks/user-delete.js?id=6bea6f8cadf4d74f", + "/chunks/plan.js": "/chunks/plan.js?id=4b267375ea9f19b3", + "/chunks/plan-subscribers.js": "/chunks/plan-subscribers.js?id=fea2f8eaae2f3334", + "/chunks/plan-settings.js": "/chunks/plan-settings.js?id=715ee86991d5e4db", + "/chunks/plan-delete.js": "/chunks/plan-delete.js?id=1ad77372d342326f", + "/chunks/payments.js": "/chunks/payments.js?id=dc4586691c25de6f", + "/chunks/payments/billings.js": "/chunks/payments/billings.js?id=dd6c9d6a29a47808", + "/chunks/payments/settings.js": "/chunks/payments/settings.js?id=022ba98937be861c", + "/chunks/app-settings.js": "/chunks/app-settings.js?id=55da23af2b076069", + "/chunks/app-appearance.js": "/chunks/app-appearance.js?id=a694a01f3641712c", + "/chunks/app-index.js": "/chunks/app-index.js?id=efdbfa062749ca00", + "/chunks/app-environment.js": "/chunks/app-environment.js?id=0f8a318553409406", + "/chunks/app-others.js": "/chunks/app-others.js?id=abb8d96cd7c3a576", + "/chunks/app-sign-in-out.js": "/chunks/app-sign-in-out.js?id=1cfffc99465b9a7a", + "/chunks/app-adsense.js": "/chunks/app-adsense.js?id=a5dc9e715f8561bd", + "/chunks/app-server.js": "/chunks/app-server.js?id=3a41e04bde0d3536", + "/chunks/app-language.js": "/chunks/app-language.js?id=6f8d8b8e3541ca0c", + "/chunks/homepage.js": "/chunks/homepage.js?id=832072b46053df76", + "/chunks/dynamic-page.js": "/chunks/dynamic-page.js?id=2504793131107b1f", + "/chunks/contact-us.js": "/chunks/contact-us.js?id=9adc7e145be4e160", + "/chunks/successfully-email-verified.js": "/chunks/successfully-email-verified.js?id=25b805ade5230382", + "/chunks/successfully-email-send.js": "/chunks/successfully-email-send.js?id=f4562229776d9f56", + "/chunks/sign-in.js": "/chunks/sign-in.js?id=d064f84d1c4bf908", + "/chunks/sign-up.js": "/chunks/sign-up.js?id=1b2d9edfb2723d1b", + "/chunks/forgotten-password.js": "/chunks/forgotten-password.js?id=50a1bc5e4ed86ec9", + "/chunks/create-new-password.js": "/chunks/create-new-password.js?id=f652de052dba55c1", + "/chunks/settings.js": "/chunks/settings.js?id=690a8653abdace7e", + "/chunks/profile.js": "/chunks/profile.js?id=0eca231475e267ab", + "/chunks/settings-password.js": "/chunks/settings-password.js?id=3755d41eaf50a5b1", + "/chunks/settings-storage.js": "/chunks/settings-storage.js?id=994b669a56fd417b", + "/chunks/billing.js": "/chunks/billing.js?id=a983c29d1a4f87ba", + "/chunks/platform.js": "/chunks/platform.js?id=9b86daee18ab692c", + "/chunks/files.js": "/chunks/files.js?id=b0ad99a9aedbc2d8", + "/chunks/recent-uploads.js": "/chunks/recent-uploads.js?id=70457fa45709a1ba", + "/chunks/my-shared-items.js": "/chunks/my-shared-items.js?id=6dab4621467b1be7", + "/chunks/trash.js": "/chunks/trash.js?id=d2c999817715fa28", + "/chunks/team-folders.js": "/chunks/team-folders.js?id=3ecbc23e85b78144", + "/chunks/shared-with-me.js": "/chunks/shared-with-me.js?id=93a10fd7afed9534", + "/chunks/invitation.js": "/chunks/invitation.js?id=d5c845919b343941", "/css/tailwind.css": "/css/tailwind.css", "/css/app.css": "/css/app.css" } diff --git a/src/App/Users/Models/UserSetting.php b/src/App/Users/Models/UserSetting.php index 6a032ff3..2ee34767 100644 --- a/src/App/Users/Models/UserSetting.php +++ b/src/App/Users/Models/UserSetting.php @@ -42,7 +42,7 @@ class UserSetting extends Model $link = []; // Get avatar from external storage - if ($this->attributes['avatar'] && ! isStorageDriver('local')) { + if ($this->attributes['avatar'] && isStorageDriver('s3')) { foreach (config('vuefilemanager.avatar_sizes') as $item) { $filePath = "avatars/{$item['name']}-{$this->attributes['avatar']}"; diff --git a/src/Domain/Files/Actions/MoveFileToFTPStorageAction.php b/src/Domain/Files/Actions/MoveFileToFTPStorageAction.php new file mode 100644 index 00000000..f7eea3b5 --- /dev/null +++ b/src/Domain/Files/Actions/MoveFileToFTPStorageAction.php @@ -0,0 +1,22 @@ +delete("files/$userId/$file"); + } +} diff --git a/src/Domain/Files/Actions/UploadFileAction.php b/src/Domain/Files/Actions/UploadFileAction.php index f913a71c..ffc6f07e 100644 --- a/src/Domain/Files/Actions/UploadFileAction.php +++ b/src/Domain/Files/Actions/UploadFileAction.php @@ -15,10 +15,11 @@ class UploadFileAction { public function __construct( public RecordUploadAction $recordUpload, - public ProcessImageThumbnailAction $createImageThumbnail, public GetFileParentId $getFileParentId, - public MoveFileToExternalStorageAction $moveFileToExternalStorage, public StoreFileExifMetadataAction $storeExifMetadata, + public MoveFileToFTPStorageAction $moveFileToFTPStorage, + public ProcessImageThumbnailAction $createImageThumbnail, + public MoveFileToExternalStorageAction $moveFileToExternalStorage, ) { } @@ -82,9 +83,10 @@ class UploadFileAction ($this->createImageThumbnail)($fileName, $file, $user->id); // Move files to external storage - if (! isStorageDriver('local')) { - ($this->moveFileToExternalStorage)($fileName, $user->id); - } + match (config('filesystems.default')) { + 's3' => ($this->moveFileToExternalStorage)($fileName, $user->id), + 'ftp' => ($this->moveFileToFTPStorage)($fileName, $user->id), + }; // Create new file $item = UserFile::create([ diff --git a/src/Domain/Files/Models/File.php b/src/Domain/Files/Models/File.php index 7a5167bf..02244c9b 100644 --- a/src/Domain/Files/Models/File.php +++ b/src/Domain/Files/Models/File.php @@ -101,7 +101,7 @@ class File extends Model ->all(); // Generate thumbnail link for external storage service - if ($this->type === 'image' && ! isStorageDriver('local')) { + if ($this->type === 'image' && isStorageDriver('s3')) { foreach ($thumbnail_sizes as $item) { $filePath = "files/{$this->user_id}/{$item['name']}-{$this->basename}"; diff --git a/src/Domain/Zip/Actions/ZipAction.php b/src/Domain/Zip/Actions/ZipAction.php index 900bbec2..007049f8 100644 --- a/src/Domain/Zip/Actions/ZipAction.php +++ b/src/Domain/Zip/Actions/ZipAction.php @@ -48,6 +48,11 @@ class ZipAction $zip->add("s3://$bucketName/$filePath", $file->name); } + + // ftp client + if (isStorageDriver('ftp')) { + $zip->addRaw(Storage::get($filePath), $file->name); + } } }); @@ -79,12 +84,15 @@ class ZipAction $zip->add(Storage::path($filePath), $zipDestination); } - // s3 client if (isStorageDriver('s3')) { $bucketName = config('filesystems.disks.s3.bucket'); $zip->add("s3://$bucketName/$filePath", $zipDestination); } + + if (isStorageDriver('ftp')) { + $zip->addRaw(Storage::get($filePath), $zipDestination); + } } } }); diff --git a/src/Support/helpers.php b/src/Support/helpers.php index 50abb8d2..09b9ce6e 100644 --- a/src/Support/helpers.php +++ b/src/Support/helpers.php @@ -272,10 +272,8 @@ if (! function_exists('get_storage')) { if (! function_exists('isStorageDriver')) { /** * Check if is running AWS s3 as storage - * - * @return bool */ - function isStorageDriver($driver) + function isStorageDriver(string|array $driver): bool { if (is_array($driver)) { return in_array(config('filesystems.default'), $driver);