1414use ArrayIterator ;
1515use Assert \Assertion ;
1616use Prooph \EventStore \EventStore ;
17+ use Prooph \EventStore \Snapshot \SnapshotStore ;
1718use Prooph \EventStore \Stream \SingleStreamStrategy ;
1819use Prooph \EventStore \Stream \StreamStrategy ;
1920
@@ -50,6 +51,11 @@ class AggregateRepository
5051 */
5152 protected $ identityMap ;
5253
54+ /**
55+ * @var SnapshotStore|null
56+ */
57+ protected $ snapshotStore ;
58+
5359 /**
5460 * @var array
5561 */
@@ -60,21 +66,24 @@ class AggregateRepository
6066 * @param AggregateType $aggregateType
6167 * @param AggregateTranslator $aggregateTranslator
6268 * @param StreamStrategy|null $streamStrategy
63- * @param IdentityMap $identityMap
69+ * @param IdentityMap|null $identityMap
70+ * @param SnapshotStore|null $snapshotStore
6471 */
6572 public function __construct (
6673 EventStore $ eventStore ,
6774 AggregateType $ aggregateType ,
6875 AggregateTranslator $ aggregateTranslator ,
6976 StreamStrategy $ streamStrategy = null ,
70- IdentityMap $ identityMap = null
77+ IdentityMap $ identityMap = null ,
78+ SnapshotStore $ snapshotStore = null
7179 ) {
7280 $ this ->eventStore = $ eventStore ;
7381 $ this ->eventStore ->getActionEventEmitter ()->attachListener ('commit.pre ' , [$ this , 'addPendingEventsToStream ' ]);
7482 $ this ->eventStore ->getActionEventEmitter ()->attachListener ('commit.post ' , [$ this , 'applyPendingStreamEvents ' ]);
7583
7684 $ this ->aggregateType = $ aggregateType ;
7785 $ this ->aggregateTranslator = $ aggregateTranslator ;
86+ $ this ->snapshotStore = $ snapshotStore ;
7887
7988 if (null === $ streamStrategy ) {
8089 $ streamStrategy = new SingleStreamStrategy ($ this ->eventStore );
@@ -184,15 +193,25 @@ public function getAggregateRoot($aggregateId)
184193 {
185194 Assertion::string ($ aggregateId , 'AggregateId needs to be string ' );
186195
187- $ aggregateRoot = $ this ->identityMap ->get ($ this ->aggregateType , $ aggregateId );
196+ $ eventSourcedAggregateRoot = $ this ->identityMap ->get ($ this ->aggregateType , $ aggregateId );
188197
189- if ($ aggregateRoot ) {
190- return $ aggregateRoot ;
198+ if ($ eventSourcedAggregateRoot ) {
199+ return $ eventSourcedAggregateRoot ;
200+ }
201+
202+ if ($ this ->snapshotStore ) {
203+ $ eventSourcedAggregateRoot = $ this ->loadFromSnapshotStore ($ aggregateId );
204+
205+ if ($ eventSourcedAggregateRoot ) {
206+ $ this ->identityMap ->add ($ this ->aggregateType , $ aggregateId , $ eventSourcedAggregateRoot );
207+
208+ return $ eventSourcedAggregateRoot ;
209+ }
191210 }
192211
193212 $ streamEvents = $ this ->streamStrategy ->read ($ this ->aggregateType , $ aggregateId );
194213
195- if (count ( $ streamEvents) === 0 ) {
214+ if (! $ streamEvents-> valid () ) {
196215 return ;
197216 }
198217
@@ -207,4 +226,33 @@ public function getAggregateRoot($aggregateId)
207226
208227 return $ eventSourcedAggregateRoot ;
209228 }
229+
230+ /**
231+ * @param string $aggregateId
232+ * @return null|object
233+ */
234+ protected function loadFromSnapshotStore ($ aggregateId )
235+ {
236+ $ snapshot = $ this ->snapshotStore ->get ($ this ->aggregateType , $ aggregateId );
237+
238+ if (!$ snapshot ) {
239+ return ;
240+ }
241+
242+ $ aggregateRoot = $ snapshot ->aggregateRoot ();
243+
244+ $ streamEvents = $ this ->streamStrategy ->read (
245+ $ this ->aggregateType ,
246+ $ aggregateId ,
247+ $ snapshot ->lastVersion () + 1
248+ );
249+
250+ if (!$ streamEvents ->valid ()) {
251+ return $ aggregateRoot ;
252+ }
253+
254+ $ this ->aggregateTranslator ->applyPendingStreamEvents ($ aggregateRoot , $ streamEvents );
255+
256+ return $ aggregateRoot ;
257+ }
210258}
0 commit comments