From dcacc11b46d97b28341dbe989fa385a6a8d1633d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henry=20Bergstr=C3=B6m?= Date: Wed, 15 Jan 2025 18:11:47 +0100 Subject: [PATCH] Release 0.5.10: PRs #95, #96, #97, #98, #100 (#101) --- .github/workflows/lint.yml | 41 + .gitignore | 2 +- .php-cs-fixer.dist.php | 21 +- README.md | 44 +- appinfo/info.xml | 8 +- appinfo/routes.php | 3 - composer.json | 10 +- composer.lock | 2135 +---------------- docker-compose.yml | 3 +- lib/AppInfo/AppConstants.php | 6 +- lib/AppInfo/Application.php | 30 +- lib/Auth/License.php | 20 +- lib/Backend/BeeSwarm.php | 49 +- lib/Controller/BeeController.php | 60 +- lib/Controller/SettingsController.php | 25 +- lib/Db/SwarmFile.php | 63 +- lib/Db/SwarmFileMapper.php | 116 +- lib/Exception/SwarmException.php | 11 + lib/Migration/Version0001Date202204071430.php | 18 +- lib/Migration/Version0002Date202409251430.php | 19 +- lib/Migration/Version0003Date202401101430.php | 44 +- lib/Migration/Version0004Date202410131430.php | 49 +- lib/Migration/Version0005Date202411081430.php | 40 +- lib/Notification/Notifier.php | 63 +- lib/Sabre/PostPlugin.php | 52 +- lib/Sabre/PropfindPlugin.php | 59 +- lib/Service/EthswarmService.php | 19 +- lib/Service/NotificationService.php | 44 +- lib/Storage/BeeSwarm.php | 598 ++--- lib/Storage/BeeSwarmTrait.php | 237 +- lib/Utils/Curl.php | 134 +- lib/Utils/Env.php | 17 + templates/admin-settings.php | 51 +- templates/vue-admin-settings.php | 5 +- 34 files changed, 1085 insertions(+), 3011 deletions(-) create mode 100644 .github/workflows/lint.yml create mode 100644 lib/Exception/SwarmException.php create mode 100644 lib/Utils/Env.php diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000..12cf4e9 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,41 @@ +name: Lint + +on: + pull_request: + branches: + - stage + types: + - opened + - synchronize + - reopened + +jobs: + php-cs-fixer: + runs-on: ubuntu-latest + + strategy: + fail-fast: true + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: "8.3" + tools: composer + + - name: Install php-cs-fixer + run: composer require --dev friendsofphp/php-cs-fixer + + - name: Run php-cs-fixer + run: vendor/bin/php-cs-fixer fix + + - name: Commit changes + uses: stefanzweifel/git-auto-commit-action@v5 + with: + commit_message: "chore: fix code style" + commit_options: "--no-verify" + commit_user_name: "GitHub Actions" + commit_user_email: "github-actions[bot]@users.noreply.github.com" diff --git a/.gitignore b/.gitignore index 29cf1b7..2372cdf 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,7 @@ /build /dev-environment js/nextcloud-swarm-plugin*.* -/.php_cs.cache +/.php-cs-fixer.cache # Package Manages /node_modules diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php index f7bbdd8..acc4889 100644 --- a/.php-cs-fixer.dist.php +++ b/.php-cs-fixer.dist.php @@ -4,12 +4,31 @@ require_once './vendor/autoload.php'; -use Nextcloud\CodingStandard\Config; +use Nextcloud\CodingStandard\Config as Base; +use PhpCsFixer\Runner\Parallel\ParallelConfig; + +class Config extends Base { + public function getRules(array $rules = []): array + { + return [ + ...parent::getRules(), // Nextcloud Standard Rules + '@PSR12' => true, + '@PhpCsFixer' => true, + 'global_namespace_import' => [ + 'import_classes' => true, + ], + 'trailing_comma_in_multiline' => ['elements' => ['arguments', 'arrays', 'match', 'parameters']], + ]; + } +} $config = new Config(); $config + ->setParallelConfig(new ParallelConfig(8)) + ->setRiskyAllowed(true) ->getFinder() ->ignoreVCSIgnored(true) + ->notPath('dev-environment') ->notPath('build') ->notPath('l10n') ->notPath('src') diff --git a/README.md b/README.md index b21be71..a9442ff 100755 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # **Hejbit - Nextcloud Swarm Plugin** -*Bring decentralized, sovereign cloud storage to Nextcloud with the Hejbit Swarm plugin!* +_Bring decentralized, sovereign cloud storage to Nextcloud with the Hejbit Swarm plugin!_ This plugin integrates [Swarm](https://www.ethswarm.org/) (a decentralized, blockchain-connected file storage system) directly into your [Nextcloud ](https://nextcloud.com/)instance. @@ -8,21 +8,21 @@ This plugin integrates [Swarm](https://www.ethswarm.org/) (a decentralized, bloc ## Table of Contents -- [Dependencies](#dependencies) -- [Setup and Installation](#setup-and-installation) -- [Usage](#usage) - - [Settings](#settings) - - [Usage](#usage) -- [Get Hejbit License](#get-hejbit-license) -- [License](#license) +- [Dependencies](#dependencies) +- [Setup and Installation](#setup-and-installation) +- [Usage](#usage) + - [Settings](#settings) + - [Usage](#usage) +- [Get Hejbit License](#get-hejbit-license) +- [License](#license) ## Dependencies Before using the plugin, ensure you have the following: -- An active Nextcloud instance (version 27,28 or 29) -- A valid license and URL to activate the service - - [Request Your Free Nextcloud Swarm Plugin Trial License](https://metaprovide.org/hejbit/start) +- An active Nextcloud instance (version 27,28 or 29) +- A valid license and URL to activate the service + - [Request Your Free Nextcloud Swarm Plugin Trial License](https://metaprovide.org/hejbit/start) ## Setup and Installation @@ -37,9 +37,9 @@ Follow these steps to configure Hejbit Swarm in Nextcloud: Once installed, Hejbit Swarm integrates directly with Nextcloud’s "Files" section, allowing seamless file operations: -- **Upload:** Transfer files to decentralized storage. -- **Download:** Retrieve and view files from decentralized storage. -- **Copy/Move:** Shift files between any external storage and decentralized storage +- **Upload:** Transfer files to decentralized storage. +- **Download:** Retrieve and view files from decentralized storage. +- **Copy/Move:** Shift files between any external storage and decentralized storage ![View, download, and file view actions in Nextcloud](https://github.com/user-attachments/assets/3bee08e4-7a9e-4b44-a904-821359cc3e7b) @@ -53,23 +53,29 @@ Users with administrative credentials can configure the plugin through the stand Once setup and configured, the Decentralized Storage is ready to use. -- Access the Decentralized Storage folder under "All Files" or via the "Files" menu under "External Storage." -- Upload files as you would in Nextcloud. +- Access the Decentralized Storage folder under "All Files" or via the "Files" menu under "External Storage." +- Upload files as you would in Nextcloud. ![Upload file to swarm in Nextcloud](https://github.com/user-attachments/assets/aadd664e-26ca-470a-a27b-af8d94351e52) -- Once uploaded, it can be viewed internally or downloaded. It can also be copied to another storage. +- Once uploaded, it can be viewed internally or downloaded. It can also be copied to another storage. ![View, download, and file view actions in Nextcloud](https://github.com/user-attachments/assets/596b72ed-d97f-48ba-bcb9-0ee5ff581a3c) -- Files from another Nextcloud storage can also be copied/moved to the decentralized storage.. Choose the decentralized storage folder as the target Folder +- Files from another Nextcloud storage can also be copied/moved to the decentralized storage.. Choose the decentralized storage folder as the target Folder ![Copying or moving files to decentralized storage folder](https://github.com/user-attachments/assets/ceed3585-f7e6-4f16-b371-d61402e9f1e9) -- Right-click on a Swarm file to copy the Swarm reference (hash) to your clipboard. Alternatively, click the three dots in the Actions menu and select 'Copy Swarm Reference.' The Swarm reference is the unique address of the file on the Swarm network. +- Right-click on a Swarm file to copy the Swarm reference (hash) to your clipboard. Alternatively, click the three dots in the Actions menu and select 'Copy Swarm Reference.' The Swarm reference is the unique address of the file on the Swarm network. ![Copy swarm reference to clipboard](https://github.com/user-attachments/assets/cc73282b-e32e-411f-a94b-a2ac3313f60b) +### Additional Integration with Moodle + +You can also enhance your experience by integrating the Hejbit Swarm plugin with the **Moodle Nextcloud plugin**. This integration allows users to access decentralized storage directly within the Moodle environment, providing a seamless experience for educational content management. For more information on how to set up this integration, visit the [Moodle Nextcloud repository documentation](https://docs.moodle.org/405/en/Nextcloud_repository). + +For detailed guidance on using the integrated features, please refer to the [Metaprovide Learning Platform](https://learning.metaprovide.org/login/index.php). + ### Get Hejbit License Experience the future of data storage with 5GB of free, decentralized storage on the Ethereum Swarm network. Our plugin seamlessly integrates with your existing Nextcloud interface, providing true data sovereignty without the complexity. diff --git a/appinfo/info.xml b/appinfo/info.xml index bafea17..e25b8a1 100644 --- a/appinfo/info.xml +++ b/appinfo/info.xml @@ -57,13 +57,19 @@ Once setup and configured, the Decentralized Storage is ready to use. - Files from another Nextcloud storage can also be copied/moved to the decentralized storage. Choose the decentralized storage folder as the target Folder. - Right-click on a Swarm file to copy the Swarm reference (hash) to your clipboard. Alternatively, click the three dots in the Actions menu and select 'Copy Swarm Reference.' The Swarm reference is the unique address of the file on the Swarm network. +### Additional Integration with Moodle + +You can also enhance your experience by integrating the Hejbit Swarm plugin with the **Moodle Nextcloud plugin**. This integration allows users to access decentralized storage directly within the Moodle environment, providing a seamless experience for educational content management. For more information on how to set up this integration, visit the [Moodle Nextcloud repository documentation](https://docs.moodle.org/405/en/Nextcloud_repository). + +For detailed guidance on using the integrated features, please refer to the [Metaprovide Learning Platform](https://learning.metaprovide.org/login/index.php). + ### **Hejbit Licence** Experience the future of data storage with 5GB of free, decentralized storage on the Ethereum Swarm network. Our plugin seamlessly integrates with your existing Nextcloud interface, providing true data sovereignty without the complexity. [Get your free licence here!](https://metaprovide.org/hejbit/start) . ]]> - 0.5.9 + 0.5.10 agpl MetaProvide Files_External_Ethswarm diff --git a/appinfo/routes.php b/appinfo/routes.php index bc08da5..1843905 100755 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -4,9 +4,7 @@ /** * @copyright Copyright (c) 2022, MetaProvide Holding EKF - * * @author Ron Trevor - * * @license GNU AGPL version 3 or any later version * * This program is free software: you can redistribute it and/or modify @@ -21,7 +19,6 @@ * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . - * */ return ['routes' => [ [ diff --git a/composer.json b/composer.json index 47030eb..f047e90 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,7 @@ { "autoload-dev": { "psr-4": { + "OC\\": "dev-environment/nextcloud_source/lib/", "OCP\\": "dev-environment/nextcloud_source/lib/public/", "OCA\\Files_External\\": "dev-environment/nextcloud_source/apps/files_external/lib/", "OCA\\Files_External_Ethswarm\\": "lib/" @@ -10,7 +11,12 @@ "ext-curl": "*" }, "require-dev": { - "nextcloud/coding-standard": "^0.5.0", - "christophwurst/nextcloud": "^22" + "nextcloud/coding-standard": "^1.3.2", + "ext-fileinfo": "*", + "friendsofphp/php-cs-fixer": "*" + }, + "scripts": { + "cs:check": "./vendor/php-cs-fixer/shim/php-cs-fixer.phar fix --dry-run --diff", + "cs:fix": "./vendor/php-cs-fixer/shim/php-cs-fixer.phar fix" } } diff --git a/composer.lock b/composer.lock index e9b6cd9..7ec96b0 100644 --- a/composer.lock +++ b/composer.lock @@ -4,145 +4,36 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "eb0300c3b09e41a72f2b682cc5c6eab9", + "content-hash": "9a0365504a1790b1f04538b1f0ddd13d", "packages": [], "packages-dev": [ { - "name": "christophwurst/nextcloud", - "version": "v22.1.1", + "name": "kubawerlos/php-cs-fixer-custom-fixers", + "version": "v3.22.0", "source": { "type": "git", - "url": "https://github.com/ChristophWurst/nextcloud_composer.git", - "reference": "8bb086cd016128b5ef8353662fd1852db3248d1e" + "url": "https://github.com/kubawerlos/php-cs-fixer-custom-fixers.git", + "reference": "8701394f0c7cd450ac4fa577d24589122c1d5d5e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ChristophWurst/nextcloud_composer/zipball/8bb086cd016128b5ef8353662fd1852db3248d1e", - "reference": "8bb086cd016128b5ef8353662fd1852db3248d1e", + "url": "https://api.github.com/repos/kubawerlos/php-cs-fixer-custom-fixers/zipball/8701394f0c7cd450ac4fa577d24589122c1d5d5e", + "reference": "8701394f0c7cd450ac4fa577d24589122c1d5d5e", "shasum": "" }, "require": { - "php": "^7.3 || ~8.0.0", - "psr/container": "^1.0", - "psr/event-dispatcher": "^1.0", - "psr/log": "^1.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "23.0.0-dev" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "AGPL-3.0-or-later" - ], - "authors": [ - { - "name": "Christoph Wurst", - "email": "christoph@winzerhof-wurst.at" - } - ], - "description": "Composer package containing Nextcloud's public API (classes, interfaces)", - "time": "2021-11-11T14:01:42+00:00" - }, - { - "name": "composer/pcre", - "version": "1.0.1", - "source": { - "type": "git", - "url": "https://github.com/composer/pcre.git", - "reference": "67a32d7d6f9f560b726ab25a061b38ff3a80c560" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/pcre/zipball/67a32d7d6f9f560b726ab25a061b38ff3a80c560", - "reference": "67a32d7d6f9f560b726ab25a061b38ff3a80c560", - "shasum": "" - }, - "require": { - "php": "^5.3.2 || ^7.0 || ^8.0" - }, - "require-dev": { - "phpstan/phpstan": "^1.3", - "phpstan/phpstan-strict-rules": "^1.1", - "symfony/phpunit-bridge": "^4.2 || ^5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Composer\\Pcre\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" - } - ], - "description": "PCRE wrapping library that offers type-safe preg_* replacements.", - "keywords": [ - "PCRE", - "preg", - "regex", - "regular expression" - ], - "funding": [ - { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" - } - ], - "time": "2022-01-21T20:24:37+00:00" - }, - { - "name": "composer/semver", - "version": "3.3.1", - "source": { - "type": "git", - "url": "https://github.com/composer/semver.git", - "reference": "5d8e574bb0e69188786b8ef77d43341222a41a71" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/semver/zipball/5d8e574bb0e69188786b8ef77d43341222a41a71", - "reference": "5d8e574bb0e69188786b8ef77d43341222a41a71", - "shasum": "" - }, - "require": { - "php": "^5.3.2 || ^7.0 || ^8.0" + "ext-filter": "*", + "ext-tokenizer": "*", + "friendsofphp/php-cs-fixer": "^3.61.1", + "php": "^7.4 || ^8.0" }, "require-dev": { - "phpstan/phpstan": "^1.4", - "symfony/phpunit-bridge": "^4.2 || ^5" + "phpunit/phpunit": "^9.6.4 || ^10.5.29" }, "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.x-dev" - } - }, "autoload": { "psr-4": { - "Composer\\Semver\\": "src" + "PhpCsFixerCustomFixers\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -151,136 +42,40 @@ ], "authors": [ { - "name": "Nils Adermann", - "email": "naderman@naderman.de", - "homepage": "http://www.naderman.de" - }, - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" - }, - { - "name": "Rob Bast", - "email": "rob.bast@gmail.com", - "homepage": "http://robbast.nl" - } - ], - "description": "Semver library that offers utilities, version constraint parsing and validation.", - "keywords": [ - "semantic", - "semver", - "validation", - "versioning" - ], - "funding": [ - { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" + "name": "Kuba Werłos", + "email": "werlos@gmail.com" } ], - "time": "2022-03-16T11:22:07+00:00" - }, - { - "name": "composer/xdebug-handler", - "version": "2.0.5", - "source": { - "type": "git", - "url": "https://github.com/composer/xdebug-handler.git", - "reference": "9e36aeed4616366d2b690bdce11f71e9178c579a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/9e36aeed4616366d2b690bdce11f71e9178c579a", - "reference": "9e36aeed4616366d2b690bdce11f71e9178c579a", - "shasum": "" - }, - "require": { - "composer/pcre": "^1", - "php": "^5.3.2 || ^7.0 || ^8.0", - "psr/log": "^1 || ^2 || ^3" - }, - "require-dev": { - "phpstan/phpstan": "^1.0", - "phpstan/phpstan-strict-rules": "^1.1", - "symfony/phpunit-bridge": "^4.2 || ^5.0 || ^6.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Composer\\XdebugHandler\\": "src" - } + "description": "A set of custom fixers for PHP CS Fixer", + "support": { + "issues": "https://github.com/kubawerlos/php-cs-fixer-custom-fixers/issues", + "source": "https://github.com/kubawerlos/php-cs-fixer-custom-fixers/tree/v3.22.0" }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "John Stevenson", - "email": "john-stevenson@blueyonder.co.uk" - } - ], - "description": "Restarts a process without Xdebug.", - "keywords": [ - "Xdebug", - "performance" - ], - "funding": [ - { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" - } - ], - "time": "2022-02-24T20:20:32+00:00" + "time": "2024-08-16T20:44:35+00:00" }, { - "name": "doctrine/annotations", - "version": "1.13.2", + "name": "nextcloud/coding-standard", + "version": "v1.3.2", "source": { "type": "git", - "url": "https://github.com/doctrine/annotations.git", - "reference": "5b668aef16090008790395c02c893b1ba13f7e08" + "url": "https://github.com/nextcloud/coding-standard.git", + "reference": "9c719c4747fa26efc12f2e8b21c14a9a75c6ba6d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/annotations/zipball/5b668aef16090008790395c02c893b1ba13f7e08", - "reference": "5b668aef16090008790395c02c893b1ba13f7e08", + "url": "https://api.github.com/repos/nextcloud/coding-standard/zipball/9c719c4747fa26efc12f2e8b21c14a9a75c6ba6d", + "reference": "9c719c4747fa26efc12f2e8b21c14a9a75c6ba6d", "shasum": "" }, "require": { - "doctrine/lexer": "1.*", - "ext-tokenizer": "*", - "php": "^7.1 || ^8.0", - "psr/cache": "^1 || ^2 || ^3" - }, - "require-dev": { - "doctrine/cache": "^1.11 || ^2.0", - "doctrine/coding-standard": "^6.0 || ^8.1", - "phpstan/phpstan": "^0.12.20", - "phpunit/phpunit": "^7.5 || ^8.0 || ^9.1.5", - "symfony/cache": "^4.4 || ^5.2" + "kubawerlos/php-cs-fixer-custom-fixers": "^3.22", + "php": "^7.3|^8.0", + "php-cs-fixer/shim": "^3.17" }, "type": "library", "autoload": { "psr-4": { - "Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations" + "Nextcloud\\CodingStandard\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -289,189 +84,48 @@ ], "authors": [ { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" + "name": "Christoph Wurst", + "email": "christoph@winzerhof-wurst.at" } ], - "description": "Docblock Annotations Parser", - "homepage": "https://www.doctrine-project.org/projects/annotations.html", - "keywords": [ - "annotations", - "docblock", - "parser" - ], - "time": "2021-08-05T19:00:23+00:00" - }, - { - "name": "doctrine/lexer", - "version": "1.2.3", - "source": { - "type": "git", - "url": "https://github.com/doctrine/lexer.git", - "reference": "c268e882d4dbdd85e36e4ad69e02dc284f89d229" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/lexer/zipball/c268e882d4dbdd85e36e4ad69e02dc284f89d229", - "reference": "c268e882d4dbdd85e36e4ad69e02dc284f89d229", - "shasum": "" - }, - "require": { - "php": "^7.1 || ^8.0" - }, - "require-dev": { - "doctrine/coding-standard": "^9.0", - "phpstan/phpstan": "^1.3", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "vimeo/psalm": "^4.11" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Common\\Lexer\\": "lib/Doctrine/Common/Lexer" - } + "description": "Nextcloud coding standards for the php cs fixer", + "support": { + "issues": "https://github.com/nextcloud/coding-standard/issues", + "source": "https://github.com/nextcloud/coding-standard/tree/v1.3.2" }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.", - "homepage": "https://www.doctrine-project.org/projects/lexer.html", - "keywords": [ - "annotations", - "docblock", - "lexer", - "parser", - "php" - ], - "funding": [ - { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Flexer", - "type": "tidelift" - } - ], - "time": "2022-02-28T11:07:21+00:00" + "time": "2024-10-14T16:49:05+00:00" }, { - "name": "friendsofphp/php-cs-fixer", - "version": "v2.19.3", + "name": "php-cs-fixer/shim", + "version": "v3.65.0", "source": { "type": "git", - "url": "https://github.com/FriendsOfPHP/PHP-CS-Fixer.git", - "reference": "75ac86f33fab4714ea5a39a396784d83ae3b5ed8" + "url": "https://github.com/PHP-CS-Fixer/shim.git", + "reference": "4983ec79b9dee926695ac324ea6e8d291935525d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/75ac86f33fab4714ea5a39a396784d83ae3b5ed8", - "reference": "75ac86f33fab4714ea5a39a396784d83ae3b5ed8", + "url": "https://api.github.com/repos/PHP-CS-Fixer/shim/zipball/4983ec79b9dee926695ac324ea6e8d291935525d", + "reference": "4983ec79b9dee926695ac324ea6e8d291935525d", "shasum": "" }, "require": { - "composer/semver": "^1.4 || ^2.0 || ^3.0", - "composer/xdebug-handler": "^1.2 || ^2.0", - "doctrine/annotations": "^1.2", "ext-json": "*", "ext-tokenizer": "*", - "php": "^5.6 || ^7.0 || ^8.0", - "php-cs-fixer/diff": "^1.3", - "symfony/console": "^3.4.43 || ^4.1.6 || ^5.0", - "symfony/event-dispatcher": "^3.0 || ^4.0 || ^5.0", - "symfony/filesystem": "^3.0 || ^4.0 || ^5.0", - "symfony/finder": "^3.0 || ^4.0 || ^5.0", - "symfony/options-resolver": "^3.0 || ^4.0 || ^5.0", - "symfony/polyfill-php70": "^1.0", - "symfony/polyfill-php72": "^1.4", - "symfony/process": "^3.0 || ^4.0 || ^5.0", - "symfony/stopwatch": "^3.0 || ^4.0 || ^5.0" + "php": "^7.4 || ^8.0" }, - "require-dev": { - "justinrainbow/json-schema": "^5.0", - "keradus/cli-executor": "^1.4", - "mikey179/vfsstream": "^1.6", - "php-coveralls/php-coveralls": "^2.4.2", - "php-cs-fixer/accessible-object": "^1.0", - "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.2", - "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.2.1", - "phpspec/prophecy-phpunit": "^1.1 || ^2.0", - "phpunit/phpunit": "^5.7.27 || ^6.5.14 || ^7.5.20 || ^8.5.13 || ^9.5", - "phpunitgoodpractices/polyfill": "^1.5", - "phpunitgoodpractices/traits": "^1.9.1", - "sanmai/phpunit-legacy-adapter": "^6.4 || ^8.2.1", - "symfony/phpunit-bridge": "^5.2.1", - "symfony/yaml": "^3.0 || ^4.0 || ^5.0" + "replace": { + "friendsofphp/php-cs-fixer": "self.version" }, "suggest": { "ext-dom": "For handling output formats in XML", - "ext-mbstring": "For handling non-UTF8 characters.", - "php-cs-fixer/phpunit-constraint-isidenticalstring": "For IsIdenticalString constraint.", - "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "For XmlMatchesXsd constraint.", - "symfony/polyfill-mbstring": "When enabling `ext-mbstring` is not possible." + "ext-mbstring": "For handling non-UTF8 characters." }, "bin": [ - "php-cs-fixer" + "php-cs-fixer", + "php-cs-fixer.phar" ], "type": "application", - "extra": { - "branch-alias": { - "dev-master": "2.19-dev" - } - }, - "autoload": { - "psr-4": { - "PhpCsFixer\\": "src/" - }, - "classmap": [ - "tests/Test/AbstractFixerTestCase.php", - "tests/Test/AbstractIntegrationCaseFactory.php", - "tests/Test/AbstractIntegrationTestCase.php", - "tests/Test/Assert/AssertTokensTrait.php", - "tests/Test/IntegrationCase.php", - "tests/Test/IntegrationCaseFactory.php", - "tests/Test/IntegrationCaseFactoryInterface.php", - "tests/Test/InternalIntegrationCaseFactory.php", - "tests/Test/IsIdenticalConstraint.php", - "tests/Test/TokensWithObservedTransformers.php", - "tests/TestCase.php" - ] - }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" @@ -487,1690 +141,23 @@ } ], "description": "A tool to automatically fix PHP code style", - "funding": [ - { - "url": "https://github.com/keradus", - "type": "github" - } - ], - "time": "2021-11-15T17:17:55+00:00" - }, - { - "name": "nextcloud/coding-standard", - "version": "v0.5.0", - "source": { - "type": "git", - "url": "https://github.com/nextcloud/coding-standard.git", - "reference": "742ed895ae76c10daf95e08488cfb3f554199f40" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nextcloud/coding-standard/zipball/742ed895ae76c10daf95e08488cfb3f554199f40", - "reference": "742ed895ae76c10daf95e08488cfb3f554199f40", - "shasum": "" - }, - "require": { - "friendsofphp/php-cs-fixer": "^2.17", - "php": "^7.2|^8.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Nextcloud\\CodingStandard\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Christoph Wurst", - "email": "christoph@winzerhof-wurst.at" - } - ], - "description": "Nextcloud coding standards for the php cs fixer", - "time": "2021-01-11T14:15:58+00:00" - }, - { - "name": "php-cs-fixer/diff", - "version": "v1.3.1", - "source": { - "type": "git", - "url": "https://github.com/PHP-CS-Fixer/diff.git", - "reference": "dbd31aeb251639ac0b9e7e29405c1441907f5759" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/PHP-CS-Fixer/diff/zipball/dbd31aeb251639ac0b9e7e29405c1441907f5759", - "reference": "dbd31aeb251639ac0b9e7e29405c1441907f5759", - "shasum": "" - }, - "require": { - "php": "^5.6 || ^7.0 || ^8.0" - }, - "require-dev": { - "phpunit/phpunit": "^5.7.23 || ^6.4.3 || ^7.0", - "symfony/process": "^3.3" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Kore Nordmann", - "email": "mail@kore-nordmann.de" - }, - { - "name": "SpacePossum" - } - ], - "description": "sebastian/diff v2 backport support for PHP5.6", - "homepage": "https://github.com/PHP-CS-Fixer", - "keywords": [ - "diff" - ], - "time": "2020-10-14T08:39:05+00:00" - }, - { - "name": "psr/cache", - "version": "1.0.1", - "source": { - "type": "git", - "url": "https://github.com/php-fig/cache.git", - "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/cache/zipball/d11b50ad223250cf17b86e38383413f5a6764bf8", - "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" + "support": { + "issues": "https://github.com/PHP-CS-Fixer/shim/issues", + "source": "https://github.com/PHP-CS-Fixer/shim/tree/v3.65.0" }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Cache\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "description": "Common interface for caching libraries", - "keywords": [ - "cache", - "psr", - "psr-6" - ], - "time": "2016-08-06T20:24:11+00:00" - }, - { - "name": "psr/container", - "version": "1.1.2", - "source": { - "type": "git", - "url": "https://github.com/php-fig/container.git", - "reference": "513e0666f7216c7459170d56df27dfcefe1689ea" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/513e0666f7216c7459170d56df27dfcefe1689ea", - "reference": "513e0666f7216c7459170d56df27dfcefe1689ea", - "shasum": "" - }, - "require": { - "php": ">=7.4.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Psr\\Container\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common Container Interface (PHP FIG PSR-11)", - "homepage": "https://github.com/php-fig/container", - "keywords": [ - "PSR-11", - "container", - "container-interface", - "container-interop", - "psr" - ], - "time": "2021-11-05T16:50:12+00:00" - }, - { - "name": "psr/event-dispatcher", - "version": "1.0.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/event-dispatcher.git", - "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0", - "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0", - "shasum": "" - }, - "require": { - "php": ">=7.2.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\EventDispatcher\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "description": "Standard interfaces for event handling.", - "keywords": [ - "events", - "psr", - "psr-14" - ], - "time": "2019-01-08T18:20:26+00:00" - }, - { - "name": "psr/log", - "version": "1.1.4", - "source": { - "type": "git", - "url": "https://github.com/php-fig/log.git", - "reference": "d49695b909c3b7628b6289db5479a1c204601f11" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11", - "reference": "d49695b909c3b7628b6289db5479a1c204601f11", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Log\\": "Psr/Log/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common interface for logging libraries", - "homepage": "https://github.com/php-fig/log", - "keywords": [ - "log", - "psr", - "psr-3" - ], - "time": "2021-05-03T11:20:27+00:00" - }, - { - "name": "symfony/console", - "version": "v5.4.5", - "source": { - "type": "git", - "url": "https://github.com/symfony/console.git", - "reference": "d8111acc99876953f52fe16d4c50eb60940d49ad" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/d8111acc99876953f52fe16d4c50eb60940d49ad", - "reference": "d8111acc99876953f52fe16d4c50eb60940d49ad", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php73": "^1.9", - "symfony/polyfill-php80": "^1.16", - "symfony/service-contracts": "^1.1|^2|^3", - "symfony/string": "^5.1|^6.0" - }, - "conflict": { - "psr/log": ">=3", - "symfony/dependency-injection": "<4.4", - "symfony/dotenv": "<5.1", - "symfony/event-dispatcher": "<4.4", - "symfony/lock": "<4.4", - "symfony/process": "<4.4" - }, - "provide": { - "psr/log-implementation": "1.0|2.0" - }, - "require-dev": { - "psr/log": "^1|^2", - "symfony/config": "^4.4|^5.0|^6.0", - "symfony/dependency-injection": "^4.4|^5.0|^6.0", - "symfony/event-dispatcher": "^4.4|^5.0|^6.0", - "symfony/lock": "^4.4|^5.0|^6.0", - "symfony/process": "^4.4|^5.0|^6.0", - "symfony/var-dumper": "^4.4|^5.0|^6.0" - }, - "suggest": { - "psr/log": "For using the console logger", - "symfony/event-dispatcher": "", - "symfony/lock": "", - "symfony/process": "" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Console\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Eases the creation of beautiful and testable command line interfaces", - "homepage": "https://symfony.com", - "keywords": [ - "cli", - "command line", - "console", - "terminal" - ], - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-02-24T12:45:35+00:00" - }, - { - "name": "symfony/deprecation-contracts", - "version": "v2.5.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "6f981ee24cf69ee7ce9736146d1c57c2780598a8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/6f981ee24cf69ee7ce9736146d1c57c2780598a8", - "reference": "6f981ee24cf69ee7ce9736146d1c57c2780598a8", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "2.5-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } - }, - "autoload": { - "files": [ - "function.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "A generic function and convention to trigger deprecation notices", - "homepage": "https://symfony.com", - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2021-07-12T14:48:14+00:00" - }, - { - "name": "symfony/event-dispatcher", - "version": "v5.4.3", - "source": { - "type": "git", - "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "dec8a9f58d20df252b9cd89f1c6c1530f747685d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/dec8a9f58d20df252b9cd89f1c6c1530f747685d", - "reference": "dec8a9f58d20df252b9cd89f1c6c1530f747685d", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/event-dispatcher-contracts": "^2|^3", - "symfony/polyfill-php80": "^1.16" - }, - "conflict": { - "symfony/dependency-injection": "<4.4" - }, - "provide": { - "psr/event-dispatcher-implementation": "1.0", - "symfony/event-dispatcher-implementation": "2.0" - }, - "require-dev": { - "psr/log": "^1|^2|^3", - "symfony/config": "^4.4|^5.0|^6.0", - "symfony/dependency-injection": "^4.4|^5.0|^6.0", - "symfony/error-handler": "^4.4|^5.0|^6.0", - "symfony/expression-language": "^4.4|^5.0|^6.0", - "symfony/http-foundation": "^4.4|^5.0|^6.0", - "symfony/service-contracts": "^1.1|^2|^3", - "symfony/stopwatch": "^4.4|^5.0|^6.0" - }, - "suggest": { - "symfony/dependency-injection": "", - "symfony/http-kernel": "" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\EventDispatcher\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", - "homepage": "https://symfony.com", - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-01-02T09:53:40+00:00" - }, - { - "name": "symfony/event-dispatcher-contracts", - "version": "v2.5.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "66bea3b09be61613cd3b4043a65a8ec48cfa6d2a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/66bea3b09be61613cd3b4043a65a8ec48cfa6d2a", - "reference": "66bea3b09be61613cd3b4043a65a8ec48cfa6d2a", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "psr/event-dispatcher": "^1" - }, - "suggest": { - "symfony/event-dispatcher-implementation": "" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "2.5-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Contracts\\EventDispatcher\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Generic abstractions related to dispatching event", - "homepage": "https://symfony.com", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" - ], - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2021-07-12T14:48:14+00:00" - }, - { - "name": "symfony/filesystem", - "version": "v5.4.6", - "source": { - "type": "git", - "url": "https://github.com/symfony/filesystem.git", - "reference": "d53a45039974952af7f7ebc461ccdd4295e29440" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/d53a45039974952af7f7ebc461ccdd4295e29440", - "reference": "d53a45039974952af7f7ebc461ccdd4295e29440", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-mbstring": "~1.8", - "symfony/polyfill-php80": "^1.16" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Filesystem\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides basic utilities for the filesystem", - "homepage": "https://symfony.com", - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-03-02T12:42:23+00:00" - }, - { - "name": "symfony/finder", - "version": "v5.4.3", - "source": { - "type": "git", - "url": "https://github.com/symfony/finder.git", - "reference": "231313534dded84c7ecaa79d14bc5da4ccb69b7d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/231313534dded84c7ecaa79d14bc5da4ccb69b7d", - "reference": "231313534dded84c7ecaa79d14bc5da4ccb69b7d", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-php80": "^1.16" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Finder\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Finds files and directories via an intuitive fluent interface", - "homepage": "https://symfony.com", - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-01-26T16:34:36+00:00" - }, - { - "name": "symfony/options-resolver", - "version": "v5.4.3", - "source": { - "type": "git", - "url": "https://github.com/symfony/options-resolver.git", - "reference": "cc1147cb11af1b43f503ac18f31aa3bec213aba8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/cc1147cb11af1b43f503ac18f31aa3bec213aba8", - "reference": "cc1147cb11af1b43f503ac18f31aa3bec213aba8", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-php73": "~1.0", - "symfony/polyfill-php80": "^1.16" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\OptionsResolver\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides an improved replacement for the array_replace PHP function", - "homepage": "https://symfony.com", - "keywords": [ - "config", - "configuration", - "options" - ], - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-01-02T09:53:40+00:00" - }, - { - "name": "symfony/polyfill-ctype", - "version": "v1.25.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "30885182c981ab175d4d034db0f6f469898070ab" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/30885182c981ab175d4d034db0f6f469898070ab", - "reference": "30885182c981ab175d4d034db0f6f469898070ab", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "provide": { - "ext-ctype": "*" - }, - "suggest": { - "ext-ctype": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.23-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Ctype\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Gert de Pagter", - "email": "BackEndTea@gmail.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for ctype functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "ctype", - "polyfill", - "portable" - ], - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2021-10-20T20:35:02+00:00" - }, - { - "name": "symfony/polyfill-intl-grapheme", - "version": "v1.25.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "81b86b50cf841a64252b439e738e97f4a34e2783" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/81b86b50cf841a64252b439e738e97f4a34e2783", - "reference": "81b86b50cf841a64252b439e738e97f4a34e2783", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "suggest": { - "ext-intl": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.23-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Intl\\Grapheme\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for intl's grapheme_* functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "grapheme", - "intl", - "polyfill", - "portable", - "shim" - ], - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2021-11-23T21:10:46+00:00" - }, - { - "name": "symfony/polyfill-intl-normalizer", - "version": "v1.25.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8590a5f561694770bdcd3f9b5c69dde6945028e8", - "reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "suggest": { - "ext-intl": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.23-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Intl\\Normalizer\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for intl's Normalizer class and related functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "intl", - "normalizer", - "polyfill", - "portable", - "shim" - ], - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2021-02-19T12:13:01+00:00" - }, - { - "name": "symfony/polyfill-mbstring", - "version": "v1.25.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "0abb51d2f102e00a4eefcf46ba7fec406d245825" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/0abb51d2f102e00a4eefcf46ba7fec406d245825", - "reference": "0abb51d2f102e00a4eefcf46ba7fec406d245825", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "provide": { - "ext-mbstring": "*" - }, - "suggest": { - "ext-mbstring": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.23-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Mbstring\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for the Mbstring extension", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "mbstring", - "polyfill", - "portable", - "shim" - ], - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2021-11-30T18:21:41+00:00" - }, - { - "name": "symfony/polyfill-php70", - "version": "v1.20.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php70.git", - "reference": "5f03a781d984aae42cebd18e7912fa80f02ee644" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php70/zipball/5f03a781d984aae42cebd18e7912fa80f02ee644", - "reference": "5f03a781d984aae42cebd18e7912fa80f02ee644", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "type": "metapackage", - "extra": { - "branch-alias": { - "dev-main": "1.20-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 7.0+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2020-10-23T14:02:19+00:00" - }, - { - "name": "symfony/polyfill-php72", - "version": "v1.25.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php72.git", - "reference": "9a142215a36a3888e30d0a9eeea9766764e96976" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/9a142215a36a3888e30d0a9eeea9766764e96976", - "reference": "9a142215a36a3888e30d0a9eeea9766764e96976", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.23-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Php72\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2021-05-27T09:17:38+00:00" - }, - { - "name": "symfony/polyfill-php73", - "version": "v1.25.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php73.git", - "reference": "cc5db0e22b3cb4111010e48785a97f670b350ca5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/cc5db0e22b3cb4111010e48785a97f670b350ca5", - "reference": "cc5db0e22b3cb4111010e48785a97f670b350ca5", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.23-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Php73\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2021-06-05T21:20:04+00:00" - }, - { - "name": "symfony/polyfill-php80", - "version": "v1.25.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "4407588e0d3f1f52efb65fbe92babe41f37fe50c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/4407588e0d3f1f52efb65fbe92babe41f37fe50c", - "reference": "4407588e0d3f1f52efb65fbe92babe41f37fe50c", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.23-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Php80\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Ion Bazan", - "email": "ion.bazan@gmail.com" - }, - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-03-04T08:16:47+00:00" - }, - { - "name": "symfony/process", - "version": "v5.4.5", - "source": { - "type": "git", - "url": "https://github.com/symfony/process.git", - "reference": "95440409896f90a5f85db07a32b517ecec17fa4c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/95440409896f90a5f85db07a32b517ecec17fa4c", - "reference": "95440409896f90a5f85db07a32b517ecec17fa4c", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/polyfill-php80": "^1.16" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Process\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Executes commands in sub-processes", - "homepage": "https://symfony.com", - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-01-30T18:16:22+00:00" - }, - { - "name": "symfony/service-contracts", - "version": "v2.5.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/service-contracts.git", - "reference": "1ab11b933cd6bc5464b08e81e2c5b07dec58b0fc" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/1ab11b933cd6bc5464b08e81e2c5b07dec58b0fc", - "reference": "1ab11b933cd6bc5464b08e81e2c5b07dec58b0fc", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "psr/container": "^1.1", - "symfony/deprecation-contracts": "^2.1" - }, - "conflict": { - "ext-psr": "<1.1|>=2" - }, - "suggest": { - "symfony/service-implementation": "" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "2.5-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Contracts\\Service\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Generic abstractions related to writing services", - "homepage": "https://symfony.com", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" - ], - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2021-11-04T16:48:04+00:00" - }, - { - "name": "symfony/stopwatch", - "version": "v5.4.5", - "source": { - "type": "git", - "url": "https://github.com/symfony/stopwatch.git", - "reference": "4d04b5c24f3c9a1a168a131f6cbe297155bc0d30" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/4d04b5c24f3c9a1a168a131f6cbe297155bc0d30", - "reference": "4d04b5c24f3c9a1a168a131f6cbe297155bc0d30", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/service-contracts": "^1|^2|^3" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Stopwatch\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides a way to profile code", - "homepage": "https://symfony.com", - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-02-18T16:06:09+00:00" - }, - { - "name": "symfony/string", - "version": "v5.4.3", - "source": { - "type": "git", - "url": "https://github.com/symfony/string.git", - "reference": "92043b7d8383e48104e411bc9434b260dbeb5a10" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/92043b7d8383e48104e411bc9434b260dbeb5a10", - "reference": "92043b7d8383e48104e411bc9434b260dbeb5a10", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-intl-grapheme": "~1.0", - "symfony/polyfill-intl-normalizer": "~1.0", - "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php80": "~1.15" - }, - "conflict": { - "symfony/translation-contracts": ">=3.0" - }, - "require-dev": { - "symfony/error-handler": "^4.4|^5.0|^6.0", - "symfony/http-client": "^4.4|^5.0|^6.0", - "symfony/translation-contracts": "^1.1|^2", - "symfony/var-exporter": "^4.4|^5.0|^6.0" - }, - "type": "library", - "autoload": { - "files": [ - "Resources/functions.php" - ], - "psr-4": { - "Symfony\\Component\\String\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", - "homepage": "https://symfony.com", - "keywords": [ - "grapheme", - "i18n", - "string", - "unicode", - "utf-8", - "utf8" - ], - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-01-02T09:53:40+00:00" + "time": "2024-11-25T00:39:41+00:00" } ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": {}, "prefer-stable": false, "prefer-lowest": false, - "platform": [], - "platform-dev": [], - "plugin-api-version": "1.1.0" + "platform": { + "ext-curl": "*" + }, + "platform-dev": { + "ext-fileinfo": "*" + }, + "plugin-api-version": "2.6.0" } diff --git a/docker-compose.yml b/docker-compose.yml index edcee4d..e571c20 100755 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -38,6 +38,8 @@ services: extra_hosts: - host.docker.internal:host-gateway - onlyoffice.local:host-gateway + - hejbit.local:host-gateway + - api.hejbit.local:host-gateway volumes: - nc-app:/var/www/html - ./:/var/www/html/custom_apps/files_external_ethswarm @@ -185,5 +187,4 @@ networks: frontend: backend: proxy: - # external: true name: hejbit-network diff --git a/lib/AppInfo/AppConstants.php b/lib/AppInfo/AppConstants.php index eb6d268..36b54d1 100644 --- a/lib/AppInfo/AppConstants.php +++ b/lib/AppInfo/AppConstants.php @@ -1,10 +1,10 @@ - * * @license GNU AGPL version 3 or any later version * * This program is free software: you can redistribute it and/or modify @@ -19,8 +19,8 @@ * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . - * */ + namespace OCA\Files_External_Ethswarm\AppInfo; class AppConstants { diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index 7acecf2..1fd388e 100755 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -1,9 +1,8 @@ - * * @license GNU AGPL version 3 or any later version * * This program is free software: you can redistribute it and/or modify @@ -18,7 +17,6 @@ * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . - * */ declare(strict_types=1); @@ -26,36 +24,29 @@ namespace OCA\Files_External_Ethswarm\AppInfo; use OCA\Files\Event\LoadAdditionalScriptsEvent; -use OCA\Files_External_Ethswarm\AppInfo\AppConstants; -use OCA\Files_External_Ethswarm\Backend\BeeSwarm; -use OCA\Files_External_Ethswarm\Auth\License; +use OCA\Files_External\Lib\Config\IAuthMechanismProvider; use OCA\Files_External\Lib\Config\IBackendProvider; use OCA\Files_External\Service\BackendService; -use OCA\Files_External\Lib\Config\IAuthMechanismProvider; +use OCA\Files_External_Ethswarm\Auth\License; +use OCA\Files_External_Ethswarm\Backend\BeeSwarm; use OCA\Files_External_Ethswarm\Notification\Notifier; use OCP\AppFramework\App; -use OCP\Util; -use OCP\AppFramework\Bootstrap\IRegistrationContext; use OCP\AppFramework\Bootstrap\IBootContext; use OCP\AppFramework\Bootstrap\IBootstrap; +use OCP\AppFramework\Bootstrap\IRegistrationContext; use OCP\EventDispatcher\IEventDispatcher; +use OCP\Util; -/** - * @package OCA\Files_external_beeswarm\AppInfo - */ class Application extends App implements IBootstrap, IBackendProvider, IAuthMechanismProvider { - public function __construct(array $urlParams = []) { parent::__construct(AppConstants::APP_NAME, $urlParams); } - /** - * @{inheritdoc} - */ public function getBackends() { $container = $this->getContainer(); + return [ - $container->query(BeeSwarm::class) + $container->query(BeeSwarm::class), ]; } @@ -82,11 +73,9 @@ public function boot(IBootContext $context): void { }); $this->getAuthMechanisms(); - } - public function registerEventsScripts(IEventDispatcher $dispatcher) { - } + public function registerEventsScripts(IEventDispatcher $dispatcher) {} public function register(IRegistrationContext $context): void { // Register AddContentSecurityPolicyEvent for CSPListener class listenser here @@ -95,6 +84,7 @@ public function register(IRegistrationContext $context): void { public function getAuthMechanisms() { $container = $this->getContainer(); + return [ // AuthMechanism::BASIC HTTP mechanisms $container->get(License::class), diff --git a/lib/Auth/License.php b/lib/Auth/License.php index 65d7da6..194b9e1 100755 --- a/lib/Auth/License.php +++ b/lib/Auth/License.php @@ -1,9 +1,8 @@ - * * @license GNU AGPL version 3 or any later version * * This program is free software: you can redistribute it and/or modify @@ -18,7 +17,6 @@ * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . - * */ namespace OCA\Files_External_Ethswarm\Auth; @@ -28,26 +26,22 @@ use OCP\IL10N; /** - * Basic Http Authentication + * Basic Http Authentication. */ -class License extends AuthMechanism -{ +class License extends AuthMechanism { /** @const string */ public const SCHEME_ACCESS_KEY = 'access_key'; - /** - * @param IL10N $l - */ - public function __construct(IL10N $l) - { + public function __construct(IL10N $l) { $this ->setIdentifier('access:key') ->setScheme(self::SCHEME_ACCESS_KEY) ->setText($l->t('License')) ->addParameters([ (new DefinitionParameter(self::SCHEME_ACCESS_KEY, $l->t('Access Key'))) - ->setTooltip($l->t("License Access Key")) + ->setTooltip($l->t('License Access Key')) ->setType(DefinitionParameter::VALUE_PASSWORD), - ]); + ]) + ; } } diff --git a/lib/Backend/BeeSwarm.php b/lib/Backend/BeeSwarm.php index 300181d..d3d4193 100755 --- a/lib/Backend/BeeSwarm.php +++ b/lib/Backend/BeeSwarm.php @@ -1,9 +1,8 @@ - * * @license GNU AGPL version 3 or any later version * * This program is free software: you can redistribute it and/or modify @@ -18,51 +17,34 @@ * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . - * */ namespace OCA\Files_External_Ethswarm\Backend; -use OCA\Files_External_Ethswarm\AppInfo\AppConstants; use OCA\Files_External\Lib\Backend\Backend; use OCA\Files_External\Lib\DefinitionParameter; use OCA\Files_External\Lib\StorageConfig; use OCA\Files_External\Service\GlobalStoragesService; +use OCA\Files_External_Ethswarm\AppInfo\AppConstants; use OCA\Files_External_Ethswarm\Auth\License; use OCP\IConfig; use OCP\IL10N; -use OCP\IUser; use Psr\Log\LoggerInterface; -class BeeSwarm extends Backend -{ - /** @var IL10N */ - private IL10N $l; +class BeeSwarm extends Backend { + /** @const string */ + public const OPTION_HOST_URL = 'host_url'; - /** @var string */ protected string $appName; + private IL10N $l; - /** @var IConfig */ private IConfig $config; - /** @var LoggerInterface */ private LoggerInterface $logger; - /** @var GlobalStoragesService */ private GlobalStoragesService $globalStoragesService; - /** @const string */ - public const OPTION_HOST_URL = 'host_url'; - - /** - * @param string $appName - * @param IL10N $l - * @param IConfig $config - * @param LoggerInterface $logger - * @param GlobalStoragesService $globalStoragesService - */ - public function __construct(string $appName, IL10N $l, IConfig $config, LoggerInterface $logger, GlobalStoragesService $globalStoragesService) - { + public function __construct(string $appName, IL10N $l, IConfig $config, LoggerInterface $logger, GlobalStoragesService $globalStoragesService) { $this->l = $l; $this->appName = $appName; $this->config = $config; @@ -75,30 +57,27 @@ public function __construct(string $appName, IL10N $l, IConfig $config, LoggerIn ->setText($l->t('HejBit-Swarm')) ->addParameters([ (new DefinitionParameter(self::OPTION_HOST_URL, $l->t('Server URL'))) - ->setTooltip($l->t("License Server URL")), - ])->addAuthScheme(License::SCHEME_ACCESS_KEY); + ->setTooltip($l->t('License Server URL')), + ])->addAuthScheme(License::SCHEME_ACCESS_KEY) + ; } - /** - * {@inheritdoc} - */ - public function validateStorageDefinition(StorageConfig $storage): bool - { + public function validateStorageDefinition(StorageConfig $storage): bool { $result = true; // access key if (!$storage->getBackendOption(License::SCHEME_ACCESS_KEY)) { - $this->logger->warning("access key not set"); + $this->logger->warning('access key not set'); $result = false; } // server url $host = $storage->getBackendOption(self::OPTION_HOST_URL); if (!preg_match('/^https?:\/\//i', $host)) { - $host = 'https://' . $host; + $host = 'https://'.$host; } if (!filter_var($host, FILTER_VALIDATE_URL)) { - $this->logger->warning("invalid url"); + $this->logger->warning('invalid url'); $result = false; } diff --git a/lib/Controller/BeeController.php b/lib/Controller/BeeController.php index 2c970db..a82fcd0 100755 --- a/lib/Controller/BeeController.php +++ b/lib/Controller/BeeController.php @@ -4,9 +4,7 @@ /** * @copyright Copyright (c) 2023, MetaProvide Holding EKF - * * @author Ron Trevor - * * @license GNU AGPL version 3 or any later version * * This program is free software: you can redistribute it and/or modify @@ -21,33 +19,27 @@ * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . - * */ namespace OCA\Files_External_Ethswarm\Controller; +use OCA\Files_External_Ethswarm\Settings\Admin; use OCP\AppFramework\Controller; +use OCP\AppFramework\Http; +use OCP\AppFramework\Http\DataResponse; use OCP\IConfig; use OCP\IRequest; -use OCA\Files_External_Ethswarm\Settings\Admin; -use OCP\AppFramework\Http\DataResponse; -use OCP\AppFramework\Http; class BeeController extends Controller { + /** @var string */ + protected $appName; /** @var Admin */ private $admin; - /** @var string */ - protected $appName; - /** @var IConfig */ private $config; - /** - * @param IConfig $config - * @param IRequest $request - */ public function __construct( string $appName, IConfig $config, @@ -61,42 +53,50 @@ public function __construct( /** * @NoCSRFRequired + * * @NoAdminRequired * Create a new postage batch stamp + * * @return \DataResponse */ - public function createPostageBatch(): DataResponse { - if ($this->request->getParam("postageBatch")) { - $postageBatch = json_decode($this->request->getParam("postageBatch"), true); + public function createPostageBatch(): DataResponse { + if ($this->request->getParam('postageBatch')) { + $postageBatch = json_decode($this->request->getParam('postageBatch'), true); - $response_data = $this->admin->buyPostageStamp($postageBatch["amount"],$postageBatch["depth"],$postageBatch["mount_urloptions"]); + $response_data = $this->admin->buyPostageStamp($postageBatch['amount'], $postageBatch['depth'], $postageBatch['mount_urloptions']); - if (isset($response_data["batchID"])) { - return new DataResponse(array('batchID' => $response_data["batchID"]), Http::STATUS_OK); - } else if (isset($response_data["message"])) { - return new DataResponse(array('msg' => $response_data["message"]), $response_data["code"]); + if (isset($response_data['batchID'])) { + return new DataResponse(['batchID' => $response_data['batchID']], Http::STATUS_OK); + } + if (isset($response_data['message'])) { + return new DataResponse(['msg' => $response_data['message']], $response_data['code']); } } - return new DataResponse(array('msg' => "Error in request"), Http::STATUS_CONFLICT); + + return new DataResponse(['msg' => 'Error in request'], Http::STATUS_CONFLICT); } /** * @NoCSRFRequired + * * @NoAdminRequired * Top up an existing batch stamp based on the batchID + * * @return \DataResponse */ public function topUpBatch(): DataResponse { - if ($this->request->getParam("postageBatch")) { - $postageBatch = json_decode($this->request->getParam("postageBatch"), true); + if ($this->request->getParam('postageBatch')) { + $postageBatch = json_decode($this->request->getParam('postageBatch'), true); - $response_data = $this->admin->topUpPostageStamp($postageBatch["activeBatchId"],$postageBatch["topUpValue"],$postageBatch["mount_urloptions"]); - if (isset($response_data["batchID"])) { - return new DataResponse(array('batchID' => $response_data["batchID"]), Http::STATUS_OK); - } else if (isset($response_data["message"])) { - return new DataResponse(array('msg' => $response_data["message"]), $response_data["code"]); + $response_data = $this->admin->topUpPostageStamp($postageBatch['activeBatchId'], $postageBatch['topUpValue'], $postageBatch['mount_urloptions']); + if (isset($response_data['batchID'])) { + return new DataResponse(['batchID' => $response_data['batchID']], Http::STATUS_OK); + } + if (isset($response_data['message'])) { + return new DataResponse(['msg' => $response_data['message']], $response_data['code']); } } - return new DataResponse(array('msg' => "Error in request"), Http::STATUS_CONFLICT); + + return new DataResponse(['msg' => 'Error in request'], Http::STATUS_CONFLICT); } } diff --git a/lib/Controller/SettingsController.php b/lib/Controller/SettingsController.php index bc53dfc..4c99320 100755 --- a/lib/Controller/SettingsController.php +++ b/lib/Controller/SettingsController.php @@ -4,9 +4,7 @@ /** * @copyright Copyright (c) 2022, MetaProvide Holding EKF - * * @author Ron Trevor - * * @license GNU AGPL version 3 or any later version * * This program is free software: you can redistribute it and/or modify @@ -21,7 +19,6 @@ * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . - * */ namespace OCA\Files_External_Ethswarm\Controller; @@ -31,47 +28,43 @@ use OCP\IRequest; class SettingsController extends Controller { - /** @var string */ protected $appName; /** @var IConfig */ private $config; - /** - * @param IConfig $config - * @param IRequest $request - */ public function __construct( string $appName, IConfig $config, - IRequest $request + IRequest $request, ) { parent::__construct($appName, $request); $this->config = $config; } /** - * Set the storage config settings + * Set the storage config settings. */ public function admin(): void { - if ($this->request->getParam("storageconfig")) { - $this->config->setAppValue($this->appName, "storageconfig", $this->request->getParam("storageconfig")); + if ($this->request->getParam('storageconfig')) { + $this->config->setAppValue($this->appName, 'storageconfig', $this->request->getParam('storageconfig')); } else { - $this->config->setAppValue($this->appName, "storageconfig", ""); + $this->config->setAppValue($this->appName, 'storageconfig', ''); } } /** * @NoCSRFRequired + * * @NoAdminRequired * Save the storage config settings */ public function save(): void { - if ($this->request->getParam("storageconfig")) { - $this->config->setAppValue($this->appName, "storageconfig", $this->request->getParam("storageconfig")); + if ($this->request->getParam('storageconfig')) { + $this->config->setAppValue($this->appName, 'storageconfig', $this->request->getParam('storageconfig')); } else { - $this->config->setAppValue($this->appName, "storageconfig", ""); + $this->config->setAppValue($this->appName, 'storageconfig', ''); } } } diff --git a/lib/Db/SwarmFile.php b/lib/Db/SwarmFile.php index 12f1fca..88fe1af 100755 --- a/lib/Db/SwarmFile.php +++ b/lib/Db/SwarmFile.php @@ -4,9 +4,7 @@ /** * @copyright Copyright (c) 2022, MetaProvide Holding EKF - * * @author Ron Trevor - * * @license GNU AGPL version 3 or any later version * * This program is free software: you can redistribute it and/or modify @@ -21,48 +19,47 @@ * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . - * */ + namespace OCA\Files_External_Ethswarm\Db; use OCP\AppFramework\Db\Entity; /** - * @method void setFileid(int $fileid) - * @method int getFileid() - * @method void setName(string $name) - * @method string getName() - * @method void setSwarmReference(string $reference) - * @method string|null getSwarmReference() - * @method void setSwarmTag(string $tag) - * @method string|null getSwarmTag() - * @method void setMimetype(int $mimetype) - * @method string|null getMimetype() - * @method void setSize(int $size) - * @method string getSize() - * @method void setStorageMtime(int $mtime) - * @method int getStorageMtime() - * @method void setEncryptionkey(string $encryption) - * @method string getEncryptionkey() - * @method void setStorage(int $storage) - * @method int|null getStorage() - * @method void setVisibility(int $visibility) - * @method int getVisibility() - * @method void setToken(string $token) - * @method int getToken() + * @method void setFileId(int $fileId) + * @method int getFileId() + * @method void setName(string $name) + * @method string getName() + * @method void setSwarmReference(string $swarmReference) + * @method null|string getSwarmReference() + * @method void setSwarmTag(string $tag) + * @method null|string getSwarmTag() + * @method void setMimetype(int $mimetype) + * @method int getMimetype() + * @method void setSize(int $size) + * @method string getSize() + * @method void setStorageMtime(int $mtime) + * @method int getStorageMtime() + * @method void setEncryptionKey(string $encryptionKey) + * @method string getEncryptionKey() + * @method void setStorage(int $storage) + * @method null|int getStorage() + * @method void setVisibility(int $visibility) + * @method int getVisibility() + * @method void setToken(string $token) + * @method int getToken() */ class SwarmFile extends Entity { - - /** @var int */ - protected $fileid; + /** @var null|int */ + protected $fileId; /** @var string */ protected $name; - /** @var string|null */ + /** @var null|string */ protected $swarmReference; - /** @var string|null */ + /** @var null|string */ protected $swarmTag; /** @var int */ @@ -75,9 +72,9 @@ class SwarmFile extends Entity { protected $storageMtime; /** @var string */ - protected $encryptionkey; + protected $encryptionKey; - /** @var int */ + /** @var null|int */ protected $storage; /** @var int */ @@ -87,7 +84,7 @@ class SwarmFile extends Entity { protected $token; public function __construct() { - $this->addType('fileid', 'int'); + $this->addType('fileId', 'int'); $this->addType('name', 'string'); $this->addType('swarmReference', 'string'); $this->addType('swarmTag', 'string'); diff --git a/lib/Db/SwarmFileMapper.php b/lib/Db/SwarmFileMapper.php index 697513a..7a7116b 100755 --- a/lib/Db/SwarmFileMapper.php +++ b/lib/Db/SwarmFileMapper.php @@ -4,9 +4,7 @@ /** * @copyright Copyright (c) 2022, MetaProvide Holding EKF - * * @author Ron Trevor - * * @license GNU AGPL version 3 or any later version * * This program is free software: you can redistribute it and/or modify @@ -21,14 +19,17 @@ * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . - * */ + namespace OCA\Files_External_Ethswarm\Db; +use OC; use OCP\AppFramework\Db\DoesNotExistException; +use OCP\AppFramework\Db\MultipleObjectsReturnedException; use OCP\AppFramework\Db\QBMapper; -use OCP\IDBConnection; +use OCP\DB\Exception; use OCP\Files\IMimeTypeLoader; +use OCP\IDBConnection; /** * @template-extends QBMapper @@ -42,24 +43,25 @@ public function __construct(IDBConnection $db) { /** * @return SwarmFile[] + * + * @throws Exception */ - public function findAll(string $fileid): array { + public function findAll(string $fileId): array { $qb = $this->db->getQueryBuilder(); $select = $qb ->select('*') ->from($this->getTableName()) - ->where($qb->expr()->eq('fileid', $qb->createNamedParameter($fileid))); + ->where($qb->expr()->eq('fileId', $qb->createNamedParameter($fileId))) + ; return $this->findEntities($select); } /** - * @param string $name - * @param int $storage - * - * @return SwarmFile * @throws DoesNotExistException + * @throws Exception + * @throws MultipleObjectsReturnedException */ public function find(string $name, int $storage): SwarmFile { $qb = $this->db->getQueryBuilder(); @@ -68,15 +70,14 @@ public function find(string $name, int $storage): SwarmFile { ->select('*') ->from($this->getTableName()) ->where($qb->expr()->eq('name', $qb->createNamedParameter($name, $qb::PARAM_STR))) - ->andWhere($qb->expr()->eq('storage', $qb->createNamedParameter($storage, $qb::PARAM_INT))); + ->andWhere($qb->expr()->eq('storage', $qb->createNamedParameter($storage, $qb::PARAM_INT))) + ; + return $this->findEntity($select); } /** - * @param string $name - * @param int $storage - * - * @return count of elements in array + * @throws Exception */ public function findExists(string $name, int $storage): int { $qb = $this->db->getQueryBuilder(); @@ -85,71 +86,95 @@ public function findExists(string $name, int $storage): int { ->select('id') ->from($this->getTableName()) ->where($qb->expr()->eq('name', $qb->createNamedParameter($name, $qb::PARAM_STR))) - ->andWhere($qb->expr()->eq('storage', $qb->createNamedParameter($storage, $qb::PARAM_INT))); + ->andWhere($qb->expr()->eq('storage', $qb->createNamedParameter($storage, $qb::PARAM_INT))) + ; + return count($this->findEntities($select)); } + /** + * @throws Exception + */ public function createDirectory(string $path, int $storage, string $token): SwarmFile { $swarm = new SwarmFile(); $swarm->setName($path); - $swarm->setMimetype(\OC::$server->get(IMimeTypeLoader::class)->getId("httpd/unix-directory")); + $swarm->setMimetype(OC::$server->get(IMimeTypeLoader::class)->getId('httpd/unix-directory')); $swarm->setSize(1); $swarm->setStorageMtime(time()); $swarm->setStorage($storage); $swarm->setToken($token); + return $this->insert($swarm); } - public function createFile(array $filearray): SwarmFile { + /** + * @throws Exception + */ + public function createFile(array $data): SwarmFile { $swarm = new SwarmFile(); - $swarm->setName($filearray["name"]); - $swarm->setSwarmReference($filearray["reference"]); - $swarm->setSwarmTag($filearray["etag"]); - $swarm->setMimetype($filearray["mimetype"]); - $swarm->setSize($filearray["size"]); - $swarm->setStorageMtime($filearray["storage_mtime"]); - $swarm->setStorage($filearray["storage"]); - $swarm->setToken($filearray["token"]); + $swarm->setName($data['name']); + $swarm->setSwarmReference($data['reference']); + $swarm->setSwarmTag($data['etag']); + $swarm->setMimetype($data['mimetype']); + $swarm->setSize($data['size']); + $swarm->setStorageMtime($data['storage_mtime']); + $swarm->setStorage($data['storage']); + $swarm->setToken($data['token']); + return $this->insert($swarm); } - public function getPathTree(string $path1, int $storage, bool $incSelf = true, bool $recursive = true): array { + /** + * @throws Exception|MultipleObjectsReturnedException + */ + public function getPathTree(string $path, int $storage, bool $incSelf = true, bool $recursive = true): array { // Get files from directory tree based on path parameter - $dir = array(); + $dir = []; if ($incSelf) { try { - array_push($dir, $this->find($path1, $storage)); + $dir[] = $this->find($path, $storage); } catch (DoesNotExistException $e) { } } - if ($path1 !== '') - $path1 .= '/'; + if ('' !== $path) { + $path .= '/'; + } $qb = $this->db->getQueryBuilder(); $select = $qb ->select('*') ->from($this->getTableName()) - ->where($qb->expr()->like('name', $qb->createNamedParameter($this->db->escapeLikeParameter($path1) . '%', $qb::PARAM_STR))) - ->andWhere($qb->expr()->eq('storage', $qb->createNamedParameter($storage, $qb::PARAM_INT))); - if (!$recursive) - $select->andWhere($qb->expr()->notLike('name', $qb->createNamedParameter($this->db->escapeLikeParameter($path1) . '%/%', $qb::PARAM_STR))); + ->where($qb->expr()->like('name', $qb->createNamedParameter($this->db->escapeLikeParameter($path).'%'), $qb::PARAM_STR)) + ->andWhere($qb->expr()->eq('storage', $qb->createNamedParameter($storage, $qb::PARAM_INT))) + ; + if (!$recursive) { + $select->andWhere($qb->expr()->notLike('name', $qb->createNamedParameter($this->db->escapeLikeParameter($path).'%/%'), $qb::PARAM_STR)); + } + return array_merge($dir, $this->findEntities($select)); } + /** + * @throws Exception + */ public function updatePath(string $path1, string $path2, int $storage): int { $qb = $this->db->getQueryBuilder(); $qb ->update($this->getTableName()) ->set('name', $qb->createNamedParameter($path2)) ->where($qb->expr()->eq('name', $qb->createNamedParameter($path1, $qb::PARAM_STR))) - ->andWhere($qb->expr()->eq('storage', $qb->createNamedParameter($storage, $qb::PARAM_INT))); - $sql = $qb->getSQL(); + ->andWhere($qb->expr()->eq('storage', $qb->createNamedParameter($storage, $qb::PARAM_INT))) + ; + $qb->getSQL(); + return $qb->executeStatement(); } /** * @return SwarmFile[] + * + * @throws Exception */ public function findAllWithToken(string $token): array { $qb = $this->db->getQueryBuilder(); @@ -157,20 +182,19 @@ public function findAllWithToken(string $token): array { $select = $qb ->select('*') ->from($this->getTableName()) - ->where($qb->expr()->eq('token', $qb->createNamedParameter($token))); + ->where($qb->expr()->eq('token', $qb->createNamedParameter($token))) + ; return $this->findEntities($select); } - - public function updateStorageIds(string $token,string $storageid): int { - + /** + * @throws Exception + */ + public function updateStorageIds(string $token, int $storageId): void { foreach ($this->findAllWithToken($token) as $swarmFile) { - $swarmFile->setStorage($storageid); + $swarmFile->setStorage($storageId); $this->update($swarmFile); - }; - - return 1; + } } - } diff --git a/lib/Exception/SwarmException.php b/lib/Exception/SwarmException.php new file mode 100644 index 0000000..55b45e9 --- /dev/null +++ b/lib/Exception/SwarmException.php @@ -0,0 +1,11 @@ + - * * @license GNU AGPL version 3 or any later version * * This program is free software: you can redistribute it and/or modify @@ -21,25 +19,25 @@ * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . - * */ + namespace OCA\Files_External_Ethswarm\Migration; use Closure; use OCP\DB\ISchemaWrapper; +use OCP\DB\Types; use OCP\Migration\IOutput; use OCP\Migration\SimpleMigrationStep; -use OCP\DB\Types; class Version0001Date202204071430 extends SimpleMigrationStep { - public const _TABLENAME = "files_swarm"; + public const _TABLENAME = 'files_swarm'; + /** - * @param IOutput $output * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper` - * @param array $options + * * @return null|ISchemaWrapper */ - public function changeSchema(IOutput $output, \Closure $schemaClosure, array $options) { + public function changeSchema(IOutput $output, Closure $schemaClosure, array $options) { /** @var ISchemaWrapper $schema */ $schema = $schemaClosure(); @@ -80,9 +78,9 @@ public function changeSchema(IOutput $output, \Closure $schemaClosure, array $op $table->setPrimaryKey(['id']); $table->addIndex(['storage'], 'storage_index'); } + return $schema; } - public function postSchemaChange(IOutput $output, \Closure $schemaClosure, array $options) { - } + public function postSchemaChange(IOutput $output, Closure $schemaClosure, array $options) {} } diff --git a/lib/Migration/Version0002Date202409251430.php b/lib/Migration/Version0002Date202409251430.php index 6ee82fe..b627dd3 100644 --- a/lib/Migration/Version0002Date202409251430.php +++ b/lib/Migration/Version0002Date202409251430.php @@ -4,9 +4,7 @@ /** * @copyright Copyright (c) 2022, MetaProvide Holding EKF - * * @author Ron Trevor - * * @license GNU AGPL version 3 or any later version * * This program is free software: you can redistribute it and/or modify @@ -21,25 +19,25 @@ * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . - * */ + namespace OCA\Files_External_Ethswarm\Migration; use Closure; use OCP\DB\ISchemaWrapper; +use OCP\DB\Types; use OCP\Migration\IOutput; use OCP\Migration\SimpleMigrationStep; -use OCP\DB\Types; class Version0002Date202409251430 extends SimpleMigrationStep { - public const _TABLENAME = "files_swarm"; + public const _TABLENAME = 'files_swarm'; + /** - * @param IOutput $output * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper` - * @param array $options + * * @return null|ISchemaWrapper */ - public function changeSchema(IOutput $output, \Closure $schemaClosure, array $options) { + public function changeSchema(IOutput $output, Closure $schemaClosure, array $options) { /** @var ISchemaWrapper $schema */ $schema = $schemaClosure(); @@ -51,11 +49,10 @@ public function changeSchema(IOutput $output, \Closure $schemaClosure, array $op 'length' => 8, 'default' => 1, ]); - } + return $schema; } - public function postSchemaChange(IOutput $output, \Closure $schemaClosure, array $options) { - } + public function postSchemaChange(IOutput $output, Closure $schemaClosure, array $options) {} } diff --git a/lib/Migration/Version0003Date202401101430.php b/lib/Migration/Version0003Date202401101430.php index 9cb9cfa..caa5046 100644 --- a/lib/Migration/Version0003Date202401101430.php +++ b/lib/Migration/Version0003Date202401101430.php @@ -4,9 +4,7 @@ /** * @copyright Copyright (c) 2022, MetaProvide Holding EKF - * * @author Ron Trevor - * * @license GNU AGPL version 3 or any later version * * This program is free software: you can redistribute it and/or modify @@ -21,68 +19,60 @@ * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . - * */ + namespace OCA\Files_External_Ethswarm\Migration; use Closure; +use OC; use OCP\DB\ISchemaWrapper; -use OCP\Migration\IOutput; -use OCP\Migration\SimpleMigrationStep; -use OCP\DB\Types; -use OCP\Files\IMimeTypeLoader; use OCP\DB\QueryBuilder\IQueryBuilder; +use OCP\Files\IMimeTypeLoader; use OCP\IDBConnection; - +use OCP\Migration\IOutput; +use OCP\Migration\SimpleMigrationStep; class Version0003Date202401101430 extends SimpleMigrationStep { - private $db; - /** @var \OCP\Files\IMimeTypeLoader */ private IMimeTypeLoader $mimeTypeHandler; public function __construct(IDBConnection $db) { $this->db = $db; - $this->mimeTypeHandler = \OC::$server->get(IMimeTypeLoader::class); + $this->mimeTypeHandler = OC::$server->get(IMimeTypeLoader::class); } - /** - * @param IOutput $output * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper` - * @param array $options + * * @return null|ISchemaWrapper */ - public function changeSchema(IOutput $output, \Closure $schemaClosure, array $options) { + public function changeSchema(IOutput $output, Closure $schemaClosure, array $options) {} - } - - public function postSchemaChange(IOutput $output, \Closure $schemaClosure, array $options) { + public function postSchemaChange(IOutput $output, Closure $schemaClosure, array $options) { $currentVersion = $this->getCurrentPluginVersion(); $mimetype = 'text/markdown'; if (version_compare($currentVersion, '0.5.4', '==')) { - $updateQb = $this->db->getQueryBuilder(); $updateQb->update('files_swarm') ->set('mimetype', $updateQb->createNamedParameter($this->mimeTypeHandler->getId($mimetype), IQueryBuilder::PARAM_INT)) ->where($updateQb->expr()->like('name', $updateQb->createNamedParameter('%.md'))) - ->executeStatement(); + ->executeStatement() + ; } - } private function getCurrentPluginVersion() { $qb = $this->db->getQueryBuilder(); $result = $qb->select('configvalue') - ->from('appconfig') - ->where($qb->expr()->eq('appid', $qb->createNamedParameter('files_external_ethswarm'))) - ->andWhere($qb->expr()->eq('configkey', $qb->createNamedParameter('installed_version'))) - ->executeQuery(); - $version = $result->fetchOne(); + ->from('appconfig') + ->where($qb->expr()->eq('appid', $qb->createNamedParameter('files_external_ethswarm'))) + ->andWhere($qb->expr()->eq('configkey', $qb->createNamedParameter('installed_version'))) + ->executeQuery() + ; - return $version; + return $result->fetchOne(); } } diff --git a/lib/Migration/Version0004Date202410131430.php b/lib/Migration/Version0004Date202410131430.php index b36f177..57c3a6c 100644 --- a/lib/Migration/Version0004Date202410131430.php +++ b/lib/Migration/Version0004Date202410131430.php @@ -4,9 +4,7 @@ /** * @copyright Copyright (c) 2022, MetaProvide Holding EKF - * * @author Ron Trevor - * * @license GNU AGPL version 3 or any later version * * This program is free software: you can redistribute it and/or modify @@ -21,17 +19,15 @@ * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . - * */ + namespace OCA\Files_External_Ethswarm\Migration; use Closure; use OCP\DB\ISchemaWrapper; +use OCP\IDBConnection; use OCP\Migration\IOutput; use OCP\Migration\SimpleMigrationStep; -use OCP\DB\Types; -use OCP\DB\QueryBuilder\IQueryBuilder; -use OCP\IDBConnection; class Version0004Date202410131430 extends SimpleMigrationStep { private $db; @@ -40,25 +36,21 @@ public function __construct(IDBConnection $db) { $this->db = $db; } - /** - * @param IOutput $output * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper` - * @param array $options + * * @return null|ISchemaWrapper */ - public function changeSchema(IOutput $output, \Closure $schemaClosure, array $options) { - - } + public function changeSchema(IOutput $output, Closure $schemaClosure, array $options) {} - public function postSchemaChange(IOutput $output, \Closure $schemaClosure, array $options) { + public function postSchemaChange(IOutput $output, Closure $schemaClosure, array $options) { $qb = $this->db->getQueryBuilder(); - $resultNI = $qb->select('numeric_id') - ->from('storages') - ->where($qb->expr()->like('id', $qb->createNamedParameter('ethswarm::https:%'))) - ->executeQuery(); + ->from('storages') + ->where($qb->expr()->like('id', $qb->createNamedParameter('ethswarm::https:%'))) + ->executeQuery() + ; // This migration step only runs if there is a license that contains the api_url (previous verion of plugin) while ($row = $resultNI->fetch()) { @@ -67,24 +59,27 @@ public function postSchemaChange(IOutput $output, \Closure $schemaClosure, array // This is assuming we only have one folder with Hejbit Plug (also true on the previous version of the plugin) $qb = $this->db->getQueryBuilder(); $result = $qb->select('mount_id') - ->from('external_mounts') - ->where($qb->expr()->eq('storage_backend', $qb->createNamedParameter('files_external_ethswarm'))) - ->executeQuery(); + ->from('external_mounts') + ->where($qb->expr()->eq('storage_backend', $qb->createNamedParameter('files_external_ethswarm'))) + ->executeQuery() + ; $mountid = $result->fetchOne(); $qb = $this->db->getQueryBuilder(); $result = $qb->select('value') - ->from('external_config','m') - ->where($qb->expr()->eq('m.mount_id', $qb->createNamedParameter($mountid))) - ->andWhere($qb->expr()->eq('m.key', $qb->createNamedParameter('access_key'))) - ->executeQuery(); + ->from('external_config', 'm') + ->where($qb->expr()->eq('m.mount_id', $qb->createNamedParameter($mountid))) + ->andWhere($qb->expr()->eq('m.key', $qb->createNamedParameter('access_key'))) + ->executeQuery() + ; $key = $result->fetchOne(); $updateQb = $this->db->getQueryBuilder(); $result = $updateQb->update('storages') ->set('id', $updateQb->createNamedParameter('ethswarm::'.$key)) ->where($updateQb->expr()->eq('numeric_id', $updateQb->createNamedParameter($numeric_id))) - ->executeStatement(); + ->executeStatement() + ; } - - }} + } +} diff --git a/lib/Migration/Version0005Date202411081430.php b/lib/Migration/Version0005Date202411081430.php index 0ee9353..09b47d6 100644 --- a/lib/Migration/Version0005Date202411081430.php +++ b/lib/Migration/Version0005Date202411081430.php @@ -4,9 +4,7 @@ /** * @copyright Copyright (c) 2022, MetaProvide Holding EKF - * * @author Ron Trevor - * * @license GNU AGPL version 3 or any later version * * This program is free software: you can redistribute it and/or modify @@ -21,35 +19,31 @@ * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . - * */ + namespace OCA\Files_External_Ethswarm\Migration; use Closure; use OCP\DB\ISchemaWrapper; -use OCP\Migration\IOutput; -use OCP\Migration\SimpleMigrationStep; use OCP\DB\Types; -use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\IDBConnection; +use OCP\Migration\IOutput; +use OCP\Migration\SimpleMigrationStep; class Version0005Date202411081430 extends SimpleMigrationStep { + public const _TABLENAME = 'files_swarm'; private $db; - public const _TABLENAME = "files_swarm"; - public function __construct(IDBConnection $db) { $this->db = $db; } - /** - * @param IOutput $output * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper` - * @param array $options + * * @return null|ISchemaWrapper */ - public function changeSchema(IOutput $output, \Closure $schemaClosure, array $options) { + public function changeSchema(IOutput $output, Closure $schemaClosure, array $options) { /** @var ISchemaWrapper $schema */ $schema = $schemaClosure(); $table = $schema->getTable(self::_TABLENAME); @@ -61,19 +55,20 @@ public function changeSchema(IOutput $output, \Closure $schemaClosure, array $op 'default' => 'none', ]); $table->addIndex(['token'], 'hejbit_token_index'); - } + return $schema; } - public function postSchemaChange(IOutput $output, \Closure $schemaClosure, array $options) { + public function postSchemaChange(IOutput $output, Closure $schemaClosure, array $options) { $gqbNI = $this->db->getQueryBuilder(); // Get all the numeric_id's of the swarm storages $resultNI = $gqbNI->select('numeric_id', 'id') - ->from('storages') - ->where($gqbNI->expr()->like('id', $gqbNI->createNamedParameter('ethswarm::%'))) - ->executeQuery(); + ->from('storages') + ->where($gqbNI->expr()->like('id', $gqbNI->createNamedParameter('ethswarm::%'))) + ->executeQuery() + ; while ($row = $resultNI->fetch()) { // Get all the files on each swarm storage @@ -83,9 +78,10 @@ public function postSchemaChange(IOutput $output, \Closure $schemaClosure, array $updateQb = $this->db->getQueryBuilder(); $result = $updateQb->update(self::_TABLENAME) - ->set('token', $updateQb->createNamedParameter($token_id)) - ->where($updateQb->expr()->eq('storage', $updateQb->createNamedParameter($numeric_id))) - ->executeStatement(); + ->set('token', $updateQb->createNamedParameter($token_id)) + ->where($updateQb->expr()->eq('storage', $updateQb->createNamedParameter($numeric_id))) + ->executeStatement() + ; } - - }} + } +} diff --git a/lib/Notification/Notifier.php b/lib/Notification/Notifier.php index a86472f..50f37d8 100644 --- a/lib/Notification/Notifier.php +++ b/lib/Notification/Notifier.php @@ -1,10 +1,10 @@ - * * @license GNU AGPL version 3 or any later version * * This program is free software: you can redistribute it and/or modify @@ -19,46 +19,50 @@ * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . - * */ + namespace OCA\Files_External_Ethswarm\Notification; +use InvalidArgumentException; use OCA\Files_External_Ethswarm\AppInfo\AppConstants; +use OCP\IURLGenerator; +use OCP\L10N\IFactory; +use OCP\Notification\INotification; +use OCP\Notification\INotifier; -class Notifier implements \OCP\Notification\INotifier { +class Notifier implements INotifier { protected $factory; protected $url; - public function __construct(\OCP\L10N\IFactory $factory, - \OCP\IURLGenerator $urlGenerator) { + public function __construct( + IFactory $factory, + IURLGenerator $urlGenerator + ) { $this->factory = $factory; $this->url = $urlGenerator; } /** - * Identifier of the notifier, only use [a-z0-9_] - * @return string + * Identifier of the notifier, only use [a-z0-9_]. */ public function getID(): string { return AppConstants::APP_NAME; } /** - * Human-readable name describing the notifier - * @return string + * Human-readable name describing the notifier. */ public function getName(): string { return $this->factory->get(AppConstants::APP_NAME)->t('Hejbit External Storage'); } /** - * @param \OCP\Notification\INotification $notification * @param string $languageCode The code of the language that should be used to prepare the notification */ - public function prepare(\OCP\Notification\INotification $notification, string $languageCode): \OCP\Notification\INotification { - if ($notification->getApp() !== AppConstants::APP_NAME) { + public function prepare(INotification $notification, string $languageCode): INotification { + if (AppConstants::APP_NAME !== $notification->getApp()) { // Not my app => throw - throw new \InvalidArgumentException(); + throw new InvalidArgumentException(); } // Read the language from the notification @@ -72,23 +76,26 @@ public function prepare(\OCP\Notification\INotification $notification, string $l // and https://github.com/nextcloud/server/blob/master/lib/public/RichObjectStrings/Definitions.php // for a list of defined objects and their parameters. $parameters = $notification->getSubjectParameters(); - $notification->setRichSubject($l->t('Your file \'{filename}\' was decentralized.'), - [ - 'filename' => [ - 'type' => 'file', - 'id' => '', - 'name' => basename($parameters['path']), - 'path' => $parameters['path'], - ], - ]); + $notification->setRichSubject( + $l->t('Your file \'{filename}\' was decentralized.'), + [ + 'filename' => [ + 'type' => 'file', + 'id' => '', + 'name' => basename($parameters['path']), + 'path' => $parameters['path'], + ], + ] + ); // Set the plain text subject automatically $this->setParsedSubjectFromRichSubject($notification); + return $notification; default: // Unknown subject => Unknown notification => throw - throw new \InvalidArgumentException(); + throw new InvalidArgumentException(); } } @@ -97,14 +104,12 @@ public function prepare(\OCP\Notification\INotification $notification, string $l * based on the rich subject you set. This is also the default behaviour of the API * since Nextcloud 26, but in case you would like to return simpler or other strings, * this function allows you to take over. - * - * @param \OCP\Notification\INotification $notification */ - protected function setParsedSubjectFromRichSubject(\OCP\Notification\INotification $notification): void { + protected function setParsedSubjectFromRichSubject(INotification $notification): void { $placeholders = $replacements = []; foreach ($notification->getRichSubjectParameters() as $placeholder => $parameter) { - $placeholders[] = '{' . $placeholder . '}'; - if ($parameter['type'] === 'file') { + $placeholders[] = '{'.$placeholder.'}'; + if ('file' === $parameter['type']) { $replacements[] = $parameter['path']; } else { $replacements[] = $parameter['name']; diff --git a/lib/Sabre/PostPlugin.php b/lib/Sabre/PostPlugin.php index 5a4b9c3..8fcc9e0 100644 --- a/lib/Sabre/PostPlugin.php +++ b/lib/Sabre/PostPlugin.php @@ -1,45 +1,45 @@ EthswarmService = $service; } - public function initialize(Server $server) - { + public function initialize(Server $server) { $this->server = $server; $this->server->on('method:POST', [$this, 'httpPost']); } - public function httpPost(RequestInterface $request, ResponseInterface $response) - { + public function httpPost(RequestInterface $request, ResponseInterface $response) { $action = $request->getRawServerValue('HTTP_HEJBIT_ACTION') ?? null; - if ($action === 'hide') { + if ('hide' === $action) { $path = $request->getPath(); $node = $this->server->tree->getNodeForPath($path); - if (($node instanceof \OCA\DAV\Connector\Sabre\File)) { + if ($node instanceof File) { $storageid = $node->getFileInfo()->getStorage()->getCache()->getNumericStorageId(); $filename = $node->getFileInfo()->getinternalPath(); } - if (($node instanceof \OCA\DAV\Connector\Sabre\Directory)) { + if ($node instanceof Directory) { $storageid = $node->getFileInfo()->getStorage()->getCache()->getNumericStorageId(); $filename = $node->getFileInfo()->getinternalPath(); } @@ -53,14 +53,14 @@ public function httpPost(RequestInterface $request, ResponseInterface $response) return false; } - else if ($action === 'unhide') { - $path = $request->getPath(); + if ('unhide' === $action) { + $path = $request->getPath(); $node = $this->server->tree->getNodeForPath($path); - if (($node instanceof \OCA\DAV\Connector\Sabre\File)) { + if ($node instanceof File) { $storageid = $node->getFileInfo()->getStorage()->getCache()->getNumericStorageId(); $filename = $node->getFileInfo()->getinternalPath(); } - if (($node instanceof \OCA\DAV\Connector\Sabre\Directory)) { + if ($node instanceof Directory) { $storageid = $node->getFileInfo()->getStorage()->getCache()->getNumericStorageId(); $filename = $node->getFileInfo()->getinternalPath(); } @@ -71,15 +71,15 @@ public function httpPost(RequestInterface $request, ResponseInterface $response) $response->setHeader('Content-Length', '0'); return false; - } - // No Hejbit-action, allow other plugins to handle the request - else if ($action === null) { - return true; - } - // Invalid Hejbit-action, throw exception - else { - $exMessage = 'There was no plugin in the system that was willing to handle a POST method with this action > '.$action.'.'; - throw new \Sabre\DAV\Exception\NotImplemented($exMessage); - } + } + // No Hejbit-action, allow other plugins to handle the request + if (null === $action) { + return true; + } + // Invalid Hejbit-action, throw exception + + $exMessage = 'There was no plugin in the system that was willing to handle a POST method with this action > '.$action.'.'; + + throw new NotImplemented($exMessage); } } diff --git a/lib/Sabre/PropfindPlugin.php b/lib/Sabre/PropfindPlugin.php index 5794984..c4222e4 100755 --- a/lib/Sabre/PropfindPlugin.php +++ b/lib/Sabre/PropfindPlugin.php @@ -1,4 +1,5 @@ . * */ + namespace OCA\Files_External_Ethswarm\Sabre; +use OCA\DAV\Connector\Sabre\Directory; +use OCA\DAV\Connector\Sabre\File; +use OCA\Files_External_Ethswarm\Service\EthswarmService; use Sabre\DAV\INode; use Sabre\DAV\PropFind; use Sabre\DAV\Server; use Sabre\DAV\ServerPlugin; -use OCA\Files_External_Ethswarm\Service\EthswarmService; class PropfindPlugin extends ServerPlugin { public const ETHSWARM_FILEREF = '{http://nextcloud.org/ns}ethswarm-fileref'; @@ -47,66 +51,55 @@ public function initialize(Server $server) { $this->server = $server; $this->server->on('propFind', [$this, 'propFind']); - - } public function propFind(PropFind $propFind, INode $node) { - if (($node instanceof \OCA\DAV\Connector\Sabre\File)) { + if ($node instanceof File) { $storageid = $node->getFileInfo()->getStorage()->getCache()->getNumericStorageId(); $filename = $node->getFileInfo()->getinternalPath(); $mountpoint = $node->getFileInfo()->getMountPoint()->getStorageId(); - if (!str_starts_with($mountpoint, "ethswarm")) { - return ""; + if (!str_starts_with($mountpoint, 'ethswarm')) { + return ''; } $class = $this->EthswarmService; - $propFind->handle(self::ETHSWARM_FILEREF, function () use ($class, $storageid, $filename) - { + $propFind->handle(self::ETHSWARM_FILEREF, function () use ($class, $storageid, $filename) { return $class->getSwarmRef($filename, $storageid); }); - if($class->getVisiblity($filename, $storageid)==1){ - $propFind->set("{http://nextcloud.org/ns}hidden","false",200); - } - else{ - $propFind->set("{http://nextcloud.org/ns}hidden","true",200); + if (1 == $class->getVisiblity($filename, $storageid)) { + $propFind->set('{http://nextcloud.org/ns}hidden', 'false', 200); + } else { + $propFind->set('{http://nextcloud.org/ns}hidden', 'true', 200); } - $propFind->handle(self::ETHSWARM_NODE, function () use ($class, $storageid, $filename) - { - return "true"; + $propFind->handle(self::ETHSWARM_NODE, function () { + return 'true'; }); } - if (($node instanceof \OCA\DAV\Connector\Sabre\Directory)) { + if ($node instanceof Directory) { $storageid = $node->getFileInfo()->getStorage()->getCache()->getNumericStorageId(); $filename = $node->getFileInfo()->getinternalPath(); $mountpoint = $node->getFileInfo()->getMountPoint()->getStorageId(); - if (!str_starts_with($mountpoint, "ethswarm")) { - return ""; + if (!str_starts_with($mountpoint, 'ethswarm')) { + return ''; } $class = $this->EthswarmService; - $propFind->handle(self::ETHSWARM_NODE, function () use ($class, $storageid, $filename) - { - return "true"; + $propFind->handle(self::ETHSWARM_NODE, function () { + return 'true'; }); - if ($filename === "") { - return ""; + if ('' === $filename) { + return ''; } - if($class->getVisiblity($filename, $storageid)==1){ - $propFind->set("{http://nextcloud.org/ns}hidden","false",200); - } - else{ - $propFind->set("{http://nextcloud.org/ns}hidden","true",200); + if (1 == $class->getVisiblity($filename, $storageid)) { + $propFind->set('{http://nextcloud.org/ns}hidden', 'false', 200); + } else { + $propFind->set('{http://nextcloud.org/ns}hidden', 'true', 200); } - - } - } - } diff --git a/lib/Service/EthswarmService.php b/lib/Service/EthswarmService.php index 585b22d..e676f78 100755 --- a/lib/Service/EthswarmService.php +++ b/lib/Service/EthswarmService.php @@ -1,4 +1,5 @@ . * */ + namespace OCA\Files_External_Ethswarm\Service; +use OC; +use OCA\Files_External_Ethswarm\Db\SwarmFileMapper; use OCP\Files\StorageNotAvailableException; use OCP\IDBConnection; -use OCA\Files_External_Ethswarm\Db\SwarmFileMapper; use OCP\IL10N; class EthswarmService { + /** @var IDBConnection */ + protected $dbConnection; /** @var IL10N */ private $l10n; @@ -35,20 +40,16 @@ class EthswarmService { /** @var SwarmFileMapper */ private $filemapper; - /** @var \OCP\IDBConnection */ - protected $dbConnection; - public function __construct(IL10N $l10n) { $this->l10n = $l10n; - $dbConnection = \OC::$server->get(IDBConnection::class); + $dbConnection = OC::$server->get(IDBConnection::class); $this->filemapper = new SwarmFileMapper($dbConnection); } /** - * @param string $filename - * @param int $storageid - * @throws StorageNotAvailableException * @return string + * + * @throws StorageNotAvailableException */ public function getSwarmRef(string $filename, int $storageid) { $swarmFile = $this->filemapper->find($filename, $storageid); @@ -58,12 +59,14 @@ public function getSwarmRef(string $filename, int $storageid) { public function getVisiblity(string $filename, int $storageid) { $swarmFile = $this->filemapper->find($filename, $storageid); + return $swarmFile->getVisibility(); } public function setVisiblity(string $filename, int $storageid, int $visibility) { $swarmFile = $this->filemapper->find($filename, $storageid); $swarmFile->setVisibility($visibility); + return $this->filemapper->update($swarmFile); } diff --git a/lib/Service/NotificationService.php b/lib/Service/NotificationService.php index decde5d..3a972a2 100644 --- a/lib/Service/NotificationService.php +++ b/lib/Service/NotificationService.php @@ -1,10 +1,10 @@ - * * @license GNU AGPL version 3 or any later version * * This program is free software: you can redistribute it and/or modify @@ -19,38 +19,38 @@ * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . - * */ namespace OCA\Files_External_Ethswarm\Service; +use DateTime; use OCA\Files_External_Ethswarm\AppInfo\AppConstants; -use OCP\Notification\IManager; use OCP\IUserManager; use OCP\IUserSession; +use OCP\Notification\IManager; class NotificationService { - private $notificationManager; - private $userManager; + private $notificationManager; + private $userManager; private $userSession; - public function __construct(IManager $notificationManager, IUserManager $userManager, IUserSession $userSession) { - $this->notificationManager = $notificationManager; - $this->userManager = $userManager; + public function __construct(IManager $notificationManager, IUserManager $userManager, IUserSession $userSession) { + $this->notificationManager = $notificationManager; + $this->userManager = $userManager; $this->userSession = $userSession; - } + } - public function sendTemporaryNotification($subject, $path) { - // Create a notification - $notification = $this->notificationManager->createNotification(); - $notification->setApp(AppConstants::APP_NAME); + public function sendTemporaryNotification($subject, $path) { + // Create a notification + $notification = $this->notificationManager->createNotification(); + $notification->setApp(AppConstants::APP_NAME); $userId = $this->userSession->getUser()->getUID(); - $notification->setUser($userId); - $notification->setSubject($subject, ['path' => $path]); - $notification->setObject('temporary', $userId); // Marks the notification as temporary - $notification->setDateTime(new \DateTime()); - - // Send the notification - $this->notificationManager->notify($notification); - } + $notification->setUser($userId); + $notification->setSubject($subject, ['path' => $path]); + $notification->setObject('temporary', $userId); // Marks the notification as temporary + $notification->setDateTime(new DateTime()); + + // Send the notification + $this->notificationManager->notify($notification); + } } diff --git a/lib/Storage/BeeSwarm.php b/lib/Storage/BeeSwarm.php index d471272..3f8d45a 100755 --- a/lib/Storage/BeeSwarm.php +++ b/lib/Storage/BeeSwarm.php @@ -1,9 +1,8 @@ - * * @license GNU AGPL version 3 or any later version * * This program is free software: you can redistribute it and/or modify @@ -18,187 +17,183 @@ * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . - * */ namespace OCA\Files_External_Ethswarm\Storage; -use OCA\Files_External_Ethswarm\AppInfo\AppConstants; +use ArrayIterator; use Exception; -use OC\AppConfig; +use OC; use OC\Files\Cache\Cache; use OC\Files\Storage\Common; +use OC_Helper; +use OCA\Files_External_Ethswarm\AppInfo\AppConstants; +use OCA\Files_External_Ethswarm\Db\SwarmFile; use OCA\Files_External_Ethswarm\Db\SwarmFileMapper; -use OCP\AppFramework\Db\DoesNotExistException; +use OCA\Files_External_Ethswarm\Service\NotificationService; use OCP\Constants; use OCP\Files\Config\IUserMountCache; -use OCP\Files\IMimeTypeLoader; +use OCP\Files\FileInfo; use OCP\Files\IMimeTypeDetector; +use OCP\Files\IMimeTypeLoader; +use OCP\Files\StorageBadConfigException; use OCP\IConfig; use OCP\IDBConnection; -use Sabre\DAV\Exception\BadRequest; use OCP\IL10N; -use OCP\L10N\IFactory as IL10NFactory; -use OCA\Files_External_Ethswarm\Service\NotificationService; +use OCP\ITempManager; use OCP\IUserManager; use OCP\IUserSession; +use OCP\L10N\IFactory as IL10NFactory; use OCP\Notification\IManager; use Psr\Log\LoggerInterface; +use Sabre\DAV\Exception\BadRequest; +use Traversable; - -class BeeSwarm extends Common -{ +class BeeSwarm extends Common { use BeeSwarmTrait; - /** @var int */ protected int $storageId; - /** @var bool */ - private bool $isEncrypted; + protected IDBConnection $dbConnection; - /** @var string */ - protected string $stampBatchId; + protected IL10N $l10n; - /** @var SwarmFileMapper */ - private SwarmFileMapper $filemapper; + protected string $id; - /** @var IConfig */ - private IConfig $config; + private bool $isEncrypted; // TODO: remove - /** @var \OCP\IDBConnection */ - protected IDBConnection $dbConnection; + private SwarmFileMapper $fileMapper; - /** @var \OCP\IL10N */ - protected IL10N $l10n; + private IConfig $config; - /** @var \OCP\Files\IMimeTypeLoader */ private IMimeTypeLoader $mimeTypeHandler; - /** @var \OCP\Files\IMimeTypeDetector */ + private ITempManager $tempManager; + private IMimeTypeDetector $mimeTypeDetector; - /** @var \OC\Files\Cache\Cache */ private Cache $cacheHandler; - /** @var NotificationService */ - private $notificationService; - - /** @var string */ - protected string $id; + private NotificationService $notificationService; - /** @var string */ private string $token; - /** @var LoggerInterface */ private LoggerInterface $logger; - public function __construct($params) - { - /** @var IL10NFactory $l10nFactory */ - $l10nFactory = \OC::$server->get(IL10NFactory::class); - $this->l10n = $l10nFactory->get(AppConstants::APP_NAME); - - $this->notificationService = new NotificationService(\OC::$server->get(IManager::class), \OC::$server->get(IUserManager::class), \OC::$server->get(IUserSession::class)); + /** + * @param mixed $params + * + * @throws StorageBadConfigException + */ + public function __construct($params) { + parent::__construct($params); + // Load storage configuration $this->parseParams($params); - $this->id = 'ethswarm::' . $this->access_key; + $this->id = 'ethswarm::'.$this->access_key; $this->storageId = $this->getStorageCache()->getNumericId(); $this->token = $this->getStorageCache()->getStorageId($this->storageId); - // Load handlers - $dbConnection = \OC::$server->get(IDBConnection::class); - $this->filemapper = new SwarmFileMapper($dbConnection); - $this->mimeTypeHandler = \OC::$server->get(IMimeTypeLoader::class); - $this->mimeTypeDetector = \OC::$server->get(IMimeTypeDetector::class); + // Load handlers and services + $this->tempManager = OC::$server->get(ITempManager::class); + $this->dbConnection = OC::$server->get(IDBConnection::class); + $this->mimeTypeHandler = OC::$server->get(IMimeTypeLoader::class); + $this->dbConnection = OC::$server->get(IDBConnection::class); + $this->mimeTypeHandler = OC::$server->get(IMimeTypeLoader::class); + $this->mimeTypeDetector = OC::$server->get(IMimeTypeDetector::class); + $this->logger = OC::$server->get(LoggerInterface::class); + $mountHandler = OC::$server->get(IUserMountCache::class); + $storageMounts = $mountHandler->getMountsForStorageId($this->storageId); - // Get logger - $this->logger = \OC::$server->get(LoggerInterface::class); + $this->fileMapper = new SwarmFileMapper($this->dbConnection); + + /** @var IL10NFactory $l10nFactory */ + $l10nFactory = OC::$server->get(IL10NFactory::class); + $this->l10n = $l10nFactory->get(AppConstants::APP_NAME); + + $this->notificationService = new NotificationService( + OC::$server->get(IManager::class), + OC::$server->get(IUserManager::class), + OC::$server->get(IUserSession::class) + ); - $mountHandler = \OC::$server->get(IUserMountCache::class); - $storageMounts = $mountHandler->getMountsForStorageId($this->storageId); - $isConfigured = false; if (is_array($storageMounts) && isset($storageMounts[0])) { // Parse array for config of requested storage $storageMount = $storageMounts[0]; $mountId = $storageMount->getMountId(); - $this->config = \OC::$server->get(IConfig::class); - $configSettings = $this->config->getAppValue(AppConstants::APP_NAME, "storageconfig", ""); //default + $this->config = OC::$server->get(IConfig::class); + $configSettings = $this->config->getAppValue(AppConstants::APP_NAME, 'storageconfig'); $mounts = json_decode($configSettings, true); if (is_array($mounts)) { $mountIds = array_column($mounts, 'mount_id'); $key = array_search($mountId, $mountIds); - if (!empty($key) || $key === 0) { - $isConfigured = true; - $this->isEncrypted = $mounts[$key]['encrypt'] == "1" ? true : false; - $this->stampBatchId = $mounts[$key]['batchid']; + if (!empty($key) || 0 === $key) { + $this->isEncrypted = '1' === $mounts[$key]['encrypt']; } } } $this->cacheHandler = new Cache($this); } - public static function checkDependencies() - { - return true; - } - - /** - * @return string - */ - public function getId(): string - { + public function getId(): string { return $this->id; } /** - * @return bool * @throws Exception */ - public function test(): bool - { + public function test(): bool { if (!$this->checkConnection()) { return false; } - $this->filemapper->updateStorageIds($this->token, $this->storageId); - $this->add_rootfolder_cache(); + $this->fileMapper->updateStorageIds($this->token, $this->storageId); + $this->add_root_folder_cache(); $this->add_token_files_cache(); + return true; } - public function copy($path1, $path2) - { + /** + * @param mixed $source + * @param mixed $target + * + * @throws Exception + */ + public function copy($source, $target): bool { try { // Get the source file from the mapper - $sourceFile = $this->filemapper->find($path1, $this->storageId); - if (!$sourceFile) { + $sourceFile = $this->fileMapper->find($source, $this->storageId); + if (!$sourceFile->getFileId()) { $this->logger->error( - 'copy failed: source file not found in mapper ' . $path1, + 'copy failed: source file not found in mapper '.$source, ['app' => AppConstants::APP_NAME] ); + return false; } // Prepare the data for the new file $copyData = []; - $copyData["name"] = $path2; - $copyData["reference"] = $sourceFile->getSwarmReference(); - $copyData["etag"] = null; - $copyData["mimetype"] = $sourceFile->getMimetype(); - $copyData["size"] = $sourceFile->getSize(); - $copyData["storage_mtime"] = time(); - $copyData["storage"] = $this->storageId; - $copyData["token"] = $this->token; + $copyData['name'] = $target; + $copyData['reference'] = $sourceFile->getSwarmReference(); + $copyData['etag'] = null; + $copyData['mimetype'] = $sourceFile->getMimetype(); + $copyData['size'] = $sourceFile->getSize(); + $copyData['storage_mtime'] = time(); + $copyData['storage'] = $this->storageId; + $copyData['token'] = $this->token; // Create the new file entry in the mapper - $newFile = $this->filemapper->createFile($copyData); + $newFile = $this->fileMapper->createFile($copyData); - if (!$newFile) { + if (!$newFile->getFileId()) { $this->logger->error( - 'copy failed: failed to create new file in mapper ' . $path2, + 'copy failed: failed to create new file in mapper '.$target, ['app' => AppConstants::APP_NAME] ); + return false; } @@ -208,9 +203,7 @@ public function copy($path1, $path2) } } - public function add_rootfolder_cache(): bool - { - + public function add_root_folder_cache(): void { $fileData = [ 'storage' => $this->storageId, 'path' => '', @@ -225,19 +218,10 @@ public function add_rootfolder_cache(): bool 'permissions' => (Constants::PERMISSION_ALL - Constants::PERMISSION_DELETE), 'parent' => -1, ]; - - - $fileId = $this->cacheHandler->put($fileData['path'], $fileData); - return true; + $this->cacheHandler->put($fileData['path'], $fileData); } - /** - * @return bool - * @throws Exception - */ - public function add_file_cache($file): bool - { - + public function add_file_cache(SwarmFile $file): bool { $fileData = [ 'storage' => $file->getStorage(), 'path' => $file->getName(), @@ -251,230 +235,191 @@ public function add_file_cache($file): bool 'mtime' => $file->getStorageMtime(), ]; - if ($file->getMimetype() == $this->mimeTypeHandler->getId('httpd/unix-directory')) + if ($file->getMimetype() == $this->mimeTypeHandler->getId('httpd/unix-directory')) { $fileData['permissions'] = (Constants::PERMISSION_ALL - Constants::PERMISSION_DELETE); - else + } else { $fileData['permissions'] = (Constants::PERMISSION_ALL - Constants::PERMISSION_DELETE - Constants::PERMISSION_UPDATE); + } + + $this->cacheHandler->put($fileData['path'], $fileData); - $fileId = $this->cacheHandler->put($fileData['path'], $fileData); return true; } /** - * @return bool * @throws Exception */ - public function add_token_files_cache(): bool - { - - foreach ($this->filemapper->findAllWithToken($this->token) as $file) { - + public function add_token_files_cache(): void { + foreach ($this->fileMapper->findAllWithToken($this->token) as $file) { $this->add_file_cache($file); } - - return true; - } /** - * @param $path - * @return bool + * @param mixed $path + * + * @throws Exception */ - public function file_exists($path): bool - { - if ($path === '' || $path === '/' || $path === '.') { + public function file_exists($path): bool { + if ('' === $path || '/' === $path || '.' === $path) { // Return true always the creation of the root folder return true; } - $exists = $this->filemapper->findExists($path, $this->storageId); - if ($exists == 0) { - return false; - } - return true; + + return $this->fileMapper->findExists($path, $this->storageId) > 0; } - public function filemtime($path) - { - $mtime = 0; - return $mtime; + public function filemtime($path): int { + return 0; } - public function stat($path) - { + /** + * @param mixed $path + * + * @throws Exception + */ + public function stat($path): array|bool { $data = $this->getMetaData($path); - if ($data['mimetype'] === 'httpd/unix-directory') { + if ('httpd/unix-directory' === $data['mimetype']) { return false; } + return [ 'mtime' => $data['mtime'], 'size' => $data['size'], ]; } - /** - * get the ETag for a file or folder - * - * @param string $path - * @return string - */ - public function getETag($path) - { + public function getETag($path): ?string { return null; } - /** - * @return bool - */ - public function needsPartFile() - { + public function needsPartFile(): bool { return false; } - public function mkdir($path): bool - { - $this->filemapper->createDirectory($path, $this->storageId, $this->token); + /** + * @param mixed $path + * + * @throws Exception + */ + public function mkdir($path): bool { + $this->fileMapper->createDirectory($path, $this->storageId, $this->token); + return true; } - public function rmdir($path) - { - + public function rmdir($path): void { + // TODO: Implement rmdir() method. } - public function rename($path1, $path2) - { - $rows = $this->filemapper->getPathTree($path1, $this->storageId); + /** + * @param mixed $source + * @param mixed $target + * + * @throws Exception + */ + public function rename($source, $target): bool { + $rows = $this->fileMapper->getPathTree($source, $this->storageId); foreach ($rows as $row) { - $oldpath = $row->getName(); - $newpath = substr_replace($oldpath, $path2, 0, strlen($path1)); - $updateSwarmTable = $this->filemapper->updatePath($oldpath, $newpath, $this->storageId); + $oldPath = $row->getName(); + $newPath = substr_replace($oldPath, $target, 0, strlen($source)); + $this->fileMapper->updatePath($oldPath, $newPath, $this->storageId); } + return true; } - public function opendir($path) - { + public function opendir($path): bool { return true; } /** - * @return bool + * * {@inheritDoc} + * + * @throws Exception */ - public function is_dir($path) - { - $data = $this->getMetaData($path); - if ($data['mimetype'] === 'httpd/unix-directory') { - return true; - } else { - return false; - } + public function is_dir($path): bool { + return 'httpd/unix-directory' === $this->getMetaData($path)['mimetype']; } /** - * @return bool + * @param mixed $path + * + * @throws Exception */ - public function is_file($path) - { - $data = $this->getMetaData($path); - if ($data['mimetype'] === 'httpd/unix-directory') { - return false; - } - return true; + public function is_file($path): bool { + return 'httpd/unix-directory' !== $this->getMetaData($path)['mimetype']; } - public function filetype($path) - { - if ($this->is_file($path)) { - return 'file'; - } - return 'dir'; + /** + * @param mixed $path + * + * @throws Exception + */ + public function filetype($path): string { + return $this->is_file($path) ? 'file' : 'dir'; } - public function getPermissions($path) - { - return (Constants::PERMISSION_ALL - Constants::PERMISSION_DELETE - Constants::PERMISSION_UPDATE); + public function getPermissions($path = null): int { + return Constants::PERMISSION_ALL - Constants::PERMISSION_DELETE - Constants::PERMISSION_UPDATE; } - public function free_space($path) - { - return \OCP\Files\FileInfo::SPACE_UNLIMITED; + public function free_space($path): false|float|int { + return FileInfo::SPACE_UNLIMITED; } - /** - * @return bool - */ - public function hasUpdated($path, $time) - { + public function hasUpdated($path, $time): bool { return true; } - /** - * @return bool - */ - public function isLocal() - { + public function isLocal(): bool { // the common implementation returns a temporary file by // default, which is not local return false; } - public function setMountOptions(array $options) - { - + public function setMountOptions(array $options): void { + // TODO: Implement setMountOptions() method. } - /** - * @param string $name - * @param mixed $default - * @return mixed - */ - public function getMountOption($name, $default = null) - { - return isset($this->mountOptions[$name]) ? $this->mountOptions[$name] : $default; + public function getMountOption($name, $default = null): ?string { + return $this->mountOptions[$name] ?? $default; } - public function verifyPath($path, $fileName) - { + public function verifyPath($path, $fileName) {} + public function isCreatable($path): bool { + return true; } - /** - * @return bool - */ - public function isCreatable($path) - { + public function isUpdatable($path): bool { return true; } - /** - * @return bool - */ - public function isUpdatable($path) - { + public function unlink($path): bool { return true; } /** - * @return bool + * @param mixed $path + * @param mixed $mode + * + * @throws Exception */ - public function unlink($path) - { - return true; - } - - public function fopen($path, $mode) - { - if ($path === '' || $path === '/' || $path === '.') { + public function fopen($path, $mode) { + if ('' === $path || '/' === $path || '.' === $path) { return false; } - $swarmFile = $this->filemapper->find($path, $this->storageId); + $swarmFile = $this->fileMapper->find($path, $this->storageId); $reference = $swarmFile->getSwarmReference(); switch ($mode) { case 'r': case 'rb': // Get file from swarm - return $this->downloadStream($reference); + return $this->downloadSwarm($reference); + case 'w': // Open for writing only; place the file pointer at the beginning of the file case 'w+': // Open for reading and writing case 'wb': @@ -488,72 +433,60 @@ public function fopen($path, $mode) case 'c': // Open the file for writing only case 'c+': // Open the file for reading and writing; } + return false; } - /** - * @return bool - */ - public function touch($path, $mtime = null) - { + public function touch($path, $mtime = null): bool { return true; } /** - * @param $path - * @return string|false - * @throws DoesNotExistException + * @param mixed $path + * + * @throws Exception */ - public function file_get_contents($path): string|false - { - $swarmFile = $this->filemapper->find($path, $this->storageId); + public function file_get_contents($path): false|string { + $swarmFile = $this->fileMapper->find($path, $this->storageId); $reference = $swarmFile->getSwarmReference(); - return stream_get_contents($this->downloadStream($reference)); - } - - public function file_put_contents($path, $data) - { + return stream_get_contents($this->downloadSwarm($reference)); } - public function getDirectDownload($path) - { + public function file_put_contents($path, $data): false|float|int { + // TODO: Implement file_put_contents() method. + return parent::file_put_contents($path, $data); + } + public function getDirectDownload($path): array|bool { + // TODO: Implement getDirectDownload() method. + return parent::getDirectDownload($path); } /* Enabling this function causes a fatal exception "Call to a member function getId() on null /var/www/html/lib/private/Files/Mount/MountPoint.php - line 276: OC\Files\Cache\Wrapper\CacheWrapper->getId("") - public function getCache($path = '', $storage = null) - { + public function getCache($path = '', $storage = null) + { - } - */ + } + */ /** - * @param string $path - * @return array|null + * @param mixed $path + * + * @throws Exception */ - public function getMetaData($path) - { + public function getMetaData($path): ?array { $data = []; - if ($path === '' || $path === '/' || $path === '.') { - // This creates a root folder for the storage mount. - $data['name'] = ''; - $data['permissions'] = Constants::PERMISSION_ALL; - $data['mimetype'] = 'httpd/unix-directory'; - $data['mtime'] = time(); - $data['storage_mtime'] = time(); - $data['size'] = 0; //unknown - $data['etag'] = null; - } - // If not in swarm table, check if it is a file or directory - $exists = $this->filemapper->findExists($path, $this->storageId) !== 0; + // If not in swarm table, assume it's a folder + $exists = 0 !== $this->fileMapper->findExists($path, $this->storageId); if (!$exists) { // Create a folder item $data['name'] = $path; + // Folder permissions should allow renaming so PERMISSION_UPDATE is included. $data['permissions'] = (Constants::PERMISSION_ALL - Constants::PERMISSION_DELETE); // Check if this is likely a file based on extension - $isFile = pathinfo($path, PATHINFO_EXTENSION) !== ''; + $isFile = '' !== pathinfo($path, PATHINFO_EXTENSION); if ($isFile) { $data['mimetype'] = $this->mimeTypeDetector->detectPath($path); @@ -565,16 +498,16 @@ public function getMetaData($path) } } else { // Get record from table - $swarmFile = $this->filemapper->find($path, $this->storageId); + $swarmFile = $this->fileMapper->find($path, $this->storageId); // Set mimetype as a string, get by using its ID (int) - $mimetypeId = $swarmFile->getMimetype(); - if ($mimetypeId == $this->mimeTypeHandler->getId('httpd/unix-directory')) + $mimeTypeId = $swarmFile->getMimetype(); + if ($mimeTypeId == $this->mimeTypeHandler->getId('httpd/unix-directory')) { $data['permissions'] = (Constants::PERMISSION_ALL - Constants::PERMISSION_DELETE); - else + } else { $data['permissions'] = (Constants::PERMISSION_ALL - Constants::PERMISSION_DELETE - Constants::PERMISSION_UPDATE); - - $data['name'] = basename($path); //TODO: Test - $data['mimetype'] = $this->mimeTypeHandler->getMimetypeById($mimetypeId); + } + $data['name'] = basename($path); // TODO: Test + $data['mimetype'] = $this->mimeTypeHandler->getMimetypeById($mimeTypeId); $data['mtime'] = time(); $data['storage_mtime'] = $swarmFile->getStorageMtime(); $data['size'] = $swarmFile->getSize(); @@ -585,71 +518,68 @@ public function getMetaData($path) return $data; } - public function getDirectoryContent($path): \Traversable - { - $rows = $this->filemapper->getPathTree( - $path, - $this->storageId, - incSelf: false, - recursive: false - ); - $content = array_map(fn($val) => $this->getMetaData($val->getName()), $rows); - - return new \ArrayIterator($content); - } + /** + * @param mixed $directory + * + * @throws Exception + */ + public function getDirectoryContent($directory): Traversable { + $rows = $this->fileMapper->getPathTree($directory, $this->storageId, false, false); + $content = array_map(fn ($val) => $this->getMetaData($val->getName()), $rows); - protected function toTempFile($source) - { - $extension = ''; - $tmpFile = \OC::$server->getTempManager()->getTemporaryFile($extension); - $target = fopen($tmpFile, 'w'); - \OC_Helper::streamCopy($source, $target); - fclose($target); - return $tmpFile; + return new ArrayIterator($content); } - public function writeStream(string $path, $stream, int $size = null): int - { - // Write to temp file - $tmpFile = $this->toTempFile($stream); - $tmpFilesize = (file_exists($tmpFile) ? filesize($tmpFile) : -1); - $mimetype = mime_content_type($tmpFile); - - if (str_ends_with(strtolower($path), '.md')) { - $mimetype = "text/markdown"; - } + /** + * @param resource $stream + * + * @throws Exception + */ + public function writeStream(string $path, $stream, ?int $size = null): int { + // save stream to temp file + $tmpFile = $this->createTempFile($stream); + $tmpFileSize = (file_exists($tmpFile) ? filesize($tmpFile) : -1); + $mimetype = str_ends_with(strtolower($path), '.md') ? 'text/markdown' : mime_content_type($tmpFile); try { - $result = $this->uploadStream($path, $tmpFile, $mimetype, $tmpFilesize); - $reference = (isset($result["reference"]) ? $result['reference'] : null); - - if (!isset($reference)) { - throw new BadRequest("Failed to upload file to " . $this->id . ": " . $result['message']); - } - } catch (\Exception $e) { - throw new \Exception($e->getMessage()); + $reference = $this->uploadSwarm($path, $tmpFile, $mimetype); + } catch (Exception $e) { + throw new BadRequest($e->getMessage()); } finally { fclose($stream); } - // Write metadata to table - $uploadfiles = [ - "name" => $path, - "permissions" => (Constants::PERMISSION_ALL - Constants::PERMISSION_DELETE - Constants::PERMISSION_UPDATE), - "mimetype" => $this->mimeTypeHandler->getId($mimetype), - "mtime" => time(), - "storage_mtime" => time(), - "size" => $tmpFilesize, - "etag" => null, - "reference" => $reference, - "storage" => $this->storageId, - "token" => $this->token, + // save to swarm table + $uploadFiles = [ + 'name' => $path, + 'permissions' => (Constants::PERMISSION_ALL - Constants::PERMISSION_DELETE - Constants::PERMISSION_UPDATE), + 'mimetype' => $this->mimeTypeHandler->getId($mimetype), + 'mtime' => time(), + 'storage_mtime' => time(), + 'size' => $tmpFileSize, + 'etag' => null, + 'reference' => $reference, + 'storage' => $this->storageId, + 'token' => $this->token, ]; - $this->filemapper->createFile($uploadfiles); + $this->fileMapper->createFile($uploadFiles); - $this->notificationService->sendTemporaryNotification("swarm-fileupload", $path); + $this->notificationService->sendTemporaryNotification('swarm-fileupload', $path); - // //TODO: Read back from swarm to return filesize? - return $tmpFilesize; + // TODO: Read back from swarm to return filesize? + return $tmpFileSize; + } + + /** + * @param resource $stream + */ + protected function createTempFile($stream): string { + $extension = ''; + $tmpFile = $this->tempManager->getTemporaryFile($extension); + $target = fopen($tmpFile, 'w'); + OC_Helper::streamCopy($stream, $target); + fclose($target); + + return $tmpFile; } } diff --git a/lib/Storage/BeeSwarmTrait.php b/lib/Storage/BeeSwarmTrait.php index 55d5ab6..c8b5b72 100755 --- a/lib/Storage/BeeSwarmTrait.php +++ b/lib/Storage/BeeSwarmTrait.php @@ -1,9 +1,8 @@ - * * @license GNU AGPL version 3 or any later version * * This program is free software: you can redistribute it and/or modify @@ -18,31 +17,38 @@ * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . - * */ namespace OCA\Files_External_Ethswarm\Storage; +use CURLFile; use OCA\Files_External_Ethswarm\Auth\License; use OCA\Files_External_Ethswarm\Backend\BeeSwarm; +use OCA\Files_External_Ethswarm\Exception\SwarmException; use OCA\Files_External_Ethswarm\Utils\Curl; +use OCP\Files\StorageBadConfigException; +use Safe\Exceptions\CurlException; -trait BeeSwarmTrait -{ +trait BeeSwarmTrait { + private const INFRASTRUCTURE_VERSION_GATEWAY = 1; + private const INFRASTRUCTURE_VERSION_HEJBIT = 2; - /** @var string */ protected string $api_url; - /** @var string */ protected string $access_key; + public function isVersion(int $version = self::INFRASTRUCTURE_VERSION_GATEWAY): bool { + return match ($version) { + self::INFRASTRUCTURE_VERSION_GATEWAY => 'https://license.hejbit.com' === $this->api_url, + self::INFRASTRUCTURE_VERSION_HEJBIT => 'https://license.hejbit.com' !== $this->api_url, + default => false, + }; + } + /** - * @param $params - * @return void - * @throws \Exception + * @throws StorageBadConfigException */ - protected function parseParams($params): void - { + protected function parseParams(array $params): void { $this->validateParams($params); $this->api_url = $params[BeeSwarm::OPTION_HOST_URL]; @@ -50,102 +56,195 @@ protected function parseParams($params): void } /** - * @param array $params - * @return void - * @throws \Exception + * @throws StorageBadConfigException */ - private function validateParams(array &$params): void - { + private function validateParams(array &$params): void { if (!$params[BeeSwarm::OPTION_HOST_URL] || !$params[License::SCHEME_ACCESS_KEY]) { - throw new \Exception('Creating ' . self::class . ' storage failed, required parameters not set'); + throw new StorageBadConfigException('Creating '.self::class.' storage failed, required parameters not set'); } if (!preg_match('/^https?:\/\//i', $params[BeeSwarm::OPTION_HOST_URL])) { - $params[BeeSwarm::OPTION_HOST_URL] = 'https://' . $params[BeeSwarm::OPTION_HOST_URL]; + $params[BeeSwarm::OPTION_HOST_URL] = 'https://'.$params[BeeSwarm::OPTION_HOST_URL]; } if (!filter_var($params[BeeSwarm::OPTION_HOST_URL], FILTER_VALIDATE_URL)) { - throw new \Exception('Creating ' . self::class . ' storage failed, invalid url'); + throw new StorageBadConfigException('Creating '.self::class.' storage failed, invalid url'); } } /** - * @param string $path - * @param string $tmpfile - * @param string $mimetype - * @param int|null $file_size - * @return array|string - * @throws \Safe\Exceptions\CurlException + * @throws CurlException + * @throws SwarmException */ - private function uploadStream(string $path, string $tmpfile, string $mimetype, int $file_size = null) - { - $endpoint = $this->api_url . DIRECTORY_SEPARATOR . 'bzz'; - $params = "?name=" . urlencode(basename($path)); + private function getUploadLink(): string { + $endpoint = $this->api_url.'/api/upload'; + $curl = new Curl($endpoint, authorization: $this->access_key); + $response = $curl->exec(true); - $curl = new Curl($endpoint . $params, [ - CURLOPT_PUT => true, - CURLOPT_CUSTOMREQUEST => "POST", - CURLOPT_POST => true, - CURLOPT_INFILE => fopen($tmpfile, 'r'), - CURLOPT_INFILESIZE => $file_size, - CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, - CURLOPT_VERBOSE => true - ], [ - 'content-type: ' . $mimetype, - 'swarm-pin: true', - 'swarm-redundancy-level: 2', - ], $this->access_key); + if (!$curl->isResponseSuccessful()) { + throw new SwarmException('Failed to connect to HejBit: '.$response['message']); + } + + return $response['url']; + } + + /** + * @throws CurlException + * @throws SwarmException + */ + private function getDownloadLink(string $reference): string { + $endpoint = $this->api_url.'/api/download'; + $curl = new Curl($endpoint, authorization: $this->access_key); + $response = $curl->exec(true); - return $curl->exec(true); + if (!$curl->isResponseSuccessful()) { + throw new SwarmException('Failed to connect to HejBit: '.$response['message']); + } + + return $response['url'].DIRECTORY_SEPARATOR.$reference; + } + + /** + * @throws CurlException|SwarmException + */ + private function uploadSwarm(string $path, string $tempFile, string $mimetype): string { + if ($this->isVersion(self::INFRASTRUCTURE_VERSION_GATEWAY)) { + return $this->uploadSwarmV1($path, $tempFile, $mimetype); + } + + $curl = new Curl($this->getUploadLink(), [ + CURLOPT_CUSTOMREQUEST => 'POST', + CURLOPT_POSTFIELDS => [ + 'file' => new CURLFile($tempFile, $mimetype, basename($path)), + ], + ]); + $response = $curl->exec(true); + + if (!$curl->isResponseSuccessful() || !isset($response['reference'])) { + throw new SwarmException('Failed to upload file to Swarm: '.$response['message']); + } + + return $response['reference']; } /** - * @param string $reference * @return resource - * @throws \Safe\Exceptions\CurlException + * + * @throws CurlException|SwarmException */ - private function downloadStream(string $reference) - { - $endpoint = $this->api_url . DIRECTORY_SEPARATOR . 'bzz' . DIRECTORY_SEPARATOR . $reference . DIRECTORY_SEPARATOR; + private function downloadSwarm(string $reference) { + if ($this->isVersion(self::INFRASTRUCTURE_VERSION_GATEWAY)) { + return $this->downloadSwarmV1($reference); + } + + $curl = new Curl($this->getDownloadLink($reference)); + $response = $curl->exec(); + + if (!$curl->isResponseSuccessful()) { + throw new SwarmException('Failed to download file from Swarm: '.$response['message']); + } + + $stream = fopen('php://memory', 'r+'); + fwrite($stream, $response); + rewind($stream); + + return $stream; + } + + /** + * Returns the connection status of Swarm node. + * + * @throws CurlException|SwarmException + */ + private function checkConnection(): bool { + if ($this->isVersion(self::INFRASTRUCTURE_VERSION_GATEWAY)) { + return $this->checkConnectionV1(); + } + + $endpoint = $this->api_url.'/api/readiness'; + + $curl = new Curl($endpoint, authorization: $this->access_key); + $response = $curl->exec(true); + + if (!$curl->isResponseSuccessful() and !isset($response['status'])) { + throw new SwarmException('Failed to connect to HejBit: '.$response['message']); + } + + return 'ok' === $response['status']; + } + + /** + * @throws CurlException + */ + private function checkConnectionV1(): bool { + $endpoint = $this->api_url.DIRECTORY_SEPARATOR.'readiness'; + + $curl = new Curl($endpoint); + $curl->setAuthorization($this->access_key, CURLAUTH_ANY); + + $output = $curl->exec(); + $httpCode = $curl->getInfo(CURLINFO_HTTP_CODE); + + return 200 === $httpCode and 'OK' === $output; + } + + /** + * @return resource + * + * @throws CurlException|SwarmException + */ + private function downloadSwarmV1(string $reference) { + $endpoint = $this->api_url.DIRECTORY_SEPARATOR.'bzz'.DIRECTORY_SEPARATOR.$reference.DIRECTORY_SEPARATOR; $curl = new Curl($endpoint, [ CURLOPT_FOLLOWLOCATION => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_MAXREDIRS => 10, - CURLOPT_HEADER => true, + CURLOPT_HEADER => false, ], [ 'content-type: application/octet-stream', - ], $this->access_key); + ]); + $curl->setAuthorization($this->access_key, CURLAUTH_ANY); $response = $curl->exec(); $httpCode = $curl->getInfo(CURLINFO_HTTP_CODE); - if ($httpCode !== 200) { - throw new \Exception('Failed to download file from Swarm'); + if (200 !== $httpCode) { + throw new SwarmException('Failed to download file from Swarm'); } - $headerSize = $curl->getInfo(CURLINFO_HEADER_SIZE); - $body = substr($response, $headerSize); - $stream = fopen('php://memory', 'r+'); - fwrite($stream, $body); + fwrite($stream, $response); rewind($stream); + return $stream; } /** - * Returns the connection status of Swarm node - * - * @return bool - * @throws \Exception if connection could not be made + * @throws CurlException|SwarmException */ - private function checkConnection(): bool - { - $endpoint = $this->api_url . DIRECTORY_SEPARATOR . 'readiness'; + private function uploadSwarmV1(string $path, string $tempFile, string $mimetype): array|string { + $endpoint = $this->api_url.DIRECTORY_SEPARATOR.'bzz'; + $params = '?name='.urlencode(basename($path)); - $curl = new Curl($endpoint); - $curl->setAuthorization($this->access_key); + $curl = new Curl($endpoint.$params, [ + CURLOPT_PUT => true, + CURLOPT_CUSTOMREQUEST => 'POST', + CURLOPT_POST => true, + CURLOPT_INFILE => fopen($tempFile, 'r'), + CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, + CURLOPT_VERBOSE => true, + ], [ + 'content-type: '.$mimetype, + 'swarm-pin: true', + 'swarm-redundancy-level: 2', + ]); + $curl->setAuthorization($this->access_key, CURLAUTH_ANY); - $output = $curl->exec(); - $httpCode = $curl->getInfo(CURLINFO_HTTP_CODE); + $result = $curl->exec(true); + $reference = ($result['reference'] ?? null); + + if (!isset($reference)) { + throw new SwarmException('Failed to upload file to '.$this->id.': '.$result['message']); + } - return $httpCode === 200 and $output === 'OK'; + return $reference; } } diff --git a/lib/Utils/Curl.php b/lib/Utils/Curl.php index aec6748..c8d62b5 100644 --- a/lib/Utils/Curl.php +++ b/lib/Utils/Curl.php @@ -5,12 +5,13 @@ use CurlHandle; use Safe\Exceptions\CurlException; -class Curl -{ +class Curl { private const DEFAULT_OPTIONS = [ CURLOPT_MAXREDIRS => 10, CURLOPT_FOLLOWLOCATION => true, CURLOPT_RETURNTRANSFER => true, + CURLOPT_SSL_VERIFYHOST => true, + CURLOPT_SSL_VERIFYPEER => true, ]; protected CurlHandle $handler; @@ -18,106 +19,111 @@ class Curl protected array $options = []; protected array $headers = []; protected ?string $authorization = null; + protected int $authorizationType = CURLAUTH_NONE; - /** - * @param string $url - * @param array $options - * @param array $headers - * @param string|null $authorization - */ - public function __construct(string $url, array $options = [], array $headers = [], ?string $authorization = null) - { + public function __construct(string $url, array $options = [], array $headers = [], ?string $authorization = null) { $this->url = $url; - $this->options = $options + self::DEFAULT_OPTIONS; + $this->options = $options + self::getDefaultOptions(); $this->headers = $headers; - $this->authorization = $authorization; + $this->setAuthorization($authorization); $this->init(); } /** - * initializes a curl handler - * @return void + * set authorization. */ - private function init(): void - { - $this->handler = curl_init(); - curl_setopt($this->handler, CURLOPT_URL, $this->url); + public function setAuthorization(?string $authorization, int $authorizationType = CURLAUTH_BEARER): void { + $this->authorization = $authorization; + if (!$authorization) { + $this->authorizationType = CURLAUTH_NONE; + } else { + $this->authorizationType = $authorizationType; + } } /** - * set curl options + * execute curl request. * - * @param array $options - * @return void + * @throws CurlException */ - private function setOptions(array $options = []): void - { - $options = self::DEFAULT_OPTIONS + $this->options + $options; - curl_setopt_array($this->handler, $options); + public function exec(bool $array = false): array|string { + $this->setOptions(); + $this->setHeaders(); + $response = curl_exec($this->handler); + $this->checkResponse(); + + return $array ? json_decode($response, true) : $response; } /** - * @param array $headers - * @return void + * get curl info. */ - private function setHeaders(array $headers = []): void - { - $headers = $this->headers + $headers; - if ($this->authorization) { - $headers[] = 'Authorization: ' . $this->authorization; + public function getInfo(?int $option = null): mixed { + return curl_getinfo($this->handler, $option); + } + + /** + * @throws CurlException + */ + public function isResponseSuccessful(): bool { + if (0 === $this->getInfo(CURLINFO_HTTP_CODE)) { + throw new CurlException('Curl handler has not been executed'); } - curl_setopt($this->handler, CURLOPT_HTTPHEADER, $headers); + + return 200 === $this->getInfo(CURLINFO_HTTP_CODE) || 201 === $this->getInfo(CURLINFO_HTTP_CODE); + } + + private static function getDefaultOptions(): array { + return self::checkSSLOption() + self::DEFAULT_OPTIONS; } /** - * set authorization - * - * @param string $authorization - * @return void + * @return bool[] */ - public function setAuthorization(string $authorization): void - { - $this->authorization = $authorization; + private static function checkSSLOption(): array { + return [ + CURLOPT_SSL_VERIFYHOST => !Env::isDevelopment(), + CURLOPT_SSL_VERIFYPEER => !Env::isDevelopment(), + ]; } /** - * execute curl request - * - * @param bool $array - * @return string|array - * @throws CurlException + * initializes a curl handler. */ - public function exec(bool $array = false): string|array - { - $this->setOptions(); - $this->setHeaders(); - $response = curl_exec($this->handler); - $this->checkResponse(); - return $array ? json_decode($response, true) : $response; + private function init(): void { + $this->handler = curl_init(); + curl_setopt($this->handler, CURLOPT_URL, $this->url); } /** - * get curl info - * - * @param int|null $option - * @return mixed + * set curl options. */ - public function getInfo(?int $option = null): mixed - { - return curl_getinfo($this->handler, $option); + private function setOptions(array $options = []): void { + $options = self::getDefaultOptions() + $this->options + $options; + curl_setopt_array($this->handler, $options); + } + + private function setHeaders(array $headers = []): void { + $headers = $this->headers + $headers; + if ($this->authorization) { + $headers[] = match ($this->authorizationType) { + CURLAUTH_BEARER => 'Authorization: Bearer '.$this->authorization, + default => 'Authorization: '.$this->authorization + }; + } + curl_setopt($this->handler, CURLOPT_HTTPHEADER, $headers); } /** - * check response results for error + * check response results for error. * - * @return void * @throws CurlException */ - private function checkResponse(): void - { - if (curl_errno($this->handler) !== 0) { + private function checkResponse(): void { + if (0 !== curl_errno($this->handler)) { curl_close($this->handler); + throw new CurlException(curl_error($this->handler)); } } diff --git a/lib/Utils/Env.php b/lib/Utils/Env.php new file mode 100644 index 0000000..c1160b6 --- /dev/null +++ b/lib/Utils/Env.php @@ -0,0 +1,17 @@ + - * * @license GNU AGPL version 3 or any later version * * This program is free software: you can redistribute it and/or modify @@ -18,67 +16,66 @@ * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . - * */ style('files_external_ethswarm', 'settings-admin'); script('files_external_ethswarm', 'settings'); ?>

t('External Storage: Swarm')); ?>

- +

t('View the current status of the Swarm node(s) configured in \'External Storage\' section of NextCloud.')); ?>

- - + + - +
diff --git a/templates/vue-admin-settings.php b/templates/vue-admin-settings.php index dc752dd..73a1fe7 100644 --- a/templates/vue-admin-settings.php +++ b/templates/vue-admin-settings.php @@ -1,11 +1,9 @@ - * * @author Henry Bergström - * * @license GNU AGPL version 3 or any later version * * This program is free software: you can redistribute it and/or modify @@ -20,7 +18,6 @@ * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . - * */ ?>