Completed
Pull Request — master (#110)
by Kristof
07:14
created

applyPlaceImportedFromUDB2Event()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 18
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 18
rs 9.4286
cc 1
eloc 11
nc 1
nop 1
1
<?php
2
3
/**
4
 * @file
5
 * Contains \Cultuurnet\UDB3\Place\PlaceLDProjector.
6
 */
7
8
namespace CultuurNet\UDB3\Place\ReadModel\JSONLD;
9
10
use Broadway\Domain\DateTime;
11
use Broadway\Domain\DomainMessage;
12
use Broadway\EventHandling\EventListenerInterface;
13
use CultuurNet\UDB3\Cdb\ActorItemFactory;
14
use CultuurNet\UDB3\Cdb\EventItemFactory;
15
use CultuurNet\UDB3\CulturefeedSlugger;
16
use CultuurNet\UDB3\EntityNotFoundException;
17
use CultuurNet\UDB3\EntityServiceInterface;
18
use CultuurNet\UDB3\Event\EventType;
19
use CultuurNet\UDB3\Event\ReadModel\DocumentRepositoryInterface;
20
use CultuurNet\UDB3\EventHandling\DelegateEventHandlingToSpecificMethodTrait;
21
use CultuurNet\UDB3\Facility;
22
use CultuurNet\UDB3\Iri\IriGeneratorInterface;
23
use CultuurNet\UDB3\Offer\ReadModel\JSONLD\CdbXMLItemBaseImporter;
24
use CultuurNet\UDB3\Place\Events\BookingInfoUpdated;
25
use CultuurNet\UDB3\Place\Events\ContactPointUpdated;
26
use CultuurNet\UDB3\Place\Events\DescriptionUpdated;
27
use CultuurNet\UDB3\Place\Events\FacilitiesUpdated;
28
use CultuurNet\UDB3\Place\Events\ImageAdded;
29
use CultuurNet\UDB3\Place\Events\ImageDeleted;
30
use CultuurNet\UDB3\Place\Events\ImageUpdated;
31
use CultuurNet\UDB3\Place\Events\MajorInfoUpdated;
32
use CultuurNet\UDB3\Place\Events\OrganizerDeleted;
33
use CultuurNet\UDB3\Place\Events\OrganizerUpdated;
34
use CultuurNet\UDB3\Place\Events\PlaceCreated;
35
use CultuurNet\UDB3\Place\Events\PlaceDeleted;
36
use CultuurNet\UDB3\Place\Events\PlaceImportedFromUDB2;
37
use CultuurNet\UDB3\Place\Events\PlaceImportedFromUDB2Event;
38
use CultuurNet\UDB3\Place\Events\TypicalAgeRangeDeleted;
39
use CultuurNet\UDB3\Place\Events\TypicalAgeRangeUpdated;
40
use CultuurNet\UDB3\Place\PlaceEvent;
41
use CultuurNet\UDB3\Place\ReadModel\JSONLD\CdbXMLImporter;
42
use CultuurNet\UDB3\ReadModel\JsonDocument;
43
use CultuurNet\UDB3\SluggerInterface;
44
use CultuurNet\UDB3\Theme;
45
46
/**
47
 * Projects state changes on Place entities to a JSON-LD read model in a
48
 * document repository.
49
 */
50
class PlaceLDProjector implements EventListenerInterface
51
{
52
    use DelegateEventHandlingToSpecificMethodTrait;
53
54
    /**
55
     * @var DocumentRepositoryInterface
56
     */
57
    protected $repository;
58
59
    /**
60
     * @var IriGeneratorInterface
61
     */
62
    protected $iriGenerator;
63
64
    /**
65
     * @var EntityServiceInterface
66
     */
67
    protected $organizerService;
68
69
    /**
70
     * @var SluggerInterface
71
     */
72
    protected $slugger;
73
74
    /**
75
     * @var CdbXMLImporter
76
     */
77
    protected $cdbXMLImporter;
78
79
    /**
80
     * @param DocumentRepositoryInterface $repository
81
     * @param IriGeneratorInterface $iriGenerator
82
     * @param EntityServiceInterface $organizerService
83
     */
84
    public function __construct(
85
        DocumentRepositoryInterface $repository,
86
        IriGeneratorInterface $iriGenerator,
87
        EntityServiceInterface $organizerService
88
    ) {
89
        $this->repository = $repository;
90
        $this->iriGenerator = $iriGenerator;
91
        $this->organizerService = $organizerService;
92
        $this->slugger = new CulturefeedSlugger();
93
        $this->cdbXMLImporter = new CdbXMLImporter(
94
            new CdbXMLItemBaseImporter()
95
        );
96
    }
97
98
    /**
99
     * @param PlaceImportedFromUDB2 $actorImportedFromUDB2
100
     */
101
    protected function applyPlaceImportedFromUDB2(
102
        PlaceImportedFromUDB2 $actorImportedFromUDB2
103
    ) {
104
        $udb2Actor = ActorItemFactory::createActorFromCdbXml(
105
            $actorImportedFromUDB2->getCdbXmlNamespaceUri(),
106
            $actorImportedFromUDB2->getCdbXml()
107
        );
108
109
        $document = $this->newDocument($actorImportedFromUDB2->getActorId());
110
        $actorLd = $document->getBody();
111
112
        $actorLd = $this->cdbXMLImporter->documentWithCdbXML(
113
            $actorLd,
114
            $udb2Actor
115
        );
116
117
        $this->repository->save($document->withBody($actorLd));
118
    }
119
120
121
    /**
122
     * @param PlaceImportedFromUDB2Event $eventImportedFromUDB2
123
     */
124
    protected function applyPlaceImportedFromUDB2Event(
125
        PlaceImportedFromUDB2Event $eventImportedFromUDB2
126
    ) {
127
        $udb2Event = EventItemFactory::createEventFromCdbXml(
128
            $eventImportedFromUDB2->getCdbXmlNamespaceUri(),
129
            $eventImportedFromUDB2->getCdbXml()
130
        );
131
132
        $document = $this->newDocument($eventImportedFromUDB2->getActorId());
133
        $eventLD = $document->getBody();
134
135
        $eventLD = $this->cdbXMLImporter->eventDocumentWithCdbXML(
136
            $eventLD,
137
            $udb2Event
138
        );
139
140
        $this->repository->save($document->withBody($eventLD));
141
    }
142
143
    /**
144
     * @param string $id
145
     * @return JsonDocument
146
     */
147 View Code Duplication
    protected function newDocument($id)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
148
    {
149
        $document = new JsonDocument($id);
150
151
        $placeLd = $document->getBody();
152
        $placeLd->{'@id'} = $this->iriGenerator->iri($id);
153
154
        // @todo provide Event-LD context here relative to the base URI
155
        $placeLd->{'@context'} = '/api/1.0/place.jsonld';
156
157
        return $document->withBody($placeLd);
158
    }
159
160
    /**
161
     * @param PlaceCreated $placeCreated
162
     * @param DomainMessage $domainMessage
163
     */
164
    protected function applyPlaceCreated(PlaceCreated $placeCreated, DomainMessage $domainMessage)
165
    {
166
        $document = $this->newDocument($placeCreated->getPlaceId());
167
168
        $jsonLD = $document->getBody();
169
170
        $jsonLD->{'@id'} = $this->iriGenerator->iri(
171
            $placeCreated->getPlaceId()
172
        );
173
        $jsonLD->name = $placeCreated->getTitle();
174
175
        $jsonLD->address = $placeCreated->getAddress()->toJsonLd();
176
177
        $calendarJsonLD = $placeCreated->getCalendar()->toJsonLd();
178
        $jsonLD = (object) array_merge((array) $jsonLD, $calendarJsonLD);
179
180
        $eventType = $placeCreated->getEventType();
181
        $jsonLD->terms = [
182
            $eventType->toJsonLd()
183
        ];
184
185
        $theme = $placeCreated->getTheme();
186
        if (!empty($theme)) {
187
            $jsonLD->terms[] = $theme->toJsonLd();
188
        }
189
190
        $recordedOn = $domainMessage->getRecordedOn()->toString();
191
        $jsonLD->created = \DateTime::createFromFormat(
192
            DateTime::FORMAT_STRING,
193
            $recordedOn
194
        )->format('c');
195
196
        $jsonLD->modified = $jsonLD->created;
197
198
        $metaData = $domainMessage->getMetadata()->serialize();
199 View Code Duplication
        if (isset($metaData['user_email'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
200
            $jsonLD->creator = $metaData['user_email'];
201
        } elseif (isset($metaData['user_nick'])) {
202
            $jsonLD->creator = $metaData['user_nick'];
203
        }
204
205
        $this->repository->save($document->withBody($jsonLD));
206
    }
207
208
    /**
209
     * @param PlaceDeleted $placeDeleted
210
     */
211
    protected function applyPlaceDeleted(PlaceDeleted $placeDeleted)
212
    {
213
        $this->repository->remove($placeDeleted->getPlaceId());
214
    }
215
216
    /**
217
     * Apply the major info updated command to the projector.
218
     * @param MajorInfoUpdated $majorInfoUpdated
219
     */
220
    protected function applyMajorInfoUpdated(MajorInfoUpdated $majorInfoUpdated)
221
    {
222
223
        $document = $this->loadPlaceDocumentFromRepository($majorInfoUpdated);
224
        $jsonLD = $document->getBody();
225
226
        $jsonLD->name = $majorInfoUpdated->getTitle();
227
        $jsonLD->address = $majorInfoUpdated->getAddress()->toJsonLd();
228
229
        $calendarJsonLD = $majorInfoUpdated->getCalendar()->toJsonLd();
230
        $jsonLD = (object) array_merge((array) $jsonLD, $calendarJsonLD);
231
232
        // Remove old theme and event type.
233
        $jsonLD->terms = array_filter($jsonLD->terms, function ($term) {
234
            return $term->domain !== EventType::DOMAIN &&  $term->domain !== Theme::DOMAIN;
235
        });
236
237
        $eventType = $majorInfoUpdated->getEventType();
238
        $jsonLD->terms = [
239
            $eventType->toJsonLd()
240
        ];
241
242
        $theme = $majorInfoUpdated->getTheme();
243
        if (!empty($theme)) {
244
            $jsonLD->terms[] = $theme->toJsonLd();
245
        }
246
247
        $this->repository->save($document->withBody($jsonLD));
248
249
    }
250
251
    /**
252
     * Apply the description updated event to the place repository.
253
     * @param DescriptionUpdated $descriptionUpdated
254
     */
255 View Code Duplication
    protected function applyDescriptionUpdated(
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
256
        DescriptionUpdated $descriptionUpdated
257
    ) {
258
259
        $document = $this->loadPlaceDocumentFromRepository($descriptionUpdated);
260
261
        $placeLD = $document->getBody();
262
        if (empty($placeLD->description)) {
263
            $placeLD->description = new \stdClass();
264
        }
265
        $placeLD->description->{'nl'} = $descriptionUpdated->getDescription();
266
267
        $this->repository->save($document->withBody($placeLD));
268
    }
269
270
    /**
271
     * Apply the booking info updated event to the place repository.
272
     * @param BookingInfoUpdated $bookingInfoUpdated
273
     */
274 View Code Duplication
    protected function applyBookingInfoUpdated(BookingInfoUpdated $bookingInfoUpdated)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
275
    {
276
277
        $document = $this->loadPlaceDocumentFromRepository($bookingInfoUpdated);
278
279
        $placeLD = $document->getBody();
280
        $placeLD->bookingInfo = $bookingInfoUpdated->getBookingInfo()->toJsonLd();
281
282
        $this->repository->save($document->withBody($placeLD));
283
284
    }
285
286
    /**
287
     * Apply the typical age range updated event to the place repository.
288
     * @param TypicalAgeRangeUpdated $typicalAgeRangeUpdated
289
     */
290 View Code Duplication
    protected function applyTypicalAgeRangeUpdated(
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
291
        TypicalAgeRangeUpdated $typicalAgeRangeUpdated
292
    ) {
293
        $document = $this->loadPlaceDocumentFromRepository($typicalAgeRangeUpdated);
294
295
        $eventLd = $document->getBody();
296
        $eventLd->typicalAgeRange = $typicalAgeRangeUpdated->getTypicalAgeRange();
297
298
        $this->repository->save($document->withBody($eventLd));
299
    }
300
301
    /**
302
     * Apply the typical age range deleted event to the place repository.
303
     * @param TypicalAgeRangeDeleted $typicalAgeRangeDeleted
304
     */
305
    protected function applyTypicalAgeRangeDeleted(
306
        TypicalAgeRangeDeleted $typicalAgeRangeDeleted
307
    ) {
308
        $document = $this->loadPlaceDocumentFromRepository($typicalAgeRangeDeleted);
309
310
        $eventLd = $document->getBody();
311
312
        unset($eventLd->typicalAgeRange);
313
314
        $this->repository->save($document->withBody($eventLd));
315
    }
316
317
    /**
318
     * Apply the organizer updated event to the place repository.
319
     * @param OrganizerUpdated $organizerUpdated
320
     */
321 View Code Duplication
    protected function applyOrganizerUpdated(OrganizerUpdated $organizerUpdated)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
322
    {
323
        $document = $this->loadPlaceDocumentFromRepository($organizerUpdated);
324
325
        $placeLd = $document->getBody();
326
327
        $placeLd->organizer = array(
328
          '@type' => 'Organizer',
329
        ) + (array)$this->organizerJSONLD($organizerUpdated->getOrganizerId());
330
331
        $this->repository->save($document->withBody($placeLd));
332
    }
333
334
    /**
335
     * Apply the organizer delete event to the place repository.
336
     * @param OrganizerDeleted $organizerDeleted
337
     */
338
    protected function applyOrganizerDeleted(OrganizerDeleted $organizerDeleted)
339
    {
340
        $document = $this->loadPlaceDocumentFromRepository($organizerDeleted);
341
342
        $placeLd = $document->getBody();
343
344
        unset($placeLd->organizer);
345
346
        $this->repository->save($document->withBody($placeLd));
347
    }
348
349
    /**
350
     * Apply the contact point updated event to the place repository.
351
     * @param ContactPointUpdated $contactPointUpdated
352
     */
353 View Code Duplication
    protected function applyContactPointUpdated(ContactPointUpdated $contactPointUpdated)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
354
    {
355
356
        $document = $this->loadPlaceDocumentFromRepository($contactPointUpdated);
357
358
        $placeLd = $document->getBody();
359
        $placeLd->contactPoint = $contactPointUpdated->getContactPoint()->toJsonLd();
360
361
        $this->repository->save($document->withBody($placeLd));
362
    }
363
364
    /**
365
     * Apply the facilitiesupdated event to the place repository.
366
     * @param FacilitiesUpdated $facilitiesUpdated
367
     */
368
    protected function applyFacilitiesUpdated(FacilitiesUpdated $facilitiesUpdated)
369
    {
370
371
        $document = $this->loadPlaceDocumentFromRepository($facilitiesUpdated);
372
373
        $placeLd = $document->getBody();
374
375
        $terms = isset($placeLd->terms) ? $placeLd->terms : array();
376
377
        // Remove all old facilities + get numeric keys.
378
        $terms = array_values(array_filter(
379
            $terms,
380
            function ($term) {
381
                return $term->domain !== Facility::DOMAIN;
382
            }
383
        ));
384
385
        // Add the new facilities.
386
        foreach ($facilitiesUpdated->getFacilities() as $facility) {
387
            $terms[] = $facility->toJsonLd();
388
        }
389
390
        $placeLd->terms = $terms;
391
392
        $this->repository->save($document->withBody($placeLd));
393
394
    }
395
396
    /**
397
     * Apply the imageAdded event to the place repository.
398
     *
399
     * @param ImageAdded $imageAdded
400
     */
401 View Code Duplication
    protected function applyImageAdded(ImageAdded $imageAdded)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
402
    {
403
404
        $document = $this->loadPlaceDocumentFromRepository($imageAdded);
405
406
        $placeLd = $document->getBody();
407
        $placeLd->mediaObject = isset($placeLd->mediaObject) ? $placeLd->mediaObject : [];
408
        $placeLd->mediaObject[] = $imageAdded->getMediaObject()->toJsonLd();
409
410
        $this->repository->save($document->withBody($placeLd));
411
412
    }
413
414
    /**
415
     * Apply the ImageUpdated event to the place repository.
416
     *
417
     * @param ImageUpdated $imageUpdated
418
     */
419 View Code Duplication
    protected function applyImageUpdated(ImageUpdated $imageUpdated)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
420
    {
421
422
        $document = $this->loadPlaceDocumentFromRepository($imageUpdated);
423
424
        $placeLd = $document->getBody();
425
        $placeLd->mediaObject = isset($placeLd->mediaObject) ? $placeLd->mediaObject : [];
426
        $placeLd->mediaObject[$imageUpdated->getIndexToUpdate()] = $imageUpdated->getMediaObject()->toJsonLd();
427
428
        $this->repository->save($document->withBody($placeLd));
429
    }
430
431
    /**
432
     * Apply the imageDeleted event to the place repository.
433
     *
434
     * @param ImageDeleted $imageDeleted
435
     */
436 View Code Duplication
    protected function applyImageDeleted(ImageDeleted $imageDeleted)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
437
    {
438
439
        $document = $this->loadPlaceDocumentFromRepository($imageDeleted);
440
441
        $placeLd = $document->getBody();
442
        unset($placeLd->mediaObject[$imageDeleted->getIndexToDelete()]);
443
444
        // Generate new numeric keys.
445
        $placeLd->mediaObject = array_values($placeLd->mediaObject);
446
447
        $this->repository->save($document->withBody($placeLd));
448
449
    }
450
451
    /**
452
     * @param PlaceEvent $place
453
     * @return JsonDocument
454
     */
455
    protected function loadPlaceDocumentFromRepository(PlaceEvent $place)
456
    {
457
        $document = $this->repository->get($place->getPlaceId());
458
459
        if (!$document) {
460
            return $this->newDocument($place->getPlaceId());
461
        }
462
463
        return $document;
464
    }
465
466
    /**
467
     * Get the organizer jsonLD.
468
     * @param string $organizerId
469
     * @return array
470
     */
471 View Code Duplication
    protected function organizerJSONLD($organizerId)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
472
    {
473
        try {
474
            $organizerJSONLD = $this->organizerService->getEntity(
475
                $organizerId
476
            );
477
478
            return json_decode($organizerJSONLD);
479
        } catch (EntityNotFoundException $e) {
480
            // In case the place can not be found at the moment, just add its ID
481
            return array(
482
                '@id' => $this->organizerService->iri($organizerId)
483
            );
484
        }
485
    }
486
}
487