Skip to content

Commit 2685009

Browse files
committed
finish DI & update readme
1 parent 494b6c3 commit 2685009

File tree

5 files changed

+230
-62
lines changed

5 files changed

+230
-62
lines changed

README.md

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,38 @@
1-
[![Type Coverage](https://shepherd.dev/github/patchlevel/event-sourcing-bundle/coverage.svg)](https://shepherd.dev/github/patchlevel/event-sourcing-bundle)
2-
[![Latest Stable Version](https://poser.pugx.org/patchlevel/event-sourcing-bundle/v)](//packagist.org/packages/patchlevel/event-sourcing-bundle)
3-
[![License](https://poser.pugx.org/patchlevel/event-sourcing-bundle/license)](//packagist.org/packages/patchlevel/event-sourcing-bundle)
1+
[![Type Coverage](https://shepherd.dev/github/patchlevel/laravel-event-sourcing/coverage.svg)](https://shepherd.dev/github/patchlevel/laravel-event-sourcing)
2+
[![Latest Stable Version](https://poser.pugx.org/patchlevel/laravel-event-sourcing/v)](//packagist.org/packages/patchlevel/laravel-event-sourcing)
3+
[![License](https://poser.pugx.org/patchlevel/laravel-event-sourcing/license)](//packagist.org/packages/patchlevel/laravel-event-sourcing)
44

5-
# Event-Sourcing-Bundle
5+
# Laravel-Event-Sourcing
66

7-
An event sourcing bundle, complete with all the essential features,
7+
An event sourcing laravel package, complete with all the essential features,
88
powered by the reliable Doctrine ecosystem and focused on developer experience.
9-
This bundle is a [symfony](https://symfony.com/) integration
9+
This package is a [laravel](https://laravel.com/) integration
1010
for [event-sourcing](https://github.com/patchlevel/event-sourcing) library.
1111

1212
## Features
1313

1414
* Everything is included in the package for event sourcing
1515
* Based on [doctrine dbal](https://github.com/doctrine/dbal) and their ecosystem
1616
* Developer experience oriented and fully typed
17-
* Automatic [snapshot](https://patchlevel.github.io/event-sourcing-docs/latest/snapshots/)-system to boost your performance
18-
* [Split](https://patchlevel.github.io/event-sourcing-docs/latest/split_stream/) big aggregates into multiple streams
19-
* Versioned and managed lifecycle of [subscriptions](https://patchlevel.github.io/event-sourcing-docs/latest/subscription/) like projections and processors
20-
* Safe usage of [Personal Data](https://patchlevel.github.io/event-sourcing-docs/latest/personal_data/) with crypto-shredding
21-
* Smooth [upcasting](https://patchlevel.github.io/event-sourcing-docs/latest/upcasting/) of old events
22-
* Simple setup with [scheme management](https://patchlevel.github.io/event-sourcing-docs/latest/store/) and [doctrine migration](https://patchlevel.github.io/event-sourcing-docs/latest/store/)
23-
* Built in [cli commands](https://patchlevel.github.io/event-sourcing-docs/latest/cli/) with [symfony](https://symfony.com/)
17+
* Automatic [snapshot](https://event-sourcing.patchlevel.io/latest/snapshots/)-system to boost your performance
18+
* [Split](https://event-sourcing.patchlevel.io/latest/split_stream/) big aggregates into multiple streams
19+
* Versioned and managed lifecycle of [subscriptions](https://event-sourcing.patchlevel.io/latest/subscription/) like projections and processors
20+
* Safe usage of [Personal Data](https://event-sourcing.patchlevel.io/latest/personal_data/) with crypto-shredding
21+
* Smooth [upcasting](https://event-sourcing.patchlevel.io/latest/upcasting/) of old events
22+
* Simple setup with [scheme management](https://event-sourcing.patchlevel.io/latest/store/) and [doctrine migration](https://event-sourcing.patchlevel.io/latest/store/)
23+
* Built in [cli commands](https://event-sourcing.patchlevel.io/latest/cli/) with [symfony](https://symfony.com/)
2424
* and much more...
2525

2626
## Installation
2727

2828
```bash
29-
composer require patchlevel/event-sourcing-bundle
29+
composer require patchlevel/laravel-event-sourcing
3030
```
3131

32-
> [!WARNING]
33-
> If you don't use the symfony flex recipe for this bundle, you need to follow
34-
this [installation documentation](https://patchlevel.github.io/event-sourcing-bundle-docs/latest/installation/).
35-
3632
## Documentation
3733

38-
* [Bundle Documentation](https://patchlevel.github.io/event-sourcing-bundle-docs/latest/)
39-
* [Library Documentation](https://patchlevel.github.io/event-sourcing-docs/latest)
34+
* [Bundle Documentation](https://event-sourcing-bundle.patchlevel.io/latest/)
35+
* [Library Documentation](https://event-sourcing.patchlevel.io/latest/)
4036
* [Related Blog](https://patchlevel.de/blog)
4137

4238
## Integration

config/event-sourcing.php

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
'service' => null,
1414
'options' => []
1515
],
16-
'' => '',
1716
'events' => [app_path()],
1817
'aggregates' => [app_path()],
1918
'headers' => [app_path()],
@@ -26,25 +25,28 @@
2625
'max_attempts' => 5,
2726
],
2827
'run_after_aggregate_save' => [
29-
'enabled' => true,
3028
'ids' => null,
3129
'groups' => null,
3230
'limit' => null
3331
],
3432
],
33+
'cryptography' => [
34+
'enabled' => true,
35+
'algorithm' => 'aes256'
36+
],
3537
'upcaster' => [
3638
// App\Upcaster\YourUpcaster::class
3739
],
3840
'message_decorator' => [
39-
// App\MessageDecorator\YourUpcaster::class
41+
// App\MessageDecorator\YourMessageDecorator::class
4042
],
4143
'listeners' => [
4244
// App\Listener\YourListener::class
4345
],
4446
'subscribers' => [
45-
// App\Subscribers\YourListener::class
47+
// App\Subscribers\YourSubscriber::class
4648
],
4749
'argument_resolvers' => [
48-
// App\ArgumentResolvers\YourListener::class
50+
// App\ArgumentResolvers\YourResolver::class
4951
],
5052
];

src/EventSourcingServiceProvider.php

Lines changed: 64 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
use Patchlevel\EventSourcing\Console\Command\SubscriptionTeardownCommand;
3030
use Patchlevel\EventSourcing\Console\Command\WatchCommand;
3131
use Patchlevel\EventSourcing\Console\DoctrineHelper;
32+
use Patchlevel\EventSourcing\Cryptography\DoctrineCipherKeyStore;
3233
use Patchlevel\EventSourcing\EventBus\AttributeListenerProvider;
3334
use Patchlevel\EventSourcing\EventBus\Consumer;
3435
use Patchlevel\EventSourcing\EventBus\DefaultConsumer;
@@ -83,9 +84,18 @@
8384
use Patchlevel\EventSourcing\Subscription\Subscriber\MetadataSubscriberAccessorRepository;
8485
use Patchlevel\EventSourcing\Subscription\Subscriber\SubscriberAccessorRepository;
8586
use Patchlevel\EventSourcing\Subscription\Subscriber\SubscriberHelper;
87+
use Patchlevel\Hydrator\Cryptography\Cipher\Cipher;
88+
use Patchlevel\Hydrator\Cryptography\Cipher\CipherKeyFactory;
89+
use Patchlevel\Hydrator\Cryptography\Cipher\OpensslCipher;
90+
use Patchlevel\Hydrator\Cryptography\Cipher\OpensslCipherKeyFactory;
91+
use Patchlevel\Hydrator\Cryptography\PayloadCryptographer;
92+
use Patchlevel\Hydrator\Cryptography\PersonalDataPayloadCryptographer;
93+
use Patchlevel\Hydrator\Cryptography\Store\CipherKeyStore;
8694
use Patchlevel\Hydrator\Hydrator;
8795
use Patchlevel\Hydrator\Metadata\AttributeMetadataFactory;
8896
use Patchlevel\Hydrator\MetadataHydrator;
97+
use Patchlevel\LaravelEventSourcing\Middleware\AutoSetupMiddleware;
98+
use Patchlevel\LaravelEventSourcing\Middleware\SubscriptionRebuildAfterFileChangeMiddleware;
8999

90100
use function array_key_exists;
91101
use function sprintf;
@@ -105,7 +115,11 @@ public function boot(): void
105115
{
106116
$this->publishes([
107117
__DIR__ . '/../config/event-sourcing.php' => config_path('event-sourcing.php'),
108-
]);
118+
], 'patchlevel-config');
119+
120+
$this->publishesMigrations([
121+
__DIR__.'/../database/migrations/' => database_path('migrations')
122+
], 'patchlevel-migrations');
109123

110124
if (!$this->app->runningInConsole()) {
111125
return;
@@ -149,6 +163,7 @@ public function register(): void
149163
$this->registerEventBus();
150164
$this->registerSnapshots();
151165
$this->registerSubscription();
166+
$this->registerCryptography();
152167
}
153168

154169
private function registerConnection(): void
@@ -270,7 +285,7 @@ private function registerHydrator(): void
270285
$this->app->singleton(Hydrator::class, static function () {
271286
return new MetadataHydrator(
272287
new AttributeMetadataFactory(),
273-
null, //app(PayloadCryptographer::class),
288+
config('event-sourcing.cryptography.enabled') ? app(PayloadCryptographer::class) : null,
274289
);
275290
});
276291
}
@@ -309,7 +324,7 @@ private function registerAggregates(): void
309324
app(MessageDecorator::class),
310325
app('event_sourcing.clock'),
311326
app(AggregateRootMetadataFactory::class),
312-
null, // app('logger', null),
327+
app('log'),
313328
);
314329
});
315330
}
@@ -446,14 +461,14 @@ private function registerEventBus(): void
446461
$this->app->singleton(Consumer::class, static function () {
447462
return new DefaultConsumer(
448463
app(ListenerProvider::class),
449-
null, // app('logger', null),
464+
app('log'),
450465
);
451466
});
452467

453468
$this->app->singleton(EventBus::class, static function () {
454469
return new DefaultEventBus(
455470
app(Consumer::class),
456-
null, // app('logger', null),
471+
app('log'),
457472
);
458473
});
459474
}
@@ -516,7 +531,7 @@ private function registerSubscription(): void
516531
app(SubscriptionStore::class),
517532
app(SubscriberAccessorRepository::class),
518533
app(RetryStrategy::class),
519-
null, // app('logger', null),
534+
app('log'),
520535
);
521536
});
522537

@@ -544,38 +559,21 @@ private function registerSubscription(): void
544559
});
545560
}
546561

547-
if (config('event-sourcing.subscription.auto_setup.enabled')) {
548-
/*
549-
$container->register(AutoSetupListener::class)
550-
->setArguments([
551-
new Reference(SubscriptionEngine::class),
552-
$config['subscription']['auto_setup']['ids'] ?: null,
553-
$config['subscription']['auto_setup']['groups'] ?: null,
554-
])
555-
->addTag('kernel.event_listener', [
556-
'event' => 'kernel.request',
557-
'priority' => 200,
558-
'method' => 'onKernelRequest',
559-
]);
560-
*/
561-
}
562+
$this->app->singleton(AutoSetupMiddleware::class, static function () {
563+
return new AutoSetupMiddleware(
564+
app(SubscriptionEngine::class),
565+
config('event-sourcing.subscription.auto_setup.ids'),
566+
config('event-sourcing.subscription.auto_setup.groups'),
567+
);
568+
});
562569

563-
if (config('event-sourcing.subscription.rebuild_after_file_change')) {
564-
/*
565-
$container->register(SubscriptionRebuildAfterFileChangeListener::class)
566-
->setArguments([
567-
new Reference(SubscriptionEngine::class),
568-
new TaggedIteratorArgument('event_sourcing.subscriber'),
569-
new Reference('cache.app'),
570-
new Reference(SubscriberMetadataFactory::class),
571-
])
572-
->addTag('kernel.event_listener', [
573-
'event' => 'kernel.request',
574-
'priority' => 100,
575-
'method' => 'onKernelRequest',
576-
]);
577-
*/
578-
}
570+
$this->app->singleton(SubscriptionRebuildAfterFileChangeMiddleware::class, function () {
571+
return new SubscriptionRebuildAfterFileChangeMiddleware(
572+
app(SubscriptionEngine::class),
573+
$this->app->tagged('event_sourcing.subscriber'),
574+
app(SubscriberMetadataFactory::class),
575+
);
576+
});
579577

580578
$this->app->singleton(SubscriptionSetupCommand::class, static function () {
581579
return new SubscriptionSetupCommand(
@@ -626,4 +624,33 @@ private function registerSubscription(): void
626624
);
627625
});
628626
}
627+
628+
private function registerCryptography(): void
629+
{
630+
if (!config('event-sourcing.cryptography.enabled')) {
631+
return;
632+
}
633+
634+
$this->app->singleton(CipherKeyFactory::class, static function () {
635+
return new OpensslCipherKeyFactory(config('event-sourcing.cryptography.algorithm'));
636+
});
637+
638+
$this->app->singleton(CipherKeyStore::class, static function () {
639+
return new DoctrineCipherKeyStore(
640+
app('event_sourcing.dbal_connection'),
641+
);
642+
});
643+
644+
$this->app->singleton(Cipher::class, static function () {
645+
return new OpensslCipher();
646+
});
647+
648+
$this->app->singleton(PayloadCryptographer::class, static function () {
649+
return new PersonalDataPayloadCryptographer(
650+
app(CipherKeyStore::class),
651+
app(CipherKeyFactory::class),
652+
app(Cipher::class),
653+
);
654+
});
655+
}
629656
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Patchlevel\LaravelEventSourcing\Middleware;
6+
7+
use Closure;
8+
use Illuminate\Http\Request;
9+
use Illuminate\Http\Response;
10+
use Patchlevel\EventSourcing\Subscription\Engine\SubscriptionEngine;
11+
use Patchlevel\EventSourcing\Subscription\Engine\SubscriptionEngineCriteria;
12+
use Patchlevel\EventSourcing\Subscription\Status;
13+
14+
final class AutoSetupMiddleware
15+
{
16+
/**
17+
* @param list<string>|null $ids
18+
* @param list<string>|null $groups
19+
*/
20+
public function __construct(
21+
private readonly SubscriptionEngine $subscriptionEngine,
22+
private readonly array|null $ids,
23+
private readonly array|null $groups,
24+
) {
25+
}
26+
27+
public function handle(Request $request, Closure $next): Response
28+
{
29+
$subscriptions = $this->subscriptionEngine->subscriptions(
30+
new SubscriptionEngineCriteria(
31+
$this->ids,
32+
$this->groups,
33+
),
34+
);
35+
36+
$ids = [];
37+
38+
foreach ($subscriptions as $subscription) {
39+
if ($subscription->status() !== Status::New) {
40+
continue;
41+
}
42+
43+
$ids[] = $subscription->id();
44+
}
45+
46+
$this->subscriptionEngine->setup(
47+
new SubscriptionEngineCriteria($ids),
48+
true,
49+
);
50+
51+
return $next($request);
52+
}
53+
}

0 commit comments

Comments
 (0)