diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..f7b8104 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,13 @@ +version: 2 +updates: + - package-ecosystem: github-actions + directory: / + schedule: + interval: weekly + open-pull-requests-limit: 5 + - package-ecosystem: composer + directory: / + schedule: + interval: monthly + open-pull-requests-limit: 5 + versioning-strategy: widen diff --git a/UPGRADE-2.0.md b/UPGRADE-2.0.md new file mode 100644 index 0000000..41ca6c0 --- /dev/null +++ b/UPGRADE-2.0.md @@ -0,0 +1,5 @@ +# Upgrade from 1.x to 2.0 + +- Minimum PHP is **8.2** (`^8.2`). +- Requires `portphp/portphp` **^2.0**. +- Symfony components: `^5.4 || ^6.0 || ^7.0 || ^8.0` (versions that run on PHP 8.2+). diff --git a/composer.json b/composer.json index 434dc97..7a526bd 100644 --- a/composer.json +++ b/composer.json @@ -19,15 +19,15 @@ ], "support": { "issues": "https://github.com/portphp/portphp/issues", - "source": "https://github.com/portphp/boilerplate", + "source": "https://github.com/portphp/steps", "docs": "https://portphp.readthedocs.io" }, "require": { "php": "^8.2", - "portphp/portphp": "^1.0.0", + "portphp/portphp": "^2.0", "seld/signal-handler": "^1.0 || ^2.0", - "symfony/property-access": "^2.3 || ^3.0 || ^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0", - "symfony/validator": "^2.5 || ^3.0 || ^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0", + "symfony/property-access": "^5.4 || ^6.0 || ^7.0 || ^8.0", + "symfony/validator": "^5.4 || ^6.0 || ^7.0 || ^8.0", "psr/log": "^1.0 || ^2.0 || ^3.0" }, "autoload": { @@ -35,11 +35,8 @@ "Port\\Steps\\": "src/" } }, - "conflict": { - "symfony/validator": "<2.5" - }, "require-dev": { - "phpspec/phpspec": "^7.2 || ^8.0", + "phpspec/phpspec": "^8.0", "friends-of-phpspec/phpspec-code-coverage": "^6.1 || ^7.0" }, "suggest": { diff --git a/src/Step/ValidatorStep.php b/src/Step/ValidatorStep.php index ab226c1..bc05dd8 100644 --- a/src/Step/ValidatorStep.php +++ b/src/Step/ValidatorStep.php @@ -101,7 +101,7 @@ public function process($item, callable $next) $this->line++; if (count($this->constraints) > 0) { - $constraints = new Constraints\Collection($this->constraints); + $constraints = $this->createCollectionConstraint(); $list = $this->validator->validate($item, $constraints); } else { $list = $this->validator->validate($item); @@ -120,6 +120,45 @@ public function process($item, callable $next) } } + + /** + * Build a Collection constraint compatible with Symfony 5.4–8. + * + * Symfony 7+ uses a fields-first constructor; older versions use an options bag. + */ + private function createCollectionConstraint(): Constraints\Collection + { + $fields = $this->constraints['fields'] ?? []; + $options = $this->constraints; + unset($options['fields']); + + $constructor = (new \ReflectionClass(Constraints\Collection::class))->getConstructor(); + $parameters = $constructor ? $constructor->getParameters() : []; + $first = $parameters[0] ?? null; + + // Symfony 7+/8: first argument is $fields (field map), not an options array + if ($first && $first->getName() === 'fields') { + $allowed = []; + foreach ($parameters as $parameter) { + $allowed[$parameter->getName()] = true; + } + $named = ['fields' => $fields]; + foreach ($options as $name => $value) { + if (!isset($allowed[$name])) { + throw new \Symfony\Component\Validator\Exception\InvalidOptionsException( + sprintf('The option "%s" does not exist in constraint "%s".', $name, Constraints\Collection::class), + [$name] + ); + } + $named[$name] = $value; + } + + return new Constraints\Collection(...$named); + } + + return new Constraints\Collection(array_merge(['fields' => $fields], $options)); + } + /** * {@inheritdoc} */