Completed
Pull Request — master (#107)
by Kristof
07:48
created

PlaceLDProjector::applyImageUpdated()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 6

Duplication

Lines 11
Ratio 100 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 11
loc 11
rs 9.4286
cc 2
eloc 6
nc 2
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\CulturefeedSlugger;
15
use CultuurNet\UDB3\EntityNotFoundException;
16
use CultuurNet\UDB3\EntityServiceInterface;
17
use CultuurNet\UDB3\Event\EventType;
18
use CultuurNet\UDB3\Event\ReadModel\DocumentRepositoryInterface;
19
use CultuurNet\UDB3\EventHandling\DelegateEventHandlingToSpecificMethodTrait;
20
use CultuurNet\UDB3\Facility;
21
use CultuurNet\UDB3\Iri\IriGeneratorInterface;
22
use CultuurNet\UDB3\Offer\ReadModel\JSONLD\CdbXMLItemBaseImporter;
23
use CultuurNet\UDB3\Place\Events\BookingInfoUpdated;
24
use CultuurNet\UDB3\Place\Events\ContactPointUpdated;
25
use CultuurNet\UDB3\Place\Events\DescriptionUpdated;
26
use CultuurNet\UDB3\Place\Events\FacilitiesUpdated;
27
use CultuurNet\UDB3\Place\Events\ImageAdded;
28
use CultuurNet\UDB3\Place\Events\ImageDeleted;
29
use CultuurNet\UDB3\Place\Events\ImageUpdated;
30
use CultuurNet\UDB3\Place\Events\MajorInfoUpdated;
31
use CultuurNet\UDB3\Place\Events\OrganizerDeleted;
32
use CultuurNet\UDB3\Place\Events\OrganizerUpdated;
33
use CultuurNet\UDB3\Place\Events\PlaceCreated;
34
use CultuurNet\UDB3\Place\Events\PlaceDeleted;
35
use CultuurNet\UDB3\Place\Events\PlaceImportedFromUDB2;
36
use CultuurNet\UDB3\Place\Events\TypicalAgeRangeDeleted;
37
use CultuurNet\UDB3\Place\Events\TypicalAgeRangeUpdated;
38
use CultuurNet\UDB3\Place\PlaceEvent;
39
use CultuurNet\UDB3\Place\ReadModel\JSONLD\CdbXMLImporter;
40
use CultuurNet\UDB3\ReadModel\JsonDocument;
41
use CultuurNet\UDB3\SluggerInterface;
42
use CultuurNet\UDB3\Theme;
43
44
/**
45
 * Projects state changes on Place entities to a JSON-LD read model in a
46
 * document repository.
47
 */
48
class PlaceLDProjector implements EventListenerInterface
49
{
50
    use DelegateEventHandlingToSpecificMethodTrait;
51
52
    /**
53
     * @var DocumentRepositoryInterface
54
     */
55
    protected $repository;
56
57
    /**
58
     * @var IriGeneratorInterface
59
     */
60
    protected $iriGenerator;
61
62
    /**
63
     * @var EntityServiceInterface
64
     */
65
    protected $organizerService;
66
67
    /**
68
     * @var SluggerInterface
69
     */
70
    protected $slugger;
71
72
    /**
73
     * @var CdbXMLImporter
74
     */
75
    protected $cdbXMLImporter;
76
77
    /**
78
     * @param DocumentRepositoryInterface $repository
79
     * @param IriGeneratorInterface $iriGenerator
80
     * @param EntityServiceInterface $organizerService
81
     */
82
    public function __construct(
83
        DocumentRepositoryInterface $repository,
84
        IriGeneratorInterface $iriGenerator,
85
        EntityServiceInterface $organizerService
86
    ) {
87
        $this->repository = $repository;
88
        $this->iriGenerator = $iriGenerator;
89
        $this->organizerService = $organizerService;
90
        $this->slugger = new CulturefeedSlugger();
91
        $this->cdbXMLImporter = new CdbXMLImporter(
92
            new CdbXMLItemBaseImporter()
93
        );
94
    }
95
96
    /**
97
     * @param PlaceImportedFromUDB2 $actorImportedFromUDB2
98
     */
99
    protected function applyPlaceImportedFromUDB2(
100
        PlaceImportedFromUDB2 $actorImportedFromUDB2
101
    ) {
102
        $udb2Actor = ActorItemFactory::createActorFromCdbXml(
103
            $actorImportedFromUDB2->getCdbXmlNamespaceUri(),
104
            $actorImportedFromUDB2->getCdbXml()
105
        );
106
107
        $document = $this->newDocument($actorImportedFromUDB2->getActorId());
108
        $actorLd = $document->getBody();
109
110
        $actorLd = $this->cdbXMLImporter->documentWithCdbXML(
111
            $actorLd,
112
            $udb2Actor
113
        );
114
115
        $this->repository->save($document->withBody($actorLd));
116
    }
117
118
    /**
119
     * @param string $id
120
     * @return JsonDocument
121
     */
122 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...
123
    {
124
        $document = new JsonDocument($id);
125
126
        $placeLd = $document->getBody();
127
        $placeLd->{'@id'} = $this->iriGenerator->iri($id);
128
129
        // @todo provide Event-LD context here relative to the base URI
130
        $placeLd->{'@context'} = '/api/1.0/place.jsonld';
131
132
        return $document->withBody($placeLd);
133
    }
134
135
    /**
136
     * @param PlaceCreated $placeCreated
137
     * @param DomainMessage $domainMessage
138
     */
139
    protected function applyPlaceCreated(PlaceCreated $placeCreated, DomainMessage $domainMessage)
140
    {
141
        $document = $this->newDocument($placeCreated->getPlaceId());
142
143
        $jsonLD = $document->getBody();
144
145
        $jsonLD->{'@id'} = $this->iriGenerator->iri(
146
            $placeCreated->getPlaceId()
147
        );
148
        $jsonLD->name = $placeCreated->getTitle();
149
150
        $jsonLD->address = $placeCreated->getAddress()->toJsonLd();
151
152
        $calendarJsonLD = $placeCreated->getCalendar()->toJsonLd();
153
        $jsonLD = (object) array_merge((array) $jsonLD, $calendarJsonLD);
154
155
        $eventType = $placeCreated->getEventType();
156
        $jsonLD->terms = [
157
            $eventType->toJsonLd()
158
        ];
159
160
        $theme = $placeCreated->getTheme();
161
        if (!empty($theme)) {
162
            $jsonLD->terms[] = $theme->toJsonLd();
163
        }
164
165
        $recordedOn = $domainMessage->getRecordedOn()->toString();
166
        $jsonLD->created = \DateTime::createFromFormat(
167
            DateTime::FORMAT_STRING,
168
            $recordedOn
169
        )->format('c');
170
171
        $jsonLD->modified = $jsonLD->created;
172
173
        $metaData = $domainMessage->getMetadata()->serialize();
174 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...
175
            $jsonLD->creator = $metaData['user_email'];
176
        } elseif (isset($metaData['user_nick'])) {
177
            $jsonLD->creator = $metaData['user_nick'];
178
        }
179
180
        $this->repository->save($document->withBody($jsonLD));
181
    }
182
183
    /**
184
     * @param PlaceDeleted $placeDeleted
185
     */
186
    protected function applyPlaceDeleted(PlaceDeleted $placeDeleted)
187
    {
188
        $this->repository->remove($placeDeleted->getPlaceId());
189
    }
190
191
    /**
192
     * Apply the major info updated command to the projector.
193
     * @param MajorInfoUpdated $majorInfoUpdated
194
     */
195
    protected function applyMajorInfoUpdated(MajorInfoUpdated $majorInfoUpdated)
196
    {
197
198
        $document = $this->loadPlaceDocumentFromRepository($majorInfoUpdated);
199
        $jsonLD = $document->getBody();
200
201
        $jsonLD->name = $majorInfoUpdated->getTitle();
202
        $jsonLD->address = $majorInfoUpdated->getAddress()->toJsonLd();
203
204
        $calendarJsonLD = $majorInfoUpdated->getCalendar()->toJsonLd();
205
        $jsonLD = (object) array_merge((array) $jsonLD, $calendarJsonLD);
206
207
        // Remove old theme and event type.
208
        $jsonLD->terms = array_filter($jsonLD->terms, function ($term) {
209
            return $term->domain !== EventType::DOMAIN &&  $term->domain !== Theme::DOMAIN;
210
        });
211
212
        $eventType = $majorInfoUpdated->getEventType();
213
        $jsonLD->terms = [
214
            $eventType->toJsonLd()
215
        ];
216
217
        $theme = $majorInfoUpdated->getTheme();
218
        if (!empty($theme)) {
219
            $jsonLD->terms[] = $theme->toJsonLd();
220
        }
221
222
        $this->repository->save($document->withBody($jsonLD));
223
224
    }
225
226
    /**
227
     * Apply the description updated event to the place repository.
228
     * @param DescriptionUpdated $descriptionUpdated
229
     */
230 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...
231
        DescriptionUpdated $descriptionUpdated
232
    ) {
233
234
        $document = $this->loadPlaceDocumentFromRepository($descriptionUpdated);
235
236
        $placeLD = $document->getBody();
237
        if (empty($placeLD->description)) {
238
            $placeLD->description = new \stdClass();
239
        }
240
        $placeLD->description->{'nl'} = $descriptionUpdated->getDescription();
241
242
        $this->repository->save($document->withBody($placeLD));
243
    }
