From e9574c3ebe06ef9ff1ac215d8a64153130ae8cde Mon Sep 17 00:00:00 2001 From: Nicolas Joubert Date: Wed, 23 Oct 2024 10:34:13 +0200 Subject: [PATCH 01/23] #3 Update README. Add docs, CHANGELOG & CONTRIBUTING. --- .gitignore | 7 +++++ CHANGELOG.md | 20 ++++++++++++ CONTRIBUTING.md | 52 +++++++++++++++++++++++++++++++ LICENSE | 2 +- README.md | 20 +++++++++++- docs/index.md | 27 ++++++++++++++++ docs/reference/tasks/_template.md | 44 ++++++++++++++++++++++++++ 7 files changed, 170 insertions(+), 2 deletions(-) create mode 100644 CHANGELOG.md create mode 100644 CONTRIBUTING.md create mode 100644 docs/index.md create mode 100644 docs/reference/tasks/_template.md diff --git a/.gitignore b/.gitignore index ff72e2d..ca08796 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,9 @@ /composer.lock /vendor +.env +.idea +/phpunit.xml +.phpunit.result.cache +.phpunit.cache +.php-cs-fixer.cache +coverage-report diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..9aba0bf --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,20 @@ +v2.0 +------ + +## BC breaks + +### Changes + +### Fixes + +v1.0.1 +------ + +### Fixes + +* Fixed dependencies after removing sidus/base-bundle from the base process bundle + +v1.0.0 +------ + +* Initial release diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..ef0dbe2 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,52 @@ +Contributing +============ + +First of all, **thank you** for contributing, **you are awesome**! + +Here are a few rules to follow in order to ease code reviews, and discussions before +maintainers accept and merge your work. + +You MUST run the quality & test suites. + +You SHOULD write (or update) unit tests. + +You SHOULD write documentation. + +Please, write [commit messages that make sense](https://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html), +and [rebase your branch](https://git-scm.com/book/en/v2/Git-Branching-Rebasing) before submitting your Pull Request. + +One may ask you to [squash your commits](https://gitready.com/advanced/2009/02/10/squashing-commits-with-rebase.html) +too. This is used to "clean" your Pull Request before merging it (we don't want +commits such as `fix tests`, `fix 2`, `fix 3`, etc.). + +Thank you! + +## Running the quality & test suites + +Tests suite uses Docker environments in order to be idempotent to OS's. More than this +PHP version is written inside the Dockerfile; this assures to test the bundle with +the same resources. No need to have PHP installed. + +You only need Docker set it up. + +To allow testing environments more smooth we implemented **Makefile**. +You have two commands available: + +```bash +make quality +``` + +```bash +make tests +``` + +## Deprecations notices + +When a feature should be deprecated, or when you have a breaking change for a future version, please : +* [Fill an issue](https://github.com/cleverage/flysystem-process-bundle/issues/new) +* Add TODO comments with the following format: `@TODO deprecated v2.0` +* Trigger a deprecation error: `@trigger_error('This feature will be deprecated in v2.0', E_USER_DEPRECATED);` + +You can check which deprecation notice is triggered in tests +* `make bash` +* `SYMFONY_DEPRECATIONS_HELPER=0 ./vendor/bin/phpunit` diff --git a/LICENSE b/LICENSE index fdc6131..045d824 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2015-2019 Clever-Age +Copyright (c) Clever-Age Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index c1fa163..ecc0df2 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,22 @@ CleverAge/FlysystemProcessBundle ======================= -See process bundle documentation +This bundle is a part of the [CleverAge/ProcessBundle](https://github.com/cleverage/process-bundle) project. +It provides [Flysystem](https://flysystem.thephpleague.com/docs/) library integration on Process bundle. + +Compatible with [Symfony stable version and latest Long-Term Support (LTS) release](https://symfony.com/releases). + +## Documentation + +For usage documentation, see: +[docs/index.md](doc/index.md) + +## Support & Contribution + +For general support and questions, please use [Github](https://github.com/cleverage/flysystem-process-bundle/issues). +If you think you found a bug or you have a feature idea to propose, feel free to open an issue after looking at the [contributing](CONTRIBUTING.md) guide. + +## License + +This bundle is under the MIT license. +For the whole copyright, see the [LICENSE](LICENSE) file distributed with this source code. diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..2e3c4d2 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,27 @@ +## Prerequisite + +CleverAge/ProcessBundle must be [installed](https://github.com/cleverage/process-bundle/blob/main/docs/01-quick_start.md#installation. + +## Installation + +Make sure Composer is installed globally, as explained in the [installation chapter](https://getcomposer.org/doc/00-intro.md) +of the Composer documentation. + +Open a command console, enter your project directory and install it using composer: + +```bash +composer require cleverage/flysystem-process-bundle +``` + +Remember to add the following line to config/bundles.php (not required if Symfony Flex is used) + +```php +CleverAge\FlysystemProcessBundle\CleverAgeFlysystemProcessBundle::class => ['all' => true], +``` + +## Reference + +- Tasks + - [FileFetchTask] + - [ListContentTask] + - [RemoveFileTask] diff --git a/docs/reference/tasks/_template.md b/docs/reference/tasks/_template.md new file mode 100644 index 0000000..ed1d4a5 --- /dev/null +++ b/docs/reference/tasks/_template.md @@ -0,0 +1,44 @@ +TaskName +======== + +_Describe main goal an use cases of the task_ + +Task reference +-------------- + +* **Service**: `ClassName` + +Accepted inputs +--------------- + +_Description of allowed types_ + +Possible outputs +---------------- + +_Description of possible types_ + +Options +------- + +| Code | Type | Required | Default | Description | +| ---- | ---- | :------: | ------- | ----------- | +| `code` | `type` | **X** _or nothing_ | `default value` _if available_ | _description_ | + +Examples +-------- + +_YAML samples and explanations_ + +* Example 1 + - details + - details + +```yaml +# Task configuration level +code: + service: '@service_ref' + options: + a: 1 + b: 2 +``` From 405f0d99b23859104c3a0342b76282055c1156b7 Mon Sep 17 00:00:00 2001 From: Nicolas Joubert Date: Wed, 23 Oct 2024 12:10:39 +0200 Subject: [PATCH 02/23] #5 Replace "oneup/flysystem-bundle": ">1.0,<4.0" by "league/flysystem-bundle": "^3.0" --- composer.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index a25787b..bbc2183 100644 --- a/composer.json +++ b/composer.json @@ -38,8 +38,9 @@ } }, "require": { - "cleverage/process-bundle": "3.*|dev-v3.0-dev", - "oneup/flysystem-bundle": ">1.0,<4.0", + "php": ">=8.1", + "cleverage/process-bundle": "dev-prepare-release", + "league/flysystem-bundle": "^3.0", "sidus/base-bundle": "~1.0" }, "require-dev": { From 5ffe1994f4d16d6e5b95beecf0ed694c52ddf90f Mon Sep 17 00:00:00 2001 From: Nicolas Joubert Date: Wed, 23 Oct 2024 12:15:08 +0200 Subject: [PATCH 03/23] #5 Update Tasks for "league/flysystem-bundle": "^3.0" --- CHANGELOG.md | 3 ++ Task/FileFetchTask.php | 93 +++++++++------------------------- Task/FilesystemOptionTrait.php | 20 +++----- Task/ListContentTask.php | 50 ++++-------------- Task/RemoveFileTask.php | 37 ++++---------- 5 files changed, 56 insertions(+), 147 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9aba0bf..cccd69e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,9 @@ v2.0 ## BC breaks +* [#5](https://github.com/cleverage/flysystem-process-bundle/issues/5) Replace "oneup/flysystem-bundle": ">1.0,<4.0" by "league/flysystem-bundle": "^3.0" +* [#5](https://github.com/cleverage/flysystem-process-bundle/issues/5) Update Tasks for "league/flysystem-bundle": "^3.0" + ### Changes ### Fixes diff --git a/Task/FileFetchTask.php b/Task/FileFetchTask.php index 422e3a4..8b0b284 100644 --- a/Task/FileFetchTask.php +++ b/Task/FileFetchTask.php @@ -13,69 +13,39 @@ use CleverAge\ProcessBundle\Model\AbstractConfigurableTask; use CleverAge\ProcessBundle\Model\IterableTaskInterface; use CleverAge\ProcessBundle\Model\ProcessState; -use League\Flysystem\FileNotFoundException; -use League\Flysystem\FilesystemInterface; -use League\Flysystem\FilesystemNotFoundException; -use League\Flysystem\MountManager; -use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; -use Symfony\Component\OptionsResolver\Exception\ExceptionInterface; +use League\Flysystem\Filesystem; +use League\Flysystem\FilesystemException; +use League\Flysystem\FilesystemOperator; use Symfony\Component\OptionsResolver\OptionsResolver; /** * Copy (or move) file from one filesystem to another, using Flysystem * Either get files using a file regexp, or take files from input - * - * @author Madeline Veyrenc */ class FileFetchTask extends AbstractConfigurableTask implements IterableTaskInterface { - /** @var MountManager */ - protected $mountManager; - - /** @var FilesystemInterface */ - protected $sourceFS; + protected FilesystemOperator $sourceFS; - /** @var FilesystemInterface */ - protected $destinationFS; + protected FilesystemOperator $destinationFS; - /** @var array */ - protected $matchingFiles = []; + protected array $matchingFiles = []; /** - * @param MountManager|null $mountManager - */ - public function __construct(MountManager $mountManager = null) - { - $this->mountManager = $mountManager; - } - - /** - * @param ProcessState $state - * * @throws \InvalidArgumentException - * @throws ExceptionInterface - * @throws FilesystemNotFoundException */ - public function initialize(ProcessState $state) + public function initialize(ProcessState $state): void { - if (!$this->mountManager) { - throw new ServiceNotFoundException('MountManager service not found, you need to install FlySystemBundle'); - } // Configure options parent::initialize($state); - $this->sourceFS = $this->mountManager->getFilesystem($this->getOption($state, 'source_filesystem')); - $this->destinationFS = $this->mountManager->getFilesystem($this->getOption($state, 'destination_filesystem')); + $this->sourceFS = new Filesystem($this->getOption($state, 'source_filesystem')); + $this->destinationFS = new Filesystem($this->getOption($state, 'destination_filesystem')); } /** - * @param ProcessState $state - * * @throws \InvalidArgumentException - * @throws ExceptionInterface * @throws \UnexpectedValueException - * @throws FilesystemNotFoundException - * @throws FileNotFoundException + * @throws FilesystemException */ public function execute(ProcessState $state): void { @@ -93,15 +63,11 @@ public function execute(ProcessState $state): void } /** - * @param ProcessState $state - * * @throws \UnexpectedValueException - * @throws ExceptionInterface * @throws \InvalidArgumentException - * - * @return bool|mixed + * @throws FilesystemException */ - public function next(ProcessState $state) + public function next(ProcessState $state): bool { $this->findMatchingFiles($state); @@ -113,9 +79,9 @@ public function next(ProcessState $state) * * @throws \UnexpectedValueException * @throws \InvalidArgumentException - * @throws ExceptionInterface + * @throws FilesystemException */ - protected function findMatchingFiles(ProcessState $state) + protected function findMatchingFiles(ProcessState $state): void { $filePattern = $this->getOption($state, 'file_pattern'); if ($filePattern) { @@ -144,45 +110,34 @@ protected function findMatchingFiles(ProcessState $state) } /** - * @param ProcessState $state - * @param string $filename - * @param bool $removeSource - * - * @throws FileNotFoundException - * @throws ExceptionInterface - * @throws FilesystemNotFoundException * @throws \InvalidArgumentException - * - * @return mixed + * @throws FilesystemException */ - protected function doFileCopy(ProcessState $state, $filename, $removeSource) + protected function doFileCopy(ProcessState $state, string $filename, bool $removeSource): bool|string|null { $prefixFrom = $this->getOption($state, 'source_filesystem'); - $prefixTo = $this->getOption($state, 'destination_filesystem'); - $buffer = $this->mountManager->getFilesystem($prefixFrom)->readStream($filename); + $buffer = $this->sourceFS->readStream($filename); - if (false === $buffer) { - return false; + try { + $this->destinationFS->writeStream($filename, $buffer); + $result = true; + } catch (FilesystemException) { + $result = false; } - $result = $this->mountManager->getFilesystem($prefixTo)->putStream($filename, $buffer); - if (\is_resource($buffer)) { fclose($buffer); } if ($removeSource) { - $this->mountManager->delete(sprintf('%s://%s', $prefixFrom, $filename)); + $this->sourceFS->delete(sprintf('%s://%s', $prefixFrom, $filename)); } return $result ? $filename : null; } - /** - * {@inheritdoc} - */ - protected function configureOptions(OptionsResolver $resolver) + protected function configureOptions(OptionsResolver $resolver): void { $resolver->setRequired(['source_filesystem', 'destination_filesystem']); $resolver->setAllowedTypes('source_filesystem', 'string'); diff --git a/Task/FilesystemOptionTrait.php b/Task/FilesystemOptionTrait.php index 27bbdcc..7df98f7 100644 --- a/Task/FilesystemOptionTrait.php +++ b/Task/FilesystemOptionTrait.php @@ -11,7 +11,8 @@ namespace CleverAge\FlysystemProcessBundle\Task; use CleverAge\ProcessBundle\Model\ProcessState; -use League\Flysystem\FilesystemInterface; +use League\Flysystem\Filesystem; +use League\Flysystem\FilesystemOperator; use League\Flysystem\MountManager; use Symfony\Component\OptionsResolver\Options; use Symfony\Component\OptionsResolver\OptionsResolver; @@ -21,29 +22,22 @@ */ trait FilesystemOptionTrait { - protected function configureFilesystemOption(OptionsResolver $resolver, $optionName) + protected function configureFilesystemOption(OptionsResolver $resolver, $optionName): void { $resolver->setRequired($optionName); $resolver->setAllowedTypes($optionName, 'string'); $resolver->setNormalizer($optionName, function (Options $options, $value) { - return $this->getMountManager()->getFilesystem($value); + return new Filesystem($value); }); } - protected function getFilesystem(ProcessState $state, $optionName): FilesystemInterface + protected function getFilesystem(ProcessState $state, $optionName): FilesystemOperator { return $this->getOption($state, $optionName); } - abstract protected function getMountManager(): MountManager; - /** - * @see \CleverAge\ProcessBundle\Model\AbstractConfigurableTask::getOption - * - * @param ProcessState $state - * @param string $code - * - * @return mixed + * @throws \InvalidArgumentException */ - abstract protected function getOption(ProcessState $state, $code); + abstract protected function getOption(ProcessState $state, string $code): mixed; } diff --git a/Task/ListContentTask.php b/Task/ListContentTask.php index c16abc4..3e01285 100644 --- a/Task/ListContentTask.php +++ b/Task/ListContentTask.php @@ -13,8 +13,8 @@ use CleverAge\ProcessBundle\Model\AbstractConfigurableTask; use CleverAge\ProcessBundle\Model\IterableTaskInterface; use CleverAge\ProcessBundle\Model\ProcessState; -use League\Flysystem\FilesystemInterface; -use League\Flysystem\MountManager; +use League\Flysystem\FilesystemException; +use League\Flysystem\FilesystemOperator; use Symfony\Component\OptionsResolver\OptionsResolver; /** @@ -24,23 +24,9 @@ class ListContentTask extends AbstractConfigurableTask implements IterableTaskIn { use FilesystemOptionTrait; - /** @var MountManager */ - protected $mountManager; + protected ?array $fsContent = null; - /** @var array|null */ - protected $fsContent = null; - - /** - * ListContentTask constructor. - * - * @param MountManager $mountManager - */ - public function __construct(MountManager $mountManager) - { - $this->mountManager = $mountManager; - } - - protected function configureOptions(OptionsResolver $resolver) + protected function configureOptions(OptionsResolver $resolver): void { $this->configureFilesystemOption($resolver, 'filesystem'); @@ -49,11 +35,10 @@ protected function configureOptions(OptionsResolver $resolver) } /** - * @param ProcessState $state - * - * @throws \Symfony\Component\OptionsResolver\Exception\ExceptionInterface + * @throws \InvalidArgumentException + * @throws FilesystemException */ - public function execute(ProcessState $state) + public function execute(ProcessState $state): void { if ($this->fsContent === null || key($this->fsContent) === null) { $filesystem = $this->getFilesystem($state, 'filesystem'); @@ -70,7 +55,7 @@ public function execute(ProcessState $state) } } - public function next(ProcessState $state) + public function next(ProcessState $state): bool { if (!is_array($this->fsContent)) { return false; @@ -81,17 +66,13 @@ public function next(ProcessState $state) return key($this->fsContent) !== null; } - /** - * @param FilesystemInterface $filesystem - * @param string|null $pattern - * - * @return array + * @throws FilesystemException */ - protected function getFilteredFilesystemContents(FilesystemInterface $filesystem, $pattern = null): array + protected function getFilteredFilesystemContents(FilesystemOperator $filesystem, string $pattern = null): array { $results = []; - foreach ($filesystem->listContents() as $item) { + foreach ($filesystem->listContents('') as $item) { if ($pattern === null || \preg_match($pattern, $item['path'])) { $results[] = $item; } @@ -99,13 +80,4 @@ protected function getFilteredFilesystemContents(FilesystemInterface $filesystem return $results; } - - /** - * @return MountManager - */ - protected function getMountManager(): MountManager - { - return $this->mountManager; - } - } diff --git a/Task/RemoveFileTask.php b/Task/RemoveFileTask.php index 68ed0e3..e001ce2 100644 --- a/Task/RemoveFileTask.php +++ b/Task/RemoveFileTask.php @@ -12,7 +12,7 @@ use CleverAge\ProcessBundle\Model\AbstractConfigurableTask; use CleverAge\ProcessBundle\Model\ProcessState; -use League\Flysystem\MountManager; +use League\Flysystem\FilesystemException; use Psr\Log\LoggerInterface; use Symfony\Component\OptionsResolver\OptionsResolver; @@ -23,46 +23,31 @@ class RemoveFileTask extends AbstractConfigurableTask { use FilesystemOptionTrait; - /** @var MountManager */ - protected $mountManager; - - /** @var LoggerInterface */ - protected $logger; - - /** - * RemoveFileTask constructor. - * - * @param MountManager $mountManager - * @param LoggerInterface $logger - */ - public function __construct(MountManager $mountManager, LoggerInterface $logger) + public function __construct(protected LoggerInterface $logger) { - $this->mountManager = $mountManager; - $this->logger = $logger; } - protected function configureOptions(OptionsResolver $resolver) + protected function configureOptions(OptionsResolver $resolver): void { $this->configureFilesystemOption($resolver, 'filesystem'); } - public function execute(ProcessState $state) + public function execute(ProcessState $state): void { $filesystem = $this->getFilesystem($state, 'filesystem'); $filePath = $state->getInput(); - $success = $filesystem->delete($filePath); + try { + $filesystem->delete($filePath); + $result = true; + } catch (FilesystemException) { + $result = false; + } - if ($success) { + if ($result) { $this->logger->info('Deleted input file', ['file' => $filePath]); } else { $this->logger->warning('Failed to deleted input file', ['file' => $filePath]); } } - - protected function getMountManager(): MountManager - { - return $this->mountManager; - } - } From cac3d6e871eebfa73106d3d43d44cfa267aba0a3 Mon Sep 17 00:00:00 2001 From: Nicolas Joubert Date: Wed, 23 Oct 2024 12:22:02 +0200 Subject: [PATCH 04/23] #3 Add Makefile & .docker for local standalone usage. Add rector, phpstan & php-cs-fixer configurations --- .docker/compose.yaml | 14 ++++++++++ .docker/php/Dockerfile | 29 ++++++++++++++++++++ .docker/php/conf.d/dev.ini | 5 ++++ .php-cs-fixer.dist.php | 46 ++++++++++++++++++++++++++++++++ CHANGELOG.md | 3 +++ Makefile | 54 ++++++++++++++++++++++++++++++++++++++ composer.json | 17 +++++++++++- phpstan.neon | 18 +++++++++++++ phpunit.xml.dist | 27 +++++++++++++++++++ rector.php | 30 +++++++++++++++++++++ tests/.gitkeep | 0 11 files changed, 242 insertions(+), 1 deletion(-) create mode 100644 .docker/compose.yaml create mode 100644 .docker/php/Dockerfile create mode 100644 .docker/php/conf.d/dev.ini create mode 100644 .php-cs-fixer.dist.php create mode 100644 Makefile create mode 100644 phpstan.neon create mode 100644 phpunit.xml.dist create mode 100644 rector.php create mode 100644 tests/.gitkeep diff --git a/.docker/compose.yaml b/.docker/compose.yaml new file mode 100644 index 0000000..d273ca0 --- /dev/null +++ b/.docker/compose.yaml @@ -0,0 +1,14 @@ +x-build-args: &build-args + UID: "${UID:-1000}" + GID: "${GID:-1000}" + +name: cleverage-flysystem-process-bundle + +services: + php: + build: + context: php + args: + <<: *build-args + volumes: + - ../:/var/www diff --git a/.docker/php/Dockerfile b/.docker/php/Dockerfile new file mode 100644 index 0000000..f98c3ba --- /dev/null +++ b/.docker/php/Dockerfile @@ -0,0 +1,29 @@ +FROM php:8.2-fpm-alpine + +ARG UID +ARG GID + +RUN mv "$PHP_INI_DIR/php.ini-development" "$PHP_INI_DIR/php.ini" +COPY /conf.d/ "$PHP_INI_DIR/conf.d/" + +RUN apk update && apk add \ + tzdata \ + shadow \ + nano \ + bash \ + icu-dev \ + && docker-php-ext-configure intl \ + && docker-php-ext-install intl opcache \ + && docker-php-ext-enable opcache + +RUN ln -s /usr/share/zoneinfo/Europe/Paris /etc/localtime \ + && sed -i "s/^;date.timezone =.*/date.timezone = Europe\/Paris/" $PHP_INI_DIR/php.ini + +COPY --from=composer:2 /usr/bin/composer /usr/bin/composer + +RUN usermod -u $UID www-data \ + && groupmod -g $GID www-data + +USER www-data:www-data + +WORKDIR /var/www diff --git a/.docker/php/conf.d/dev.ini b/.docker/php/conf.d/dev.ini new file mode 100644 index 0000000..2a141be --- /dev/null +++ b/.docker/php/conf.d/dev.ini @@ -0,0 +1,5 @@ +display_errors = 1 +error_reporting = E_ALL + +opcache.validate_timestamps = 1 +opcache.revalidate_freq = 0 diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php new file mode 100644 index 0000000..5ed013e --- /dev/null +++ b/.php-cs-fixer.dist.php @@ -0,0 +1,46 @@ +setRules([ + '@PHP71Migration' => true, + '@PHP82Migration' => true, + '@PHPUnit75Migration:risky' => true, + '@Symfony' => true, + '@Symfony:risky' => true, + 'protected_to_private' => false, + 'native_constant_invocation' => ['strict' => false], + 'header_comment' => ['header' => $fileHeaderComment], + 'modernize_strpos' => true, + 'get_class_to_class_keyword' => true, + ]) + ->setRiskyAllowed(true) + ->setFinder( + (new PhpCsFixer\Finder()) + ->in(__DIR__.'/src') + ->in(__DIR__.'/tests') + ->append([__FILE__]) + ) + ->setCacheFile('.php-cs-fixer.cache') +; diff --git a/CHANGELOG.md b/CHANGELOG.md index cccd69e..0e03d8f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,9 @@ v2.0 ### Changes +* [#3](https://github.com/cleverage/flysystem-process-bundle/issues/3) Add Makefile & .docker for local standalone usage +* [#3](https://github.com/cleverage/flysystem-process-bundle/issues/3) Add rector, phpstan & php-cs-fixer configurations & apply it + ### Fixes v1.0.1 diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..0a58e32 --- /dev/null +++ b/Makefile @@ -0,0 +1,54 @@ +.ONESHELL: +SHELL := /bin/bash + +DOCKER_RUN_PHP = docker compose -f .docker/compose.yaml run --rm php "bash" "-c" +DOCKER_COMPOSE = docker compose -f .docker/compose.yaml + +start: upd #[Global] Start application + +src/vendor: #[Composer] install dependencies + $(DOCKER_RUN_PHP) "composer install --no-interaction" + +upd: #[Docker] Start containers detached + touch .docker/.env + make src/vendor + $(DOCKER_COMPOSE) up --remove-orphans --detach + +up: #[Docker] Start containers + touch .docker/.env + make src/vendor + $(DOCKER_COMPOSE) up --remove-orphans + +stop: #[Docker] Down containers + $(DOCKER_COMPOSE) stop + +down: #[Docker] Down containers + $(DOCKER_COMPOSE) down + +build: #[Docker] Build containers + $(DOCKER_COMPOSE) build + +ps: # [Docker] Show running containers + $(DOCKER_COMPOSE) ps + +bash: #[Docker] Connect to php container with current host user + $(DOCKER_COMPOSE) exec php bash + +logs: #[Docker] Show logs + $(DOCKER_COMPOSE) logs -f + +quality: phpstan php-cs-fixer rector #[Quality] Run all quality checks + +phpstan: #[Quality] Run PHPStan + $(DOCKER_RUN_PHP) "vendor/bin/phpstan --no-progress --memory-limit=1G analyse" + +php-cs-fixer: #[Quality] Run PHP-CS-Fixer + $(DOCKER_RUN_PHP) "vendor/bin/php-cs-fixer fix --diff --verbose" + +rector: #[Quality] Run Rector + $(DOCKER_RUN_PHP) "vendor/bin/rector" + +tests: phpunit #[Tests] Run all tests + +phpunit: #[Tests] Run PHPUnit + $(DOCKER_RUN_PHP) "vendor/bin/phpunit" diff --git a/composer.json b/composer.json index bbc2183..1527884 100644 --- a/composer.json +++ b/composer.json @@ -44,6 +44,21 @@ "sidus/base-bundle": "~1.0" }, "require-dev": { - "phpunit/phpunit": "~6.4" + "friendsofphp/php-cs-fixer": "*", + "phpstan/extension-installer": "*", + "phpstan/phpstan": "*", + "phpstan/phpstan-symfony": "*", + "phpunit/phpunit": "*", + "rector/rector": "*", + "roave/security-advisories": "dev-latest", + "symfony/test-pack": "^1.1" + }, + "config": { + "allow-plugins": { + "phpstan/extension-installer": true, + "symfony/flex": true, + "symfony/runtime": true + }, + "sort-packages": true } } diff --git a/phpstan.neon b/phpstan.neon new file mode 100644 index 0000000..30e9572 --- /dev/null +++ b/phpstan.neon @@ -0,0 +1,18 @@ +parameters: + level: 6 + paths: + - src + - tests + ignoreErrors: + - '#type has no value type specified in iterable type#' + - '#has parameter .* with no value type specified in iterable type#' + - '#has no value type specified in iterable type array#' + - '#configureOptions\(\) has no return type specified.#' + - '#configure\(\) has no return type specified#' + - '#process\(\) has no return type specified#' + - '#should return Iterator but returns Traversable#' + - '#Negated boolean expression is always false#' + checkGenericClassInNonGenericObjectType: false + reportUnmatchedIgnoredErrors: false + inferPrivatePropertyTypeFromConstructor: true + treatPhpDocTypesAsCertain: false diff --git a/phpunit.xml.dist b/phpunit.xml.dist new file mode 100644 index 0000000..766495c --- /dev/null +++ b/phpunit.xml.dist @@ -0,0 +1,27 @@ + + + + + tests + + + + + + src + + + diff --git a/rector.php b/rector.php new file mode 100644 index 0000000..72a2408 --- /dev/null +++ b/rector.php @@ -0,0 +1,30 @@ +withPhpVersion(PhpVersion::PHP_82) + ->withPaths([ + __DIR__.'/src', + __DIR__.'/tests', + ]) + ->withPhpSets(php82: true) + // here we can define, what prepared sets of rules will be applied + ->withPreparedSets( + deadCode: true, + codeQuality: true + ) + ->withSets([ + LevelSetList::UP_TO_PHP_82, + SymfonySetList::SYMFONY_64, + SymfonySetList::SYMFONY_71, + SymfonySetList::SYMFONY_CODE_QUALITY, + SymfonySetList::SYMFONY_CONSTRUCTOR_INJECTION, + SymfonySetList::ANNOTATIONS_TO_ATTRIBUTES, + ]) +; diff --git a/tests/.gitkeep b/tests/.gitkeep new file mode 100644 index 0000000..e69de29 From c0cf2d3e89f849fdc29ab502eeb4dd5cab19bd95 Mon Sep 17 00:00:00 2001 From: Nicolas Joubert Date: Wed, 23 Oct 2024 12:23:25 +0200 Subject: [PATCH 05/23] #3 Add notifications, quality & test github workflows --- .github/ISSUE_TEMPLATE.md | 14 ++++++ .github/PULL_REQUEST_TEMPLATE.md | 14 ++++++ .github/workflows/notifications.yml | 23 +++++++++ .github/workflows/quality.yml | 62 ++++++++++++++++++++++++ .github/workflows/test.yml | 74 +++++++++++++++++++++++++++++ 5 files changed, 187 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE.md create mode 100644 .github/PULL_REQUEST_TEMPLATE.md create mode 100644 .github/workflows/notifications.yml create mode 100644 .github/workflows/quality.yml create mode 100644 .github/workflows/test.yml diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 0000000..7711713 --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,14 @@ +## Description + + + +## Requirements + +* Documentation updates + - [ ] Reference + - [ ] Changelog +* [ ] Unit tests + +## Breaking changes + + diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..58db37d --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,14 @@ +## Description + + + +## Requirements + +* Documentation updates + - [ ] Reference + - [ ] Changelog +* [ ] Unit tests + +## Breaking changes + + diff --git a/.github/workflows/notifications.yml b/.github/workflows/notifications.yml new file mode 100644 index 0000000..c9cd06b --- /dev/null +++ b/.github/workflows/notifications.yml @@ -0,0 +1,23 @@ +name: Rocket chat notifications + +# Controls when the action will run. +on: + push: + tags: + - '*' + +jobs: + notification: + runs-on: ubuntu-latest + + steps: + - name: Get the tag short reference + id: get_tag + run: echo "TAG=${GITHUB_REF/refs\/tags\//}" >> $GITHUB_OUTPUT + + - name: Rocket.Chat Notification + uses: madalozzo/Rocket.Chat.GitHub.Action.Notification@master + with: + type: success + job_name: "[cleverage/flysystem-process-bundle](https://github.com/cleverage/flysystem-process-bundle) : ${{ steps.get_tag.outputs.TAG }} has been released" + url: ${{ secrets.CLEVER_AGE_ROCKET_CHAT_WEBOOK_URL }} diff --git a/.github/workflows/quality.yml b/.github/workflows/quality.yml new file mode 100644 index 0000000..9f1580f --- /dev/null +++ b/.github/workflows/quality.yml @@ -0,0 +1,62 @@ +name: Quality + +on: + push: + branches: + - main + pull_request: + +permissions: + contents: read + +jobs: + phpstan: + name: PHPStan + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Install PHP with extensions + uses: shivammathur/setup-php@v2 + with: + php-version: '8.2' + coverage: none + tools: composer:v2 + - name: Install Composer dependencies (locked) + uses: ramsey/composer-install@v3 + - name: PHPStan + run: vendor/bin/phpstan --no-progress --memory-limit=1G analyse --error-format=github + + php-cs-fixer: + name: PHP-CS-Fixer + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Install PHP with extensions + uses: shivammathur/setup-php@v2 + with: + php-version: '8.2' + coverage: none + tools: composer:v2 + - name: Install Composer dependencies (locked) + uses: ramsey/composer-install@v3 + - name: PHP-CS-Fixer + run: vendor/bin/php-cs-fixer fix --diff --dry-run --show-progress=none + + rector: + name: Rector + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + - name: Install PHP with extensions + uses: shivammathur/setup-php@v2 + with: + php-version: '8.2' + coverage: none + tools: composer:v2 + - name: Install Composer dependencies (locked) + uses: ramsey/composer-install@v3 + - name: Rector + run: vendor/bin/rector --no-progress-bar --dry-run diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..2d7e7a4 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,74 @@ +name: Test + +on: + push: + branches: + - main + pull_request: + +permissions: + contents: read + +jobs: + test: + name: PHP ${{ matrix.php-version }} + ${{ matrix.dependencies }} + ${{ matrix.variant }} + runs-on: ubuntu-latest + continue-on-error: ${{ matrix.allowed-to-fail }} + env: + SYMFONY_REQUIRE: ${{matrix.symfony-require}} + + strategy: + matrix: + php-version: + - '8.2' + - '8.3' + dependencies: [highest] + allowed-to-fail: [false] + symfony-require: [''] + variant: [normal] + include: + - php-version: '8.2' + dependencies: highest + allowed-to-fail: false + symfony-require: 6.4.* + variant: symfony/symfony:"6.4.*" + - php-version: '8.2' + dependencies: highest + allowed-to-fail: false + symfony-require: 7.1.* + variant: symfony/symfony:"7.1.*" + - php-version: '8.3' + dependencies: highest + allowed-to-fail: false + symfony-require: 6.4.* + variant: symfony/symfony:"6.4.*" + - php-version: '8.3' + dependencies: highest + allowed-to-fail: false + symfony-require: 7.1.* + variant: symfony/symfony:"7.1.*" + + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Install PHP with extensions + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-version }} + coverage: pcov + tools: composer:v2, flex + - name: Add PHPUnit matcher + run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json" + - name: Install variant + if: matrix.variant != 'normal' && !startsWith(matrix.variant, 'symfony/symfony') + run: composer require ${{ matrix.variant }} --no-update + - name: Install Composer dependencies (${{ matrix.dependencies }}) + uses: ramsey/composer-install@v3 + with: + dependency-versions: ${{ matrix.dependencies }} + - name: Run Tests with coverage + run: vendor/bin/phpunit -c phpunit.xml.dist --coverage-clover build/logs/clover.xml + #- name: Send coverage to Codecov + # uses: codecov/codecov-action@v4 + # with: + # files: build/logs/clover.xml From 8da051f28d14a0472fd5f3e03b283cde2a8577aa Mon Sep 17 00:00:00 2001 From: Nicolas Joubert Date: Wed, 23 Oct 2024 12:29:25 +0200 Subject: [PATCH 06/23] #3 Update directory structure with code on /src --- composer.json | 7 ++++++- .../CleverAgeFlysystemProcessExtension.php | 0 {Resources => src/Resources}/config/services/task.yml | 0 {Task => src/Task}/FileFetchTask.php | 0 {Task => src/Task}/FilesystemOptionTrait.php | 1 - {Task => src/Task}/ListContentTask.php | 0 {Task => src/Task}/RemoveFileTask.php | 0 7 files changed, 6 insertions(+), 2 deletions(-) rename {DependencyInjection => src/DependencyInjection}/CleverAgeFlysystemProcessExtension.php (100%) rename {Resources => src/Resources}/config/services/task.yml (100%) rename {Task => src/Task}/FileFetchTask.php (100%) rename {Task => src/Task}/FilesystemOptionTrait.php (97%) rename {Task => src/Task}/ListContentTask.php (100%) rename {Task => src/Task}/RemoveFileTask.php (100%) diff --git a/composer.json b/composer.json index 1527884..f2e8375 100644 --- a/composer.json +++ b/composer.json @@ -34,7 +34,12 @@ ], "autoload": { "psr-4": { - "CleverAge\\FlysystemProcessBundle\\": "" + "CleverAge\\FlysystemProcessBundle\\": "src/" + } + }, + "autoload-dev": { + "psr-4": { + "CleverAge\\FlysystemProcessBundle\\Tests\\": "tests/" } }, "require": { diff --git a/DependencyInjection/CleverAgeFlysystemProcessExtension.php b/src/DependencyInjection/CleverAgeFlysystemProcessExtension.php similarity index 100% rename from DependencyInjection/CleverAgeFlysystemProcessExtension.php rename to src/DependencyInjection/CleverAgeFlysystemProcessExtension.php diff --git a/Resources/config/services/task.yml b/src/Resources/config/services/task.yml similarity index 100% rename from Resources/config/services/task.yml rename to src/Resources/config/services/task.yml diff --git a/Task/FileFetchTask.php b/src/Task/FileFetchTask.php similarity index 100% rename from Task/FileFetchTask.php rename to src/Task/FileFetchTask.php diff --git a/Task/FilesystemOptionTrait.php b/src/Task/FilesystemOptionTrait.php similarity index 97% rename from Task/FilesystemOptionTrait.php rename to src/Task/FilesystemOptionTrait.php index 7df98f7..243150d 100644 --- a/Task/FilesystemOptionTrait.php +++ b/src/Task/FilesystemOptionTrait.php @@ -13,7 +13,6 @@ use CleverAge\ProcessBundle\Model\ProcessState; use League\Flysystem\Filesystem; use League\Flysystem\FilesystemOperator; -use League\Flysystem\MountManager; use Symfony\Component\OptionsResolver\Options; use Symfony\Component\OptionsResolver\OptionsResolver; diff --git a/Task/ListContentTask.php b/src/Task/ListContentTask.php similarity index 100% rename from Task/ListContentTask.php rename to src/Task/ListContentTask.php diff --git a/Task/RemoveFileTask.php b/src/Task/RemoveFileTask.php similarity index 100% rename from Task/RemoveFileTask.php rename to src/Task/RemoveFileTask.php From c9bc1c4765d9e7ea2633f29d8cd9e65ba6dc502c Mon Sep 17 00:00:00 2001 From: Nicolas Joubert Date: Wed, 23 Oct 2024 12:34:21 +0200 Subject: [PATCH 07/23] #3 Apply phpstan, php-cs-fixer & rector rules --- .php-cs-fixer.dist.php | 2 +- .../CleverAgeFlysystemProcessExtension.php | 9 +++++--- src/Task/FileFetchTask.php | 17 +++++++------- src/Task/FilesystemOptionTrait.php | 19 +++++++-------- src/Task/ListContentTask.php | 23 +++++++++++-------- src/Task/RemoveFileTask.php | 11 +++++---- 6 files changed, 46 insertions(+), 35 deletions(-) diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php index 5ed013e..58730f9 100644 --- a/.php-cs-fixer.dist.php +++ b/.php-cs-fixer.dist.php @@ -1,7 +1,7 @@ sourceFS->listContents('/') as $file) { if ('file' === $file['type'] - && preg_match($filePattern, $file['path']) + && preg_match($filePattern, (string) $file['path']) && !\in_array($file['path'], $this->matchingFiles, true)) { $this->matchingFiles[] = $file['path']; } @@ -131,7 +132,7 @@ protected function doFileCopy(ProcessState $state, string $filename, bool $remov } if ($removeSource) { - $this->sourceFS->delete(sprintf('%s://%s', $prefixFrom, $filename)); + $this->sourceFS->delete(\sprintf('%s://%s', $prefixFrom, $filename)); } return $result ? $filename : null; diff --git a/src/Task/FilesystemOptionTrait.php b/src/Task/FilesystemOptionTrait.php index 243150d..ac2f66f 100644 --- a/src/Task/FilesystemOptionTrait.php +++ b/src/Task/FilesystemOptionTrait.php @@ -1,8 +1,11 @@ -setRequired($optionName); $resolver->setAllowedTypes($optionName, 'string'); - $resolver->setNormalizer($optionName, function (Options $options, $value) { - return new Filesystem($value); - }); + $resolver->setNormalizer($optionName, fn (Options $options, $value) => new Filesystem($value)); } - protected function getFilesystem(ProcessState $state, $optionName): FilesystemOperator + protected function getFilesystem(ProcessState $state, string $optionName): FilesystemOperator { return $this->getOption($state, $optionName); } diff --git a/src/Task/ListContentTask.php b/src/Task/ListContentTask.php index 3e01285..419cf53 100644 --- a/src/Task/ListContentTask.php +++ b/src/Task/ListContentTask.php @@ -1,8 +1,11 @@ -fsContent === null || key($this->fsContent) === null) { + if (null === $this->fsContent || null === key($this->fsContent)) { $filesystem = $this->getFilesystem($state, 'filesystem'); $pattern = $this->getOption($state, 'file_pattern'); $this->fsContent = $this->getFilteredFilesystemContents($filesystem, $pattern); } - if (key($this->fsContent) === null) { + if (null === key($this->fsContent)) { $state->setSkipped(true); $this->fsContent = null; } else { @@ -57,23 +60,23 @@ public function execute(ProcessState $state): void public function next(ProcessState $state): bool { - if (!is_array($this->fsContent)) { + if (!\is_array($this->fsContent)) { return false; } next($this->fsContent); - return key($this->fsContent) !== null; + return null !== key($this->fsContent); } /** * @throws FilesystemException */ - protected function getFilteredFilesystemContents(FilesystemOperator $filesystem, string $pattern = null): array + protected function getFilteredFilesystemContents(FilesystemOperator $filesystem, ?string $pattern = null): array { $results = []; foreach ($filesystem->listContents('') as $item) { - if ($pattern === null || \preg_match($pattern, $item['path'])) { + if (null === $pattern || preg_match($pattern, (string) $item['path'])) { $results[] = $item; } } diff --git a/src/Task/RemoveFileTask.php b/src/Task/RemoveFileTask.php index e001ce2..b69b9b7 100644 --- a/src/Task/RemoveFileTask.php +++ b/src/Task/RemoveFileTask.php @@ -1,8 +1,11 @@ - Date: Wed, 23 Oct 2024 14:03:46 +0200 Subject: [PATCH 08/23] #4 Remove `sidus/base-bundle` dependency --- CHANGELOG.md | 1 + composer.json | 3 +- .../CleverAgeFlysystemProcessExtension.php | 32 +++++++++++++++---- .../config/services/{task.yml => task.yaml} | 0 4 files changed, 27 insertions(+), 9 deletions(-) rename src/Resources/config/services/{task.yml => task.yaml} (100%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0e03d8f..8514cbb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ v2.0 * [#3](https://github.com/cleverage/flysystem-process-bundle/issues/3) Add Makefile & .docker for local standalone usage * [#3](https://github.com/cleverage/flysystem-process-bundle/issues/3) Add rector, phpstan & php-cs-fixer configurations & apply it +* [#4](https://github.com/cleverage/flysystem-process-bundle/issues/4) Remove `sidus/base-bundle` dependency ### Fixes diff --git a/composer.json b/composer.json index f2e8375..ff9025f 100644 --- a/composer.json +++ b/composer.json @@ -45,8 +45,7 @@ "require": { "php": ">=8.1", "cleverage/process-bundle": "dev-prepare-release", - "league/flysystem-bundle": "^3.0", - "sidus/base-bundle": "~1.0" + "league/flysystem-bundle": "^3.0" }, "require-dev": { "friendsofphp/php-cs-fixer": "*", diff --git a/src/DependencyInjection/CleverAgeFlysystemProcessExtension.php b/src/DependencyInjection/CleverAgeFlysystemProcessExtension.php index 799ccdf..50bf63a 100644 --- a/src/DependencyInjection/CleverAgeFlysystemProcessExtension.php +++ b/src/DependencyInjection/CleverAgeFlysystemProcessExtension.php @@ -13,17 +13,35 @@ namespace CleverAge\FlysystemProcessBundle\DependencyInjection; -use Sidus\BaseBundle\DependencyInjection\SidusBaseExtension; +use Symfony\Component\Config\FileLocator; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Extension\Extension; +use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; +use Symfony\Component\Finder\Finder; /** * This is the class that loads and manages your bundle configuration. * - * @see http://symfony.com/doc/current/cookbook/bundles/extension.html - * - * @author Valentin Clavreul - * @author Vincent Chalnot - * @author Madeline Veyrenc + * @see http://symfony.com/doc/current/cookbook/bundles/extension.html */ -class CleverAgeFlysystemProcessExtension extends SidusBaseExtension +class CleverAgeFlysystemProcessExtension extends Extension { + public function load(array $configs, ContainerBuilder $container): void + { + $this->findServices($container, __DIR__.'/../Resources/config/services'); + } + + /** + * Recursively import config files into container. + */ + protected function findServices(ContainerBuilder $container, string $path, string $extension = 'yaml'): void + { + $finder = new Finder(); + $finder->in($path) + ->name('*.'.$extension)->files(); + $loader = new YamlFileLoader($container, new FileLocator($path)); + foreach ($finder as $file) { + $loader->load($file->getFilename()); + } + } } diff --git a/src/Resources/config/services/task.yml b/src/Resources/config/services/task.yaml similarity index 100% rename from src/Resources/config/services/task.yml rename to src/Resources/config/services/task.yaml From e5c3c94515ac255088ee8fad0fd96c2ceba53acf Mon Sep 17 00:00:00 2001 From: Nicolas Joubert Date: Wed, 23 Oct 2024 14:16:39 +0200 Subject: [PATCH 09/23] #6 Update services and directories according to Symfony best practices. Services should not use autowiring or autoconfiguration. Instead, all services should be defined explicitly. Services must be prefixed with the bundle alias instead of using fully qualified class names => `cleverage_flysystem_process` --- CHANGELOG.md | 2 ++ config/services/task.yaml | 16 +++++++++++++++ .../CleverAgeFlysystemProcessBundle.php | 20 +++++++++---------- .../CleverAgeFlysystemProcessExtension.php | 2 +- src/Resources/config/services/task.yaml | 8 -------- 5 files changed, 29 insertions(+), 19 deletions(-) create mode 100644 config/services/task.yaml rename CleverAgeFlysystemProcessBundle.php => src/CleverAgeFlysystemProcessBundle.php (55%) delete mode 100644 src/Resources/config/services/task.yaml diff --git a/CHANGELOG.md b/CHANGELOG.md index 8514cbb..7d7d7c5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ v2.0 * [#5](https://github.com/cleverage/flysystem-process-bundle/issues/5) Replace "oneup/flysystem-bundle": ">1.0,<4.0" by "league/flysystem-bundle": "^3.0" * [#5](https://github.com/cleverage/flysystem-process-bundle/issues/5) Update Tasks for "league/flysystem-bundle": "^3.0" +* [#6](https://github.com/cleverage/flysystem-process-bundle/issues/6) Update services according to Symfony best practices. Services should not use autowiring or autoconfiguration. Instead, all services should be defined explicitly. + Services must be prefixed with the bundle alias instead of using fully qualified class names => `cleverage_flysystem_process` ### Changes diff --git a/config/services/task.yaml b/config/services/task.yaml new file mode 100644 index 0000000..39fda82 --- /dev/null +++ b/config/services/task.yaml @@ -0,0 +1,16 @@ +services: + _defaults: + public: false + tags: + - { name: monolog.logger, channel: cleverage_process_task } + + cleverage_flysystem_process.task.file_fetch: + class: CleverAge\FlysystemProcessBundle\Task\FileFetch + + cleverage_flysystem_process.task.list_content: + class: CleverAge\FlysystemProcessBundle\Task\ListContentTask + + cleverage_flysystem_process.task.remove_file: + class: CleverAge\FlysystemProcessBundle\Task\RemoveFileTask + arguments: + - '@monolog.logger' diff --git a/CleverAgeFlysystemProcessBundle.php b/src/CleverAgeFlysystemProcessBundle.php similarity index 55% rename from CleverAgeFlysystemProcessBundle.php rename to src/CleverAgeFlysystemProcessBundle.php index 778cb4d..0b3a69a 100644 --- a/CleverAgeFlysystemProcessBundle.php +++ b/src/CleverAgeFlysystemProcessBundle.php @@ -1,8 +1,11 @@ - - * @author Vincent Chalnot - * @author Madeline Veyrenc - */ class CleverAgeFlysystemProcessBundle extends Bundle { + public function getPath(): string + { + return \dirname(__DIR__); + } } diff --git a/src/DependencyInjection/CleverAgeFlysystemProcessExtension.php b/src/DependencyInjection/CleverAgeFlysystemProcessExtension.php index 50bf63a..3802c8c 100644 --- a/src/DependencyInjection/CleverAgeFlysystemProcessExtension.php +++ b/src/DependencyInjection/CleverAgeFlysystemProcessExtension.php @@ -28,7 +28,7 @@ class CleverAgeFlysystemProcessExtension extends Extension { public function load(array $configs, ContainerBuilder $container): void { - $this->findServices($container, __DIR__.'/../Resources/config/services'); + $this->findServices($container, __DIR__.'/../../config/services'); } /** diff --git a/src/Resources/config/services/task.yaml b/src/Resources/config/services/task.yaml deleted file mode 100644 index 6440b85..0000000 --- a/src/Resources/config/services/task.yaml +++ /dev/null @@ -1,8 +0,0 @@ -services: - CleverAge\FlysystemProcessBundle\Task\: - resource: '../../../Task/*' - autowire: true - public: true - shared: false - tags: - - { name: monolog.logger, channel: cleverage_process_task } From 244ea49e3e08eda2b7aa36d08e6d38d17731eee3 Mon Sep 17 00:00:00 2001 From: Nicolas Joubert Date: Thu, 24 Oct 2024 14:18:22 +0200 Subject: [PATCH 10/23] Fix service definition --- config/services/task.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/services/task.yaml b/config/services/task.yaml index 39fda82..82c1086 100644 --- a/config/services/task.yaml +++ b/config/services/task.yaml @@ -5,7 +5,7 @@ services: - { name: monolog.logger, channel: cleverage_process_task } cleverage_flysystem_process.task.file_fetch: - class: CleverAge\FlysystemProcessBundle\Task\FileFetch + class: CleverAge\FlysystemProcessBundle\Task\FileFetchTask cleverage_flysystem_process.task.list_content: class: CleverAge\FlysystemProcessBundle\Task\ListContentTask From 63b24b57872f2a1a83065985d8b3b1f8fb618a2e Mon Sep 17 00:00:00 2001 From: Nicolas Joubert Date: Thu, 24 Oct 2024 16:03:27 +0200 Subject: [PATCH 11/23] Minor README fix --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ecc0df2..9b11f51 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ Compatible with [Symfony stable version and latest Long-Term Support (LTS) relea ## Documentation For usage documentation, see: -[docs/index.md](doc/index.md) +[docs/index.md](docs/index.md) ## Support & Contribution From 8a85e46a112731a5a521d2a6a3fe44b1952b3df4 Mon Sep 17 00:00:00 2001 From: Nicolas Joubert Date: Tue, 29 Oct 2024 17:01:56 +0100 Subject: [PATCH 12/23] #3 Apply <10.0 restriction on phpunit/phpunit since configuration file is not compatible with 10.0+ --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index ff9025f..e3cef49 100644 --- a/composer.json +++ b/composer.json @@ -52,7 +52,7 @@ "phpstan/extension-installer": "*", "phpstan/phpstan": "*", "phpstan/phpstan-symfony": "*", - "phpunit/phpunit": "*", + "phpunit/phpunit": "<10.0", "rector/rector": "*", "roave/security-advisories": "dev-latest", "symfony/test-pack": "^1.1" From 4033e4f8df304256eb45c3d505b9c1d16ac51256 Mon Sep 17 00:00:00 2001 From: Nicolas Joubert Date: Fri, 22 Nov 2024 09:48:13 +0100 Subject: [PATCH 13/23] #9 Aliasing Transformers & Tasks with FQCN to maintain old release configuration compatibility. --- config/services/task.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/config/services/task.yaml b/config/services/task.yaml index 82c1086..f16e810 100644 --- a/config/services/task.yaml +++ b/config/services/task.yaml @@ -6,11 +6,17 @@ services: cleverage_flysystem_process.task.file_fetch: class: CleverAge\FlysystemProcessBundle\Task\FileFetchTask + CleverAge\FlysystemProcessBundle\Task\FileFetchTask: + alias: cleverage_flysystem_process.task.file_fetch cleverage_flysystem_process.task.list_content: class: CleverAge\FlysystemProcessBundle\Task\ListContentTask + CleverAge\FlysystemProcessBundle\Task\ListContentTask: + alias: cleverage_flysystem_process.task.list_content cleverage_flysystem_process.task.remove_file: class: CleverAge\FlysystemProcessBundle\Task\RemoveFileTask arguments: - '@monolog.logger' + CleverAge\FlysystemProcessBundle\Task\RemoveFileTask: + alias: cleverage_flysystem_process.task.remove_file From c9f90aeac92f9a24076587fb4ac2eeda5a5293f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tonon=20Gr=C3=A9gory?= Date: Mon, 9 Dec 2024 16:26:56 +0100 Subject: [PATCH 14/23] Use service locator as registry instead of MountManager --- config/services/task.yaml | 8 +++++- src/Task/FileFetchTask.php | 18 ++++++++----- src/Task/FilesystemOptionTrait.php | 43 ------------------------------ src/Task/ListContentTask.php | 15 +++++++---- src/Task/RemoveFileTask.php | 10 +++---- 5 files changed, 34 insertions(+), 60 deletions(-) delete mode 100644 src/Task/FilesystemOptionTrait.php diff --git a/config/services/task.yaml b/config/services/task.yaml index f16e810..f6d4d98 100644 --- a/config/services/task.yaml +++ b/config/services/task.yaml @@ -6,17 +6,23 @@ services: cleverage_flysystem_process.task.file_fetch: class: CleverAge\FlysystemProcessBundle\Task\FileFetchTask + arguments: [!tagged_locator { tag: 'flysystem.storage', index_by: 'storage' }] CleverAge\FlysystemProcessBundle\Task\FileFetchTask: alias: cleverage_flysystem_process.task.file_fetch + public: true cleverage_flysystem_process.task.list_content: class: CleverAge\FlysystemProcessBundle\Task\ListContentTask + arguments: [!tagged_locator { tag: 'flysystem.storage', index_by: 'storage' }] CleverAge\FlysystemProcessBundle\Task\ListContentTask: alias: cleverage_flysystem_process.task.list_content + public: true cleverage_flysystem_process.task.remove_file: class: CleverAge\FlysystemProcessBundle\Task\RemoveFileTask arguments: - - '@monolog.logger' + - '@logger' + - !tagged_locator { tag: 'flysystem.storage', index_by: 'storage' } CleverAge\FlysystemProcessBundle\Task\RemoveFileTask: alias: cleverage_flysystem_process.task.remove_file + public: true diff --git a/src/Task/FileFetchTask.php b/src/Task/FileFetchTask.php index cefd228..f9344ea 100644 --- a/src/Task/FileFetchTask.php +++ b/src/Task/FileFetchTask.php @@ -19,6 +19,7 @@ use League\Flysystem\Filesystem; use League\Flysystem\FilesystemException; use League\Flysystem\FilesystemOperator; +use Symfony\Component\DependencyInjection\ServiceLocator; use Symfony\Component\OptionsResolver\OptionsResolver; /** @@ -33,6 +34,13 @@ class FileFetchTask extends AbstractConfigurableTask implements IterableTaskInte protected array $matchingFiles = []; + /** + * @param MountManager|null $mountManager + */ + public function __construct(protected readonly ServiceLocator $storages) + { + } + /** * @throws \InvalidArgumentException */ @@ -41,8 +49,8 @@ public function initialize(ProcessState $state): void // Configure options parent::initialize($state); - $this->sourceFS = new Filesystem($this->getOption($state, 'source_filesystem')); - $this->destinationFS = new Filesystem($this->getOption($state, 'destination_filesystem')); + $this->sourceFS = $this->storages->get($this->getOption($state, 'source_filesystem')); + $this->destinationFS = $this->storages->get($this->getOption($state, 'destination_filesystem')); } /** @@ -74,7 +82,7 @@ public function next(ProcessState $state): bool { $this->findMatchingFiles($state); - return next($this->matchingFiles); + return false === next($this->matchingFiles) ? false : true; } /** @@ -116,8 +124,6 @@ protected function findMatchingFiles(ProcessState $state): void */ protected function doFileCopy(ProcessState $state, string $filename, bool $removeSource): bool|string|null { - $prefixFrom = $this->getOption($state, 'source_filesystem'); - $buffer = $this->sourceFS->readStream($filename); try { @@ -132,7 +138,7 @@ protected function doFileCopy(ProcessState $state, string $filename, bool $remov } if ($removeSource) { - $this->sourceFS->delete(\sprintf('%s://%s', $prefixFrom, $filename)); + $this->sourceFS->delete($filename); } return $result ? $filename : null; diff --git a/src/Task/FilesystemOptionTrait.php b/src/Task/FilesystemOptionTrait.php deleted file mode 100644 index ac2f66f..0000000 --- a/src/Task/FilesystemOptionTrait.php +++ /dev/null @@ -1,43 +0,0 @@ -setRequired($optionName); - $resolver->setAllowedTypes($optionName, 'string'); - $resolver->setNormalizer($optionName, fn (Options $options, $value) => new Filesystem($value)); - } - - protected function getFilesystem(ProcessState $state, string $optionName): FilesystemOperator - { - return $this->getOption($state, $optionName); - } - - /** - * @throws \InvalidArgumentException - */ - abstract protected function getOption(ProcessState $state, string $code): mixed; -} diff --git a/src/Task/ListContentTask.php b/src/Task/ListContentTask.php index 419cf53..fe16d64 100644 --- a/src/Task/ListContentTask.php +++ b/src/Task/ListContentTask.php @@ -18,6 +18,8 @@ use CleverAge\ProcessBundle\Model\ProcessState; use League\Flysystem\FilesystemException; use League\Flysystem\FilesystemOperator; +use Psr\Log\LoggerInterface; +use Symfony\Component\DependencyInjection\ServiceLocator; use Symfony\Component\OptionsResolver\OptionsResolver; /** @@ -25,14 +27,17 @@ */ class ListContentTask extends AbstractConfigurableTask implements IterableTaskInterface { - use FilesystemOptionTrait; - protected ?array $fsContent = null; - protected function configureOptions(OptionsResolver $resolver): void + public function __construct(protected readonly ServiceLocator $storages) { - $this->configureFilesystemOption($resolver, 'filesystem'); + } + + protected function configureOptions(OptionsResolver $resolver): void + { + $resolver->setRequired('filesystem'); + $resolver->setAllowedTypes('filesystem', 'string'); $resolver->setDefault('file_pattern', null); $resolver->setAllowedTypes('file_pattern', ['null', 'string']); } @@ -44,7 +49,7 @@ protected function configureOptions(OptionsResolver $resolver): void public function execute(ProcessState $state): void { if (null === $this->fsContent || null === key($this->fsContent)) { - $filesystem = $this->getFilesystem($state, 'filesystem'); + $filesystem = $this->storages->get($this->getOption($state, 'filesystem')); $pattern = $this->getOption($state, 'file_pattern'); $this->fsContent = $this->getFilteredFilesystemContents($filesystem, $pattern); diff --git a/src/Task/RemoveFileTask.php b/src/Task/RemoveFileTask.php index b69b9b7..8b5d4d7 100644 --- a/src/Task/RemoveFileTask.php +++ b/src/Task/RemoveFileTask.php @@ -17,6 +17,7 @@ use CleverAge\ProcessBundle\Model\ProcessState; use League\Flysystem\FilesystemException; use Psr\Log\LoggerInterface; +use Symfony\Component\DependencyInjection\ServiceLocator; use Symfony\Component\OptionsResolver\OptionsResolver; /** @@ -24,20 +25,19 @@ */ class RemoveFileTask extends AbstractConfigurableTask { - use FilesystemOptionTrait; - - public function __construct(protected LoggerInterface $logger) + public function __construct(protected LoggerInterface $logger, protected readonly ServiceLocator $storages) { } protected function configureOptions(OptionsResolver $resolver): void { - $this->configureFilesystemOption($resolver, 'filesystem'); + $resolver->setRequired('filesystem'); + $resolver->setAllowedTypes('filesystem', 'string'); } public function execute(ProcessState $state): void { - $filesystem = $this->getFilesystem($state, 'filesystem'); + $filesystem = $this->storages->get($this->getOption($state, 'filesystem')); $filePath = $state->getInput(); try { From 81a7ab5ce9396ba96a79673ed303a5e11debcdd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tonon=20Gr=C3=A9gory?= Date: Tue, 10 Dec 2024 11:24:31 +0100 Subject: [PATCH 15/23] Quality tools --- src/Task/FileFetchTask.php | 4 ++-- src/Task/ListContentTask.php | 5 +++-- src/Task/RemoveFileTask.php | 4 ++++ 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/Task/FileFetchTask.php b/src/Task/FileFetchTask.php index f9344ea..0ea81a2 100644 --- a/src/Task/FileFetchTask.php +++ b/src/Task/FileFetchTask.php @@ -35,7 +35,7 @@ class FileFetchTask extends AbstractConfigurableTask implements IterableTaskInte protected array $matchingFiles = []; /** - * @param MountManager|null $mountManager + * @param ServiceLocator $storages */ public function __construct(protected readonly ServiceLocator $storages) { @@ -82,7 +82,7 @@ public function next(ProcessState $state): bool { $this->findMatchingFiles($state); - return false === next($this->matchingFiles) ? false : true; + return false !== next($this->matchingFiles); } /** diff --git a/src/Task/ListContentTask.php b/src/Task/ListContentTask.php index fe16d64..8c394cd 100644 --- a/src/Task/ListContentTask.php +++ b/src/Task/ListContentTask.php @@ -18,7 +18,6 @@ use CleverAge\ProcessBundle\Model\ProcessState; use League\Flysystem\FilesystemException; use League\Flysystem\FilesystemOperator; -use Psr\Log\LoggerInterface; use Symfony\Component\DependencyInjection\ServiceLocator; use Symfony\Component\OptionsResolver\OptionsResolver; @@ -29,11 +28,13 @@ class ListContentTask extends AbstractConfigurableTask implements IterableTaskIn { protected ?array $fsContent = null; + /** + * @param ServiceLocator $storages + */ public function __construct(protected readonly ServiceLocator $storages) { } - protected function configureOptions(OptionsResolver $resolver): void { $resolver->setRequired('filesystem'); diff --git a/src/Task/RemoveFileTask.php b/src/Task/RemoveFileTask.php index 8b5d4d7..5bb0af9 100644 --- a/src/Task/RemoveFileTask.php +++ b/src/Task/RemoveFileTask.php @@ -16,6 +16,7 @@ use CleverAge\ProcessBundle\Model\AbstractConfigurableTask; use CleverAge\ProcessBundle\Model\ProcessState; use League\Flysystem\FilesystemException; +use League\Flysystem\FilesystemOperator; use Psr\Log\LoggerInterface; use Symfony\Component\DependencyInjection\ServiceLocator; use Symfony\Component\OptionsResolver\OptionsResolver; @@ -25,6 +26,9 @@ */ class RemoveFileTask extends AbstractConfigurableTask { + /** + * @param ServiceLocator $storages + */ public function __construct(protected LoggerInterface $logger, protected readonly ServiceLocator $storages) { } From 8889c3b7803601d3c0f69f3b17aa00de5caa1f23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tonon=20Gr=C3=A9gory?= Date: Tue, 10 Dec 2024 15:13:25 +0100 Subject: [PATCH 16/23] #10 Update documention --- docs/01 - FileFetchTask.md | 67 +++++++++++++++++++++++++++++++++++++ docs/02 -ListContentTask.md | 43 ++++++++++++++++++++++++ docs/03 - RemoveFileTask.md | 44 ++++++++++++++++++++++++ docs/index.md | 21 ++++++++++-- 4 files changed, 172 insertions(+), 3 deletions(-) create mode 100644 docs/01 - FileFetchTask.md create mode 100644 docs/02 -ListContentTask.md create mode 100644 docs/03 - RemoveFileTask.md diff --git a/docs/01 - FileFetchTask.md b/docs/01 - FileFetchTask.md new file mode 100644 index 0000000..69ee79b --- /dev/null +++ b/docs/01 - FileFetchTask.md @@ -0,0 +1,67 @@ +FileFetchTask +======== + +Perform copy between 2 flysystems storage + +Task reference +-------------- + +* **Service**: [`CleverAge\FlysystemProcessBundle\Task\FileFetchTask`](../src/Task/RemoveFileTask.php) + +Accepted inputs +--------------- + +The filename or filenames to copy from. + +If the option `file_pattern` is not set the input is used as strict filename(s) to match. + +If input is set but not corresponding as any file into `source_filesystem` task failed with UnableToReadFile exception. + +If FileFetchTask is the fisrt task of you process and you wan to use input, don't forgive to set the `entry_point` task name at process level + +Possible outputs +---------------- + +Filename of copied file. + +Options +------- + +| Code | Type | Required | Default | Description | +| ---- |------|:------------------:|-|-----------------------------------------------------------------------------------------------------------------------------------------------| +| `source_filesystem` | `string` |**X**|| The source flysystem/storage.
See config/packages/flysystem.yaml to see configured flysystem/storages. | +| `destination_filesystem` | `string` |**X**|| The source flysystem/storage.
See config/packages/flysystem.yaml to see configured flysystem/storages. | +| `file_pattern` | `string` || null | The file_parttern used in preg_match to match into `source_filesystem` list of files. If not set try to use input as strict filename to match | +| `remove_source`|`bool`|| false | If true delete source file after copy | + + +Examples +-------- + +```yaml +# Task configuration level +code: + service: '@CleverAge\FlysystemProcessBundle\Task\FileFetchTask' + description: > + Download all .csv files from storage.source to storage.destination. + See config/packages/flysystem.yaml to see configured flysystem/storages. + options: + source_filesystem: 'storage.source' + destination_filesystem: 'storage.destination' + file_pattern: '/.csv$/' + remove_source: true +``` + +```yaml +# Full process configuration to use input as filename with the following call +# bin/console cleverage:process:execute my_custom_process --input=foobar.csv -vv +my_custom_process: + entry_point: copy_from_input + tasks: + copy_from_input: + service: '@CleverAge\FlysystemProcessBundle\Task\FileFetchTask' + options: + source_filesystem: 'storage.source' + destination_filesystem: 'storage.destination' + remove_source: true +``` diff --git a/docs/02 -ListContentTask.md b/docs/02 -ListContentTask.md new file mode 100644 index 0000000..1392212 --- /dev/null +++ b/docs/02 -ListContentTask.md @@ -0,0 +1,43 @@ +ListContentTask +======== + +List files of a flysystem storage + +Task reference +-------------- + +* **Service**: [`CleverAge\FlysystemProcessBundle\Task\ListContentTask`](../src/Task/ListContentTask.php) + +Accepted inputs +--------------- + +Input is ignored + +Possible outputs +---------------- + +League\Flysystem\StorageAttributes + +Options +------- + +| Code | Type | Required | Default | Description | +| ---- |----------|:-----------------:|-|----------------------------------------------------------------| +| `filesystem` | `string` | **X** || The source flysystem/storage.
See config/packages/flysystem.yaml to see configured flysystem/storages. | +| `file_pattern` | `string` ||| he file_parttern used in preg_match to match into `filesystem` | + +Examples +-------- + +```yaml +# Task configuration level +code: + service: '@CleverAge\FlysystemProcessBundle\Task\ListContentTask' + description: > + List .csv files from storage.source. + See config/packages/flysystem.yaml to see configured flysystem/storages. + outputs: get_file_path + options: + filesystem: 'storage.source' + file_pattern: '/.csv$/' +``` diff --git a/docs/03 - RemoveFileTask.md b/docs/03 - RemoveFileTask.md new file mode 100644 index 0000000..a7395d2 --- /dev/null +++ b/docs/03 - RemoveFileTask.md @@ -0,0 +1,44 @@ +RemoveFileTask +======== + +Remove a file from a flysystem storage + +Task reference +-------------- + +* **Service**: [`CleverAge\FlysystemProcessBundle\Task\RemoveFileTask`](../src/Task/RemoveFileTask.php) + +Accepted inputs +--------------- + +The filename of the file to remove on `filesystem`. + +When filename is deleted add a info log. + +If filename not found or cannot be deleted on `filesystem` add a warning log. + +Possible outputs +---------------- + +None + +Options +------- + +| Code | Type | Required | Default | Description | +| ---- |------|:------------------:|-|--------------------------------| +| `filesystem` | `string` |**X**|| The source flysystem/storage.
See config/packages/flysystem.yaml to see configured flysystem/storages. | + +Examples +-------- + +```yaml +# bin/console cleverage:process:execute my_custom_process --input=foobar.csv -vv +my_custom_process: + entry_point: remove_from_input + tasks: + remove_from_input: + service: '@CleverAge\FlysystemProcessBundle\Task\FileFetchTask' + options: + filesystem: 'storage.source' +``` diff --git a/docs/index.md b/docs/index.md index 2e3c4d2..b5ebe47 100644 --- a/docs/index.md +++ b/docs/index.md @@ -19,9 +19,24 @@ Remember to add the following line to config/bundles.php (not required if Symfon CleverAge\FlysystemProcessBundle\CleverAgeFlysystemProcessBundle::class => ['all' => true], ``` +Configure at least one flysytem/storage into `config/packages/flysytem.yaml` + +```yaml +#config/packages/flysytem.yaml +flysystem: + storages: + storage.source: # This is the identifier of flysytem/storage + adapter: 'local' + options: + directory: '%kernel.project_dir%/var/storage/source' +``` + +See https://github.com/thephpleague/flysystem-bundle?tab=readme-ov-file for more sample configuration (sftp, ftp, amazon s3 ...) + + ## Reference - Tasks - - [FileFetchTask] - - [ListContentTask] - - [RemoveFileTask] + - [FileFetchTask](01%20-%20FileFetchTask.md) + - [ListContentTask](02%20-ListContentTask.md) + - [RemoveFileTask](03%20-%20RemoveFileTask.md) From 43dce76ce80f6360214695ba0e5266db9bed2191 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tonon=20Gr=C3=A9gory?= Date: Tue, 10 Dec 2024 16:07:05 +0100 Subject: [PATCH 17/23] #10 Update documention --- docs/01 - FileFetchTask.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/01 - FileFetchTask.md b/docs/01 - FileFetchTask.md index 69ee79b..b2ac35d 100644 --- a/docs/01 - FileFetchTask.md +++ b/docs/01 - FileFetchTask.md @@ -6,7 +6,7 @@ Perform copy between 2 flysystems storage Task reference -------------- -* **Service**: [`CleverAge\FlysystemProcessBundle\Task\FileFetchTask`](../src/Task/RemoveFileTask.php) +* **Service**: [`CleverAge\FlysystemProcessBundle\Task\FileFetchTask`](../src/Task/FileFetchTask.php) Accepted inputs --------------- From 088b36cca4277346d83aca6b4c752286476747ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tonon=20Gr=C3=A9gory?= Date: Wed, 11 Dec 2024 09:40:17 +0100 Subject: [PATCH 18/23] #10 Update documention --- docs/{01 - FileFetchTask.md => 01-FileFetchTask.md} | 12 ++++++------ ...{02 -ListContentTask.md => 02-ListContentTask.md} | 8 ++++---- .../{03 - RemoveFileTask.md => 03-RemoveFileTask.md} | 6 +++--- docs/index.md | 6 +++--- 4 files changed, 16 insertions(+), 16 deletions(-) rename docs/{01 - FileFetchTask.md => 01-FileFetchTask.md} (62%) rename docs/{02 -ListContentTask.md => 02-ListContentTask.md} (51%) rename docs/{03 - RemoveFileTask.md => 03-RemoveFileTask.md} (61%) diff --git a/docs/01 - FileFetchTask.md b/docs/01-FileFetchTask.md similarity index 62% rename from docs/01 - FileFetchTask.md rename to docs/01-FileFetchTask.md index b2ac35d..87481a0 100644 --- a/docs/01 - FileFetchTask.md +++ b/docs/01-FileFetchTask.md @@ -27,12 +27,12 @@ Filename of copied file. Options ------- -| Code | Type | Required | Default | Description | -| ---- |------|:------------------:|-|-----------------------------------------------------------------------------------------------------------------------------------------------| -| `source_filesystem` | `string` |**X**|| The source flysystem/storage.
See config/packages/flysystem.yaml to see configured flysystem/storages. | -| `destination_filesystem` | `string` |**X**|| The source flysystem/storage.
See config/packages/flysystem.yaml to see configured flysystem/storages. | -| `file_pattern` | `string` || null | The file_parttern used in preg_match to match into `source_filesystem` list of files. If not set try to use input as strict filename to match | -| `remove_source`|`bool`|| false | If true delete source file after copy | +| Code | Type | Required | Default | Description | +|--------------------------|:----------:|:---------:|:---------:|-----------------------------------------------------------------------------------------------------------------------------------------------| +| `source_filesystem` | `string` | **X** | | The source flysystem/storage.
See config/packages/flysystem.yaml to see configured flysystem/storages. | +| `destination_filesystem` | `string` | **X** | | The source flysystem/storage.
See config/packages/flysystem.yaml to see configured flysystem/storages. | +| `file_pattern` | `string` | | null | The file_parttern used in preg_match to match into `source_filesystem` list of files. If not set try to use input as strict filename to match | +| `remove_source` | `bool` | | false | If true delete source file after copy | Examples diff --git a/docs/02 -ListContentTask.md b/docs/02-ListContentTask.md similarity index 51% rename from docs/02 -ListContentTask.md rename to docs/02-ListContentTask.md index 1392212..ca9238e 100644 --- a/docs/02 -ListContentTask.md +++ b/docs/02-ListContentTask.md @@ -21,10 +21,10 @@ League\Flysystem\StorageAttributes Options ------- -| Code | Type | Required | Default | Description | -| ---- |----------|:-----------------:|-|----------------------------------------------------------------| -| `filesystem` | `string` | **X** || The source flysystem/storage.
See config/packages/flysystem.yaml to see configured flysystem/storages. | -| `file_pattern` | `string` ||| he file_parttern used in preg_match to match into `filesystem` | +| Code | Type | Required | Default | Description | +|----------------|:----------:|:---------:|:---------:|------------------------------------------------------------------------------------------------------------| +| `filesystem` | `string` | **X** | | The source flysystem/storage.
See config/packages/flysystem.yaml to see configured flysystem/storages. | +| `file_pattern` | `string` | | | The file_parttern used in preg_match to match into `filesystem` | Examples -------- diff --git a/docs/03 - RemoveFileTask.md b/docs/03-RemoveFileTask.md similarity index 61% rename from docs/03 - RemoveFileTask.md rename to docs/03-RemoveFileTask.md index a7395d2..79f7b99 100644 --- a/docs/03 - RemoveFileTask.md +++ b/docs/03-RemoveFileTask.md @@ -25,9 +25,9 @@ None Options ------- -| Code | Type | Required | Default | Description | -| ---- |------|:------------------:|-|--------------------------------| -| `filesystem` | `string` |**X**|| The source flysystem/storage.
See config/packages/flysystem.yaml to see configured flysystem/storages. | +| Code | Type | Required | Default | Description | +|--------------|:----------:|:----------:|:---------:|-------------------------------------------------------------------------------------------------------------| +| `filesystem` | `string` | **X** | | The source flysystem/storage.
See config/packages/flysystem.yaml to see configured flysystem/storages. | Examples -------- diff --git a/docs/index.md b/docs/index.md index b5ebe47..37f9dd7 100644 --- a/docs/index.md +++ b/docs/index.md @@ -37,6 +37,6 @@ See https://github.com/thephpleague/flysystem-bundle?tab=readme-ov-file for more ## Reference - Tasks - - [FileFetchTask](01%20-%20FileFetchTask.md) - - [ListContentTask](02%20-ListContentTask.md) - - [RemoveFileTask](03%20-%20RemoveFileTask.md) + - [FileFetchTask](01-FileFetchTask.md) + - [ListContentTask](02-ListContentTask.md) + - [RemoveFileTask](03-RemoveFileTask.md) From c2a7f6f69e9a3fb69d010ba209aa65445fbf84e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tonon=20Gr=C3=A9gory?= Date: Wed, 11 Dec 2024 09:58:12 +0100 Subject: [PATCH 19/23] #10 Update documention --- docs/index.md | 6 +++--- docs/{ => reference/tasks}/01-FileFetchTask.md | 0 docs/{ => reference/tasks}/02-ListContentTask.md | 0 docs/{ => reference/tasks}/03-RemoveFileTask.md | 0 4 files changed, 3 insertions(+), 3 deletions(-) rename docs/{ => reference/tasks}/01-FileFetchTask.md (100%) rename docs/{ => reference/tasks}/02-ListContentTask.md (100%) rename docs/{ => reference/tasks}/03-RemoveFileTask.md (100%) diff --git a/docs/index.md b/docs/index.md index 37f9dd7..bf1ecdb 100644 --- a/docs/index.md +++ b/docs/index.md @@ -37,6 +37,6 @@ See https://github.com/thephpleague/flysystem-bundle?tab=readme-ov-file for more ## Reference - Tasks - - [FileFetchTask](01-FileFetchTask.md) - - [ListContentTask](02-ListContentTask.md) - - [RemoveFileTask](03-RemoveFileTask.md) + - [FileFetchTask](reference/tasks/01-FileFetchTask.md) + - [ListContentTask](reference/tasks/02-ListContentTask.md) + - [RemoveFileTask](reference/tasks/03-RemoveFileTask.md) diff --git a/docs/01-FileFetchTask.md b/docs/reference/tasks/01-FileFetchTask.md similarity index 100% rename from docs/01-FileFetchTask.md rename to docs/reference/tasks/01-FileFetchTask.md diff --git a/docs/02-ListContentTask.md b/docs/reference/tasks/02-ListContentTask.md similarity index 100% rename from docs/02-ListContentTask.md rename to docs/reference/tasks/02-ListContentTask.md diff --git a/docs/03-RemoveFileTask.md b/docs/reference/tasks/03-RemoveFileTask.md similarity index 100% rename from docs/03-RemoveFileTask.md rename to docs/reference/tasks/03-RemoveFileTask.md From ce388b9826c394559a62ed243c6f2012d41411c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tonon=20Gr=C3=A9gory?= Date: Wed, 11 Dec 2024 10:31:26 +0100 Subject: [PATCH 20/23] #10 Update documention --- docs/reference/tasks/01-FileFetchTask.md | 14 ++++++++++---- docs/reference/tasks/02-ListContentTask.md | 9 ++++----- docs/reference/tasks/03-RemoveFileTask.md | 6 ++++-- 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/docs/reference/tasks/01-FileFetchTask.md b/docs/reference/tasks/01-FileFetchTask.md index 87481a0..a5dca8a 100644 --- a/docs/reference/tasks/01-FileFetchTask.md +++ b/docs/reference/tasks/01-FileFetchTask.md @@ -38,13 +38,15 @@ Options Examples -------- +* Simple fetch task configuration + - See config/packages/flysystem.yaml to see configured flysystems/storages. + - copy all .csv files from 'storage.source' to 'storage.destination' + - remove .csv from 'storage.source' after copy + - output will be filename of copied files ```yaml # Task configuration level code: service: '@CleverAge\FlysystemProcessBundle\Task\FileFetchTask' - description: > - Download all .csv files from storage.source to storage.destination. - See config/packages/flysystem.yaml to see configured flysystem/storages. options: source_filesystem: 'storage.source' destination_filesystem: 'storage.destination' @@ -52,9 +54,13 @@ code: remove_source: true ``` +* Simple fetch process configuration to cipy a specific file from --input option via
```bin/console cleverage:process:execute my_custom_process --input=foobar.csv -vv``` + - See config/packages/flysystem.yaml to see configured flysystems/storages. + - copy input file from 'storage.source' to 'storage.destination' + - remove .csv from 'storage.source' after copy + - output will be filename of copied file ```yaml # Full process configuration to use input as filename with the following call -# bin/console cleverage:process:execute my_custom_process --input=foobar.csv -vv my_custom_process: entry_point: copy_from_input tasks: diff --git a/docs/reference/tasks/02-ListContentTask.md b/docs/reference/tasks/02-ListContentTask.md index ca9238e..036c0c3 100644 --- a/docs/reference/tasks/02-ListContentTask.md +++ b/docs/reference/tasks/02-ListContentTask.md @@ -28,15 +28,14 @@ Options Examples -------- - +* Simple list task configuration from a filesystem + - see config/packages/flysystem.yaml to see configured flysystems/storages. + - list all .csv files from 'storage.source' + - output will be League\Flysystem\StorageAttributes representation of copied files ```yaml # Task configuration level code: service: '@CleverAge\FlysystemProcessBundle\Task\ListContentTask' - description: > - List .csv files from storage.source. - See config/packages/flysystem.yaml to see configured flysystem/storages. - outputs: get_file_path options: filesystem: 'storage.source' file_pattern: '/.csv$/' diff --git a/docs/reference/tasks/03-RemoveFileTask.md b/docs/reference/tasks/03-RemoveFileTask.md index 79f7b99..4928f33 100644 --- a/docs/reference/tasks/03-RemoveFileTask.md +++ b/docs/reference/tasks/03-RemoveFileTask.md @@ -31,9 +31,11 @@ Options Examples -------- - +* Simple process to remove a file on 'storage.source' via
```bin/console cleverage:process:execute my_custom_process --input=foobar.csv -vv``` + - see config/packages/flysystem.yaml to see configured flysystems/storages. + - remove file with name passed as input ```yaml -# bin/console cleverage:process:execute my_custom_process --input=foobar.csv -vv +# my_custom_process: entry_point: remove_from_input tasks: From 2341a977540482dc84c98bfe5c34b29790746f21 Mon Sep 17 00:00:00 2001 From: Nicolas Joubert Date: Fri, 13 Dec 2024 11:52:34 +0100 Subject: [PATCH 21/23] #12 Remove all phpstan ignoreErrors. Fix code. --- phpstan.neon | 13 ------------- src/Task/FileFetchTask.php | 4 +++- src/Task/ListContentTask.php | 5 +++++ 3 files changed, 8 insertions(+), 14 deletions(-) diff --git a/phpstan.neon b/phpstan.neon index 30e9572..63aadba 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -3,16 +3,3 @@ parameters: paths: - src - tests - ignoreErrors: - - '#type has no value type specified in iterable type#' - - '#has parameter .* with no value type specified in iterable type#' - - '#has no value type specified in iterable type array#' - - '#configureOptions\(\) has no return type specified.#' - - '#configure\(\) has no return type specified#' - - '#process\(\) has no return type specified#' - - '#should return Iterator but returns Traversable#' - - '#Negated boolean expression is always false#' - checkGenericClassInNonGenericObjectType: false - reportUnmatchedIgnoredErrors: false - inferPrivatePropertyTypeFromConstructor: true - treatPhpDocTypesAsCertain: false diff --git a/src/Task/FileFetchTask.php b/src/Task/FileFetchTask.php index 0ea81a2..9652580 100644 --- a/src/Task/FileFetchTask.php +++ b/src/Task/FileFetchTask.php @@ -16,7 +16,6 @@ use CleverAge\ProcessBundle\Model\AbstractConfigurableTask; use CleverAge\ProcessBundle\Model\IterableTaskInterface; use CleverAge\ProcessBundle\Model\ProcessState; -use League\Flysystem\Filesystem; use League\Flysystem\FilesystemException; use League\Flysystem\FilesystemOperator; use Symfony\Component\DependencyInjection\ServiceLocator; @@ -32,6 +31,9 @@ class FileFetchTask extends AbstractConfigurableTask implements IterableTaskInte protected FilesystemOperator $destinationFS; + /** + * @var array + */ protected array $matchingFiles = []; /** diff --git a/src/Task/ListContentTask.php b/src/Task/ListContentTask.php index 8c394cd..758512b 100644 --- a/src/Task/ListContentTask.php +++ b/src/Task/ListContentTask.php @@ -26,6 +26,9 @@ */ class ListContentTask extends AbstractConfigurableTask implements IterableTaskInterface { + /** + * @var list<\League\Flysystem\StorageAttributes>|null + */ protected ?array $fsContent = null; /** @@ -76,6 +79,8 @@ public function next(ProcessState $state): bool } /** + * @return list<\League\Flysystem\StorageAttributes> + * * @throws FilesystemException */ protected function getFilteredFilesystemContents(FilesystemOperator $filesystem, ?string $pattern = null): array From 63640606b349dcaa1a83eabbd036313200a002c3 Mon Sep 17 00:00:00 2001 From: Nicolas Joubert Date: Fri, 13 Dec 2024 14:18:46 +0100 Subject: [PATCH 22/23] #12 Apply phpstan level 10 --- phpstan.neon | 2 +- src/Task/FileFetchTask.php | 23 ++++++++++++++++------- src/Task/ListContentTask.php | 11 +++++++---- src/Task/RemoveFileTask.php | 5 ++++- 4 files changed, 28 insertions(+), 13 deletions(-) diff --git a/phpstan.neon b/phpstan.neon index 63aadba..e9a9e7e 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -1,5 +1,5 @@ parameters: - level: 6 + level: 10 paths: - src - tests diff --git a/src/Task/FileFetchTask.php b/src/Task/FileFetchTask.php index 9652580..b915e67 100644 --- a/src/Task/FileFetchTask.php +++ b/src/Task/FileFetchTask.php @@ -51,8 +51,12 @@ public function initialize(ProcessState $state): void // Configure options parent::initialize($state); - $this->sourceFS = $this->storages->get($this->getOption($state, 'source_filesystem')); - $this->destinationFS = $this->storages->get($this->getOption($state, 'destination_filesystem')); + /** @var string $sourceFilesystemOption */ + $sourceFilesystemOption = $this->getOption($state, 'source_filesystem'); + $this->sourceFS = $this->storages->get($sourceFilesystemOption); + /** @var string $destinationFilesystemOption */ + $destinationFilesystemOption = $this->getOption($state, 'destination_filesystem'); + $this->destinationFS = $this->storages->get($destinationFilesystemOption); } /** @@ -71,7 +75,9 @@ public function execute(ProcessState $state): void return; } - $this->doFileCopy($state, $file, $this->getOption($state, 'remove_source')); + /** @var bool $removeSourceOption */ + $removeSourceOption = $this->getOption($state, 'remove_source'); + $this->doFileCopy($state, $file, $removeSourceOption); $state->setOutput($file); } @@ -94,16 +100,19 @@ public function next(ProcessState $state): bool */ protected function findMatchingFiles(ProcessState $state): void { + /** @var ?string $filePattern */ $filePattern = $this->getOption($state, 'file_pattern'); if ($filePattern) { foreach ($this->sourceFS->listContents('/') as $file) { - if ('file' === $file['type'] - && preg_match($filePattern, (string) $file['path']) - && !\in_array($file['path'], $this->matchingFiles, true)) { - $this->matchingFiles[] = $file['path']; + if ('file' === $file->type() + && preg_match($filePattern, $file->path()) + && !\in_array($file->path(), $this->matchingFiles, true) + ) { + $this->matchingFiles[] = $file->path(); } } } else { + /** @var array|string|null $input */ $input = $state->getInput(); if (!$input) { throw new \UnexpectedValueException('No pattern neither input provided for the Task'); diff --git a/src/Task/ListContentTask.php b/src/Task/ListContentTask.php index 758512b..c804135 100644 --- a/src/Task/ListContentTask.php +++ b/src/Task/ListContentTask.php @@ -53,10 +53,13 @@ protected function configureOptions(OptionsResolver $resolver): void public function execute(ProcessState $state): void { if (null === $this->fsContent || null === key($this->fsContent)) { - $filesystem = $this->storages->get($this->getOption($state, 'filesystem')); - $pattern = $this->getOption($state, 'file_pattern'); + /** @var string $filesystemOption */ + $filesystemOption = $this->getOption($state, 'filesystem'); + $filesystem = $this->storages->get($filesystemOption); + /** @var ?string $patternOption */ + $patternOption = $this->getOption($state, 'file_pattern'); - $this->fsContent = $this->getFilteredFilesystemContents($filesystem, $pattern); + $this->fsContent = $this->getFilteredFilesystemContents($filesystem, $patternOption); } if (null === key($this->fsContent)) { @@ -87,7 +90,7 @@ protected function getFilteredFilesystemContents(FilesystemOperator $filesystem, { $results = []; foreach ($filesystem->listContents('') as $item) { - if (null === $pattern || preg_match($pattern, (string) $item['path'])) { + if (null === $pattern || preg_match($pattern, $item->path())) { $results[] = $item; } } diff --git a/src/Task/RemoveFileTask.php b/src/Task/RemoveFileTask.php index 5bb0af9..2f195f4 100644 --- a/src/Task/RemoveFileTask.php +++ b/src/Task/RemoveFileTask.php @@ -41,7 +41,10 @@ protected function configureOptions(OptionsResolver $resolver): void public function execute(ProcessState $state): void { - $filesystem = $this->storages->get($this->getOption($state, 'filesystem')); + /** @var string $filesystemOption */ + $filesystemOption = $this->getOption($state, 'filesystem'); + $filesystem = $this->storages->get($filesystemOption); + /** @var string $filePath */ $filePath = $state->getInput(); try { From eeaf8709d47f95ec6d45ffb7d98b6cd8b6dbcb08 Mon Sep 17 00:00:00 2001 From: Nicolas Joubert Date: Tue, 17 Dec 2024 15:20:30 +0100 Subject: [PATCH 23/23] #8 Bump dependency "cleverage/process-bundle": "^4.0" --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index e3cef49..208e9f4 100644 --- a/composer.json +++ b/composer.json @@ -44,7 +44,7 @@ }, "require": { "php": ">=8.1", - "cleverage/process-bundle": "dev-prepare-release", + "cleverage/process-bundle": "^4.0", "league/flysystem-bundle": "^3.0" }, "require-dev": {