Completed
Pull Request — master (#118)
by Kristof
18:24 queued 09:02
created

EventLDProjector::applyEventCdbXml()   B

Complexity

Conditions 2
Paths 2

Size

Total Lines 30
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 30
rs 8.8571
cc 2
eloc 19
nc 2
nop 3
1
<?php
2
/**
3
 * @file
4
 */
5
6
namespace CultuurNet\UDB3\Event;
7
8
use Broadway\Domain\DateTime;
9
use Broadway\Domain\DomainMessage;
10
use Broadway\Domain\Metadata;
11
use Broadway\EventHandling\EventListenerInterface;
12
use CultuurNet\UDB3\Cdb\EventItemFactory;
13
use CultuurNet\UDB3\CulturefeedSlugger;
14
use CultuurNet\UDB3\EntityNotFoundException;
15
use CultuurNet\UDB3\Event\Events\EventCreatedFromCdbXml;
16
use CultuurNet\UDB3\Event\Events\BookingInfoUpdated;
17
use CultuurNet\UDB3\Event\Events\ContactPointUpdated;
18
use CultuurNet\UDB3\Event\Events\DescriptionUpdated;
19
use CultuurNet\UDB3\Event\Events\EventCreated;
20
use CultuurNet\UDB3\Event\Events\EventDeleted;
21
use CultuurNet\UDB3\Event\Events\EventImportedFromUDB2;
22
use CultuurNet\UDB3\Event\Events\EventUpdatedFromCdbXml;
23
use CultuurNet\UDB3\Event\Events\EventUpdatedFromUDB2;
24
use CultuurNet\UDB3\Event\Events\EventWasLabelled;
25
use CultuurNet\UDB3\Event\Events\ImageAdded;
26
use CultuurNet\UDB3\Event\Events\ImageDeleted;
27
use CultuurNet\UDB3\Event\Events\ImageUpdated;
28
use CultuurNet\UDB3\Event\Events\LabelsMerged;
29
use CultuurNet\UDB3\Event\Events\MajorInfoUpdated;
30
use CultuurNet\UDB3\Event\Events\OrganizerDeleted;
31
use CultuurNet\UDB3\Event\Events\OrganizerUpdated;
32
use CultuurNet\UDB3\Event\Events\TranslationApplied;
33
use CultuurNet\UDB3\Event\Events\TranslationDeleted;
34
use CultuurNet\UDB3\Event\Events\TypicalAgeRangeDeleted;
35
use CultuurNet\UDB3\Event\Events\TypicalAgeRangeUpdated;
36
use CultuurNet\UDB3\Event\Events\Unlabelled;
37
use CultuurNet\UDB3\Event\ReadModel\DocumentRepositoryInterface;
38
use CultuurNet\UDB3\Event\ReadModel\JSONLD\CdbXMLImporter;
39
use CultuurNet\UDB3\Event\ReadModel\JSONLD\OrganizerServiceInterface;
40
use CultuurNet\UDB3\Event\ReadModel\JSONLD\PlaceServiceInterface;
41
use CultuurNet\UDB3\EventHandling\DelegateEventHandlingToSpecificMethodTrait;
42
use CultuurNet\UDB3\EventServiceInterface;
43
use CultuurNet\UDB3\Iri\IriGeneratorInterface;
44
use CultuurNet\UDB3\Label;
45
use CultuurNet\UDB3\LabelCollection;
46
use CultuurNet\UDB3\Offer\ReadModel\JSONLD\CdbXMLItemBaseImporter;
47
use CultuurNet\UDB3\Media\Serialization\MediaObjectSerializer;
48
use CultuurNet\UDB3\Organizer\OrganizerProjectedToJSONLD;
49
use CultuurNet\UDB3\OrganizerService;
50
use CultuurNet\UDB3\Place\PlaceProjectedToJSONLD;
51
use CultuurNet\UDB3\PlaceService;
52
use CultuurNet\UDB3\ReadModel\JsonDocument;
53
use CultuurNet\UDB3\SluggerInterface;
54
use CultuurNet\UDB3\StringFilter\StringFilterInterface;
55
use CultuurNet\UDB3\Theme;
56
use Symfony\Component\Serializer\SerializerInterface;
57
use ValueObjects\String\String;
58
59
/**
60
 * Projects state changes on Event entities to a JSON-LD read model in a
61
 * document repository.
62
 *
63
 * Implements PlaceServiceInterface and OrganizerServiceInterface to do a double
64
 * dispatch with CdbXMLImporter.
65
 */
66
class EventLDProjector implements EventListenerInterface, PlaceServiceInterface, OrganizerServiceInterface
67
{
68
    use DelegateEventHandlingToSpecificMethodTrait;
69
70
    /**
71
     * @var DocumentRepositoryInterface
72
     */
73
    protected $repository;
74
75
    /**
76
     * @var IriGeneratorInterface
77
     */
78
    protected $iriGenerator;
79
80
    /**
81
     * @var OrganizerService
82
     */
83
    protected $organizerService;
84
85
    /**
86
     * @var PlaceService
87
     */
88
    protected $placeService;
89
90
    /**
91
     * @var EventServiceInterface
92
     */
93
    protected $eventService;
94
95
    /**
96
     * @var SluggerInterface
97
     */
98
    protected $slugger;
99
100
    /**
101
     * @var CdbXMLImporter
102
     */
103
    protected $cdbXMLImporter;
104
105
    /**
106
     * @var SerializerInterface
107
     */
108
    protected $mediaObjectSerializer;
109
110
    /**
111
     * @param DocumentRepositoryInterface $repository
112
     * @param IriGeneratorInterface $iriGenerator
113
     * @param EventServiceInterface $eventService
114
     * @param PlaceService $placeService
115
     * @param OrganizerService $organizerService
116
     * @param SerializerInterface $mediaObjectSerializer
117
     */
118
    public function __construct(
119
        DocumentRepositoryInterface $repository,
120
        IriGeneratorInterface $iriGenerator,
121
        EventServiceInterface $eventService,
122
        PlaceService $placeService,
123
        OrganizerService $organizerService,
124
        SerializerInterface $mediaObjectSerializer
125
    ) {
126
        $this->repository = $repository;
127
        $this->iriGenerator = $iriGenerator;
128
        $this->organizerService = $organizerService;
129
        $this->placeService = $placeService;
130
        $this->eventService = $eventService;
131
        $this->mediaObjectSerializer = $mediaObjectSerializer;
132
133
        $this->slugger = new CulturefeedSlugger();
134
        $this->cdbXMLImporter = new CdbXMLImporter(new CdbXMLItemBaseImporter());
135
    }
136
137 View Code Duplication
    protected function applyOrganizerProjectedToJSONLD(OrganizerProjectedToJSONLD $organizerProjectedToJSONLD)
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...
138
    {
139
        $eventIds = $this->eventsOrganizedByOrganizer(
140
            $organizerProjectedToJSONLD->getId()
141
        );
142
143
        $organizer = $this->organizerService->getEntity(
144
            $organizerProjectedToJSONLD->getId()
145
        );
146
147
        foreach ($eventIds as $eventId) {
148
            $document = $this->loadDocumentFromRepositoryByEventId(
149
                $eventId
150
            );
151
            $eventLD = $document->getBody();
152
153
            $newEventLD = clone $eventLD;
154
            $newEventLD->organizer = json_decode($organizer);
155
156
            if ($newEventLD != $eventLD) {
157
                $this->repository->save($document->withBody($newEventLD));
158
            }
159
        }
160
    }
161
162 View Code Duplication
    protected function applyPlaceProjectedToJSONLD(
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...
163
        PlaceProjectedToJSONLD $placeProjectedToJSONLD
164
    ) {
165
        $eventsLocatedAtPlace = $this->eventsLocatedAtPlace(
166
            $placeProjectedToJSONLD->getId()
167
        );
168
169
        $placeJSONLD = $this->placeService->getEntity(
170
            $placeProjectedToJSONLD->getId()
171
        );
172
173
        foreach ($eventsLocatedAtPlace as $eventId) {
174
            $document = $this->loadDocumentFromRepositoryByEventId(
175
                $eventId
176
            );
177
            $eventLD = $document->getBody();
178
179
            $newEventLD = clone $eventLD;
180
            $newEventLD->location = json_decode($placeJSONLD);
181
182
            if ($newEventLD != $eventLD) {
183
                $this->repository->save($document->withBody($newEventLD));
184
            }
185
        }
186
    }
187
188
    /**
189
     * @param string $organizerId
190
     * @return string[]
191
     */
192
    protected function eventsOrganizedByOrganizer($organizerId)
193
    {
194
        return $this->eventService->eventsOrganizedByOrganizer(
195
            $organizerId
196
        );
197
    }
198
199
    /**
200
     * @param string $placeId
201
     * @return string[]
202
     */
203
    protected function eventsLocatedAtPlace($placeId)
204
    {
205
        return $this->eventService->eventsLocatedAtPlace(
206
            $placeId
207
        );
208
    }
209
210
    /**
211
     * @param EventImportedFromUDB2 $eventImportedFromUDB2
212
     */
213
    protected function applyEventImportedFromUDB2(
214
        EventImportedFromUDB2 $eventImportedFromUDB2
215
    ) {
216
        $this->applyEventCdbXml(
217
            $eventImportedFromUDB2->getEventId(),
218
            $eventImportedFromUDB2->getCdbXmlNamespaceUri(),
219
            $eventImportedFromUDB2->getCdbXml()
220
        );
221
    }
222
223
    /**
224
     * @param EventUpdatedFromUDB2 $eventUpdatedFromUDB2
225
     */
226
    protected function applyEventUpdatedFromUDB2(
227
        EventUpdatedFromUDB2 $eventUpdatedFromUDB2
228
    ) {
229
        $this->applyEventCdbXml(
230
            $eventUpdatedFromUDB2->getEventId(),
231
            $eventUpdatedFromUDB2->getCdbXmlNamespaceUri(),
232
            $eventUpdatedFromUDB2->getCdbXml()
233
        );
234
    }
235
236
    /**
237
     * @param EventCreatedFromCdbXml $eventCreatedFromCdbXml
238
     * @param DomainMessage $domainMessage
239
     */
240 View Code Duplication
    protected function applyEventCreatedFromCdbXml(
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...
241
        EventCreatedFromCdbXml $eventCreatedFromCdbXml,
242
        DomainMessage $domainMessage
243
    ) {
244
        $cdbXmlNamespaceUri = $eventCreatedFromCdbXml->getCdbXmlNamespaceUri()->toNative();
245
        $cdbXml = $eventCreatedFromCdbXml->getEventXmlString()->toEventXmlString();
246
        $eventId = $eventCreatedFromCdbXml->getEventId()->toNative();
247
248
        $this->applyEventFromCdbXml(
249
            $eventId,
250
            $cdbXmlNamespaceUri,
251
            $cdbXml,
252
            $domainMessage
253
        );
254
    }
255
256
    /**
257
     * @param EventUpdatedFromCdbXml $eventUpdatedFromCdbXml
258
     * @param DomainMessage $domainMessage
259
     */
260 View Code Duplication
    protected function applyEventUpdatedFromCdbXml(
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...
261
        EventUpdatedFromCdbXml $eventUpdatedFromCdbXml,
262
        DomainMessage $domainMessage
263
    ) {
264
        $cdbXmlNamespaceUri = $eventUpdatedFromCdbXml->getCdbXmlNamespaceUri()->toNative();
265
        $cdbXml = $eventUpdatedFromCdbXml->getEventXmlString()->toEventXmlString();
266
        $eventId = $eventUpdatedFromCdbXml->getEventId()->toNative();
267
268
        $this->applyEventFromCdbXml(
269
            $eventId,
270
            $cdbXmlNamespaceUri,
271
            $cdbXml,
272
            $domainMessage
273
        );
274
    }
275
276
    /**
277
     * Helper function to save JSONLD document from entryapi cdbxml.
278
     *
279
     * @param string $eventId
280
     * @param string $cdbXmlNamespaceUri
281
     * @param string $cdbXml
282
     * @param DomainMessage $domainMessage
283
     */
284
    protected function applyEventFromCdbXml(
285
        $eventId,
286
        $cdbXmlNamespaceUri,
287
        $cdbXml,
288
        $domainMessage
289
    ) {
290
        $udb2Event = EventItemFactory::createEventFromCdbXml(
291
            $cdbXmlNamespaceUri,
292
            $cdbXml
293
        );
294
295
        $document = $this->newDocument($eventId);
296
        $eventLd = $document->getBody();
297
298
        $eventLd = $this->cdbXMLImporter->documentWithCdbXML(
299
            $eventLd,
300
            $udb2Event,
301
            $this,
302
            $this,
303
            $this->slugger
304
        );
305
306
        // Add creation date and update date from metadata.
307
        $eventCreationDate = $domainMessage->getRecordedOn();
308
309
        $eventCreationString = $eventCreationDate->toString();
310
        $eventCreationDateTime = \DateTime::createFromFormat(
311
            DateTime::FORMAT_STRING,
312
            $eventCreationString
313
        );
314
        $eventLd->created = $eventCreationDateTime->format('c');
315
        $eventLd->modified = $eventCreationDateTime->format('c');
316
317
        // Add creator.
318
        $eventLd->creator = $this->getAuthorFromMetadata($domainMessage->getMetadata())->toNative();
319
320
        // Add publisher, which is the consumer name.
321
        $eventLd->publisher = $this->getConsumerFromMetadata($domainMessage->getMetadata())->toNative();
322
323
        // Because we can not properly track media coming from UDB2 we simply
324
        // ignore it and give priority to content added through UDB3.
325
        $media = $this->UDB3Media($eventId);
326
        if (!empty($media)) {
327
            $eventLd->mediaObject = $media;
328
        }
329
330
        $this->repository->save($document->withBody($eventLd));
331
    }
332
333
    /**
334
     * @param string $eventId
335
     * @param string $cdbXmlNamespaceUri
336
     * @param string $cdbXml
337
     */
338
    protected function applyEventCdbXml(
339
        $eventId,
340
        $cdbXmlNamespaceUri,
341
        $cdbXml
342
    ) {
343
        $udb2Event = EventItemFactory::createEventFromCdbXml(
344
            $cdbXmlNamespaceUri,
345
            $cdbXml
346
        );
347
348
        $document = $this->newDocument($eventId);
349
        $eventLd = $document->getBody();
350
351
        $eventLd = $this->cdbXMLImporter->documentWithCdbXML(
352
            $eventLd,
353
            $udb2Event,
354
            $this,
355
            $this,
356
            $this->slugger
357
        );
358
359
        // Because we can not properly track media coming from UDB2 we simply
360
        // ignore it and give priority to content added through UDB3.
361
        $media = $this->UDB3Media($eventId);
362
        if (!empty($media)) {
363
            $eventLd->mediaObject = $media;
364
        }
365
366
        $this->repository->save($document->withBody($eventLd));
367
    }
368
369
    /**
370
     * Return the media of an event if it already exists.
371
     *
372
     * @param $eventId
373
     *  The id of the event.
374
     *
375
     * @return array
376
     *  A list of media objects.
377
     */
378
    private function UDB3Media($eventId)
379
    {
380
        $document = $this->loadDocumentFromRepositoryByEventId($eventId);
381
        $media = [];
382
        
383
        if ($document) {
384
            $item = $document->getBody();
385
            // At the moment we do not include any media coming from UDB2.
386
            // If the mediaObject property contains data it's coming from UDB3.
387
            $item->mediaObject = isset($item->mediaObject) ? $item->mediaObject : [];
388
        }
389
390
        return $media;
391
    }
392
393
    /**
394
     * @param EventCreated $eventCreated
395
     * @param DomainMessage $domainMessage
396
     */
397
    protected function applyEventCreated(
398
        EventCreated $eventCreated,
399
        DomainMessage $domainMessage
400
    ) {
401
        $document = $this->newDocument($eventCreated->getEventId());
402
403
        $jsonLD = $document->getBody();
404
405
        $jsonLD->{'@id'} = $this->iriGenerator->iri(
406
            $eventCreated->getEventId()
407
        );
408
        $jsonLD->name['nl'] = $eventCreated->getTitle();
409
        $jsonLD->location = array(
410
          '@type' => 'Place',
411
        ) + (array)$this->placeJSONLD($eventCreated->getLocation()->getCdbid());
412
413
        $calendarJsonLD = $eventCreated->getCalendar()->toJsonLd();
414
        $jsonLD = (object) array_merge((array) $jsonLD, $calendarJsonLD);
415
416
        // Same as.
417
        $jsonLD->sameAs = $this->generateSameAs(
418
            $eventCreated->getEventId(),
419
            reset($jsonLD->name)
420
        );
421
422
        $eventType = $eventCreated->getEventType();
423
        $jsonLD->terms = [
424
            $eventType->toJsonLd()
425
        ];
426
427
        $theme = $eventCreated->getTheme();
428
        if (!empty($theme)) {
429
            $jsonLD->terms[] = $theme->toJsonLd();
430
        }
431
432
        $recordedOn = $domainMessage->getRecordedOn()->toString();
433
        $jsonLD->created = \DateTime::createFromFormat(
434
            DateTime::FORMAT_STRING,
435
            $recordedOn
436
        )->format('c');
437
        $jsonLD->modified = $jsonLD->created;
438
439
        $metaData = $domainMessage->getMetadata()->serialize();
440 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...
441
            $jsonLD->creator = $metaData['user_email'];
442
        } elseif (isset($metaData['user_nick'])) {
443
            $jsonLD->creator = $metaData['user_nick'];
444
        }
445
446
        $this->repository->save($document->withBody($jsonLD));
447
    }
448
449
    /**
450
     * @param EventDeleted $eventDeleted
451
     */
452
    protected function applyEventDeleted(EventDeleted $eventDeleted)
453
    {
454
        $this->repository->remove($eventDeleted->getEventId());
455
    }
456
457
    /**
458
     * Apply the major info updated command to the projector.
459
     */
460
    protected function applyMajorInfoUpdated(MajorInfoUpdated $majorInfoUpdated)
461
    {
462
463
        $document = $this->loadDocumentFromRepository($majorInfoUpdated);
464
        $jsonLD = $document->getBody();
465
466
        $jsonLD->name->nl = $majorInfoUpdated->getTitle();
467
        $jsonLD->location = array(
468
          '@type' => 'Place',
469
        ) + (array)$this->placeJSONLD($majorInfoUpdated->getLocation()->getCdbid());
470
471
        $calendarJsonLD = $majorInfoUpdated->getCalendar()->toJsonLd();
472
        $jsonLD = (object) array_merge((array) $jsonLD, $calendarJsonLD);
473
474
        // Remove old theme and event type.
475
        $jsonLD->terms = array_filter($jsonLD->terms, function ($term) {
476
            return $term->domain !== EventType::DOMAIN &&  $term->domain !== Theme::DOMAIN;
477
        });
478
479
        $eventType = $majorInfoUpdated->getEventType();
480
        $jsonLD->terms = [
481
            $eventType->toJsonLd()
482
        ];
483
484
        $theme = $majorInfoUpdated->getTheme();
485
        if (!empty($theme)) {
486
            $jsonLD->terms[] = $theme->toJsonLd();
487
        }
488
489
        $this->repository->save($document->withBody($jsonLD));
490
491
    }
492
493
    /**
494
     * @inheritdoc
495
     */
496
    public function placeJSONLD($placeId)
497
    {
498
        try {
499
            $placeJSONLD = $this->placeService->getEntity(
500
                $placeId
501
            );
502
503
            return json_decode($placeJSONLD);
504
        } catch (EntityNotFoundException $e) {
505
            // In case the place can not be found at the moment, just add its ID
506
            return array(
0 ignored issues
show
Bug Best Practice introduced by
The return type of return array('@id' => $t...ervice->iri($placeId)); (array<string,string>) is incompatible with the return type declared by the interface CultuurNet\UDB3\Event\Re...eInterface::placeJSONLD of type stdClass.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
507
                '@id' => $this->placeService->iri($placeId)
508
            );
509
        }
510
    }
511
512
    /**
513
     * @inheritdoc
514
     */
515 View Code Duplication
    public 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...
516
    {
517
518
        try {
519
            $organizerJSONLD = $this->organizerService->getEntity(
520
                $organizerId
521
            );
522
523
            return json_decode($organizerJSONLD);
524
        } catch (EntityNotFoundException $e) {
525
            // In case the place can not be found at the moment, just add its ID
526
            return array(
0 ignored issues
show
Bug Best Practice introduced by
The return type of return array('@id' => $t...ce->iri($organizerId)); (array<string,string>) is incompatible with the return type declared by the interface CultuurNet\UDB3\Event\Re...erface::organizerJSONLD of type stdClass.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
527
                '@id' => $this->organizerService->iri($organizerId)
528
            );
529
        }
530
    }
531
532
    /**
533
     * @param EventWasLabelled $eventWasLabelled
534
     */
535
    protected function applyEventWasLabelled(EventWasLabelled $eventWasLabelled)
536
    {
537
        $document = $this->loadDocumentFromRepository($eventWasLabelled);
538
539
        $eventLd = $document->getBody();
540
541
        $labels = isset($eventLd->labels) ? $eventLd->labels : [];
542
        $label = (string) $eventWasLabelled->getLabel();
543
544
        $labels[] = $label;
545
        $eventLd->labels = array_unique($labels);
546
547
        $this->repository->save($document->withBody($eventLd));
548
    }
549
550
    protected function applyUnlabelled(Unlabelled $unlabelled)
551
    {
552
        $document = $this->loadDocumentFromRepository($unlabelled);
553
554
        $eventLd = $document->getBody();
555
556
        if (is_array($eventLd->labels)) {
557
            $eventLd->labels = array_filter(
558
                $eventLd->labels,
559
                function ($label) use ($unlabelled) {
560
                    return !$unlabelled->getLabel()->equals(
561
                        new Label($label)
562
                    );
563
                }
564
            );
565
            // Ensure array keys start with 0 so json_encode() does encode it
566
            // as an array and not as an object.
567
            $eventLd->labels = array_values($eventLd->labels);
568
        }
569
570
        $this->repository->save($document->withBody($eventLd));
571
    }
572
573
    /**
574
     * @param LabelsMerged $labelsMerged
575
     */
576
    protected function applyLabelsMerged(LabelsMerged $labelsMerged)
577
    {
578
        $document = $this->loadDocumentFromRepositoryByEventId($labelsMerged->getEventId()->toNative());
579
580
        $eventLd = $document->getBody();
581
582
        $labels = isset($eventLd->labels) ? $eventLd->labels : [];
583
584
        $currentCollection = LabelCollection::fromStrings($labels);
585
586
        $newLabels = $labelsMerged->getLabels();
587
588
        $eventLd->labels = $currentCollection->merge($newLabels)->toStrings();
589
590
        $this->repository->save($document->withBody($eventLd));
591
    }
592
593
    protected function applyTitleTranslated(TitleTranslated $titleTranslated)
594
    {
595
        $document = $this->loadDocumentFromRepository($titleTranslated);
596
597
        $eventLd = $document->getBody();
598
        $eventLd->name->{$titleTranslated->getLanguage()->getCode(
599
        )} = $titleTranslated->getTitle();
600
601
        $this->repository->save($document->withBody($eventLd));
602
    }
603
604 View Code Duplication
    protected function applyDescriptionTranslated(
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...
605
        DescriptionTranslated $descriptionTranslated
606
    ) {
607
        $document = $this->loadDocumentFromRepository($descriptionTranslated);
608
609
        $eventLd = $document->getBody();
610
        $eventLd->description->{$descriptionTranslated->getLanguage()->getCode(
611
        )} = $descriptionTranslated->getDescription();
612
613
        $this->repository->save($document->withBody($eventLd));
614
    }
615
616
    protected function applyTranslationApplied(
617
        TranslationApplied $translationApplied
618
    ) {
619
        $document = $this->loadDocumentFromRepositoryByEventId($translationApplied->getEventId()->toNative());
620
621
        $eventLd = $document->getBody();
622
623 View Code Duplication
        if ($translationApplied->getTitle() !== null) {
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...
624
            $eventLd->name->{$translationApplied->getLanguage()->getCode(
625
            )} = $translationApplied->getTitle()->toNative();
626
        }
627
628 View Code Duplication
        if ($translationApplied->getLongDescription() !== null) {
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...
629
            $eventLd->description->{$translationApplied->getLanguage()->getCode(
630
            )} = $translationApplied->getLongDescription()->toNative();
631
        }
632
633
        $this->repository->save($document->withBody($eventLd));
634
    }
635
636
    /**
637
     * Apply the translation deleted event to the event repository.
638
     * @param TranslationDeleted $translationDeleted
639
     */
640
    protected function applyTranslationDeleted(
641
        TranslationDeleted $translationDeleted
642
    ) {
643
        $document = $this->loadDocumentFromRepositoryByEventId($translationDeleted->getEventId()->toNative());
644
645
        $eventLd = $document->getBody();
646
647
        unset($eventLd->name->{$translationDeleted->getLanguage()->getCode()});
648
649
        unset($eventLd->description->{$translationDeleted->getLanguage()->getCode()});
650
651
        $this->repository->save($document->withBody($eventLd));
652
    }
653
654
    /**
655
     * Apply the description updated event to the event repository.
656
     * @param DescriptionUpdated $descriptionUpdated
657
     */
658 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...
659
        DescriptionUpdated $descriptionUpdated
660
    ) {
661
        $document = $this->loadDocumentFromRepository($descriptionUpdated);
662
663
        $eventLd = $document->getBody();
664
        if (empty($eventLd->description)) {
665
            $eventLd->description = new \stdClass();
666
        }
667
        $eventLd->description->{'nl'} = $descriptionUpdated->getDescription();
668
669
        $this->repository->save($document->withBody($eventLd));
670
    }