244
245
    /**
246
     * Apply the booking info updated event to the place repository.
247
     * @param BookingInfoUpdated $bookingInfoUpdated
248
     */
249 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...
250
    {
251
252
        $document = $this->loadPlaceDocumentFromRepository($bookingInfoUpdated);
253
254
        $placeLD = $document->getBody();
255
        $placeLD->bookingInfo = $bookingInfoUpdated->getBookingInfo()->toJsonLd();
256
257
        $this->repository->save($document->withBody($placeLD));
258
259
    }
260
261
    /**
262
     * Apply the typical age range updated event to the place repository.
263
     * @param TypicalAgeRangeUpdated $typicalAgeRangeUpdated
264
     */
265 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...
266
        TypicalAgeRangeUpdated $typicalAgeRangeUpdated
267
    ) {
268
        $document = $this->loadPlaceDocumentFromRepository($typicalAgeRangeUpdated);
269
270
        $eventLd = $document->getBody();
271
        $eventLd->typicalAgeRange = $typicalAgeRangeUpdated->getTypicalAgeRange();
272
273
        $this->repository->save($document->withBody($eventLd));
274
    }
275
276
    /**
277
     * Apply the typical age range deleted event to the place repository.
278
     * @param TypicalAgeRangeDeleted $typicalAgeRangeDeleted
279
     */
