diff --git a/docs/pages/configuration.md b/docs/pages/configuration.md index 36305406..df495fe5 100644 --- a/docs/pages/configuration.md +++ b/docs/pages/configuration.md @@ -340,6 +340,8 @@ patchlevel_event_sourcing: store: type: 'custom' # default is 'dbal' service: 'my_subscription_store' + options: + table_name: 'my_subscription_store' ``` !!! tip @@ -670,7 +672,7 @@ For this you need to enable the crypto shredding. ```yaml patchlevel_event_sourcing: cryptography: - use_encrypted_field_name: true, + use_encrypted_field_name: true ``` !!! tip diff --git a/docs/pages/installation.md b/docs/pages/installation.md index cc0ce51a..b9432835 100644 --- a/docs/pages/installation.md +++ b/docs/pages/installation.md @@ -37,6 +37,20 @@ patchlevel_event_sourcing: connection: url: '%env(EVENTSTORE_URL)%' provide_dedicated_connection: true + store: + type: dbal_stream + # if you are using doctrine bundle you should enable this + #merge_orm_schema: true + command_bus: + service: messenger.default_bus + query_bus: + service: messenger.default_bus + subscription: + gap_detection: ~ + + # enable this if you want to use sensitive data encryption + #cryptography: ~ + # use_encrypted_field_name: true when@dev: patchlevel_event_sourcing: @@ -50,6 +64,8 @@ when@dev: when@test: patchlevel_event_sourcing: subscription: + store: + type: 'static_in_memory' catch_up: true throw_on_error: true run_after_aggregate_save: true diff --git a/docs/pages/usage.md b/docs/pages/usage.md index d2e3ee1f..fa034b13 100644 --- a/docs/pages/usage.md +++ b/docs/pages/usage.md @@ -1,7 +1,7 @@ # Usage Here you will find some examples of how to use the bundle. -But we provide only examples for specific symfo +But we provide only examples for specific symfony features. !!! info diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 683babf7..2a5fff41 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -1,7 +1,67 @@ parameters: ignoreErrors: + - + message: '#^Parameter \#2 \$id of static method Patchlevel\\EventSourcingBundle\\DependencyInjection\\ServiceAliasResolver\:\:resolve\(\) expects string, array\|bool\|float\|int\|string\|null given\.$#' + identifier: argument.type + count: 1 + path: src/DependencyInjection/CommandHandlerCompilerPass.php + - message: '#^Parameter \#1 \$classString of static method Patchlevel\\EventSourcing\\QueryBus\\HandlerFinder\:\:findInClass\(\) expects class\-string, string given\.$#' identifier: argument.type count: 1 path: src/DependencyInjection/QueryHandlerCompilerPass.php + + - + message: '#^Parameter \#2 \$id of static method Patchlevel\\EventSourcingBundle\\DependencyInjection\\ServiceAliasResolver\:\:resolve\(\) expects string, array\|bool\|float\|int\|string\|null given\.$#' + identifier: argument.type + count: 1 + path: src/DependencyInjection/QueryHandlerCompilerPass.php + + - + message: '#^Property Patchlevel\\EventSourcingBundle\\Tests\\Fixtures\\Profile\:\:\$id is never read, only written\.$#' + identifier: property.onlyWritten + count: 1 + path: tests/Fixtures/Profile.php + + - + message: '#^Property Patchlevel\\EventSourcingBundle\\Tests\\Fixtures\\SnapshotableProfile\:\:\$id is unused\.$#' + identifier: property.unused + count: 1 + path: tests/Fixtures/SnapshotableProfile.php + + - + message: '#^Call to an undefined method Symfony\\Component\\DependencyInjection\\ContainerBuilder\:\:getAutoconfiguredAttributes\(\)\.$#' + identifier: method.notFound + count: 1 + path: tests/Unit/PatchlevelEventSourcingBundleTest.php + + - + message: '#^Cannot access offset ''Patchlevel\\\\EventSourcing\\\\Attribute\\\\Aggregate''\|''Patchlevel\\\\EventSourcing\\\\Attribute\\\\Event'' on mixed\.$#' + identifier: offsetAccess.nonOffsetAccessible + count: 1 + path: tests/Unit/PatchlevelEventSourcingBundleTest.php + + - + message: '#^Cannot access offset ''bus'' on mixed\.$#' + identifier: offsetAccess.nonOffsetAccessible + count: 3 + path: tests/Unit/PatchlevelEventSourcingBundleTest.php + + - + message: '#^Cannot access offset ''handles'' on mixed\.$#' + identifier: offsetAccess.nonOffsetAccessible + count: 3 + path: tests/Unit/PatchlevelEventSourcingBundleTest.php + + - + message: '#^Cannot access offset ''method'' on mixed\.$#' + identifier: offsetAccess.nonOffsetAccessible + count: 2 + path: tests/Unit/PatchlevelEventSourcingBundleTest.php + + - + message: '#^Trying to invoke mixed but it''s not a callable\.$#' + identifier: callable.nonCallable + count: 1 + path: tests/Unit/PatchlevelEventSourcingBundleTest.php diff --git a/phpstan.neon.dist b/phpstan.neon.dist index dc02b387..c01c9daa 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -6,3 +6,4 @@ parameters: level: max paths: - src + - tests diff --git a/src/DependencyInjection/CommandHandlerCompilerPass.php b/src/DependencyInjection/CommandHandlerCompilerPass.php index dad31be7..a078c79b 100644 --- a/src/DependencyInjection/CommandHandlerCompilerPass.php +++ b/src/DependencyInjection/CommandHandlerCompilerPass.php @@ -25,7 +25,10 @@ public function process(ContainerBuilder $container): void return; } - $bus = $container->getParameter('patchlevel_event_sourcing.aggregate_handlers.bus'); + $bus = ServiceAliasResolver::resolve( + $container, + $container->getParameter('patchlevel_event_sourcing.aggregate_handlers.bus'), + ); /** @var AggregateRootRegistry $aggregateRootRegistry */ $aggregateRootRegistry = $container->get(AggregateRootRegistry::class); diff --git a/src/DependencyInjection/Configuration.php b/src/DependencyInjection/Configuration.php index 52f41deb..001b3b9b 100644 --- a/src/DependencyInjection/Configuration.php +++ b/src/DependencyInjection/Configuration.php @@ -22,7 +22,11 @@ * }, * query_bus: array{enabled: bool, service: string}, * subscription: array{ - * store: array{type: string, service: string|null}, + * store: array{ + * type: string, + * service: string|null, + * options: array{table_name: string} + * }, * retry_strategy?: array{base_delay: int, delay_factor: int, max_attempts: int}, * retry_strategies: array}>, * default_retry_strategy: string, @@ -197,6 +201,12 @@ public function getConfigTreeBuilder(): TreeBuilder ->defaultValue('dbal') ->end() ->scalarNode('service')->defaultNull()->end() + ->arrayNode('options') + ->addDefaultsIfNotSet() + ->children() + ->scalarNode('table_name')->defaultValue('subscriptions')->end() + ->end() + ->end() ->end() ->end() diff --git a/src/DependencyInjection/PatchlevelEventSourcingExtension.php b/src/DependencyInjection/PatchlevelEventSourcingExtension.php index 80979afd..e2bc845d 100644 --- a/src/DependencyInjection/PatchlevelEventSourcingExtension.php +++ b/src/DependencyInjection/PatchlevelEventSourcingExtension.php @@ -488,6 +488,8 @@ static function (ChildDefinition $definition): void { $container->register(DoctrineSubscriptionStore::class) ->setArguments([ new Reference('event_sourcing.dbal_connection'), + new Reference('event_sourcing.clock'), + $config['subscription']['store']['options']['table_name'], ]) ->addTag('event_sourcing.doctrine_schema_configurator'); diff --git a/src/DependencyInjection/QueryHandlerCompilerPass.php b/src/DependencyInjection/QueryHandlerCompilerPass.php index c2d069ab..2e00cb55 100644 --- a/src/DependencyInjection/QueryHandlerCompilerPass.php +++ b/src/DependencyInjection/QueryHandlerCompilerPass.php @@ -19,7 +19,10 @@ public function process(ContainerBuilder $container): void return; } - $bus = $container->getParameter('patchlevel_event_sourcing.query_handlers.bus'); + $bus = ServiceAliasResolver::resolve( + $container, + $container->getParameter('patchlevel_event_sourcing.query_handlers.bus'), + ); $subscribers = $container->findTaggedServiceIds('event_sourcing.subscriber'); foreach (array_keys($subscribers) as $subscriberServiceName) { diff --git a/src/DependencyInjection/ServiceAliasResolver.php b/src/DependencyInjection/ServiceAliasResolver.php new file mode 100644 index 00000000..440d27f1 --- /dev/null +++ b/src/DependencyInjection/ServiceAliasResolver.php @@ -0,0 +1,23 @@ +hasAlias($id)) { + return self::resolve( + $container, + (string)$container->getAlias($id), + ); + } + + return $id; + } +} diff --git a/src/DependencyInjection/SubscriberGuardCompilePass.php b/src/DependencyInjection/SubscriberGuardCompilePass.php index 1dd1a766..65b5f2bb 100644 --- a/src/DependencyInjection/SubscriberGuardCompilePass.php +++ b/src/DependencyInjection/SubscriberGuardCompilePass.php @@ -34,7 +34,7 @@ public function process(ContainerBuilder $container): void ); } - $subscriptionConnection = $this->resolveService($container, (string)$argument); + $subscriptionConnection = ServiceAliasResolver::resolve($container, (string)$argument); $subscribers = $container->findTaggedServiceIds('event_sourcing.subscriber'); @@ -48,7 +48,7 @@ public function process(ContainerBuilder $container): void continue; } - if ($subscriptionConnection !== $this->resolveService($container, (string)$argument)) { + if ($subscriptionConnection !== ServiceAliasResolver::resolve($container, (string)$argument)) { continue; } @@ -68,16 +68,4 @@ public function process(ContainerBuilder $container): void } } } - - private function resolveService(ContainerBuilder $container, string $id): string - { - if ($container->hasAlias($id)) { - return $this->resolveService( - $container, - (string)$container->getAlias($id), - ); - } - - return $id; - } } diff --git a/tests/Fixtures/Profile.php b/tests/Fixtures/Profile.php index b3aedad4..551afe1c 100644 --- a/tests/Fixtures/Profile.php +++ b/tests/Fixtures/Profile.php @@ -16,6 +16,7 @@ class Profile extends BasicAggregateRoot #[Id] private CustomId $id; + /** @param Repository $profileRepository */ #[Handle] public static function create( CreateProfile $command, diff --git a/tests/Unit/DataCollector/EventSourcingCollectorTest.php b/tests/Unit/DataCollector/EventSourcingCollectorTest.php index 860373b8..f7f24a57 100644 --- a/tests/Unit/DataCollector/EventSourcingCollectorTest.php +++ b/tests/Unit/DataCollector/EventSourcingCollectorTest.php @@ -68,7 +68,6 @@ public function testCollectData(): void self::assertEquals(ProfileCreated::class, $message['event_class']); self::assertEquals('profile.created', $message['event_name']); self::assertInstanceOf(Data::class, $message['event']); - self::assertIsArray($message['headers']); self::assertCount(1, $message['headers']); self::assertInstanceOf(Data::class, $message['headers'][0]); } diff --git a/tests/Unit/PatchlevelEventSourcingBundleTest.php b/tests/Unit/PatchlevelEventSourcingBundleTest.php index 5659f6bb..d2b28281 100644 --- a/tests/Unit/PatchlevelEventSourcingBundleTest.php +++ b/tests/Unit/PatchlevelEventSourcingBundleTest.php @@ -83,6 +83,7 @@ use Patchlevel\EventSourcing\Subscription\Store\SubscriptionStore; use Patchlevel\EventSourcing\Subscription\Subscriber\MetadataSubscriberAccessorRepository; use Patchlevel\EventSourcingBundle\Command\StoreMigrateCommand; +use Patchlevel\EventSourcingBundle\DependencyInjection\Configuration; use Patchlevel\EventSourcingBundle\DependencyInjection\PatchlevelEventSourcingExtension; use Patchlevel\EventSourcingBundle\EventBus\SymfonyEventBus; use Patchlevel\EventSourcingBundle\PatchlevelEventSourcingBundle; @@ -1551,6 +1552,9 @@ public function testNamedRepository(): void self::assertSame($profileRepository, $namedArgumentProfileRepository); } + /** + * @param array{patchlevel_event_sourcing: array} $config + */ private function compileContainer(ContainerBuilder $container, array $config): void { $bundle = new PatchlevelEventSourcingBundle();