671
672
    /**
673
     * Apply the typical age range updated event to the event repository.
674
     * @param TypicalAgeRangeUpdated $typicalAgeRangeUpdated
675
     */
676 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...
677
        TypicalAgeRangeUpdated $typicalAgeRangeUpdated
678
    ) {
679
        $document = $this->loadDocumentFromRepository($typicalAgeRangeUpdated);
680
681
        $eventLd = $document->getBody();
682
        $eventLd->typicalAgeRange = $typicalAgeRangeUpdated->getTypicalAgeRange();
683
684
        $this->repository->save($document->withBody($eventLd));
685
    }
686
687
    /**
688
     * Apply the typical age range deleted event to the event repository.
689
     * @param TypicalAgeRangeDeleted $typicalAgeRangeDeleted
690
     */
691
    protected function applyTypicalAgeRangeDeleted(
692
        TypicalAgeRangeDeleted $typicalAgeRangeDeleted
693
    ) {
694
        $document = $this->loadDocumentFromRepository($typicalAgeRangeDeleted);
695
696
        $eventLd = $document->getBody();
697
698
        unset($eventLd->typicalAgeRange);
699
700
        $this->repository->save($document->withBody($eventLd));
701
    }
702
703
    /**
704
     * Apply the organizer updated event to the event repository.
705
     * @param OrganizerUpdated $organizerUpdated
706
     */
