diff --git a/.github/workflows/ci-linux.yaml b/.github/workflows/ci-linux.yaml index 2f0449821..1ea5a3ecb 100644 --- a/.github/workflows/ci-linux.yaml +++ b/.github/workflows/ci-linux.yaml @@ -52,6 +52,9 @@ jobs: - php-version: '8.1' symfony-version: '6.4.*' dependency-versions: 'lowest' + - php-version: '8.4' + symfony-version: '^8.0.0-BETA1' + dependency-versions: 'highest' steps: - name: Checkout code diff --git a/composer.json b/composer.json index 28b0594f1..dc5d5b767 100644 --- a/composer.json +++ b/composer.json @@ -12,30 +12,30 @@ } ], "minimum-stability": "dev", - "prefer-stable": true, "require": { "php": ">=8.1", "doctrine/inflector": "^2.0", "nikic/php-parser": "^5.0", - "symfony/config": "^6.4|^7.0", - "symfony/console": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", + "symfony/config": "^6.4|^7.0|^8.0", + "symfony/console": "^6.4|^7.0|^8.0", + "symfony/dependency-injection": "^6.4|^7.0|^8.0", "symfony/deprecation-contracts": "^2.2|^3", - "symfony/filesystem": "^6.4|^7.0", - "symfony/finder": "^6.4|^7.0", - "symfony/framework-bundle": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/process": "^6.4|^7.0" + "symfony/filesystem": "^6.4|^7.0|^8.0", + "symfony/finder": "^6.4|^7.0|^8.0", + "symfony/framework-bundle": "^6.4|^7.0|^8.0", + "symfony/http-kernel": "^6.4|^7.0|^8.0", + "symfony/process": "^6.4|^7.0|^8.0" }, "require-dev": { "composer/semver": "^3.0", - "doctrine/doctrine-bundle": "^2.5.0", + "doctrine/doctrine-bundle": "^2.5.0|^3.0.0", "doctrine/orm": "^2.15|^3", - "symfony/http-client": "^6.4|^7.0", - "symfony/phpunit-bridge": "^6.4.1|^7.0", - "symfony/security-core": "^6.4|^7.0", - "symfony/security-http": "^6.4|^7.0", - "symfony/yaml": "^6.4|^7.0", + "doctrine/persistence": "^3.1|^4.0", + "symfony/http-client": "^6.4|^7.0|^8.0", + "symfony/phpunit-bridge": "^6.4.1|^7.0|^8.0", + "symfony/security-core": "^6.4|^7.0|^8.0", + "symfony/security-http": "^6.4|^7.0|^8.0", + "symfony/yaml": "^6.4|^7.0|^8.0", "twig/twig": "^3.0|^4.x-dev" }, "config": { diff --git a/config/makers.php b/config/makers.php new file mode 100644 index 000000000..91a0a68cd --- /dev/null +++ b/config/makers.php @@ -0,0 +1,201 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Loader\Configurator; + +use Symfony\Bundle\MakerBundle\Maker\MakeAuthenticator; +use Symfony\Bundle\MakerBundle\Maker\MakeCommand; +use Symfony\Bundle\MakerBundle\Maker\MakeController; +use Symfony\Bundle\MakerBundle\Maker\MakeCrud; +use Symfony\Bundle\MakerBundle\Maker\MakeDockerDatabase; +use Symfony\Bundle\MakerBundle\Maker\MakeEntity; +use Symfony\Bundle\MakerBundle\Maker\MakeFixtures; +use Symfony\Bundle\MakerBundle\Maker\MakeForm; +use Symfony\Bundle\MakerBundle\Maker\MakeFunctionalTest; +use Symfony\Bundle\MakerBundle\Maker\MakeMessengerMiddleware; +use Symfony\Bundle\MakerBundle\Maker\MakeRegistrationForm; +use Symfony\Bundle\MakerBundle\Maker\MakeResetPassword; +use Symfony\Bundle\MakerBundle\Maker\MakeSchedule; +use Symfony\Bundle\MakerBundle\Maker\MakeSerializerEncoder; +use Symfony\Bundle\MakerBundle\Maker\MakeSerializerNormalizer; +use Symfony\Bundle\MakerBundle\Maker\MakeStimulusController; +use Symfony\Bundle\MakerBundle\Maker\MakeSubscriber; +use Symfony\Bundle\MakerBundle\Maker\MakeTest; +use Symfony\Bundle\MakerBundle\Maker\MakeTwigComponent; +use Symfony\Bundle\MakerBundle\Maker\MakeTwigExtension; +use Symfony\Bundle\MakerBundle\Maker\MakeUnitTest; +use Symfony\Bundle\MakerBundle\Maker\MakeUser; +use Symfony\Bundle\MakerBundle\Maker\MakeValidator; +use Symfony\Bundle\MakerBundle\Maker\MakeVoter; +use Symfony\Bundle\MakerBundle\Maker\MakeWebhook; +use Symfony\Bundle\MakerBundle\Maker\Security\MakeCustomAuthenticator; +use Symfony\Bundle\MakerBundle\Maker\Security\MakeFormLogin; + +return static function (ContainerConfigurator $container) { + $services = $container->services(); + + $services->set('maker.maker.make_authenticator', MakeAuthenticator::class) + ->args([ + service('maker.file_manager'), + service('maker.security_config_updater'), + service('maker.generator'), + service('maker.doctrine_helper'), + service('maker.security_controller_builder'), + ]) + ->tag('maker.command'); + + $services->set('maker.maker.make_command', MakeCommand::class) + ->tag('maker.command'); + + $services->set('maker.maker.make_twig_component', MakeTwigComponent::class) + ->args([service('maker.file_manager')]) + ->tag('maker.command'); + + $services->set('maker.maker.make_controller', MakeController::class) + ->tag('maker.command'); + + $services->set('maker.maker.make_crud', MakeCrud::class) + ->args([ + service('maker.doctrine_helper'), + service('maker.renderer.form_type_renderer'), + ]) + ->tag('maker.command'); + + $services->set('maker.maker.make_docker_database', MakeDockerDatabase::class) + ->args([service('maker.file_manager')]) + ->tag('maker.command'); + + $services->set('maker.maker.make_entity', MakeEntity::class) + ->args([ + service('maker.file_manager'), + service('maker.doctrine_helper'), + null, + service('maker.generator'), + service('maker.entity_class_generator'), + ]) + ->tag('maker.command'); + + $services->set('maker.maker.make_fixtures', MakeFixtures::class) + ->tag('maker.command'); + + $services->set('maker.maker.make_form', MakeForm::class) + ->args([ + service('maker.doctrine_helper'), + service('maker.renderer.form_type_renderer'), + ]) + ->tag('maker.command'); + + $services->set('maker.maker.make_functional_test', MakeFunctionalTest::class) + ->tag('maker.command') + ->deprecate('symfony/maker-bundle', '1.29', 'The "%service_id%" service is deprecated, use "maker.maker.make_test" instead.'); + + $services->set('maker.maker.make_listener', \Symfony\Bundle\MakerBundle\Maker\MakeListener::class) + ->args([service('maker.event_registry')]) + ->tag('maker.command'); + + $services->set('maker.maker.make_message', \Symfony\Bundle\MakerBundle\Maker\MakeMessage::class) + ->args([service('maker.file_manager')]) + ->tag('maker.command'); + + $services->set('maker.maker.make_messenger_middleware', MakeMessengerMiddleware::class) + ->tag('maker.command'); + + $services->set('maker.maker.make_registration_form', MakeRegistrationForm::class) + ->args([ + service('maker.file_manager'), + service('maker.renderer.form_type_renderer'), + service('maker.doctrine_helper'), + service('router')->ignoreOnInvalid(), + ]) + ->tag('maker.command'); + + $services->set('maker.maker.make_reset_password', MakeResetPassword::class) + ->args([ + service('maker.file_manager'), + service('maker.doctrine_helper'), + service('maker.entity_class_generator'), + service('router')->ignoreOnInvalid(), + ]) + ->tag('maker.command'); + + $services->set('maker.maker.make_schedule', MakeSchedule::class) + ->args([service('maker.file_manager')]) + ->tag('maker.command'); + + $services->set('maker.maker.make_serializer_encoder', MakeSerializerEncoder::class) + ->tag('maker.command'); + + $services->set('maker.maker.make_serializer_normalizer', MakeSerializerNormalizer::class) + ->tag('maker.command'); + + $services->set('maker.maker.make_subscriber', MakeSubscriber::class) + ->args([service('maker.event_registry')]) + ->tag('maker.command') + ->deprecate('symfony/maker-bundle', '1.51', 'The "%service_id%" service is deprecated, use "maker.maker.make_listener" instead.'); + + $services->set('maker.maker.make_twig_extension', MakeTwigExtension::class) + ->tag('maker.command'); + + $services->set('maker.maker.make_test', MakeTest::class) + ->tag('maker.command'); + + $services->set('maker.maker.make_unit_test', MakeUnitTest::class) + ->tag('maker.command') + ->deprecate('symfony/maker-bundle', '1.29', 'The "%service_id%" service is deprecated, use "maker.maker.make_test" instead.'); + + $services->set('maker.maker.make_validator', MakeValidator::class) + ->tag('maker.command'); + + $services->set('maker.maker.make_voter', MakeVoter::class) + ->tag('maker.command'); + + $services->set('maker.maker.make_user', MakeUser::class) + ->args([ + service('maker.file_manager'), + service('maker.user_class_builder'), + service('maker.security_config_updater'), + service('maker.entity_class_generator'), + service('maker.doctrine_helper'), + ]) + ->tag('maker.command'); + + $services->set('maker.maker.make_migration', \Symfony\Bundle\MakerBundle\Maker\MakeMigration::class) + ->args([ + '%kernel.project_dir%', + service('maker.file_link_formatter'), + ]) + ->tag('maker.command'); + + $services->set('maker.maker.make_stimulus_controller', MakeStimulusController::class) + ->tag('maker.command'); + + $services->set('maker.maker.make_form_login', MakeFormLogin::class) + ->args([ + service('maker.file_manager'), + service('maker.security_config_updater'), + service('maker.security_controller_builder'), + ]) + ->tag('maker.command'); + + $services->set('maker.maker.make_custom_authenticator', MakeCustomAuthenticator::class) + ->args([ + service('maker.file_manager'), + service('maker.generator'), + ]) + ->tag('maker.command'); + + $services->set('maker.maker.make_webhook', MakeWebhook::class) + ->args([ + service('maker.file_manager'), + service('maker.generator'), + ]) + ->tag('maker.command'); +}; diff --git a/config/makers.xml b/config/makers.xml deleted file mode 100644 index ad7d45483..000000000 --- a/config/makers.xml +++ /dev/null @@ -1,175 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - null - - - - - - - - - - - - - - - - - - The "%service_id%" service is deprecated, use "maker.maker.make_test" instead. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - The "%service_id%" service is deprecated, use "maker.maker.make_listener" instead. - - - - - - - - - - - - - The "%service_id%" service is deprecated, use "maker.maker.make_test" instead. - - - - - - - - - - - - - - - - - - - - - %kernel.project_dir% - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/config/services.php b/config/services.php new file mode 100644 index 000000000..9583d65cf --- /dev/null +++ b/config/services.php @@ -0,0 +1,112 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Loader\Configurator; + +use Symfony\Bundle\MakerBundle\Command\MakerCommand; +use Symfony\Bundle\MakerBundle\Doctrine\DoctrineHelper; +use Symfony\Bundle\MakerBundle\Doctrine\EntityClassGenerator; +use Symfony\Bundle\MakerBundle\Event\ConsoleErrorSubscriber; +use Symfony\Bundle\MakerBundle\EventRegistry; +use Symfony\Bundle\MakerBundle\FileManager; +use Symfony\Bundle\MakerBundle\Generator; +use Symfony\Bundle\MakerBundle\Renderer\FormTypeRenderer; +use Symfony\Bundle\MakerBundle\Security\SecurityConfigUpdater; +use Symfony\Bundle\MakerBundle\Security\SecurityControllerBuilder; +use Symfony\Bundle\MakerBundle\Security\UserClassBuilder; +use Symfony\Bundle\MakerBundle\Util\AutoloaderUtil; +use Symfony\Bundle\MakerBundle\Util\ComposerAutoloaderFinder; +use Symfony\Bundle\MakerBundle\Util\MakerFileLinkFormatter; +use Symfony\Bundle\MakerBundle\Util\PhpCompatUtil; +use Symfony\Bundle\MakerBundle\Util\TemplateComponentGenerator; +use Symfony\Bundle\MakerBundle\Util\TemplateLinter; + +return static function (ContainerConfigurator $container) { + $services = $container->services(); + + $services->set('maker.file_manager', FileManager::class) + ->args([ + service('filesystem'), + service('maker.autoloader_util'), + service('maker.file_link_formatter'), + '%kernel.project_dir%', + '%twig.default_path%', + ]); + + $services->set('maker.autoloader_finder', ComposerAutoloaderFinder::class) + ->args(['']); + + $services->set('maker.autoloader_util', AutoloaderUtil::class) + ->args([service('maker.autoloader_finder')]); + + $services->set('maker.file_link_formatter', MakerFileLinkFormatter::class) + ->args([service('debug.file_link_formatter')->ignoreOnInvalid()]); + + $services->set('maker.event_registry', EventRegistry::class) + ->args([service('event_dispatcher')]); + + $services->set('maker.console_error_listener', ConsoleErrorSubscriber::class) + ->tag('kernel.event_subscriber'); + + $services->set('maker.doctrine_helper', DoctrineHelper::class) + ->args([ + '', + service('doctrine')->ignoreOnInvalid(), + ]); + + $services->set('maker.template_linter', TemplateLinter::class) + ->args([ + '%env(default::string:MAKER_PHP_CS_FIXER_BINARY_PATH)%', + '%env(default::string:MAKER_PHP_CS_FIXER_CONFIG_PATH)%', + ]); + + $services->set('maker.auto_command.abstract', MakerCommand::class) + ->abstract() + ->args([ + '', + service('maker.file_manager'), + service('maker.generator'), + service('maker.template_linter'), + ]); + + $services->set('maker.generator', Generator::class) + ->args([ + service('maker.file_manager'), + '', + null, + service('maker.template_component_generator'), + ]); + + $services->set('maker.entity_class_generator', EntityClassGenerator::class) + ->args([ + service('maker.generator'), + service('maker.doctrine_helper'), + ]); + + $services->set('maker.user_class_builder', UserClassBuilder::class); + + $services->set('maker.security_config_updater', SecurityConfigUpdater::class); + + $services->set('maker.renderer.form_type_renderer', FormTypeRenderer::class) + ->args([service('maker.generator')]); + + $services->set('maker.security_controller_builder', SecurityControllerBuilder::class); + + $services->set('maker.php_compat_util', PhpCompatUtil::class) + ->args([service('maker.file_manager')]); + + $services->set('maker.template_component_generator', TemplateComponentGenerator::class) + ->args([ + '', + '', + '', + ]); +}; diff --git a/config/services.xml b/config/services.xml deleted file mode 100644 index 5fbc0439b..000000000 --- a/config/services.xml +++ /dev/null @@ -1,88 +0,0 @@ - - - - - - - - - - - - %kernel.project_dir% - %twig.default_path% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - %env(default::string:MAKER_PHP_CS_FIXER_BINARY_PATH)% - %env(default::string:MAKER_PHP_CS_FIXER_CONFIG_PATH)% - - - - - - - - - - - - - null - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/MakerBundle.php b/src/MakerBundle.php index 42516aec8..8c7231e6c 100644 --- a/src/MakerBundle.php +++ b/src/MakerBundle.php @@ -41,8 +41,8 @@ public function configure(DefinitionConfigurator $definition): void public function loadExtension(array $config, ContainerConfigurator $container, ContainerBuilder $builder): void { - $container->import('../config/services.xml'); - $container->import('../config/makers.xml'); + $container->import('../config/services.php'); + $container->import('../config/makers.php'); $rootNamespace = trim($config['root_namespace'], '\\'); diff --git a/src/Test/MakerTestEnvironment.php b/src/Test/MakerTestEnvironment.php index f7af580ff..a1f5bdd6a 100644 --- a/src/Test/MakerTestEnvironment.php +++ b/src/Test/MakerTestEnvironment.php @@ -275,12 +275,14 @@ private function buildFlexSkeleton(): void 'filename' => '.env.test', 'find' => 'SYMFONY_DEPRECATIONS_HELPER=999999', 'replace' => 'SYMFONY_DEPRECATIONS_HELPER=max[self]=0', + 'allow_not_found' => true, // Not present in PHPUnit 11+ recipe ], // do not explicitly set the PHPUnit version [ 'filename' => 'phpunit.xml.dist', 'find' => '', 'replace' => '', + 'allow_not_found' => true, // Not present in PHPUnit 10+ recipe ], ]; $this->processReplacements($replacements, $this->flexPath); @@ -297,7 +299,7 @@ private function buildFlexSkeleton(): void private function processReplacements(array $replacements, string $rootDir): void { foreach ($replacements as $replacement) { - $this->processReplacement($rootDir, $replacement['filename'], $replacement['find'], $replacement['replace']); + $this->processReplacement($rootDir, $replacement['filename'], $replacement['find'], $replacement['replace'], $replacement['allow_not_found'] ?? false); } } diff --git a/src/Test/MakerTestKernel.php b/src/Test/MakerTestKernel.php index 1938dfecd..fcefa1aaf 100644 --- a/src/Test/MakerTestKernel.php +++ b/src/Test/MakerTestKernel.php @@ -75,10 +75,7 @@ public function getRootDir(): string return $this->testRootDir; } - /** - * @return void - */ - public function process(ContainerBuilder $container) + public function process(ContainerBuilder $container): void { // makes all makers public to help the tests foreach ($container->findTaggedServiceIds(MakeCommandRegistrationPass::MAKER_TAG) as $id => $tags) { diff --git a/tests/Doctrine/EntityRegeneratorTest.php b/tests/Doctrine/EntityRegeneratorTest.php index 5a8f07e5f..bb1f3c264 100644 --- a/tests/Doctrine/EntityRegeneratorTest.php +++ b/tests/Doctrine/EntityRegeneratorTest.php @@ -11,8 +11,8 @@ namespace Symfony\Bundle\MakerBundle\Tests\Doctrine; +use Composer\InstalledVersions; use Doctrine\Bundle\DoctrineBundle\DoctrineBundle; -use Doctrine\Persistence\Reflection\RuntimeReflectionProperty; use PHPUnit\Framework\TestCase; use Symfony\Bundle\FrameworkBundle\FrameworkBundle; use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait; @@ -175,9 +175,13 @@ protected function configureContainer(ContainerBuilder $c, LoaderInterface $load ], ]; - /* @legacy Remove conditional when doctrine/persistence <3.1 are no longer supported. */ - if (class_exists(RuntimeReflectionProperty::class)) { - $orm['enable_lazy_ghost_objects'] = true; + if (null !== $doctrineBundleVersion = InstalledVersions::getVersion('doctrine/doctrine-bundle')) { + if (version_compare($doctrineBundleVersion, '2.8.0', '>=')) { + $orm['enable_lazy_ghost_objects'] = true; + } + if (\PHP_VERSION_ID >= 80400 && version_compare($doctrineBundleVersion, '2.15.0', '>=')) { + $orm['enable_native_lazy_objects'] = true; + } } $c->prependExtensionConfig('doctrine', [ @@ -192,74 +196,6 @@ public function getProjectDir(): string } } -class TestXmlEntityRegeneratorKernel extends Kernel -{ - use MicroKernelTrait; - - public function registerBundles(): array - { - return [ - new FrameworkBundle(), - new DoctrineBundle(), - ]; - } - - protected function configureRoutes(RouteCollectionBuilder $routes): void - { - } - - protected function configureContainer(ContainerBuilder $c, LoaderInterface $loader): void - { - $c->loadFromExtension('framework', [ - 'secret' => 123, - 'router' => [ - 'utf8' => true, - ], - 'http_method_override' => false, - 'handle_all_throwables' => true, - 'php_errors' => [ - 'log' => true, - ], - ]); - - $dbal = [ - 'driver' => 'pdo_sqlite', - 'url' => 'sqlite:///fake', - ]; - - $orm = [ - 'auto_generate_proxy_classes' => true, - 'mappings' => [ - 'EntityRegenerator' => [ - 'is_bundle' => false, - 'type' => 'xml', - 'dir' => '%kernel.project_dir%/config/doctrine', - 'prefix' => 'Symfony\Bundle\MakerBundle\Tests\tmp\current_project_xml\src\Entity', - 'alias' => 'EntityRegeneratorApp', - ], - ], - 'controller_resolver' => [ - 'auto_mapping' => false, - ], - ]; - - /* @legacy Remove conditional when doctrine/persistence <3.1 are no longer supported. */ - if (class_exists(RuntimeReflectionProperty::class)) { - $orm['enable_lazy_ghost_objects'] = true; - } - - $c->prependExtensionConfig('doctrine', [ - 'dbal' => $dbal, - 'orm' => $orm, - ]); - } - - public function getProjectDir(): string - { - return __DIR__.'/../tmp/current_project_xml'; - } -} - class AllButTraitsIterator extends \RecursiveFilterIterator { public function accept(): bool diff --git a/tests/fixtures/make-form/tests/it_generates_form_with_many_to_many_relation.php b/tests/fixtures/make-form/tests/it_generates_form_with_many_to_many_relation.php index 5be663aa6..206689fe0 100644 --- a/tests/fixtures/make-form/tests/it_generates_form_with_many_to_many_relation.php +++ b/tests/fixtures/make-form/tests/it_generates_form_with_many_to_many_relation.php @@ -12,8 +12,8 @@ use Doctrine\ORM\Query; use Doctrine\ORM\QueryBuilder; use Doctrine\Persistence\ManagerRegistry; +use PHPUnit\Framework\Attributes\DataProvider; use Symfony\Bridge\Doctrine\Form\DoctrineOrmExtension; -use Symfony\Component\Form\PreloadedExtension; use Symfony\Component\Form\Test\TypeTestCase; class GeneratedFormTest extends TypeTestCase @@ -21,6 +21,7 @@ class GeneratedFormTest extends TypeTestCase /** * @dataProvider provideFormData */ + #[DataProvider('provideFormData')] public function testGeneratedFormWithMultipleChoices($formData, $collection) { $form = $this->factory->create(BookType::class); @@ -40,7 +41,7 @@ public function testGeneratedFormWithMultipleChoices($formData, $collection) } } - public function provideFormData(): iterable + public static function provideFormData(): iterable { yield 'test_submit_with_single_choice_selected' => [ @@ -52,7 +53,8 @@ public function provideFormData(): iterable (new Library())->setName('bar'), ]), ]; - yield ['test_submit_with_multiple_choices_selected' => + yield 'test_submit_with_multiple_choices_selected' => + [ [ 'title' => 'foobar', 'libraries' => [0, 1], @@ -62,7 +64,8 @@ public function provideFormData(): iterable (new Library())->setName('bar'), ]), ]; - yield ['test_submit_with_no_choice_selected' => + yield 'test_submit_with_no_choice_selected' => + [ [ 'title' => 'foobar', 'libraries' => [], diff --git a/tests/fixtures/make-twig-component/tests/it_generates_live_component.php b/tests/fixtures/make-twig-component/tests/it_generates_live_component.php index f45c9818e..01fc4b25a 100644 --- a/tests/fixtures/make-twig-component/tests/it_generates_live_component.php +++ b/tests/fixtures/make-twig-component/tests/it_generates_live_component.php @@ -4,7 +4,7 @@ use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; -class GeneratedTwigComponentTest extends KernelTestCase +class GeneratedLiveComponentTest extends KernelTestCase { public function testController() {