diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml index c04b9ef..20f21f6 100644 --- a/.github/workflows/php.yml +++ b/.github/workflows/php.yml @@ -10,6 +10,7 @@ jobs: build: runs-on: ubuntu-latest strategy: + fail-fast: false matrix: php-versions: ['7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3', '8.4', '8.5'] name: PHP ${{ matrix.php-versions }} @@ -51,7 +52,7 @@ jobs: run: composer validate --strict - name: Install dependencies - run: composer install --prefer-dist --no-progress + run: composer install --no-blocking --prefer-dist --no-progress - name: Run test suite run: composer run-script tests @@ -60,8 +61,25 @@ jobs: name: Compatibility between prime versions runs-on: ubuntu-latest strategy: + fail-fast: false matrix: - prime-versions: ['~1.2.0', '~1.3.0', '~2.0.0', '~2.1.0', '~2.2.0'] + versions: + - prime: '~1.2.0' + php: '8.0' + - prime: '~1.3.0' + php: '8.0' + - prime: '~2.0.0' + php: '8.0' + - prime: '~2.1.0' + php: '8.0' + - prime: '~2.2.0' + php: '8.0' + - prime: '~2.3.0' + php: '8.1' + - prime: '~3.0.0' + php: '8.4' + - prime: 'dev-chore-FRAM-232-modernize-code as 3.0.0' + php: '8.4' steps: - uses: actions/checkout@v2 @@ -74,7 +92,7 @@ jobs: - name: Install PHP uses: shivammathur/setup-php@v2 with: - php-version: 8.0 + php-version: ${{ matrix.versions.php }} extensions: json ini-values: date.timezone=Europe/Paris @@ -94,8 +112,8 @@ jobs: FLUSH PRIVILEGES; EOF - - name: Install prime ${{ matrix.prime-versions }} - run: composer require "b2pweb/bdf-prime:${{ matrix.prime-versions }}" --with-all-dependencies + - name: Install prime ${{ matrix.versions.prime }} + run: composer require --no-blocking "b2pweb/bdf-prime:${{ matrix.versions.prime }}" --with-all-dependencies - name: Run test suite run: composer run-script tests @@ -139,7 +157,7 @@ jobs: uses: supercharge/mongodb-github-action@1.7.0 - name: Install mongo driver - run: composer require "b2pweb/bdf-prime-mongodb:~2.0" --with-all-dependencies + run: composer require --no-blocking "b2pweb/bdf-prime-mongodb:~2.0" --with-all-dependencies - name: Run test suite run: composer run-script tests @@ -183,7 +201,7 @@ jobs: uses: supercharge/mongodb-github-action@1.7.0 - name: Install mongo driver - run: composer require "b2pweb/bdf-prime-shell" --with-all-dependencies + run: composer require --no-blocking "b2pweb/bdf-prime-shell" --with-all-dependencies - name: Run test suite run: composer run-script tests @@ -224,7 +242,7 @@ jobs: EOF - name: Install symfony clock - run: composer require "symfony/clock" --with-all-dependencies + run: composer require --no-blocking "symfony/clock" --with-all-dependencies - name: Run test suite run: composer run-script tests diff --git a/DependencyInjection/Compiler/IgnorePrimeAnnotationsPass.php b/DependencyInjection/Compiler/IgnorePrimeAnnotationsPass.php index e482bbc..93c818f 100644 --- a/DependencyInjection/Compiler/IgnorePrimeAnnotationsPass.php +++ b/DependencyInjection/Compiler/IgnorePrimeAnnotationsPass.php @@ -11,7 +11,7 @@ */ class IgnorePrimeAnnotationsPass implements CompilerPassInterface { - public function process(ContainerBuilder $container) + public function process(ContainerBuilder $container): void { if (!class_exists(AnnotationReader::class)) { return; diff --git a/DependencyInjection/Compiler/PrimeConnectionFactoryPass.php b/DependencyInjection/Compiler/PrimeConnectionFactoryPass.php index 14f2de8..c538b02 100644 --- a/DependencyInjection/Compiler/PrimeConnectionFactoryPass.php +++ b/DependencyInjection/Compiler/PrimeConnectionFactoryPass.php @@ -24,7 +24,7 @@ public function __construct(string $service = ChainFactory::class, string $loade $this->tag = $loaderTag; } - public function process(ContainerBuilder $container) + public function process(ContainerBuilder $container): void { if (!$container->hasDefinition($this->service)) { return; diff --git a/DependencyInjection/Compiler/PrimeMiddlewarePass.php b/DependencyInjection/Compiler/PrimeMiddlewarePass.php index 3373e09..af83a3a 100644 --- a/DependencyInjection/Compiler/PrimeMiddlewarePass.php +++ b/DependencyInjection/Compiler/PrimeMiddlewarePass.php @@ -21,7 +21,7 @@ public function __construct(string $loaderTag = self::TAG) $this->tag = $loaderTag; } - public function process(ContainerBuilder $container) + public function process(ContainerBuilder $container): void { // Skip if middleware are not available on the installed version of doctrine/dbal if (!\interface_exists(Middleware::class)) { diff --git a/DependencyInjection/PrimeExtension.php b/DependencyInjection/PrimeExtension.php index 3ef1001..4f37863 100644 --- a/DependencyInjection/PrimeExtension.php +++ b/DependencyInjection/PrimeExtension.php @@ -2,6 +2,7 @@ namespace Bdf\PrimeBundle\DependencyInjection; +use Bdf\Prime\Cache\CachePoolAdapter; use Bdf\Prime\Cache\DoctrineCacheAdapter; use Bdf\Prime\Configuration as PrimeConfiguration; use Bdf\Prime\Connection\ConnectionRegistry; @@ -32,6 +33,7 @@ use Symfony\Bridge\Doctrine\Middleware\Debug\DebugDataHolder; use Symfony\Bridge\Doctrine\Middleware\Debug\Middleware as ProfilingMiddleware; use Symfony\Component\Cache\Psr16Cache; +use Symfony\Component\Config\Definition\ConfigurationInterface; use Symfony\Component\Config\FileLocator; use Symfony\Component\Config\Loader\FileLoader; use Symfony\Component\DependencyInjection\ChildDefinition; @@ -46,7 +48,7 @@ */ class PrimeExtension extends Extension { - public function load(array $configs, ContainerBuilder $container) + public function load(array $configs, ContainerBuilder $container): void { $configuration = $this->getConfiguration($configs, $container); $config = $this->processConfiguration($configuration, $configs); @@ -54,6 +56,7 @@ public function load(array $configs, ContainerBuilder $container) $loader = new YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); $loader->load('prime.yaml'); $loader->load('collector.yaml'); + $this->configureCollector($container); if (\class_exists(LoggerMiddleware::class)) { $loader->load('middlewares.yaml'); @@ -83,6 +86,7 @@ public function load(array $configs, ContainerBuilder $container) $container->setParameter('prime.locatorizable', $config['activerecord']); $this->configurePrime21($container); + $this->configureLegacyCommands($container); } public function configureConnection(array $config, ContainerBuilder $container) @@ -253,6 +257,35 @@ private function configurePrime21(ContainerBuilder $container): void } } + /** + * Register CLI commands deleted from prime 3.0, if exists. + */ + private function configureLegacyCommands(ContainerBuilder $container): void + { + if (\class_exists('Bdf\Prime\Console\GraphCommand')) { + $container->register('prime.graph_command', 'Bdf\Prime\Console\GraphCommand') + ->addArgument(new Reference(ServiceLocator::class)) + ->addTag('console.command') + ; + } + + if (\class_exists('Bdf\Prime\Console\MapperCommand')) { + $container->register('prime.mapper_command', 'Bdf\Prime\Console\MapperCommand') + ->addArgument(new Reference(ServiceLocator::class)) + ->addTag('console.command') + ; + } + } + + private function configureCollector(ContainerBuilder $container): void + { + if (\class_exists('Doctrine\DBAL\Logging\DebugStack')) { + $container->getDefinition(PrimeDataCollector::class) + ->addMethodCall('addLogger', ['', new Reference('prime.logger.profiling')]) + ; + } + } + public function mergeConfiguration(array $globalConfig, array $config): array { return [ @@ -287,6 +320,7 @@ public function createConfiguration(string $name, array $config, ContainerBuilde $logger = null; $supportsMiddleware = $container->hasDefinition('prime.middleware.logger'); + $supportsLegacySqlLogger = \method_exists(PrimeConfiguration::class, 'setSQLLogger'); // Mongo driver for Prime does not support middleware prior to introduction of MongoConnectionFactory // So we must use the legacy SQLLogger @@ -306,15 +340,17 @@ public function createConfiguration(string $name, array $config, ContainerBuilde } if ($config['profiling']) { - $profilingLogger = new Reference('prime.logger.profiling'); + if ($supportsLegacySqlLogger) { + $profilingLogger = new Reference('prime.logger.profiling'); - if (null !== $logger) { - $chainLogger = $container->findDefinition('prime.logger.chain'); - $chainLogger->replaceArgument(0, [$logger, $profilingLogger]); + if (null !== $logger) { + $chainLogger = $container->findDefinition('prime.logger.chain'); + $chainLogger->replaceArgument(0, [$logger, $profilingLogger]); - $logger = new Reference('prime.logger.chain'); - } else { - $logger = $profilingLogger; + $logger = new Reference('prime.logger.chain'); + } else { + $logger = $profilingLogger; + } } // Symfony 7 : new profiler middleware @@ -344,7 +380,7 @@ public function createConfiguration(string $name, array $config, ContainerBuilde } } - if ($logger) { + if ($logger && $supportsLegacySqlLogger) { $configuration->addMethodCall('setSQLLogger', [$logger]); } @@ -387,12 +423,17 @@ private function createResultCacheReference(string $namespace, array $config, Co if (isset($config['pool'])) { if (!$container->has($namespace)) { - $definition = $container->register($namespace.'.doctrine-provider', DoctrineProvider::class); - $definition->setFactory([DoctrineProvider::class, 'wrap']); - $definition->addArgument(new Reference($config['pool'])); - - $definition = $container->register($namespace, DoctrineCacheAdapter::class); - $definition->addArgument(new Reference($namespace.'.doctrine-provider')); + if (\class_exists(DoctrineCacheAdapter::class)) { + $definition = $container->register($namespace.'.doctrine-provider', DoctrineProvider::class); + $definition->setFactory([DoctrineProvider::class, 'wrap']); + $definition->addArgument(new Reference($config['pool'])); + + $definition = $container->register($namespace, DoctrineCacheAdapter::class); + $definition->addArgument(new Reference($namespace.'.doctrine-provider')); + } else { + $definition = $container->register($namespace, CachePoolAdapter::class); + $definition->addArgument(new Reference($config['pool'])); + } } return new Reference($namespace); @@ -449,7 +490,7 @@ private function cleanConnectionOptions(array $options): array return $options; } - public function getConfiguration(array $config, ContainerBuilder $container) + public function getConfiguration(array $config, ContainerBuilder $container): ?ConfigurationInterface { return new Configuration($container->getParameter('kernel.debug')); } diff --git a/Resources/config/collector.yaml b/Resources/config/collector.yaml index 6e585cb..a5abe4f 100644 --- a/Resources/config/collector.yaml +++ b/Resources/config/collector.yaml @@ -3,8 +3,6 @@ services: public: true class: 'Bdf\PrimeBundle\Collector\PrimeDataCollector' arguments: ['@Bdf\Prime\Persistence\PrimeManagerRegistry', false, null] - calls: - - ['addLogger', ['', '@prime.logger.profiling']] tags: - { name: 'data_collector', template: '@Doctrine/Collector/db.html.twig', id: 'db', 'priority': 250 } diff --git a/Resources/config/prime.yaml b/Resources/config/prime.yaml index 0b5d9db..4ac568b 100644 --- a/Resources/config/prime.yaml +++ b/Resources/config/prime.yaml @@ -199,13 +199,6 @@ services: tags: - { name: 'console.command' } - prime.graph_command: - class: 'Bdf\Prime\Console\GraphCommand' - arguments: - - '@prime' - tags: - - { name: 'console.command' } - prime.hydrator_command: class: 'Bdf\Prime\Console\HydratorGenerationCommand' arguments: @@ -214,13 +207,6 @@ services: tags: - { name: 'console.command' } - prime.mapper_command: - class: 'Bdf\Prime\Console\MapperCommand' - arguments: - - '@prime' - tags: - - { name: 'console.command' } - prime.upgrade_command: class: 'Bdf\Prime\Console\UpgraderCommand' arguments: diff --git a/TestingPrimeBundle.php b/TestingPrimeBundle.php index f63781b..2f3e0c8 100644 --- a/TestingPrimeBundle.php +++ b/TestingPrimeBundle.php @@ -13,13 +13,13 @@ */ class TestingPrimeBundle extends Bundle { - public function boot() + public function boot(): void { Prime::configure($this->container); TestPack::pack()->initialize(); } - public function shutdown() + public function shutdown(): void { TestPack::pack()->clear(); TestPack::pack()->destroy(); diff --git a/Tests/BdfPrimeBundleTest.php b/Tests/BdfPrimeBundleTest.php index 42540d1..6ede32a 100644 --- a/Tests/BdfPrimeBundleTest.php +++ b/Tests/BdfPrimeBundleTest.php @@ -5,6 +5,7 @@ require_once __DIR__.'/TestKernel.php'; use Bdf\Prime\Cache\ArrayCache; +use Bdf\Prime\Cache\CachePoolAdapter; use Bdf\Prime\Cache\DoctrineCacheAdapter; use Bdf\Prime\Configuration; use Bdf\Prime\Connection\Middleware\LoggerMiddleware; @@ -14,8 +15,10 @@ use Bdf\Prime\Locatorizable; use Bdf\Prime\Mapper\ContainerMapperFactory; use Bdf\Prime\Migration\MigrationManager; -use Bdf\Prime\Platform\Sql\Types\SqlStringType; +use Bdf\Prime\Platform\AbstractPlatformType; +use Bdf\Prime\Platform\PlatformInterface; use Bdf\Prime\Repository\EntityRepository; +use Bdf\Prime\Schema\ColumnInterface; use Bdf\Prime\Schema\RepositoryUpgrader; use Bdf\Prime\Schema\StructureUpgraderResolverAggregate; use Bdf\Prime\Schema\StructureUpgraderResolverInterface; @@ -23,6 +26,7 @@ use Bdf\Prime\Sharding\ShardingConnection; use Bdf\Prime\Sharding\ShardingQuery; use Bdf\Prime\Types\ArrayType; +use Bdf\Prime\Types\PhpTypeInterface; use Bdf\Prime\Types\TypeInterface; use Bdf\Prime\Types\UnitEnumType; use Bdf\PrimeBundle\Collector\PrimeDataCollector; @@ -40,6 +44,7 @@ use Bdf\PrimeBundle\Tests\Fixtures\WithInjection; use Doctrine\Common\Cache\Psr6\DoctrineProvider; use Doctrine\DBAL\Driver\Middleware; +use Doctrine\DBAL\Types\Types; use PHPUnit\Framework\TestCase; use Symfony\Bundle\FrameworkBundle\Console\Application; use Symfony\Bundle\FrameworkBundle\FrameworkBundle; @@ -96,7 +101,7 @@ public function testConsole() $this->assertInstanceOf(UpgraderCommand::class, $this->getCommand($console, 'prime:upgrade')); - if (class_exists(CriteriaCommand::class)) { + if (\class_exists(CriteriaCommand::class)) { $this->assertInstanceOf(CriteriaCommand::class, $this->getCommand($console, 'prime:criteria')); } @@ -124,7 +129,7 @@ public function testStructureUpgrader() $this->assertInstanceOf(StructureUpgraderResolverAggregate::class, $kernel->getContainer()->get(StructureUpgraderResolverAggregate::class)); $console = new Application($kernel); - $command = $this->getCommand($console, UpgraderCommand::getDefaultName()); + $command = $this->getCommand($console, 'prime:upgrade'); $r = new \ReflectionProperty($command, 'resolver'); PHP_VERSION_ID >= 80100 or $r->setAccessible(true); @@ -206,7 +211,7 @@ protected function configureRoutes(RouteCollectionBuilder $routes) $connection = $prime->connection('test.shard1'); $expectedConfig = $prime->connection('test')->getConfiguration(); - if (method_exists($expectedConfig, 'withName')) { + if (\method_exists($expectedConfig, 'withName')) { $expectedConfig = $expectedConfig->withName('test.shard1'); } @@ -272,7 +277,12 @@ protected function configureRoutes($routes) /** @var ServiceLocator $prime */ $prime = $kernel->getContainer()->get(ServiceLocator::class); - $this->assertEquals(new DoctrineCacheAdapter(DoctrineProvider::wrap(new FilesystemAdapter())), $prime->mappers()->getResultCache()); + + if (\class_exists(DoctrineCacheAdapter::class)) { + $this->assertEquals(new DoctrineCacheAdapter(DoctrineProvider::wrap(new FilesystemAdapter())), $prime->mappers()->getResultCache()); + } else { + $this->assertEquals(new CachePoolAdapter(new FilesystemAdapter()), $prime->mappers()->getResultCache()); + } } public function testGlobalConfig() @@ -305,15 +315,18 @@ protected function configureRoutes($routes) /** @var SimpleConnection $connection */ $connection = $prime->connection('test2'); - $this->assertNotNull($connection->getConfiguration()->getSQLLogger()); + if (\method_exists($connection->getConfiguration(), 'getSQLLogger')) { + $this->assertNotNull($connection->getConfiguration()->getSQLLogger()); + } + $this->assertTrue($connection->getConfiguration()->getAutoCommit()); $this->assertInstanceOf(FooType::class, $connection->getConfiguration()->getTypes()->get('foo')); $this->assertInstanceOf(BarType::class, $connection->getConfiguration()->getTypes()->get('bar')); $this->assertInstanceOf(ArrayType::class, $connection->getConfiguration()->getTypes()->get('array')); - if (class_exists(LoggerMiddleware::class) && (!class_exists(\Bdf\Prime\MongoDB\Collection\MongoCollectionLocator::class) || class_exists(\Bdf\Prime\MongoDB\Driver\MongoConnectionFactory::class))) { + if (\class_exists(LoggerMiddleware::class) && (!\class_exists(\Bdf\Prime\MongoDB\Collection\MongoCollectionLocator::class) || \class_exists(\Bdf\Prime\MongoDB\Driver\MongoConnectionFactory::class))) { $middlewares = $connection->getConfiguration()->getMiddlewares(); - $middlewares = array_values(array_filter($middlewares, function ($middleware) { return $middleware instanceof LoggerMiddleware; })); + $middlewares = \array_values(\array_filter($middlewares, function ($middleware) { return $middleware instanceof LoggerMiddleware; })); $this->assertNotEmpty($middlewares); $this->assertEquals($middlewares[0]->withConfiguration($connection->getConfiguration()), $middlewares[0]); @@ -398,11 +411,20 @@ protected function configureRoutes($routes) /** @var SimpleConnection $connection */ $connection = $prime->connection('test'); - $this->assertNull($connection->getConfiguration()->getSQLLogger()); + if (\method_exists($connection->getConfiguration(), 'getSQLLogger')) { + $this->assertNull($connection->getConfiguration()->getSQLLogger()); + } + $this->assertFalse($connection->getConfiguration()->getAutoCommit()); $this->assertInstanceOf(BarType::class, $connection->getConfiguration()->getTypes()->get('foo')); $this->assertInstanceOf(BarType::class, $connection->getConfiguration()->getTypes()->get('bar')); $this->assertInstanceOf(ArrayType::class, $connection->getConfiguration()->getTypes()->get('array')); + + if (\class_exists(LoggerMiddleware::class) && (!\class_exists(\Bdf\Prime\MongoDB\Collection\MongoCollectionLocator::class) || \class_exists(\Bdf\Prime\MongoDB\Driver\MongoConnectionFactory::class))) { + $middlewares = $connection->getConfiguration()->getMiddlewares(); + $middlewares = \array_values(\array_filter($middlewares, function ($middleware) { return $middleware instanceof LoggerMiddleware; })); + $this->assertEmpty($middlewares); + } } /** @@ -437,7 +459,7 @@ public function testCustomPlatformTypesNotSupported() { $this->expectExceptionMessage('Define platform types is only supported by bdf-prime version >= 2.1'); - if (method_exists(Configuration::class, 'addPlatformType')) { + if (\method_exists(Configuration::class, 'addPlatformType')) { $this->markTestSkipped(); } @@ -467,7 +489,7 @@ protected function configureRoutes($routes) public function testCustomPlatformTypes() { - if (!method_exists(Configuration::class, 'addPlatformType')) { + if (!\method_exists(Configuration::class, 'addPlatformType')) { $this->markTestSkipped(); } @@ -500,7 +522,7 @@ protected function configureRoutes($routes) public function testMapperDependencyInjection() { - if (!class_exists(ContainerMapperFactory::class)) { + if (!\class_exists(ContainerMapperFactory::class)) { $this->markTestSkipped('ContainerMapperFactory is not available'); } @@ -513,7 +535,7 @@ public function testMapperDependencyInjection() public function testEnumTypes() { - if (PHP_VERSION_ID < 80100 || !class_exists(UnitEnumType::class)) { + if (PHP_VERSION_ID < 80100 || !\class_exists(UnitEnumType::class)) { $this->markTestSkipped(); } @@ -543,7 +565,7 @@ public function testEnumTypes() public function testInjectRepositoryWithAttribute() { - if (PHP_VERSION_ID < 80100 || !class_exists(AutowireInline::class)) { + if (PHP_VERSION_ID < 80100 || !\class_exists(AutowireInline::class)) { $this->markTestSkipped(); } @@ -614,10 +636,30 @@ public function phpType(): string } } -class OverriddenString extends SqlStringType +class OverriddenString extends AbstractPlatformType { - public function toDatabase($value) + public function __construct(PlatformInterface $platform, $name = self::STRING) + { + parent::__construct($platform, $name); + } + + public function toDatabase($value): string { return 'foo'; } + + public function fromDatabase($value, array $fieldOptions = []): ?string + { + return null === $value ? null : (string) $value; + } + + public function declaration(ColumnInterface $column): string + { + return Types::STRING; + } + + public function phpType(): string + { + return PhpTypeInterface::STRING; + } } diff --git a/composer.json b/composer.json index 1575f80..f8477af 100644 --- a/composer.json +++ b/composer.json @@ -15,20 +15,20 @@ "minimum-stability": "dev", "require": { "php": "~7.2 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0", - "b2pweb/bdf-prime": "~1.2|~2.0", + "b2pweb/bdf-prime": "~1.2|~2.0|~3.0", "b2pweb/bdf-prime-persistence": "~1.0", - "symfony/config": "^5.1|^6.0|~7.0", - "symfony/dependency-injection": "^5.1|^6.0|~7.0", - "symfony/framework-bundle": "^5.1|^6.0|~7.0", - "doctrine/doctrine-bundle": "~2.0", + "symfony/config": "^5.1|^6.0|~7.0|~8.0", + "symfony/dependency-injection": "^5.1|^6.0|~7.0|~8.0", + "symfony/framework-bundle": "^5.1|^6.0|~7.0|~8.0", + "doctrine/doctrine-bundle": "~2.0|~3.0", "doctrine/cache": "~1.0|~2.0" }, "require-dev": { "phpunit/phpunit": "~7.0|~8.0|~9.0", - "symfony/phpunit-bridge": "^5.1|^6.0|~7.0", - "symfony/yaml": "^5.1|^6.0|~7.0", - "symfony/console": "^5.1|^6.0|~7.0", - "symfony/web-profiler-bundle": "^5.1|^6.0|~7.0", + "symfony/phpunit-bridge": "^5.1|^6.0|~7.0|~8.0", + "symfony/yaml": "^5.1|^6.0|~7.0|~8.0", + "symfony/console": "^5.1|^6.0|~7.0|~8.0", + "symfony/web-profiler-bundle": "^5.1|^6.0|~7.0|~8.0", "friendsofphp/php-cs-fixer": "~3.0", "twig/twig": "~3.11" },