707 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...
708
    {
709
710
        $document = $this->loadDocumentFromRepository($organizerUpdated);
711
712
        $eventLd = $document->getBody();
713
714
        $eventLd->organizer = array(
715
          '@type' => 'Organizer',
716
        ) + (array)$this->organizerJSONLD($organizerUpdated->getOrganizerId());
717
718
        $this->repository->save($document->withBody($eventLd));
719
    }
720
721
    /**
722
     * Apply the organizer delete event to the event repository.
723
     * @param OrganizerDeleted $organizerDeleted
724
     */
725
    protected function applyOrganizerDeleted(OrganizerDeleted $organizerDeleted)
726
    {
727
728
        $document = $this->loadDocumentFromRepository($organizerDeleted);
729
730
        $eventLd = $document->getBody();
731
732
        unset($eventLd->organizer);
733
734
        $this->repository->save($document->withBody($eventLd));
735
    }
736
737
    /**
738
     * Apply the contact info updated event to the event repository.
739
     * @param ContactPointUpdated $contactPointUpdated
740
     */
741
    protected function applyContactPointUpdated(ContactPointUpdated $contactPointUpdated)
742
    {
743
744
        $document = $this->loadDocumentFromRepository($contactPointUpdated);
745
746
        $eventLd = $document->getBody();
747
        $eventLd->contactPoint = $contactPointUpdated->getContactPoint()->toJsonLd();
748
749
        $this->repository->save($document->withBody($eventLd));
750
    }