280
    protected function applyTypicalAgeRangeDeleted(
281
        TypicalAgeRangeDeleted $typicalAgeRangeDeleted
282
    ) {
283
        $document = $this->loadPlaceDocumentFromRepository($typicalAgeRangeDeleted);
284
285
        $eventLd = $document->getBody();
286
287
        unset($eventLd->typicalAgeRange);
288
289
        $this->repository->save($document->withBody($eventLd));
290
    }
291
292
    /**
293
     * Apply the organizer updated event to the place repository.
294
     * @param OrganizerUpdated $organizerUpdated
295
     */
296 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...
297
    {
298
        $document = $this->loadPlaceDocumentFromRepository($organizerUpdated);
299
300
        $placeLd = $document->getBody();
301
302
        $placeLd->organizer = array(
303
          '@type' => 'Organizer',
304
        ) + (array)$this->organizerJSONLD($organizerUpdated->getOrganizerId());
305
306
        $this->repository->save($document->withBody($placeLd));
307
    }
308
309
    /**
310
     * Apply the organizer delete event to the place repository.
311
     * @param OrganizerDeleted $organizerDeleted
312
     */
313
    protected function applyOrganizerDeleted(OrganizerDeleted $organizerDeleted)
314
    {
315
        $document = $this->loadPlaceDocumentFromRepository($organizerDeleted);
316
317
        $placeLd = $document->getBody();
318
319
        unset($placeLd->organizer);
320
321
        $this->repository->save($document->withBody($placeLd));
322
    }
323
324
    /**
325
     * Apply the contact point updated event to the place repository.
326
     * @param ContactPointUpdated $contactPointUpdated
327
     */
