diff --git a/CHANGELOG.md b/CHANGELOG.md index 134470ab..dfac53b7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ Latest ------ ## Changes +* [#299](https://github.com/cleverage/process-bundle/issues/299) Require `symfony/polyfill-php83`, `symfony/polyfill-php84` and `symfony/polyfill-php85`: the functions of PHP 8.3 to 8.5 can be used while supporting PHP 8.2. Rector targets PHP 8.2 (`withPhpVersion()`, `withPhpSets()` read from `composer.json`) and applies the rules using a newer function when its polyfill is required: `ProcessConfiguration` uses `array_any()` again; `array_first()` replaces `reset()` / `current()` in `ProcessConfiguration::getMainTask()`, `ConstraintLoader` and `ProcessHelpCommand` (no internal array pointer, same results). * [#279](https://github.com/cleverage/process-bundle/issues/279) Define the public API (Symfony BC promise): the classes not meant to be extended are marked `@final since 5.4` (the engine: `ProcessManager`, `ProcessConfigurationRegistry`, `TransformerRegistry`, `ContextualOptionResolver`; the models: `ProcessState`, `ProcessHistory`, `SubprocessInstance`, the configurations, the events, the `Filesystem` files; the concrete tasks and transformers), they will be `final` in v6.0: extending them triggers a deprecation with the Symfony `DebugClassLoader`. The abstract classes, interfaces, traits, exceptions and the file tasks extended by other tasks (`FileReaderTask`, `LineReaderTask`, `FolderBrowserTask`, `CsvReaderTask`, `InputCsvReaderTask`, `Filesystem\CsvResource`) stay open. `TaskRegistry`, new in this version, is `final`. The infrastructure classes are marked `@internal`: `CleverAgeProcessExtension`, `Configuration`, the commands, `DataQueueEventListener`, `PhpFunctionProvider`, the Monolog processors, `ProcessLogger` and `TaskLogger`. Update documentation. * [#269](https://github.com/cleverage/process-bundle/issues/269) Composer: `symfony/process`, `symfony/stopwatch`, `symfony/var-dumper` and `symfony/monolog-bundle` are no longer required, they are suggested (applications using them must require them). Without `symfony/process` (`CommandRunnerTask`, `ProcessLauncherTask`) or `symfony/stopwatch` (`StopwatchTask`), the container still compiles and these tasks fail with an explicit message (`UnavailableServicesCompilerPass`); without `symfony/var-dumper`, nothing is dumped (as before); without `symfony/monolog-bundle`, the `cleverage_process*` channels and processors are not registered and the default logger is used. `monolog/monolog` stays required (`Logger\*Processor`). Remove the unused `symfony/monolog-bridge` dependency. `ProcessConfiguration` no longer uses `array_any()` (PHP 8.4), whose polyfill was only installed by the removed packages. Add a `conflict` with `cleverage/doctrine-process-bundle`, `cleverage/soap-process-bundle` and `cleverage/ui-process-bundle` `<3.3`, which use the MonologBundle without requiring it. Update documentation, add tests. * [#91](https://github.com/cleverage/process-bundle/issues/91) Reference a task by a code in the process configurations: new `task` key (`task: transformer`), next to its `options`. The code of a task service is declared with the new `code` attribute of the `cleverage.task` tag or the new `#[AsTask(code: '...')]` attribute (autoconfiguration); every task of the bundle has a code, given on its reference page (snake case of its class name without `Task`, e.g. `transformer`, `constant_output`, `csv_reader`). The codes are resolved when the container is compiled (`TaskLocatorCompilerPass`): an unknown or duplicate code fails the compilation. Referencing a task by its `service` (e.g. `service: '@CleverAge\ProcessBundle\Task\TransformerTask'`) is deprecated (configuration deprecation), it will be removed in v6.0: use `task: `. The documentation examples use the codes. Update documentation, add tests. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d5f790d9..84655d97 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -40,6 +40,14 @@ make quality make tests ``` +## PHP version + +The bundle supports PHP 8.2 and later: do not use a syntax introduced by a later version (typed class constants, +property hooks, pipe operator...). The functions of PHP 8.3 to 8.5 (`json_validate()`, `array_find()`, `array_any()`, +`mb_trim()`, `array_first()`...) can be used: they are provided by the required `symfony/polyfill-php83`, +`symfony/polyfill-php84` and `symfony/polyfill-php85` packages on the older versions. Rector (`make quality`) is +configured accordingly. + ## Deprecations notices When a feature should be deprecated, or when you have a breaking change for a future version, please : diff --git a/composer.json b/composer.json index 5ecb8559..0648a899 100644 --- a/composer.json +++ b/composer.json @@ -76,6 +76,9 @@ "symfony/framework-bundle": "^6.4|^7.4|^8", "symfony/http-kernel": "^6.4|^7.4|^8", "symfony/options-resolver": "^6.4|^7.4|^8", + "symfony/polyfill-php83": "^1.33", + "symfony/polyfill-php84": "^1.33", + "symfony/polyfill-php85": "^1.33", "symfony/property-access": "^6.4|^7.4|^8", "symfony/serializer": "^6.4|^7.4|^8", "symfony/service-contracts": "^2.5|^3", diff --git a/rector.php b/rector.php index 7628528c..a601b303 100644 --- a/rector.php +++ b/rector.php @@ -3,23 +3,21 @@ declare(strict_types=1); use Rector\Config\RectorConfig; -use Rector\Set\ValueObject\LevelSetList; use Rector\Symfony\Set\SymfonySetList; use Rector\ValueObject\PhpVersion; return RectorConfig::configure() - ->withPhpVersion(PhpVersion::PHP_85) + ->withPhpVersion(PhpVersion::PHP_82) ->withPaths([ __DIR__.'/src', __DIR__.'/tests', ]) - ->withPhpSets(php82: true) + ->withPhpSets() // here we can define, what prepared sets of rules will be applied ->withComposerBased(phpunit: true, symfony: true) ->withPreparedSets(deadCode: true, codeQuality: true, symfonyCodeQuality: true) ->withAttributesSets(symfony: true) ->withSets([ - LevelSetList::UP_TO_PHP_82, SymfonySetList::SYMFONY_CONSTRUCTOR_INJECTION, ]) ; diff --git a/src/Command/ProcessHelpCommand.php b/src/Command/ProcessHelpCommand.php index adfc96bf..f02109a4 100644 --- a/src/Command/ProcessHelpCommand.php +++ b/src/Command/ProcessHelpCommand.php @@ -270,7 +270,7 @@ protected function resolveBranchOutput( if ([] === $previousTasks) { $branches[] = $task->getCode(); } elseif (1 === \count($previousTasks)) { - $prevTask = current($previousTasks) + $prevTask = array_first($previousTasks) ->getCode(); foreach (array_reverse($branches, true) as $i => $branchTask) { if ($branchTask === $prevTask) { diff --git a/src/Configuration/ProcessConfiguration.php b/src/Configuration/ProcessConfiguration.php index 767d9bbd..9f782734 100644 --- a/src/Configuration/ProcessConfiguration.php +++ b/src/Configuration/ProcessConfiguration.php @@ -148,13 +148,7 @@ public function getDependencyGroups(): array if (null === $this->dependencyGroups) { $this->dependencyGroups = []; foreach ($this->getTaskConfigurations() as $taskConfiguration) { - $isInBranch = false; - foreach ($this->dependencyGroups as $branch) { - if (\in_array($taskConfiguration->getCode(), $branch, true)) { - $isInBranch = true; - break; - } - } + $isInBranch = array_any($this->dependencyGroups, static fn ($branch) => \in_array($taskConfiguration->getCode(), $branch, true)); if (!$isInBranch) { $dependencies = $this->buildDependencies($taskConfiguration); $dependencies = $this->sortDependencies($dependencies); @@ -207,12 +201,8 @@ public function getMainTask(): ?TaskConfiguration // By default use the first defined task if (!$entryTask instanceof TaskConfiguration) { - $entryTask = reset($this->taskConfigurations); - } - - // May happen with an empty array - if (false === $entryTask) { - return null; + // null with an empty array + return array_first($this->taskConfigurations); } return $entryTask; diff --git a/src/Validator/ConstraintLoader.php b/src/Validator/ConstraintLoader.php index 03b50053..81971e4c 100644 --- a/src/Validator/ConstraintLoader.php +++ b/src/Validator/ConstraintLoader.php @@ -41,13 +41,13 @@ public function buildConstraints(array $nodes): array foreach ($nodes as $name => $childNodes) { if (is_numeric($name) && \is_array($childNodes) && 1 === \count($childNodes)) { - $options = current($childNodes); + $options = array_first($childNodes); if (\is_array($options)) { $options = $this->buildConstraints($options); } - $values[] = $this->newConstraint(key($childNodes), $options); + $values[] = $this->newConstraint(array_key_first($childNodes), $options); } else { if (\is_array($childNodes)) { $childNodes = $this->buildConstraints($childNodes);