751
752
    /**
753
     * Apply the booking info updated event to the event repository.
754
     * @param BookingInfoUpdated $bookingInfoUpdated
755
     */
756 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...
757
    {
758
759
        $document = $this->loadDocumentFromRepository($bookingInfoUpdated);
760
761
        $eventLd = $document->getBody();
762
        $eventLd->bookingInfo = $bookingInfoUpdated->getBookingInfo()->toJsonLd();
763
764
        $this->repository->save($document->withBody($eventLd));
765
766
    }
767
768
    /**
769
     * Apply the imageAdded event to the event repository.
770
     *
771
     * @param ImageAdded $imageAdded
772
     */
773 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...
774
    {
775
        $document = $this->loadDocumentFromRepository($imageAdded);
776
777
        $eventLd = $document->getBody();
778
        $eventLd->mediaObject = isset($eventLd->mediaObject) ? $eventLd->mediaObject : [];
779
780
        $imageData = $this->mediaObjectSerializer
781
            ->serialize($imageAdded->getImage(), 'json-ld');
782
        $eventLd->mediaObject[] = $imageData;
783
784
        $this->repository->save($document->withBody($eventLd));
785
    }
786
787
    /**
788
     * Apply the ImageUpdated event to the event repository.
789
     *
790
     * @param ImageUpdated $imageUpdated
791
     */