328 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...
329
    {
330
331
        $document = $this->loadPlaceDocumentFromRepository($contactPointUpdated);
332
333
        $placeLd = $document->getBody();
334
        $placeLd->contactPoint = $contactPointUpdated->getContactPoint()->toJsonLd();
335
336
        $this->repository->save($document->withBody($placeLd));
337
    }
338
339
    /**
340
     * Apply the facilitiesupdated event to the place repository.
341
     * @param FacilitiesUpdated $facilitiesUpdated
342
     */
343
    protected function applyFacilitiesUpdated(FacilitiesUpdated $facilitiesUpdated)
344
    {
345
346
        $document = $this->loadPlaceDocumentFromRepository($facilitiesUpdated);
347
348
        $placeLd = $document->getBody();
349
350
        $terms = isset($placeLd->terms) ? $placeLd->terms : array();
351
352
        // Remove all old facilities + get numeric keys.
353
        $terms = array_values(array_filter(
354
            $terms,
355
            function ($term) {
356
                return $term->domain !== Facility::DOMAIN;
357
            }
358
        ));
359
360
        // Add the new facilities.
361
        foreach ($facilitiesUpdated->getFacilities() as $facility) {
362
            $terms[] = $facility->toJsonLd();
363
        }
364
365
        $placeLd->terms = $terms;
366
367
        $this->repository->save($document->withBody($placeLd));
368
369
    }
370
371
    /**
372
     * Apply the imageAdded event to the place repository.
373
     *
374
     * @param ImageAdded $imageAdded
375
     */
376 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...
377
    {
378
379
        $document = $this->loadPlaceDocumentFromRepository($imageAdded);
380
381
        $placeLd = $document->getBody();
382
        $placeLd->mediaObject = isset($placeLd->mediaObject) ? $placeLd->mediaObject : [];
383
        $placeLd->mediaObject[] = $imageAdded->getMediaObject()->toJsonLd();
384
385
        $this->repository->save($document->withBody($placeLd));
386
387
    }
388
389
    /**
390
     * Apply the ImageUpdated event to the place repository.
391
     *
392
     * @param ImageUpdated $imageUpdated
393
     */
394 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...
395
    {
396
397
        $document = $this->loadPlaceDocumentFromRepository($imageUpdated);
398
399
        $placeLd = $document->getBody();
400
        $placeLd->mediaObject = isset($placeLd->mediaObject) ? $placeLd->mediaObject : [];
401
        $placeLd->mediaObject[$imageUpdated->getIndexToUpdate()] = $imageUpdated->getMediaObject()->toJsonLd();
402
403
        $this->repository->save($document->withBody($placeLd));
404
    }
405
406
    /**
407
     * Apply the imageDeleted event to the place repository.
408
     *
409
     * @param ImageDeleted $imageDeleted
410
     */
411 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...
412
    {
413
414
        $document = $this->loadPlaceDocumentFromRepository($imageDeleted);
415
416
        $placeLd = $document->getBody();
417
        unset($placeLd->mediaObject[$imageDeleted->getIndexToDelete()]);
418
419
        // Generate new numeric keys.
420
        $placeLd->mediaObject = array_values($placeLd->mediaObject);
421
422
        $this->repository->save($document->withBody($placeLd));
423
424
    }
425
426
    /**
427
     * @param PlaceEvent $place
428
     * @return JsonDocument
429
     */
430
    protected function loadPlaceDocumentFromRepository(PlaceEvent $place)
431
    {
432
        $document = $this->repository->get($place->getPlaceId());
433
434
        if (!$document) {
435
            return $this->newDocument($place->getPlaceId());
436
        }
437
438
        return $document;
439
    }
440
441
    /**
442
     * Get the organizer jsonLD.
443
     * @param string $organizerId
444
     * @return array
445
     */
446 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...
447
    {
448
        try {
449
            $organizerJSONLD = $this->organizerService->getEntity(
450
                $organizerId
451
            );
452
453
            return json_decode($organizerJSONLD);
454
        } catch (EntityNotFoundException $e) {
455
            // In case the place can not be found at the moment, just add its ID
456
            return array(
457
                '@id' => $this->organizerService->iri($organizerId)
458
            );
459
        }
460
    }
461
}
462