From 2a7ccccdde5b9a098accc938bd56422835014a06 Mon Sep 17 00:00:00 2001 From: Vincent Langlet Date: Sat, 25 Nov 2023 13:06:45 +0100 Subject: [PATCH 1/3] Add SF 7 support (#8127) --- .github/workflows/test.yaml | 5 ++ composer.json | 60 +++++++++---------- src/Filter/Model/FilterData.php | 4 +- src/Form/Type/Filter/DateTimeRangeType.php | 3 +- src/Form/Type/Filter/DateTimeType.php | 3 +- src/Route/RoutesCacheWarmUp.php | 2 +- src/Security/Handler/AclSecurityHandler.php | 4 +- src/Security/Handler/RoleSecurityHandler.php | 4 +- src/Util/TraversableToCollection.php | 4 +- tests/Filter/Model/FilterDataTest.php | 4 +- .../Persister/SessionFilterPersisterTest.php | 3 +- tests/Form/AdminLayoutTest.php | 16 +++-- .../Type/Filter/DateTimeRangeTypeTest.php | 3 +- tests/Form/Widget/FormChoiceWidgetTest.php | 16 +++-- tests/Util/TraversableToCollectionTest.php | 2 +- 15 files changed, 74 insertions(+), 59 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index f9a7e616d4..655f0fe256 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -57,6 +57,11 @@ jobs: allowed-to-fail: false symfony-require: 6.3.* variant: symfony/symfony:"6.3.*" + - php-version: '8.2' + dependencies: highest + allowed-to-fail: false + symfony-require: 7.0.* + variant: symfony/symfony:"7.0.*" steps: - name: Checkout diff --git a/composer.json b/composer.json index 5828b98929..bdaa29b3c6 100644 --- a/composer.json +++ b/composer.json @@ -37,39 +37,39 @@ "sonata-project/exporter": "^2.14 || ^3.1.1", "sonata-project/form-extensions": "^1.15 || ^2.0", "sonata-project/twig-extensions": "^1.4.1 || ^2.0", - "symfony/asset": "^5.4 || ^6.2", - "symfony/config": "^5.4 || ^6.2", - "symfony/console": "^5.4 || ^6.2", - "symfony/dependency-injection": "^5.4 || ^6.2", - "symfony/doctrine-bridge": "^5.4 || ^6.2", - "symfony/event-dispatcher": "^5.4 || ^6.2", + "symfony/asset": "^5.4 || ^6.2 || ^7.0", + "symfony/config": "^5.4 || ^6.2 || ^7.0", + "symfony/console": "^5.4 || ^6.2 || ^7.0", + "symfony/dependency-injection": "^5.4 || ^6.2 || ^7.0", + "symfony/doctrine-bridge": "^5.4 || ^6.2 || ^7.0", + "symfony/event-dispatcher": "^5.4 || ^6.2 || ^7.0", "symfony/event-dispatcher-contracts": "^2.0 || ^3.0", - "symfony/expression-language": "^5.4 || ^6.2", - "symfony/form": "^5.4 || ^6.2", - "symfony/framework-bundle": "^5.4 || ^6.2", - "symfony/http-foundation": "^5.4 || ^6.2", - "symfony/http-kernel": "^5.4 || ^6.2", - "symfony/options-resolver": "^5.4 || ^6.2", - "symfony/property-access": "^5.4 || ^6.2", - "symfony/routing": "^5.4 || ^6.2", + "symfony/expression-language": "^5.4 || ^6.2 || ^7.0", + "symfony/form": "^5.4 || ^6.2 || ^7.0", + "symfony/framework-bundle": "^5.4 || ^6.2 || ^7.0", + "symfony/http-foundation": "^5.4 || ^6.2 || ^7.0", + "symfony/http-kernel": "^5.4 || ^6.2 || ^7.0", + "symfony/options-resolver": "^5.4 || ^6.2 || ^7.0", + "symfony/property-access": "^5.4 || ^6.2 || ^7.0", + "symfony/routing": "^5.4 || ^6.2 || ^7.0", "symfony/security-acl": "^3.1", - "symfony/security-bundle": "^5.4 || ^6.2", - "symfony/security-core": "^5.4 || ^6.2", - "symfony/security-csrf": "^5.4 || ^6.2", - "symfony/serializer": "^5.4 || ^6.2", - "symfony/string": "^5.4 || ^6.2", - "symfony/translation": "^5.4 || ^6.2", + "symfony/security-bundle": "^5.4 || ^6.2 || ^7.0", + "symfony/security-core": "^5.4 || ^6.2 || ^7.0", + "symfony/security-csrf": "^5.4 || ^6.2 || ^7.0", + "symfony/serializer": "^5.4 || ^6.2 || ^7.0", + "symfony/string": "^5.4 || ^6.2 || ^7.0", + "symfony/translation": "^5.4 || ^6.2 || ^7.0", "symfony/translation-contracts": "^2.3 || ^3.0", - "symfony/twig-bridge": "^5.4 || ^6.2", - "symfony/twig-bundle": "^5.4 || ^6.2", - "symfony/validator": "^5.4 || ^6.2", + "symfony/twig-bridge": "^5.4 || ^6.2 || ^7.0", + "symfony/twig-bundle": "^5.4 || ^6.2 || ^7.0", + "symfony/validator": "^5.4 || ^6.2 || ^7.0", "twig/string-extra": "^3.0", "twig/twig": "^3.0" }, "require-dev": { "friendsofphp/php-cs-fixer": "^3.4", - "matthiasnoback/symfony-config-test": "^4.2", - "matthiasnoback/symfony-dependency-injection-test": "^4.2", + "matthiasnoback/symfony-config-test": "^4.2 || ^5.0", + "matthiasnoback/symfony-dependency-injection-test": "^4.2 || ^5.0", "phpstan/extension-installer": "^1.0", "phpstan/phpstan": "^1.0", "phpstan/phpstan-phpunit": "^1.0", @@ -80,12 +80,12 @@ "psalm/plugin-symfony": "^5.0", "psr/event-dispatcher": "^1.0", "rector/rector": "^0.18", - "symfony/browser-kit": "^5.4 || ^6.2", - "symfony/css-selector": "^5.4 || ^6.2", - "symfony/filesystem": "^5.4 || ^6.2", + "symfony/browser-kit": "^5.4 || ^6.2 || ^7.0", + "symfony/css-selector": "^5.4 || ^6.2 || ^7.0", + "symfony/filesystem": "^5.4 || ^6.2 || ^7.0", "symfony/maker-bundle": "^1.25", - "symfony/phpunit-bridge": "^6.2", - "symfony/yaml": "^5.4 || ^6.2", + "symfony/phpunit-bridge": "^6.2 || ^7.0", + "symfony/yaml": "^5.4 || ^6.2 || ^7.0", "vimeo/psalm": "^5.8.0" }, "suggest": { diff --git a/src/Filter/Model/FilterData.php b/src/Filter/Model/FilterData.php index d4d8d1c6e2..64a247c864 100644 --- a/src/Filter/Model/FilterData.php +++ b/src/Filter/Model/FilterData.php @@ -43,8 +43,8 @@ public static function fromArray(array $data): self if (isset($data['type'])) { if (!\is_int($data['type']) && (!\is_string($data['type']) || !is_numeric($data['type']))) { throw new \InvalidArgumentException(sprintf( - 'The "type" parameter MUST be of type "integer" or "null", %s given.', - \is_object($data['type']) ? 'instance of "'.$data['type']::class.'"' : '"'.\gettype($data['type']).'"' + 'The "type" parameter MUST be of type "integer" or "null", "%s" given.', + \gettype($data['type']) )); } diff --git a/src/Form/Type/Filter/DateTimeRangeType.php b/src/Form/Type/Filter/DateTimeRangeType.php index 1f56214619..464b553ec9 100644 --- a/src/Form/Type/Filter/DateTimeRangeType.php +++ b/src/Form/Type/Filter/DateTimeRangeType.php @@ -16,7 +16,6 @@ use Sonata\AdminBundle\Form\Type\Operator\DateRangeOperatorType; use Sonata\Form\Type\DateTimeRangeType as FormDateTimeRangeType; use Symfony\Component\Form\AbstractType; -use Symfony\Component\Form\Extension\Core\Type\DateTimeType; use Symfony\Component\OptionsResolver\OptionsResolver; /** @@ -46,7 +45,7 @@ public function configureOptions(OptionsResolver $resolver): void 'operator_type' => DateRangeOperatorType::class, 'field_type' => FormDateTimeRangeType::class, 'field_options' => [ - 'field_options' => ['date_format' => DateTimeType::HTML5_FORMAT], + 'field_options' => [], ], ]); } diff --git a/src/Form/Type/Filter/DateTimeType.php b/src/Form/Type/Filter/DateTimeType.php index 67efae6dcd..4365a81103 100644 --- a/src/Form/Type/Filter/DateTimeType.php +++ b/src/Form/Type/Filter/DateTimeType.php @@ -16,7 +16,6 @@ use Sonata\AdminBundle\Form\Type\Operator\DateOperatorType; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\Extension\Core\Type\DateTimeType as FormDateTimeType; -use Symfony\Component\Form\Extension\Core\Type\DateType; use Symfony\Component\OptionsResolver\OptionsResolver; /** @@ -45,7 +44,7 @@ public function configureOptions(OptionsResolver $resolver): void $resolver->setDefaults([ 'operator_type' => DateOperatorType::class, 'field_type' => FormDateTimeType::class, - 'field_options' => ['date_format' => DateType::HTML5_FORMAT], + 'field_options' => [], ]); } } diff --git a/src/Route/RoutesCacheWarmUp.php b/src/Route/RoutesCacheWarmUp.php index 6876c4077f..4d1208fcb8 100644 --- a/src/Route/RoutesCacheWarmUp.php +++ b/src/Route/RoutesCacheWarmUp.php @@ -35,7 +35,7 @@ public function isOptional(): bool /** * @return string[] */ - public function warmUp(string $cacheDir): array + public function warmUp(string $cacheDir, ?string $buildDir = null): array { foreach ($this->pool->getAdminServiceCodes() as $code) { $this->cache->load($this->pool->getInstance($code)); diff --git a/src/Security/Handler/AclSecurityHandler.php b/src/Security/Handler/AclSecurityHandler.php index 4fb5e915f1..11bf10131f 100644 --- a/src/Security/Handler/AclSecurityHandler.php +++ b/src/Security/Handler/AclSecurityHandler.php @@ -74,9 +74,9 @@ public function __construct( $this->superAdminRoles = [$superAdminRoles]; } else { throw new \TypeError(sprintf( - 'Argument 1 passed to "%s()" must be of type "array" or "string", %s given.', + 'Argument 1 passed to "%s()" must be of type "array" or "string", "%s" given.', __METHOD__, - \is_object($superAdminRoles) ? 'instance of "'.$superAdminRoles::class.'"' : '"'.\gettype($superAdminRoles).'"' + \gettype($superAdminRoles) )); } } diff --git a/src/Security/Handler/RoleSecurityHandler.php b/src/Security/Handler/RoleSecurityHandler.php index 1c9ac0acba..9640870966 100644 --- a/src/Security/Handler/RoleSecurityHandler.php +++ b/src/Security/Handler/RoleSecurityHandler.php @@ -48,9 +48,9 @@ public function __construct( $this->superAdminRoles = [$superAdminRoles]; } else { throw new \TypeError(sprintf( - 'Argument 1 passed to "%s()" must be of type "array" or "string", %s given.', + 'Argument 1 passed to "%s()" must be of type "array" or "string", "%s" given.', __METHOD__, - \is_object($superAdminRoles) ? 'instance of "'.$superAdminRoles::class.'"' : '"'.\gettype($superAdminRoles).'"' + \gettype($superAdminRoles) )); } } diff --git a/src/Util/TraversableToCollection.php b/src/Util/TraversableToCollection.php index 819827967d..434a794042 100644 --- a/src/Util/TraversableToCollection.php +++ b/src/Util/TraversableToCollection.php @@ -51,9 +51,9 @@ public static function transform($value): Collection } throw new \TypeError(sprintf( - 'Argument 1 passed to "%s()" must be an iterable, %s given.', + 'Argument 1 passed to "%s()" must be an iterable, "%s" given.', __METHOD__, - \is_object($value) ? 'instance of "'.$value::class.'"' : '"'.\gettype($value).'"' + \gettype($value) )); } } diff --git a/tests/Filter/Model/FilterDataTest.php b/tests/Filter/Model/FilterDataTest.php index 40d50ebd24..762f0ad041 100644 --- a/tests/Filter/Model/FilterDataTest.php +++ b/tests/Filter/Model/FilterDataTest.php @@ -25,8 +25,8 @@ public function testTypeMustBeNumericOrNull(mixed $type): void { $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessage(sprintf( - 'The "type" parameter MUST be of type "integer" or "null", %s given.', - \is_object($type) ? 'instance of "'.$type::class.'"' : '"'.\gettype($type).'"' + 'The "type" parameter MUST be of type "integer" or "null", "%s" given.', + \gettype($type) )); // @phpstan-ignore-next-line diff --git a/tests/Filter/Persister/SessionFilterPersisterTest.php b/tests/Filter/Persister/SessionFilterPersisterTest.php index feb9c4661e..737dd793b6 100644 --- a/tests/Filter/Persister/SessionFilterPersisterTest.php +++ b/tests/Filter/Persister/SessionFilterPersisterTest.php @@ -71,8 +71,7 @@ public function testSetValueToSession(): void DatagridInterface::PER_PAGE => 25, ]; $this->session->expects(static::once())->method('set') - ->with('admin.customer.filter.parameters', $filters) - ->willReturn(null); + ->with('admin.customer.filter.parameters', $filters); $this->createPersister()->set('admin.customer', $filters); } diff --git a/tests/Form/AdminLayoutTest.php b/tests/Form/AdminLayoutTest.php index 6ae308bdec..c4c7a705e4 100644 --- a/tests/Form/AdminLayoutTest.php +++ b/tests/Form/AdminLayoutTest.php @@ -146,7 +146,10 @@ public function testRowSetId(): void $view = $form->createView(); $html = $this->renderRow($view); - self::assertMatchesXpath($html, '//div[@class="form-group"][@id="sonata-ba-field-container-name"]'); + static::assertStringContainsString( + '
', + $html + ); } public function testRowWithErrors(): void @@ -158,7 +161,10 @@ public function testRowWithErrors(): void $view = $form->createView(); $html = $this->renderRow($view); - self::assertMatchesXpath($html, '/div[@class="form-group has-error"][@id="sonata-ba-field-container-name"]'); + static::assertStringContainsString( + '
', + $html + ); } public function testErrors(): void @@ -208,9 +214,9 @@ public function testRowAttr(): void $view = $form->createView(); $html = $this->renderRow($view); - self::assertMatchesXpath( - $html, - '//div[@class="foo form-group"][@data-value="bar"][@id="sonata-ba-field-container-name"]' + static::assertStringContainsString( + '
', + $html ); } diff --git a/tests/Form/Type/Filter/DateTimeRangeTypeTest.php b/tests/Form/Type/Filter/DateTimeRangeTypeTest.php index 7fc9454274..559d53232c 100644 --- a/tests/Form/Type/Filter/DateTimeRangeTypeTest.php +++ b/tests/Form/Type/Filter/DateTimeRangeTypeTest.php @@ -16,7 +16,6 @@ use Sonata\AdminBundle\Form\Type\Filter\DateTimeRangeType; use Sonata\AdminBundle\Form\Type\Operator\DateRangeOperatorType; use Sonata\Form\Type\DateTimeRangeType as FormDateTimeRangeType; -use Symfony\Component\Form\Extension\Core\Type\DateTimeType; use Symfony\Component\OptionsResolver\OptionsResolver; /** @@ -52,7 +51,7 @@ public function testGetDefaultOptions(): void $expected = [ 'operator_type' => DateRangeOperatorType::class, 'field_type' => FormDateTimeRangeType::class, - 'field_options' => ['field_options' => ['date_format' => DateTimeType::HTML5_FORMAT]], + 'field_options' => ['field_options' => []], ]; static::assertSame($expected, $options); } diff --git a/tests/Form/Widget/FormChoiceWidgetTest.php b/tests/Form/Widget/FormChoiceWidgetTest.php index 385312ca8a..75057ce8d9 100644 --- a/tests/Form/Widget/FormChoiceWidgetTest.php +++ b/tests/Form/Widget/FormChoiceWidgetTest.php @@ -15,6 +15,7 @@ use Symfony\Component\Form\Extension\Core\Type\ChoiceType; use Symfony\Component\Form\FormTypeInterface; +use Symfony\Component\HttpKernel\Kernel; final class FormChoiceWidgetTest extends BaseWidgetTest { @@ -40,10 +41,17 @@ public function testLabelRendering(): void $html = $this->renderWidget($choice->createView()); - static::assertStringContainsString( - '
  • ', - $this->cleanHtmlWhitespace($html) - ); + if (0 !== preg_match("/7\..\../", Kernel::VERSION)) { + static::assertStringContainsString( + '
  • ', + $this->cleanHtmlWhitespace($html) + ); + } else { + static::assertStringContainsString( + '
  • ', + $this->cleanHtmlWhitespace($html) + ); + } } public function testDefaultValueRendering(): void diff --git a/tests/Util/TraversableToCollectionTest.php b/tests/Util/TraversableToCollectionTest.php index 96c1d8e41e..1dd6f1a958 100644 --- a/tests/Util/TraversableToCollectionTest.php +++ b/tests/Util/TraversableToCollectionTest.php @@ -74,6 +74,6 @@ public function provideFailedTransformCases(): iterable yield ['"integer"', 0]; yield ['"integer"', 1]; yield ['"string"', 'a']; - yield ['instance of "stdClass"', new \stdClass()]; + yield ['"object"', new \stdClass()]; } } From 87d392dd49af5d928c1d0ddcd3a77eb2db15ac76 Mon Sep 17 00:00:00 2001 From: SonataCI Date: Sat, 25 Nov 2023 12:12:08 +0000 Subject: [PATCH 2/3] DevKit updates --- .github/workflows/test.yaml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 655f0fe256..f9a7e616d4 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -57,11 +57,6 @@ jobs: allowed-to-fail: false symfony-require: 6.3.* variant: symfony/symfony:"6.3.*" - - php-version: '8.2' - dependencies: highest - allowed-to-fail: false - symfony-require: 7.0.* - variant: symfony/symfony:"7.0.*" steps: - name: Checkout From d327aa08872f99f343086257dfa325db0386e5bd Mon Sep 17 00:00:00 2001 From: Vincent Langlet Date: Sat, 25 Nov 2023 14:13:56 +0100 Subject: [PATCH 3/3] 4.29.0 (#8130) --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 48008e6fe7..815f6c99b6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +## [4.29.0](https://github.com/sonata-project/SonataAdminBundle/compare/4.28.1...4.29.0) - 2023-11-25 +### Added +- [[#8127](https://github.com/sonata-project/SonataAdminBundle/pull/8127)] Symfony 7 support ([@VincentLanglet](https://github.com/VincentLanglet)) + ## [4.28.1](https://github.com/sonata-project/SonataAdminBundle/compare/4.28.0...4.28.1) - 2023-11-20 ### Fixed - [[#8125](https://github.com/sonata-project/SonataAdminBundle/pull/8125)] Needing to submit form twice when using CRUDController::render() ([@AntoineRoue](https://github.com/AntoineRoue))