792
    protected function applyImageUpdated(ImageUpdated $imageUpdated)
793
    {
794
        $document = $this->loadDocumentFromRepositoryByEventId($imageUpdated->getItemId());
795
796
        $eventLd = $document->getBody();
797
798
        if (!isset($eventLd->mediaObject)) {
799
            throw new \Exception('The image to update could not be found.');
800
        }
801
802
        $updatedMediaObjects = [];
803
804 View Code Duplication
        foreach ($eventLd->mediaObject as $mediaObject) {
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...
805
            $mediaObjectMatches = (
806
                strpos(
807
                    $mediaObject->{'@id'},
808
                    (string)$imageUpdated->getMediaObjectId()
809
                ) > 0
810
            );
811
812
            if ($mediaObjectMatches) {
813
                $mediaObject->description = (string)$imageUpdated->getDescription();
814
                $mediaObject->copyrightHolder = (string)$imageUpdated->getCopyrightHolder();
815
816
                $updatedMediaObjects[] = $mediaObject;
817
            }
818
        };
819
820
        if (empty($updatedMediaObjects)) {
821
            throw new \Exception('The image to update could not be found.');
822
        }
823
824
        $this->repository->save($document->withBody($eventLd));
825
    }
826
827
    /**
828
     * Apply the imageDeleted event to the event repository.
829
     *
830
     * @param ImageDeleted $imageDeleted
831
     */
832 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...
833
    {
834
835
        $document = $this->loadDocumentFromRepository($imageDeleted);
836
837
        $eventLd = $document->getBody();
838
        unset($eventLd->mediaObject[$imageDeleted->getIndexToDelete()]);
839
840
        // Generate new numeric keys.
841
        $eventLd->mediaObject = array_values($eventLd->mediaObject);
842
843
        $this->repository->save($document->withBody($eventLd));
844
845
    }
846
847
    /**
848
     * @param string $id
849
     * @return JsonDocument
850
     */
851 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...
852
    {
853
        $document = new JsonDocument($id);
854
855
        $eventLd = $document->getBody();
856
        $eventLd->{'@id'} = $this->iriGenerator->iri($id);
857
858
        // @todo provide Event-LD context here relative to the base URI
859
        $eventLd->{'@context'} = '/api/1.0/event.jsonld';
860
861
        return $document->withBody($eventLd);
862
    }
863
864
    /**
865
     * @param EventEvent $event
866
     * @return JsonDocument
867
     */
868
    protected function loadDocumentFromRepository(EventEvent $event)
869
    {
870
        return $this->loadDocumentFromRepositoryByEventId($event->getEventId());
871
    }
872
873
    /**
874
     * @param string $eventId
875
     * @return JsonDocument
876
     */
877
    protected function loadDocumentFromRepositoryByEventId($eventId)
878
    {
879
        $document = $this->repository->get($eventId);
880
881
        if (!$document) {
882
            return $this->newDocument($eventId);
883
        }
884
885
        return $document;
886
    }
887
888
    private function generateSameAs($eventId, $name)
889
    {
890
        $eventSlug = $this->slugger->slug($name);
891
        return array(
892
            'http://www.uitinvlaanderen.be/agenda/e/' . $eventSlug . '/' . $eventId,
893
        );
894
    }
895
896
    public function addDescriptionFilter(StringFilterInterface $filter)
897
    {
898
        $this->cdbXMLImporter->addDescriptionFilter($filter);
899
    }
900
901 View Code Duplication
    private function getAuthorFromMetadata(Metadata $metadata)
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...
902
    {
903
        $properties = $metadata->serialize();
904
905
        if (isset($properties['user_nick'])) {
906
            return new String($properties['user_nick']);
907
        }
908
    }
909
910 View Code Duplication
    private function getConsumerFromMetadata(Metadata $metadata)
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...
911
    {
912
        $properties = $metadata->serialize();
913
914
        if (isset($properties['consumer']['name'])) {
915
            return new String($properties['consumer']['name']);
916
        }
917
    }
918
}
919